From 13449634b4d543e23a7a229a3e570cf6e8977d58 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Tue, 10 Feb 2026 13:57:51 +0100 Subject: [PATCH 1/3] regression: fix loading clashes of 'replace' and 'add-if-missing' load configs --- src/components/EditingOverview/index.tsx | 5 +++-- src/hooks/useDocumentRoot.ts | 8 ++++++++ src/hooks/useFirstMainDocument.ts | 2 +- src/models/Page.ts | 4 +++- src/stores/DocumentRootStore.ts | 8 +++++++- src/stores/PageStore.ts | 10 +++++++--- 6 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/components/EditingOverview/index.tsx b/src/components/EditingOverview/index.tsx index bfdfff1b5..e86b8e78e 100644 --- a/src/components/EditingOverview/index.tsx +++ b/src/components/EditingOverview/index.tsx @@ -62,10 +62,11 @@ const EditingOverview = observer(() => { if (!isBrowser || !currentUser || !currentPage) { return null; } - const taskStates = currentPage.taskableDocuments.filter((ts) => RWAccess.has(ts.root?.permission)) || []; - if (taskStates.length === 0) { + const taskableDocumentsCount = currentPage.taskableDocumentRootIds.length; + if (taskableDocumentsCount === 0) { return null; } + const taskStates = currentPage.taskableDocuments.filter((ts) => RWAccess.has(ts.root?.permission)) || []; const someChecked = taskStates.some((d) => d.isDone); const allChecked = someChecked && taskStates.every((d) => d.isDone); return ( diff --git a/src/hooks/useDocumentRoot.ts b/src/hooks/useDocumentRoot.ts index bbc534076..417f88c63 100644 --- a/src/hooks/useDocumentRoot.ts +++ b/src/hooks/useDocumentRoot.ts @@ -46,6 +46,14 @@ export const useDocumentRoot = ( () => documentRootStore.find(id), (docRoot) => { if (docRoot) { + if (docRoot.isLoadable && !docRoot.isLoaded) { + documentRootStore.loadInNextBatch( + id!, + meta, + { skipCreate: !!skipCreate, documentType: loadOnlyType, documentRoot: 'replace' }, + access + ); + } return; } if (addDummyToStore) { diff --git a/src/hooks/useFirstMainDocument.ts b/src/hooks/useFirstMainDocument.ts index ee0ed3b96..864c21364 100644 --- a/src/hooks/useFirstMainDocument.ts +++ b/src/hooks/useFirstMainDocument.ts @@ -25,7 +25,7 @@ export const useFirstMainDocument = ( loadOnlyType?: DocumentType ) => { const defaultDocId = useDummyId(documentRootId); - const documentRoot = useDocumentRoot(documentRootId, meta, true, access, undefined, loadOnlyType); + const documentRoot = useDocumentRoot(documentRootId, meta, true, access, false, loadOnlyType); const userStore = useStore('userStore'); const documentStore = useStore('documentStore'); const [dummyDocument] = React.useState( diff --git a/src/models/Page.ts b/src/models/Page.ts index 337c2e281..67a476b34 100644 --- a/src/models/Page.ts +++ b/src/models/Page.ts @@ -209,7 +209,9 @@ export default class Page { @computed get stepsOnPage(): number { - return this.taskableDocuments.length; + // use the id's, otherwise not yet created documents would not be counted, + // which leads to wrong progress values until all documents are loaded + return this.taskableDocumentRootIds.length; } @computed diff --git a/src/stores/DocumentRootStore.ts b/src/stores/DocumentRootStore.ts index db56726b8..37364cea7 100644 --- a/src/stores/DocumentRootStore.ts +++ b/src/stores/DocumentRootStore.ts @@ -146,7 +146,13 @@ export class DocumentRootStore extends iStore { accessConfig?: Partial ) { if (this.queued.has(id)) { - return; + const currentConfig = this.queued.get(id); + const needsReplacement = + loadConfig?.documentRoot === 'replace' && currentConfig?.load.documentRoot !== 'replace'; + if (!needsReplacement) { + // already queued with same or higher loadConfig - do nothing + return; + } } this.queued.set(id, { meta: meta, diff --git a/src/stores/PageStore.ts b/src/stores/PageStore.ts index 3841a2df1..e22059407 100644 --- a/src/stores/PageStore.ts +++ b/src/stores/PageStore.ts @@ -22,10 +22,14 @@ export const SidebarVersions = ( ).versions.map((version) => { const versionPath = ensureTrailingSlash(version.path); const slashCount = version.path.split('/').length + 1; - const rdocs = version.docs.filter( - (doc) => + const rdocs = version.docs.filter((doc) => { + if (version.mainDocId === 'index' && doc.id === version.mainDocId) { + return true; + } + return ( doc.path.startsWith(version.path) && doc.path.replace(/\/$/, '').split('/').length === slashCount - ); + ); + }); return { name: version.name, rootPaths: rdocs.map((doc) => ensureTrailingSlash(doc.path)), From 81fe5a3571925c3f36f309bb0df67fae81609639 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Tue, 10 Feb 2026 13:59:22 +0100 Subject: [PATCH 2/3] rm unused import --- src/components/EditingOverview/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/EditingOverview/index.tsx b/src/components/EditingOverview/index.tsx index e86b8e78e..a0cb49ad4 100644 --- a/src/components/EditingOverview/index.tsx +++ b/src/components/EditingOverview/index.tsx @@ -5,7 +5,7 @@ import styles from './styles.module.scss'; import { observer } from 'mobx-react-lite'; import { useStore } from '@tdev-hooks/useStore'; import Button from '@tdev-components/shared/Button'; -import { mdiAccountAlert, mdiAccountSyncOutline, mdiCheckboxMultipleMarkedCircle } from '@mdi/js'; +import { mdiAccountSyncOutline, mdiCheckboxMultipleMarkedCircle } from '@mdi/js'; import { StateType } from '@tdev-api/document'; import Icon from '@mdi/react'; import Popup from 'reactjs-popup'; From d930d89ca411ba9246d8c6623a861a49f7bf0b8d Mon Sep 17 00:00:00 2001 From: bh0fer Date: Tue, 10 Feb 2026 15:27:02 +0100 Subject: [PATCH 3/3] remove unused imports --- packages/tdev/page-read-check/model/index.ts | 2 +- src/stores/PageStore.ts | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/tdev/page-read-check/model/index.ts b/packages/tdev/page-read-check/model/index.ts index a3cb156c6..28cfe61fa 100644 --- a/packages/tdev/page-read-check/model/index.ts +++ b/packages/tdev/page-read-check/model/index.ts @@ -4,7 +4,7 @@ import { iTaskableDocument } from '@tdev-models/iTaskableDocument'; import { Document as DocumentProps, TypeDataMapping, Factory } from '@tdev-api/document'; import DocumentStore from '@tdev-stores/DocumentStore'; import { ModelMeta } from './ModelMeta'; -import { mdiBookCheck, mdiBookCheckOutline, mdiBookEducation, mdiBookOpenVariantOutline } from '@mdi/js'; +import { mdiBookCheck, mdiBookEducation, mdiBookOpenVariantOutline } from '@mdi/js'; import { fSeconds, fSecondsLong } from '../helpers/time'; export const createModel: Factory = (data, store) => { diff --git a/src/stores/PageStore.ts b/src/stores/PageStore.ts index e22059407..468a806c5 100644 --- a/src/stores/PageStore.ts +++ b/src/stores/PageStore.ts @@ -140,14 +140,15 @@ export class PageStore extends iStore { @action setCurrentPath(path: string | undefined) { - if (path === this.currentPath) { + const normalizedPath = path?.replace(BasePathRegex, '/'); + if (normalizedPath === this.currentPath) { return; } - if (!path) { + if (!normalizedPath) { this.currentPath = undefined; return; } - this.currentPath = path.replace(BasePathRegex, '/'); + this.currentPath = normalizedPath; if (this.isPageIndexLoaded) { this.loadTaskableDocuments(this.currentStudentGroupName); }