From a496c583f375fe5e118f786b1244c42bc8a34fec Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 28 Jan 2025 14:20:40 -0500 Subject: fixed flashcard practice mode. moved doc sorting from cardDeck into collectionSubView to apply it to all collections. --- src/client/views/collections/CollectionSubView.tsx | 49 ++++++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) (limited to 'src/client/views/collections/CollectionSubView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 0c059f729..5e99bec39 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -1,7 +1,7 @@ import { action, computed, makeObservable, observable } from 'mobx'; import * as React from 'react'; import * as rp from 'request-promise'; -import { ClientUtils, returnFalse } from '../../../ClientUtils'; +import { ClientUtils, DashColor, returnFalse } from '../../../ClientUtils'; import CursorField from '../../../fields/CursorField'; import { Doc, DocListCast, GetDocFromUrl, GetHrefFromHTML, Opt, RTFIsFragment, StrListCast } from '../../../fields/Doc'; import { AclPrivate, DocData } from '../../../fields/DocSymbols'; @@ -9,7 +9,7 @@ import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { listSpec } from '../../../fields/Schema'; import { ScriptField } from '../../../fields/ScriptField'; -import { BoolCast, Cast, NumCast, ScriptCast, StrCast, toList } from '../../../fields/Types'; +import { BoolCast, Cast, DateCast, NumCast, ScriptCast, StrCast, toList } from '../../../fields/Types'; import { WebField } from '../../../fields/URLField'; import { GetEffectiveAcl, TraceMobx } from '../../../fields/util'; import { GestureUtils } from '../../../pen-gestures/GestureUtils'; @@ -29,6 +29,14 @@ import { DocumentView, DocumentViewProps } from '../nodes/DocumentView'; import { FlashcardPracticeUI } from './FlashcardPracticeUI'; import { OpenWhere, OpenWhereMod } from '../nodes/OpenWhere'; +export enum docSortings { + Time = 'time', + Type = 'type', + Color = 'color', + Chat = 'chat', + Tag = 'tag', + None = '', +} export interface CollectionViewProps extends React.PropsWithChildren { isAnnotationOverlay?: boolean; // is the collection an annotation overlay (eg an overlay on an image/video/etc) isAnnotationOverlayScrollable?: boolean; // whether the annotation overlay can be vertically scrolled (just for tree views, currently) @@ -150,6 +158,8 @@ export function CollectionSubView() { unrecursiveDocFilters = () => [...(this._props.childFilters?.().filter(f => !ClientUtils.IsRecursiveFilter(f)) || [])]; childDocRangeFilters = () => [...(this._props.childFiltersByRanges?.() || []), ...this.collectionRangeDocFilters()]; searchFilterDocs = () => this._props.searchFilterDocs?.() ?? DocListCast(this.Document._searchFilterDocs); + + @observable docDraggedIndex = -1; @computed.struct get childDocs() { TraceMobx(); let rawdocs: (Doc | Promise)[] = []; @@ -166,8 +176,10 @@ export function CollectionSubView() { const templateRoot = this._props.TemplateDataDocument; rawdocs = templateRoot && !this._props.isAnnotationOverlay ? [Doc.GetProto(templateRoot)] : []; } - - const childDocs = rawdocs.filter(d => !(d instanceof Promise) && GetEffectiveAcl(Doc.GetProto(d)) !== AclPrivate && (this._props.ignoreUnrendered || !d.layout_unrendered)).map(d => d as Doc); + const childDocs = this.childSortedDocs( + rawdocs.filter(d => !(d instanceof Promise) && GetEffectiveAcl(Doc.GetProto(d)) !== AclPrivate && (this._props.ignoreUnrendered || !d.layout_unrendered)).map(d => d as Doc), + this.docDraggedIndex + ); const childDocFilters = this.childDocFilters(); const childFiltersByRanges = this.childDocRangeFilters(); @@ -214,6 +226,35 @@ export function CollectionSubView() { return docsforFilter; } + childSortedDocs = (docsIn: Doc[], dragIndex: number) => { + const sortType = StrCast(this.Document[this._props.fieldKey + '_sort']) as docSortings; + const isDesc = BoolCast(this.Document[this._props.fieldKey + '_sort_desc']); + const docs = docsIn.slice(); + if (sortType) { + docs.sort((docA, docB) => { + const [typeA, typeB] = (() => { + switch (sortType) { + default: + case docSortings.Type: return [StrCast(docA.type), StrCast(docB.type)]; + case docSortings.Chat: return [NumCast(docA.chatIndex, 9999), NumCast(docB.chatIndex,9999)]; + case docSortings.Time: return [DateCast(docA.author_date)?.date ?? Date.now(), DateCast(docB.author_date)?.date ?? Date.now()]; + case docSortings.Color:return [DashColor(StrCast(docA.backgroundColor)).hsv().hue(), DashColor(StrCast(docB.backgroundColor)).hsv().hue()]; + case docSortings.Tag: return [StrListCast(docA.tags).join(""), StrListCast(docB.tags).join("")]; + } + })(); //prettier-ignore + return (typeA < typeB ? -1 : typeA > typeB ? 1 : 0) * (isDesc ? 1 : -1); + }); + } + if (dragIndex !== -1) { + const draggedDoc = DragManager.docsBeingDragged[0]; + const originalIndex = docs.findIndex(doc => doc === draggedDoc); + + originalIndex !== -1 && docs.splice(originalIndex, 1); + draggedDoc && docs.splice(dragIndex, 0, draggedDoc); + } + return docs; + }; + @action protected async setCursorPosition(position: [number, number]) { let ind; -- cgit v1.2.3-70-g09d2