Skip to content

Commit

Permalink
[form-builder] Misc. minor adjustments uploader infrastructure (#241)
Browse files Browse the repository at this point in the history
* [form-builder] Misc. minor adjustments uploader infrastructure

* [form-builder] Rename key for tracking upload progress from 'percent' to 'progress', add file name and type to upload status
  • Loading branch information
bjoerge committed Oct 12, 2017
1 parent c4f741a commit 4380338
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 44 deletions.
6 changes: 3 additions & 3 deletions packages/@sanity/base/src/preview/SanityDefaultPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ export default class SanityDefaultPreview extends React.PureComponent {

const item = _upload ? {
...value,
// todo: remove this from here and handle invalid preview urls (e.g. blob urls from another computer)
imageUrl: _upload.previewImage
imageUrl: _upload.previewImage,
title: value.title || (_upload.file && _upload.file.name) || 'Uploading…'
} : value

return (
<div>
{_upload && <UploadProgressBar percent={_upload.percent} />}
{_upload && <UploadProgressBar progress={_upload.progress} />}
<PreviewComponent item={item} {...rest} />
</div>
)
Expand Down
10 changes: 5 additions & 5 deletions packages/@sanity/base/src/preview/UploadProgressBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import PropTypes from 'prop-types'
import styles from './UploadProgressBar.css'

export default function UploadProgressBar(props) {
const {percent} = props
const {progress} = props
const classes = [
styles.root,
percent === 100 && styles.completed
progress === 100 && styles.completed
]
.filter(Boolean)
.join(' ')
Expand All @@ -15,17 +15,17 @@ export default function UploadProgressBar(props) {
<div className={classes}>
<div className={styles.inner}>
<div className={styles.barContainer}>
<div className={styles.bar} style={{width: `${percent}%`}} />
<div className={styles.bar} style={{width: `${progress}%`}} />
</div>
</div>
</div>
)
}

UploadProgressBar.propTypes = {
percent: PropTypes.number
progress: PropTypes.number
}

UploadProgressBar.defaultProps = {
percent: 0
progress: 0
}
9 changes: 7 additions & 2 deletions packages/@sanity/form-builder/src/sanity/uploads/typedefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export type UploaderDef = {
upload: (file: File, type: Type) => ObservableI<UploadEvent>
}

export type Uploader = UploaderDef & {
priority: number,
export type Uploader = {
type: string,
accepts: string,
upload: (file: File, type: Type) => ObservableI<UploadEvent>,
priority: number
}

export type UploaderResolver = (type: Type, file: File) => ?Uploader
13 changes: 5 additions & 8 deletions packages/@sanity/form-builder/src/sanity/uploads/uploadFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,21 @@ import {set} from '../../utils/patches'
import type {ObservableI} from '../../typedefs/observable'
import type {UploadEvent} from './typedefs'
import {UPLOAD_STATUS_KEY} from './constants'
import {createUploadEvent, CLEANUP_EVENT, INIT_EVENT} from './utils'

const setInitialUploadState$ = Observable.of(INIT_EVENT)
const unsetUploadState$ = Observable.of(CLEANUP_EVENT)
import {createUploadEvent, createInitialUploadEvent, CLEANUP_EVENT} from './utils'

export default function uploadFile(file: File): ObservableI<UploadEvent> {
const upload$ = uploadFileAsset(file)
.map(event => {
if (event.type === 'complete') {
return createUploadEvent([
set({_type: 'reference', _ref: event.asset._id}, ['asset']),
set(100, [UPLOAD_STATUS_KEY, 'percent'])
set(100, [UPLOAD_STATUS_KEY, 'progress'])
])
}
return createUploadEvent([set(event.percent, [UPLOAD_STATUS_KEY, 'percent'])])
return createUploadEvent([set(event.percent, [UPLOAD_STATUS_KEY, 'progress'])])
})

return setInitialUploadState$
return Observable.of(createInitialUploadEvent(file))
.concat(upload$)
.concat(unsetUploadState$)
.concat(Observable.of(CLEANUP_EVENT))
}
15 changes: 6 additions & 9 deletions packages/@sanity/form-builder/src/sanity/uploads/uploadImage.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,33 +12,30 @@ import type {UploadEvent} from './typedefs'
import type {OrientationId} from './image/orient'
import type {ObservableI} from '../../typedefs/observable'
import {UPLOAD_STATUS_KEY} from './constants'
import {CLEANUP_EVENT, INIT_EVENT, createUploadEvent} from './utils'
import {createUploadEvent, createInitialUploadEvent, CLEANUP_EVENT} from './utils'
import {createUploadId, getUploadEvents, scheduleUpload} from './uploadQueue'

type Exif = {
orientation: OrientationId
}

const setInitialUploadState$ = Observable.of(INIT_EVENT)
const unsetUploadState$ = Observable.of(CLEANUP_EVENT)

export default function uploadImage(file: File): ObservableI<UploadEvent> {
const uploadId = createUploadId(file)

const upload$ = getUploadEvents(uploadId)
.filter(event => event.stage !== 'download')
.map(event => ({
...event,
percent: 2 + ((event.percent / 100) * 98)
progress: 2 + ((event.percent / 100) * 98)
}))
.map(event => {
if (event.type === 'complete') {
return createUploadEvent([
set({_type: 'reference', _ref: event.asset._id}, ['asset']),
set(100, [UPLOAD_STATUS_KEY, 'percent'])
set(100, [UPLOAD_STATUS_KEY, 'progress'])
])
}
return createUploadEvent([set(event.percent, [UPLOAD_STATUS_KEY, 'percent'])])
return createUploadEvent([set(event.percent, [UPLOAD_STATUS_KEY, 'progress'])])
})

const setPreviewUrl$ = readExif(file)
Expand All @@ -54,7 +51,7 @@ export default function uploadImage(file: File): ObservableI<UploadEvent> {

scheduleUpload(uploadId, file)

return setInitialUploadState$
return Observable.of(createInitialUploadEvent(file))
.concat(Observable.from(upload$).merge(setPreviewUrl$))
.concat(unsetUploadState$)
.concat(Observable.of(CLEANUP_EVENT))
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,12 @@ uploadRequests$.asObservable()
.mergeMap(
({uploadId, file}) => new Observable(observer => {
const upload = Observable.from(uploadImageAsset(file)).share()
upload.subscribe(registry[uploadId]._multicast)
return upload.subscribe(observer)
const registrySubscription = upload.subscribe(registry[uploadId]._multicast)
const uploadSubscription = upload.subscribe(observer)
return () => {
registrySubscription.unsubscribe()
uploadSubscription.unsubscribe()
}
}),
CONCURRENCY
)
Expand Down
7 changes: 4 additions & 3 deletions packages/@sanity/form-builder/src/sanity/uploads/uploaders.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,25 @@
import uploadImage from './uploadImage'
import uploadFile from './uploadFile'
import type {Uploader, UploaderDef} from './typedefs'
import type {Type} from '../../typedefs'
import {set} from '../../utils/patches'

const UPLOAD_IMAGE: UploaderDef = {
type: 'image',
accepts: 'image/*',
upload: (file: File, type: any) => uploadImage(file)
upload: (file: File, type?: Type) => uploadImage(file)
}

const UPLOAD_FILE: UploaderDef = {
type: 'file',
accepts: '',
upload: (file: File, type: any) => uploadFile(file)
upload: (file: File, type: Type) => uploadFile(file)
}

const UPLOAD_TEXT: UploaderDef = {
type: 'string',
accepts: 'text/*',
upload: (file: File, type: any) => uploadFile(file)
upload: (file: File, type: Type) => uploadFile(file)
.map(content => ({
patches: [set(content)]
}))
Expand Down
18 changes: 11 additions & 7 deletions packages/@sanity/form-builder/src/sanity/uploads/utils.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@

import {UploadEvent} from './typedefs'
import {UPLOAD_STATUS_KEY} from './constants'
import {set, unset} from '../../utils/patches'

const SET_UPLOAD_PATCH = set({
percent: 2,
initiated: new Date().toISOString()
}, [UPLOAD_STATUS_KEY])

const UNSET_UPLOAD_PATCH = unset([UPLOAD_STATUS_KEY])

export function createUploadEvent(patches = []): UploadEvent {
Expand All @@ -16,5 +10,15 @@ export function createUploadEvent(patches = []): UploadEvent {
patches
}
}
export const INIT_EVENT = createUploadEvent([SET_UPLOAD_PATCH])

export const CLEANUP_EVENT = createUploadEvent([UNSET_UPLOAD_PATCH])

export function createInitialUploadEvent(file: File) {
return createUploadEvent([
set({
progress: 2,
initiated: new Date().toISOString(),
file: {name: file.name, type: file.type}
}, [UPLOAD_STATUS_KEY])
])
}
5 changes: 5 additions & 0 deletions packages/@sanity/form-builder/src/typedefs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@ export type Type = {
name: string,
options: ?Object
}

export type Reference = {
_type: string,
_ref?: string
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ interface ObserverI<T> {
error: (error: Error) => void
}

interface Subscription {
export interface Subscription {
unsubscribe: () => void
}

type FunctionSubscriber<T> = T => void
type ObjectSubscriber<T> = {
next: T => void,
error: (error: Error) => void,
complete: () => void
next?: T => void,
error?: (error: Error) => void,
complete?: () => void
}

type Subscriber<T> = FunctionSubscriber<T> | ObjectSubscriber<T>

export interface ObservableI<T> {
constructor: (observer: ObserverI<T>) => void,
subscribe: (subscriber: Subscriber<T>) => Subscription<T>,
subscribe: (subscriber: Subscriber<T>) => Subscription,
map<T, A>((T) => A): ObservableI<A>
}

0 comments on commit 4380338

Please sign in to comment.