This commit is contained in:
Harry Hedger 2016-07-13 22:31:14 -04:00
commit 57427bdd6f
13 changed files with 157 additions and 62 deletions

View file

@ -26,7 +26,7 @@ Ideas that will be planned and find their way into a release at one point
- [ ] drive: Show a visual indication that downloading has started after double-clicking. Prevent that 6 clicks = 3 downloads
- [ ] instagram: Make a barely working Instagram Plugin + example (#21)
- [ ] meta: Use <waffle.io> instead of Markdown task tracking. Some discussion [here](https://transloadit.slack.com/archives/general/p1455693654000062) (@kvz)
- [ ] modal: polish on mobile
- [ ] dashboard: polish on mobile
- [ ] presets: Add basic preset that mimics Transloadit's jQuery plugin (#28)
- [ ] test: Human should check http://www.webpagetest.org, use it sometimes to test our website & Uppy? Which will show response/loading times and where big delays are
- [ ] test: Human should test with real screen reader to identify accessibility problems
@ -39,19 +39,26 @@ Ideas that will be planned and find their way into a release at one point
## 0.8.0
To be released: July 29, 2016
Theme: The Webcam Edition
To be released: July 29, 2016. Releasemaster: Artur
- [ ] core: fix bug: no meta information from uppy-server files (@hedgerh)
- [ ] core: fix bug: uppy-server file is treated as local and directly uploaded (@hedgerh)
- [ ] meta: better readme on GitHub and NPM (@arturi)
- [ ] meta: release “Uppy Begins” post + minor blog polish (@arturi)
- [ ] webcam: initial version: webcam light goes on (@hedgerh)
- [ ] uppy-server: hammering out websockets/oauth (@hedgerh, @acconut)
- [ ] modifier: A plugin to supply meta data (like width, tag, filename, user_id) (@arturi)
- [ ] modifier: pass custom metadata with non-tus-upload. Maybe mimic meta behavior of tus here, too
- [ ] modifier: pass custom metadata with tus-upload with tus-js-client (@arturi)
- [ ] progress: better icons, style, file types (mime + extension) (@arturi)
- [ ] modal: merge modal and dashboard (@arturi)
- [ ] modal: try a workflow where import from external service slides over and takes up the whole modal screen (@arturi)
- [ ] progress: better icons, style (@arturi)
- [ ] core: better mime/type detection (via mime + extension) (@arturi)
- [ ] test: add next-update https://www.npmjs.com/package/next-update to check if packages we use can be safely updated
- [ ] test: Get IE4 on windows 3.11 to run Uppy and see it fall back to regular form upload (`api2.transloadit.com`) (@arturi)
- [ ] test: working Uppy example on Require Bin — latest version straight from NPM (@arturi)
- [ ] test: add next-update https://www.npmjs.com/package/next-update to check if packages we use can be safely updated
- [x] dashboard: try a workflow where import from external service slides over and takes up the whole dashboard screen (@arturi)
- [x] modal: merge modal and dashboard (@arturi)
## 0.7.0
@ -238,13 +245,13 @@ Here are the go-to folks for each individual component or area of expertise:
- build (@hedgerh)
- complete (@hedgerh)
- core (@arturi)
- dashboard (/modal) (@hedgerh)
- docs (@arturi)
- dragdrop (@arturi)
- dropbox (@hedgerh)
- drive (@hedgerh)
- dropbox (@hedgerh)
- instagram (@hedgerh)
- meta (@kvz)
- modal (@hedgerh)
- presets (@arturi)
- server (@hedgerh)
- test (@arturi)

View file

@ -1,10 +1,74 @@
# uppy
# Uppy
A work in progress - you'll find nothing useful here yet.
<img src="http://uppy.io/images/logos/uppy-dog-full.svg" width="150" alt="Uppy logo — a puppy superman">
But if you're here to dig in, these are some places you might find interesting:
<a href="https://www.npmjs.com/package/uppy"><img src="https://img.shields.io/badge/stability-experimental-orange.svg?style=flat-square"></a>
<a href="https://www.npmjs.com/package/uppy"><img src="https://img.shields.io/npm/v/uppy.svg?style=flat-square"></a>
<a href="https://travis-ci.org/transloadit/uppy"><img src="https://img.shields.io/travis/transloadit/uppy/master.svg?style=flat-square" alt="Build Status"></a>
<a href="https://saucelabs.com/u/transloadit-uppy"><img src="https://saucelabs.com/buildstatus/transloadit-uppy" alt="Sauce Test Status"></a>
- Our website (under construction) [http://uppy.io/](http://uppy.io/)
Uppy is (going to be) a cool JavaScript file uploader that fetches files for you from local disk, Google Drive, Dropbox, Instagram, remote URLs, cameras and other exciting locations, and then uploads them to wherever you want. Uppy is being developed by the [Transloadit](https://transloadit.com) team because we want file uploading experience to be better — both for users and developers.
Check out [uppy.io](http://uppy.io/) for docs, API, examples and stats.
## Features
- Lightweight / easy on dependencies
- Usable as a bundle straight from a CDN as well as a module to import
- Resumable file uploads via the open [tus](http://tus.io/) standard
- Uppy speaks multiple languages (i18n support)
- Works great with file encoding and processing backends, such as [Transloadit](http://transloadit.com)
- Small core, modular plugin-based architecture.
- Qute as a puppy :dog:, also accepts cat pictures
## Demo
<img width="600" alt="Uppy UI Demo: modal dialog with a few selected files and an upload button" src="https://cloud.githubusercontent.com/assets/1199054/16790119/2dd6eda2-4881-11e6-908b-4de5581d2de6.png">
- [Full featured UI](http://uppy.io/examples/modal)
- [Simple Drag & Drop](http://uppy.io/examples/dragdrop)
## Usage
:warning: **Dont use Uppy in production just yet, were working on it**
Its easy to start using Uppy, we recommend installing from npm with `npm install uppy` and then:
``` javascript
import Uppy from 'uppy/core'
import { DragDrop, Tus10 } from 'uppy/plugins'
const uppy = new Uppy({wait: false})
const files = uppy
.use(DragDrop, {target: '#upload-target'})
.use(Tus10, {endpoint: 'http://master.tus.io:8080/files/'})
.run()
```
But if you like, you can also use a pre-built bundle, in that case `Uppy` will attach itself to the global `window` object:
``` javascript
<script src="uppy.min.js"></script>
<script>
var uppy = new Uppy.Core({locales: Uppy.locales.ru_RU, debug: true});
uppy.use(Uppy.plugins.DragDrop, {target: '.UppyDragDrop'});
uppy.use(Uppy.plugins.Tus10, {endpoint: 'http://master.tus.io:3020/files/'});
uppy.run();
</script>
```
## Browser Support
<a href="https://saucelabs.com/u/transloadit-uppy">
<img src="https://saucelabs.com/browser-matrix/transloadit-uppy.svg" alt="Sauce Test Status"/>
</a>
## Contributions are welcome
- Contributors guide in [`website/src/guide/contributing.md`](website/src/guide/contributing.md)
- Architecture in [`website/src/api/architecture.md`](website/src/api/architecture.md)
- Contributor's guide in [`website/src/guide/contributing.md`](website/src/guide/contributing.md)
- Open todos in for a minimum valuable product [`CHANGELOG.md`](CHANGELOG.md#todo)
- Changelog to track our release progress (we aim to roll out a release every month): [`CHANGELOG.md`](CHANGELOG.md)
## License
[The MIT License](LICENSE).

View file

@ -1,15 +1,15 @@
import Uppy from '../src/core/Core.js'
import Modal from '../src/plugins/modal'
// import Dashboard from '../src/plugins/dashboard'
import Modal from '../src/plugins/Modal'
import Dummy from '../src/plugins/Dummy'
import DragDrop from '../src/plugins/DragDrop'
import GoogleDrive from '../src/plugins/GoogleDrive'
import ProgressBar from '../src/plugins/ProgressBar'
import Tus10 from '../src/plugins/Tus10'
const uppy = new Uppy({debug: true})
.use(Modal, {trigger: '#uppyModalOpener'})
// .use(Dashboard, {target: Modal})
.use(DragDrop, {target: Modal})
.use(GoogleDrive, {target: Modal, host: 'http://ya.ru'})
.use(Dummy, {target: Modal})
.use(ProgressBar, {target: Modal})
.use(Tus10, {endpoint: 'http://master.tus.io:8080/files/'})

View file

@ -3,6 +3,7 @@ import { fileIcon, checkIcon, removeIcon } from './icons'
export default function fileItem (bus, file) {
const isUploaded = file.progress === 100
const uploadInProgress = file.progress > 0 && file.progress
const remove = (ev) => {
bus.emit('file-remove', file.id)
@ -23,8 +24,8 @@ export default function fileItem (bus, file) {
</h4>
<h5 class="UppyDashboardItem-status">
${file.totalSize}<br>
${file.progress > 0 && file.progress < 100 ? 'Uploading… ' + file.progress + '%' : ''}
${file.progress === 100 ? 'Completed' : ''}
${uploadInProgress ? 'Uploading… ' + file.progress + '%' : ''}
${isUploaded ? 'Completed' : ''}
</h5>
<div class="UppyDashboardItem-action">
${isUploaded
@ -36,7 +37,7 @@ export default function fileItem (bus, file) {
</button>`
}
</div>
<div class="UppyDashboardItem-progress">
<div class="UppyDashboardItem-progress ${uploadInProgress ? 'is-active' : ''}">
<div class="UppyDashboardItem-progressInner" style="width: ${file.progress}%"></div>
</div>
</li>`

View file

@ -3,9 +3,6 @@ import html from 'yo-yo'
// https://css-tricks.com/creating-svg-icon-system-react/
export function defaultTabIcon () {
// return html`<svg class="UppyIcon UppyModalTab-icon" width="28" height="28" viewBox="0 0 101 58">
// <path d="M17.582.3L.915 41.713l32.94 13.295L17.582.3zm83.333 41.414L67.975 55.01 84.25.3l16.665 41.414zm-48.998 5.403L63.443 35.59H38.386l11.527 11.526v5.905l-3.063 3.32 1.474 1.36 2.59-2.806 2.59 2.807 1.475-1.357-3.064-3.32v-5.906zm16.06-26.702c-3.973 0-7.194-3.22-7.194-7.193 0-3.973 3.222-7.193 7.193-7.193 3.974 0 7.193 3.22 7.193 7.19 0 3.974-3.22 7.194-7.195 7.194zM70.48 8.682c-.737 0-1.336.6-1.336 1.337 0 .736.6 1.335 1.337 1.335.738 0 1.338-.598 1.338-1.336 0-.74-.6-1.338-1.338-1.338zM33.855 20.415c-3.973 0-7.193-3.22-7.193-7.193 0-3.973 3.22-7.193 7.195-7.193 3.973 0 7.192 3.22 7.192 7.19 0 3.974-3.22 7.194-7.192 7.194zM36.36 8.682c-.737 0-1.336.6-1.336 1.337 0 .736.6 1.335 1.337 1.335.738 0 1.338-.598 1.338-1.336 0-.74-.598-1.338-1.337-1.338z"/>
// </svg>`
return html`<svg class="UppyIcon UppyModalTab-icon" width="224" height="224" viewBox="0 0 224 224">
<path d="M112 224c61.856 0 112-50.144 112-112S173.856 0 112 0 0 50.144 0 112s50.144 112 112 112zm0-12c55.228 0 100-44.772 100-100S167.228 12 112 12 12 56.772 12 112s44.772 100 100 100z"/>
<path d="M147.67 132.24v57.43H77v-57.43H29.79l82.38-103.71 82.37 103.71h-46.87z" fill="#FFF"/>
@ -54,14 +51,11 @@ export function uploadIcon () {
}
export function fileIcon (fileType) {
return html`<svg class="UppyIcon" width="100" height="100" viewBox="0 0 21 29">
<path d="M2.473.31C1.44.31.59 1.21.59 2.307V26.31c0 1.097.85 2 1.883 2H18.71c1.03 0 1.88-.903 1.88-2V7.746a.525.525 0 0 0-.014-.108v-.015a.51.51 0 0 0-.014-.03v-.017a.51.51 0 0 0-.015-.03.482.482 0 0 0-.014-.016v-.015a.482.482 0 0 0-.015-.015.51.51 0 0 0-.014-.03.482.482 0 0 0-.014-.017.51.51 0 0 0-.015-.03.483.483 0 0 0-.03-.03L13.636.45a.47.47 0 0 0-.118-.093.448.448 0 0 0-.044-.015.448.448 0 0 0-.044-.016.448.448 0 0 0-.045-.015.44.44 0 0 0-.073 0H2.474zm0 .99h10.372v4.943c0 1.097.85 2 1.88 2h4.932V26.31c0 .56-.42 1.007-.948 1.007H2.472c-.527 0-.95-.446-.95-1.007V2.308c0-.56.423-1.008.95-1.008zm11.305.667l4.843 4.927.352.357h-4.246c-.527 0-.948-.446-.948-1.007V1.967z"
fill="#F6A623"
fill-rule="evenodd" />
return html`<svg class="UppyIcon" width="90" height="90" viewBox="0 0 21 29">
<path d="M2.473.31C1.44.31.59 1.21.59 2.307V26.31c0 1.097.85 2 1.883 2H18.71c1.03 0 1.88-.903 1.88-2V7.746a.525.525 0 0 0-.014-.108v-.015a.51.51 0 0 0-.014-.03v-.017a.51.51 0 0 0-.015-.03.482.482 0 0 0-.014-.016v-.015a.482.482 0 0 0-.015-.015.51.51 0 0 0-.014-.03.482.482 0 0 0-.014-.017.51.51 0 0 0-.015-.03.483.483 0 0 0-.03-.03L13.636.45a.47.47 0 0 0-.118-.093.448.448 0 0 0-.044-.015.448.448 0 0 0-.044-.016.448.448 0 0 0-.045-.015.44.44 0 0 0-.073 0H2.474zm0 .99h10.372v4.943c0 1.097.85 2 1.88 2h4.932V26.31c0 .56-.42 1.007-.948 1.007H2.472c-.527 0-.95-.446-.95-1.007V2.308c0-.56.423-1.008.95-1.008zm11.305.667l4.843 4.927.352.357h-4.246c-.527 0-.948-.446-.948-1.007V1.967z">
<text font-family="ArialMT, Arial"
font-size="5"
font-weight="bold"
fill="#F6A623"
text-anchor="middle"
x="11"
y="22">

View file

@ -28,7 +28,9 @@ export default class Modal extends Plugin {
this.showModal = this.showModal.bind(this)
this.addTarget = this.addTarget.bind(this)
this.toggleTabPanel = this.toggleTabPanel.bind(this)
this.actions = this.actions.bind(this)
this.hideAllPanels = this.hideAllPanels.bind(this)
this.showPanel = this.showPanel.bind(this)
this.initEvents = this.initEvents.bind(this)
this.render = this.render.bind(this)
this.install = this.install.bind(this)
@ -69,7 +71,22 @@ export default class Modal extends Plugin {
return this.opts.target
}
toggleTabPanel (id) {
hideAllPanels () {
const modal = this.core.getState().modal
const newModalTargets = modal.targets.slice()
newModalTargets.forEach((target) => {
if (target.type === 'acquirer') {
target.isHidden = true
}
})
this.core.setState({modal: Object.assign({}, modal, {
targets: newModalTargets
})})
}
showPanel (id) {
const modal = this.core.getState().modal
// hide all panels, except the one that matches current id
@ -78,7 +95,7 @@ export default class Modal extends Plugin {
if (target.id === id) {
target.focus()
return Object.assign({}, target, {
isHidden: target.isHidden !== true
isHidden: false
})
}
return Object.assign({}, target, {
@ -168,6 +185,12 @@ export default class Modal extends Plugin {
})
}
actions () {
this.core.emitter.on('file-add', () => {
this.hideAllPanels()
})
}
handleDrop (files) {
this.core.log('All right, someone dropped something...')
@ -218,7 +241,7 @@ export default class Modal extends Plugin {
tabindex="0"
aria-controls="${this.opts.panelSelectorPrefix}--${target.id}"
aria-selected="${target.isHidden ? 'false' : 'true'}"
onclick=${this.toggleTabPanel.bind(this, target.id)}>
onclick=${this.showPanel.bind(this, target.id)}>
${target.icon}
<h5 class="UppyModalTab-name">${target.name}</h5>
</button>
@ -234,7 +257,7 @@ export default class Modal extends Plugin {
<div class="UppyModalContent-bar">
<h2 class="UppyModalContent-title">Import From ${target.name}</h2>
<button class="UppyModalContent-back"
onclick=${this.toggleTabPanel.bind(this, target.id)}>Back</button>
onclick=${this.hideAllPanels}>Back</button>
</div>
${target.render(state)}
</div>`
@ -265,6 +288,7 @@ export default class Modal extends Plugin {
this.target = this.mount(target, plugin)
this.initEvents()
this.actions()
dragDrop(this.opts.target, (files) => {
this.handleDrop(files)

View file

@ -2,7 +2,7 @@
import Plugin from './Plugin'
// Orchestrators
import Modal from './modal'
import Modal from './Modal'
// Acquirers
import Dummy from './Dummy'

View file

@ -6,7 +6,7 @@
height: 100%;
position: relative;
padding: 0 20px;
padding-top: 40px;
padding-top: 50px;
}
.UppyDashboard-title {
@ -18,7 +18,7 @@
margin: 0;
padding: 0;
position: absolute;
top: 15px;
top: 18px;
left: 0;
width: 100%;
text-align: center;
@ -33,18 +33,15 @@
padding: 0;
overflow: scroll;
height: 100%;
// position: absolute;
// top: 50px;
// bottom: 15px;
// right: 15px;
// left: 0;
// padding: 15px;
padding-top: 10px;
}
.UppyDashboardItem {
list-style: none;
margin: 0;
width: 140px;
height: 200px;
overflow: hidden;
float: left;
padding-top: 20px;
margin: 0 15px;
@ -53,13 +50,14 @@
}
.UppyDashboardItem-icon {
width: 100px;
height: 100px;
width: 90px;
height: 90px;
margin: auto;
border-radius: 8px;
overflow: hidden;
box-shadow: inset 0 0 0 1px rgba($color-black, 0.1);
// box-shadow: inset 0 0 0 1px rgba($color-black, 0.1);
margin-bottom: 10px;
color: $color-orange;
}
.UppyDashboardItem-icon img {
@ -69,12 +67,12 @@
}
.UppyDashboardItem-name {
font-size: 13px;
line-height: 1.4;
font-size: 12px;
line-height: 1.35;
font-weight: bold;
margin: 0;
padding: 0;
margin-bottom: 8px;
margin-bottom: 3px;
}
.UppyDashboardItem-name a {
@ -85,16 +83,17 @@
.UppyDashboardItem-status {
margin: 0;
padding: 0;
font-size: 12px;
font-size: 11px;
line-height: 1.45;
font-weight: normal;
color: $color-gray;
text-transform: uppercase;
}
.UppyDashboardItem-action {
position: absolute;
top: 10px;
right: -6px;
right: 0;
}
.UppyDashboardItem-remove {
@ -106,15 +105,18 @@
width: 85px;
height: 4px;
margin: auto;
background-color: lighten($color-cornflower-blue, 50%);
position: absolute;
top: 100px;
top: 90px;
left: 0;
right: 0;
border-radius: 8px;
overflow: hidden;
}
.UppyDashboardItem-progress.is-active {
background-color: lighten($color-cornflower-blue, 50%);
}
.UppyDashboardItem-progressInner {
height: 4px;
background-color: $color-cornflower-blue;

View file

@ -24,8 +24,10 @@
.UppyModal-inner {
@include clearfix;
background-color: darken($color-white, 4%);
height: 80vh;
width: 65%;
height: 80vh;
max-width: 800px;
max-height: 600px;
position: fixed;
top: 50%;
left: 50%;
@ -39,7 +41,7 @@
.UppyModal-close {
position: absolute;
top: 10px;
top: 15px;
right: 15px;
padding: 0;
border: 0;
@ -92,7 +94,7 @@
.UppyModalTab-name {
font-size: 10px;
margin: 8px 0;
margin: 6px 0;
font-weight: normal;
}
@ -136,14 +138,14 @@
position: absolute;
top: 0;
left: 0;
height: 40px;
height: 50px;
width: 100%;
border-bottom: 1px solid rgba($color-gray, 0.3);
}
.UppyModalContent-title {
position: absolute;
top: 10px;
top: 15px;
left: 0;
right: 0;
text-align: center;
@ -155,7 +157,7 @@
.UppyModalContent-back {
@include reset-button;
position: absolute;
top: 12px;
top: 17px;
left: 15px;
font-size: 14px;
cursor: pointer;
@ -172,8 +174,8 @@
bottom: 0;
left: 0;
right: 0;
transform: translate3d(0, -105%, 0);
transition: all 0.5s;
transform: translateY(-105%);
transition: all 0.5s ease-in-out;
background-color: darken($color-white, 4%);
box-shadow: 0 0 10px 5px rgba($color-black, 0.15);
padding: 15px;
@ -182,7 +184,7 @@
}
.UppyModalContent-panel[aria-hidden=false] {
transform: translate3d(0, 0, 0);
transform: translateY(0);
}
// Progress bar placeholder

View file

@ -5,6 +5,7 @@ $color-black: #000;
$color-gray: #939393;
$color-pink: #e02177;
$color-green: #7AC824;
$color-orange: #F6A623;
$color-white: #fff;
$color-cornflower-blue: #4A90E2;
$color-asphalt-gray: #525252;

View file

@ -1,7 +1,7 @@
import Uppy from '../../../../src/core/Core.js'
import Dummy from '../../../../src/plugins/Dummy'
import Tus10 from '../../../../src/plugins/Tus10.js'
import Modal from '../../../../src/plugins/modal'
import Modal from '../../../../src/plugins/Modal'
import DragDrop from '../../../../src/plugins/DragDrop.js'
import GoogleDrive from '../../../../src/plugins/GoogleDrive.js'
import ProgressBar from '../../../../src/plugins/ProgressBar.js'