Skip to content

Commit

Permalink
fix: outline docs order (#31)
Browse files Browse the repository at this point in the history
* feat: outline api for moving document
* fix: order of sub docs on Outline after imports
  • Loading branch information
hungluu authored Feb 26, 2024
1 parent a175790 commit fb091fe
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 28 deletions.
5 changes: 5 additions & 0 deletions .changeset/pretty-numbers-bow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"coda-mover": patch
---

Fix order of sub docs on Outline after imports
18 changes: 13 additions & 5 deletions src/modules/simple-mover/Mover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,17 +255,17 @@ export class Mover implements IMover {
}

setStatus (id: string, status: IStatus, message?: string) {
const itemId = id.replace('import::', '')
const itemName = this.items[itemId]?.name
const itemId = id.replace(/^.+::/, '') // remove prefixes
const itemName = this.items[itemId]?.name || ''
const itemStatus: IItemStatus = { id, status, message, name: itemName }

this._itemStatuses[id] = itemStatus
if (status === ITEM_STATUS_ERROR) {
log.error(`[mover] ${id} ${itemName}`, status, message)
log.error(`[mover] ${id} ${itemName}`, `[${status}]`, message)
} else if (message) {
log.info(`[mover] ${id} ${itemName}`, status, message)
log.info(`[mover] ${id} ${itemName}`, `[${status}]`, message)
} else {
log.info(`[mover] ${id} ${itemName}`, status)
log.info(`[mover] ${id} ${itemName}`, `[${status}]`)
}

/**
Expand All @@ -292,6 +292,14 @@ export class Mover implements IMover {
return this._itemStatuses[id].status || ''
}

getInnerPages (item: ICodaItem) {
const innerCodaTreePath = `${item.treePath}${item.id}/`

return Object.values(this.items).filter(page => (
page.treePath === innerCodaTreePath
))
}

private cancelExports () {
if (this._exporter) {
log.info('[mover] cancel exports')
Expand Down
5 changes: 5 additions & 0 deletions src/modules/simple-mover/apis/OutlineApis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
IOutlineSearchDocumentResult,
IOutlineDocumentUpdateInput,
IOutlineDocumentCreateInput,
IOutlineDocumentMoveInput,
} from './interfaces'
import { createReadStream, pathExists } from 'fs-extra'
import FormData from 'form-data'
Expand Down Expand Up @@ -97,4 +98,8 @@ export class OutlineApis implements IOutlineApis {

return data.data
}

async moveDocument (input: IOutlineDocumentMoveInput) {
await this.apis.post('/documents.move', input)
}
}
9 changes: 9 additions & 0 deletions src/modules/simple-mover/apis/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ export interface IOutlineDocumentUpdateInput {
title?: string
}

export interface IOutlineDocumentMoveInput {
id: string
collectionId: string
index: number
parentDocumentId?: string
}

export interface IOutlineDocumentTreeItem {
id: string
title: string
Expand All @@ -110,6 +117,7 @@ export interface IOutlineItem {
id: string
name: string
treePath: string
index?: number // index of sub document under parent document
}

export interface IOutlineApis {
Expand All @@ -122,4 +130,5 @@ export interface IOutlineApis {
importDocumentByFile: (collectionId: string, filePath: string, parentDocumentId?: string) => Promise<IOutlineDocument>
updateDocument: (document: IOutlineDocumentUpdateInput) => Promise<IOutlineDocument>
getCollectionTree: (collectionId: string) => Promise<IOutlineDocumentTreeItem[]>
moveDocument: (input: IOutlineDocumentMoveInput) => Promise<void>
}
2 changes: 2 additions & 0 deletions src/modules/simple-mover/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export interface IMover {

saveItems: () => Promise<void>
dispose: () => void

getInnerPages: (item: ICodaItem) => ICodaPage[]
}

export type IStatusUpdateHandler = (itemStatus: IItemStatus) => void
Expand Down
82 changes: 59 additions & 23 deletions src/modules/simple-mover/transfers/OutlineImporter.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { TaskEmitter, TaskPriority } from '@abxvn/tasks'
import {
CLIENT_IMPORT_OUTLINE,
ITEM_STATUS_ARCHIVING,
ITEM_STATUS_CONFIRMING,
ITEM_STATUS_DONE,
ITEM_STATUS_ERROR,
ITEM_STATUS_IMPORTING,
ITEM_STATUS_LISTING,
ITEM_STATUS_PENDING,
ITEM_STATUS_SKIPPED,
ITEM_STATUS_VALIDATING,
ITEM_STATUS_WAITING,
} from '../events'
Expand Down Expand Up @@ -50,6 +48,8 @@ export class OutlineImporter implements IImporter {
private collectionId: string | undefined
private documentTreeItems: IOutlineItem[] = []
private waitingExports: Array<{ id: string, outlineTreePath: string }> = []
// coda id => corresponding outline index (for ordering)
private readonly codaOrderingIndexes: Record<string, number> = {}

constructor (
private readonly mover: IMover,
Expand Down Expand Up @@ -136,8 +136,13 @@ export class OutlineImporter implements IImporter {
private receiveDocumentTreeItems (items: IOutlineDocumentTreeItem[], parentPath = '/') {
if (!items.length) return

items.forEach(item => {
this.documentTreeItems.push({ id: item.id, name: item.title, treePath: parentPath })
items.forEach((item, idx) => {
this.documentTreeItems.push({
id: item.id,
name: item.title,
treePath: parentPath,
index: idx,
})
this.receiveDocumentTreeItems(item.children, `${parentPath}${item.id}/`)
})
}
Expand Down Expand Up @@ -169,13 +174,11 @@ export class OutlineImporter implements IImporter {
this.documentTreeItems.push(docTreeItem)
}

const innerCodaTreePath = `${doc.treePath}${doc.id}/`
const innerOutlineTreePath = `${outlineTreePath}${docTreeItem.id}/`
const innerPages = Object.values(this.mover.items).filter(item => (
item.treePath === innerCodaTreePath
))
const innerPages = this.mover.getInnerPages(doc)

innerPages.forEach(innerPage => {
innerPages.forEach((innerPage, index) => {
this.codaOrderingIndexes[innerPage.id] = index
this.setStatus(innerPage.id, ITEM_STATUS_PENDING)
this.tasks.add({
id: innerPage.id,
Expand Down Expand Up @@ -220,30 +223,26 @@ export class OutlineImporter implements IImporter {

if (!importedPage) throw Error('Failed to import page')

const innerCodaTreePath = `${page.treePath}${page.id}/`
const outlineId = importedPage.id
const innerOutlineTreePath = `${outlineTreePath}${importedPage.id}/`
const innerPages = Object.values(this.mover.items).filter(item => (
item.treePath === innerCodaTreePath
))
const shouldArchiveOutdatedPage = docTreeItem && isPageOutOfSync
const orderingIndex = this.codaOrderingIndexes[page.id]
const shouldFixDocumentOrder = orderingIndex !== undefined && docTreeItem?.index !== orderingIndex
const innerPages = this.mover.getInnerPages(page)

innerPages.forEach(innerPage => {
innerPages.forEach((innerPage, index) => {
this.codaOrderingIndexes[innerPage.id] = index
this.setStatus(innerPage.id, ITEM_STATUS_PENDING)
this.tasks.add({
id: innerPage.id,
execute: async () => await this.importPage(innerPage, innerOutlineTreePath),
})
})

if (docTreeItem && isPageOutOfSync) {
this.setStatus(page.id, ITEM_STATUS_ARCHIVING, `Archiving outdated page ${page.name}`)
await this.archiveOutdatedPage(docTreeItem.id)
}
if (shouldArchiveOutdatedPage) this.queueArchivingOutdatedPage(page.id, docTreeItem.id)
if (shouldFixDocumentOrder) this.queueFixingDocumentOrder(page.id, outlineId, outlineParentId, orderingIndex)

if (isPageOutOfSync) {
this.setStatus(page.id, ITEM_STATUS_DONE, `Imported ${page.name}`)
} else {
this.setStatus(page.id, ITEM_STATUS_SKIPPED, `Skipped ${page.name}`)
}
this.setStatus(page.id, ITEM_STATUS_DONE, isPageOutOfSync ? `Imported ${page.name}` : `Skipped ${page.name}`)
}

async createAndPublishDocIfNotExists (doc: ICodaDoc) {
Expand All @@ -254,6 +253,19 @@ export class OutlineImporter implements IImporter {
})
}

private queueArchivingOutdatedPage (pageId: string, outlineId: string) {
this.tasks.add({
id: `archive::${pageId}`,
priority: TaskPriority.IDLE,
execute: async () => {
await this.archiveOutdatedPage(outlineId)
this.setStatus(`archive::${pageId}`, ITEM_STATUS_DONE)
},
})

this.tasks.next()
}

async archiveOutdatedPage (outlineId: string) {
await this.apis.archiveDocument(outlineId)
}
Expand All @@ -279,6 +291,30 @@ export class OutlineImporter implements IImporter {
return importedPage
}

private queueFixingDocumentOrder (
pageId: string,
documentId: string,
parentDocumentId: string,
orderingIndex: number,
) {
this.tasks.add({
id: `order::${pageId}`,
priority: TaskPriority.IDLE,
execute: async () => {
await this.apis.moveDocument({
id: documentId,
collectionId: this.collectionId!,
parentDocumentId,
index: orderingIndex,
})

this.setStatus(`order::${pageId}`, ITEM_STATUS_DONE)
},
})

this.tasks.next()
}

private setStatus (id: string, status: IStatus, message?: string) {
const itemId = id === CLIENT_IMPORT_OUTLINE ? id : `import::${id}`

Expand Down

0 comments on commit fb091fe

Please sign in to comment.