From e0641c3175bc7cf53dea924524e51f1eefa6a8b1 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Mon, 18 Mar 2024 13:39:34 -0400 Subject: the lack of pushing is astounding actually --- .../views/collections/CollectionCardDeckView.tsx | 164 +++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 src/client/views/collections/CollectionCardDeckView.tsx (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx new file mode 100644 index 000000000..feb9e61cc --- /dev/null +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -0,0 +1,164 @@ +import { action, computed, IReactionDisposer, makeObservable } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { Doc, DocListCast } from '../../../fields/Doc'; +import { ScriptField } from '../../../fields/ScriptField'; +import { NumCast, StrCast } from '../../../fields/Types'; +import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; +import { DocUtils } from '../../documents/Documents'; +import { SelectionManager } from '../../util/SelectionManager'; +import { undoBatch, UndoManager } from '../../util/UndoManager'; +import { OpenWhere } from '../nodes/DocumentView'; +import { computePassLayout, computeStarburstLayout, computeCardDeckLayout } from './collectionFreeForm'; +import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; +import './CollectionPileView.scss'; +import { CollectionSubView } from './CollectionSubView'; +import { dropActionType } from '../../util/DragManager'; + +@observer +export class CollectionCardView extends CollectionSubView() { + _originalChrome: any = ''; + _disposers: { [name: string]: IReactionDisposer } = {}; + + constructor(props: any) { + super(props); + makeObservable(this); + } + + componentDidMount() { + if (this.layoutEngine() !== computePassLayout.name && this.layoutEngine() !== computeCardDeckLayout.name) { + this.Document._freeform_cardEngine = computePassLayout.name; + } + this._originalChrome = this.layoutDoc._chromeHidden; + this.layoutDoc._chromeHidden = true; + } + componentWillUnmount() { + this.layoutDoc._chromeHidden = this._originalChrome; + Object.values(this._disposers).forEach(disposer => disposer?.()); + } + + layoutEngine = () => StrCast(this.Document._freeform_cardEngine); + + @undoBatch + addCardDoc = (doc: Doc | Doc[]) => { + (doc instanceof Doc ? [doc] : doc).map(d => DocUtils.iconify(d)); + return this._props.addDocument?.(doc) || false; + }; + + @undoBatch + removeCardDoc = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { + (doc instanceof Doc ? [doc] : doc).forEach(d => Doc.deiconifyView(d)); + const ret = this._props.moveDocument?.(doc, targetCollection, addDoc) || false; + if (ret && !DocListCast(this.dataDoc[this.fieldKey ?? 'data']).length) this.DocumentView?.()._props.removeDocument?.(this.Document); + return ret; + }; + + @computed get toggleIcon() { + return ScriptField.MakeScript('documentView.iconify()', { documentView: 'any' }); + } + @computed get contentEvents() { + const isCard = this.layoutEngine() === computeCardDeckLayout.name; + return this._props.isContentActive() && isCard ? undefined : 'none'; + } + + // returns the contents of the cardSpread in a CollectionFreeFormView + @computed get contents() { + return ( +
+ +
+ ); + } + + // // toggles the pileup between starburst to compact + // toggleStarburst = action(() => { + // this.layoutDoc._freeform_scale = undefined; + // if (this.layoutEngine() === computeStarburstLayout.name) { + // if (NumCast(this.layoutDoc._width) !== NumCast(this.Document._starburstDiameter, 500)) { + // this.Document._starburstDiameter = NumCast(this.layoutDoc._width); + // } + // const defaultSize = 110; + // this.Document.x = NumCast(this.Document.x) + NumCast(this.layoutDoc._width) / 2 - NumCast(this.layoutDoc._freeform_pileWidth, defaultSize) / 2; + // this.Document.y = NumCast(this.Document.y) + NumCast(this.layoutDoc._height) / 2 - NumCast(this.layoutDoc._freeform_pileHeight, defaultSize) / 2; + // this.layoutDoc._width = NumCast(this.layoutDoc._freeform_pileWidth, defaultSize); + // this.layoutDoc._height = NumCast(this.layoutDoc._freeform_pileHeight, defaultSize); + // DocUtils.pileup(this.childDocs, undefined, undefined, NumCast(this.layoutDoc._width) / 2, false); + // this.layoutDoc._freeform_panX = 0; + // this.layoutDoc._freeform_panY = -10; + // this.Document._freeform_pileEngine = computePassLayout.name; + // } else { + // const defaultSize = NumCast(this.Document._starburstDiameter, 400); + // this.Document.x = NumCast(this.Document.x) + NumCast(this.layoutDoc._width) / 2 - defaultSize / 2; + // this.Document.y = NumCast(this.Document.y) + NumCast(this.layoutDoc._height) / 2 - defaultSize / 2; + // this.layoutDoc._freeform_pileWidth = NumCast(this.layoutDoc._width); + // this.layoutDoc._freeform_pileHeight = NumCast(this.layoutDoc._height); + // this.layoutDoc._freeform_panX = this.layoutDoc._freeform_panY = 0; + // this.layoutDoc._width = this.layoutDoc._height = defaultSize; + // this.layoutDoc.background; + // this.Document._freeform_pileEngine = computeStarburstLayout.name; + // } + // }); + + // for dragging documents out of the pileup view + _undoBatch: UndoManager.Batch | undefined; + pointerDown = (e: React.PointerEvent) => { + let dist = 0; + setupMoveUpEvents( + this, + e, + (e: PointerEvent, down: number[], delta: number[]) => { + if (this.layoutEngine() === 'pass' && this.childDocs.length && e.shiftKey) { + dist += Math.sqrt(delta[0] * delta[0] + delta[1] * delta[1]); + if (dist > 100) { + if (!this._undoBatch) { + this._undoBatch = UndoManager.StartBatch('layout pile'); + } + const doc = this.childDocs[0]; + doc.x = e.clientX; + doc.y = e.clientY; + this._props.addDocTab(doc, OpenWhere.inParentFromScreen) && (this._props.removeDocument?.(doc) || false); + dist = 0; + } + } + return false; + }, + () => { + this._undoBatch?.end(); + this._undoBatch = undefined; + }, + emptyFunction, + e.shiftKey && this.layoutEngine() === computePassLayout.name, + this.layoutEngine() === computePassLayout.name && e.shiftKey + ); // this sets _doubleTap + }; + + // onClick for toggling the pileup view + // @undoBatch + // onClick = (e: React.MouseEvent) => { + // if (e.button === 0) { + // SelectionManager.DeselectAll(); + // this.toggleStarburst(); + // e.stopPropagation(); + // } + // }; + + render() { + return ( +
+ {this.contents} +
+ ); + } +} -- cgit v1.2.3-70-g09d2 From d3383640a8007a15e0deb47715e203508c4fd64a Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Tue, 19 Mar 2024 16:21:34 -0400 Subject: working on implementing card logic --- src/client/documents/Documents.ts | 16 +- src/client/util/CurrentUserUtils.ts | 2 +- .../views/collections/CollectionCardDeckView.scss | 0 .../views/collections/CollectionCardDeckView.tsx | 281 +++++++++++---------- src/client/views/collections/CollectionMenu.tsx | 4 + .../CollectionFreeFormLayoutEngines.tsx | 61 ++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 6 +- 7 files changed, 198 insertions(+), 172 deletions(-) create mode 100644 src/client/views/collections/CollectionCardDeckView.scss (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index d12c61fd7..c453fd793 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1219,14 +1219,7 @@ export namespace Docs { ); } - export function CardDeckDocument(documents: Array, options: DocumentOptions, id?: string) { - return InstanceFromProto( - Prototypes.get(DocumentType.COL), - new List(documents), - { backgroundColor: 'transparent', dropAction: dropActionType.move, _forceActive: true, _freeform_noZoom: true, _freeform_noAutoPan: true, ...options, _type_collection: CollectionViewType.Card }, - id - ); - } + export function LinearDocument(documents: Array, options: DocumentOptions, id?: string) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _type_collection: CollectionViewType.Linear }, id); @@ -1244,6 +1237,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _type_collection: CollectionViewType.Carousel3D }); } + export function CardDeckDocument(documents: Array, options: DocumentOptions, id?: string) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _type_collection: CollectionViewType.Card}); + } + export function SchemaDocument(schemaHeaders: SchemaHeaderField[], documents: Array, options: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { schemaHeaders: new List(schemaHeaders), ...options, _type_collection: CollectionViewType.Schema }); } @@ -1887,6 +1884,7 @@ export namespace DocUtils { } export function spreadCards(docList: Doc[], x: number = 0, y: number = 0, spreadAngle: number = 30, radius: number = 100, create: boolean = true) { + console.log('spread cards'); const totalCards = docList.length; const halfSpreadAngle = spreadAngle * 0.5; const angleStep = spreadAngle / (totalCards - 1); @@ -1897,7 +1895,7 @@ export namespace DocUtils { const angle = (-halfSpreadAngle + angleStep * i) * (Math.PI / 180); // Convert degrees to radians d.x = x + Math.cos(angle) * radius; d.y = y + Math.sin(angle) * radius; - d.rotation = angle; // Assuming 'd.rotation' sets the rotation, adjust accordingly + d.rotation = angle; d._timecodeToShow = undefined; }); }); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 11f6c82ec..15c3ddad6 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -796,7 +796,7 @@ pie title Minerals in my tap water CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.Multicolumn, CollectionViewType.Multirow, CollectionViewType.Time, CollectionViewType.Carousel, CollectionViewType.Carousel3D, CollectionViewType.Linear, CollectionViewType.Map, - CollectionViewType.Grid, CollectionViewType.NoteTaking]), + CollectionViewType.Grid, CollectionViewType.NoteTaking, CollectionViewType.Card]), title: "Perspective", toolTip: "View", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: '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/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index feb9e61cc..e35f7b421 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -1,164 +1,185 @@ -import { action, computed, IReactionDisposer, makeObservable } from 'mobx'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { computed, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { Utils, emptyFunction, returnFalse, returnZero } from '../../../Utils'; import { Doc, DocListCast } from '../../../fields/Doc'; -import { ScriptField } from '../../../fields/ScriptField'; -import { NumCast, StrCast } from '../../../fields/Types'; -import { emptyFunction, returnFalse, setupMoveUpEvents } from '../../../Utils'; -import { DocUtils } from '../../documents/Documents'; +import { Id } from '../../../fields/FieldSymbols'; +import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; +import { DocumentType } from '../../documents/DocumentTypes'; +import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; -import { undoBatch, UndoManager } from '../../util/UndoManager'; -import { OpenWhere } from '../nodes/DocumentView'; -import { computePassLayout, computeStarburstLayout, computeCardDeckLayout } from './collectionFreeForm'; -import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; -import './CollectionPileView.scss'; +import { StyleProp } from '../StyleProvider'; +import { DocumentView } from '../nodes/DocumentView'; +import { FocusViewOptions } from '../nodes/FieldView'; +import './CollectionCarousel3DView.scss'; import { CollectionSubView } from './CollectionSubView'; -import { dropActionType } from '../../util/DragManager'; - +const { default: { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } } = require('../global/globalCssVariables.module.scss'); // prettier-ignore @observer export class CollectionCardView extends CollectionSubView() { - _originalChrome: any = ''; - _disposers: { [name: string]: IReactionDisposer } = {}; - + @computed get scrollSpeed() { + return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; //default scroll speed + } constructor(props: any) { super(props); makeObservable(this); } - componentDidMount() { - if (this.layoutEngine() !== computePassLayout.name && this.layoutEngine() !== computeCardDeckLayout.name) { - this.Document._freeform_cardEngine = computePassLayout.name; - } - this._originalChrome = this.layoutDoc._chromeHidden; - this.layoutDoc._chromeHidden = true; - } + private _dropDisposer?: DragManager.DragDropDisposer; + componentWillUnmount() { - this.layoutDoc._chromeHidden = this._originalChrome; - Object.values(this._disposers).forEach(disposer => disposer?.()); + this._dropDisposer?.(); } - layoutEngine = () => StrCast(this.Document._freeform_cardEngine); - - @undoBatch - addCardDoc = (doc: Doc | Doc[]) => { - (doc instanceof Doc ? [doc] : doc).map(d => DocUtils.iconify(d)); - return this._props.addDocument?.(doc) || false; + protected createDashEventsTarget = (ele: HTMLDivElement | null) => { + this._dropDisposer?.(); + if (ele) { + this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc); + } }; - @undoBatch - removeCardDoc = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => { - (doc instanceof Doc ? [doc] : doc).forEach(d => Doc.deiconifyView(d)); - const ret = this._props.moveDocument?.(doc, targetCollection, addDoc) || false; - if (ret && !DocListCast(this.dataDoc[this.fieldKey ?? 'data']).length) this.DocumentView?.()._props.removeDocument?.(this.Document); - return ret; + centerScale = Number(CAROUSEL3D_CENTER_SCALE); + panelWidth = () => this._props.PanelWidth() / 3; + panelHeight = () => this._props.PanelHeight() * Number(CAROUSEL3D_SIDE_SCALE); + onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick); + isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive(); + isChildContentActive = () => (this.isContentActive() ? true : false); + childScreenToLocal = () => + this._props // document's left is the panel shifted by the doc's index * panelWidth/#docs. But it scales by centerScale around its center, so it's left moves left by the distance of the left from the center (panelwidth/2) * the scale delta (centerScale-1) + .ScreenToLocalTransform() // the top behaves the same way ecept it's shifted by the 'top' amount specified for the panel in css and then by the scale factor. + .translate(-this.panelWidth() + ((this.centerScale - 1) * this.panelWidth()) / 2, -((Number(CAROUSEL3D_TOP) / 100) * this._props.PanelHeight()) + ((this.centerScale - 1) * this.panelHeight()) / 2) + .scale(1 / this.centerScale); + + focus = (anchor: Doc, options: FocusViewOptions) => { + const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); + if (anchor.type !== DocumentType.CONFIG && !docs.includes(anchor)) return; + options.didMove = true; + const target = DocCast(anchor.annotationOn) ?? anchor; + const index = docs.indexOf(target); + index !== -1 && (this.layoutDoc._carousel_index = index); //if index is not -1, then assign index to this.layoutDoc._carousel_index + return undefined; }; - @computed get toggleIcon() { - return ScriptField.MakeScript('documentView.iconify()', { documentView: 'any' }); - } - @computed get contentEvents() { - const isCard = this.layoutEngine() === computeCardDeckLayout.name; - return this._props.isContentActive() && isCard ? undefined : 'none'; + + @computed get content() { + const currentIndex = NumCast(this.layoutDoc._carousel_index); + const displayDoc = (childPair: { layout: Doc; data: Doc }) => { + return ( + + ); + }; + + return this.childLayoutPairs.map((childPair, index) => { + return ( +
+ {displayDoc(childPair)} +
+ ); + }); } - // returns the contents of the cardSpread in a CollectionFreeFormView - @computed get contents() { + changeSlide = (direction: number) => { + SelectionManager.DeselectAll(); + this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length; + }; + + onArrowClick = (direction: number) => { + this.changeSlide(direction); + !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = direction === 1 ? 'fwd' : 'back'); // while autoscroll is on, keep the other autoscroll button hidden + !this.layoutDoc.autoScrollOn && this.fadeScrollButton(); // keep pause button visible while autoscroll is on + }; + + interval?: number; + startAutoScroll = (direction: number) => { + this.interval = window.setInterval(() => { + this.changeSlide(direction); + }, this.scrollSpeed); + }; + + stopAutoScroll = () => { + window.clearInterval(this.interval); + this.interval = undefined; + this.fadeScrollButton(); + }; + + toggleAutoScroll = (direction: number) => { + this.layoutDoc.autoScrollOn = this.layoutDoc.autoScrollOn ? false : true; + this.layoutDoc.autoScrollOn ? this.startAutoScroll(direction) : this.stopAutoScroll(); + }; + + fadeScrollButton = () => { + window.setTimeout(() => { + !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = 'none'); //fade away after 1.5s if it's not clicked. + }, 1500); + }; + + @computed get buttons() { return ( -
- +
+
this.onArrowClick(-1)} /> +
this.onArrowClick(1)} /> + {/* {this.autoScrollButton} */}
); } - // // toggles the pileup between starburst to compact - // toggleStarburst = action(() => { - // this.layoutDoc._freeform_scale = undefined; - // if (this.layoutEngine() === computeStarburstLayout.name) { - // if (NumCast(this.layoutDoc._width) !== NumCast(this.Document._starburstDiameter, 500)) { - // this.Document._starburstDiameter = NumCast(this.layoutDoc._width); - // } - // const defaultSize = 110; - // this.Document.x = NumCast(this.Document.x) + NumCast(this.layoutDoc._width) / 2 - NumCast(this.layoutDoc._freeform_pileWidth, defaultSize) / 2; - // this.Document.y = NumCast(this.Document.y) + NumCast(this.layoutDoc._height) / 2 - NumCast(this.layoutDoc._freeform_pileHeight, defaultSize) / 2; - // this.layoutDoc._width = NumCast(this.layoutDoc._freeform_pileWidth, defaultSize); - // this.layoutDoc._height = NumCast(this.layoutDoc._freeform_pileHeight, defaultSize); - // DocUtils.pileup(this.childDocs, undefined, undefined, NumCast(this.layoutDoc._width) / 2, false); - // this.layoutDoc._freeform_panX = 0; - // this.layoutDoc._freeform_panY = -10; - // this.Document._freeform_pileEngine = computePassLayout.name; - // } else { - // const defaultSize = NumCast(this.Document._starburstDiameter, 400); - // this.Document.x = NumCast(this.Document.x) + NumCast(this.layoutDoc._width) / 2 - defaultSize / 2; - // this.Document.y = NumCast(this.Document.y) + NumCast(this.layoutDoc._height) / 2 - defaultSize / 2; - // this.layoutDoc._freeform_pileWidth = NumCast(this.layoutDoc._width); - // this.layoutDoc._freeform_pileHeight = NumCast(this.layoutDoc._height); - // this.layoutDoc._freeform_panX = this.layoutDoc._freeform_panY = 0; - // this.layoutDoc._width = this.layoutDoc._height = defaultSize; - // this.layoutDoc.background; - // this.Document._freeform_pileEngine = computeStarburstLayout.name; - // } - // }); - - // for dragging documents out of the pileup view - _undoBatch: UndoManager.Batch | undefined; - pointerDown = (e: React.PointerEvent) => { - let dist = 0; - setupMoveUpEvents( - this, - e, - (e: PointerEvent, down: number[], delta: number[]) => { - if (this.layoutEngine() === 'pass' && this.childDocs.length && e.shiftKey) { - dist += Math.sqrt(delta[0] * delta[0] + delta[1] * delta[1]); - if (dist > 100) { - if (!this._undoBatch) { - this._undoBatch = UndoManager.StartBatch('layout pile'); - } - const doc = this.childDocs[0]; - doc.x = e.clientX; - doc.y = e.clientY; - this._props.addDocTab(doc, OpenWhere.inParentFromScreen) && (this._props.removeDocument?.(doc) || false); - dist = 0; - } - } - return false; - }, - () => { - this._undoBatch?.end(); - this._undoBatch = undefined; - }, - emptyFunction, - e.shiftKey && this.layoutEngine() === computePassLayout.name, - this.layoutEngine() === computePassLayout.name && e.shiftKey - ); // this sets _doubleTap - }; + @computed get autoScrollButton() { + const whichButton = this.layoutDoc.showScrollButton; + return ( + <> +
this.toggleAutoScroll(-1)}> + {this.layoutDoc.autoScrollOn ? : } +
+
this.toggleAutoScroll(1)}> + {this.layoutDoc.autoScrollOn ? : } +
+ + ); + } - // onClick for toggling the pileup view - // @undoBatch - // onClick = (e: React.MouseEvent) => { - // if (e.button === 0) { - // SelectionManager.DeselectAll(); - // this.toggleStarburst(); - // e.stopPropagation(); - // } - // }; + @computed get dots() { + return this.childLayoutPairs.map((_child, index) =>
(this.layoutDoc._carousel_index = index)} />); + } + @computed get translateX() { + const index = NumCast(this.layoutDoc._carousel_index); + return this.panelWidth() * (1 - index); + } render() { return ( -
- {this.contents} +
+
+ {this.content} +
+ {this.buttons} +
{this.dots}
); } + + } diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 8729ef549..9d135eb3b 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -319,6 +319,10 @@ export class CollectionViewBaseChrome extends React.Component(); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index e972f44f1..b3ae382e3 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -126,39 +126,40 @@ export function computeStarburstLayout(poolData: Map, pivotDoc return normalizeResults(burstDiam, 12, docMap, poolData, viewDefsToJSX, [], 0, [divider]); } -export function computeCardDeckLayout(poolData: Map, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], engineProps: any) { - const docMap = new Map(); - const spreadWidth = Math.min(panelDim[0], childPairs.length * 50); // Total width of the spread - const startX = -(spreadWidth / 2); // Starting X position - const fanAngle = 5; // Angle in degrees for fanning out cards - const baseZIndex = 1000; // Base Z-index to ensure cards are stacked in order +// export function computeCardDeckLayout(poolData: Map, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], engineProps: any) { +// console.log('hi'); +// const docMap = new Map(); +// const spreadWidth = Math.min(panelDim[0], childPairs.length * 50); // Total width of the spread +// const startX = -(spreadWidth / 2); // Starting X position +// const fanAngle = 5; // Angle in degrees for fanning out cards +// const baseZIndex = 1000; // Base Z-index to ensure cards are stacked in order - childPairs.forEach(({ layout, data }, i) => { - const aspect = NumCast(layout._height) / NumCast(layout._width); - const docSize = Math.min(400, NumCast(layout._width)) * NumCast(pivotDoc._starburstDocScale, 1); - const posX = startX + (spreadWidth / childPairs.length) * i; - const posY = 0; // Adjust if you want to change the vertical alignment - const rotation = (i - (childPairs.length / 2)) * fanAngle; // Calculate rotation for fanning effect +// childPairs.forEach(({ layout, data }, i) => { +// const aspect = NumCast(layout._height) / NumCast(layout._width); +// const docSize = Math.min(400, NumCast(layout._width)) * NumCast(pivotDoc._starburstDocScale, 1); +// const posX = startX + (spreadWidth / childPairs.length) * i; +// const posY = 0; // Adjust if you want to change the vertical alignment +// const rotation = (i - (childPairs.length / 2)) * fanAngle; // Calculate rotation for fanning effect - docMap.set(layout[Id], { - x: posX, - y: posY, - width: docSize, - height: docSize * aspect, - zIndex: baseZIndex + i, // Increment Z-index for each card to stack them correctly - rotation: rotation, // Optional: Add this if you want to rotate elements for a fanned effect - pair: { layout, data }, - replica: '', - color: 'white', - backgroundColor: 'white', - transition: 'all 0.3s', - }); - }); +// docMap.set(layout[Id], { +// x: posX, +// y: posY, +// width: docSize, +// height: docSize * aspect, +// zIndex: baseZIndex + i, +// rotation: rotation, +// pair: { layout, data }, +// replica: '', +// color: 'white', +// backgroundColor: 'white', +// transition: 'all 0.3s', +// }); +// }); - // This is a placeholder for the divider object and may need to be adjusted based on actual usage - const divider = { type: 'div', color: 'transparent', x: -panelDim[0] / 2, y: -panelDim[1] / 2, width: 15, height: 15, payload: undefined }; - return normalizeResults(panelDim, 12, docMap, poolData, viewDefsToJSX, [], 0, [divider]); -} +// // This is a placeholder for the divider object and may need to be adjusted based on actual usage +// const divider = { type: 'div', color: 'transparent', x: -panelDim[0] / 2, y: -panelDim[1] / 2, width: 15, height: 15, payload: undefined }; +// return normalizeResults(panelDim, 12, docMap, poolData, viewDefsToJSX, [], 0, [divider]); +// } export function computePivotLayout(poolData: Map, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], engineProps: any) { const docMap = new Map(); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index f9fe306fa..10b849dab 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -49,7 +49,9 @@ import { CollectionSubView } from '../CollectionSubView'; import { TreeViewType } from '../CollectionTreeView'; import { CollectionFreeFormBackgroundGrid } from './CollectionFreeFormBackgroundGrid'; import { CollectionFreeFormInfoUI } from './CollectionFreeFormInfoUI'; -import { computePassLayout, computePivotLayout, computeStarburstLayout, computeTimelineLayout, PoolData, ViewDefBounds, ViewDefResult, computeCardDeckLayout } from './CollectionFreeFormLayoutEngines'; +import { computePassLayout, computePivotLayout, computeStarburstLayout, computeTimelineLayout, PoolData, ViewDefBounds, ViewDefResult, + // computeCardDeckLayout + } from './CollectionFreeFormLayoutEngines'; import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannableContents'; import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors'; import './CollectionFreeFormView.scss'; @@ -1383,7 +1385,7 @@ export class CollectionFreeFormView extends CollectionSubView Date: Wed, 20 Mar 2024 03:27:55 -0400 Subject: me vs pointer events who will win --- src/client/views/DocComponent.tsx | 2 +- .../views/collections/CollectionCardDeckView.tsx | 168 ++++++++++++--------- 2 files changed, 94 insertions(+), 76 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 18e7ab12a..a7a9763ec 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -35,7 +35,7 @@ export interface ViewBoxInterface { addDocument?: (doc: Doc | Doc[], annotationKey?: string) => boolean; // add a document (used only by collections) removeDocument?: (doc: Doc | Doc[], annotationKey?: string, leavePushpin?: boolean, dontAddToRemoved?: boolean) => boolean; // add a document (used only by collections) select?: (ctrlKey: boolean, shiftKey: boolean) => void; - focus?: (textAnchor: Doc, options: FocusViewOptions) => Opt; + focus?: (textAnchor: Doc, options: FocusViewOptions) => Opt; viewTransition?: () => Opt; // duration of a view transition animation isAnyChildContentActive?: () => boolean; // is any child content of the document active onClickScriptDisable?: () => 'never' | 'always'; // disable click scripts : never, always, or undefined = only when selected diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index e35f7b421..778280215 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { computed, makeObservable } from 'mobx'; -import { observer } from 'mobx-react'; +import { computed, makeObservable, observable, action } from 'mobx'; +import { observer, } from 'mobx-react'; import * as React from 'react'; import { Utils, emptyFunction, returnFalse, returnZero } from '../../../Utils'; import { Doc, DocListCast } from '../../../fields/Doc'; @@ -14,12 +14,31 @@ import { DocumentView } from '../nodes/DocumentView'; import { FocusViewOptions } from '../nodes/FieldView'; import './CollectionCarousel3DView.scss'; import { CollectionSubView } from './CollectionSubView'; +import { ScriptField } from '../../../fields/ScriptField'; + const { default: { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } } = require('../global/globalCssVariables.module.scss'); // prettier-ignore @observer export class CollectionCardView extends CollectionSubView() { - @computed get scrollSpeed() { - return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; //default scroll speed - } + // @computed get scrollSpeed() { + // return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; //default scroll speed + // } + + selectedNodeIndex = observable.box(-1); // -1 indicates no selection + + @action + setSelectedNodeIndex = (index: number) => { + console.log('hi'); + SelectionManager.DeselectAll(); + this.selectedNodeIndex.set(index); + }; + + @computed + get rotationDegree() { + return this.isChildContentActive() ? 30 : 0; // Rotate by 30 degrees if selected, otherwise no rotation +} + + + constructor(props: any) { super(props); makeObservable(this); @@ -39,17 +58,23 @@ export class CollectionCardView extends CollectionSubView() { }; centerScale = Number(CAROUSEL3D_CENTER_SCALE); - panelWidth = () => this._props.PanelWidth() / 3; - panelHeight = () => this._props.PanelHeight() * Number(CAROUSEL3D_SIDE_SCALE); + panelWidth = () => (this._props.PanelWidth()) / this.childLayoutPairs.length; + panelHeight = () => this.panelWidth() * 1.5; onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick); + onChildClick = () => ScriptCast(this.rotate(3, 3)); isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive(); isChildContentActive = () => (this.isContentActive() ? true : false); + + //thid needs to be fixed childScreenToLocal = () => this._props // document's left is the panel shifted by the doc's index * panelWidth/#docs. But it scales by centerScale around its center, so it's left moves left by the distance of the left from the center (panelwidth/2) * the scale delta (centerScale-1) .ScreenToLocalTransform() // the top behaves the same way ecept it's shifted by the 'top' amount specified for the panel in css and then by the scale factor. - .translate(-this.panelWidth() + ((this.centerScale - 1) * this.panelWidth()) / 2, -((Number(CAROUSEL3D_TOP) / 100) * this._props.PanelHeight()) + ((this.centerScale - 1) * this.panelHeight()) / 2) - .scale(1 / this.centerScale); + // .translate(-this.panelWidth() + ((this.centerScale - 1) * this.panelWidth()) / 2,-((Number(CAROUSEL3D_TOP) / 100) * this._props.PanelHeight()) + ((this.centerScale - 1) * this.panelHeight()) / 2) + .rotate(this.rotate(this.childLayoutPairs.length, Number(this.layoutDoc._carousel_index))) + // .scale(1 / this.centerScale); + + //literally doesnot do anythin focus = (anchor: Doc, options: FocusViewOptions) => { const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); if (anchor.type !== DocumentType.CONFIG && !docs.includes(anchor)) return; @@ -60,15 +85,41 @@ export class CollectionCardView extends CollectionSubView() { return undefined; }; + rotate = (amCards: number, index: number) => { + + const possRotate = -30 + (index * (30/((amCards - (amCards%2))/2))); + + if (amCards%2 == 0 && possRotate==0){ + console.log('whaddup') + return possRotate + Math.abs(-30 + ((index-1) * (30/((amCards - 1)/2)))) + } + + return possRotate; + } + + // translateY = (amCards: number, index: number) => { + // // Assuming you want a default value when index > amCards/2 + // // Adjust the logic as necessary for your use case + // if (index <= amCards / 2) { + // return -((50 / ((amCards - (amCards % 2)) / 2)) * index); + // } else { + // // Return a default or calculated value for indices greater than amCards/2 + // // This is just an example; adjust the logic as needed + // return -((50 / ((amCards - (amCards % 2)) / 2)) * (amCards - index - 1)); + // } + // }; + @computed get content() { - const currentIndex = NumCast(this.layoutDoc._carousel_index); + // const currentIndex = NumCast(this.layoutDoc._carousel_index); + const amCards = this.childLayoutPairs.length; const displayDoc = (childPair: { layout: Doc; data: Doc }) => { return ( { + + const isSelected = this.selectedNodeIndex.get() === index; + const rotationDegree = isSelected ? 30 : 0; // Rotate selected node by 5 degrees, for example + + return ( -
+
this.setSelectedNodeIndex(index)} + + + + > + {/* {this.lol(childPair.data, index)} */} + + {displayDoc(childPair)} -
+
); }); } - changeSlide = (direction: number) => { - SelectionManager.DeselectAll(); - this.layoutDoc._carousel_index = (NumCast(this.layoutDoc._carousel_index) + direction + this.childLayoutPairs.length) % this.childLayoutPairs.length; - }; - - onArrowClick = (direction: number) => { - this.changeSlide(direction); - !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = direction === 1 ? 'fwd' : 'back'); // while autoscroll is on, keep the other autoscroll button hidden - !this.layoutDoc.autoScrollOn && this.fadeScrollButton(); // keep pause button visible while autoscroll is on - }; - - interval?: number; - startAutoScroll = (direction: number) => { - this.interval = window.setInterval(() => { - this.changeSlide(direction); - }, this.scrollSpeed); - }; + // lol = (d : Doc, index: number) => { + // if (SelectionManager.IsSelected(d)){ + // this.setSelectedNodeIndex(index); - stopAutoScroll = () => { - window.clearInterval(this.interval); - this.interval = undefined; - this.fadeScrollButton(); - }; - - toggleAutoScroll = (direction: number) => { - this.layoutDoc.autoScrollOn = this.layoutDoc.autoScrollOn ? false : true; - this.layoutDoc.autoScrollOn ? this.startAutoScroll(direction) : this.stopAutoScroll(); - }; + // } + // } - fadeScrollButton = () => { - window.setTimeout(() => { - !this.layoutDoc.autoScrollOn && (this.layoutDoc.showScrollButton = 'none'); //fade away after 1.5s if it's not clicked. - }, 1500); - }; - - @computed get buttons() { - return ( -
-
this.onArrowClick(-1)} /> -
this.onArrowClick(1)} /> - {/* {this.autoScrollButton} */} -
- ); - } - - @computed get autoScrollButton() { - const whichButton = this.layoutDoc.showScrollButton; - return ( - <> -
this.toggleAutoScroll(-1)}> - {this.layoutDoc.autoScrollOn ? : } -
-
this.toggleAutoScroll(1)}> - {this.layoutDoc.autoScrollOn ? : } -
- - ); - } - - @computed get dots() { - return this.childLayoutPairs.map((_child, index) =>
(this.layoutDoc._carousel_index = index)} />); - } @computed get translateX() { const index = NumCast(this.layoutDoc._carousel_index); return this.panelWidth() * (1 - index); @@ -172,11 +188,13 @@ export class CollectionCardView extends CollectionSubView() { background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor), color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color), }}> -
+
{this.content}
- {this.buttons} -
{this.dots}
+ {/* {this.buttons} +
{this.dots}
*/}
); } -- cgit v1.2.3-70-g09d2 From 568d196c15c44f89388985c267d4ffe6c2e28a7b Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Wed, 20 Mar 2024 14:14:02 -0400 Subject: figuring out how to find the doc wrapper thing --- .../views/collections/CollectionCardDeckView.scss | 19 ++++ .../views/collections/CollectionCardDeckView.tsx | 114 ++++++++++++++------- 2 files changed, 96 insertions(+), 37 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss index e69de29bb..b6d9ca202 100644 --- a/src/client/views/collections/CollectionCardDeckView.scss +++ b/src/client/views/collections/CollectionCardDeckView.scss @@ -0,0 +1,19 @@ +@import '../global/globalCssVariables.module.scss'; + +.collectionCardView-outer { + height: 100%; + position: relative; + background-color: white; + overflow: hidden; +} + +.card-wrapper { + display: flex; + position: absolute; + top: $CAROUSEL3D_TOP * 1%; + height: ($CAROUSEL3D_SIDE_SCALE * 100) * 1%; + align-items: center; + transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); +} + + diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 778280215..3b3c4a764 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -12,36 +12,69 @@ import { SelectionManager } from '../../util/SelectionManager'; import { StyleProp } from '../StyleProvider'; import { DocumentView } from '../nodes/DocumentView'; import { FocusViewOptions } from '../nodes/FieldView'; -import './CollectionCarousel3DView.scss'; +import './CollectionCardDeckView.scss'; import { CollectionSubView } from './CollectionSubView'; import { ScriptField } from '../../../fields/ScriptField'; +import { lengthToDegrees } from '@turf/turf'; -const { default: { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } } = require('../global/globalCssVariables.module.scss'); // prettier-ignore @observer export class CollectionCardView extends CollectionSubView() { - // @computed get scrollSpeed() { - // return this.layoutDoc._autoScrollSpeed ? NumCast(this.layoutDoc._autoScrollSpeed) : 1000; //default scroll speed - // } + + @observable selectedNodeIndex = -1; + + @observable hoveredNodeIndex = -1; + + @action + setHoveredNodeIndex = (index : number) => { + this.hoveredNodeIndex = index; + } - selectedNodeIndex = observable.box(-1); // -1 indicates no selection + translateHover = (index : number) => { + if (this.hoveredNodeIndex == index){ + return -50; + } + return 0; + } + + @action setSelectedNodeIndex = (index: number) => { - console.log('hi'); - SelectionManager.DeselectAll(); - this.selectedNodeIndex.set(index); + + const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); + console.log("goodnight") + + if (SelectionManager.IsSelected(docs[index])){ + console.log("good mornings") + this.setSelectedNodeIndex(index); + } }; - @computed - get rotationDegree() { - return this.isChildContentActive() ? 30 : 0; // Rotate by 30 degrees if selected, otherwise no rotation -} + + isSelected = (index : number) => { + const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); + + return SelectionManager.IsSelected(docs[index]) + + } + + // @computed + // rotationDegree = (index : number) => { + // const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); + + // if (SelectionManager.IsSelected(docs[index])){ + // return 30; + // } + + // return 0; + // } constructor(props: any) { super(props); makeObservable(this); + // this.rotationDegree(7); } private _dropDisposer?: DragManager.DragDropDisposer; @@ -57,11 +90,10 @@ export class CollectionCardView extends CollectionSubView() { } }; - centerScale = Number(CAROUSEL3D_CENTER_SCALE); panelWidth = () => (this._props.PanelWidth()) / this.childLayoutPairs.length; panelHeight = () => this.panelWidth() * 1.5; onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick); - onChildClick = () => ScriptCast(this.rotate(3, 3)); + // onChildClick = () => ScriptCast(this.rotate(3, 3)); isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive(); isChildContentActive = () => (this.isContentActive() ? true : false); @@ -75,15 +107,15 @@ export class CollectionCardView extends CollectionSubView() { //literally doesnot do anythin - focus = (anchor: Doc, options: FocusViewOptions) => { - const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); - if (anchor.type !== DocumentType.CONFIG && !docs.includes(anchor)) return; - options.didMove = true; - const target = DocCast(anchor.annotationOn) ?? anchor; - const index = docs.indexOf(target); - index !== -1 && (this.layoutDoc._carousel_index = index); //if index is not -1, then assign index to this.layoutDoc._carousel_index - return undefined; - }; + // focus = (anchor: Doc, options: FocusViewOptions) => { + // const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); + // if (anchor.type !== DocumentType.CONFIG && !docs.includes(anchor)) return; + // options.didMove = true; + // const target = DocCast(anchor.annotationOn) ?? anchor; + // const index = docs.indexOf(target); + // index !== -1 && (this.layoutDoc._carousel_index = index); //if index is not -1, then assign index to this.layoutDoc._carousel_index + // return undefined; + // }; rotate = (amCards: number, index: number) => { @@ -128,7 +160,7 @@ export class CollectionCardView extends CollectionSubView() { renderDepth={this._props.renderDepth + 1} LayoutTemplate={this._props.childLayoutTemplate} LayoutTemplateString={this._props.childLayoutString} - focus={this.focus} + // focus={this.focus} ScreenToLocalTransform={this.childScreenToLocal} //makes sure the box wrapper thing is in the right spot isContentActive={this.isChildContentActive} isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive} @@ -140,20 +172,29 @@ export class CollectionCardView extends CollectionSubView() { return this.childLayoutPairs.map((childPair, index) => { - const isSelected = this.selectedNodeIndex.get() === index; - const rotationDegree = isSelected ? 30 : 0; // Rotate selected node by 5 degrees, for example - + const isSelected = this.isSelected(index); + console.log(index + "is select?: " + isSelected); + const isHovered = this.hoveredNodeIndex === index; return (
this.setSelectedNodeIndex(index)} + + + // onClick={() => this.setSelectedNodeIndex(index)} + + onMouseEnter={() => this.setHoveredNodeIndex(index)} + onMouseLeave={() => this.setHoveredNodeIndex(-1)} @@ -182,19 +223,18 @@ export class CollectionCardView extends CollectionSubView() { render() { return (
-
{this.content}
- {/* {this.buttons} -
{this.dots}
*/}
); } -- cgit v1.2.3-70-g09d2 From 1bc9290023c854f805a5fea15ffe34383be3d242 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 20 Mar 2024 16:09:22 -0400 Subject: fix for document decorations --- .../views/collections/CollectionCardDeckView.tsx | 127 +++++++++------------ 1 file changed, 55 insertions(+), 72 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 3b3c4a764..460f74a61 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -1,62 +1,52 @@ -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { computed, makeObservable, observable, action } from 'mobx'; -import { observer, } from 'mobx-react'; +import { ObservableMap, action, computed, makeObservable, observable } from 'mobx'; +import { observer } from 'mobx-react'; import * as React from 'react'; -import { Utils, emptyFunction, returnFalse, returnZero } from '../../../Utils'; +import { Utils, returnZero } from '../../../Utils'; import { Doc, DocListCast } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; -import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; -import { DocumentType } from '../../documents/DocumentTypes'; +import { NumCast, ScriptCast } from '../../../fields/Types'; import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { StyleProp } from '../StyleProvider'; import { DocumentView } from '../nodes/DocumentView'; -import { FocusViewOptions } from '../nodes/FieldView'; import './CollectionCardDeckView.scss'; import { CollectionSubView } from './CollectionSubView'; -import { ScriptField } from '../../../fields/ScriptField'; -import { lengthToDegrees } from '@turf/turf'; +import { Transform } from '../../util/Transform'; @observer export class CollectionCardView extends CollectionSubView() { - @observable selectedNodeIndex = -1; @observable hoveredNodeIndex = -1; @action - setHoveredNodeIndex = (index : number) => { + setHoveredNodeIndex = (index: number) => { this.hoveredNodeIndex = index; - } + }; - translateHover = (index : number) => { - if (this.hoveredNodeIndex == index){ + translateHover = (index: number) => { + if (this.hoveredNodeIndex == index) { return -50; } return 0; - } - - + }; @action setSelectedNodeIndex = (index: number) => { - const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); - console.log("goodnight") + console.log('goodnight'); - if (SelectionManager.IsSelected(docs[index])){ - console.log("good mornings") + if (SelectionManager.IsSelected(docs[index])) { + console.log('good mornings'); this.setSelectedNodeIndex(index); } }; - - isSelected = (index : number) => { + isSelected = (index: number) => { const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); - return SelectionManager.IsSelected(docs[index]) - - } + return SelectionManager.IsSelected(docs[index]); + }; // @computed // rotationDegree = (index : number) => { @@ -69,8 +59,6 @@ export class CollectionCardView extends CollectionSubView() { // return 0; // } - - constructor(props: any) { super(props); makeObservable(this); @@ -90,21 +78,20 @@ export class CollectionCardView extends CollectionSubView() { } }; - panelWidth = () => (this._props.PanelWidth()) / this.childLayoutPairs.length; + panelWidth = () => this._props.PanelWidth() / this.childLayoutPairs.length; panelHeight = () => this.panelWidth() * 1.5; onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick); // onChildClick = () => ScriptCast(this.rotate(3, 3)); isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive(); isChildContentActive = () => (this.isContentActive() ? true : false); - + //thid needs to be fixed childScreenToLocal = () => this._props // document's left is the panel shifted by the doc's index * panelWidth/#docs. But it scales by centerScale around its center, so it's left moves left by the distance of the left from the center (panelwidth/2) * the scale delta (centerScale-1) .ScreenToLocalTransform() // the top behaves the same way ecept it's shifted by the 'top' amount specified for the panel in css and then by the scale factor. // .translate(-this.panelWidth() + ((this.centerScale - 1) * this.panelWidth()) / 2,-((Number(CAROUSEL3D_TOP) / 100) * this._props.PanelHeight()) + ((this.centerScale - 1) * this.panelHeight()) / 2) - .rotate(this.rotate(this.childLayoutPairs.length, Number(this.layoutDoc._carousel_index))) - // .scale(1 / this.centerScale); - + .rotate(this.rotate(this.childLayoutPairs.length, Number(this.layoutDoc._carousel_index))); + // .scale(1 / this.centerScale); //literally doesnot do anythin // focus = (anchor: Doc, options: FocusViewOptions) => { @@ -118,16 +105,15 @@ export class CollectionCardView extends CollectionSubView() { // }; rotate = (amCards: number, index: number) => { + const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2)); - const possRotate = -30 + (index * (30/((amCards - (amCards%2))/2))); - - if (amCards%2 == 0 && possRotate==0){ - console.log('whaddup') - return possRotate + Math.abs(-30 + ((index-1) * (30/((amCards - 1)/2)))) + if (amCards % 2 == 0 && possRotate == 0) { + console.log('whaddup'); + return possRotate + Math.abs(-30 + (index - 1) * (30 / ((amCards - 1) / 2))); } - - return possRotate; - } + + return possRotate; + }; // translateY = (amCards: number, index: number) => { // // Assuming you want a default value when index > amCards/2 @@ -140,15 +126,16 @@ export class CollectionCardView extends CollectionSubView() { // return -((50 / ((amCards - (amCards % 2)) / 2)) * (amCards - index - 1)); // } // }; + @observable docRefs = new ObservableMap(); - @computed get content() { // const currentIndex = NumCast(this.layoutDoc._carousel_index); const amCards = this.childLayoutPairs.length; - const displayDoc = (childPair: { layout: Doc; data: Doc }) => { + const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { return ( r?.ContentDiv && this.docRefs.set(childPair.layout, r))} Document={childPair.layout} TemplateDataDocument={childPair.data} // onClickScript={this.toggleIcon} @@ -161,7 +148,7 @@ export class CollectionCardView extends CollectionSubView() { LayoutTemplate={this._props.childLayoutTemplate} LayoutTemplateString={this._props.childLayoutString} // focus={this.focus} - ScreenToLocalTransform={this.childScreenToLocal} //makes sure the box wrapper thing is in the right spot + ScreenToLocalTransform={screenToLocalTransform} //makes sure the box wrapper thing is in the right spot isContentActive={this.isChildContentActive} isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive} PanelWidth={this.panelWidth} @@ -171,39 +158,37 @@ export class CollectionCardView extends CollectionSubView() { }; return this.childLayoutPairs.map((childPair, index) => { - const isSelected = this.isSelected(index); - console.log(index + "is select?: " + isSelected); + console.log(index + 'is select?: ' + isSelected); const isHovered = this.hoveredNodeIndex === index; + const childScreenToLocal = () => { + const dref = this.docRefs.get(childPair.layout); + const { translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv); + // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off + return new Transform(-translateX + (dref?.centeringX || 0), -translateY + (dref?.centeringY || 0), 1).scale(1 / (isSelected ? 1.25 : 1)).rotate(!isSelected ? -this.rotate(amCards, index) : 0); + }; + return ( -
this.setSelectedNodeIndex(index)} - - - - }} - - - // onClick={() => this.setSelectedNodeIndex(index)} - - onMouseEnter={() => this.setHoveredNodeIndex(index)} - onMouseLeave={() => this.setHoveredNodeIndex(-1)} - - - - > + onMouseEnter={() => this.setHoveredNodeIndex(index)} + onMouseLeave={() => this.setHoveredNodeIndex(-1)}> {/* {this.lol(childPair.data, index)} */} - - {displayDoc(childPair)} -
+ {displayDoc(childPair, childScreenToLocal)} +
); }); } @@ -229,15 +214,13 @@ export class CollectionCardView extends CollectionSubView() { background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor), color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color), }}> -
{this.content}
); } - - } -- cgit v1.2.3-70-g09d2 From e15b5873b429e9a01cf92a471748d8ee123461ef Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Thu, 21 Mar 2024 03:29:26 -0400 Subject: . --- .../views/collections/CollectionCardDeckView.scss | 10 ++ .../views/collections/CollectionCardDeckView.tsx | 110 ++++++++++++--------- 2 files changed, 71 insertions(+), 49 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss index b6d9ca202..95a9b658c 100644 --- a/src/client/views/collections/CollectionCardDeckView.scss +++ b/src/client/views/collections/CollectionCardDeckView.scss @@ -16,4 +16,14 @@ transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); } +.card-item-active, .card-item{ + transition: transform 0.3s ease-in-out; +} + + +.card-item-active{ + position: absolute; + z-index: 100; +} + diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 460f74a61..a4d0d1862 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -12,6 +12,7 @@ import { DocumentView } from '../nodes/DocumentView'; import './CollectionCardDeckView.scss'; import { CollectionSubView } from './CollectionSubView'; import { Transform } from '../../util/Transform'; +import { indexes } from 'd3'; @observer export class CollectionCardView extends CollectionSubView() { @@ -21,11 +22,13 @@ export class CollectionCardView extends CollectionSubView() { @action setHoveredNodeIndex = (index: number) => { + if (!this.isSelected(index)){ this.hoveredNodeIndex = index; + } }; - translateHover = (index: number) => { - if (this.hoveredNodeIndex == index) { + translateHover = (index: number): number => { + if (this.hoveredNodeIndex == index && !this.isSelected(index)) { return -50; } return 0; @@ -42,22 +45,17 @@ export class CollectionCardView extends CollectionSubView() { } }; - isSelected = (index: number) => { + isSelected = (index: number): boolean => { const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); return SelectionManager.IsSelected(docs[index]); }; - // @computed - // rotationDegree = (index : number) => { - // const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); - - // if (SelectionManager.IsSelected(docs[index])){ - // return 30; - // } + inactiveDocs = () => { + const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); - // return 0; - // } + return docs.filter(d => !SelectionManager.IsSelected(d)); + } constructor(props: any) { super(props); @@ -81,28 +79,9 @@ export class CollectionCardView extends CollectionSubView() { panelWidth = () => this._props.PanelWidth() / this.childLayoutPairs.length; panelHeight = () => this.panelWidth() * 1.5; onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick); - // onChildClick = () => ScriptCast(this.rotate(3, 3)); isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive(); isChildContentActive = () => (this.isContentActive() ? true : false); - //thid needs to be fixed - childScreenToLocal = () => - this._props // document's left is the panel shifted by the doc's index * panelWidth/#docs. But it scales by centerScale around its center, so it's left moves left by the distance of the left from the center (panelwidth/2) * the scale delta (centerScale-1) - .ScreenToLocalTransform() // the top behaves the same way ecept it's shifted by the 'top' amount specified for the panel in css and then by the scale factor. - // .translate(-this.panelWidth() + ((this.centerScale - 1) * this.panelWidth()) / 2,-((Number(CAROUSEL3D_TOP) / 100) * this._props.PanelHeight()) + ((this.centerScale - 1) * this.panelHeight()) / 2) - .rotate(this.rotate(this.childLayoutPairs.length, Number(this.layoutDoc._carousel_index))); - // .scale(1 / this.centerScale); - - //literally doesnot do anythin - // focus = (anchor: Doc, options: FocusViewOptions) => { - // const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); - // if (anchor.type !== DocumentType.CONFIG && !docs.includes(anchor)) return; - // options.didMove = true; - // const target = DocCast(anchor.annotationOn) ?? anchor; - // const index = docs.indexOf(target); - // index !== -1 && (this.layoutDoc._carousel_index = index); //if index is not -1, then assign index to this.layoutDoc._carousel_index - // return undefined; - // }; rotate = (amCards: number, index: number) => { const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2)); @@ -126,11 +105,33 @@ export class CollectionCardView extends CollectionSubView() { // return -((50 / ((amCards - (amCards % 2)) / 2)) * (amCards - index - 1)); // } // }; + + + translateSelected = (index: number): number => { + if (this.isSelected(index)){ + const middleOfPanel = this._props.PanelWidth() / 2; + const scaledNodeWidth = this.panelWidth() * 1.25; + + // 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); + + // Calculate the translation needed to align the scaled node's center with the panel's center + const translation = middleOfPanel - scaledNodeCenter; + + return translation; + } + + return 0; + }; + @observable docRefs = new ObservableMap(); @computed get content() { // const currentIndex = NumCast(this.layoutDoc._carousel_index); - const amCards = this.childLayoutPairs.length; + const amCards = this.inactiveDocs().length; + // const myInactives = const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { return ( { const isSelected = this.isSelected(index); - console.log(index + 'is select?: ' + isSelected); const isHovered = this.hoveredNodeIndex === index; + const inactiveIndex = this.inactiveDocs().indexOf(childPair.layout); const childScreenToLocal = () => { const dref = this.docRefs.get(childPair.layout); const { translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv); // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off - return new Transform(-translateX + (dref?.centeringX || 0), -translateY + (dref?.centeringY || 0), 1).scale(1 / (isSelected ? 1.25 : 1)).rotate(!isSelected ? -this.rotate(amCards, index) : 0); + return new Transform(-translateX + (dref?.centeringX || 0), -translateY + (dref?.centeringY || 0), 1).scale(1 / (isSelected ? 1.25 : 1)).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0); }; return (
this.setSelectedNodeIndex(index)} onMouseEnter={() => this.setHoveredNodeIndex(index)} - onMouseLeave={() => this.setHoveredNodeIndex(-1)}> + > {/* {this.lol(childPair.data, index)} */} {displayDoc(childPair, childScreenToLocal)} @@ -193,16 +201,13 @@ export class CollectionCardView extends CollectionSubView() { }); } - // lol = (d : Doc, index: number) => { - // if (SelectionManager.IsSelected(d)){ - // this.setSelectedNodeIndex(index); + @computed get translateWrapperX() { - // } - // } + if (this.inactiveDocs().length != this.childLayoutPairs.length){ + return this.panelWidth()/2 + } - @computed get translateX() { - const index = NumCast(this.layoutDoc._carousel_index); - return this.panelWidth() * (1 - index); + return 0; } render() { @@ -216,10 +221,17 @@ export class CollectionCardView extends CollectionSubView() { }}>
this.setHoveredNodeIndex(-1)} > {this.content}
+ + {/* {this.focusContent} */} + +
); } -- cgit v1.2.3-70-g09d2 From bf84209b90427d9bd91e9f1e5c191f613a96a90a Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Thu, 21 Mar 2024 04:54:19 -0400 Subject: figuring out sorting-- may just leave it to god --- .../views/collections/CollectionCardDeckView.tsx | 47 ++++++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index a4d0d1862..66729d64b 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -2,9 +2,9 @@ import { ObservableMap, action, computed, makeObservable, observable } from 'mob import { observer } from 'mobx-react'; import * as React from 'react'; import { Utils, returnZero } from '../../../Utils'; -import { Doc, DocListCast } from '../../../fields/Doc'; +import { Doc, DocListCast, Field } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; -import { NumCast, ScriptCast } from '../../../fields/Types'; +import { NumCast, ScriptCast, StrCast, BoolCast } from '../../../fields/Types'; import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { StyleProp } from '../StyleProvider'; @@ -57,6 +57,19 @@ export class CollectionCardView extends CollectionSubView() { return docs.filter(d => !SelectionManager.IsSelected(d)); } + middleIndex = Math.floor(this.inactiveDocs().length / 2); + + + // verticalOffset = (index: number) => { + + // const distanceFromMiddle = Math.abs(index - this.middleIndex); + // // Adjust '4' to control the curvature; larger values create a flatter arc. + // return Math.pow(distanceFromMiddle, 2)* (Math.floor(64/this.inactiveDocs().length)); // Example quadratic function + // }; + + + + constructor(props: any) { super(props); makeObservable(this); @@ -126,6 +139,25 @@ export class CollectionCardView extends CollectionSubView() { return 0; }; + @computed get sortedDocs() { + const field = StrCast(this.layoutDoc.sortField); + const desc = BoolCast(this.layoutDoc.sortDesc); + const docs = !field + ? this.childDocs + : [...this.childDocs].sort((docA, docB) => { + const aStr = Field.toString(docA[field] as Field); + const bStr = Field.toString(docB[field] as Field); + var out = 0; + if (aStr < bStr) out = -1; + if (aStr > bStr) out = 1; + if (desc) out *= -1; + return out; + }); + return { docs }; + } + + + @observable docRefs = new ObservableMap(); @computed get content() { @@ -162,6 +194,8 @@ export class CollectionCardView extends CollectionSubView() { const isSelected = this.isSelected(index); const isHovered = this.hoveredNodeIndex === index; const inactiveIndex = this.inactiveDocs().indexOf(childPair.layout); + // const yOffset = this.verticalOffset(index); + const childScreenToLocal = () => { const dref = this.docRefs.get(childPair.layout); @@ -180,15 +214,20 @@ export class CollectionCardView extends CollectionSubView() { transform: ` rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg) - translateX(${isSelected ? ((this._props.PanelWidth() / 2) - 210) : 0}px) translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 : 0}px) - scale(${isSelected ? 1.25 : 1})` //scale has to be applied last or selected offset gets messed up + translateX(${isSelected ? ((this._props.PanelWidth() / 2) - ((this.panelWidth())/2) - (this.panelWidth()/2)) : 0}px) + + scale(${isSelected ? 1.25 : 1}) + + ` //scale has to be applied last or selected offset gets messed up , }} + + // onClick={() => this.setSelectedNodeIndex(index)} onMouseEnter={() => this.setHoveredNodeIndex(index)} -- cgit v1.2.3-70-g09d2 From 268c4487aab34c8bef51df87953d83b968864fc4 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 21 Mar 2024 11:10:16 -0400 Subject: transformation fixes for cardDeckView --- .../views/collections/CollectionCardDeckView.scss | 10 +-- .../views/collections/CollectionCardDeckView.tsx | 93 +++++++++------------- 2 files changed, 39 insertions(+), 64 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss index 95a9b658c..ebd7f9856 100644 --- a/src/client/views/collections/CollectionCardDeckView.scss +++ b/src/client/views/collections/CollectionCardDeckView.scss @@ -10,20 +10,16 @@ .card-wrapper { display: flex; position: absolute; - top: $CAROUSEL3D_TOP * 1%; - height: ($CAROUSEL3D_SIDE_SCALE * 100) * 1%; align-items: center; transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); } -.card-item-active, .card-item{ +.card-item-active, +.card-item { transition: transform 0.3s ease-in-out; } - -.card-item-active{ +.card-item-active { position: absolute; z-index: 100; } - - diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 66729d64b..e923f9a72 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -1,7 +1,7 @@ import { ObservableMap, action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Utils, returnZero } from '../../../Utils'; +import { Utils, returnFalse, returnTrue, returnZero } from '../../../Utils'; import { Doc, DocListCast, Field } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { NumCast, ScriptCast, StrCast, BoolCast } from '../../../fields/Types'; @@ -12,7 +12,6 @@ import { DocumentView } from '../nodes/DocumentView'; import './CollectionCardDeckView.scss'; import { CollectionSubView } from './CollectionSubView'; import { Transform } from '../../util/Transform'; -import { indexes } from 'd3'; @observer export class CollectionCardView extends CollectionSubView() { @@ -22,8 +21,8 @@ export class CollectionCardView extends CollectionSubView() { @action setHoveredNodeIndex = (index: number) => { - if (!this.isSelected(index)){ - this.hoveredNodeIndex = index; + if (!this.isSelected(index)) { + this.hoveredNodeIndex = index; } }; @@ -55,21 +54,10 @@ export class CollectionCardView extends CollectionSubView() { const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); return docs.filter(d => !SelectionManager.IsSelected(d)); - } + }; middleIndex = Math.floor(this.inactiveDocs().length / 2); - - // verticalOffset = (index: number) => { - - // const distanceFromMiddle = Math.abs(index - this.middleIndex); - // // Adjust '4' to control the curvature; larger values create a flatter arc. - // return Math.pow(distanceFromMiddle, 2)* (Math.floor(64/this.inactiveDocs().length)); // Example quadratic function - // }; - - - - constructor(props: any) { super(props); makeObservable(this); @@ -89,13 +77,19 @@ export class CollectionCardView extends CollectionSubView() { } }; - panelWidth = () => this._props.PanelWidth() / this.childLayoutPairs.length; - panelHeight = () => this.panelWidth() * 1.5; + childDocumentWidth = 600; // target width of a Doc... + /** + * how much to scale down the contents of the view so that everything will fit + */ + @computed get fitContentScale() { + return (this.childDocumentWidth * this.childLayoutPairs.length) / this._props.PanelWidth(); + } + panelWidth = () => this.childDocumentWidth; + panelHeight = (layout: Doc) => () => (2 * (this.panelWidth() * NumCast(layout._height))) / NumCast(layout._width); onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick); isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive(); isChildContentActive = () => (this.isContentActive() ? true : false); - rotate = (amCards: number, index: number) => { const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2)); @@ -119,23 +113,22 @@ export class CollectionCardView extends CollectionSubView() { // } // }; - translateSelected = (index: number): number => { - if (this.isSelected(index)){ + if (this.isSelected(index)) { const middleOfPanel = this._props.PanelWidth() / 2; const scaledNodeWidth = this.panelWidth() * 1.25; - + // 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); - + const scaledNodeCenter = nodeLeftEdge + scaledNodeWidth / 2; + // Calculate the translation needed to align the scaled node's center with the panel's center const translation = middleOfPanel - scaledNodeCenter; - + return translation; } - + return 0; }; @@ -156,14 +149,12 @@ export class CollectionCardView extends CollectionSubView() { return { docs }; } - - @observable docRefs = new ObservableMap(); @computed get content() { // const currentIndex = NumCast(this.layoutDoc._carousel_index); const amCards = this.inactiveDocs().length; - // const myInactives = + // const myInactives = const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { return ( ); }; @@ -196,12 +187,11 @@ export class CollectionCardView extends CollectionSubView() { const inactiveIndex = this.inactiveDocs().indexOf(childPair.layout); // const yOffset = this.verticalOffset(index); - const childScreenToLocal = () => { const dref = this.docRefs.get(childPair.layout); - const { translateX, translateY } = Utils.GetScreenTransform(dref?.ContentDiv); + const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv); // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off - return new Transform(-translateX + (dref?.centeringX || 0), -translateY + (dref?.centeringY || 0), 1).scale(1 / (isSelected ? 1.25 : 1)).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0); + return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0); }; return ( @@ -210,28 +200,19 @@ export class CollectionCardView extends CollectionSubView() { className={`card-item${isSelected ? '-active' : ''}`} style={{ width: this.panelWidth(), - height: this.panelHeight(), - transform: - ` + height: this.panelHeight(childPair.layout)(), + transform: ` rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg) translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 : 0}px) - translateX(${isSelected ? ((this._props.PanelWidth() / 2) - ((this.panelWidth())/2) - (this.panelWidth()/2)) : 0}px) + translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth / 2 : 0}px) scale(${isSelected ? 1.25 : 1}) - ` //scale has to be applied last or selected offset gets messed up - - , + `, //scale has to be applied last or selected offset gets messed up }} - - - - - // onClick={() => this.setSelectedNodeIndex(index)} - onMouseEnter={() => this.setHoveredNodeIndex(index)} - > + onMouseEnter={() => this.setHoveredNodeIndex(index)}> {/* {this.lol(childPair.data, index)} */} {displayDoc(childPair, childScreenToLocal)} @@ -241,9 +222,8 @@ export class CollectionCardView extends CollectionSubView() { } @computed get translateWrapperX() { - - if (this.inactiveDocs().length != this.childLayoutPairs.length){ - return this.panelWidth()/2 + if (this.inactiveDocs().length != this.childLayoutPairs.length) { + return this.panelWidth(); } return 0; @@ -260,17 +240,16 @@ export class CollectionCardView extends CollectionSubView() { }}>
this.setHoveredNodeIndex(-1)} - > + onMouseLeave={() => this.setHoveredNodeIndex(-1)}> {this.content}
{/* {this.focusContent} */} - -
); } -- cgit v1.2.3-70-g09d2 From 10f6780728ca83d76a058552ba7023c4a5c881b5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 21 Mar 2024 14:43:08 -0400 Subject: from last --- src/client/views/collections/CollectionCardDeckView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index e923f9a72..b636b878e 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -28,7 +28,7 @@ export class CollectionCardView extends CollectionSubView() { translateHover = (index: number): number => { if (this.hoveredNodeIndex == index && !this.isSelected(index)) { - return -50; + return -50 * this.fitContentScale; } return 0; }; @@ -203,7 +203,7 @@ export class CollectionCardView extends CollectionSubView() { height: this.panelHeight(childPair.layout)(), transform: ` rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg) - translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 : 0}px) + translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 * this.fitContentScale : 0}px) translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth / 2 : 0}px) scale(${isSelected ? 1.25 : 1}) -- cgit v1.2.3-70-g09d2 From 276250446b4ad0f86a43a6773d2fff83e8bcaa49 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Thu, 4 Apr 2024 04:22:37 -0400 Subject: fixed weird centering, finally got the y positioning working, and am (unsuccesfully) working on creating rows --- .../views/collections/CollectionCardDeckView.scss | 9 ++ .../views/collections/CollectionCardDeckView.tsx | 174 ++++++++++++++++++--- 2 files changed, 162 insertions(+), 21 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss index ebd7f9856..ff9c0a569 100644 --- a/src/client/views/collections/CollectionCardDeckView.scss +++ b/src/client/views/collections/CollectionCardDeckView.scss @@ -14,6 +14,15 @@ transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); } +.card-row{ + display: flex; + position: absolute; + align-items: center; + transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); + + +} + .card-item-active, .card-item { transition: transform 0.3s ease-in-out; diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index b636b878e..98b4e8ec9 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -92,26 +92,55 @@ export class CollectionCardView extends CollectionSubView() { rotate = (amCards: number, index: number) => { const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2)); + const stepMag = Math.abs(-30 + ((amCards/2)- 1) * (30 / ((amCards - (amCards % 2)) / 2))); + + // console.log(possRotate + "poss") if (amCards % 2 == 0 && possRotate == 0) { - console.log('whaddup'); - return possRotate + Math.abs(-30 + (index - 1) * (30 / ((amCards - 1) / 2))); + // console.log('whaddup'); + return possRotate + Math.abs(-30 + (index - 1) * (30 / ((amCards) / 2))); + } + + else if (amCards %2 == 0 && index > (amCards+1)/2){ + // console.log("sup" + stepMag); + + return possRotate + stepMag; } return possRotate; }; - // translateY = (amCards: number, index: number) => { - // // Assuming you want a default value when index > amCards/2 - // // Adjust the logic as necessary for your use case - // if (index <= amCards / 2) { - // return -((50 / ((amCards - (amCards % 2)) / 2)) * index); - // } else { - // // Return a default or calculated value for indices greater than amCards/2 - // // This is just an example; adjust the logic as needed - // return -((50 / ((amCards - (amCards % 2)) / 2)) * (amCards - index - 1)); - // } - // }; + translateY = (amCards: number, index: number) => { + const evenOdd =amCards% 2 + const apex = (amCards-evenOdd)/2 + const stepMag = (200 / ((amCards - evenOdd)/2)) + + Math.abs(((apex-index) *25)) + + console.log("steo" + stepMag) + + if (evenOdd == 1 || index < apex -1){ + console.log('hi' + index) + return Math.abs(stepMag * (apex - index)) + } + + else{ + if (index == apex || index == apex -1){ + return 0 + } + + return Math.abs(stepMag * (apex - index -1)) + + } + + }; + + translateOverFlowY = (amCards: number, index: number) => { + if (amCards>8 && index > amCards/2){ + return 100 + + } + return 0 + } translateSelected = (index: number): number => { if (this.isSelected(index)) { @@ -151,9 +180,80 @@ export class CollectionCardView extends CollectionSubView() { @observable docRefs = new ObservableMap(); - @computed get content() { + // @computed get content() { + // // const currentIndex = NumCast(this.layoutDoc._carousel_index); + // const amCards = this.inactiveDocs().length; + // // const myInactives = + // const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { + // return ( + // r?.ContentDiv && this.docRefs.set(childPair.layout, r))} + // Document={childPair.layout} + // TemplateDataDocument={childPair.data} + // // onClickScript={this.toggleIcon} + // //suppressSetHeight={true} + // NativeWidth={returnZero} + // NativeHeight={returnZero} + // layout_fitWidth={returnFalse} + // onDoubleClickScript={this.onChildDoubleClick} + // renderDepth={this._props.renderDepth + 1} + // LayoutTemplate={this._props.childLayoutTemplate} + // LayoutTemplateString={this._props.childLayoutString} + // // focus={this.focus} + // ScreenToLocalTransform={screenToLocalTransform} //makes sure the box wrapper thing is in the right spot + // isContentActive={this.isChildContentActive} + // isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive} + // PanelWidth={this.panelWidth} + // PanelHeight={this.panelHeight(childPair.layout)} + // /> + // ); + // }; + + // return this.childLayoutPairs.map((childPair, index) => { + // const isSelected = this.isSelected(index); + // const isHovered = this.hoveredNodeIndex === index; + // const isOverflow = amCards > 8 && index > amCards/2 + // const inactiveIndex = this.inactiveDocs().indexOf(childPair.layout); + // // const yOffset = this.verticalOffset(index); + + // const childScreenToLocal = () => { + // const dref = this.docRefs.get(childPair.layout); + // const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv); + // // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off + // return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0); + // }; + + // return ( + //
this.setSelectedNodeIndex(index)} + + // onMouseEnter={() => this.setHoveredNodeIndex(index)}> + // {/* {this.lol(childPair.data, index)} */} + + // {displayDoc(childPair, childScreenToLocal)} + //
+ // ); + // }); + // } + + @action content(amCards: number, startIndex: number, stopIndex: number) { // const currentIndex = NumCast(this.layoutDoc._carousel_index); - const amCards = this.inactiveDocs().length; + // const amCards = this.inactiveDocs().length; // const myInactives = const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { return ( @@ -181,9 +281,13 @@ export class CollectionCardView extends CollectionSubView() { ); }; - return this.childLayoutPairs.map((childPair, index) => { + const inactiveDocs = this.inactiveDocs(); + return this.childLayoutPairs.filter((childPair, index) => { const inactiveIndex = inactiveDocs.indexOf(childPair.layout); return inactiveIndex >= startIndex && inactiveIndex <= stopIndex; + }).map((childPair, index) => { + const isSelected = this.isSelected(index); const isHovered = this.hoveredNodeIndex === index; + const isOverflow = amCards > 8 && index > amCards/2 const inactiveIndex = this.inactiveDocs().indexOf(childPair.layout); // const yOffset = this.verticalOffset(index); @@ -203,8 +307,10 @@ export class CollectionCardView extends CollectionSubView() { height: this.panelHeight(childPair.layout)(), transform: ` rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg) - translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 * this.fitContentScale : 0}px) - translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth / 2 : 0}px) + translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, inactiveIndex) + // + this.translateOverFlowY(amCards, inactiveIndex) + }px) + translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth : 0}px) scale(${isSelected ? 1.25 : 1}) @@ -221,9 +327,35 @@ export class CollectionCardView extends CollectionSubView() { }); } + renderRows() { + const cards = this.inactiveDocs(); + const totalCards = cards.length; + const rowsNeeded = Math.ceil(totalCards / 8); + + let rows = []; + + for (let rowIndex = 0; rowIndex < rowsNeeded; rowIndex++) { + let rowStartIndex = rowIndex * 8; + let rowEndIndex = rowStartIndex + 8; + let rowCards = cards.slice(rowStartIndex, rowEndIndex); + + rows.push(this.renderRowCards(rowCards, rowIndex)); + } + + return rows; + } + + renderRowCards(rowCards: Doc[], rowIndex: number) { + return ( +
+ {this.content(rowCards.length, rowIndex*8, rowIndex*8+8)} +
+ ); + } + @computed get translateWrapperX() { if (this.inactiveDocs().length != this.childLayoutPairs.length) { - return this.panelWidth(); + return this.panelWidth()/2; } return 0; @@ -241,12 +373,12 @@ export class CollectionCardView extends CollectionSubView() {
this.setHoveredNodeIndex(-1)}> - {this.content} + {this.renderRows()}
{/* {this.focusContent} */} -- cgit v1.2.3-70-g09d2 From ba68af85177c9db3475532a13af08fd15f6b6ebe Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Thu, 11 Apr 2024 12:23:52 -0400 Subject: sorting works but nothing else does as is life --- .../views/collections/CollectionCardDeckView.tsx | 277 ++++++++++----------- 1 file changed, 128 insertions(+), 149 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 98b4e8ec9..d0a796218 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -12,6 +12,8 @@ import { DocumentView } from '../nodes/DocumentView'; import './CollectionCardDeckView.scss'; import { CollectionSubView } from './CollectionSubView'; import { Transform } from '../../util/Transform'; +// import Card from 'react-bootstrap/Card'; + @observer export class CollectionCardView extends CollectionSubView() { @@ -53,6 +55,8 @@ export class CollectionCardView extends CollectionSubView() { inactiveDocs = () => { const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); + + return docs.filter(d => !SelectionManager.IsSelected(d)); }; @@ -91,19 +95,18 @@ export class CollectionCardView extends CollectionSubView() { isChildContentActive = () => (this.isContentActive() ? true : false); rotate = (amCards: number, index: number) => { + console.log(amCards + "wtf") const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2)); - const stepMag = Math.abs(-30 + ((amCards/2)- 1) * (30 / ((amCards - (amCards % 2)) / 2))); + const stepMag = Math.abs(-30 + (amCards / 2 - 1) * (30 / ((amCards - (amCards % 2)) / 2))); // console.log(possRotate + "poss") if (amCards % 2 == 0 && possRotate == 0) { // console.log('whaddup'); - return possRotate + Math.abs(-30 + (index - 1) * (30 / ((amCards) / 2))); - } - - else if (amCards %2 == 0 && index > (amCards+1)/2){ + return possRotate + Math.abs(-30 + (index - 1) * (30 / (amCards / 2))); + } else if (amCards % 2 == 0 && index > (amCards + 1) / 2) { // console.log("sup" + stepMag); - + return possRotate + stepMag; } @@ -111,36 +114,30 @@ export class CollectionCardView extends CollectionSubView() { }; translateY = (amCards: number, index: number) => { - const evenOdd =amCards% 2 - const apex = (amCards-evenOdd)/2 - const stepMag = (200 / ((amCards - evenOdd)/2)) - + Math.abs(((apex-index) *25)) - - console.log("steo" + stepMag) - - if (evenOdd == 1 || index < apex -1){ - console.log('hi' + index) - return Math.abs(stepMag * (apex - index)) - } - - else{ - if (index == apex || index == apex -1){ - return 0 + const evenOdd = amCards % 2; + const apex = (amCards - evenOdd) / 2; + const stepMag = 200 / ((amCards - evenOdd) / 2) + Math.abs((apex - index) * 25); + + console.log('steo' + stepMag); + + if (evenOdd == 1 || index < apex - 1) { + console.log('hi' + index); + return Math.abs(stepMag * (apex - index)); + } else { + if (index == apex || index == apex - 1) { + return 0; } - return Math.abs(stepMag * (apex - index -1)) - + return Math.abs(stepMag * (apex - index - 1)); } - }; translateOverFlowY = (amCards: number, index: number) => { - if (amCards>8 && index > amCards/2){ - return 100 - + if (amCards > 8 && index > amCards / 2) { + return 100; } - return 0 - } + return 0; + }; translateSelected = (index: number): number => { if (this.isSelected(index)) { @@ -161,99 +158,100 @@ export class CollectionCardView extends CollectionSubView() { return 0; }; - @computed get sortedDocs() { - const field = StrCast(this.layoutDoc.sortField); + @computed get sortedDocsType() { + // This field is set to 'type' to sort documents by their type + // const typeField = 'type'; + + // Whether to sort in descending order const desc = BoolCast(this.layoutDoc.sortDesc); - const docs = !field - ? this.childDocs - : [...this.childDocs].sort((docA, docB) => { - const aStr = Field.toString(docA[field] as Field); - const bStr = Field.toString(docB[field] as Field); - var out = 0; - if (aStr < bStr) out = -1; - if (aStr > bStr) out = 1; - if (desc) out *= -1; - return out; - }); + + // Copy and sort documents by type + const docs = this.childLayoutPairs.sort((docA, docB) => { + const typeA = docA.layout.type ?? ''; // If docA.type is undefined, use an empty string + const typeB = docB.layout.type ?? ''; // If docB.type is undefined, use an empty string + + // Perform a basic string comparison if types are strings + let out = 0; + if (typeA < typeB) out = -1; + if (typeA > typeB) out = 1; + if (desc) out *= -1; // Reverse the sort order if descending is true + return out; + }); + return { docs }; } @observable docRefs = new ObservableMap(); - // @computed get content() { - // // const currentIndex = NumCast(this.layoutDoc._carousel_index); - // const amCards = this.inactiveDocs().length; - // // const myInactives = - // const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { - // return ( - // r?.ContentDiv && this.docRefs.set(childPair.layout, r))} - // Document={childPair.layout} - // TemplateDataDocument={childPair.data} - // // onClickScript={this.toggleIcon} - // //suppressSetHeight={true} - // NativeWidth={returnZero} - // NativeHeight={returnZero} - // layout_fitWidth={returnFalse} - // onDoubleClickScript={this.onChildDoubleClick} - // renderDepth={this._props.renderDepth + 1} - // LayoutTemplate={this._props.childLayoutTemplate} - // LayoutTemplateString={this._props.childLayoutString} - // // focus={this.focus} - // ScreenToLocalTransform={screenToLocalTransform} //makes sure the box wrapper thing is in the right spot - // isContentActive={this.isChildContentActive} - // isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive} - // PanelWidth={this.panelWidth} - // PanelHeight={this.panelHeight(childPair.layout)} - // /> - // ); - // }; - - // return this.childLayoutPairs.map((childPair, index) => { - // const isSelected = this.isSelected(index); - // const isHovered = this.hoveredNodeIndex === index; - // const isOverflow = amCards > 8 && index > amCards/2 - // const inactiveIndex = this.inactiveDocs().indexOf(childPair.layout); - // // const yOffset = this.verticalOffset(index); - - // const childScreenToLocal = () => { - // const dref = this.docRefs.get(childPair.layout); - // const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv); - // // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off - // return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0); - // }; - - // return ( - //
this.setSelectedNodeIndex(index)} + @computed get contentSorted() { + const sortedDocs = this.sortedDocsType.docs; + const amCards = this.inactiveDocs().length; + + const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { + return ( + r?.ContentDiv && this.docRefs.set(childPair.layout, r))} + Document={childPair.layout} + TemplateDataDocument={childPair.data} + NativeWidth={returnZero} + NativeHeight={returnZero} + layout_fitWidth={returnFalse} + onDoubleClickScript={this.onChildDoubleClick} + renderDepth={this._props.renderDepth + 1} + LayoutTemplate={this._props.childLayoutTemplate} + LayoutTemplateString={this._props.childLayoutString} + ScreenToLocalTransform={screenToLocalTransform} + isContentActive={this.isChildContentActive} + isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive} + PanelWidth={this.panelWidth} + PanelHeight={this.panelHeight(childPair.layout)} + /> + ); + }; + + // Map sorted documents to their rendered components + return sortedDocs.map((childPair, index) => { + // const childPair = { layout: doc, data: doc }; + const isSelected = this.isSelected(index); + const isHovered = this.hoveredNodeIndex === index; + const inactiveIndex = this.sortedDocsType.docs.indexOf(childPair); + + - // onMouseEnter={() => this.setHoveredNodeIndex(index)}> - // {/* {this.lol(childPair.data, index)} */} + const childScreenToLocal = () => { + const dref = this.docRefs.get(childPair.layout); + const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv); + return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0); + }; - // {displayDoc(childPair, childScreenToLocal)} - //
- // ); - // }); - // } + return ( +
this.setHoveredNodeIndex(index)}> + {displayDoc(childPair, childScreenToLocal)} +
+ ); + }); + } - @action content(amCards: number, startIndex: number, stopIndex: number) { + @computed get content() { // const currentIndex = NumCast(this.layoutDoc._carousel_index); - // const amCards = this.inactiveDocs().length; + const amCards = this.inactiveDocs().length; + console.log(amCards + "lol") + const sortedDocs = this.sortedDocsType.docs; // Retrieve sorted documents + // const myInactives = const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { return ( @@ -281,13 +279,11 @@ export class CollectionCardView extends CollectionSubView() { ); }; - const inactiveDocs = this.inactiveDocs(); - return this.childLayoutPairs.filter((childPair, index) => { const inactiveIndex = inactiveDocs.indexOf(childPair.layout); return inactiveIndex >= startIndex && inactiveIndex <= stopIndex; - }).map((childPair, index) => { - + return this.childLayoutPairs.map((childPair, index) => { const isSelected = this.isSelected(index); const isHovered = this.hoveredNodeIndex === index; - const isOverflow = amCards > 8 && index > amCards/2 + const isOverflow = amCards > 8 && index > amCards / 2; + // const inactiveIndex = this.sortedDocsType.docs.indexOf(childPair); const inactiveIndex = this.inactiveDocs().indexOf(childPair.layout); // const yOffset = this.verticalOffset(index); @@ -307,11 +303,8 @@ export class CollectionCardView extends CollectionSubView() { height: this.panelHeight(childPair.layout)(), transform: ` rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg) - translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, inactiveIndex) - // + this.translateOverFlowY(amCards, inactiveIndex) - }px) + translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, inactiveIndex)}px) translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth : 0}px) - scale(${isSelected ? 1.25 : 1}) `, //scale has to be applied last or selected offset gets messed up @@ -327,35 +320,9 @@ export class CollectionCardView extends CollectionSubView() { }); } - renderRows() { - const cards = this.inactiveDocs(); - const totalCards = cards.length; - const rowsNeeded = Math.ceil(totalCards / 8); - - let rows = []; - - for (let rowIndex = 0; rowIndex < rowsNeeded; rowIndex++) { - let rowStartIndex = rowIndex * 8; - let rowEndIndex = rowStartIndex + 8; - let rowCards = cards.slice(rowStartIndex, rowEndIndex); - - rows.push(this.renderRowCards(rowCards, rowIndex)); - } - - return rows; - } - - renderRowCards(rowCards: Doc[], rowIndex: number) { - return ( -
- {this.content(rowCards.length, rowIndex*8, rowIndex*8+8)} -
- ); - } - @computed get translateWrapperX() { if (this.inactiveDocs().length != this.childLayoutPairs.length) { - return this.panelWidth()/2; + return this.panelWidth() / 2; } return 0; @@ -378,9 +345,21 @@ export class CollectionCardView extends CollectionSubView() { height: `${100 * this.fitContentScale}%`, }} onMouseLeave={() => this.setHoveredNodeIndex(-1)}> - {this.renderRows()} + {this.contentSorted}
+ {/* + + {header} + + + + + */} + {/* {this.focusContent} */}
); -- cgit v1.2.3-70-g09d2 From 8ca77556c3a9caba66faf37fbf259762c2084c0b Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Tue, 7 May 2024 17:28:21 -0400 Subject: hm --- src/client/documents/Documents.ts | 6 +++ src/client/util/CurrentUserUtils.ts | 10 +++++ src/client/views/MainView.tsx | 2 + .../views/collections/CollectionCardDeckView.tsx | 42 ++++++++++++----- src/client/views/global/globalScripts.ts | 52 +++++++++++++++++++++- 5 files changed, 100 insertions(+), 12 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index c453fd793..b4aa1c90c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -495,6 +495,12 @@ export class DocumentOptions { hoverBackgroundColor?: string; // background color of a label when hovered userBackgroundColor?: STRt = new StrInfo('background color associated with a Dash user (seen in header fields of shared documents)'); userColor?: STRt = new StrInfo('color associated with a Dash user (seen in header fields of shared documents)'); + + card_sort_time?: BOOLt = new BoolInfo('whether sorting cards in deck view by time'); + card_sort_type?: BOOLt = new BoolInfo('whether sorting cards in deck view by type'); + card_sort_color?: BOOLt = new BoolInfo('whether sorting cards in deck view by color'); + + } export const DocOptions = new DocumentOptions(); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 15c3ddad6..cb10f0658 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -719,6 +719,14 @@ pie title Minerals in my tap water { 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 ] } + static cardTools(): Button[] { + return [ + { title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ClickButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ClickButton, expertMode: false, toolType:"docType", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ClickButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + + ] + } static viewTools(): Button[] { return [ { title: "Snap", icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform @@ -727,6 +735,7 @@ pie title Minerals in my tap water { title: "Clusters", icon: "braille", toolTip: "Show Doc Clusters", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"clusters", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform { title: "Cards", icon: "brain", toolTip: "Flashcards", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"flashcards", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform { title: "Arrange", icon:"arrow-down-short-wide",toolTip:"Toggle Auto Arrange", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"arrange", funcs: {hidden: 'IsNoviceMode()'}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform + ] } static textTools():Button[] { @@ -811,6 +820,7 @@ 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: `!SelectionManager_selectedDocType(this.toolType, this.expertMode, true)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Stack", icon: "View", toolTip: "Stacking tools", subMenu: CurrentUserUtils.stackTools(), expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available + { title: "Card", icon: "Sort", toolTip: "Card sort", subMenu: CurrentUserUtils.cardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_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: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected { title: "Schema", icon: "Schema",linearBtnWidth:58,toolTip: "Schema functions",subMenu: CurrentUserUtils.schemaTools(),expertMode: false,toolType:CollectionViewType.Schema,funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Only when Schema is selected diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 56d28ee5d..e6ae57911 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -526,6 +526,8 @@ export class MainView extends ObservableReactComponent<{}> { fa.faZ, fa.faArrowsUpToLine, fa.faArrowsDownToLine, + fa.faPalette, + fa.faHourglassHalf ] ); } diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index d0a796218..ab7aac267 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -159,14 +159,18 @@ export class CollectionCardView extends CollectionSubView() { }; @computed get sortedDocsType() { - // This field is set to 'type' to sort documents by their type - // const typeField = 'type'; - - // Whether to sort in descending order + const desc = BoolCast(this.layoutDoc.sortDesc); + let sorted = [] + + for (let i=0; i< this.childLayoutPairs.length; i++){ //copying everything in childlayout pairs to sorted so that i can use the sort function without altering the original list + sorted[i] = this.childLayoutPairs[i] + } + + // Copy and sort documents by type - const docs = this.childLayoutPairs.sort((docA, docB) => { + const docs = sorted.sort((docA, docB) => { const typeA = docA.layout.type ?? ''; // If docA.type is undefined, use an empty string const typeB = docB.layout.type ?? ''; // If docB.type is undefined, use an empty string @@ -177,10 +181,15 @@ export class CollectionCardView extends CollectionSubView() { if (desc) out *= -1; // Reverse the sort order if descending is true return out; }); + return { docs }; } + + + + @observable docRefs = new ObservableMap(); @computed get contentSorted() { @@ -213,9 +222,10 @@ export class CollectionCardView extends CollectionSubView() { // Map sorted documents to their rendered components return sortedDocs.map((childPair, index) => { // const childPair = { layout: doc, data: doc }; - const isSelected = this.isSelected(index); const isHovered = this.hoveredNodeIndex === index; - const inactiveIndex = this.sortedDocsType.docs.indexOf(childPair); + const inactiveIndex = this.sortedDocsType.docs.filter(d => !SelectionManager.IsSelected(d.layout)).indexOf(childPair); + const isSelected = SelectionManager.IsSelected(childPair.layout); + @@ -234,7 +244,7 @@ export class CollectionCardView extends CollectionSubView() { height: this.panelHeight(childPair.layout)(), transform: ` rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg) - translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, inactiveIndex)}px) + translateY(${isHovered ? this.translateHover(inactiveIndex) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, inactiveIndex)}px) translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth : 0}px) scale(${isSelected ? 1.25 : 1}) `, @@ -250,7 +260,7 @@ export class CollectionCardView extends CollectionSubView() { // const currentIndex = NumCast(this.layoutDoc._carousel_index); const amCards = this.inactiveDocs().length; console.log(amCards + "lol") - const sortedDocs = this.sortedDocsType.docs; // Retrieve sorted documents + // const sortedDocs = this.sortedDocsType.docs; // Retrieve sorted documents // const myInactives = const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { @@ -328,6 +338,18 @@ export class CollectionCardView extends CollectionSubView() { return 0; } + @computed get renderCardsSort(){ + if (BoolCast(this._props.Document.card_sort_type) == true){ + return this.contentSorted + } + + else{ + return this.content + } + } + + + render() { return (
this.setHoveredNodeIndex(-1)}> - {this.contentSorted} + {this.renderCardsSort}
{/* diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 3fdc9a488..ffb1d751d 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -102,10 +102,10 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { selected ? selected.CollectionFreeFormDocumentView?.float() : console.log('[FontIconBox.tsx] toggleOverlay failed'); }); -ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce', checkResult?: boolean, persist?: boolean) { +ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color', checkResult?: boolean, persist?: boolean) { const selected = SelectionManager.Docs.lastElement(); // prettier-ignore - const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([ + const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color', { 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,dv:DocumentView) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid, @@ -135,6 +135,19 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid 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), + setDoc: (doc:Doc,dv:DocumentView) => doc.card_sort_time = !doc.card_sort_time, + }], + ['docType', { + checkResult: (doc:Doc) => StrCast(doc?.cardSort), + setDoc: (doc:Doc,dv:DocumentView) => doc.card_sort_type = !doc.card_sort_type, + }], + ['color', { + checkResult: (doc:Doc) => StrCast(doc?.cardSort), + setDoc: (doc:Doc,dv:DocumentView) => doc.card_sort_color = !doc.card_sort_color, + }], + ]); if (checkResult) { @@ -145,6 +158,39 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid setTimeout(() => batch.end(), 100); }); +// 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') +// }); + ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize' | 'alignment', value: any, checkResult?: boolean) { const editorView = RichTextMenu.Instance?.TextView?.EditorView; const selected = SelectionManager.Docs.lastElement(); @@ -182,6 +228,8 @@ ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highligh map.get(attr)?.setDoc?.(); }); + + type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'elide' | 'underline' | 'left' | 'center' | 'right' | 'vcent' | 'bullet' | 'decimal'; type attrfuncs = [attrname, { checkResult: () => boolean; toggle: () => any }]; -- cgit v1.2.3-70-g09d2 From 4429a0565888d9118e37f1e58dec300220831661 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Sat, 11 May 2024 22:30:39 -0400 Subject: transformations are being unbelieveably silly rn --- src/client/documents/Documents.ts | 7 +- src/client/util/CurrentUserUtils.ts | 8 +- .../views/collections/CollectionCardDeckView.scss | 31 +- .../views/collections/CollectionCardDeckView.tsx | 417 ++++++++++++++------- src/client/views/global/globalScripts.ts | 15 +- 5 files changed, 316 insertions(+), 162 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1c57c5d63..77cc5f51e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -499,9 +499,10 @@ export class DocumentOptions { userBackgroundColor?: STRt = new StrInfo('background color associated with a Dash user (seen in header fields of shared documents)'); userColor?: STRt = new StrInfo('color associated with a Dash user (seen in header fields of shared documents)'); - card_sort_time?: BOOLt = new BoolInfo('whether sorting cards in deck view by time'); - card_sort_type?: BOOLt = new BoolInfo('whether sorting cards in deck view by type'); - card_sort_color?: BOOLt = new BoolInfo('whether sorting cards in deck view by color'); + cardSort?: STRt = new StrInfo('way cards are sorted in deck view'); + // card_sort_time?: BOOLt = new BoolInfo('whether sorting cards in deck view by time'); + // card_sort_type?: BOOLt = new BoolInfo('whether sorting cards in deck view by type'); + // card_sort_color?: BOOLt = new BoolInfo('whether sorting cards in deck view by color'); } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 88fcf098b..767d6c635 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -713,9 +713,11 @@ 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.ClickButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ClickButton, expertMode: false, toolType:"docType", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ClickButton, 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: "Links", icon:"link", toolTip:"Sort by its links", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"links", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + ] } diff --git a/src/client/views/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss index ff9c0a569..aafc3b556 100644 --- a/src/client/views/collections/CollectionCardDeckView.scss +++ b/src/client/views/collections/CollectionCardDeckView.scss @@ -2,26 +2,43 @@ .collectionCardView-outer { height: 100%; + width: 100%; position: relative; background-color: white; overflow: hidden; } .card-wrapper { - display: flex; + display: grid; + grid-template-columns: repeat(10, 1fr); /* Creates 10 columns, adjust number as needed */ + // width: 100%; + position: absolute; align-items: center; + justify-items: center; + justify-content: center; + transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); } -.card-row{ - display: flex; - position: absolute; - align-items: center; - transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); +// .card-wrapper::after { +// content: ""; +// width: 100%; /* Forces wrapping */ +// } +// .card-wrapper > .card-item:nth-child(10n)::after { +// content: ""; +// width: 100%; /* Forces wrapping after every 10th item */ +// } -} +// .card-row{ +// display: flex; +// position: absolute; +// align-items: center; +// transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); + + +// } .card-item-active, .card-item { diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index ab7aac267..bda72b2d6 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import { Utils, returnFalse, returnTrue, returnZero } from '../../../Utils'; import { Doc, DocListCast, Field } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; -import { NumCast, ScriptCast, StrCast, BoolCast } from '../../../fields/Types'; +import { NumCast, ScriptCast, StrCast, BoolCast, DocCast } from '../../../fields/Types'; import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { StyleProp } from '../StyleProvider'; @@ -12,7 +12,10 @@ import { DocumentView } from '../nodes/DocumentView'; import './CollectionCardDeckView.scss'; import { CollectionSubView } from './CollectionSubView'; import { Transform } from '../../util/Transform'; +import { LinkManager } from '../../util/LinkManager'; // import Card from 'react-bootstrap/Card'; +import { DocumentType } from '../../documents/DocumentTypes'; +import { forEach } from 'lodash'; @observer @@ -21,6 +24,10 @@ export class CollectionCardView extends CollectionSubView() { @observable hoveredNodeIndex = -1; + @computed get myChildLayoutPairs(){ + return this.childLayoutPairs.filter(l => l.layout.type != DocumentType.LINK) + } + @action setHoveredNodeIndex = (index: number) => { if (!this.isSelected(index)) { @@ -38,10 +45,10 @@ export class CollectionCardView extends CollectionSubView() { @action setSelectedNodeIndex = (index: number) => { const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); - console.log('goodnight'); + // console.log('goodnight'); if (SelectionManager.IsSelected(docs[index])) { - console.log('good mornings'); + // console.log('good mornings'); this.setSelectedNodeIndex(index); } }; @@ -53,12 +60,11 @@ export class CollectionCardView extends CollectionSubView() { }; inactiveDocs = () => { - const docs = DocListCast(this.Document[this.fieldKey ?? Doc.LayoutFieldKey(this.Document)]); - + const docs = this.myChildLayoutPairs; + return docs.filter(d => !SelectionManager.IsSelected(d.layout)); + }; - return docs.filter(d => !SelectionManager.IsSelected(d)); - }; middleIndex = Math.floor(this.inactiveDocs().length / 2); @@ -81,12 +87,21 @@ export class CollectionCardView extends CollectionSubView() { } }; + + childDocumentWidth = 600; // target width of a Doc... /** * how much to scale down the contents of the view so that everything will fit */ @computed get fitContentScale() { - return (this.childDocumentWidth * this.childLayoutPairs.length) / this._props.PanelWidth(); + if (this.myChildLayoutPairs.length< this.maxRowCount){ + length = this.myChildLayoutPairs.length + } + + else{ + length = this.maxRowCount + } + return (this.childDocumentWidth * length) / this._props.PanelWidth(); } panelWidth = () => this.childDocumentWidth; panelHeight = (layout: Doc) => () => (2 * (this.panelWidth() * NumCast(layout._height))) / NumCast(layout._width); @@ -95,7 +110,7 @@ export class CollectionCardView extends CollectionSubView() { isChildContentActive = () => (this.isContentActive() ? true : false); rotate = (amCards: number, index: number) => { - console.log(amCards + "wtf") + // console.log(amCards + "wtf") const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2)); const stepMag = Math.abs(-30 + (amCards / 2 - 1) * (30 / ((amCards - (amCards % 2)) / 2))); @@ -113,31 +128,39 @@ export class CollectionCardView extends CollectionSubView() { return possRotate; }; - translateY = (amCards: number, index: number) => { + translateY = (amCards: number, index: number, realIndex: number) => { const evenOdd = amCards % 2; const apex = (amCards - evenOdd) / 2; const stepMag = 200 / ((amCards - evenOdd) / 2) + Math.abs((apex - index) * 25); + let rowOffset = 0 - console.log('steo' + stepMag); + if (realIndex > this.maxRowCount -1){ + // 11 - 1 = 10 + rowOffset = 400 * ((realIndex - (realIndex % this.maxRowCount)) / this.maxRowCount) + } + + + + // console.log('steo' + stepMag); if (evenOdd == 1 || index < apex - 1) { - console.log('hi' + index); - return Math.abs(stepMag * (apex - index)); + // console.log('hi' + index); + return Math.abs(stepMag * (apex - index)) - rowOffset; } else { if (index == apex || index == apex - 1) { - return 0; + return 0 - rowOffset; } - return Math.abs(stepMag * (apex - index - 1)); + return Math.abs(stepMag * (apex - index - 1)) - rowOffset; } }; - translateOverFlowY = (amCards: number, index: number) => { - if (amCards > 8 && index > amCards / 2) { - return 100; - } - return 0; - }; + // translateOverFlowY = (amCards: number, index: number) => { + // if (amCards > 8 && index > amCards / 2) { + // return 100; + // } + // return 0; + // }; translateSelected = (index: number): number => { if (this.isSelected(index)) { @@ -161,78 +184,190 @@ export class CollectionCardView extends CollectionSubView() { @computed get sortedDocsType() { const desc = BoolCast(this.layoutDoc.sortDesc); - let sorted = [] + let docs = [] - for (let i=0; i< this.childLayoutPairs.length; i++){ //copying everything in childlayout pairs to sorted so that i can use the sort function without altering the original list - sorted[i] = this.childLayoutPairs[i] + for (let i=0; i< this.myChildLayoutPairs.length; i++){ //copying everything in childlayout pairs to sorted so that i can use the sort function without altering the original list + sorted[i] = this.myChildLayoutPairs[i] } + switch(this._props.Document.cardSort){ + case "type": + // Copy and sort documents by type + return this.sort(sorted, "type", desc) + case "color": + return this.sort(sorted, "color", desc) + case "links": + console.log("hi") + + let links = LinkManager.Instance.getAllRelatedLinks(this.myChildLayoutPairs[0].layout) + + console.log(links) + + // } - // Copy and sort documents by type - const docs = sorted.sort((docA, docB) => { - const typeA = docA.layout.type ?? ''; // If docA.type is undefined, use an empty string - const typeB = docB.layout.type ?? ''; // If docB.type is undefined, use an empty string + default: + docs = this.myChildLayoutPairs + return {docs} + + + + } + } + + + + + hexToHsv = (hex: string): [number, number, number] => { + if (!hex) return [0, 0, 0]; // Default to black if hex is not defined + const r = parseInt(hex.slice(1, 3), 16) / 255; + const g = parseInt(hex.slice(3, 5), 16) / 255; + const b = parseInt(hex.slice(5, 7), 16) / 255; + const max = Math.max(r, g, b), min = Math.min(r, g, b); + const d = max - min; + let h: number; + const s = (max === 0 ? 0 : d / max); + const v = max; + + switch (max) { + case min: h = 0; break; + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + default: h = 0; break; + } + h /= 6; + return [h, s, v]; + }; + + + + sort = (docs: {layout: Doc; data: Doc; }[], sortType: string, isDesc: boolean) => { + + docs.sort((docA, docB) => { + let typeA; + let typeB + + switch(sortType) { + case "color": + typeA = this.hexToHsv(StrCast(docA.layout.backgroundColor)) ?? ''; // If docA.type is undefined, use an empty string + typeB = this.hexToHsv(StrCast(docB.layout.backgroundColor)) ?? ''; // If docB.type is undefined, use an empty string + break + + default: + typeA = docA.layout.type ?? ''; // If docA.type is undefined, use an empty string + typeB = docB.layout.type ?? ''; // If docB.type is undefined, use an empty string + break + } + // Perform a basic string comparison if types are strings let out = 0; if (typeA < typeB) out = -1; if (typeA > typeB) out = 1; - if (desc) out *= -1; // Reverse the sort order if descending is true + if (isDesc) out *= -1; // Reverse the sort order if descending is true return out; - }); - + }); - return { docs }; + return {docs} } + // @computed get cards(){ + + + // } + + + displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { + return ( + r?.ContentDiv && this.docRefs.set(childPair.layout, r))} + Document={childPair.layout} + TemplateDataDocument={childPair.data} + // onClickScript={this.toggleIcon} + //suppressSetHeight={true} + NativeWidth={returnZero} + NativeHeight={returnZero} + layout_fitWidth={returnFalse} + onDoubleClickScript={this.onChildDoubleClick} + renderDepth={this._props.renderDepth + 1} + LayoutTemplate={this._props.childLayoutTemplate} + LayoutTemplateString={this._props.childLayoutString} + // focus={this.focus} + ScreenToLocalTransform={screenToLocalTransform} //makes sure the box wrapper thing is in the right spot + isContentActive={this.isChildContentActive} + isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive} + PanelWidth={this.panelWidth} + PanelHeight={this.panelHeight(childPair.layout)} + /> + ); + }; @observable docRefs = new ObservableMap(); + @observable maxRowCount = 10; + + overflowAmCardsCalc(index: number) { + if (this.inactiveDocs().length < this.maxRowCount){ + return this.inactiveDocs().length + } + // 13 - 3 = 10 + const totalCards = this.inactiveDocs().length + // if 9 or less + if ( index < ((totalCards - (totalCards % 10)))){ + return this.maxRowCount + } + //(3) + return totalCards % 10 + + } + + overflowIndexCalc(realIndex: number) { + if (realIndex < 10){ + return realIndex + } + + return realIndex % 10 + + } + + translateOverflowX(realIndex: number, calcRowCards: number){ + if (realIndex < this.maxRowCount){ + return 0 + } + + return (10 - calcRowCards) * (this.panelWidth()/2) + + + + + } + @computed get contentSorted() { const sortedDocs = this.sortedDocsType.docs; - const amCards = this.inactiveDocs().length; - - const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { - return ( - r?.ContentDiv && this.docRefs.set(childPair.layout, r))} - Document={childPair.layout} - TemplateDataDocument={childPair.data} - NativeWidth={returnZero} - NativeHeight={returnZero} - layout_fitWidth={returnFalse} - onDoubleClickScript={this.onChildDoubleClick} - renderDepth={this._props.renderDepth + 1} - LayoutTemplate={this._props.childLayoutTemplate} - LayoutTemplateString={this._props.childLayoutString} - ScreenToLocalTransform={screenToLocalTransform} - isContentActive={this.isChildContentActive} - isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive} - PanelWidth={this.panelWidth} - PanelHeight={this.panelHeight(childPair.layout)} - /> - ); - }; + // const amCards = this.inactiveDocs().length; // Map sorted documents to their rendered components return sortedDocs.map((childPair, index) => { // const childPair = { layout: doc, data: doc }; - const isHovered = this.hoveredNodeIndex === index; - const inactiveIndex = this.sortedDocsType.docs.filter(d => !SelectionManager.IsSelected(d.layout)).indexOf(childPair); - const isSelected = SelectionManager.IsSelected(childPair.layout); + const isHovered = this.hoveredNodeIndex === index; + const realIndex = this.sortedDocsType.docs.filter(d => !SelectionManager.IsSelected(d.layout)).indexOf(childPair); + const calcRowIndex = this.overflowIndexCalc(realIndex) + + const amCards = this.overflowAmCardsCalc(realIndex) + const isSelected = SelectionManager.IsSelected(childPair.layout); const childScreenToLocal = () => { const dref = this.docRefs.get(childPair.layout); const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv); - return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0); + return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, calcRowIndex) : 0); }; return ( @@ -243,111 +378,105 @@ export class CollectionCardView extends CollectionSubView() { width: this.panelWidth(), height: this.panelHeight(childPair.layout)(), transform: ` - rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg) - translateY(${isHovered ? this.translateHover(inactiveIndex) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, inactiveIndex)}px) - translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth : 0}px) + rotate(${!isSelected ? this.rotate(amCards, calcRowIndex) : 0}deg) + translateY(${isHovered ? this.translateHover(realIndex) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, calcRowIndex, realIndex)}px) + translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth : this.translateOverflowX(realIndex, amCards)}px) scale(${isSelected ? 1.25 : 1}) `, }} onMouseEnter={() => this.setHoveredNodeIndex(index)}> - {displayDoc(childPair, childScreenToLocal)} + {this.displayDoc(childPair, childScreenToLocal)} + + {/* */} +
); }); } - @computed get content() { - // const currentIndex = NumCast(this.layoutDoc._carousel_index); - const amCards = this.inactiveDocs().length; - console.log(amCards + "lol") - // const sortedDocs = this.sortedDocsType.docs; // Retrieve sorted documents - - // const myInactives = - const displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { - return ( - r?.ContentDiv && this.docRefs.set(childPair.layout, r))} - Document={childPair.layout} - TemplateDataDocument={childPair.data} - // onClickScript={this.toggleIcon} - //suppressSetHeight={true} - NativeWidth={returnZero} - NativeHeight={returnZero} - layout_fitWidth={returnFalse} - onDoubleClickScript={this.onChildDoubleClick} - renderDepth={this._props.renderDepth + 1} - LayoutTemplate={this._props.childLayoutTemplate} - LayoutTemplateString={this._props.childLayoutString} - // focus={this.focus} - ScreenToLocalTransform={screenToLocalTransform} //makes sure the box wrapper thing is in the right spot - isContentActive={this.isChildContentActive} - isDocumentActive={this._props.childDocumentsActive?.() || this.Document._childDocumentsActive ? this._props.isDocumentActive : this.isContentActive} - PanelWidth={this.panelWidth} - PanelHeight={this.panelHeight(childPair.layout)} - /> - ); - }; + - return this.childLayoutPairs.map((childPair, index) => { - const isSelected = this.isSelected(index); - const isHovered = this.hoveredNodeIndex === index; - const isOverflow = amCards > 8 && index > amCards / 2; - // const inactiveIndex = this.sortedDocsType.docs.indexOf(childPair); - const inactiveIndex = this.inactiveDocs().indexOf(childPair.layout); - // const yOffset = this.verticalOffset(index); + // @computed get content() { + // // const currentIndex = NumCast(this.layoutDoc._carousel_index); + // const amCards = this.inactiveDocs().length; + // console.log(amCards + "lol") + // // const sortedDocs = this.sortedDocsType.docs; // Retrieve sorted documents - const childScreenToLocal = () => { - const dref = this.docRefs.get(childPair.layout); - const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv); - // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off - return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0); - }; + // // const myInactives = + - return ( -
{ + // const isSelected = this.isSelected(index); + // const isHovered = this.hoveredNodeIndex === index; + // const isOverflow = amCards > 8 && index > amCards / 2; + // // const inactiveIndex = this.sortedDocsType.docs.indexOf(childPair); + // const inactiveIndex = this.inactiveDocs().indexOf(childPair.layout); + // // const yOffset = this.verticalOffset(index); + + // const childScreenToLocal = () => { + // const dref = this.docRefs.get(childPair.layout); + // const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv); + // // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off + // return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0); + // }; + + // return ( + //
this.setSelectedNodeIndex(index)} + // `, //scale has to be applied last or selected offset gets messed up + // }} + // // onClick={() => this.setSelectedNodeIndex(index)} - onMouseEnter={() => this.setHoveredNodeIndex(index)}> - {/* {this.lol(childPair.data, index)} */} + // onMouseEnter={() => this.setHoveredNodeIndex(index)}> + // {/* {this.lol(childPair.data, index)} */} - {displayDoc(childPair, childScreenToLocal)} -
- ); - }); - } + // {this.displayDoc(childPair, childScreenToLocal)} + //
+ // ); + // }); + // } @computed get translateWrapperX() { - if (this.inactiveDocs().length != this.childLayoutPairs.length) { - return this.panelWidth() / 2; - } - return 0; - } + let translate = 0 - @computed get renderCardsSort(){ - if (BoolCast(this._props.Document.card_sort_type) == true){ - return this.contentSorted + if (this.inactiveDocs().length != this.myChildLayoutPairs.length) { + translate += this.panelWidth() / 2; } - else{ - return this.content - } + console.log("in" + this.inactiveDocs().length) + console.log("max" + this.maxRowCount) + + // if (this.inactiveDocs().length > this.maxRowCount){ + // translate += ((this.inactiveDocs().length % this.maxRowCount) * this.panelWidth()) / 2 + // console.log("trans" + (this.inactiveDocs().length % this.maxRowCount) / 2 ) + // } + + + + return translate; } + // @computed get renderCardsSort(){ + // if (StrCast(this._props.Document.cardSort) == "type"){ + // return this.contentSorted + // } + + // else{ + // return this.content + // } + // } + render() { @@ -367,7 +496,7 @@ export class CollectionCardView extends CollectionSubView() { height: `${100 * this.fitContentScale}%`, }} onMouseLeave={() => this.setHoveredNodeIndex(-1)}> - {this.renderCardsSort} + {this.contentSorted}
{/* @@ -386,4 +515,4 @@ export class CollectionCardView extends CollectionSubView() {
); } -} +} \ No newline at end of file diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 0c6095346..526315802 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -105,10 +105,10 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { selected ? selected.CollectionFreeFormDocumentView?.float() : console.log('[FontIconBox.tsx] toggleOverlay failed'); }); -ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color', checkResult?: boolean, persist?: boolean) { +ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links', checkResult?: boolean, persist?: boolean) { const selected = SelectionManager.Docs.lastElement(); // prettier-ignore - const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([ + const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links', { 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,dv:DocumentView) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid, @@ -140,15 +140,20 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid }], ['time', { checkResult: (doc:Doc) => StrCast(doc?.cardSort), - setDoc: (doc:Doc,dv:DocumentView) => doc.card_sort_time = !doc.card_sort_time, + setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "time", }], ['docType', { checkResult: (doc:Doc) => StrCast(doc?.cardSort), - setDoc: (doc:Doc,dv:DocumentView) => doc.card_sort_type = !doc.card_sort_type, + setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "type", }], ['color', { checkResult: (doc:Doc) => StrCast(doc?.cardSort), - setDoc: (doc:Doc,dv:DocumentView) => doc.card_sort_color = !doc.card_sort_color, + setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "color", + }], + + ['links', { + checkResult: (doc:Doc) => StrCast(doc?.cardSort), + setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "links", }], ]); -- cgit v1.2.3-70-g09d2 From 13b4aa868ac664399bfd320902f3ddee57072392 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Mon, 13 May 2024 09:21:29 -0400 Subject: create technically working --- src/client/documents/Documents.ts | 1 + src/client/util/CurrentUserUtils.ts | 18 +++- src/client/util/SelectionManager.ts | 1 + src/client/views/MainView.tsx | 3 +- .../views/collections/CollectionCardDeckView.scss | 27 ++++- .../views/collections/CollectionCardDeckView.tsx | 111 ++++++++++++++++++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/global/globalScripts.ts | 21 +++- 8 files changed, 163 insertions(+), 21 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 77cc5f51e..df69e215a 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -500,6 +500,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'); + customSortCount?: NUMt = new NumInfo('number of custom sorts the user has created'); // card_sort_time?: BOOLt = new BoolInfo('whether sorting cards in deck view by time'); // card_sort_type?: BOOLt = new BoolInfo('whether sorting cards in deck view by type'); // card_sort_color?: BOOLt = new BoolInfo('whether sorting cards in deck view by color'); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 767d6c635..59560dd78 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -9,7 +9,7 @@ import { PrefetchProxy } from "../../fields/Proxy"; import { RichTextField } from "../../fields/RichTextField"; import { listSpec } from "../../fields/Schema"; import { ScriptField } from "../../fields/ScriptField"; -import { Cast, DateCast, DocCast, StrCast } from "../../fields/Types"; +import { Cast, DateCast, DocCast, StrCast, NumCast } from "../../fields/Types"; import { WebField, nullAudio } from "../../fields/URLField"; import { SetCachedGroups, SharingPermissions } from "../../fields/util"; import { GestureUtils } from "../../pen-gestures/GestureUtils"; @@ -34,6 +34,9 @@ import { SnappingManager } from "./SnappingManager"; import { UndoManager } from "./UndoManager"; import { LabelBox } from "../views/nodes/LabelBox"; import { ImageBox } from "../views/nodes/ImageBox"; +import { CollectionFreeFormView } from "../views/collections/collectionFreeForm"; +import { CollectionCardView } from "../views/collections/CollectionCardDeckView"; +import { SelectionManager } from "./SelectionManager"; interface Button { // DocumentOptions fields a button can set @@ -712,12 +715,23 @@ pie title Minerals in my tap water ] } static cardTools(): Button[] { + + + // if (view != undefined){ + // for (let i=0; i< NumCast(view.layoutDoc.customSortCount); i++){ + // customs.push( + // { title: "Custom " + i, icon:"robot", toolTip:"Custom sort option " + i, btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}} + // ) + + // } + // } 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: "Links", icon:"link", toolTip:"Sort by its links", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"links", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - + { title: "Create", icon:"plus", toolTip:"Create new custom groupings!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // ...customs ] } diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 36b926053..d507e35ad 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -68,6 +68,7 @@ export class SelectionManager { public static IsSelected = (doc?: Doc) => Array.from(doc?.[DocViews] ?? []).some(dv => dv?.IsSelected); public static get Views() { return this.Instance.SelectedViews; } // prettier-ignore public static get SelectedSchemaDoc() { return this.Instance.SelectedSchemaDocument; } // prettier-ignore + public static get Docs() { return this.Instance.SelectedViews.map(dv => dv.Document).filter(doc => doc?._type_collection !== CollectionViewType.Docking); } // prettier-ignore } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index abdb5abef..a5882dcf3 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -526,7 +526,8 @@ export class MainView extends ObservableReactComponent<{}> { fa.faArrowsUpToLine, fa.faArrowsDownToLine, fa.faPalette, - fa.faHourglassHalf + fa.faHourglassHalf, + fa.faRobot ] ); } diff --git a/src/client/views/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss index aafc3b556..222a1d226 100644 --- a/src/client/views/collections/CollectionCardDeckView.scss +++ b/src/client/views/collections/CollectionCardDeckView.scss @@ -10,7 +10,7 @@ .card-wrapper { display: grid; - grid-template-columns: repeat(10, 1fr); /* Creates 10 columns, adjust number as needed */ + grid-template-columns: repeat(10, 1fr); // width: 100%; position: absolute; @@ -21,6 +21,31 @@ transition: transform 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955); } +.card-button-container { + display: flex; + padding: 3px; + // width: 300px; + background-color: rgb(218, 218, 218); /* Background color of the container */ + border-radius: 50px; /* Rounds the corners of the container */ + transform: translateY(-50px); + // 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 { + width: 35px; + height: 35px; + border-radius: 50%; + background-color: $dark-gray; + // border-color: $medium-blue; + margin: 5px; // transform: translateY(-50px); +} + +// button:hover { +// transform: translateY(-50px); +// } + // .card-wrapper::after { // content: ""; // width: 100%; /* Forces wrapping */ diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index bda72b2d6..bf26ad4b5 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -37,7 +37,7 @@ export class CollectionCardView extends CollectionSubView() { translateHover = (index: number): number => { if (this.hoveredNodeIndex == index && !this.isSelected(index)) { - return -50 * this.fitContentScale; + return -50; } return 0; }; @@ -109,6 +109,10 @@ export class CollectionCardView extends CollectionSubView() { isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive(); isChildContentActive = () => (this.isContentActive() ? true : false); + + + + rotate = (amCards: number, index: number) => { // console.log(amCards + "wtf") const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2)); @@ -163,7 +167,7 @@ export class CollectionCardView extends CollectionSubView() { // }; translateSelected = (index: number): number => { - if (this.isSelected(index)) { + // if (this.isSelected(index)) { const middleOfPanel = this._props.PanelWidth() / 2; const scaledNodeWidth = this.panelWidth() * 1.25; @@ -173,12 +177,12 @@ export class CollectionCardView extends CollectionSubView() { const scaledNodeCenter = nodeLeftEdge + scaledNodeWidth / 2; // Calculate the translation needed to align the scaled node's center with the panel's center - const translation = middleOfPanel - scaledNodeCenter; + const translation = middleOfPanel - scaledNodeCenter - scaledNodeWidth - (scaledNodeWidth /4); return translation; - } + // } - return 0; + // return 0; }; @computed get sortedDocsType() { @@ -197,15 +201,20 @@ export class CollectionCardView extends CollectionSubView() { return this.sort(sorted, "type", desc) case "color": return this.sort(sorted, "color", desc) - case "links": - console.log("hi") + // case "links": + // console.log("hi") - let links = LinkManager.Instance.getAllRelatedLinks(this.myChildLayoutPairs[0].layout) + // let links = LinkManager.Instance.getAllRelatedLinks(this.myChildLayoutPairs[0].layout) - console.log(links) + // console.log(links) // } + case "custom": + console.log("hiiiii") + return this.sort(sorted, "custom", desc) + + default: docs = this.myChildLayoutPairs return {docs} @@ -254,6 +263,14 @@ export class CollectionCardView extends CollectionSubView() { typeB = this.hexToHsv(StrCast(docB.layout.backgroundColor)) ?? ''; // If docB.type is undefined, use an empty string break + case "custom": + typeA = this.customGroupDictionary.get(docs.indexOf(docA)) ?? '' + // console.log(typeA + "A") + typeB = this.customGroupDictionary.get(docs.indexOf(docB)) ?? '' + // console.log(typeB + 'b') + break + + default: typeA = docA.layout.type ?? ''; // If docA.type is undefined, use an empty string typeB = docB.layout.type ?? ''; // If docB.type is undefined, use an empty string @@ -341,10 +358,24 @@ export class CollectionCardView extends CollectionSubView() { } return (10 - calcRowCards) * (this.panelWidth()/2) + } + + calculateTranslateY(isHovered: boolean, isSelected: boolean, realIndex: number, amCards: number, calcRowIndex: number) { + let trans = 0; + if (isHovered) { + trans += this.translateHover(realIndex); + } + + trans += this.translateY(amCards, calcRowIndex, realIndex); + + if (isSelected) { + trans = 50 * this.fitContentScale; + } + return trans } @computed get contentSorted() { @@ -357,6 +388,7 @@ export class CollectionCardView extends CollectionSubView() { const isHovered = this.hoveredNodeIndex === index; + const childPairIndex = this.myChildLayoutPairs.indexOf(childPair) const realIndex = this.sortedDocsType.docs.filter(d => !SelectionManager.IsSelected(d.layout)).indexOf(childPair); const calcRowIndex = this.overflowIndexCalc(realIndex) @@ -379,21 +411,72 @@ export class CollectionCardView extends CollectionSubView() { height: this.panelHeight(childPair.layout)(), transform: ` rotate(${!isSelected ? this.rotate(amCards, calcRowIndex) : 0}deg) - translateY(${isHovered ? this.translateHover(realIndex) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, calcRowIndex, realIndex)}px) - translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth : this.translateOverflowX(realIndex, amCards)}px) + translateY(${this.calculateTranslateY(isHovered, isSelected, realIndex, amCards, calcRowIndex)}px) + translateX(${isSelected ? this.translateSelected(calcRowIndex) : this.translateOverflowX(realIndex, amCards)}px) scale(${isSelected ? 1.25 : 1}) `, }} - onMouseEnter={() => this.setHoveredNodeIndex(index)}> + onMouseEnter={() => this.setHoveredNodeIndex(index)} + + > {this.displayDoc(childPair, childScreenToLocal)} - {/* */} + {this._props.Document.cardSort == 'custom' ? this.renderButtons(childPairIndex) : ''}
); }); } + @observable amGroups = 0 + @observable customGroupDictionary = new Map< + number, number>(); + + + @action toggleButton(childPairIndex: number, buttonID: number) { + + this.customGroupDictionary.set(childPairIndex, buttonID); + } + + renderButtons (childPairIndex: number) { + const buttons = []; // Array to hold the button elements + + let amButtons = 4 + + if (this.amGroups > 4){ + amButtons = this.amGroups + } + + let activeButtonIndex = this.customGroupDictionary.get(childPairIndex) + + for (let i = 0; i < amButtons; i++) { + const isActive = activeButtonIndex == i + + buttons.push( + ); + } + + const totalWidth = amButtons * 35 + (amButtons * 2* 5) + 6; + return ( +
+ {buttons} +
+ ); + } + + + + + + + + + + + // @computed get content() { @@ -450,7 +533,7 @@ export class CollectionCardView extends CollectionSubView() { let translate = 0 - if (this.inactiveDocs().length != this.myChildLayoutPairs.length) { + if (this.inactiveDocs().length != this.myChildLayoutPairs.length && this.inactiveDocs().length < 10) { translate += this.panelWidth() / 2; } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 2d05b5490..11193f496 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -2010,4 +2010,4 @@ ScriptingGlobals.add(function datavizFromSchema(doc: Doc) { SchemaCSVPopUp.Instance.setVisible(true); } }); -}); +}); \ No newline at end of file diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 526315802..9056917fe 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -105,10 +105,12 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { selected ? selected.CollectionFreeFormDocumentView?.float() : console.log('[FontIconBox.tsx] toggleOverlay failed'); }); -ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links', checkResult?: boolean, persist?: boolean) { + + +ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom' | 'create', checkResult?: boolean, persist?: boolean, customNumber?: number) { const selected = SelectionManager.Docs.lastElement(); // prettier-ignore - const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([ + const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom' | 'create', { 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,dv:DocumentView) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid, @@ -156,6 +158,21 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "links", }], + ['custom', { + checkResult: (doc:Doc) => StrCast(doc?.cardSort), + setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "custom", + }], + + //in an ideal world lol + + + // ['create', { + // checkResult: (doc:Doc) => NumCast(doc?.customSortCount), + // setDoc: (doc:Doc,dv:DocumentView) => doc.customSortCount = NumCast(doc.customSortCount) + 1, + // }], + + + ]); if (checkResult) { -- cgit v1.2.3-70-g09d2 From f0b41a82df3ce7ea9a29e8a779a1967349f5b92a Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 13 May 2024 10:49:06 -0400 Subject: fixed documentDecorations for cardDeck view to not lag behind document movement --- .../views/collections/CollectionCardDeckView.tsx | 286 +++++++++------------ 1 file changed, 123 insertions(+), 163 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index bf26ad4b5..80159ae38 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -16,7 +16,7 @@ import { LinkManager } from '../../util/LinkManager'; // import Card from 'react-bootstrap/Card'; import { DocumentType } from '../../documents/DocumentTypes'; import { forEach } from 'lodash'; - +import { SnappingManager } from '../../util/SnappingManager'; @observer export class CollectionCardView extends CollectionSubView() { @@ -24,8 +24,8 @@ export class CollectionCardView extends CollectionSubView() { @observable hoveredNodeIndex = -1; - @computed get myChildLayoutPairs(){ - return this.childLayoutPairs.filter(l => l.layout.type != DocumentType.LINK) + @computed get myChildLayoutPairs() { + return this.childLayoutPairs.filter(l => l.layout.type != DocumentType.LINK); } @action @@ -64,8 +64,6 @@ export class CollectionCardView extends CollectionSubView() { return docs.filter(d => !SelectionManager.IsSelected(d.layout)); }; - - middleIndex = Math.floor(this.inactiveDocs().length / 2); constructor(props: any) { @@ -87,19 +85,15 @@ export class CollectionCardView extends CollectionSubView() { } }; - - childDocumentWidth = 600; // target width of a Doc... /** * how much to scale down the contents of the view so that everything will fit */ @computed get fitContentScale() { - if (this.myChildLayoutPairs.length< this.maxRowCount){ - length = this.myChildLayoutPairs.length - } - - else{ - length = this.maxRowCount + if (this.myChildLayoutPairs.length < this.maxRowCount) { + length = this.myChildLayoutPairs.length; + } else { + length = this.maxRowCount; } return (this.childDocumentWidth * length) / this._props.PanelWidth(); } @@ -109,10 +103,6 @@ export class CollectionCardView extends CollectionSubView() { isContentActive = () => this._props.isSelected() || this._props.isContentActive() || this._props.isAnyChildContentActive(); isChildContentActive = () => (this.isContentActive() ? true : false); - - - - rotate = (amCards: number, index: number) => { // console.log(amCards + "wtf") const possRotate = -30 + index * (30 / ((amCards - (amCards % 2)) / 2)); @@ -136,15 +126,13 @@ export class CollectionCardView extends CollectionSubView() { const evenOdd = amCards % 2; const apex = (amCards - evenOdd) / 2; const stepMag = 200 / ((amCards - evenOdd) / 2) + Math.abs((apex - index) * 25); - let rowOffset = 0 + let rowOffset = 0; - if (realIndex > this.maxRowCount -1){ + if (realIndex > this.maxRowCount - 1) { // 11 - 1 = 10 - rowOffset = 400 * ((realIndex - (realIndex % this.maxRowCount)) / this.maxRowCount) + rowOffset = 400 * ((realIndex - (realIndex % this.maxRowCount)) / this.maxRowCount); } - - // console.log('steo' + stepMag); if (evenOdd == 1 || index < apex - 1) { @@ -168,115 +156,114 @@ export class CollectionCardView extends CollectionSubView() { translateSelected = (index: number): number => { // if (this.isSelected(index)) { - const middleOfPanel = this._props.PanelWidth() / 2; - const scaledNodeWidth = this.panelWidth() * 1.25; + const middleOfPanel = this._props.PanelWidth() / 2; + const scaledNodeWidth = this.panelWidth() * 1.25; - // 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; + // 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; - // Calculate the translation needed to align the scaled node's center with the panel's center - const translation = middleOfPanel - scaledNodeCenter - scaledNodeWidth - (scaledNodeWidth /4); + // Calculate the translation needed to align the scaled node's center with the panel's center + const translation = middleOfPanel - scaledNodeCenter - scaledNodeWidth - scaledNodeWidth / 4; - return translation; + return translation; // } // return 0; }; @computed get sortedDocsType() { - const desc = BoolCast(this.layoutDoc.sortDesc); - let sorted = [] - let docs = [] + let sorted = []; + let docs = []; - for (let i=0; i< this.myChildLayoutPairs.length; i++){ //copying everything in childlayout pairs to sorted so that i can use the sort function without altering the original list - sorted[i] = this.myChildLayoutPairs[i] + for (let i = 0; i < this.myChildLayoutPairs.length; i++) { + //copying everything in childlayout pairs to sorted so that i can use the sort function without altering the original list + sorted[i] = this.myChildLayoutPairs[i]; } - switch(this._props.Document.cardSort){ - case "type": - // Copy and sort documents by type - return this.sort(sorted, "type", desc) - case "color": - return this.sort(sorted, "color", desc) + switch (this._props.Document.cardSort) { + case 'type': + // Copy and sort documents by type + return this.sort(sorted, 'type', desc); + case 'color': + return this.sort(sorted, 'color', desc); // case "links": // console.log("hi") - // let links = LinkManager.Instance.getAllRelatedLinks(this.myChildLayoutPairs[0].layout) + // let links = LinkManager.Instance.getAllRelatedLinks(this.myChildLayoutPairs[0].layout) - // console.log(links) - - // } + // console.log(links) - case "custom": - console.log("hiiiii") - return this.sort(sorted, "custom", desc) - + // } - default: - docs = this.myChildLayoutPairs - return {docs} + case 'custom': + console.log('hiiiii'); + return this.sort(sorted, 'custom', desc); - - + default: + docs = this.myChildLayoutPairs; + return { docs }; } } - - - hexToHsv = (hex: string): [number, number, number] => { if (!hex) return [0, 0, 0]; // Default to black if hex is not defined const r = parseInt(hex.slice(1, 3), 16) / 255; const g = parseInt(hex.slice(3, 5), 16) / 255; const b = parseInt(hex.slice(5, 7), 16) / 255; - const max = Math.max(r, g, b), min = Math.min(r, g, b); + const max = Math.max(r, g, b), + min = Math.min(r, g, b); const d = max - min; let h: number; - const s = (max === 0 ? 0 : d / max); + const s = max === 0 ? 0 : d / max; const v = max; switch (max) { - case min: h = 0; break; - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - default: h = 0; break; + case min: + h = 0; + break; + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + default: + h = 0; + break; } h /= 6; return [h, s, v]; }; - - - sort = (docs: {layout: Doc; data: Doc; }[], sortType: string, isDesc: boolean) => { - + sort = (docs: { layout: Doc; data: Doc }[], sortType: string, isDesc: boolean) => { docs.sort((docA, docB) => { let typeA; - let typeB + let typeB; - switch(sortType) { - case "color": + switch (sortType) { + case 'color': typeA = this.hexToHsv(StrCast(docA.layout.backgroundColor)) ?? ''; // If docA.type is undefined, use an empty string typeB = this.hexToHsv(StrCast(docB.layout.backgroundColor)) ?? ''; // If docB.type is undefined, use an empty string - break + break; - case "custom": - typeA = this.customGroupDictionary.get(docs.indexOf(docA)) ?? '' + case 'custom': + typeA = this.customGroupDictionary.get(docs.indexOf(docA)) ?? ''; // console.log(typeA + "A") - typeB = this.customGroupDictionary.get(docs.indexOf(docB)) ?? '' + typeB = this.customGroupDictionary.get(docs.indexOf(docB)) ?? ''; // console.log(typeB + 'b') - break - + break; default: typeA = docA.layout.type ?? ''; // If docA.type is undefined, use an empty string typeB = docB.layout.type ?? ''; // If docB.type is undefined, use an empty string - break + break; } - // Perform a basic string comparison if types are strings let out = 0; @@ -284,19 +271,15 @@ export class CollectionCardView extends CollectionSubView() { if (typeA > typeB) out = 1; if (isDesc) out *= -1; // Reverse the sort order if descending is true return out; - }); - - return {docs} - } + }); - + return { docs }; + }; // @computed get cards(){ - // } - displayDoc = (childPair: { layout: Doc; data: Doc }, screenToLocalTransform: () => Transform) => { return ( ); }; - @observable docRefs = new ObservableMap(); @observable maxRowCount = 10; overflowAmCardsCalc(index: number) { - if (this.inactiveDocs().length < this.maxRowCount){ - return this.inactiveDocs().length + if (this.inactiveDocs().length < this.maxRowCount) { + return this.inactiveDocs().length; } - // 13 - 3 = 10 - const totalCards = this.inactiveDocs().length + // 13 - 3 = 10 + const totalCards = this.inactiveDocs().length; // if 9 or less - if ( index < ((totalCards - (totalCards % 10)))){ - return this.maxRowCount + if (index < totalCards - (totalCards % 10)) { + return this.maxRowCount; } //(3) - return totalCards % 10 - + return totalCards % 10; } overflowIndexCalc(realIndex: number) { - if (realIndex < 10){ - return realIndex + if (realIndex < 10) { + return realIndex; } - return realIndex % 10 - + return realIndex % 10; } - translateOverflowX(realIndex: number, calcRowCards: number){ - if (realIndex < this.maxRowCount){ - return 0 + translateOverflowX(realIndex: number, calcRowCards: number) { + if (realIndex < this.maxRowCount) { + return 0; } - return (10 - calcRowCards) * (this.panelWidth()/2) + return (10 - calcRowCards) * (this.panelWidth() / 2); } - calculateTranslateY(isHovered: boolean, isSelected: boolean, realIndex: number, amCards: number, calcRowIndex: number) { - let trans = 0; if (isHovered) { trans += this.translateHover(realIndex); } - + trans += this.translateY(amCards, calcRowIndex, realIndex); - if (isSelected) { trans = 50 * this.fitContentScale; } - return trans + return trans; } + @observable _forceChildXf = false; @computed get contentSorted() { - const sortedDocs = this.sortedDocsType.docs; - // const amCards = this.inactiveDocs().length; + const sortedDocs = this.sortedDocsType.docs; + // const amCards = this.inactiveDocs().length; // Map sorted documents to their rendered components return sortedDocs.map((childPair, index) => { - // const childPair = { layout: doc, data: doc }; - + // const childPair = { layout: doc, data: doc }; const isHovered = this.hoveredNodeIndex === index; - const childPairIndex = this.myChildLayoutPairs.indexOf(childPair) + const childPairIndex = this.myChildLayoutPairs.indexOf(childPair); const realIndex = this.sortedDocsType.docs.filter(d => !SelectionManager.IsSelected(d.layout)).indexOf(childPair); - const calcRowIndex = this.overflowIndexCalc(realIndex) + const calcRowIndex = this.overflowIndexCalc(realIndex); - const amCards = this.overflowAmCardsCalc(realIndex) + const amCards = this.overflowAmCardsCalc(realIndex); const isSelected = SelectionManager.IsSelected(childPair.layout); const childScreenToLocal = () => { + this._forceChildXf; const dref = this.docRefs.get(childPair.layout); const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv); return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, calcRowIndex) : 0); @@ -406,6 +384,16 @@ export class CollectionCardView extends CollectionSubView() {
{ + SnappingManager.SetIsResizing(this.Document); + setTimeout( + action(() => { + SnappingManager.SetIsResizing(undefined); + this._forceChildXf = !this._forceChildXf; + }), + 400 + ); + }} style={{ width: this.panelWidth(), height: this.panelHeight(childPair.layout)(), @@ -416,69 +404,47 @@ export class CollectionCardView extends CollectionSubView() { scale(${isSelected ? 1.25 : 1}) `, }} - onMouseEnter={() => this.setHoveredNodeIndex(index)} - - > + onMouseEnter={() => this.setHoveredNodeIndex(index)}> {this.displayDoc(childPair, childScreenToLocal)} {this._props.Document.cardSort == 'custom' ? this.renderButtons(childPairIndex) : ''} -
); }); } - @observable amGroups = 0 - @observable customGroupDictionary = new Map< - number, number>(); - + @observable amGroups = 0; + @observable customGroupDictionary = new Map(); @action toggleButton(childPairIndex: number, buttonID: number) { - this.customGroupDictionary.set(childPairIndex, buttonID); } - renderButtons (childPairIndex: number) { + renderButtons(childPairIndex: number) { const buttons = []; // Array to hold the button elements - let amButtons = 4 + let amButtons = 4; - if (this.amGroups > 4){ - amButtons = this.amGroups + if (this.amGroups > 4) { + amButtons = this.amGroups; } - let activeButtonIndex = this.customGroupDictionary.get(childPairIndex) + let activeButtonIndex = this.customGroupDictionary.get(childPairIndex); for (let i = 0; i < amButtons; i++) { - const isActive = activeButtonIndex == i - - buttons.push( - ); + const isActive = activeButtonIndex == i; + + buttons.push(); } - const totalWidth = amButtons * 35 + (amButtons * 2* 5) + 6; + const totalWidth = amButtons * 35 + amButtons * 2 * 5 + 6; return (
{buttons}
- ); + ); } - - - - - - - - - - - - // @computed get content() { // // const currentIndex = NumCast(this.layoutDoc._carousel_index); // const amCards = this.inactiveDocs().length; @@ -486,7 +452,6 @@ export class CollectionCardView extends CollectionSubView() { // // const sortedDocs = this.sortedDocsType.docs; // Retrieve sorted documents // // const myInactives = - // return this.myChildLayoutPairs.map((childPair, index) => { // const isSelected = this.isSelected(index); @@ -511,11 +476,11 @@ export class CollectionCardView extends CollectionSubView() { // width: this.panelWidth(), // height: this.panelHeight(childPair.layout)(), // transform: ` - // rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg) + // rotate(${!isSelected ? this.rotate(amCards, inactiveIndex) : 0}deg) // translateY(${isHovered ? this.translateHover(index) : isSelected ? 50 * this.fitContentScale : this.translateY(amCards, inactiveIndex)}px) // translateX(${isSelected ? (this._props.PanelWidth() / 2) * this.fitContentScale - this.childDocumentWidth : 0}px) // scale(${isSelected ? 1.25 : 1}) - + // `, //scale has to be applied last or selected offset gets messed up // }} // // onClick={() => this.setSelectedNodeIndex(index)} @@ -530,23 +495,20 @@ export class CollectionCardView extends CollectionSubView() { // } @computed get translateWrapperX() { - - let translate = 0 + let translate = 0; if (this.inactiveDocs().length != this.myChildLayoutPairs.length && this.inactiveDocs().length < 10) { translate += this.panelWidth() / 2; } - console.log("in" + this.inactiveDocs().length) - console.log("max" + this.maxRowCount) + console.log('in' + this.inactiveDocs().length); + console.log('max' + this.maxRowCount); // if (this.inactiveDocs().length > this.maxRowCount){ // translate += ((this.inactiveDocs().length % this.maxRowCount) * this.panelWidth()) / 2 // console.log("trans" + (this.inactiveDocs().length % this.maxRowCount) / 2 ) // } - - return translate; } @@ -560,8 +522,6 @@ export class CollectionCardView extends CollectionSubView() { // } // } - - render() { return (
); } -} \ No newline at end of file +} -- cgit v1.2.3-70-g09d2 From d699cac7cab64e868aeee8d88b16e7a76e92e483 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Mon, 13 May 2024 16:42:25 -0400 Subject: god is good --- src/client/views/collections/CollectionCardDeckView.scss | 1 + src/client/views/collections/CollectionCardDeckView.tsx | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss index 222a1d226..09d6f70ea 100644 --- a/src/client/views/collections/CollectionCardDeckView.scss +++ b/src/client/views/collections/CollectionCardDeckView.scss @@ -67,6 +67,7 @@ button { .card-item-active, .card-item { + position: relative; transition: transform 0.3s ease-in-out; } diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 80159ae38..996c5711b 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -332,7 +332,13 @@ export class CollectionCardView extends CollectionSubView() { return realIndex % 10; } - translateOverflowX(realIndex: number, calcRowCards: number) { + translateOverflowX(realIndex: number, calcIndex: number, calcRowCards: number) { + + let trans = 0; + + // trans += (calcIndex * this.panelWidth()) + this.panelWidth() + + // return trans if (realIndex < this.maxRowCount) { return 0; } @@ -398,10 +404,10 @@ export class CollectionCardView extends CollectionSubView() { width: this.panelWidth(), height: this.panelHeight(childPair.layout)(), transform: ` - rotate(${!isSelected ? this.rotate(amCards, calcRowIndex) : 0}deg) - translateY(${this.calculateTranslateY(isHovered, isSelected, realIndex, amCards, calcRowIndex)}px) - translateX(${isSelected ? this.translateSelected(calcRowIndex) : this.translateOverflowX(realIndex, amCards)}px) - scale(${isSelected ? 1.25 : 1}) + translateY(${this.calculateTranslateY(isHovered, isSelected, realIndex, amCards, calcRowIndex)}px) + translateX(${isSelected ? this.translateSelected(calcRowIndex) : this.translateOverflowX(realIndex, calcRowIndex, amCards)}px) + rotate(${!isSelected ? this.rotate(amCards, calcRowIndex) : 0}deg) + scale(${isSelected ? 1.25 : 1}) `, }} onMouseEnter={() => this.setHoveredNodeIndex(index)}> -- cgit v1.2.3-70-g09d2 From 3c5b2353cb20843e968e51fdff58cc92f101ed51 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Tue, 14 May 2024 02:14:58 -0400 Subject: getting close to done --- src/client/documents/Documents.ts | 3 +- src/client/util/CurrentUserUtils.ts | 6 ++- src/client/views/MainView.tsx | 4 +- .../views/collections/CollectionCardDeckView.scss | 2 +- .../views/collections/CollectionCardDeckView.tsx | 63 +++++++++++++++++----- .../CollectionFreeFormLayoutEngines.tsx | 26 ++++----- .../collections/collectionFreeForm/MarqueeView.tsx | 4 +- src/client/views/global/globalScripts.ts | 35 +++++++----- 8 files changed, 94 insertions(+), 49 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index df69e215a..57f91399a 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -500,7 +500,8 @@ 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'); - customSortCount?: NUMt = new NumInfo('number of custom sorts the user has created'); + customSortNumber?: NUMt = new NumInfo('number of custom sorts the user has created'); + customHashMap?: List // card_sort_time?: BOOLt = new BoolInfo('whether sorting cards in deck view by time'); // card_sort_type?: BOOLt = new BoolInfo('whether sorting cards in deck view by type'); // card_sort_color?: BOOLt = new BoolInfo('whether sorting cards in deck view by color'); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 59560dd78..abc728cd3 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -730,7 +730,11 @@ 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: "Links", icon:"link", toolTip:"Sort by its links", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"links", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Create", icon:"plus", toolTip:"Create new custom groupings!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Create", icon:"robot", toolTip:"Create your first custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom1", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Create", icon:"star", toolTip:"Create your second custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom2", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Create", icon:"satellite", toolTip:"Create your third custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom3", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + + // ...customs ] diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index a5882dcf3..f1296e46a 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -527,7 +527,9 @@ export class MainView extends ObservableReactComponent<{}> { fa.faArrowsDownToLine, fa.faPalette, fa.faHourglassHalf, - fa.faRobot + fa.faRobot, + fa.faSatellite, + fa.faStar ] ); } diff --git a/src/client/views/collections/CollectionCardDeckView.scss b/src/client/views/collections/CollectionCardDeckView.scss index 09d6f70ea..babc604b5 100644 --- a/src/client/views/collections/CollectionCardDeckView.scss +++ b/src/client/views/collections/CollectionCardDeckView.scss @@ -68,7 +68,7 @@ button { .card-item-active, .card-item { position: relative; - transition: transform 0.3s ease-in-out; + transition: transform 0.5s ease-in-out; } .card-item-active { diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 996c5711b..fc183b72b 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -2,7 +2,7 @@ import { ObservableMap, action, computed, makeObservable, observable } from 'mob import { observer } from 'mobx-react'; import * as React from 'react'; import { Utils, returnFalse, returnTrue, returnZero } from '../../../Utils'; -import { Doc, DocListCast, Field } from '../../../fields/Doc'; +import { Doc, DocListCast, Field, StrListCast } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { NumCast, ScriptCast, StrCast, BoolCast, DocCast } from '../../../fields/Types'; import { DragManager } from '../../util/DragManager'; @@ -17,6 +17,7 @@ import { LinkManager } from '../../util/LinkManager'; import { DocumentType } from '../../documents/DocumentTypes'; import { forEach } from 'lodash'; import { SnappingManager } from '../../util/SnappingManager'; +import { List } from '../../../fields/List'; @observer export class CollectionCardView extends CollectionSubView() { @@ -70,11 +71,49 @@ export class CollectionCardView extends CollectionSubView() { super(props); makeObservable(this); // this.rotationDegree(7); + + if (this._props.Document.customHashMap != undefined){ + this.customGroupDictionary = this.getCustoms(StrListCast(this._props.Document.customHashMap)) + } + } + + @observable customGroupDictionary: Map[] = [new Map(), new Map(), new Map()]; + + @computed get mapToField(): List { + const resultList = new List(); // Creating a new ListImpl instance for strings + + this.customGroupDictionary.forEach(map => { + // Convert each map to a single string with entries formatted as "key:value" + const mapString = Array.from(map.entries()) + .map(([key, value]) => `${key}:${value}`) + .join(','); // Join all key-value pairs with commas + resultList.push(mapString); // Add the formatted string of the current map to the list + }); + + return resultList; + } + + getCustoms = (stringFrom: string[]): Map[] => { + return stringFrom.map(s => { + // Create a new Map object for each string. + const map = new Map(); + // Split the string by commas to get key-value pairs, then process each pair. + s.split(',').forEach(pair => { + const [key, value] = pair.split(':'); + map.set(Number(key), Number(value)); + }); + return map; + }); } + + + + private _dropDisposer?: DragManager.DragDropDisposer; componentWillUnmount() { + console.log("hey hey hey") this._dropDisposer?.(); } @@ -253,9 +292,11 @@ export class CollectionCardView extends CollectionSubView() { break; case 'custom': - typeA = this.customGroupDictionary.get(docs.indexOf(docA)) ?? ''; + + console.log(this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)]) + typeA = this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].get(docs.indexOf(docA)) ?? '9999'; // console.log(typeA + "A") - typeB = this.customGroupDictionary.get(docs.indexOf(docB)) ?? ''; + typeB = this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].get(docs.indexOf(docB)) ?? '9999'; // console.log(typeB + 'b') break; @@ -397,7 +438,7 @@ export class CollectionCardView extends CollectionSubView() { SnappingManager.SetIsResizing(undefined); this._forceChildXf = !this._forceChildXf; }), - 400 + 700 ); }} style={{ @@ -419,11 +460,13 @@ export class CollectionCardView extends CollectionSubView() { }); } - @observable amGroups = 0; - @observable customGroupDictionary = new Map(); + + + @action toggleButton(childPairIndex: number, buttonID: number) { - this.customGroupDictionary.set(childPairIndex, buttonID); + this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].set(childPairIndex, buttonID); + this._props.Document.customHashMap = this.mapToField } renderButtons(childPairIndex: number) { @@ -431,11 +474,7 @@ export class CollectionCardView extends CollectionSubView() { let amButtons = 4; - if (this.amGroups > 4) { - amButtons = this.amGroups; - } - - let activeButtonIndex = this.customGroupDictionary.get(childPairIndex); + let activeButtonIndex = this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].get(childPairIndex); for (let i = 0; i < amButtons; i++) { const isActive = activeButtonIndex == i; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index becad63f6..22005eb23 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -126,27 +126,20 @@ export function computeStarburstLayout(poolData: Map, pivotDoc } // export function computeCardDeckLayout(poolData: Map, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], engineProps: any) { -// console.log('hi'); // const docMap = new Map(); -// const spreadWidth = Math.min(panelDim[0], childPairs.length * 50); // Total width of the spread -// const startX = -(spreadWidth / 2); // Starting X position -// const fanAngle = 5; // Angle in degrees for fanning out cards -// const baseZIndex = 1000; // Base Z-index to ensure cards are stacked in order +// const burstDiam = [NumCast(pivotDoc._width), NumCast(pivotDoc._height)]; +// const burstScale = NumCast(pivotDoc._starburstDocScale, 1); // childPairs.forEach(({ layout, data }, i) => { // const aspect = NumCast(layout._height) / NumCast(layout._width); -// const docSize = Math.min(400, NumCast(layout._width)) * NumCast(pivotDoc._starburstDocScale, 1); -// const posX = startX + (spreadWidth / childPairs.length) * i; -// const posY = 0; // Adjust if you want to change the vertical alignment -// const rotation = (i - (childPairs.length / 2)) * fanAngle; // Calculate rotation for fanning effect - +// const docSize = Math.min(Math.min(400, NumCast(layout._width)), Math.min(400, NumCast(layout._width)) / aspect) * burstScale; +// const deg = (i / childPairs.length) * Math.PI * 2; // docMap.set(layout[Id], { -// x: posX, -// y: posY, +// x: Math.min(burstDiam[0] / 2 - docSize, Math.max(-burstDiam[0] / 2, (Math.cos(deg) * burstDiam[0]) / 2 - docSize / 2)), +// y: Math.min(burstDiam[1] / 2 - docSize * aspect, Math.max(-burstDiam[1] / 2, (Math.sin(deg) * burstDiam[1]) / 2 - (docSize / 2) * aspect)), // width: docSize, // height: docSize * aspect, -// zIndex: baseZIndex + i, -// rotation: rotation, +// zIndex: NumCast(layout.zIndex), // pair: { layout, data }, // replica: '', // color: 'white', @@ -154,9 +147,8 @@ export function computeStarburstLayout(poolData: Map, pivotDoc // transition: 'all 0.3s', // }); // }); - -// const divider = { type: 'div', color: 'transparent', x: -panelDim[0] / 2, y: -panelDim[1] / 2, width: 15, height: 15, payload: undefined }; -// return normalizeResults(panelDim, 12, docMap, poolData, viewDefsToJSX, [], 0, [divider]); +// const divider = { type: 'div', color: 'transparent', x: -burstDiam[0] / 2, y: -burstDiam[1] / 2, width: 15, height: 15, payload: undefined }; +// return normalizeResults(burstDiam, 12, docMap, poolData, viewDefsToJSX, [], 0, [divider]); // } export function computePivotLayout(poolData: Map, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], engineProps: any) { diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 98684ae98..7e7a5c2c6 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -533,7 +533,7 @@ export class MarqueeView extends ObservableReactComponent any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([ + const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom1' | 'custom2' | 'custom3', { 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,dv:DocumentView) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid, @@ -158,21 +158,28 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "links", }], - ['custom', { + ['custom1', { checkResult: (doc:Doc) => StrCast(doc?.cardSort), - setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "custom", - }], - - //in an ideal world lol - - - // ['create', { - // checkResult: (doc:Doc) => NumCast(doc?.customSortCount), - // setDoc: (doc:Doc,dv:DocumentView) => doc.customSortCount = NumCast(doc.customSortCount) + 1, - // }], + setDoc: (doc, dv) => { + doc.cardSort = "custom"; + doc.customSortNumber = 0; + } + }], - + ['custom2', { + checkResult: (doc:Doc) => StrCast(doc?.cardSort), + setDoc: (doc, dv) => { + doc.cardSort = "custom"; + doc.customSortNumber = 1; + console.log(doc.customSortNumber + " numberrrrrrrr") + } }], + ['custom3', { + checkResult: (doc:Doc) => StrCast(doc?.cardSort), + setDoc: (doc, dv) => { + doc.cardSort = "custom"; + doc.customSortNumber = 2; + } }], ]); if (checkResult) { -- cgit v1.2.3-70-g09d2 From 938a9d94823064fa3487a8f8f378cdfb7d8db437 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Tue, 14 May 2024 11:01:36 -0400 Subject: me vs the gpt API who will win --- .../views/collections/CollectionCardDeckView.tsx | 87 +++++----------------- 1 file changed, 18 insertions(+), 69 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index fc183b72b..7af6eb614 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import { Utils, returnFalse, returnTrue, returnZero } from '../../../Utils'; import { Doc, DocListCast, Field, StrListCast } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; -import { NumCast, ScriptCast, StrCast, BoolCast, DocCast } from '../../../fields/Types'; +import { NumCast, ScriptCast, StrCast, BoolCast, DocCast, RTFCast } from '../../../fields/Types'; import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { StyleProp } from '../StyleProvider'; @@ -52,6 +52,9 @@ export class CollectionCardView extends CollectionSubView() { // console.log('good mornings'); this.setSelectedNodeIndex(index); } + + + }; isSelected = (index: number): boolean => { @@ -62,7 +65,11 @@ export class CollectionCardView extends CollectionSubView() { inactiveDocs = () => { const docs = this.myChildLayoutPairs; + + return docs.filter(d => !SelectionManager.IsSelected(d.layout)); + + }; middleIndex = Math.floor(this.inactiveDocs().length / 2); @@ -80,7 +87,7 @@ export class CollectionCardView extends CollectionSubView() { @observable customGroupDictionary: Map[] = [new Map(), new Map(), new Map()]; @computed get mapToField(): List { - const resultList = new List(); // Creating a new ListImpl instance for strings + const resultList = new List(); this.customGroupDictionary.forEach(map => { // Convert each map to a single string with entries formatted as "key:value" @@ -110,10 +117,11 @@ export class CollectionCardView extends CollectionSubView() { + + private _dropDisposer?: DragManager.DragDropDisposer; componentWillUnmount() { - console.log("hey hey hey") this._dropDisposer?.(); } @@ -238,7 +246,7 @@ export class CollectionCardView extends CollectionSubView() { // } case 'custom': - console.log('hiiiii'); + // console.log('hiiiii'); return this.sort(sorted, 'custom', desc); default: @@ -293,7 +301,7 @@ export class CollectionCardView extends CollectionSubView() { case 'custom': - console.log(this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)]) + // console.log(this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)]) typeA = this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].get(docs.indexOf(docA)) ?? '9999'; // console.log(typeA + "A") typeB = this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].get(docs.indexOf(docB)) ?? '9999'; @@ -467,6 +475,9 @@ export class CollectionCardView extends CollectionSubView() { @action toggleButton(childPairIndex: number, buttonID: number) { this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].set(childPairIndex, buttonID); this._props.Document.customHashMap = this.mapToField + + // const queryText = RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1'])); + // console.log(queryText) } renderButtons(childPairIndex: number) { @@ -490,54 +501,6 @@ export class CollectionCardView extends CollectionSubView() { ); } - // @computed get content() { - // // const currentIndex = NumCast(this.layoutDoc._carousel_index); - // const amCards = this.inactiveDocs().length; - // console.log(amCards + "lol") - // // const sortedDocs = this.sortedDocsType.docs; // Retrieve sorted documents - - // // const myInactives = - - // return this.myChildLayoutPairs.map((childPair, index) => { - // const isSelected = this.isSelected(index); - // const isHovered = this.hoveredNodeIndex === index; - // const isOverflow = amCards > 8 && index > amCards / 2; - // // const inactiveIndex = this.sortedDocsType.docs.indexOf(childPair); - // const inactiveIndex = this.inactiveDocs().indexOf(childPair.layout); - // // const yOffset = this.verticalOffset(index); - - // const childScreenToLocal = () => { - // const dref = this.docRefs.get(childPair.layout); - // const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv); - // // the document view may center its contents and if so, will prepend that onto the screenToLocalTansform. so we have to subtract that off - // return new Transform(-translateX + (dref?.centeringX || 0) * scale, -translateY + (dref?.centeringY || 0) * scale, 1).scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, inactiveIndex) : 0); - // }; - - // return ( - //
this.setSelectedNodeIndex(index)} - - // onMouseEnter={() => this.setHoveredNodeIndex(index)}> - // {/* {this.lol(childPair.data, index)} */} - - // {this.displayDoc(childPair, childScreenToLocal)} - //
- // ); - // }); - // } @computed get translateWrapperX() { let translate = 0; @@ -546,8 +509,8 @@ export class CollectionCardView extends CollectionSubView() { translate += this.panelWidth() / 2; } - console.log('in' + this.inactiveDocs().length); - console.log('max' + this.maxRowCount); + // console.log('in' + this.inactiveDocs().length); + // console.log('max' + this.maxRowCount); // if (this.inactiveDocs().length > this.maxRowCount){ // translate += ((this.inactiveDocs().length % this.maxRowCount) * this.panelWidth()) / 2 @@ -586,20 +549,6 @@ export class CollectionCardView extends CollectionSubView() { onMouseLeave={() => this.setHoveredNodeIndex(-1)}> {this.contentSorted}
- - {/* - - {header} - - - - - */} - - {/* {this.focusContent} */} ); } -- cgit v1.2.3-70-g09d2 From df7532553db3df270fcbd25a46e7a349a82bd712 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Thu, 16 May 2024 12:52:14 -0400 Subject: pdfs being weird --- src/client/apis/gpt/GPT.ts | 35 +++++------ src/client/util/CurrentUserUtils.ts | 4 +- .../views/collections/CollectionCardDeckView.tsx | 70 ++++++++++++++++++++-- src/client/views/global/globalScripts.ts | 8 ++- src/client/views/nodes/PDFBox.tsx | 1 + 5 files changed, 92 insertions(+), 26 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 30194f9f8..1f50ad0b8 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -5,7 +5,8 @@ enum GPTCallType { SUMMARY = 'summary', COMPLETION = 'completion', EDIT = 'edit', - DATA = 'data', + // MERMAID='mermaid' + SORT = 'sort' } type GPTCallOpts = { @@ -15,45 +16,40 @@ type GPTCallOpts = { prompt: string; }; -/** - * Replace completions (deprecated) with chat - */ - const callTypeMap: { [type: string]: GPTCallOpts } = { - // newest model: gpt-4 - summary: { model: 'gpt-3.5-turbo', maxTokens: 256, temp: 0.5, prompt: 'Summarize the text given in simpler terms.' }, - edit: { model: 'gpt-3.5-turbo', maxTokens: 256, temp: 0.5, prompt: 'Reword the text.' }, - completion: { model: 'gpt-3.5-turbo', maxTokens: 256, temp: 0.5, prompt: "You are a helpful assistant. Answer the user's prompt." }, - data: { model: 'gpt-3.5-turbo', maxTokens: 256, temp: 0.5, prompt: "You are a helpful resarch assistant. Analyze the user's data to find meaningful patterns and/or correlation. Please keep your response short and to the point." }, + summary: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Summarize this text in simpler terms: ' }, + edit: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Reword this: ' }, + completion: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: '' }, + sort:{model:'gpt-4-turbo',maxTokens:2048,temp:0,prompt:"I'm going to give you a list of strings. Sort them into lists by shared content. The format of should be: '[string1, string2], [string 3, string4][string5, string6]' where the actual numbers of strings in each category / total categorys is arbritray and up to your interpretation"} }; -/** + +/**` * Calls the OpenAI API. * * @param inputText Text to process * @returns AI Output */ -const gptAPICall = async (inputText: string, callType: GPTCallType, prompt?: any) => { +const gptAPICall = async (inputText: string, callType: GPTCallType) => { if (callType === GPTCallType.SUMMARY) inputText += '.'; const opts: GPTCallOpts = callTypeMap[callType]; try { const configuration: ClientOptions = { - apiKey: process.env.OPENAI_KEY, + apiKey: "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", dangerouslyAllowBrowser: true, }; const openai = new OpenAI(configuration); - let usePrompt = prompt ? opts.prompt + prompt : opts.prompt; let messages: ChatCompletionMessageParam[] = [ - { role: 'system', content: usePrompt }, + { role: 'system', content: opts.prompt }, { role: 'user', content: inputText }, ]; const response = await openai.chat.completions.create({ model: opts.model, - max_tokens: opts.maxTokens, + messages: messages, temperature: opts.temp, - messages, + max_tokens: opts.maxTokens, }); const content = response.choices[0].message.content; return content; @@ -76,11 +72,12 @@ const gptImageCall = async (prompt: string, n?: number) => { n: n ?? 1, size: '1024x1024', }); - return response.data.map(data => data.url); + return response.data.map((data: any) => data.url); + // return response.data.data[0].url; } catch (err) { console.error(err); return; } }; -export { gptAPICall, gptImageCall, GPTCallType }; +export { gptAPICall, gptImageCall, GPTCallType }; \ No newline at end of file diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index abc728cd3..e18c22bac 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -730,9 +730,11 @@ 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: "Links", icon:"link", toolTip:"Sort by its links", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"links", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Create", icon:"robot", toolTip:"Create your first custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom1", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Create", icon:"heart", toolTip:"Create your first custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom1", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Create", icon:"star", toolTip:"Create your second custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom2", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, { title: "Create", icon:"satellite", toolTip:"Create your third custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom3", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Create", icon:"robot", toolTip:"Have ChatGPT sort your text-based nodes !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + // ...customs diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 7af6eb614..561b9f806 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import { Utils, returnFalse, returnTrue, returnZero } from '../../../Utils'; import { Doc, DocListCast, Field, StrListCast } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; -import { NumCast, ScriptCast, StrCast, BoolCast, DocCast, RTFCast } from '../../../fields/Types'; +import { NumCast, ScriptCast, StrCast, BoolCast, DocCast, RTFCast, Cast} from '../../../fields/Types'; import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { StyleProp } from '../StyleProvider'; @@ -18,6 +18,9 @@ import { DocumentType } from '../../documents/DocumentTypes'; import { forEach } from 'lodash'; import { SnappingManager } from '../../util/SnappingManager'; import { List } from '../../../fields/List'; +import { gptAPICall } from '../../apis/gpt/GPT'; +import { GPTCallType } from '../../apis/gpt/GPT'; +import { ImageField } from '../../../fields/URLField'; @observer export class CollectionCardView extends CollectionSubView() { @@ -249,6 +252,11 @@ export class CollectionCardView extends CollectionSubView() { // console.log('hiiiii'); return this.sort(sorted, 'custom', desc); + case 'chat': + this.smartSort() + docs = this.myChildLayoutPairs; + return {docs} + default: docs = this.myChildLayoutPairs; return { docs }; @@ -306,7 +314,7 @@ export class CollectionCardView extends CollectionSubView() { // console.log(typeA + "A") typeB = this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].get(docs.indexOf(docB)) ?? '9999'; // console.log(typeB + 'b') - break; + break; default: typeA = docA.layout.type ?? ''; // If docA.type is undefined, use an empty string @@ -468,6 +476,8 @@ export class CollectionCardView extends CollectionSubView() { }); } + + @@ -476,10 +486,62 @@ export class CollectionCardView extends CollectionSubView() { this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].set(childPairIndex, buttonID); this._props.Document.customHashMap = this.mapToField - // const queryText = RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1'])); - // console.log(queryText) + // Cast(selected.Document.data, WebField, null)?.url?.href) + + // StrCast(selected.Document.data, Cast(selected.Document.data, WebField, null)?.url?.href) + + + + // const + const imgurlperchance = Cast(this.childDocs[1].data, ImageField, null)?.url; + + console.log('Print Front of cards: ' + RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text); + console.log('Print Back of cards: ' + RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text); + + + // const queryText = (RTFCast(this.myChildLayoutPairs[0].layout.text)).Text; + // const queryText = RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text; + + console.log(imgurlperchance ?? "sad") } + childPairStringList () { + let string = "" + for (let i=0; i < this.myChildLayoutPairs.length; i++){ + string += StrCast((RTFCast(this.myChildLayoutPairs[i].layout.text)).Text) + ", " + } + return string + } + + @observable isLoading = false + + @action async smartSort() { + this.isLoading = true; + console.log("loading") + let prompt= "" + + if (this.childPairStringList() == ""){ + console.log("no child pairs :(") + } + + else{ + console.log(this.childPairStringList() + "og list") + prompt = "Sort this list of strings by shared content " + this.childPairStringList() + } + + + let res = await gptAPICall(prompt, GPTCallType.SORT); + this.isLoading = false; + if (res == 'Error connecting with API.') { + // If GPT call failed + console.error('GPT call failed'); + } else if (res != null) { + // If GPT call succeeded, set htmlCode;;; TODO: check if valid html + console.log(res) + } + this.isLoading = false; + }; + renderButtons(childPairIndex: number) { const buttons = []; // Array to hold the button elements diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 30602ea0b..14f83beb6 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -107,10 +107,10 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { -ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom1' | 'custom2' | 'custom3', checkResult?: boolean, persist?: boolean, customNumber?: number) { +ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom1' | 'custom2' | 'custom3'| 'chat', checkResult?: boolean, persist?: boolean, customNumber?: number) { const selected = SelectionManager.Docs.lastElement(); // prettier-ignore - const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom1' | 'custom2' | 'custom3', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([ + const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom1' | 'custom2' | 'custom3'| 'chat', { 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,dv:DocumentView) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid, @@ -180,6 +180,10 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid doc.cardSort = "custom"; doc.customSortNumber = 2; } }], + ['chat', { + checkResult: (doc:Doc) => StrCast(doc?.cardSort), + setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "chat", + }], ]); if (checkResult) { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 1274220b6..90d6133e4 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -33,6 +33,7 @@ import { FocusViewOptions, FieldView, FieldViewProps } from './FieldView'; import { ImageBox } from './ImageBox'; import './PDFBox.scss'; import { PinProps, PresBox } from './trails'; +import { Networking } from '../../Network'; @observer export class PDFBox extends ViewBoxAnnotatableComponent() implements ViewBoxInterface { -- cgit v1.2.3-70-g09d2 From d56ce09de98d843cf46b0d6eda5f8c82446f7849 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Thu, 16 May 2024 23:04:38 -0400 Subject: ab to do some silly thing --- src/client/apis/gpt/GPT.ts | 50 +++++++++++++-- .../views/collections/CollectionCardDeckView.tsx | 72 +++++++++++++++++++--- .../collectionSchema/CollectionSchemaView.tsx | 2 +- src/client/views/pdf/PDFViewer.tsx | 2 +- 4 files changed, 111 insertions(+), 15 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 1f50ad0b8..7c53ee83e 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -5,8 +5,8 @@ enum GPTCallType { SUMMARY = 'summary', COMPLETION = 'completion', EDIT = 'edit', - // MERMAID='mermaid' - SORT = 'sort' + SORT = 'sort', + DESCRIBE = 'describe' } type GPTCallOpts = { @@ -20,7 +20,10 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { summary: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Summarize this text in simpler terms: ' }, edit: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Reword this: ' }, completion: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: '' }, - sort:{model:'gpt-4-turbo',maxTokens:2048,temp:0,prompt:"I'm going to give you a list of strings. Sort them into lists by shared content. The format of should be: '[string1, string2], [string 3, string4][string5, string6]' where the actual numbers of strings in each category / total categorys is arbritray and up to your interpretation"} + sort:{model:'gpt-4-turbo',maxTokens:2048,temp:0.5,prompt:"I'm going to give you a list of strings. Sort them into lists by shared content. The format of should be: [string1, string2], [string 3, string4], [string5, string6] where the actual numbers of strings in each category / total categorys is arbritray and up to your interpretation"}, + describe:{model:'gpt-4-vision-preview',maxTokens:2048,temp:0,prompt:"Describe these images in 3-5 words"}, + + }; @@ -30,6 +33,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { * @param inputText Text to process * @returns AI Output */ + const gptAPICall = async (inputText: string, callType: GPTCallType) => { if (callType === GPTCallType.SUMMARY) inputText += '.'; const opts: GPTCallOpts = callTypeMap[callType]; @@ -59,6 +63,44 @@ const gptAPICall = async (inputText: string, callType: GPTCallType) => { } }; + +const gptImageLabel = async (imgUrl: string): Promise => { + try { + const configuration: ClientOptions = { + apiKey: "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", + dangerouslyAllowBrowser: true, + }; + + const openai = new OpenAI(configuration); + const response = await openai.chat.completions.create({ + model: 'gpt-4o', + messages: [ + { + role: 'user', + content: [ + { type: 'text', text: 'Describe this image in 3-5 words' }, + { + type: 'image_url', + image_url: { + url: `${imgUrl}`, + }, + }, + ], + }, + ], + }); + if (response.choices[0].message.content) { + return response.choices[0].message.content; + } else { + return ':('; + } + } catch (err) { + console.log(err); + return 'Error connecting with API'; + } +}; + + const gptImageCall = async (prompt: string, n?: number) => { try { const configuration: ClientOptions = { @@ -80,4 +122,4 @@ const gptImageCall = async (prompt: string, n?: number) => { } }; -export { gptAPICall, gptImageCall, GPTCallType }; \ No newline at end of file +export { gptAPICall, gptImageCall, gptImageLabel, GPTCallType }; \ No newline at end of file diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 561b9f806..e7e2cba4a 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -18,9 +18,9 @@ import { DocumentType } from '../../documents/DocumentTypes'; import { forEach } from 'lodash'; import { SnappingManager } from '../../util/SnappingManager'; import { List } from '../../../fields/List'; -import { gptAPICall } from '../../apis/gpt/GPT'; +import { gptAPICall, gptImageLabel } from '../../apis/gpt/GPT'; import { GPTCallType } from '../../apis/gpt/GPT'; -import { ImageField } from '../../../fields/URLField'; +import { ImageField, PdfField, URLField } from '../../../fields/URLField'; @observer export class CollectionCardView extends CollectionSubView() { @@ -253,7 +253,7 @@ export class CollectionCardView extends CollectionSubView() { return this.sort(sorted, 'custom', desc); case 'chat': - this.smartSort() + this.getImageDesc() docs = this.myChildLayoutPairs; return {docs} @@ -493,28 +493,83 @@ export class CollectionCardView extends CollectionSubView() { // const - const imgurlperchance = Cast(this.childDocs[1].data, ImageField, null)?.url; + const imgurlperchance = Cast(this.childDocs[1].data, ImageField, null)?.url.href; + const perchance = this.imageUrlToBase64(imgurlperchance) + // const imgurlperchance = Cast(this.childDocs[1].data, PdfField, null)?.url.; - console.log('Print Front of cards: ' + RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text); - console.log('Print Back of cards: ' + RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text); + // console.log('Print Front of cards: ' + RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text); + // console.log('Print Back of cards: ' + RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text); + + // const perchance = StrCast(this.childDocs[0].text); + + + + // const pdf = (StrCast(this.myChildLayoutPairs[0].layout.text)); //pdf + // const queryText = (RTFCast(this.myChildLayoutPairs[0].layout.text)); //everything else - // const queryText = (RTFCast(this.myChildLayoutPairs[0].layout.text)).Text; // const queryText = RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text; - console.log(imgurlperchance ?? "sad") + console.log(perchance ?? "sad") } childPairStringList () { let string = "" for (let i=0; i < this.myChildLayoutPairs.length; i++){ + + + let text = StrCast((RTFCast(this.myChildLayoutPairs[i].layout.text)).Text) string += StrCast((RTFCast(this.myChildLayoutPairs[i].layout.text)).Text) + ", " + this.textToDoc.has() } return string } @observable isLoading = false + imageUrlToBase64 = async (imageUrl: string): Promise => { + try { + const response = await fetch(imageUrl); + const blob = await response.blob(); + + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(blob); + reader.onloadend = () => resolve(reader.result as string); + reader.onerror = error => reject(error); + }); + } catch (error) { + console.error('Error:', error); + throw error; + } + }; + + textToDoc = new Map() + gptProccessedImages = new Set() + + @action async getImageDesc(){ + const images = this.childDocs.filter(d => d.type == DocumentType.IMG).filter(d=> !this.gptProccessedImages.has(d)); + images.map(doc => { + let href = (doc['data'] as URLField).url.href; + let hrefParts = href.split('.'); + let hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`; + return this.imageUrlToBase64(hrefComplete).then(hrefBase64 => { + return gptImageLabel(hrefBase64).then(response => { + this.textToDoc.set(response, doc) + this.gptProccessedImages.add(doc) + console.log(response); + + }); + }); + }); + } + + + + //a set of all the images that have already been given desc + //a map from the text to the Doc (for everything) + + @action async smartSort() { this.isLoading = true; console.log("loading") @@ -536,7 +591,6 @@ export class CollectionCardView extends CollectionSubView() { // If GPT call failed console.error('GPT call failed'); } else if (res != null) { - // If GPT call succeeded, set htmlCode;;; TODO: check if valid html console.log(res) } this.isLoading = false; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 6a956f2ac..731ea1235 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -51,7 +51,7 @@ export const FInfotoColType: { [key: string]: ColumnType } = { enumeration: ColumnType.Enumeration, }; -const defaultColumnKeys: string[] = ['title', 'type', 'author', 'author_date', 'text']; +const defaultColumnKeys: string[] = ['title', 'type', 'author', 'author_date', 'text']; @observer export class CollectionSchemaView extends CollectionSubView() { diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index aaff2a342..b87e29d4e 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -30,7 +30,7 @@ const _global = (window /* browser */ || global) /* node */ as any; //pdfjsLib.GlobalWorkerOptions.workerSrc = `/assets/pdf.worker.js`; // The workerSrc property shall be specified. -Pdfjs.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.1.392/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 825463b4f7bb609082d16b302d40c6af56c98b26 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Fri, 17 May 2024 02:31:22 -0400 Subject: we did it joe --- src/client/apis/gpt/GPT.ts | 2 +- .../views/collections/CollectionCardDeckView.tsx | 188 ++++++++++++++------- 2 files changed, 126 insertions(+), 64 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 7c53ee83e..9a24c808c 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -20,7 +20,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { summary: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Summarize this text in simpler terms: ' }, edit: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Reword this: ' }, completion: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: '' }, - sort:{model:'gpt-4-turbo',maxTokens:2048,temp:0.5,prompt:"I'm going to give you a list of strings. Sort them into lists by shared content. The format of should be: [string1, string2], [string 3, string4], [string5, string6] where the actual numbers of strings in each category / total categorys is arbritray and up to your interpretation"}, + sort:{model:'gpt-4o',maxTokens:2048,temp:0.5,prompt:"I'm going to give you a list of descriptions. Each one is seperated by ====== on either side. They will vary in length, so make sure to only seperate when you see ======. Sort them into lists by shared content. MAKE SURE EACH DESCRIPTOR IS IN ONLY ONE LIST. Generate only the list with each list seperated by ====== with the elements seperated by ~~~~~~"}, describe:{model:'gpt-4-vision-preview',maxTokens:2048,temp:0,prompt:"Describe these images in 3-5 words"}, diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index e7e2cba4a..e64c013f1 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -24,7 +24,10 @@ import { ImageField, PdfField, URLField } from '../../../fields/URLField'; @observer export class CollectionCardView extends CollectionSubView() { - @observable selectedNodeIndex = -1; + + //TODO: for saving custom groups instead of string field hashmap nonsense should instead just set teh index for each child document per group as a fie;d + // so like, group1Ibndex = 1 etc etc as they change. That way, if the documents change it doesnt matter since the idnexes are tied to the + // documents themselves @observable hoveredNodeIndex = -1; @@ -223,40 +226,34 @@ export class CollectionCardView extends CollectionSubView() { // return 0; }; + @observable sortedDocs = [] as { layout: Doc; data: Doc }[]; + + @computed get sortedDocsType() { + if (this._props.Document.cardSort === 'chat' && this.sortedDocs.length === 0) { + this.smartSort(); // Trigger the sorting if it hasn't been done yet + return { docs: [] }; // Return an empty array or a loading state + } + const desc = BoolCast(this.layoutDoc.sortDesc); let sorted = []; let docs = []; - + for (let i = 0; i < this.myChildLayoutPairs.length; i++) { //copying everything in childlayout pairs to sorted so that i can use the sort function without altering the original list sorted[i] = this.myChildLayoutPairs[i]; } - + switch (this._props.Document.cardSort) { case 'type': // Copy and sort documents by type return this.sort(sorted, 'type', desc); case 'color': return this.sort(sorted, 'color', desc); - // case "links": - // console.log("hi") - - // let links = LinkManager.Instance.getAllRelatedLinks(this.myChildLayoutPairs[0].layout) - - // console.log(links) - - // } - case 'custom': - // console.log('hiiiii'); return this.sort(sorted, 'custom', desc); - case 'chat': - this.getImageDesc() - docs = this.myChildLayoutPairs; - return {docs} - + return { docs: this.sortedDocs }; // Use the sorted docs from the observable default: docs = this.myChildLayoutPairs; return { docs }; @@ -314,7 +311,21 @@ export class CollectionCardView extends CollectionSubView() { // console.log(typeA + "A") typeB = this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].get(docs.indexOf(docB)) ?? '9999'; // console.log(typeB + 'b') - break; + break; + + case 'gpt': + + // console.log(this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)]) + typeA = this.gptGroups.get(docA.layout) ?? '9999'; + console.log(typeA + "typea") + typeB = this.gptGroups.get(docB.layout) ?? '9999'; + console.log(typeB + "typeB") + + + // console.log(typeA + "A") + // typeB = this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].get(docs.indexOf(docB)) ?? '9999'; + // console.log(typeB + 'b') + break; default: typeA = docA.layout.type ?? ''; // If docA.type is undefined, use an empty string @@ -488,6 +499,8 @@ export class CollectionCardView extends CollectionSubView() { // Cast(selected.Document.data, WebField, null)?.url?.href) + //note richtext + // StrCast(selected.Document.data, Cast(selected.Document.data, WebField, null)?.url?.href) @@ -506,23 +519,42 @@ export class CollectionCardView extends CollectionSubView() { // const pdf = (StrCast(this.myChildLayoutPairs[0].layout.text)); //pdf - // const queryText = (RTFCast(this.myChildLayoutPairs[0].layout.text)); //everything else + const queryText = this.myChildLayoutPairs[0].layout.type; //everything else // const queryText = RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text; - console.log(perchance ?? "sad") + console.log(queryText ?? "sad") } - childPairStringList () { - let string = "" - for (let i=0; i < this.myChildLayoutPairs.length; i++){ - - - let text = StrCast((RTFCast(this.myChildLayoutPairs[i].layout.text)).Text) - string += StrCast((RTFCast(this.myChildLayoutPairs[i].layout.text)).Text) + ", " - this.textToDoc.has() + async childPairStringList(): Promise { + let string = ""; + for (let i = 0; i < this.childDocs.length; i++) { + switch (this.childDocs[i].type) { + case DocumentType.IMG: + string += `======${await this.getImageDesc(this.childDocs[i])}======`; + break; + + case DocumentType.PDF: + let pdfText = StrCast(this.childDocs[i].text); + let words = pdfText.split(/\s+/); + let first50Words = words.slice(0, 50); + string += `======${first50Words.join(' ')}======`; + + this.textToDoc.set(first50Words.join(' ').trim(), this.childDocs[i]); + break; + + case DocumentType.RTF: + let rtfText = StrCast((RTFCast(this.childDocs[i].text)).Text); + string += `======${StrCast((RTFCast(this.childDocs[i].text)).Text)}======`; + this.textToDoc.set(rtfText.trim(), this.childDocs[i]); + break; + + default: + string += `======${StrCast(this.childDocs[i].title)}======`; + this.textToDoc.set(StrCast(this.childDocs[i].title).trim(), this.childDocs[i]); + } } - return string + return string; } @observable isLoading = false @@ -547,21 +579,20 @@ export class CollectionCardView extends CollectionSubView() { textToDoc = new Map() gptProccessedImages = new Set() - @action async getImageDesc(){ - const images = this.childDocs.filter(d => d.type == DocumentType.IMG).filter(d=> !this.gptProccessedImages.has(d)); - images.map(doc => { - let href = (doc['data'] as URLField).url.href; + @action async getImageDesc(image: Doc){ + let href = (image['data'] as URLField).url.href; let hrefParts = href.split('.'); let hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`; - return this.imageUrlToBase64(hrefComplete).then(hrefBase64 => { - return gptImageLabel(hrefBase64).then(response => { - this.textToDoc.set(response, doc) - this.gptProccessedImages.add(doc) - console.log(response); - - }); - }); - }); + try { + let hrefBase64 = await this.imageUrlToBase64(hrefComplete); + let response = await gptImageLabel(hrefBase64); + this.textToDoc.set(response.trim(), image); + this.gptProccessedImages.add(image); + console.log(response); + return response; // Return the response from gptImageLabel + } catch (error) { + console.log("bad things have happened"); + } } @@ -572,29 +603,60 @@ export class CollectionCardView extends CollectionSubView() { @action async smartSort() { this.isLoading = true; - console.log("loading") - let prompt= "" - - if (this.childPairStringList() == ""){ - console.log("no child pairs :(") + console.log("loading"); + + // Store the result of childPairStringList in a variable + const childPairStrings = await this.childPairStringList(); + + if (childPairStrings === "") { + console.log("no child pairs :("); + } else { + console.log(childPairStrings + " og list"); + let prompt = childPairStrings; + + let res = await gptAPICall(prompt, GPTCallType.SORT); + this.isLoading = false; + if (res == 'Error connecting with API.') { + // If GPT call failed + console.error('GPT call failed'); + } else if (res != null) { + console.log(res); + this.processGptOutput(res); + // Update the observable with the sorted documents + this.sortedDocs = this.sort(this.myChildLayoutPairs, 'gpt', BoolCast(this.layoutDoc.sortDesc)).docs; + } + this.isLoading = false; } + } - else{ - console.log(this.childPairStringList() + "og list") - prompt = "Sort this list of strings by shared content " + this.childPairStringList() - } - + gptGroups = new Map + + // Method to convert the GPT-produced string into a map + processGptOutput(gptOutput: string) { + + // Split the string into individual list items + const listItems = gptOutput.split('======').filter(item => item.trim() !== ''); + + listItems.forEach((item, index) => { + // Split the item by '~~~~~~' to get all descriptors + const parts = item.split('~~~~~~').map(part => part.trim()); + + parts.forEach(part => { + console.log(part + "part") + // Find the corresponding Doc in the textToDoc map + if (this.textToDoc.has(part)) { + const doc = this.textToDoc.get(part); + console.log("hewoooooo") + if (doc) { + console.log('hi') + this.gptGroups.set(doc, index); + } + } + }); + }); + } - let res = await gptAPICall(prompt, GPTCallType.SORT); - this.isLoading = false; - if (res == 'Error connecting with API.') { - // If GPT call failed - console.error('GPT call failed'); - } else if (res != null) { - console.log(res) - } - this.isLoading = false; - }; + renderButtons(childPairIndex: number) { const buttons = []; // Array to hold the button elements -- cgit v1.2.3-70-g09d2 From 10ae244338383662992350b2b6f6ef80106558c3 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Fri, 17 May 2024 14:28:09 -0400 Subject: yay git add -A --- .../views/collections/CollectionCardDeckView.tsx | 52 +++++++- src/client/views/pdf/GPTPopup/GPTPopup.scss | 33 +++++ src/client/views/pdf/GPTPopup/GPTPopup.tsx | 138 ++++++++++++++++++++- 3 files changed, 215 insertions(+), 8 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index e64c013f1..e96fbc161 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -21,7 +21,9 @@ import { List } from '../../../fields/List'; import { gptAPICall, gptImageLabel } from '../../apis/gpt/GPT'; import { GPTCallType } from '../../apis/gpt/GPT'; import { ImageField, PdfField, URLField } from '../../../fields/URLField'; - +import { GPTPopup } from '../pdf/GPTPopup/GPTPopup'; +import { GPTPopupMode } from '../pdf/GPTPopup/GPTPopup'; +import { reaction } from 'mobx'; @observer export class CollectionCardView extends CollectionSubView() { @@ -88,6 +90,15 @@ export class CollectionCardView extends CollectionSubView() { if (this._props.Document.customHashMap != undefined){ this.customGroupDictionary = this.getCustoms(StrListCast(this._props.Document.customHashMap)) } + + reaction( + () => this._props.Document.cardSort, + (cardSort) => { + if (cardSort === 'chat') { + this.openChatPopup(); + } + } + ); } @observable customGroupDictionary: Map[] = [new Map(), new Map(), new Map()]; @@ -230,10 +241,18 @@ export class CollectionCardView extends CollectionSubView() { @computed get sortedDocsType() { - if (this._props.Document.cardSort === 'chat' && this.sortedDocs.length === 0) { - this.smartSort(); // Trigger the sorting if it hasn't been done yet - return { docs: [] }; // Return an empty array or a loading state - } + // if (this._props.Document.cardSort === 'chat'){ + // this.openChatPopup() + // const textDesc = await this.childPairStringList(); + // GPTPopup.Instance.setSortDesc(textDesc) + // } + + // if (this._props.Document.cardSort === 'chat' && this.sortedDocs.length === 0) { + + // this.smartSort(); // Trigger the sorting if it hasn't been done yet + // return { docs: [] }; // Return an empty array or a loading state + // } + const desc = BoolCast(this.layoutDoc.sortDesc); let sorted = []; @@ -253,7 +272,7 @@ export class CollectionCardView extends CollectionSubView() { case 'custom': return this.sort(sorted, 'custom', desc); case 'chat': - return { docs: this.sortedDocs }; // Use the sorted docs from the observable + return { docs: this.sortedDocs || this.myChildLayoutPairs}; // Use the sorted docs from the observable default: docs = this.myChildLayoutPairs; return { docs }; @@ -656,6 +675,25 @@ export class CollectionCardView extends CollectionSubView() { }); } + @observable isChatPopupOpen = false; + + @action openChatPopup = async () => { + this.isChatPopupOpen = true; + GPTPopup.Instance.setVisible(true); + GPTPopup.Instance.setMode(GPTPopupMode.SORT); + + // Await the promise to get the string result + const sortDesc = await this.childPairStringList(); + GPTPopup.Instance.setSortDesc(sortDesc); + GPTPopup.Instance.onSortComplete = this.handleGptSortResult; +}; + @action handleGptSortResult = (sortResult: string) => { + this.processGptOutput(sortResult); + this.sortedDocs = this.sort(this.myChildLayoutPairs, 'gpt', BoolCast(this.layoutDoc.sortDesc)).docs; + }; + + + renderButtons(childPairIndex: number) { @@ -708,6 +746,8 @@ export class CollectionCardView extends CollectionSubView() { // } // } + + render() { return (
{ private done: boolean = false; @action public setDone = (done: boolean) => { + console.log("HIIIIIIIII") this.done = done; this.chatMode = false; }; + @observable + private sortDone: boolean = false // this is so redundant but the og done variable was causing weird unknown problems and im just a girl + + @action + public setSortDone = (done: boolean) => { + console.log("HIIIIIIIII") + this.sortDone = done; + }; + + // change what can be a ref into a ref @observable private sidebarId: string = ''; @@ -120,9 +132,61 @@ export class GPTPopup extends ObservableReactComponent { this.textAnchor = anchor; }; + @observable + public sortPrompt: string = ''; + @action + public setSortPrompt = ((e: React.ChangeEvent) => { + this.sortPrompt = e.target.value; + }); + + @observable + public sortText: string = '' + @action + public setSortText = (t: string) => { + this.sortText = t + } + + @observable + public sortDesc: string = '' + + @action public setSortDesc = (t:string) => { + this.sortDesc = t + } + + @observable onSortComplete?: (sortResult: string) => void; + + + + + + public addDoc: (doc: Doc | Doc[], sidebarKey?: string | undefined) => boolean = () => false; public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined; + + generateSort = async () => { + this.setLoading(true); + this.setSortDone(false); + + try { + const res = await gptAPICall(this.sortPrompt + this.sortDesc, GPTCallType.SORT); + this.setSortText(res || 'Something went wrong :('); + + // Trigger the callback with the result + if (this.onSortComplete) { + this.onSortComplete(res || 'Something went wrong :('); + } + } catch (err) { + console.error(err); + this.setSortText('Something went wrong :('); + } + + this.setLoading(false); + this.setSortDone(true); + } + + + /** * Generates a Dalle image and uploads it to the server. */ @@ -243,6 +307,74 @@ export class GPTPopup extends ObservableReactComponent { } }; + sortBox = () => ( + <> +
+ {this.heading("SORTING")} + {this.loading ? ( +
+
+ + Loading... +
+
+ ) : !this.sortDone && ( +
+ { + if (e.key === 'Enter') { + this.generateSort(); + } + e.stopPropagation(); + }} + type="text" + placeholder="Enter sorting instructions..." + id="search-input" + className="searchBox-input" + style={{ width: "100%" }} + /> +
+ )} + + {this.sortDone && ( +
+
+ +

{this.text== "Something went wrong :(" ? "Something went wrong :(" : "Sorting done! Feel free to move things around / regenerate :) !"}

+ + + this.setSortDone(false)} + icon={} + color={StrCast(Doc.UserDoc().userVariantColor)} + /> + +
+
+ )} +
+ + ); + + + + +// <> +//
+// )} + imageBox = () => { return (
@@ -396,8 +528,10 @@ 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.SUMMARY ? this.summaryBox() : + this.mode === GPTPopupMode.DATA ? this.dataAnalysisBox() : + this.mode === GPTPopupMode.IMAGE ? this.imageBox() : + this.mode === GPTPopupMode.SORT ? this.sortBox() : <>}
); } } -- cgit v1.2.3-70-g09d2 From 6c7615110dcf8334196bbfddfd89b684e4ceee4f Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Fri, 17 May 2024 21:30:02 -0400 Subject: GOD IS GOOD --- src/client/apis/gpt/GPT.ts | 2 +- src/client/documents/Documents.ts | 2 + src/client/util/CurrentUserUtils.ts | 29 ++- .../views/collections/CollectionCardDeckView.tsx | 231 +++++++++++++-------- src/client/views/global/globalScripts.ts | 153 ++++++++++---- src/client/views/pdf/GPTPopup/GPTPopup.scss | 6 +- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 102 +++++---- 7 files changed, 343 insertions(+), 182 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 9a24c808c..398f8ae39 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -20,7 +20,7 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { summary: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Summarize this text in simpler terms: ' }, edit: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Reword this: ' }, completion: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: '' }, - sort:{model:'gpt-4o',maxTokens:2048,temp:0.5,prompt:"I'm going to give you a list of descriptions. Each one is seperated by ====== on either side. They will vary in length, so make sure to only seperate when you see ======. Sort them into lists by shared content. MAKE SURE EACH DESCRIPTOR IS IN ONLY ONE LIST. Generate only the list with each list seperated by ====== with the elements seperated by ~~~~~~"}, + sort:{model:'gpt-4o',maxTokens:2048,temp:0.5,prompt:"I'm going to give you a list of descriptions. Each one is seperated by ====== on either side. They will vary in length, so make sure to only seperate when you see ======. Sort them into lists by shared content. MAKE SURE EACH DESCRIPTOR IS IN ONLY ONE LIST. Generate only the list with each list seperated by ====== with the elements seperated by ~~~~~~. Try to do around 4 groups, but a little more or less is ok."}, describe:{model:'gpt-4-vision-preview',maxTokens:2048,temp:0,prompt:"Describe these images in 3-5 words"}, diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 57f91399a..eded2b485 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -502,6 +502,8 @@ export class DocumentOptions { cardSort?: STRt = new StrInfo('way cards are sorted in deck view'); customSortNumber?: NUMt = new NumInfo('number of custom sorts the user has created'); customHashMap?: List + visibleGroupNumbers?: List + // card_sort_time?: BOOLt = new BoolInfo('whether sorting cards in deck view by time'); // card_sort_type?: BOOLt = new BoolInfo('whether sorting cards in deck view by type'); // card_sort_color?: BOOLt = new BoolInfo('whether sorting cards in deck view by color'); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index e18c22bac..251771e8e 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -729,18 +729,34 @@ 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: "Links", icon:"link", toolTip:"Sort by its links", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"links", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Create", icon:"heart", toolTip:"Create your first custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom1", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Create", icon:"star", toolTip:"Create your second custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom2", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Create", icon:"satellite", toolTip:"Create your third custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom3", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, - { title: "Create", icon:"robot", toolTip:"Have ChatGPT sort your text-based nodes !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Smart Sort", icon:"robot", toolTip:"Have ChatGPT sort your text-based nodes !", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"chat", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + ] + } + static customCardTools(): Button[] { + return [ + { title: "Create", icon:"heart", toolTip:"Create your first custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom1", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Create", icon:"star", toolTip:"Create your second custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom2", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Create", icon:"satellite", toolTip:"Create your third custom grouping!", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"custom3", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "Custom 1", icon: "Custom 1", width: 10, toolTip: "Set visibilty!", subMenu: CurrentUserUtils.cardGroupTools("heart"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!isThatCardGroup(0)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available + { title: "Custom 2", icon: "Custom 2", width: 80, toolTip: "Set visibilty!", subMenu: CurrentUserUtils.cardGroupTools("star"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!isThatCardGroup(1)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available + { title: "Custom 3", icon: "Custom 3", width: 80, toolTip: "Set visibilty!", subMenu: CurrentUserUtils.cardGroupTools("satellite"), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!isThatCardGroup(2)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available + ] + } - // ...customs + static cardGroupTools(icon: string): Button[] { + return [ + { title: "", icon:icon, toolTip:"Click to toggle visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"1", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "", icon:icon, toolTip:"Click to toggle visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"2", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "", icon:icon, toolTip:"Click to toggle visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"3", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, + { title: "", icon:icon, toolTip:"Click to toggle visibility", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"4", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, ] } + + + static viewTools(): Button[] { return [ { title: "Snap", icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform @@ -842,6 +858,7 @@ pie title Minerals in my tap water { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Stack", icon: "View", toolTip: "Stacking tools", subMenu: CurrentUserUtils.stackTools(), expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Card", icon: "Sort", toolTip: "Card sort", subMenu: CurrentUserUtils.cardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available + { title: "CustomCard", icon: "Create", toolTip: "Create custom groupings!", subMenu: CurrentUserUtils.customCardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Always available { title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_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: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_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: `!SelectionManager_selectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectionManager_selectedDocType(this.toolType, this.expertMode)`} }, // Only when image is selected diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index e96fbc161..42c82ca74 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -24,6 +24,7 @@ import { ImageField, PdfField, URLField } from '../../../fields/URLField'; import { GPTPopup } from '../pdf/GPTPopup/GPTPopup'; import { GPTPopupMode } from '../pdf/GPTPopup/GPTPopup'; import { reaction } from 'mobx'; +import { NumListCast } from '../../../fields/Doc'; @observer export class CollectionCardView extends CollectionSubView() { @@ -32,8 +33,42 @@ export class CollectionCardView extends CollectionSubView() { // documents themselves @observable hoveredNodeIndex = -1; + //index to group + @observable customGroupDictionary: Map[] = [new Map(), new Map(), new Map()]; + @computed get myChildLayoutPairs() { + let activeGroups = NumListCast(this._props.Document.visibleGroupNumbers); + let currCustom = NumCast(this._props.Document.customSortNumber); + + // console.log("Active Groups:", activeGroups); + + for (let i=0; i< activeGroups.length; i++){ + console.log("Active Groups" + activeGroups[i]) + } + // console.log("Current Custom Sort Number:", currCustom); + + if (activeGroups.length <= 0) { + return this.childLayoutPairs.filter(l => l.layout.type != DocumentType.LINK); + } + + if (StrCast(this._props.Document.cardSort).includes("custom")) { + return this.childLayoutPairs.filter((l, index) => { + if (l.layout.type === DocumentType.LINK) { + return false; + } + + // Get the group number for the current index from the customGroupDictionary + const groupNumber = this.customGroupDictionary[currCustom].get(index); + + // console.log(`Index: ${index}, Group Number: ${groupNumber}`); + + // Check if the group number is in the active groups + return groupNumber !== undefined && activeGroups.includes(groupNumber); + }); + } + + // Default return for non-custom cardSort or other cases, filtering out links return this.childLayoutPairs.filter(l => l.layout.type != DocumentType.LINK); } @@ -90,6 +125,9 @@ export class CollectionCardView extends CollectionSubView() { if (this._props.Document.customHashMap != undefined){ this.customGroupDictionary = this.getCustoms(StrListCast(this._props.Document.customHashMap)) } + // this._props.Document.visibleGroupNumbers = new List([1,2,3,4]) + + reaction( () => this._props.Document.cardSort, @@ -101,7 +139,6 @@ export class CollectionCardView extends CollectionSubView() { ); } - @observable customGroupDictionary: Map[] = [new Map(), new Map(), new Map()]; @computed get mapToField(): List { const resultList = new List(); @@ -272,7 +309,8 @@ export class CollectionCardView extends CollectionSubView() { case 'custom': return this.sort(sorted, 'custom', desc); case 'chat': - return { docs: this.sortedDocs || this.myChildLayoutPairs}; // Use the sorted docs from the observable + return this.sort(this.myChildLayoutPairs, 'gpt', BoolCast(this.layoutDoc.sortDesc)); + default: docs = this.myChildLayoutPairs; return { docs }; @@ -458,7 +496,8 @@ export class CollectionCardView extends CollectionSubView() { // const childPair = { layout: doc, data: doc }; const isHovered = this.hoveredNodeIndex === index; - const childPairIndex = this.myChildLayoutPairs.indexOf(childPair); + // const childPairIndex = this.myChildLayoutPairs.indexOf(childPair); + const childPairIndex = this.childLayoutPairs.filter(d => d.layout.type != DocumentType.LINK).indexOf(childPair) const realIndex = this.sortedDocsType.docs.filter(d => !SelectionManager.IsSelected(d.layout)).indexOf(childPair); const calcRowIndex = this.overflowIndexCalc(realIndex); @@ -501,6 +540,8 @@ export class CollectionCardView extends CollectionSubView() { {this.displayDoc(childPair, childScreenToLocal)} {this._props.Document.cardSort == 'custom' ? this.renderButtons(childPairIndex) : ''} + {this._props.Document.cardSort == 'chat' ? this.renderButtons(childPairIndex, childPair.layout, true) : ''} + ); }); @@ -512,38 +553,23 @@ export class CollectionCardView extends CollectionSubView() { - @action toggleButton(childPairIndex: number, buttonID: number) { - this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].set(childPairIndex, buttonID); - this._props.Document.customHashMap = this.mapToField - - // Cast(selected.Document.data, WebField, null)?.url?.href) - - //note richtext - - // StrCast(selected.Document.data, Cast(selected.Document.data, WebField, null)?.url?.href) - - - - // const - const imgurlperchance = Cast(this.childDocs[1].data, ImageField, null)?.url.href; - const perchance = this.imageUrlToBase64(imgurlperchance) - // const imgurlperchance = Cast(this.childDocs[1].data, PdfField, null)?.url.; - - - // console.log('Print Front of cards: ' + RTFCast(DocCast(this.dataDoc[this.fieldKey + '_0']).text)?.Text); - // console.log('Print Back of cards: ' + RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text); - - // const perchance = StrCast(this.childDocs[0].text); - - - - // const pdf = (StrCast(this.myChildLayoutPairs[0].layout.text)); //pdf - const queryText = this.myChildLayoutPairs[0].layout.type; //everything else - - // const queryText = RTFCast(DocCast(this.dataDoc[this.fieldKey + '_1']).text)?.Text; - - console.log(queryText ?? "sad") + @action toggleButton(childPairIndex: number, buttonID: number, isChat = false, doc?: Doc) { + if (!isChat) { + this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].set(childPairIndex, buttonID); + this._props.Document.customHashMap = this.mapToField; + } + + if (isChat && doc) { + this.gptGroups.set(doc, buttonID); + } + + // console.log(`Toggled button for childPairIndex: ${childPairIndex}, buttonID: ${buttonID}, isChat: ${isChat}`); + // console.log(`Updated customGroupDictionary:`, this.customGroupDictionary); + if (isChat && doc) { + console.log(`Updated gptGroups for doc ${doc}:`, this.gptGroups.get(doc)); + } } + async childPairStringList(): Promise { let string = ""; @@ -598,20 +624,25 @@ export class CollectionCardView extends CollectionSubView() { textToDoc = new Map() gptProccessedImages = new Set() - @action async getImageDesc(image: Doc){ - let href = (image['data'] as URLField).url.href; - let hrefParts = href.split('.'); - let hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`; - try { - let hrefBase64 = await this.imageUrlToBase64(hrefComplete); - let response = await gptImageLabel(hrefBase64); - this.textToDoc.set(response.trim(), image); - this.gptProccessedImages.add(image); - console.log(response); - return response; // Return the response from gptImageLabel - } catch (error) { - console.log("bad things have happened"); - } + @action async getImageDesc(image: Doc) { + if (this.gptProccessedImages.has(image)) { + // Return the already processed description + return Array.from(this.textToDoc.keys()).find(key => this.textToDoc.get(key) === image) || ''; + } + + let href = (image['data'] as URLField).url.href; + let hrefParts = href.split('.'); + let hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`; + try { + let hrefBase64 = await this.imageUrlToBase64(hrefComplete); + let response = await gptImageLabel(hrefBase64); + this.textToDoc.set(response.trim(), image); + this.gptProccessedImages.add(image); + console.log(response); + return response; // Return the response from gptImageLabel + } catch (error) { + console.log("bad things have happened"); + } } @@ -620,41 +651,43 @@ export class CollectionCardView extends CollectionSubView() { //a map from the text to the Doc (for everything) - @action async smartSort() { - this.isLoading = true; - console.log("loading"); + // @action async smartSort() { + // this.isLoading = true; + // console.log("loading"); - // Store the result of childPairStringList in a variable - const childPairStrings = await this.childPairStringList(); + // // Store the result of childPairStringList in a variable + // const childPairStrings = await this.childPairStringList(); - if (childPairStrings === "") { - console.log("no child pairs :("); - } else { - console.log(childPairStrings + " og list"); - let prompt = childPairStrings; + // if (childPairStrings === "") { + // console.log("no child pairs :("); + // } else { + // console.log(childPairStrings + " og list"); + // let prompt = childPairStrings; - let res = await gptAPICall(prompt, GPTCallType.SORT); - this.isLoading = false; - if (res == 'Error connecting with API.') { - // If GPT call failed - console.error('GPT call failed'); - } else if (res != null) { - console.log(res); - this.processGptOutput(res); - // Update the observable with the sorted documents - this.sortedDocs = this.sort(this.myChildLayoutPairs, 'gpt', BoolCast(this.layoutDoc.sortDesc)).docs; - } - this.isLoading = false; - } - } + // let res = await gptAPICall(prompt, GPTCallType.SORT); + // this.isLoading = false; + // if (res == 'Error connecting with API.') { + // // If GPT call failed + // console.error('GPT call failed'); + // } else if (res != null) { + // console.log(res); + // this.processGptOutput(res); + // // Update the observable with the sorted documents + // this.sortedDocs = this.sort(this.myChildLayoutPairs, 'gpt', BoolCast(this.layoutDoc.sortDesc)).docs; + // } + // this.isLoading = false; + // } + // } - gptGroups = new Map + gptGroups = new ObservableMap + @observable amGPTGroups = 0 // Method to convert the GPT-produced string into a map processGptOutput(gptOutput: string) { // Split the string into individual list items const listItems = gptOutput.split('======').filter(item => item.trim() !== ''); + this.amGPTGroups = listItems.length listItems.forEach((item, index) => { // Split the item by '~~~~~~' to get all descriptors @@ -678,14 +711,15 @@ export class CollectionCardView extends CollectionSubView() { @observable isChatPopupOpen = false; @action openChatPopup = async () => { - this.isChatPopupOpen = true; - GPTPopup.Instance.setVisible(true); - GPTPopup.Instance.setMode(GPTPopupMode.SORT); - - // Await the promise to get the string result - const sortDesc = await this.childPairStringList(); - GPTPopup.Instance.setSortDesc(sortDesc); - GPTPopup.Instance.onSortComplete = this.handleGptSortResult; + this.isChatPopupOpen = true; + GPTPopup.Instance.setVisible(true); + GPTPopup.Instance.setMode(GPTPopupMode.SORT); + + // Await the promise to get the string result + const sortDesc = await this.childPairStringList(); + GPTPopup.Instance.setCardsDoneLoading(true); // Set dataDoneLoading to true after data is loaded + GPTPopup.Instance.setSortDesc(sortDesc); + GPTPopup.Instance.onSortComplete = this.handleGptSortResult; }; @action handleGptSortResult = (sortResult: string) => { this.processGptOutput(sortResult); @@ -696,19 +730,34 @@ export class CollectionCardView extends CollectionSubView() { - renderButtons(childPairIndex: number) { + renderButtons(childPairIndex: number, doc?: Doc, isChat = false) { const buttons = []; // Array to hold the button elements - - let amButtons = 4; - - let activeButtonIndex = this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].get(childPairIndex); - + const groupNumber = NumCast(this._props.Document.customSortNumber); + + let amButtons = 4; // Adjusted to your context + let activeButtonIndex = this.customGroupDictionary[groupNumber].get(childPairIndex); + + if (isChat && doc) { + if (this.amGPTGroups > 4){ + amButtons = this.amGPTGroups; + } + activeButtonIndex = this.gptGroups.get(doc); + } + + console.log("childPairIndex:", childPairIndex, "activeButtonIndex:", activeButtonIndex, "groupNumber:", groupNumber); + for (let i = 0; i < amButtons; i++) { - const isActive = activeButtonIndex == i; - - buttons.push(); + const isActive = activeButtonIndex === i; + console.log(`Rendering button ${i} for childPairIndex ${childPairIndex} isActive: ${isActive}`); + buttons.push( + + ); } - + const totalWidth = amButtons * 35 + amButtons * 2 * 5 + 6; return (
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 14f83beb6..496d7482c 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -22,7 +22,8 @@ import { VideoBox } from '../nodes/VideoBox'; import { WebBox } from '../nodes/WebBox'; import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; import { ImageBox } from '../nodes/ImageBox'; - +import { NumListCast } from '../../../fields/Doc'; +import { List } from '../../../fields/List'; ScriptingGlobals.add(function IsNoneSelected() { return SelectionManager.Views.length <= 0; }, 'are no document selected'); @@ -107,84 +108,146 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { -ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom1' | 'custom2' | 'custom3'| 'chat', checkResult?: boolean, persist?: boolean, customNumber?: number) { +ScriptingGlobals.add(function showFreeform( + attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom1' | 'custom2' | 'custom3' | 'chat' | '1' | '2' | '3' | '4', + checkResult?: boolean, + persist?: boolean, + isDoubleClick?: boolean +) { const selected = SelectionManager.Docs.lastElement(); // prettier-ignore - const map: Map<'flashcards' | 'center' |'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom1' | 'custom2' | 'custom3'| 'chat', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc, dv:DocumentView) => void;}> = new Map([ + const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom1' | 'custom2' | 'custom3' | 'chat' | '1' | '2' | '3' | '4', + { + 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,dv:DocumentView) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid, + checkResult: (doc: Doc) => BoolCast(doc?._freeform_backgroundGrid, false), + setDoc: (doc: Doc, dv: DocumentView) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid, }], ['snaplines', { - checkResult: (doc:Doc) => BoolCast(doc?._freeform_snapLines, false), - setDoc: (doc:Doc, dv:DocumentView) => doc._freeform_snapLines = !doc._freeform_snapLines, + checkResult: (doc: Doc) => BoolCast(doc?._freeform_snapLines, false), + setDoc: (doc: Doc, dv: DocumentView) => doc._freeform_snapLines = !doc._freeform_snapLines, }], ['viewAll', { - checkResult: (doc:Doc) => BoolCast(doc?._freeform_fitContentsToBox, false), - setDoc: (doc:Doc,dv:DocumentView) => { + checkResult: (doc: Doc) => BoolCast(doc?._freeform_fitContentsToBox, false), + setDoc: (doc: Doc, dv: DocumentView) => { if (persist) doc._freeform_fitContentsToBox = !doc._freeform_fitContentsToBox; else if (doc._freeform_fitContentsToBox) doc._freeform_fitContentsToBox = undefined; else (dv.ComponentView as CollectionFreeFormView)?.fitContentOnce(); }, }], ['center', { - checkResult: (doc:Doc) => BoolCast(doc?._stacking_alignCenter, false), - setDoc: (doc:Doc,dv:DocumentView) => doc._stacking_alignCenter = !doc._stacking_alignCenter, + checkResult: (doc: Doc) => BoolCast(doc?._stacking_alignCenter, false), + setDoc: (doc: Doc, dv: DocumentView) => 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,dv:DocumentView) => doc._freeform_useClusters = !doc._freeform_useClusters, + waitForRender: true, + checkResult: (doc: Doc) => BoolCast(doc?._freeform_useClusters, false), + setDoc: (doc: Doc, dv: DocumentView) => doc._freeform_useClusters = !doc._freeform_useClusters, }], ['flashcards', { - checkResult: (doc:Doc) => BoolCast(Doc.UserDoc().defaultToFlashcards, false), - setDoc: (doc:Doc,dv:DocumentView) => Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards, + 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), - setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "time", + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "time", + setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "time", }], ['docType', { - checkResult: (doc:Doc) => StrCast(doc?.cardSort), - setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "type", + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "type", + setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "type", }], ['color', { - checkResult: (doc:Doc) => StrCast(doc?.cardSort), - setDoc: (doc:Doc,dv:DocumentView) => 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), - setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "links", + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "links", + setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "links", }], - ['custom1', { - checkResult: (doc:Doc) => StrCast(doc?.cardSort), - setDoc: (doc, dv) => { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && NumCast(doc?.customSortNumber) === 0, + setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; doc.customSortNumber = 0; + doc.visibleGroupNumbers = new List(); } - }], - + }], ['custom2', { - checkResult: (doc:Doc) => StrCast(doc?.cardSort), - setDoc: (doc, dv) => { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && NumCast(doc?.customSortNumber) === 1, + setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; doc.customSortNumber = 1; - console.log(doc.customSortNumber + " numberrrrrrrr") - } }], - + doc.visibleGroupNumbers = new List(); + } + }], ['custom3', { - checkResult: (doc:Doc) => StrCast(doc?.cardSort), - setDoc: (doc, dv) => { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && NumCast(doc?.customSortNumber) === 2, + setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; doc.customSortNumber = 2; - } }], + doc.visibleGroupNumbers = new List(); + } + }], ['chat', { - checkResult: (doc:Doc) => StrCast(doc?.cardSort), - setDoc: (doc:Doc,dv:DocumentView) => doc.cardSort = "chat", + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "chat", + setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "chat", + }], + ['1', { + checkResult: (doc: Doc) => NumListCast(doc?.visibleGroupNumbers).includes(0), + setDoc: (doc: Doc, dv: DocumentView) => { + let list = NumListCast(doc.visibleGroupNumbers); + if (list.includes(0)) { + let newList = new List(list.filter(d => d !== 0)); + doc.visibleGroupNumbers = newList; + } else { + list.push(0); + doc.visibleGroupNumbers = new List(list); + } + } }], - ]); + ['2', { + checkResult: (doc: Doc) => NumListCast(doc?.visibleGroupNumbers).includes(1), + setDoc: (doc: Doc, dv: DocumentView) => { + let list = NumListCast(doc.visibleGroupNumbers); + if (list.includes(1)) { + let newList = new List(list.filter(d => d !== 1)); + doc.visibleGroupNumbers = newList; + } else { + list.push(1); + doc.visibleGroupNumbers = new List(list); + } + } + }], + ['3', { + checkResult: (doc: Doc) => NumListCast(doc?.visibleGroupNumbers).includes(2), + setDoc: (doc: Doc, dv: DocumentView) => { + let list = NumListCast(doc.visibleGroupNumbers); + if (list.includes(2)) { + let newList = new List(list.filter(d => d !== 2)); + doc.visibleGroupNumbers = newList; + } else { + list.push(2); + doc.visibleGroupNumbers = new List(list); + } + } + }], + ['4', { + checkResult: (doc: Doc) => NumListCast(doc?.visibleGroupNumbers).includes(3), + setDoc: (doc: Doc, dv: DocumentView) => { + let list = NumListCast(doc.visibleGroupNumbers); + if (list.includes(3)) { + let newList = new List(list.filter(d => d !== 3)); + doc.visibleGroupNumbers = newList; + } else { + list.push(3); + doc.visibleGroupNumbers = new List(list); + } + } + }], + ]); if (checkResult) { return map.get(attr)?.checkResult(selected); @@ -194,6 +257,14 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'center' | 'grid setTimeout(() => batch.end(), 100); }); + +ScriptingGlobals.add(function isThatCardGroup(n: number){ + const canvas = SelectionManager.Docs.lastElement(); + return canvas.customSortNumber == n + + +}) + // ScriptingGlobals.add(function setCardSortAttr(attr: 'time' | 'docType' | 'color', value: any, checkResult?: boolean) { // // const editorView = RichTextMenu.Instance?.TextView?.EditorView; // const selected = SelectionManager.Docs.lastElement(); diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss index 4425cf158..551c8e5af 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.scss +++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss @@ -55,10 +55,10 @@ $highlightedText: #82e0ff; overflow-y: auto; } - .btns-wrapper { + .btns-wrapper-gpt { height: 50px; display: flex; - justify-content: space-between; + justify-content: center; align-items: center; transform: translateY(30px); @@ -76,6 +76,8 @@ $highlightedText: #82e0ff; display: flex; align-items: center; } + + } button { diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index faf66af85..d94be1860 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -154,6 +154,13 @@ export class GPTPopup extends ObservableReactComponent { } @observable onSortComplete?: (sortResult: string) => void; + @observable cardsDoneLoading = false; + + @action setCardsDoneLoading(done: boolean) { + console.log(done + "HI HIHI") + this.cardsDoneLoading = done; + } + @@ -169,12 +176,14 @@ export class GPTPopup extends ObservableReactComponent { this.setSortDone(false); try { - const res = await gptAPICall(this.sortPrompt + this.sortDesc, GPTCallType.SORT); + + const res = await gptAPICall(this.sortDesc, GPTCallType.SORT); this.setSortText(res || 'Something went wrong :('); // Trigger the callback with the result if (this.onSortComplete) { this.onSortComplete(res || 'Something went wrong :('); + console.log(res) } } catch (err) { console.error(err); @@ -313,52 +322,63 @@ export class GPTPopup extends ObservableReactComponent { {this.heading("SORTING")} {this.loading ? (
-
- - Loading... -
-
- ) : !this.sortDone && ( -
- { - if (e.key === 'Enter') { - this.generateSort(); - } - e.stopPropagation(); - }} - type="text" - placeholder="Enter sorting instructions..." - id="search-input" - className="searchBox-input" - style={{ width: "100%" }} - /> +
+ + Loading...
- )} +
+ ) : ( + <> + {!this.cardsDoneLoading ? ( +
+
+ + Reading Cards... +
+
+ ) : ( + !this.sortDone && ( +
+
+ ) + )} - {this.sortDone && ( -
-
- -

{this.text== "Something went wrong :(" ? "Something went wrong :(" : "Sorting done! Feel free to move things around / regenerate :) !"}

- - - this.setSortDone(false)} - icon={} - color={StrCast(Doc.UserDoc().userVariantColor)} - /> - -
-
+ {this.sortDone && ( +
+
+

+ {this.text === "Something went wrong :(" ? + "Something went wrong :(" : + "Sorting done! Feel free to move things around / regenerate :) !"} +

+ this.setSortDone(false)} + icon={} + color={StrCast(Doc.UserDoc().userVariantColor)} + /> +
+
+ )} + )}
); + -- cgit v1.2.3-70-g09d2 From 0b32642fc9c2d33810252cd90e45b8b505ef49b2 Mon Sep 17 00:00:00 2001 From: aidahosa1 Date: Sat, 18 May 2024 00:16:31 -0400 Subject: done :) --- src/client/documents/Documents.ts | 14 +- .../views/collections/CollectionCardDeckView.tsx | 188 +++++++++++---------- 2 files changed, 112 insertions(+), 90 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index eded2b485..80774f4ad 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -501,8 +501,20 @@ export class DocumentOptions { cardSort?: STRt = new StrInfo('way cards are sorted in deck view'); customSortNumber?: NUMt = new NumInfo('number of custom sorts the user has created'); - customHashMap?: List + // customGroup1?: List + // customGroup2?: List + // customGroup3?: List visibleGroupNumbers?: List + custom1Group?: NUMt = new NumInfo('Which group a card is in for the 1st custom grouping'); + custom2Group?: NUMt = new NumInfo('Which group a card is in for the 2nd custom grouping'); + custom3Group?: NUMt = new NumInfo('Which group a card is in for the 3rd custom grouping'); + chatGroup?: NUMt = new NumInfo("Which group a card is in for the chat's grouping"); + chatAmGroups?: NUMt = new NumInfo("Number of cards created by chat sort"); + + + + + // card_sort_time?: BOOLt = new BoolInfo('whether sorting cards in deck view by time'); // card_sort_type?: BOOLt = new BoolInfo('whether sorting cards in deck view by type'); diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 42c82ca74..c719c9e19 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -33,7 +33,8 @@ export class CollectionCardView extends CollectionSubView() { // documents themselves @observable hoveredNodeIndex = -1; - //index to group + + //key is the index in the child pair list, value is the id# for the group its in @observable customGroupDictionary: Map[] = [new Map(), new Map(), new Map()]; @@ -43,9 +44,9 @@ export class CollectionCardView extends CollectionSubView() { // console.log("Active Groups:", activeGroups); - for (let i=0; i< activeGroups.length; i++){ - console.log("Active Groups" + activeGroups[i]) - } + // for (let i=0; i< activeGroups.length; i++){ + // console.log("Active Groups" + activeGroups[i]) + // } // console.log("Current Custom Sort Number:", currCustom); if (activeGroups.length <= 0) { @@ -121,10 +122,32 @@ export class CollectionCardView extends CollectionSubView() { super(props); makeObservable(this); // this.rotationDegree(7); + const pairs = this.childLayoutPairs.filter(d => d.layout.type != DocumentType.LINK); + - if (this._props.Document.customHashMap != undefined){ - this.customGroupDictionary = this.getCustoms(StrListCast(this._props.Document.customHashMap)) + for (let i=0; i< pairs.length; i++){ + if (pairs[i].layout.custom1Group != undefined){ + this.customGroupDictionary[0].set(i, NumCast(pairs[i].layout.custom1Group)) + } + + if (pairs[i].layout.custom2Group != undefined){ + this.customGroupDictionary[1].set(i, NumCast(pairs[i].layout.custom2Group)) + } + + if (pairs[i].layout.custom3Group != undefined){ + this.customGroupDictionary[2].set(i, NumCast(pairs[i].layout.custom3Group)) + } + + if (pairs[i].layout.chatGroup != undefined){ + this.gptGroups.set(pairs[i].layout, NumCast(pairs[i].layout.chatGroup)) + this.amGPTGroups = NumCast(this._props.Document.chatAmGroups) + + } } + + // if (this._props.Document.customHashMap != undefined){ + // this.customGroupDictionary = this.convertListsToArrayOfMaps(DocListCast(this._props.Document.customGroup1),DocListCast(this._props.Document.customGroup2), DocListCast(this._props.Document.customGroup3)) + // } // this._props.Document.visibleGroupNumbers = new List([1,2,3,4]) @@ -139,32 +162,52 @@ export class CollectionCardView extends CollectionSubView() { ); } + //converts the customGroupDictionary into a Lists of Docs + mapToField(groupNumber: number) { + const groupList = new List(); + + const pairs = this.childLayoutPairs.filter(d => d.layout.type != DocumentType.LINK); + console.log(groupNumber+ "group#") + + this.customGroupDictionary[groupNumber].forEach((group, index) => { + const doc = pairs[index].layout; + groupList.push(doc); + }); + + this._props.Document[`group${groupNumber}`] = groupList; + } - @computed get mapToField(): List { - const resultList = new List(); - - this.customGroupDictionary.forEach(map => { - // Convert each map to a single string with entries formatted as "key:value" - const mapString = Array.from(map.entries()) - .map(([key, value]) => `${key}:${value}`) - .join(','); // Join all key-value pairs with commas - resultList.push(mapString); // Add the formatted string of the current map to the list + // This function converts three Lists of Docs back into an array of maps + convertListsToArrayOfMaps = (group0: Doc[], group1: Doc[], group2: Doc[]): Map[] => { + const mapsArray: Map[] = [ + new Map(), + new Map(), + new Map() + ]; + const layoutPairs = this.childLayoutPairs.filter(d => d.layout.type != DocumentType.LINK) + + group0.forEach((doc, index) => { + const docIndex = layoutPairs.findIndex(pair => pair.layout === doc); + if (docIndex !== -1) { + mapsArray[0].set(docIndex, 0); + } }); - return resultList; - } + group1.forEach((doc, index) => { + const docIndex = layoutPairs.findIndex(pair => pair.layout === doc); + if (docIndex !== -1) { + mapsArray[1].set(docIndex, 1); + } + }); - getCustoms = (stringFrom: string[]): Map[] => { - return stringFrom.map(s => { - // Create a new Map object for each string. - const map = new Map(); - // Split the string by commas to get key-value pairs, then process each pair. - s.split(',').forEach(pair => { - const [key, value] = pair.split(':'); - map.set(Number(key), Number(value)); - }); - return map; + group2.forEach((doc, index) => { + const docIndex = layoutPairs.findIndex(pair => pair.layout === doc); + if (docIndex !== -1) { + mapsArray[2].set(docIndex, 2); + } }); + + return mapsArray; } @@ -278,17 +321,6 @@ export class CollectionCardView extends CollectionSubView() { @computed get sortedDocsType() { - // if (this._props.Document.cardSort === 'chat'){ - // this.openChatPopup() - // const textDesc = await this.childPairStringList(); - // GPTPopup.Instance.setSortDesc(textDesc) - // } - - // if (this._props.Document.cardSort === 'chat' && this.sortedDocs.length === 0) { - - // this.smartSort(); // Trigger the sorting if it hasn't been done yet - // return { docs: [] }; // Return an empty array or a loading state - // } const desc = BoolCast(this.layoutDoc.sortDesc); @@ -374,9 +406,9 @@ export class CollectionCardView extends CollectionSubView() { // console.log(this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)]) typeA = this.gptGroups.get(docA.layout) ?? '9999'; - console.log(typeA + "typea") + // console.log(typeA + "typea") typeB = this.gptGroups.get(docB.layout) ?? '9999'; - console.log(typeB + "typeB") + // console.log(typeB + "typeB") // console.log(typeA + "A") @@ -539,35 +571,45 @@ export class CollectionCardView extends CollectionSubView() { onMouseEnter={() => this.setHoveredNodeIndex(index)}> {this.displayDoc(childPair, childScreenToLocal)} - {this._props.Document.cardSort == 'custom' ? this.renderButtons(childPairIndex) : ''} + {this._props.Document.cardSort == 'custom' ? this.renderButtons(childPairIndex, childPair.layout, false) : ''} {this._props.Document.cardSort == 'chat' ? this.renderButtons(childPairIndex, childPair.layout, true) : ''} ); }); } + - - - - - - - @action toggleButton(childPairIndex: number, buttonID: number, isChat = false, doc?: Doc) { + @action toggleButton(childPairIndex: number, buttonID: number, isChat = false, doc: Doc) { if (!isChat) { - this.customGroupDictionary[NumCast(this._props.Document.customSortNumber)].set(childPairIndex, buttonID); - this._props.Document.customHashMap = this.mapToField; + const sortNumber = NumCast(this._props.Document.customSortNumber) + this.customGroupDictionary[sortNumber].set(childPairIndex, buttonID) + switch (sortNumber){ + case 0: + doc.custom1Group = buttonID + break + case 1: + doc.custom2Group = buttonID + break + case 2: + doc.custom3Group = buttonID + break + default: + break + } + // this.mapToField(buttonID); } if (isChat && doc) { this.gptGroups.set(doc, buttonID); + doc.chatGroup = buttonID } // console.log(`Toggled button for childPairIndex: ${childPairIndex}, buttonID: ${buttonID}, isChat: ${isChat}`); // console.log(`Updated customGroupDictionary:`, this.customGroupDictionary); - if (isChat && doc) { - console.log(`Updated gptGroups for doc ${doc}:`, this.gptGroups.get(doc)); - } + // if (isChat && doc) { + // // console.log(`Updated gptGroups for doc ${doc}:`, this.gptGroups.get(doc)); + // } } @@ -645,39 +687,6 @@ export class CollectionCardView extends CollectionSubView() { } } - - - //a set of all the images that have already been given desc - //a map from the text to the Doc (for everything) - - - // @action async smartSort() { - // this.isLoading = true; - // console.log("loading"); - - // // Store the result of childPairStringList in a variable - // const childPairStrings = await this.childPairStringList(); - - // if (childPairStrings === "") { - // console.log("no child pairs :("); - // } else { - // console.log(childPairStrings + " og list"); - // let prompt = childPairStrings; - - // let res = await gptAPICall(prompt, GPTCallType.SORT); - // this.isLoading = false; - // if (res == 'Error connecting with API.') { - // // If GPT call failed - // console.error('GPT call failed'); - // } else if (res != null) { - // console.log(res); - // this.processGptOutput(res); - // // Update the observable with the sorted documents - // this.sortedDocs = this.sort(this.myChildLayoutPairs, 'gpt', BoolCast(this.layoutDoc.sortDesc)).docs; - // } - // this.isLoading = false; - // } - // } gptGroups = new ObservableMap @observable amGPTGroups = 0 @@ -688,6 +697,7 @@ export class CollectionCardView extends CollectionSubView() { // Split the string into individual list items const listItems = gptOutput.split('======').filter(item => item.trim() !== ''); this.amGPTGroups = listItems.length + this._props.Document.chatAmGroups = this.amGPTGroups listItems.forEach((item, index) => { // Split the item by '~~~~~~' to get all descriptors @@ -730,7 +740,7 @@ export class CollectionCardView extends CollectionSubView() { - renderButtons(childPairIndex: number, doc?: Doc, isChat = false) { + renderButtons(childPairIndex: number, doc: Doc, isChat = false) { const buttons = []; // Array to hold the button elements const groupNumber = NumCast(this._props.Document.customSortNumber); @@ -744,11 +754,11 @@ export class CollectionCardView extends CollectionSubView() { activeButtonIndex = this.gptGroups.get(doc); } - console.log("childPairIndex:", childPairIndex, "activeButtonIndex:", activeButtonIndex, "groupNumber:", groupNumber); + // console.log("childPairIndex:", childPairIndex, "activeButtonIndex:", activeButtonIndex, "groupNumber:", groupNumber); for (let i = 0; i < amButtons; i++) { const isActive = activeButtonIndex === i; - console.log(`Rendering button ${i} for childPairIndex ${childPairIndex} isActive: ${isActive}`); + // console.log(`Rendering button ${i} for childPairIndex ${childPairIndex} isActive: ${isActive}`); buttons.push( - ); - } - + renderButtons = (doc: Doc, cardSort: cardSortings) => { + if (cardSort !== cardSortings.Custom) return ''; + const amButtons = Math.max(4, this.childDocs?.reduce((set, doc) => this.customSortField && set.add(NumCast(doc[this.customSortField])), new Set()).size ?? 0); + const activeButtonIndex = CollectionCardView.getButtonGroup(this.customSortField, doc); const totalWidth = amButtons * 35 + amButtons * 2 * 5 + 6; return (
- {buttons} + {numberRange(amButtons).map(i => ( +
); - } - - getButtonGroup(groupNumber: number, doc: Doc, isChat?: boolean) { - if (isChat){ - return NumCast(doc.chatGroup) - } - switch (groupNumber){ - case 0: - return NumCast(doc.custom1Group) - case 1: - return NumCast(doc.custom2Group) - case 2: - return NumCast(doc.custom3Group) - default: - break - } - - - } - + }; + /** + * Actually renders all the cards + */ + renderCards = () => { + const anySelected = this.childDocs.some(doc => SelectionManager.IsSelected(doc)); + // Map sorted documents to their rendered components + return this.sortedDocs.map((doc, index) => { + const realIndex = this.sortedDocs.filter(sortDoc => !SelectionManager.IsSelected(sortDoc)).indexOf(doc); + const calcRowIndex = this.overflowIndexCalc(realIndex); + const amCards = this.overflowAmCardsCalc(realIndex); + const isSelected = SelectionManager.IsSelected(doc); - @computed get translateWrapperX() { - let translate = 0; + const childScreenToLocal = () => { + this._forceChildXf; + const dref = this._docRefs.get(doc); + const { translateX, translateY, scale } = Utils.GetScreenTransform(dref?.ContentDiv); + return new Transform(-translateX + (dref?.centeringX || 0) * scale, + -translateY + (dref?.centeringY || 0) * scale, 1) + .scale(1 / scale).rotate(!isSelected ? -this.rotate(amCards, calcRowIndex) : 0); // prettier-ignore + }; - if (this.inactiveDocs().length != this.myChildLayoutPairs.length && this.inactiveDocs().length < 10) { - translate += this.panelWidth() / 2; - } - return translate; - } + return ( +
{ + // this turns off documentDecorations during a transition, then turns them back on afterward. + SnappingManager.SetIsResizing(this.Document); + setTimeout( + action(() => { + SnappingManager.SetIsResizing(undefined); + this._forceChildXf = !this._forceChildXf; + }), + 700 + ); + }} + style={{ + width: this.panelWidth(), + height: 'max-content', // this.panelHeight(childPair.layout)(), + transform: `translateY(${this.calculateTranslateY(this._hoveredNodeIndex === index, isSelected, realIndex, amCards, calcRowIndex)}px) + translateX(${isSelected ? this.translateSelected(calcRowIndex) : this.translateOverflowX(realIndex, amCards)}px) + rotate(${!isSelected ? this.rotate(amCards, calcRowIndex) : 0}deg) + scale(${isSelected ? 1.25 : 1})`, + }} + onMouseEnter={() => this.setHoveredNodeIndex(index)}> + {this.displayDoc(doc, childScreenToLocal)} + {this.renderButtons(doc, this.cardSort)} +
+ ); + }); + }; render() { return (
this.setHoveredNodeIndex(-1)}> - {this.contentSorted} + {this.renderCards()}
); diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 496d7482c..35a3a2e31 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -1,7 +1,7 @@ import { Colors } from 'browndash-components'; import { action, runInAction } from 'mobx'; import { aggregateBounds } from '../../../Utils'; -import { Doc, Opt } from '../../../fields/Doc'; +import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { InkTool } from '../../../fields/InkField'; import { BoolCast, Cast, NumCast, StrCast } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; @@ -106,17 +106,15 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) { selected ? selected.CollectionFreeFormDocumentView?.float() : console.log('[FontIconBox.tsx] toggleOverlay failed'); }); - - ScriptingGlobals.add(function showFreeform( - attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom1' | 'custom2' | 'custom3' | 'chat' | '1' | '2' | '3' | '4', + attr: 'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'like' | 'star' | 'idea' | 'chat' | '1' | '2' | '3' | '4', checkResult?: boolean, persist?: boolean, isDoubleClick?: boolean ) { const selected = SelectionManager.Docs.lastElement(); // prettier-ignore - const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'custom1' | 'custom2' | 'custom3' | 'chat' | '1' | '2' | '3' | '4', + 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; @@ -167,87 +165,48 @@ ScriptingGlobals.add(function showFreeform( checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "links", setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "links", }], - ['custom1', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && NumCast(doc?.customSortNumber) === 0, + ['like', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.customSortField) === "like", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; - doc.customSortNumber = 0; + doc.customSortField = "like"; doc.visibleGroupNumbers = new List(); } }], - ['custom2', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && NumCast(doc?.customSortNumber) === 1, + ['star', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.customSortField) === "star", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; - doc.customSortNumber = 1; + doc.customSortField = "star"; doc.visibleGroupNumbers = new List(); } }], - ['custom3', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && NumCast(doc?.customSortNumber) === 2, + ['idea', { + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.customSortField) === "idea", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; - doc.customSortNumber = 2; + doc.customSortField = "idea"; doc.visibleGroupNumbers = new List(); } }], ['chat', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "chat", - setDoc: (doc: Doc, dv: DocumentView) => doc.cardSort = "chat", - }], - ['1', { - checkResult: (doc: Doc) => NumListCast(doc?.visibleGroupNumbers).includes(0), - setDoc: (doc: Doc, dv: DocumentView) => { - let list = NumListCast(doc.visibleGroupNumbers); - if (list.includes(0)) { - let newList = new List(list.filter(d => d !== 0)); - doc.visibleGroupNumbers = newList; - } else { - list.push(0); - doc.visibleGroupNumbers = new List(list); - } - } - }], - ['2', { - checkResult: (doc: Doc) => NumListCast(doc?.visibleGroupNumbers).includes(1), - setDoc: (doc: Doc, dv: DocumentView) => { - let list = NumListCast(doc.visibleGroupNumbers); - if (list.includes(1)) { - let newList = new List(list.filter(d => d !== 1)); - doc.visibleGroupNumbers = newList; - } else { - list.push(1); - doc.visibleGroupNumbers = new List(list); - } - } - }], - ['3', { - checkResult: (doc: Doc) => NumListCast(doc?.visibleGroupNumbers).includes(2), - setDoc: (doc: Doc, dv: DocumentView) => { - let list = NumListCast(doc.visibleGroupNumbers); - if (list.includes(2)) { - let newList = new List(list.filter(d => d !== 2)); - doc.visibleGroupNumbers = newList; - } else { - list.push(2); - doc.visibleGroupNumbers = new List(list); - } - } - }], - ['4', { - checkResult: (doc: Doc) => NumListCast(doc?.visibleGroupNumbers).includes(3), + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.customSortField) === "chat", setDoc: (doc: Doc, dv: DocumentView) => { - let list = NumListCast(doc.visibleGroupNumbers); - if (list.includes(3)) { - let newList = new List(list.filter(d => d !== 3)); - doc.visibleGroupNumbers = newList; - } else { - list.push(3); - doc.visibleGroupNumbers = new List(list); - } - } + doc.cardSort = "custom"; + doc.customSortField = "chat"; + doc.visibleGroupNumbers = new List(); + }, }], ]); + for (let i = 0; i < 8; i++) { + map.set((i + 1 + '') as any, { + checkResult: (doc: Doc) => NumListCast(doc?.visibleGroupNumbers).includes(i), + setDoc: (doc: Doc, dv: DocumentView) => { + const list = NumListCast(doc.visibleGroupNumbers); + doc.visibleGroupNumbers = new List(list.includes(i) ? list.filter(d => d !== i) : [...list, i]); + }, + }); + } if (checkResult) { return map.get(attr)?.checkResult(selected); @@ -257,13 +216,11 @@ ScriptingGlobals.add(function showFreeform( setTimeout(() => batch.end(), 100); }); - -ScriptingGlobals.add(function isThatCardGroup(n: number){ - const canvas = SelectionManager.Docs.lastElement(); - return canvas.customSortNumber == n - - -}) +ScriptingGlobals.add(function cardHasLabel(label: string) { + const selected = SelectionManager.Docs.lastElement(); + const labelNum = Number(label) - 1; + return labelNum < 4 || (selected && DocListCast(selected[Doc.LayoutFieldKey(selected)]).some(doc => doc[StrCast(selected.customSortField)] == labelNum)); +}, ''); // ScriptingGlobals.add(function setCardSortAttr(attr: 'time' | 'docType' | 'color', value: any, checkResult?: boolean) { // // const editorView = RichTextMenu.Instance?.TextView?.EditorView; -- cgit v1.2.3-70-g09d2 From 9badfc489f00afd10489f0dde0a3b9e21817feb5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 18 May 2024 23:15:49 -0400 Subject: more cardView cleanup --- src/Utils.ts | 1 - src/client/apis/gpt/GPT.ts | 22 ++-- src/client/documents/Documents.ts | 65 +---------- src/client/util/SelectionManager.ts | 1 - src/client/views/DocComponent.tsx | 2 +- .../views/collections/CollectionCardDeckView.tsx | 20 ++-- src/client/views/collections/CollectionMenu.tsx | 2 - src/client/views/collections/CollectionView.tsx | 2 - .../CollectionFreeFormLayoutEngines.tsx | 26 ----- .../collectionFreeForm/CollectionFreeFormView.tsx | 8 +- .../collections/collectionFreeForm/MarqueeView.tsx | 19 +--- .../collectionSchema/CollectionSchemaView.tsx | 2 +- src/client/views/global/globalScripts.ts | 32 +++--- src/client/views/nodes/PDFBox.tsx | 3 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 7 +- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 126 +++++++++------------ 16 files changed, 105 insertions(+), 233 deletions(-) (limited to 'src/client/views/collections/CollectionCardDeckView.tsx') diff --git a/src/Utils.ts b/src/Utils.ts index fb72a5836..291d7c799 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -179,7 +179,6 @@ export namespace Utils { export function toRGBAstr(col: { r: number; g: number; b: number; a?: number }) { return 'rgba(' + col.r + ',' + col.g + ',' + col.b + (col.a !== undefined ? ',' + col.a : '') + ')'; } - export function HSLtoRGB(h: number, s: number, l: number) { // Must be fractions of 1 diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts index 398f8ae39..3b3b3b9a0 100644 --- a/src/client/apis/gpt/GPT.ts +++ b/src/client/apis/gpt/GPT.ts @@ -6,7 +6,7 @@ enum GPTCallType { COMPLETION = 'completion', EDIT = 'edit', SORT = 'sort', - DESCRIBE = 'describe' + DESCRIBE = 'describe', } type GPTCallOpts = { @@ -20,13 +20,15 @@ const callTypeMap: { [type: string]: GPTCallOpts } = { summary: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Summarize this text in simpler terms: ' }, edit: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: 'Reword this: ' }, completion: { model: 'gpt-3.5-turbo-instruct', maxTokens: 256, temp: 0.5, prompt: '' }, - sort:{model:'gpt-4o',maxTokens:2048,temp:0.5,prompt:"I'm going to give you a list of descriptions. Each one is seperated by ====== on either side. They will vary in length, so make sure to only seperate when you see ======. Sort them into lists by shared content. MAKE SURE EACH DESCRIPTOR IS IN ONLY ONE LIST. Generate only the list with each list seperated by ====== with the elements seperated by ~~~~~~. Try to do around 4 groups, but a little more or less is ok."}, - describe:{model:'gpt-4-vision-preview',maxTokens:2048,temp:0,prompt:"Describe these images in 3-5 words"}, - - + sort: { + model: 'gpt-4o', + maxTokens: 2048, + temp: 0.5, + prompt: "I'm going to give you a list of descriptions. Each one is seperated by ====== on either side. They will vary in length, so make sure to only seperate when you see ======. Sort them into lists by shared content. MAKE SURE EACH DESCRIPTOR IS IN ONLY ONE LIST. Generate only the list with each list seperated by ====== with the elements seperated by ~~~~~~. Try to do around 4 groups, but a little more or less is ok.", + }, + describe: { model: 'gpt-4-vision-preview', maxTokens: 2048, temp: 0, prompt: 'Describe these images in 3-5 words' }, }; - /**` * Calls the OpenAI API. * @@ -39,7 +41,7 @@ const gptAPICall = async (inputText: string, callType: GPTCallType) => { const opts: GPTCallOpts = callTypeMap[callType]; try { const configuration: ClientOptions = { - apiKey: "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", + apiKey: process.env.OPENAI_KEY, dangerouslyAllowBrowser: true, }; const openai = new OpenAI(configuration); @@ -63,11 +65,10 @@ const gptAPICall = async (inputText: string, callType: GPTCallType) => { } }; - const gptImageLabel = async (imgUrl: string): Promise => { try { const configuration: ClientOptions = { - apiKey: "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", + apiKey: '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', dangerouslyAllowBrowser: true, }; @@ -100,7 +101,6 @@ const gptImageLabel = async (imgUrl: string): Promise => { } }; - const gptImageCall = async (prompt: string, n?: number) => { try { const configuration: ClientOptions = { @@ -122,4 +122,4 @@ const gptImageCall = async (prompt: string, n?: number) => { } }; -export { gptAPICall, gptImageCall, gptImageLabel, GPTCallType }; \ No newline at end of file +export { gptAPICall, gptImageCall, gptImageLabel, GPTCallType }; diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 80774f4ad..903bd907a 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -500,27 +500,8 @@ 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'); - customSortNumber?: NUMt = new NumInfo('number of custom sorts the user has created'); - // customGroup1?: List - // customGroup2?: List - // customGroup3?: List - visibleGroupNumbers?: List - custom1Group?: NUMt = new NumInfo('Which group a card is in for the 1st custom grouping'); - custom2Group?: NUMt = new NumInfo('Which group a card is in for the 2nd custom grouping'); - custom3Group?: NUMt = new NumInfo('Which group a card is in for the 3rd custom grouping'); - chatGroup?: NUMt = new NumInfo("Which group a card is in for the chat's grouping"); - chatAmGroups?: NUMt = new NumInfo("Number of cards created by chat sort"); - - - - - - - // card_sort_time?: BOOLt = new BoolInfo('whether sorting cards in deck view by time'); - // card_sort_type?: BOOLt = new BoolInfo('whether sorting cards in deck view by type'); - // card_sort_color?: BOOLt = new BoolInfo('whether sorting cards in deck view by color'); - - + cardSort_customField?: STRt = new StrInfo('field key used for sorting cards'); + cardSort_visibleSortGroups?: List; // which sorting values are being filtered (shown) } export const DocOptions = new DocumentOptions(); @@ -1239,8 +1220,6 @@ export namespace Docs { ); } - - export function LinearDocument(documents: Array, options: DocumentOptions, id?: string) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _type_collection: CollectionViewType.Linear }, id); } @@ -1258,7 +1237,7 @@ export namespace Docs { } export function CardDeckDocument(documents: Array, options: DocumentOptions, id?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _type_collection: CollectionViewType.Card}); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _type_collection: CollectionViewType.Card }); } export function SchemaDocument(schemaHeaders: SchemaHeaderField[], documents: Array, options: DocumentOptions) { @@ -1911,44 +1890,6 @@ export namespace DocUtils { } } - export function spreadCards(docList: Doc[], x: number = 0, y: number = 0, spreadAngle: number = 30, radius: number = 100, create: boolean = true) { - console.log('spread cards'); - const totalCards = docList.length; - const halfSpreadAngle = spreadAngle * 0.5; - const angleStep = spreadAngle / (totalCards - 1); - - runInAction(() => { - docList.forEach((d, i) => { - DocUtils.iconify(d); - const angle = (-halfSpreadAngle + angleStep * i) * (Math.PI / 180); // Convert degrees to radians - d.x = x + Math.cos(angle) * radius; - d.y = y + Math.sin(angle) * radius; - d.rotation = angle; - d._timecodeToShow = undefined; - }); - }); - - if (create) { - const newCollection = Docs.Create.CardDeckDocument(docList, { - title: 'card-spread', - _freeform_noZoom: true, - x: x - radius, - y: y - radius, - _width: radius * 2, - _height: radius * 2, - dragWhenActive: true, - _layout_fitWidth: false - }); - // Adjust position based on the collection's dimensions if needed - newCollection.x = NumCast(newCollection.x) + NumCast(newCollection._width) / 2 - radius; - newCollection.y = NumCast(newCollection.y) + NumCast(newCollection._height) / 2 - radius; - newCollection._width = newCollection._height = radius * 2; - return newCollection; - } - } - - - export function makeIntoPortal(doc: Doc, layoutDoc: Doc, allLinks: Doc[]) { const portalLink = allLinks.find(d => d.link_anchor_1 === doc && d.link_relationship === 'portal to:portal from'); if (!portalLink) { diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index d507e35ad..36b926053 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -68,7 +68,6 @@ export class SelectionManager { public static IsSelected = (doc?: Doc) => Array.from(doc?.[DocViews] ?? []).some(dv => dv?.IsSelected); public static get Views() { return this.Instance.SelectedViews; } // prettier-ignore public static get SelectedSchemaDoc() { return this.Instance.SelectedSchemaDocument; } // prettier-ignore - public static get Docs() { return this.Instance.SelectedViews.map(dv => dv.Document).filter(doc => doc?._type_collection !== CollectionViewType.Docking); } // prettier-ignore } diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index ef4257937..de4df1830 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -35,7 +35,7 @@ export interface ViewBoxInterface { addDocument?: (doc: Doc | Doc[], annotationKey?: string) => boolean; // add a document (used only by collections) removeDocument?: (doc: Doc | Doc[], annotationKey?: string, leavePushpin?: boolean, dontAddToRemoved?: boolean) => boolean; // add a document (used only by collections) select?: (ctrlKey: boolean, shiftKey: boolean) => void; - focus?: (textAnchor: Doc, options: FocusViewOptions) => Opt; + focus?: (textAnchor: Doc, options: FocusViewOptions) => Opt; viewTransition?: () => Opt; // duration of a view transition animation isAnyChildContentActive?: () => boolean; // is any child content of the document active onClickScriptDisable?: () => 'never' | 'always'; // disable click scripts : never, always, or undefined = only when selected diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx index 9e5668ffa..5f8ddd5c1 100644 --- a/src/client/views/collections/CollectionCardDeckView.tsx +++ b/src/client/views/collections/CollectionCardDeckView.tsx @@ -75,7 +75,7 @@ export class CollectionCardView extends CollectionSubView() { componentDidMount(): void { this._disposers.sort = reaction( - () => ({ cardSort: this.cardSort, field: this.customSortField }), + () => ({ cardSort: this.cardSort, field: this.cardSort_customField }), ({ cardSort, field }) => (cardSort === cardSortings.Custom && field === 'chat' ? this.openChatPopup() : GPTPopup.Instance.setVisible(false)) ); } @@ -85,8 +85,8 @@ export class CollectionCardView extends CollectionSubView() { this._dropDisposer?.(); } - @computed get customSortField() { - return StrCast(this.Document.customSortField) as any as 'chat' | 'star' | 'idea' | 'like'; + @computed get cardSort_customField() { + return StrCast(this.Document.cardSort_customField) as any as 'chat' | 'star' | 'idea' | 'like'; } @computed get cardSort() { @@ -115,12 +115,12 @@ export class CollectionCardView extends CollectionSubView() { */ @computed get childDocsWithoutLinks() { const regularDocs = this.childDocs.filter(l => l.type !== DocumentType.LINK); - const activeGroups = NumListCast(this.Document.visibleGroupNumbers); + const activeGroups = NumListCast(this.Document.cardSort_visibleSortGroups); if (activeGroups.length > 0 && this.cardSort === cardSortings.Custom) { return regularDocs.filter(doc => { // Get the group number for the current index - const groupNumber = CollectionCardView.getButtonGroup(this.customSortField, doc); + const groupNumber = CollectionCardView.getButtonGroup(this.cardSort_customField, doc); // Check if the group number is in the active groups return groupNumber !== undefined && activeGroups.includes(groupNumber); }); @@ -245,8 +245,8 @@ export class CollectionCardView extends CollectionSubView() { return [DashColor(StrCast(docA.backgroundColor)).hsv().toString(), // If docA.type is undefined, use an empty string DashColor(StrCast(docB.backgroundColor)).hsv().toString()]; // If docB.type is undefined, use an empty string case cardSortings.Custom: - return [CollectionCardView.getButtonGroup(this.customSortField, docA)??0, - CollectionCardView.getButtonGroup(this.customSortField, docB)??0]; + return [CollectionCardView.getButtonGroup(this.cardSort_customField, docA)??0, + CollectionCardView.getButtonGroup(this.cardSort_customField, docB)??0]; 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 @@ -335,7 +335,7 @@ export class CollectionCardView extends CollectionSubView() { * @param buttonID * @param doc */ - toggleButton = undoable((buttonID: number, doc: Doc) => this.customSortField && (doc[this.customSortField] = buttonID), 'toggle custom button'); + toggleButton = undoable((buttonID: number, doc: Doc) => 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. @@ -422,8 +422,8 @@ export class CollectionCardView extends CollectionSubView() { */ renderButtons = (doc: Doc, cardSort: cardSortings) => { if (cardSort !== cardSortings.Custom) return ''; - const amButtons = Math.max(4, this.childDocs?.reduce((set, doc) => this.customSortField && set.add(NumCast(doc[this.customSortField])), new Set()).size ?? 0); - const activeButtonIndex = CollectionCardView.getButtonGroup(this.customSortField, doc); + const amButtons = Math.max(4, this.childDocs?.reduce((set, doc) => this.cardSort_customField && set.add(NumCast(doc[this.cardSort_customField])), new Set()).size ?? 0); + const activeButtonIndex = CollectionCardView.getButtonGroup(this.cardSort_customField, doc); const totalWidth = amButtons * 35 + amButtons * 2 * 5 + 6; return (
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 81d9f4eea..94896f277 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -321,8 +321,6 @@ export class CollectionViewBaseChrome extends React.Component(); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index b7805bf3f..97a0b7bef 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -137,8 +137,6 @@ export class CollectionView extends ViewBoxAnnotatableComponent; case CollectionViewType.Grid: return ; case CollectionViewType.Card: return ; - - } }; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx index 22005eb23..c83c26509 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx @@ -125,32 +125,6 @@ export function computeStarburstLayout(poolData: Map, pivotDoc return normalizeResults(burstDiam, 12, docMap, poolData, viewDefsToJSX, [], 0, [divider]); } -// export function computeCardDeckLayout(poolData: Map, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], engineProps: any) { -// const docMap = new Map(); -// const burstDiam = [NumCast(pivotDoc._width), NumCast(pivotDoc._height)]; -// const burstScale = NumCast(pivotDoc._starburstDocScale, 1); - -// childPairs.forEach(({ layout, data }, i) => { -// const aspect = NumCast(layout._height) / NumCast(layout._width); -// const docSize = Math.min(Math.min(400, NumCast(layout._width)), Math.min(400, NumCast(layout._width)) / aspect) * burstScale; -// const deg = (i / childPairs.length) * Math.PI * 2; -// docMap.set(layout[Id], { -// x: Math.min(burstDiam[0] / 2 - docSize, Math.max(-burstDiam[0] / 2, (Math.cos(deg) * burstDiam[0]) / 2 - docSize / 2)), -// y: Math.min(burstDiam[1] / 2 - docSize * aspect, Math.max(-burstDiam[1] / 2, (Math.sin(deg) * burstDiam[1]) / 2 - (docSize / 2) * aspect)), -// width: docSize, -// height: docSize * aspect, -// zIndex: NumCast(layout.zIndex), -// pair: { layout, data }, -// replica: '', -// color: 'white', -// backgroundColor: 'white', -// transition: 'all 0.3s', -// }); -// }); -// const divider = { type: 'div', color: 'transparent', x: -burstDiam[0] / 2, y: -burstDiam[1] / 2, width: 15, height: 15, payload: undefined }; -// return normalizeResults(burstDiam, 12, docMap, poolData, viewDefsToJSX, [], 0, [divider]); -// } - export function computePivotLayout(poolData: Map, pivotDoc: Doc, childPairs: { layout: Doc; data?: Doc }[], panelDim: number[], viewDefsToJSX: (views: ViewDefBounds[]) => ViewDefResult[], engineProps: any) { const docMap = new Map(); const fieldKey = 'data'; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 11193f496..079a5d977 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -49,9 +49,7 @@ import { CollectionSubView } from '../CollectionSubView'; import { TreeViewType } from '../CollectionTreeView'; import { CollectionFreeFormBackgroundGrid } from './CollectionFreeFormBackgroundGrid'; import { CollectionFreeFormInfoUI } from './CollectionFreeFormInfoUI'; -import { computePassLayout, computePivotLayout, computeStarburstLayout, computeTimelineLayout, PoolData, ViewDefBounds, ViewDefResult, - // computeCardDeckLayout - } from './CollectionFreeFormLayoutEngines'; +import { computePassLayout, computePivotLayout, computeStarburstLayout, computeTimelineLayout, PoolData, ViewDefBounds, ViewDefResult } from './CollectionFreeFormLayoutEngines'; import { CollectionFreeFormPannableContents } from './CollectionFreeFormPannableContents'; import { CollectionFreeFormRemoteCursors } from './CollectionFreeFormRemoteCursors'; import './CollectionFreeFormView.scss'; @@ -1385,8 +1383,6 @@ export class CollectionFreeFormView extends CollectionSubView { - // const selected = this.marqueeSelect(false); - // SelectionManager.DeselectAll(); - // selected.forEach(d => this._props.removeDocument?.(d)); - // const newCollection = DocUtils.spreadCards(selected, this.Bounds.left + this.Bounds.width / 2, this.Bounds.top + this.Bounds.height / 2)!; - // this._props.addDocument?.(newCollection); - // this._props.selectDocuments([newCollection]); - // MarqueeOptionsMenu.Instance.fadeOut(true); - // this.hideMarquee(); - // }); - /** * This triggers the TabDocView.PinDoc method which is the universal method * used to pin documents to the currently active presentation trail. @@ -522,7 +510,6 @@ export class MarqueeView extends ObservableReactComponent { - if (this._commandExecuted || (e as any).propagationIsStopped) { return; } @@ -533,8 +520,7 @@ export class MarqueeView extends ObservableReactComponent doc.cardSort = "links", }], ['like', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.customSortField) === "like", + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "like", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; - doc.customSortField = "like"; - doc.visibleGroupNumbers = new List(); + doc.cardSort_customField = "like"; + doc.cardSort_visibleSortGroups = new List(); } }], ['star', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.customSortField) === "star", + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "star", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; - doc.customSortField = "star"; - doc.visibleGroupNumbers = new List(); + doc.cardSort_customField = "star"; + doc.cardSort_visibleSortGroups = new List(); } }], ['idea', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.customSortField) === "idea", + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "idea", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; - doc.customSortField = "idea"; - doc.visibleGroupNumbers = new List(); + doc.cardSort_customField = "idea"; + doc.cardSort_visibleSortGroups = new List(); } }], ['chat', { - checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.customSortField) === "chat", + checkResult: (doc: Doc) => StrCast(doc?.cardSort) === "custom" && StrCast(doc?.cardSort_customField) === "chat", setDoc: (doc: Doc, dv: DocumentView) => { doc.cardSort = "custom"; - doc.customSortField = "chat"; - doc.visibleGroupNumbers = new List(); + 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?.visibleGroupNumbers).includes(i), + checkResult: (doc: Doc) => NumListCast(doc?.cardSort_visibleSortGroups).includes(i), setDoc: (doc: Doc, dv: DocumentView) => { - const list = NumListCast(doc.visibleGroupNumbers); - doc.visibleGroupNumbers = new List(list.includes(i) ? list.filter(d => d !== i) : [...list, i]); + const list = NumListCast(doc.cardSort_visibleSortGroups); + doc.cardSort_visibleSortGroups = new List(list.includes(i) ? list.filter(d => d !== i) : [...list, i]); }, }); } @@ -219,7 +219,7 @@ ScriptingGlobals.add(function showFreeform( ScriptingGlobals.add(function cardHasLabel(label: string) { const selected = SelectionManager.Docs.lastElement(); const labelNum = Number(label) - 1; - return labelNum < 4 || (selected && DocListCast(selected[Doc.LayoutFieldKey(selected)]).some(doc => doc[StrCast(selected.customSortField)] == labelNum)); + return labelNum < 4 || (selected && DocListCast(selected[Doc.LayoutFieldKey(selected)]).some(doc => doc[StrCast(selected.cardSort_customField)] == labelNum)); }, ''); // ScriptingGlobals.add(function setCardSortAttr(attr: 'time' | 'docType' | 'color', value: any, checkResult?: boolean) { diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 90d6133e4..3e0270aa3 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -29,11 +29,10 @@ import { CreateImage } from '../nodes/WebBoxRenderer'; import { PDFViewer } from '../pdf/PDFViewer'; import { SidebarAnnos } from '../SidebarAnnos'; import { DocumentView, OpenWhere } from './DocumentView'; -import { FocusViewOptions, FieldView, FieldViewProps } from './FieldView'; +import { FieldView, FieldViewProps, FocusViewOptions } from './FieldView'; import { ImageBox } from './ImageBox'; import './PDFBox.scss'; import { PinProps, PresBox } from './trails'; -import { Networking } from '../../Network'; @observer export class PDFBox extends ViewBoxAnnotatableComponent() implements ViewBoxInterface { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index f856d9637..43010b2ed 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -972,8 +972,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent (this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight), icon: this.Document._layout_autoHeight ? 'lock' : 'unlock', }); - optionItems.push({ description: `show markdown options`, event: RTFMarkup.Instance.open, icon: }); - !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'sliders' }); + !options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' }); + const help = cm.findByDescription('Help...'); + const helpItems = help && 'subitems' in help ? help.subitems : []; + helpItems.push({ description: `show markdown options`, event: RTFMarkup.Instance.open, icon: }); + !help && cm.addItem({ description: 'Help...', subitems: helpItems, icon: 'eye' }); this._downX = this._downY = Number.NaN; }; diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index 4fb757d8a..0ba62d60e 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -21,7 +21,7 @@ export enum GPTPopupMode { EDIT, IMAGE, DATA, - SORT + SORT, } interface GPTPopupProps {} @@ -60,7 +60,7 @@ export class GPTPopup extends ObservableReactComponent { public dataChatPrompt: string | null = null; @action public setDataJson = (text: string) => { - if (text=="") this.dataChatPrompt = ""; + if (text == '') this.dataChatPrompt = ''; this.dataJson = text; }; @@ -95,21 +95,18 @@ export class GPTPopup extends ObservableReactComponent { private done: boolean = false; @action public setDone = (done: boolean) => { - console.log("HIIIIIIIII") this.done = done; this.chatMode = false; }; @observable - private sortDone: boolean = false // this is so redundant but the og done variable was causing weird unknown problems and im just a girl + private sortDone: boolean = false; // this is so redundant but the og done variable was causing weird unknown problems and im just a girl @action public setSortDone = (done: boolean) => { - console.log("HIIIIIIIII") this.sortDone = done; }; - // change what can be a ref into a ref @observable private sidebarId: string = ''; @@ -133,26 +130,20 @@ export class GPTPopup extends ObservableReactComponent { }; @observable - public sortDesc: string = '' + public sortDesc: string = ''; - @action public setSortDesc = (t:string) => { - this.sortDesc = t - } + @action public setSortDesc = (t: string) => { + this.sortDesc = t; + }; @observable onSortComplete?: (sortResult: string) => void; @observable cardsDoneLoading = false; @action setCardsDoneLoading(done: boolean) { - console.log(done + "HI HIHI") + console.log(done + 'HI HIHI'); this.cardsDoneLoading = done; } - - - - - - public addDoc: (doc: Doc | Doc[], sidebarKey?: string | undefined) => boolean = () => false; public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined; @@ -164,12 +155,11 @@ export class GPTPopup extends ObservableReactComponent { this.setSortDone(false); try { - const res = await gptAPICall(this.sortDesc, GPTCallType.SORT); // Trigger the callback with the result if (this.onSortComplete) { this.onSortComplete(res || 'Something went wrong :('); - console.log(res) + console.log(res); } } catch (err) { console.error(err); @@ -177,9 +167,7 @@ export class GPTPopup extends ObservableReactComponent { this.setLoading(false); this.setSortDone(true); - } - - + }; /** * Generates a Dalle image and uploads it to the server. @@ -219,7 +207,7 @@ export class GPTPopup extends ObservableReactComponent { console.error(err); } GPTPopup.Instance.setLoading(false); - } + }; generateDataAnalysis = async () => { GPTPopup.Instance.setVisible(true); @@ -231,7 +219,7 @@ export class GPTPopup extends ObservableReactComponent { console.error(err); } GPTPopup.Instance.setLoading(false); - } + }; /** * Transfers the summarization text to a sidebar annotation text document. @@ -282,7 +270,7 @@ export class GPTPopup extends ObservableReactComponent { */ private chatWithAI = () => { this.chatMode = true; - } + }; dataPromptChanged = action((e: React.ChangeEvent) => { this.dataChatPrompt = e.target.value; }); @@ -304,14 +292,14 @@ export class GPTPopup extends ObservableReactComponent { sortBox = () => ( <>
- {this.heading("SORTING")} + {this.heading('SORTING')} {this.loading ? (
-
- - Loading... +
+ + Loading... +
-
) : ( <> {!this.cardsDoneLoading ? ( @@ -334,27 +322,18 @@ export class GPTPopup extends ObservableReactComponent { width: '90%', // Almost as wide as the container textAlign: 'center', color: '#ffffff', // White text - fontSize: '16px' // Adjust font size as needed + fontSize: '16px', // Adjust font size as needed }} />
) )} - + {this.sortDone && (
-

- {this.text === "Something went wrong :(" ? - "Something went wrong :(" : - "Sorting done! Feel free to move things around / regenerate :) !"} -

- this.setSortDone(false)} - icon={} - color={StrCast(Doc.UserDoc().userVariantColor)} - /> +

{this.text === 'Something went wrong :(' ? 'Something went wrong :(' : 'Sorting done! Feel free to move things around / regenerate :) !'}

+ this.setSortDone(false)} icon={} color={StrCast(Doc.UserDoc().userVariantColor)} />
)} @@ -364,21 +343,17 @@ export class GPTPopup extends ObservableReactComponent { ); - - - - -// <> -//
-// )} + // <> + //