Skip to content

Commit

Permalink
[desk-tool] Add support for live edit (#741)
Browse files Browse the repository at this point in the history
* [schema] First pass at draft: true

* [test-studio] Add a type to the test studio schema for playing around with draft: true

* [schema] Apply document core types on extend

* [desk-tool] Commit the published document on change if drafts are disabled

* [desk-tool] Only render Publish Changes button if drafts are enabled

* [desk-tool] Only render the has-unpublished-stuff tooltip if drafts are enabled

* [desk-tool] Fix a couple of imports and proptypes

* [test-studio] Renae draft flag to liveEdit

* [schema] Roll back draft flag on document schema type

* [schema] Update components following rename of schema flag draft --> liveEdit

* [desk-tool] In case of liveEdit, don't render unpublish and discard choices from dropdown
  • Loading branch information
Thomas Drevon authored and bjoerge committed Apr 23, 2018
1 parent ab72b95 commit 6f34912
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 56 deletions.
34 changes: 26 additions & 8 deletions packages/@sanity/desk-tool/src/pane/DocumentsPane.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
import PropTypes from 'prop-types'
import React from 'react'
import Spinner from 'part:@sanity/components/loading/spinner'
import styles from './styles/DocumentsPane.css'
import {StateLink, IntentLink, withRouterHOC} from 'part:@sanity/base/router'
import {StateLink, withRouterHOC} from 'part:@sanity/base/router'
import SortIcon from 'part:@sanity/base/sort-icon'
import Ink from 'react-ink'

import ListView from './ListView'
import {partition, uniqBy, get} from 'lodash'
import VisibilityOffIcon from 'part:@sanity/base/visibility-off-icon'
import EditIcon from 'part:@sanity/base/edit-icon'
import QueryContainer from 'part:@sanity/base/query-container'
import {DRAFTS_FOLDER, getPublishedId, isDraftId, getDraftId} from '../utils/draftUtils'
import {isPublishedId} from '../utils/draftUtils'
import schema from 'part:@sanity/base/schema'
import Preview from 'part:@sanity/base/preview'
import Pane from 'part:@sanity/components/panes/default'
import DocumentsPaneMenu from './DocumentsPaneMenu'
import Button from 'part:@sanity/components/buttons/default'
import PlusIcon from 'part:@sanity/base/plus-icon'
import Snackbar from 'part:@sanity/components/snackbar/default'
import {Tooltip} from '@sanity/react-tippy'
import {
DRAFTS_FOLDER,
getPublishedId,
isDraftId,
isPublishedId,
getDraftId
} from '../utils/draftUtils'
import DocumentsPaneMenu from './DocumentsPaneMenu'
import ListView from './ListView'
import styles from './styles/DocumentsPane.css'

const NOOP = () => {} // eslint-disable-line

const LOCALSTORAGE_KEY = 'desk-tool.documents-pane-settings'
Expand Down Expand Up @@ -85,10 +90,14 @@ function writeSettingsForType(type, settings) {
export default withRouterHOC(
class DocumentsPane extends React.PureComponent {
static propTypes = {
loading: PropTypes.bool,
selectedType: PropTypes.string,
selectedDocumentId: PropTypes.string,
schemaType: PropTypes.object,
isCollapsed: PropTypes.bool,
published: PropTypes.array,
drafts: PropTypes.array,
onSetListLayout: PropTypes.any,
router: PropTypes.object
}

Expand Down Expand Up @@ -156,6 +165,11 @@ export default withRouterHOC(
this.setState(prevState => ({menuIsOpen: !prevState.menuIsOpen}))
}

isLiveEditEnabled() {
const selectedSchemaType = schema.get(this.props.selectedType)
return selectedSchemaType.liveEdit === true
}

getOrderingOptions(selectedType) {
const type = schema.get(selectedType)

Expand Down Expand Up @@ -184,6 +198,7 @@ export default withRouterHOC(
renderDocumentsPaneMenu = () => {
const {selectedType} = this.props
const type = schema.get(selectedType)

return (
<DocumentsPaneMenu
onSetListLayout={this.handleSetListLayout}
Expand All @@ -199,6 +214,8 @@ export default withRouterHOC(
}

renderStatus = item => {
const isLiveEditEnabled = this.isLiveEditEnabled()

return (
<div className={styles.itemStatus}>
{!item.hasPublished && (
Expand All @@ -208,7 +225,8 @@ export default withRouterHOC(
</i>
</Tooltip>
)}
{item.hasDraft &&
{!isLiveEditEnabled &&
item.hasDraft &&
item.hasPublished && (
<Tooltip
title="Has changes not yet published"
Expand Down
93 changes: 54 additions & 39 deletions packages/@sanity/desk-tool/src/pane/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,27 @@ const getDuplicateItem = (draft, published) => ({
isDisabled: !draft && !published
})

const getDiscardItem = (draft, published) => ({
action: 'discard',
title: 'Discard changes…',
icon: UndoIcon,
divider: true,
isDisabled: !draft || !published
})
const getDiscardItem = (draft, published, isLiveEditEnabled) =>
isLiveEditEnabled
? null
: {
action: 'discard',
title: 'Discard changes…',
icon: UndoIcon,
divider: true,
isDisabled: !draft || !published
}

const getUnpublishItem = (draft, published) => ({
action: 'unpublish',
title: 'Unpublish…',
icon: VisibilityOffIcon,
divider: true,
isDisabled: !published
})
const getUnpublishItem = (draft, published, isLiveEditEnabled) =>
isLiveEditEnabled
? null
: {
action: 'unpublish',
title: 'Unpublish…',
icon: VisibilityOffIcon,
divider: true,
isDisabled: !published
}

const getDeleteItem = (draft, published) => ({
action: 'delete',
Expand Down Expand Up @@ -127,7 +133,7 @@ const getProductionPreviewItem = (draft, published) => {
)
}

const getMenuItems = (draft, published) =>
const getMenuItems = (draft, published, isLiveEditEnabled) =>
[
getProductionPreviewItem,
getDiscardItem,
Expand All @@ -136,7 +142,7 @@ const getMenuItems = (draft, published) =>
getDeleteItem,
getInspectItem
]
.map(fn => fn(draft, published))
.map(fn => fn(draft, published, isLiveEditEnabled))
.filter(Boolean)

const isValidationError = marker => marker.type === 'validation' && marker.level === 'error'
Expand Down Expand Up @@ -410,6 +416,11 @@ export default withRouterHOC(
this.setState(prevState => ({showValidationTooltip: !prevState.showValidationTooltip}))
}

isLiveEditEnabled() {
const selectedSchemaType = schema.get(this.props.type.name)
return selectedSchemaType.liveEdit === true
}

getTitle(value) {
const {type} = this.props
if (!value) {
Expand Down Expand Up @@ -517,20 +528,22 @@ export default withRouterHOC(
</Button>
</Tooltip>
)}
<Tooltip
arrow
theme="light"
className={styles.publishButton}
title={errors.length > 0 ? 'Fix errors before publishing' : 'Ctrl+Alt+P'}
>
<Button
disabled={isReconnecting || !draft || errors.length > 0}
onClick={this.handlePublishRequested}
color="primary"
{!this.isLiveEditEnabled() && (
<Tooltip
arrow
theme="light"
className={styles.publishButton}
title={errors.length > 0 ? 'Fix errors before publishing' : 'Ctrl+Alt+P'}
>
{published ? 'Publish changes' : 'Publish'}
</Button>
</Tooltip>
<Button
disabled={isReconnecting || !draft || errors.length > 0}
onClick={this.handlePublishRequested}
color="primary"
>
{published ? 'Publish changes' : 'Publish'}
</Button>
</Tooltip>
)}
</div>
)
}
Expand All @@ -543,7 +556,7 @@ export default withRouterHOC(
isOpen={this.state.isMenuOpen}
onClose={this.handleMenuClose}
onClickOutside={this.handleMenuClose}
items={getMenuItems(draft, published)}
items={getMenuItems(draft, published, this.isLiveEditEnabled())}
origin="top-right"
/>
)
Expand Down Expand Up @@ -621,15 +634,17 @@ export default withRouterHOC(
</span>
)}
</div>
<div className={styles.publishedDate}>
{published ? (
<span>
Published <TimeAgo time={published._updatedAt} />
</span>
) : (
'Not published'
)}
</div>
{!this.isLiveEditEnabled() && (
<div className={styles.publishedDate}>
{published ? (
<span>
Published <TimeAgo time={published._updatedAt} />
</span>
) : (
'Not published'
)}
</div>
)}
</div>
<form
className={styles.editor}
Expand Down
29 changes: 22 additions & 7 deletions packages/@sanity/desk-tool/src/pane/EditorWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ export default class EditorWrapper extends React.Component {
this.dispose()
}

isLiveEditEnabled() {
const selectedSchemaType = schema.get(this.props.typeName)
return selectedSchemaType.liveEdit === true
}

dispose() {
if (this.subscription) {
this.subscription.unsubscribe()
Expand Down Expand Up @@ -318,15 +323,23 @@ export default class EditorWrapper extends React.Component {
const {published, draft} = this.state
const {typeName} = this.props

if (!draft.snapshot) {
this.draft.createIfNotExists({
...omit(published.snapshot, '_updatedAt'),
_id: this.getDraftId(),
if (this.isLiveEditEnabled()) {
// No drafting, patch and commit the published document
this.published.createIfNotExists({
_id: this.getPublishedId(),
_type: typeName
})
this.published.patch(event.patches)
} else {
if (!draft.snapshot) {
this.draft.createIfNotExists({
...omit(published.snapshot, '_updatedAt'),
_id: this.getDraftId(),
_type: typeName
})
}
this.draft.patch(event.patches)
}

this.draft.patch(event.patches)
this.commit()
}

Expand All @@ -340,8 +353,10 @@ export default class EditorWrapper extends React.Component {

commit = throttle(
() => {
const currentDoc = this.isLiveEditEnabled() ? this.published : this.draft
this.setStateIfMounted({isSaving: true})
this.draft.commit().subscribe({

currentDoc.commit().subscribe({
next: () => {
// todo
},
Expand Down
53 changes: 53 additions & 0 deletions packages/test-studio/schemas/liveEdit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import BookIcon from 'react-icons/lib/fa/book'

function formatSubtitle(thesis) {
if (thesis.authorName && thesis.publicationYear) {
return `By ${thesis.authorName} (${thesis.publicationYear})`
}
return thesis.authorName ? `By ${thesis.authorName}` : String(thesis.publicationYear || '')
}

export default {
title: 'Thesis (live edit)',
name: 'thesis',
type: 'document',
liveEdit: true,
description: 'A simple type for testing draft: false',
icon: BookIcon,
fields: [
{
name: 'title',
title: 'Title',
type: 'string'
},
{
name: 'author',
title: 'Author',
type: 'reference',
to: {type: 'author', title: 'Author'}
},
{
name: 'coverImage',
title: 'Cover Image',
type: 'image'
},
{
name: 'publicationYear',
title: 'Year of publication',
type: 'number'
}
],
preview: {
select: {
title: 'title',
authorName: 'author.name',
publicationYear: 'publicationYear'
},
prepare(thesis, options = {}) {
return Object.assign({}, thesis, {
title: thesis.title,
subtitle: formatSubtitle(thesis)
})
}
}
}
5 changes: 3 additions & 2 deletions packages/test-studio/schemas/schema.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import createSchema from 'part:@sanity/base/schema-creator'
import codeInputType from 'part:@sanity/form-builder/input/code/schema'
import schemaTypes from 'all:part:@sanity/base/schema-type'
import richDateType from 'part:@sanity/form-builder/input/rich-date/schema'

import book from './book'
import author from './author'

import blocks from './blocks'
import references from './references'
import images, {myImage} from './images'
Expand All @@ -18,6 +18,7 @@ import uploads from './uploads'
import code from './code'
import customNumber from './customNumber'
import color from './color'
import liveEdit from './liveEdit'
import recursive from './recursive'
import recursiveArray from './recursiveArray'
import recursivePopover from './recursivePopover'
Expand All @@ -36,7 +37,6 @@ import customInputs from './customInputs'
import notitle from './notitle'
import typeWithNoToplevelStrings from './typeWithNoToplevelStrings'

import richDateType from 'part:@sanity/form-builder/input/rich-date/schema'
import focus from './focus'
import previewImageUrlTest from './previewImageUrlTest'
import previewMediaTest from './previewMediaTest'
Expand Down Expand Up @@ -64,6 +64,7 @@ export default createSchema({
uploads,
code,
color,
liveEdit,
images,
files,
references,
Expand Down

0 comments on commit 6f34912

Please sign in to comment.