Skip to content

Commit

Permalink
[base] Optimize and move collate function to draft-utils (#1422)
Browse files Browse the repository at this point in the history
This optimizes how we collate drafts and published into a single entry for display in document lists. Also moved the collate function into the common draftUtils package so that we can re-use it anywhere else it's needed.

The numbers I got when collating a list of 10474 items locally (average of around 10 samples):

*Before*: 142.15 ms
*After*: 18.47 ms
  • Loading branch information
bjoerge authored Aug 1, 2019
1 parent e004b06 commit 4bf926e
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 24 deletions.
22 changes: 13 additions & 9 deletions packages/@sanity/base/src/util/draftUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,19 @@ export function createPublishedFrom(document) {
}
}

// Takes a list of documents and collates draft/published pairs into single entries
// {id: <published id>, draft?: <draft document>, published?: <published document>}
export function collate(documents) {
const byId = documents.reduce((res, doc) => {
const id = getPublishedId(doc._id)
const entry = res[id] || (res[id] = {id})
entry[id === doc._id ? 'published' : 'draft'] = doc
return res
}, Object.create(null))
return Object.values(byId)
}

// Removes published documents that also has a draft
export function removeDupes(documents) {
const drafts = documents.map(doc => doc._id).filter(isDraftId)

return documents.filter(doc => {
const draftId = getDraftId(doc._id)
const publishedId = getPublishedId(doc._id)
const hasDraft = drafts.includes(draftId)
const isPublished = doc._id === publishedId
return isPublished ? !hasDraft : true
})
return collate(documents).map(entry => entry.draft || entry.published)
}
23 changes: 23 additions & 0 deletions packages/@sanity/base/test/draftUtils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {collate, removeDupes} from '../src/util/draftUtils'

test('collate()', () => {
const foo = {_id: 'foo'}
const fooDraft = {_id: 'drafts.foo'}
const barDraft = {_id: 'drafts.bar'}
const baz = {_id: 'baz'}

expect(collate([foo, fooDraft, barDraft, baz])).toEqual([
{id: 'foo', draft: fooDraft, published: foo},
{id: 'bar', draft: barDraft},
{id: 'baz', published: baz}
])
})

test('removeDupes()', () => {
const foo = {_id: 'foo'}
const fooDraft = {_id: 'drafts.foo'}
const barDraft = {_id: 'drafts.bar'}
const baz = {_id: 'baz'}

expect(removeDupes([foo, fooDraft, barDraft, baz])).toEqual([fooDraft, barDraft, baz])
})
23 changes: 8 additions & 15 deletions packages/@sanity/desk-tool/src/pane/DocumentsListPane.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react'
import PropTypes from 'prop-types'
import {partition} from 'lodash'
import {withRouterHOC} from 'part:@sanity/base/router'
import schema from 'part:@sanity/base/schema'
import PlusIcon from 'part:@sanity/base/plus-icon'
Expand All @@ -9,12 +8,7 @@ import DefaultPane from 'part:@sanity/components/panes/default'
import QueryContainer from 'part:@sanity/base/query-container'
import Snackbar from 'part:@sanity/components/snackbar/default'
import Spinner from 'part:@sanity/components/loading/spinner'
import {
getPublishedId,
isDraftId,
isPublishedId,
getDraftId
} from 'part:@sanity/base/util/draft-utils'
import {collate, getPublishedId} from 'part:@sanity/base/util/draft-utils'
import {isActionEnabled} from 'part:@sanity/base/util/document-action-utils'

import {combineLatest} from 'rxjs'
Expand All @@ -28,15 +22,14 @@ import {map, tap} from 'rxjs/operators'
const DEFAULT_ORDERING = [{field: '_createdAt', direction: 'desc'}]

function removePublishedWithDrafts(documents) {
const [draftIds, publishedIds] = partition(documents.map(doc => doc._id), isDraftId)

return documents
.map(doc => ({
return collate(documents).map(entry => {
const doc = entry.draft || entry.published
return {
...doc,
hasPublished: publishedIds.includes(getPublishedId(doc._id)),
hasDraft: draftIds.includes(getDraftId(doc._id))
}))
.filter(doc => !(isPublishedId(doc._id) && doc.hasDraft))
hasPublished: !!entry.published,
hasDraft: !!entry.draft
}
})
}

function getDocumentKey(document) {
Expand Down

0 comments on commit 4bf926e

Please sign in to comment.