diff --git a/.eslintrc.js b/.eslintrc.js index 950799469f..27f2f42a47 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -85,7 +85,7 @@ module.exports = { 'no-param-reassign': ['warn'], 'no-redeclare': ['warn'], 'no-shadow': ['warn'], - 'no-use-before-define': ['warn'], + 'no-use-before-define': ['warn', { 'functions': false }], 'radix': ['warn'], 'react/button-has-type': 'error', 'react/destructuring-assignment': ['warn'], diff --git a/.github/workflows/cdn.yml b/.github/workflows/cdn.yml index 2c02dd41ab..da256c5afc 100644 --- a/.github/workflows/cdn.yml +++ b/.github/workflows/cdn.yml @@ -12,9 +12,9 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - name: Install Node.js - uses: actions/setup-node@v2-beta + uses: actions/setup-node@v2 with: - node-version: 14.x + node-version: 16.x - name: Install npm 7 run: npm install --global npm@7 - name: Install dependencies diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad0f4eeb9e..f6a5ee3e11 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,12 +7,12 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [12.x, 14.x] + node-version: [12.x, 14.x, 16.x] steps: - name: Checkout sources uses: actions/checkout@v2 - name: Install Node.js - uses: actions/setup-node@v2-beta + uses: actions/setup-node@v2 with: node-version: ${{matrix.node-version}} - name: Install npm 7 @@ -29,7 +29,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - name: Install Node.js - uses: actions/setup-node@v2-beta + uses: actions/setup-node@v2 with: node-version: 14.x - name: Install npm 7 @@ -46,7 +46,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - name: Install Node.js - uses: actions/setup-node@v2-beta + uses: actions/setup-node@v2 with: node-version: 14.x - name: Install npm 7 @@ -63,7 +63,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - name: Install Node.js - uses: actions/setup-node@v2-beta + uses: actions/setup-node@v2 with: node-version: 14.x - name: Install npm 7 diff --git a/.github/workflows/companion.yml b/.github/workflows/companion.yml index 32ca8a937e..8daa048e86 100644 --- a/.github/workflows/companion.yml +++ b/.github/workflows/companion.yml @@ -12,7 +12,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - name: Install Node.js - uses: actions/setup-node@v2-beta + uses: actions/setup-node@v2 with: node-version: ${{matrix.node-version}} - name: Install npm 7 diff --git a/.github/workflows/end-to-end.yml b/.github/workflows/end-to-end.yml index 8371c18668..6b6da4d124 100644 --- a/.github/workflows/end-to-end.yml +++ b/.github/workflows/end-to-end.yml @@ -15,7 +15,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - name: Install Node.js - uses: actions/setup-node@v2-beta + uses: actions/setup-node@v2 with: node-version: 14.x - name: Install npm 7 diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 781090d795..5de6346c19 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -12,7 +12,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v2 - name: Install Node.js - uses: actions/setup-node@v2-beta + uses: actions/setup-node@v2 with: node-version: 14.x - name: Install npm 7 diff --git a/BACKLOG.md b/BACKLOG.md index e73cf9a67c..7387eba168 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -50,7 +50,6 @@ PRs are welcome! Please do open an issue to discuss first if it's a big feature, - [ ] Display data like image resolution on file cards. should be done by thumbnail generator maybe #783 - [ ] Possibility to edit/delete more than one file at once. example: add copyrigh info to 1000 files #118, #97 - [ ] Possibility to work on already uploaded / in progress files. We'll just provide the `fileId` to the `file-edit-complete` event so that folks can more easily roll out custom code for this themselves #112, #113, #2063 -- [ ] Show upload speed too if `showProgressDetails: true`. Maybe have separate options for which things are displayed, or at least have css-classes that can be hidden with `display: none` #766 - [ ] Focus jumps weirdly if you remove a file https://github.com/transloadit/uppy/pull/2161#issuecomment-613565486 - [ ] A mini UI that features drop & progress (may involve a `mini: true` options for dashboard, may involve drop+progress or new plugin) (@arturi) - [ ] Add a Load More button so you don't have to TAB endlessly to get to the upload button (https://github.com/transloadit/uppy/issues/1419) diff --git a/BUNDLE-README.md b/BUNDLE-README.md index 613876674b..4043acbbad 100644 --- a/BUNDLE-README.md +++ b/BUNDLE-README.md @@ -1,7 +1,7 @@ # Uppy Hi, thanks for trying out the bundled version of the Uppy File Uploader. You can use -this from a CDN (e.g. ``) or bundle it with your webapp. +this from a CDN (e.g. ``) or bundle it with your webapp. Note that the recommended way to use Uppy is to install it with yarn/npm and use a bundler like Webpack so that you can create a smaller custom build with just the diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a89e4dc33..88147db2b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,41 @@ Please add your entries in this format: In the current stage we aim to release a new version at least every month. +## 2.1.1 + +Released: 2021-09-20 + +| Package | Version | Package | Version | +|-|-|-|-| +| @uppy/angular | 0.2.3 | @uppy/progress-bar | 2.0.2 | +| @uppy/aws-s3-multipart | 2.0.3 | @uppy/provider-views | 2.0.2 | +| @uppy/aws-s3 | 2.0.3 | @uppy/react-native | 0.2.2 | +| @uppy/box | 1.0.2 | @uppy/react | 2.0.3 | +| @uppy/companion-client | 2.0.1 | @uppy/robodog | 2.0.4 | +| @uppy/core | 2.0.3 | @uppy/screen-capture | 2.0.2 | +| @uppy/dashboard | 2.0.3 | @uppy/status-bar | 2.0.2 | +| @uppy/drag-drop | 2.0.2 | @uppy/svelte | 1.0.3 | +| @uppy/drop-target | 1.0.2 | @uppy/thumbnail-generator | 2.0.3 | +| @uppy/dropbox | 2.0.2 | @uppy/transloadit | 2.0.2 | +| @uppy/facebook | 2.0.2 | @uppy/tus | 2.0.2 | +| @uppy/file-input | 2.0.2 | @uppy/unsplash | 1.0.2 | +| @uppy/form | 2.0.2 | @uppy/url | 2.0.2 | +| @uppy/golden-retriever | 2.0.3 | @uppy/utils | 4.0.1 | +| @uppy/google-drive | 2.0.2 | @uppy/vue | 0.4.1 | +| @uppy/image-editor | 1.0.2 | @uppy/webcam | 2.0.2 | +| @uppy/informer | 2.0.2 | @uppy/xhr-upload | 2.0.3 | +| @uppy/instagram | 2.0.2 | @uppy/zoom | 1.0.2 | +| @uppy/locales | 2.0.1 | uppy | 2.1.1 | +| @uppy/onedrive | 2.0.2 | - | - | + +- @uppy/unsplash: Fix "attempted to use private field on non-instance" in `SearchProvider` (#3201) +- @uppy/locales: Add 'done' to `nb_NO.js` (#3200) +- @uppy/transloadit: Fix unhandledPromiseRejection failures (#3197) +- @uppy/aws-s3-multipart: Fix AbortController is not defined on Node.js (Server Side Render) (#3169) +- @uppy/aws-s3-multipart: Fix `net::ERR_OUT_OF_MEMORY` (#3183) +- @uppy/dashboard: Fix `autoOpenFileEditor` (#3186) +- @uppy/dashboard: Update Google Drive for brand compliance (#3178) + ## 2.1.0 Released: 2021-09-01 diff --git a/README.md b/README.md index b8ba6c919d..708e71863e 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ $ npm install @uppy/core @uppy/dashboard @uppy/tus We recommend installing from npm and then using a module bundler such as [Webpack](https://webpack.js.org/), [Browserify](http://browserify.org/) or [Rollup.js](http://rollupjs.org/). -Add CSS [uppy.min.css](https://releases.transloadit.com/uppy/v2.1.0/uppy.min.css), either to your HTML page's `` or include in JS, if your bundler of choice supports it — transforms and plugins are available for Browserify and Webpack. +Add CSS [uppy.min.css](https://releases.transloadit.com/uppy/v2.1.1/uppy.min.css), either to your HTML page's `` or include in JS, if your bundler of choice supports it — transforms and plugins are available for Browserify and Webpack. Alternatively, you can also use a pre-built bundle from Transloadit's CDN: Edgly. In that case `Uppy` will attach itself to the global `window.Uppy` object. @@ -77,10 +77,10 @@ Alternatively, you can also use a pre-built bundle from Transloadit's CDN: Edgly ```html - + - +
@@ -190,7 +190,7 @@ If you're using Uppy from CDN, those polyfills are already included in the legac bundle, so no need to include anything additionally: ```html - + ``` ## FAQ @@ -251,189 +251,193 @@ Use Uppy in your project? [Let us know](https://github.com/transloadit/uppy/issu :---: |:---: |:---: |:---: |:---: |:---: | [arturi](https://github.com/arturi) |[goto-bus-stop](https://github.com/goto-bus-stop) |[kvz](https://github.com/kvz) |[ifedapoolarewaju](https://github.com/ifedapoolarewaju) |[hedgerh](https://github.com/hedgerh) |[AJvanLoon](https://github.com/AJvanLoon) | -[nqst](https://github.com/nqst) |[aduh95](https://github.com/aduh95) |[lakesare](https://github.com/lakesare) |[kiloreux](https://github.com/kiloreux) |[Murderlon](https://github.com/Murderlon) |[sadovnychyi](https://github.com/sadovnychyi) | +[nqst](https://github.com/nqst) |[aduh95](https://github.com/aduh95) |[lakesare](https://github.com/lakesare) |[Murderlon](https://github.com/Murderlon) |[kiloreux](https://github.com/kiloreux) |[sadovnychyi](https://github.com/sadovnychyi) | :---: |:---: |:---: |:---: |:---: |:---: | -[nqst](https://github.com/nqst) |[aduh95](https://github.com/aduh95) |[lakesare](https://github.com/lakesare) |[kiloreux](https://github.com/kiloreux) |[Murderlon](https://github.com/Murderlon) |[sadovnychyi](https://github.com/sadovnychyi) | +[nqst](https://github.com/nqst) |[aduh95](https://github.com/aduh95) |[lakesare](https://github.com/lakesare) |[Murderlon](https://github.com/Murderlon) |[kiloreux](https://github.com/kiloreux) |[sadovnychyi](https://github.com/sadovnychyi) | -[samuelayo](https://github.com/samuelayo) |[richardwillars](https://github.com/richardwillars) |[ajkachnic](https://github.com/ajkachnic) |[dependabot[bot]](https://github.com/apps/dependabot) |[mifi](https://github.com/mifi) |[zcallan](https://github.com/zcallan) | +[samuelayo](https://github.com/samuelayo) |[richardwillars](https://github.com/richardwillars) |[ajkachnic](https://github.com/ajkachnic) |[mifi](https://github.com/mifi) |[dependabot[bot]](https://github.com/apps/dependabot) |[zcallan](https://github.com/zcallan) | :---: |:---: |:---: |:---: |:---: |:---: | -[samuelayo](https://github.com/samuelayo) |[richardwillars](https://github.com/richardwillars) |[ajkachnic](https://github.com/ajkachnic) |[dependabot[bot]](https://github.com/apps/dependabot) |[mifi](https://github.com/mifi) |[zcallan](https://github.com/zcallan) | +[samuelayo](https://github.com/samuelayo) |[richardwillars](https://github.com/richardwillars) |[ajkachnic](https://github.com/ajkachnic) |[mifi](https://github.com/mifi) |[dependabot[bot]](https://github.com/apps/dependabot) |[zcallan](https://github.com/zcallan) | [tim-kos](https://github.com/tim-kos) |[janko](https://github.com/janko) |[wilkoklak](https://github.com/wilkoklak) |[oliverpool](https://github.com/oliverpool) |[Botz](https://github.com/Botz) |[mcallistertyler](https://github.com/mcallistertyler) | :---: |:---: |:---: |:---: |:---: |:---: | [tim-kos](https://github.com/tim-kos) |[janko](https://github.com/janko) |[wilkoklak](https://github.com/wilkoklak) |[oliverpool](https://github.com/oliverpool) |[Botz](https://github.com/Botz) |[mcallistertyler](https://github.com/mcallistertyler) | -[mokutsu-coursera](https://github.com/mokutsu-coursera) |[DJWassink](https://github.com/DJWassink) |[taoqf](https://github.com/taoqf) |[tuoxiansp](https://github.com/tuoxiansp) |[dominiceden](https://github.com/dominiceden) |[elenalape](https://github.com/elenalape) | +[mokutsu-coursera](https://github.com/mokutsu-coursera) |[YukeshShr](https://github.com/YukeshShr) |[DJWassink](https://github.com/DJWassink) |[taoqf](https://github.com/taoqf) |[tuoxiansp](https://github.com/tuoxiansp) |[dominiceden](https://github.com/dominiceden) | :---: |:---: |:---: |:---: |:---: |:---: | -[mokutsu-coursera](https://github.com/mokutsu-coursera) |[DJWassink](https://github.com/DJWassink) |[taoqf](https://github.com/taoqf) |[tuoxiansp](https://github.com/tuoxiansp) |[dominiceden](https://github.com/dominiceden) |[elenalape](https://github.com/elenalape) | +[mokutsu-coursera](https://github.com/mokutsu-coursera) |[YukeshShr](https://github.com/YukeshShr) |[DJWassink](https://github.com/DJWassink) |[taoqf](https://github.com/taoqf) |[tuoxiansp](https://github.com/tuoxiansp) |[dominiceden](https://github.com/dominiceden) | -[mejiaej](https://github.com/mejiaej) |[gavboulton](https://github.com/gavboulton) |[Hawxy](https://github.com/Hawxy) |[bertho-zero](https://github.com/bertho-zero) |[tranvansang](https://github.com/tranvansang) |[ap--](https://github.com/ap--) | +[elenalape](https://github.com/elenalape) |[mejiaej](https://github.com/mejiaej) |[gavboulton](https://github.com/gavboulton) |[Hawxy](https://github.com/Hawxy) |[bertho-zero](https://github.com/bertho-zero) |[tranvansang](https://github.com/tranvansang) | :---: |:---: |:---: |:---: |:---: |:---: | -[mejiaej](https://github.com/mejiaej) |[gavboulton](https://github.com/gavboulton) |[Hawxy](https://github.com/Hawxy) |[bertho-zero](https://github.com/bertho-zero) |[tranvansang](https://github.com/tranvansang) |[ap--](https://github.com/ap--) | +[elenalape](https://github.com/elenalape) |[mejiaej](https://github.com/mejiaej) |[gavboulton](https://github.com/gavboulton) |[Hawxy](https://github.com/Hawxy) |[bertho-zero](https://github.com/bertho-zero) |[tranvansang](https://github.com/tranvansang) | -[mrbatista](https://github.com/mrbatista) |[MikeKovarik](https://github.com/MikeKovarik) |[pauln](https://github.com/pauln) |[szh](https://github.com/szh) |[toadkicker](https://github.com/toadkicker) |[ofhope](https://github.com/ofhope) | +[ap--](https://github.com/ap--) |[mrbatista](https://github.com/mrbatista) |[MikeKovarik](https://github.com/MikeKovarik) |[pauln](https://github.com/pauln) |[szh](https://github.com/szh) |[toadkicker](https://github.com/toadkicker) | :---: |:---: |:---: |:---: |:---: |:---: | -[mrbatista](https://github.com/mrbatista) |[MikeKovarik](https://github.com/MikeKovarik) |[pauln](https://github.com/pauln) |[szh](https://github.com/szh) |[toadkicker](https://github.com/toadkicker) |[ofhope](https://github.com/ofhope) | +[ap--](https://github.com/ap--) |[mrbatista](https://github.com/mrbatista) |[MikeKovarik](https://github.com/MikeKovarik) |[pauln](https://github.com/pauln) |[szh](https://github.com/szh) |[toadkicker](https://github.com/toadkicker) | -[johnnyperkins](https://github.com/johnnyperkins) |[dargmuesli](https://github.com/dargmuesli) |[juliangruber](https://github.com/juliangruber) |[manuelkiessling](https://github.com/manuelkiessling) |[nndevstudio](https://github.com/nndevstudio) |[ogtfaber](https://github.com/ogtfaber) | +[ofhope](https://github.com/ofhope) |[johnnyperkins](https://github.com/johnnyperkins) |[dargmuesli](https://github.com/dargmuesli) |[juliangruber](https://github.com/juliangruber) |[manuelkiessling](https://github.com/manuelkiessling) |[nndevstudio](https://github.com/nndevstudio) | :---: |:---: |:---: |:---: |:---: |:---: | -[johnnyperkins](https://github.com/johnnyperkins) |[dargmuesli](https://github.com/dargmuesli) |[juliangruber](https://github.com/juliangruber) |[manuelkiessling](https://github.com/manuelkiessling) |[nndevstudio](https://github.com/nndevstudio) |[ogtfaber](https://github.com/ogtfaber) | +[ofhope](https://github.com/ofhope) |[johnnyperkins](https://github.com/johnnyperkins) |[dargmuesli](https://github.com/dargmuesli) |[juliangruber](https://github.com/juliangruber) |[manuelkiessling](https://github.com/manuelkiessling) |[nndevstudio](https://github.com/nndevstudio) | -[sksavant](https://github.com/sksavant) |[suchoproduction](https://github.com/suchoproduction) |[sunil-shrestha](https://github.com/sunil-shrestha) |[timodwhit](https://github.com/timodwhit) |[yonahforst](https://github.com/yonahforst) |[a-kriya](https://github.com/a-kriya) | +[ogtfaber](https://github.com/ogtfaber) |[sksavant](https://github.com/sksavant) |[suchoproduction](https://github.com/suchoproduction) |[sunil-shrestha](https://github.com/sunil-shrestha) |[timodwhit](https://github.com/timodwhit) |[yonahforst](https://github.com/yonahforst) | :---: |:---: |:---: |:---: |:---: |:---: | -[sksavant](https://github.com/sksavant) |[suchoproduction](https://github.com/suchoproduction) |[sunil-shrestha](https://github.com/sunil-shrestha) |[timodwhit](https://github.com/timodwhit) |[yonahforst](https://github.com/yonahforst) |[a-kriya](https://github.com/a-kriya) | +[ogtfaber](https://github.com/ogtfaber) |[sksavant](https://github.com/sksavant) |[suchoproduction](https://github.com/suchoproduction) |[sunil-shrestha](https://github.com/sunil-shrestha) |[timodwhit](https://github.com/timodwhit) |[yonahforst](https://github.com/yonahforst) | -[stephentuso](https://github.com/stephentuso) |[jhen0409](https://github.com/jhen0409) |[mskelton](https://github.com/mskelton) |[ahmedkandel](https://github.com/ahmedkandel) |[btrice](https://github.com/btrice) |[behnammodi](https://github.com/behnammodi) | +[a-kriya](https://github.com/a-kriya) |[stephentuso](https://github.com/stephentuso) |[jhen0409](https://github.com/jhen0409) |[mskelton](https://github.com/mskelton) |[ahmedkandel](https://github.com/ahmedkandel) |[btrice](https://github.com/btrice) | :---: |:---: |:---: |:---: |:---: |:---: | -[stephentuso](https://github.com/stephentuso) |[jhen0409](https://github.com/jhen0409) |[mskelton](https://github.com/mskelton) |[ahmedkandel](https://github.com/ahmedkandel) |[btrice](https://github.com/btrice) |[behnammodi](https://github.com/behnammodi) | +[a-kriya](https://github.com/a-kriya) |[stephentuso](https://github.com/stephentuso) |[jhen0409](https://github.com/jhen0409) |[mskelton](https://github.com/mskelton) |[ahmedkandel](https://github.com/ahmedkandel) |[btrice](https://github.com/btrice) | -[craigjennings11](https://github.com/craigjennings11) |[davekiss](https://github.com/davekiss) |[DenysNosov](https://github.com/DenysNosov) |[ethanwillis](https://github.com/ethanwillis) |[frobinsonj](https://github.com/frobinsonj) |[geertclerx](https://github.com/geertclerx) | +[behnammodi](https://github.com/behnammodi) |[BePo65](https://github.com/BePo65) |[Burkes](https://github.com/Burkes) |[craigjennings11](https://github.com/craigjennings11) |[davekiss](https://github.com/davekiss) |[DenysNosov](https://github.com/DenysNosov) | :---: |:---: |:---: |:---: |:---: |:---: | -[craigjennings11](https://github.com/craigjennings11) |[davekiss](https://github.com/davekiss) |[DenysNosov](https://github.com/DenysNosov) |[ethanwillis](https://github.com/ethanwillis) |[frobinsonj](https://github.com/frobinsonj) |[geertclerx](https://github.com/geertclerx) | +[behnammodi](https://github.com/behnammodi) |[BePo65](https://github.com/BePo65) |[Burkes](https://github.com/Burkes) |[craigjennings11](https://github.com/craigjennings11) |[davekiss](https://github.com/davekiss) |[DenysNosov](https://github.com/DenysNosov) | -[ghasrfakhri](https://github.com/ghasrfakhri) |[jasonbosco](https://github.com/jasonbosco) |[jedwood](https://github.com/jedwood) |[dogrocker](https://github.com/dogrocker) |[lamartire](https://github.com/lamartire) |[Mactaivsh](https://github.com/Mactaivsh) | +[ethanwillis](https://github.com/ethanwillis) |[frobinsonj](https://github.com/frobinsonj) |[geertclerx](https://github.com/geertclerx) |[ghasrfakhri](https://github.com/ghasrfakhri) |[jasonbosco](https://github.com/jasonbosco) |[jedwood](https://github.com/jedwood) | :---: |:---: |:---: |:---: |:---: |:---: | -[ghasrfakhri](https://github.com/ghasrfakhri) |[jasonbosco](https://github.com/jasonbosco) |[jedwood](https://github.com/jedwood) |[dogrocker](https://github.com/dogrocker) |[lamartire](https://github.com/lamartire) |[Mactaivsh](https://github.com/Mactaivsh) | +[ethanwillis](https://github.com/ethanwillis) |[frobinsonj](https://github.com/frobinsonj) |[geertclerx](https://github.com/geertclerx) |[ghasrfakhri](https://github.com/ghasrfakhri) |[jasonbosco](https://github.com/jasonbosco) |[jedwood](https://github.com/jedwood) | -[maferland](https://github.com/maferland) |[Martin005](https://github.com/Martin005) |[martiuslim](https://github.com/martiuslim) |[MatthiasKunnen](https://github.com/MatthiasKunnen) |[msand](https://github.com/msand) |[paescuj](https://github.com/paescuj) | +[dogrocker](https://github.com/dogrocker) |[lamartire](https://github.com/lamartire) |[Mactaivsh](https://github.com/Mactaivsh) |[maferland](https://github.com/maferland) |[Martin005](https://github.com/Martin005) |[martiuslim](https://github.com/martiuslim) | :---: |:---: |:---: |:---: |:---: |:---: | -[maferland](https://github.com/maferland) |[Martin005](https://github.com/Martin005) |[martiuslim](https://github.com/martiuslim) |[MatthiasKunnen](https://github.com/MatthiasKunnen) |[msand](https://github.com/msand) |[paescuj](https://github.com/paescuj) | +[dogrocker](https://github.com/dogrocker) |[lamartire](https://github.com/lamartire) |[Mactaivsh](https://github.com/Mactaivsh) |[maferland](https://github.com/maferland) |[Martin005](https://github.com/Martin005) |[martiuslim](https://github.com/martiuslim) | -[richartkeil](https://github.com/richartkeil) |[richmeij](https://github.com/richmeij) |[rosenfeld](https://github.com/rosenfeld) |[jrschumacher](https://github.com/jrschumacher) |[ThomasG77](https://github.com/ThomasG77) |[sparanoid](https://github.com/sparanoid) | +[MatthiasKunnen](https://github.com/MatthiasKunnen) |[msand](https://github.com/msand) |[paescuj](https://github.com/paescuj) |[richartkeil](https://github.com/richartkeil) |[richmeij](https://github.com/richmeij) |[rosenfeld](https://github.com/rosenfeld) | :---: |:---: |:---: |:---: |:---: |:---: | -[richartkeil](https://github.com/richartkeil) |[richmeij](https://github.com/richmeij) |[rosenfeld](https://github.com/rosenfeld) |[jrschumacher](https://github.com/jrschumacher) |[ThomasG77](https://github.com/ThomasG77) |[sparanoid](https://github.com/sparanoid) | +[MatthiasKunnen](https://github.com/MatthiasKunnen) |[msand](https://github.com/msand) |[paescuj](https://github.com/paescuj) |[richartkeil](https://github.com/richartkeil) |[richmeij](https://github.com/richmeij) |[rosenfeld](https://github.com/rosenfeld) | -[zhuangya](https://github.com/zhuangya) |[YukeshShr](https://github.com/YukeshShr) |[allenfantasy](https://github.com/allenfantasy) |[Zyclotrop-j](https://github.com/Zyclotrop-j) |[anark](https://github.com/anark) |[fortrieb](https://github.com/fortrieb) | +[jrschumacher](https://github.com/jrschumacher) |[ThomasG77](https://github.com/ThomasG77) |[sparanoid](https://github.com/sparanoid) |[zhuangya](https://github.com/zhuangya) |[allenfantasy](https://github.com/allenfantasy) |[Zyclotrop-j](https://github.com/Zyclotrop-j) | :---: |:---: |:---: |:---: |:---: |:---: | -[zhuangya](https://github.com/zhuangya) |[YukeshShr](https://github.com/YukeshShr) |[allenfantasy](https://github.com/allenfantasy) |[Zyclotrop-j](https://github.com/Zyclotrop-j) |[anark](https://github.com/anark) |[fortrieb](https://github.com/fortrieb) | +[jrschumacher](https://github.com/jrschumacher) |[ThomasG77](https://github.com/ThomasG77) |[sparanoid](https://github.com/sparanoid) |[zhuangya](https://github.com/zhuangya) |[allenfantasy](https://github.com/allenfantasy) |[Zyclotrop-j](https://github.com/Zyclotrop-j) | -[fortrieb](https://github.com/fortrieb) |[jarey](https://github.com/jarey) |[muhammadInam](https://github.com/muhammadInam) |[rettgerst](https://github.com/rettgerst) |[mkabatek](https://github.com/mkabatek) |[jukakoski](https://github.com/jukakoski) | +[anark](https://github.com/anark) |[fortrieb](https://github.com/fortrieb) |[jarey](https://github.com/jarey) |[muhammadInam](https://github.com/muhammadInam) |[rettgerst](https://github.com/rettgerst) |[mkabatek](https://github.com/mkabatek) | :---: |:---: |:---: |:---: |:---: |:---: | -[fortrieb](https://github.com/fortrieb) |[jarey](https://github.com/jarey) |[muhammadInam](https://github.com/muhammadInam) |[rettgerst](https://github.com/rettgerst) |[mkabatek](https://github.com/mkabatek) |[jukakoski](https://github.com/jukakoski) | +[anark](https://github.com/anark) |[fortrieb](https://github.com/fortrieb) |[jarey](https://github.com/jarey) |[muhammadInam](https://github.com/muhammadInam) |[rettgerst](https://github.com/rettgerst) |[mkabatek](https://github.com/mkabatek) | -[olemoign](https://github.com/olemoign) |[ajschmidt8](https://github.com/ajschmidt8) |[superhawk610](https://github.com/superhawk610) |[abannach](https://github.com/abannach) |[adamelmore](https://github.com/adamelmore) |[ajh-sr](https://github.com/ajh-sr) | +[jukakoski](https://github.com/jukakoski) |[olemoign](https://github.com/olemoign) |[ajschmidt8](https://github.com/ajschmidt8) |[superhawk610](https://github.com/superhawk610) |[abannach](https://github.com/abannach) |[adamelmore](https://github.com/adamelmore) | :---: |:---: |:---: |:---: |:---: |:---: | -[olemoign](https://github.com/olemoign) |[ajschmidt8](https://github.com/ajschmidt8) |[superhawk610](https://github.com/superhawk610) |[abannach](https://github.com/abannach) |[adamelmore](https://github.com/adamelmore) |[ajh-sr](https://github.com/ajh-sr) | +[jukakoski](https://github.com/jukakoski) |[olemoign](https://github.com/olemoign) |[ajschmidt8](https://github.com/ajschmidt8) |[superhawk610](https://github.com/superhawk610) |[abannach](https://github.com/abannach) |[adamelmore](https://github.com/adamelmore) | -[adamvigneault](https://github.com/adamvigneault) |[adritasharma](https://github.com/adritasharma) |[asmt3](https://github.com/asmt3) |[alexnj](https://github.com/alexnj) |[aalepis](https://github.com/aalepis) |[Dogfalo](https://github.com/Dogfalo) | +[ajh-sr](https://github.com/ajh-sr) |[adamvigneault](https://github.com/adamvigneault) |[Adrrei](https://github.com/Adrrei) |[adritasharma](https://github.com/adritasharma) |[asmt3](https://github.com/asmt3) |[alexnj](https://github.com/alexnj) | :---: |:---: |:---: |:---: |:---: |:---: | -[adamvigneault](https://github.com/adamvigneault) |[adritasharma](https://github.com/adritasharma) |[asmt3](https://github.com/asmt3) |[alexnj](https://github.com/alexnj) |[aalepis](https://github.com/aalepis) |[Dogfalo](https://github.com/Dogfalo) | +[ajh-sr](https://github.com/ajh-sr) |[adamvigneault](https://github.com/adamvigneault) |[Adrrei](https://github.com/Adrrei) |[adritasharma](https://github.com/adritasharma) |[asmt3](https://github.com/asmt3) |[alexnj](https://github.com/alexnj) | -[tekacs](https://github.com/tekacs) |[amitport](https://github.com/amitport) |[functino](https://github.com/functino) |[radarhere](https://github.com/radarhere) |[superandrew213](https://github.com/superandrew213) |[andychongyz](https://github.com/andychongyz) | +[aalepis](https://github.com/aalepis) |[Dogfalo](https://github.com/Dogfalo) |[tekacs](https://github.com/tekacs) |[amitport](https://github.com/amitport) |[functino](https://github.com/functino) |[radarhere](https://github.com/radarhere) | :---: |:---: |:---: |:---: |:---: |:---: | -[tekacs](https://github.com/tekacs) |[amitport](https://github.com/amitport) |[functino](https://github.com/functino) |[radarhere](https://github.com/radarhere) |[superandrew213](https://github.com/superandrew213) |[andychongyz](https://github.com/andychongyz) | +[aalepis](https://github.com/aalepis) |[Dogfalo](https://github.com/Dogfalo) |[tekacs](https://github.com/tekacs) |[amitport](https://github.com/amitport) |[functino](https://github.com/functino) |[radarhere](https://github.com/radarhere) | -[anthony0030](https://github.com/anthony0030) |[Abourass](https://github.com/Abourass) |[arthurdenner](https://github.com/arthurdenner) |[apuyou](https://github.com/apuyou) |[atsawin](https://github.com/atsawin) |[ayhankesicioglu](https://github.com/ayhankesicioglu) | +[superandrew213](https://github.com/superandrew213) |[andychongyz](https://github.com/andychongyz) |[anthony0030](https://github.com/anthony0030) |[Abourass](https://github.com/Abourass) |[arthurdenner](https://github.com/arthurdenner) |[apuyou](https://github.com/apuyou) | :---: |:---: |:---: |:---: |:---: |:---: | -[anthony0030](https://github.com/anthony0030) |[Abourass](https://github.com/Abourass) |[arthurdenner](https://github.com/arthurdenner) |[apuyou](https://github.com/apuyou) |[atsawin](https://github.com/atsawin) |[ayhankesicioglu](https://github.com/ayhankesicioglu) | +[superandrew213](https://github.com/superandrew213) |[andychongyz](https://github.com/andychongyz) |[anthony0030](https://github.com/anthony0030) |[Abourass](https://github.com/Abourass) |[arthurdenner](https://github.com/arthurdenner) |[apuyou](https://github.com/apuyou) | -[azeemba](https://github.com/azeemba) |[azizk](https://github.com/azizk) |[bducharme](https://github.com/bducharme) |[Quorafind](https://github.com/Quorafind) |[wbaaron](https://github.com/wbaaron) |[bedgerotto](https://github.com/bedgerotto) | +[atsawin](https://github.com/atsawin) |[ayhankesicioglu](https://github.com/ayhankesicioglu) |[azeemba](https://github.com/azeemba) |[azizk](https://github.com/azizk) |[bducharme](https://github.com/bducharme) |[Quorafind](https://github.com/Quorafind) | :---: |:---: |:---: |:---: |:---: |:---: | -[azeemba](https://github.com/azeemba) |[azizk](https://github.com/azizk) |[bducharme](https://github.com/bducharme) |[Quorafind](https://github.com/Quorafind) |[wbaaron](https://github.com/wbaaron) |[bedgerotto](https://github.com/bedgerotto) | +[atsawin](https://github.com/atsawin) |[ayhankesicioglu](https://github.com/ayhankesicioglu) |[azeemba](https://github.com/azeemba) |[azizk](https://github.com/azizk) |[bducharme](https://github.com/bducharme) |[Quorafind](https://github.com/Quorafind) | -[cyu](https://github.com/cyu) |[cartfisk](https://github.com/cartfisk) |[cellvinchung](https://github.com/cellvinchung) |[chao](https://github.com/chao) |[csprance](https://github.com/csprance) |[Aarbel](https://github.com/Aarbel) | +[wbaaron](https://github.com/wbaaron) |[bedgerotto](https://github.com/bedgerotto) |[cyu](https://github.com/cyu) |[cartfisk](https://github.com/cartfisk) |[cellvinchung](https://github.com/cellvinchung) |[chao](https://github.com/chao) | :---: |:---: |:---: |:---: |:---: |:---: | -[cyu](https://github.com/cyu) |[cartfisk](https://github.com/cartfisk) |[cellvinchung](https://github.com/cellvinchung) |[chao](https://github.com/chao) |[csprance](https://github.com/csprance) |[Aarbel](https://github.com/Aarbel) | +[wbaaron](https://github.com/wbaaron) |[bedgerotto](https://github.com/bedgerotto) |[cyu](https://github.com/cyu) |[cartfisk](https://github.com/cartfisk) |[cellvinchung](https://github.com/cellvinchung) |[chao](https://github.com/chao) | -[cbush06](https://github.com/cbush06) |[czj](https://github.com/czj) |[ardeois](https://github.com/ardeois) |[sercraig](https://github.com/sercraig) |[Cruaier](https://github.com/Cruaier) |[danmichaelo](https://github.com/danmichaelo) | +[csprance](https://github.com/csprance) |[Aarbel](https://github.com/Aarbel) |[cbush06](https://github.com/cbush06) |[czj](https://github.com/czj) |[ardeois](https://github.com/ardeois) |[sercraig](https://github.com/sercraig) | :---: |:---: |:---: |:---: |:---: |:---: | -[cbush06](https://github.com/cbush06) |[czj](https://github.com/czj) |[ardeois](https://github.com/ardeois) |[sercraig](https://github.com/sercraig) |[Cruaier](https://github.com/Cruaier) |[danmichaelo](https://github.com/danmichaelo) | +[csprance](https://github.com/csprance) |[Aarbel](https://github.com/Aarbel) |[cbush06](https://github.com/cbush06) |[czj](https://github.com/czj) |[ardeois](https://github.com/ardeois) |[sercraig](https://github.com/sercraig) | -[mrboomer](https://github.com/mrboomer) |[akizor](https://github.com/akizor) |[davilima6](https://github.com/davilima6) |[DennisKofflard](https://github.com/DennisKofflard) |[jeetiss](https://github.com/jeetiss) |[sweetro](https://github.com/sweetro) | +[Cruaier](https://github.com/Cruaier) |[danmichaelo](https://github.com/danmichaelo) |[mrboomer](https://github.com/mrboomer) |[akizor](https://github.com/akizor) |[davilima6](https://github.com/davilima6) |[DennisKofflard](https://github.com/DennisKofflard) | :---: |:---: |:---: |:---: |:---: |:---: | -[mrboomer](https://github.com/mrboomer) |[akizor](https://github.com/akizor) |[davilima6](https://github.com/davilima6) |[DennisKofflard](https://github.com/DennisKofflard) |[jeetiss](https://github.com/jeetiss) |[sweetro](https://github.com/sweetro) | +[Cruaier](https://github.com/Cruaier) |[danmichaelo](https://github.com/danmichaelo) |[mrboomer](https://github.com/mrboomer) |[akizor](https://github.com/akizor) |[davilima6](https://github.com/davilima6) |[DennisKofflard](https://github.com/DennisKofflard) | -[efbautista](https://github.com/efbautista) |[yoldar](https://github.com/yoldar) |[eliOcs](https://github.com/eliOcs) |[EnricoSottile](https://github.com/EnricoSottile) |[Gkleinereva](https://github.com/Gkleinereva) |[fgallinari](https://github.com/fgallinari) | +[jeetiss](https://github.com/jeetiss) |[sweetro](https://github.com/sweetro) |[efbautista](https://github.com/efbautista) |[yoldar](https://github.com/yoldar) |[eliOcs](https://github.com/eliOcs) |[EnricoSottile](https://github.com/EnricoSottile) | :---: |:---: |:---: |:---: |:---: |:---: | -[efbautista](https://github.com/efbautista) |[yoldar](https://github.com/yoldar) |[eliOcs](https://github.com/eliOcs) |[EnricoSottile](https://github.com/EnricoSottile) |[Gkleinereva](https://github.com/Gkleinereva) |[fgallinari](https://github.com/fgallinari) | +[jeetiss](https://github.com/jeetiss) |[sweetro](https://github.com/sweetro) |[efbautista](https://github.com/efbautista) |[yoldar](https://github.com/yoldar) |[eliOcs](https://github.com/eliOcs) |[EnricoSottile](https://github.com/EnricoSottile) | -[ferdiusa](https://github.com/ferdiusa) |[dtrucs](https://github.com/dtrucs) |[geoffappleford](https://github.com/geoffappleford) |[gjungb](https://github.com/gjungb) |[roenschg](https://github.com/roenschg) |[HughbertD](https://github.com/HughbertD) | +[Gkleinereva](https://github.com/Gkleinereva) |[fgallinari](https://github.com/fgallinari) |[ferdiusa](https://github.com/ferdiusa) |[dtrucs](https://github.com/dtrucs) |[geoffappleford](https://github.com/geoffappleford) |[gjungb](https://github.com/gjungb) | :---: |:---: |:---: |:---: |:---: |:---: | -[ferdiusa](https://github.com/ferdiusa) |[dtrucs](https://github.com/dtrucs) |[geoffappleford](https://github.com/geoffappleford) |[gjungb](https://github.com/gjungb) |[roenschg](https://github.com/roenschg) |[HughbertD](https://github.com/HughbertD) | +[Gkleinereva](https://github.com/Gkleinereva) |[fgallinari](https://github.com/fgallinari) |[ferdiusa](https://github.com/ferdiusa) |[dtrucs](https://github.com/dtrucs) |[geoffappleford](https://github.com/geoffappleford) |[gjungb](https://github.com/gjungb) | -[HussainAlkhalifah](https://github.com/HussainAlkhalifah) |[huydod](https://github.com/huydod) |[IanVS](https://github.com/IanVS) |[ishendyweb](https://github.com/ishendyweb) |[NaxYo](https://github.com/NaxYo) |[intenzive](https://github.com/intenzive) | +[roenschg](https://github.com/roenschg) |[HughbertD](https://github.com/HughbertD) |[HussainAlkhalifah](https://github.com/HussainAlkhalifah) |[huydod](https://github.com/huydod) |[IanVS](https://github.com/IanVS) |[ishendyweb](https://github.com/ishendyweb) | :---: |:---: |:---: |:---: |:---: |:---: | -[HussainAlkhalifah](https://github.com/HussainAlkhalifah) |[huydod](https://github.com/huydod) |[IanVS](https://github.com/IanVS) |[ishendyweb](https://github.com/ishendyweb) |[NaxYo](https://github.com/NaxYo) |[intenzive](https://github.com/intenzive) | +[roenschg](https://github.com/roenschg) |[HughbertD](https://github.com/HughbertD) |[HussainAlkhalifah](https://github.com/HussainAlkhalifah) |[huydod](https://github.com/huydod) |[IanVS](https://github.com/IanVS) |[ishendyweb](https://github.com/ishendyweb) | -[GreenJimmy](https://github.com/GreenJimmy) |[mazoruss](https://github.com/mazoruss) |[JacobMGEvans](https://github.com/JacobMGEvans) |[jdssem](https://github.com/jdssem) |[Jbithell](https://github.com/Jbithell) |[jcjmcclean](https://github.com/jcjmcclean) | +[NaxYo](https://github.com/NaxYo) |[intenzive](https://github.com/intenzive) |[GreenJimmy](https://github.com/GreenJimmy) |[mazoruss](https://github.com/mazoruss) |[JacobMGEvans](https://github.com/JacobMGEvans) |[jdssem](https://github.com/jdssem) | :---: |:---: |:---: |:---: |:---: |:---: | -[GreenJimmy](https://github.com/GreenJimmy) |[mazoruss](https://github.com/mazoruss) |[JacobMGEvans](https://github.com/JacobMGEvans) |[jdssem](https://github.com/jdssem) |[Jbithell](https://github.com/Jbithell) |[jcjmcclean](https://github.com/jcjmcclean) | +[NaxYo](https://github.com/NaxYo) |[intenzive](https://github.com/intenzive) |[GreenJimmy](https://github.com/GreenJimmy) |[mazoruss](https://github.com/mazoruss) |[JacobMGEvans](https://github.com/JacobMGEvans) |[jdssem](https://github.com/jdssem) | -[janklimo](https://github.com/janklimo) |[janwilts](https://github.com/janwilts) |[vith](https://github.com/vith) |[jessica-coursera](https://github.com/jessica-coursera) |[Jmales](https://github.com/Jmales) |[theJoeBiz](https://github.com/theJoeBiz) | +[Jbithell](https://github.com/Jbithell) |[jcjmcclean](https://github.com/jcjmcclean) |[janklimo](https://github.com/janklimo) |[janwilts](https://github.com/janwilts) |[vith](https://github.com/vith) |[jessica-coursera](https://github.com/jessica-coursera) | :---: |:---: |:---: |:---: |:---: |:---: | -[janklimo](https://github.com/janklimo) |[janwilts](https://github.com/janwilts) |[vith](https://github.com/vith) |[jessica-coursera](https://github.com/jessica-coursera) |[Jmales](https://github.com/Jmales) |[theJoeBiz](https://github.com/theJoeBiz) | +[Jbithell](https://github.com/Jbithell) |[jcjmcclean](https://github.com/jcjmcclean) |[janklimo](https://github.com/janklimo) |[janwilts](https://github.com/janwilts) |[vith](https://github.com/vith) |[jessica-coursera](https://github.com/jessica-coursera) | -[profsmallpine](https://github.com/profsmallpine) |[jonathanarbely](https://github.com/jonathanarbely) |[jderrough](https://github.com/jderrough) |[jonathanly](https://github.com/jonathanly) |[jorgeepc](https://github.com/jorgeepc) |[jszobody](https://github.com/jszobody) | +[Jmales](https://github.com/Jmales) |[theJoeBiz](https://github.com/theJoeBiz) |[profsmallpine](https://github.com/profsmallpine) |[jonathanarbely](https://github.com/jonathanarbely) |[jderrough](https://github.com/jderrough) |[jonathanly](https://github.com/jonathanly) | :---: |:---: |:---: |:---: |:---: |:---: | -[profsmallpine](https://github.com/profsmallpine) |[jonathanarbely](https://github.com/jonathanarbely) |[jderrough](https://github.com/jderrough) |[jonathanly](https://github.com/jonathanly) |[jorgeepc](https://github.com/jorgeepc) |[jszobody](https://github.com/jszobody) | +[Jmales](https://github.com/Jmales) |[theJoeBiz](https://github.com/theJoeBiz) |[profsmallpine](https://github.com/profsmallpine) |[jonathanarbely](https://github.com/jonathanarbely) |[jderrough](https://github.com/jderrough) |[jonathanly](https://github.com/jonathanly) | -[jszobody](https://github.com/jszobody) |[julianocomg](https://github.com/julianocomg) |[jmontoyaa](https://github.com/jmontoyaa) |[firesharkstudios](https://github.com/firesharkstudios) |[elkebab](https://github.com/elkebab) |[kyleparisi](https://github.com/kyleparisi) | +[jorgeepc](https://github.com/jorgeepc) |[jszobody](https://github.com/jszobody) |[julianocomg](https://github.com/julianocomg) |[jmontoyaa](https://github.com/jmontoyaa) |[firesharkstudios](https://github.com/firesharkstudios) |[elkebab](https://github.com/elkebab) | :---: |:---: |:---: |:---: |:---: |:---: | -[jszobody](https://github.com/jszobody) |[julianocomg](https://github.com/julianocomg) |[jmontoyaa](https://github.com/jmontoyaa) |[firesharkstudios](https://github.com/firesharkstudios) |[elkebab](https://github.com/elkebab) |[kyleparisi](https://github.com/kyleparisi) | +[jorgeepc](https://github.com/jorgeepc) |[jszobody](https://github.com/jszobody) |[julianocomg](https://github.com/julianocomg) |[jmontoyaa](https://github.com/jmontoyaa) |[firesharkstudios](https://github.com/firesharkstudios) |[elkebab](https://github.com/elkebab) | -[lafe](https://github.com/lafe) |[leaanthony](https://github.com/leaanthony) |[larowlan](https://github.com/larowlan) |[dviry](https://github.com/dviry) |[galli-leo](https://github.com/galli-leo) |[leods92](https://github.com/leods92) | +[kyleparisi](https://github.com/kyleparisi) |[lafe](https://github.com/lafe) |[leaanthony](https://github.com/leaanthony) |[larowlan](https://github.com/larowlan) |[dviry](https://github.com/dviry) |[galli-leo](https://github.com/galli-leo) | :---: |:---: |:---: |:---: |:---: |:---: | -[lafe](https://github.com/lafe) |[leaanthony](https://github.com/leaanthony) |[larowlan](https://github.com/larowlan) |[dviry](https://github.com/dviry) |[galli-leo](https://github.com/galli-leo) |[leods92](https://github.com/leods92) | +[kyleparisi](https://github.com/kyleparisi) |[lafe](https://github.com/lafe) |[leaanthony](https://github.com/leaanthony) |[larowlan](https://github.com/larowlan) |[dviry](https://github.com/dviry) |[galli-leo](https://github.com/galli-leo) | -[louim](https://github.com/louim) |[lucaperret](https://github.com/lucaperret) |[mperrando](https://github.com/mperrando) |[marcosthejew](https://github.com/marcosthejew) |[marcusforsberg](https://github.com/marcusforsberg) |[Acconut](https://github.com/Acconut) | +[leods92](https://github.com/leods92) |[louim](https://github.com/louim) |[lucaperret](https://github.com/lucaperret) |[onhate](https://github.com/onhate) |[mperrando](https://github.com/mperrando) |[marcosthejew](https://github.com/marcosthejew) | :---: |:---: |:---: |:---: |:---: |:---: | -[louim](https://github.com/louim) |[lucaperret](https://github.com/lucaperret) |[mperrando](https://github.com/mperrando) |[marcosthejew](https://github.com/marcosthejew) |[marcusforsberg](https://github.com/marcusforsberg) |[Acconut](https://github.com/Acconut) | +[leods92](https://github.com/leods92) |[louim](https://github.com/louim) |[lucaperret](https://github.com/lucaperret) |[onhate](https://github.com/onhate) |[mperrando](https://github.com/mperrando) |[marcosthejew](https://github.com/marcosthejew) | -[martin-brennan](https://github.com/martin-brennan) |[masaok](https://github.com/masaok) |[mattfik](https://github.com/mattfik) |[matthewhartstonge](https://github.com/matthewhartstonge) |[hrsh](https://github.com/hrsh) |[mhulet](https://github.com/mhulet) | +[marcusforsberg](https://github.com/marcusforsberg) |[Acconut](https://github.com/Acconut) |[martin-brennan](https://github.com/martin-brennan) |[masaok](https://github.com/masaok) |[mattfik](https://github.com/mattfik) |[matthewhartstonge](https://github.com/matthewhartstonge) | :---: |:---: |:---: |:---: |:---: |:---: | -[martin-brennan](https://github.com/martin-brennan) |[masaok](https://github.com/masaok) |[mattfik](https://github.com/mattfik) |[matthewhartstonge](https://github.com/matthewhartstonge) |[hrsh](https://github.com/hrsh) |[mhulet](https://github.com/mhulet) | +[marcusforsberg](https://github.com/marcusforsberg) |[Acconut](https://github.com/Acconut) |[martin-brennan](https://github.com/martin-brennan) |[masaok](https://github.com/masaok) |[mattfik](https://github.com/mattfik) |[matthewhartstonge](https://github.com/matthewhartstonge) | -[mkopinsky](https://github.com/mkopinsky) |[achmiral](https://github.com/achmiral) |[mnafees](https://github.com/mnafees) |[shahimclt](https://github.com/shahimclt) |[pleasespammelater](https://github.com/pleasespammelater) |[naveed-ahmad](https://github.com/naveed-ahmad) | +[hrsh](https://github.com/hrsh) |[mhulet](https://github.com/mhulet) |[mkopinsky](https://github.com/mkopinsky) |[achmiral](https://github.com/achmiral) |[mnafees](https://github.com/mnafees) |[shahimclt](https://github.com/shahimclt) | :---: |:---: |:---: |:---: |:---: |:---: | -[mkopinsky](https://github.com/mkopinsky) |[achmiral](https://github.com/achmiral) |[mnafees](https://github.com/mnafees) |[shahimclt](https://github.com/shahimclt) |[pleasespammelater](https://github.com/pleasespammelater) |[naveed-ahmad](https://github.com/naveed-ahmad) | +[hrsh](https://github.com/hrsh) |[mhulet](https://github.com/mhulet) |[mkopinsky](https://github.com/mkopinsky) |[achmiral](https://github.com/achmiral) |[mnafees](https://github.com/mnafees) |[shahimclt](https://github.com/shahimclt) | -[coreprocess](https://github.com/coreprocess) |[nil1511](https://github.com/nil1511) |[leftdevel](https://github.com/leftdevel) |[cryptic022](https://github.com/cryptic022) |[patricklindsay](https://github.com/patricklindsay) |[pedrofs](https://github.com/pedrofs) | +[shahimclt](https://github.com/shahimclt) |[pleasespammelater](https://github.com/pleasespammelater) |[naveed-ahmad](https://github.com/naveed-ahmad) |[nicojones](https://github.com/nicojones) |[coreprocess](https://github.com/coreprocess) |[nil1511](https://github.com/nil1511) | :---: |:---: |:---: |:---: |:---: |:---: | -[coreprocess](https://github.com/coreprocess) |[nil1511](https://github.com/nil1511) |[leftdevel](https://github.com/leftdevel) |[cryptic022](https://github.com/cryptic022) |[patricklindsay](https://github.com/patricklindsay) |[pedrofs](https://github.com/pedrofs) | +[shahimclt](https://github.com/shahimclt) |[pleasespammelater](https://github.com/pleasespammelater) |[naveed-ahmad](https://github.com/naveed-ahmad) |[nicojones](https://github.com/nicojones) |[coreprocess](https://github.com/coreprocess) |[nil1511](https://github.com/nil1511) | -[phillipalexander](https://github.com/phillipalexander) |[ppadmavilasom](https://github.com/ppadmavilasom) |[Pzoco](https://github.com/Pzoco) |[eman8519](https://github.com/eman8519) |[luarmr](https://github.com/luarmr) |[SxDx](https://github.com/SxDx) | +[leftdevel](https://github.com/leftdevel) |[cryptic022](https://github.com/cryptic022) |[patricklindsay](https://github.com/patricklindsay) |[pedrofs](https://github.com/pedrofs) |[phillipalexander](https://github.com/phillipalexander) |[ppadmavilasom](https://github.com/ppadmavilasom) | :---: |:---: |:---: |:---: |:---: |:---: | -[phillipalexander](https://github.com/phillipalexander) |[ppadmavilasom](https://github.com/ppadmavilasom) |[Pzoco](https://github.com/Pzoco) |[eman8519](https://github.com/eman8519) |[luarmr](https://github.com/luarmr) |[SxDx](https://github.com/SxDx) | +[leftdevel](https://github.com/leftdevel) |[cryptic022](https://github.com/cryptic022) |[patricklindsay](https://github.com/patricklindsay) |[pedrofs](https://github.com/pedrofs) |[phillipalexander](https://github.com/phillipalexander) |[ppadmavilasom](https://github.com/ppadmavilasom) | -[robwilson1](https://github.com/robwilson1) |[romain-preston](https://github.com/romain-preston) |[scherroman](https://github.com/scherroman) |[rossng](https://github.com/rossng) |[rart](https://github.com/rart) |[fortunto2](https://github.com/fortunto2) | +[Pzoco](https://github.com/Pzoco) |[eman8519](https://github.com/eman8519) |[luarmr](https://github.com/luarmr) |[SxDx](https://github.com/SxDx) |[robwilson1](https://github.com/robwilson1) |[romain-preston](https://github.com/romain-preston) | :---: |:---: |:---: |:---: |:---: |:---: | -[robwilson1](https://github.com/robwilson1) |[romain-preston](https://github.com/romain-preston) |[scherroman](https://github.com/scherroman) |[rossng](https://github.com/rossng) |[rart](https://github.com/rart) |[fortunto2](https://github.com/fortunto2) | +[Pzoco](https://github.com/Pzoco) |[eman8519](https://github.com/eman8519) |[luarmr](https://github.com/luarmr) |[SxDx](https://github.com/SxDx) |[robwilson1](https://github.com/robwilson1) |[romain-preston](https://github.com/romain-preston) | -[samuelcolburn](https://github.com/samuelcolburn) |[sergei-zelinsky](https://github.com/sergei-zelinsky) |[SpazzMarticus](https://github.com/SpazzMarticus) |[waptik](https://github.com/waptik) |[steverob](https://github.com/steverob) |[taj](https://github.com/taj) | +[scherroman](https://github.com/scherroman) |[rossng](https://github.com/rossng) |[rart](https://github.com/rart) |[fortunto2](https://github.com/fortunto2) |[samuelcolburn](https://github.com/samuelcolburn) |[sergei-zelinsky](https://github.com/sergei-zelinsky) | :---: |:---: |:---: |:---: |:---: |:---: | -[samuelcolburn](https://github.com/samuelcolburn) |[sergei-zelinsky](https://github.com/sergei-zelinsky) |[SpazzMarticus](https://github.com/SpazzMarticus) |[waptik](https://github.com/waptik) |[steverob](https://github.com/steverob) |[taj](https://github.com/taj) | +[scherroman](https://github.com/scherroman) |[rossng](https://github.com/rossng) |[rart](https://github.com/rart) |[fortunto2](https://github.com/fortunto2) |[samuelcolburn](https://github.com/samuelcolburn) |[sergei-zelinsky](https://github.com/sergei-zelinsky) | -[Tashows](https://github.com/Tashows) |[twarlop](https://github.com/twarlop) |[tmaier](https://github.com/tmaier) |[tomsaleeba](https://github.com/tomsaleeba) |[tvaliasek](https://github.com/tvaliasek) |[vially](https://github.com/vially) | +[SpazzMarticus](https://github.com/SpazzMarticus) |[waptik](https://github.com/waptik) |[steverob](https://github.com/steverob) |[taj](https://github.com/taj) |[Tashows](https://github.com/Tashows) |[twarlop](https://github.com/twarlop) | :---: |:---: |:---: |:---: |:---: |:---: | -[Tashows](https://github.com/Tashows) |[twarlop](https://github.com/twarlop) |[tmaier](https://github.com/tmaier) |[tomsaleeba](https://github.com/tomsaleeba) |[tvaliasek](https://github.com/tvaliasek) |[vially](https://github.com/vially) | +[SpazzMarticus](https://github.com/SpazzMarticus) |[waptik](https://github.com/waptik) |[steverob](https://github.com/steverob) |[taj](https://github.com/taj) |[Tashows](https://github.com/Tashows) |[twarlop](https://github.com/twarlop) | -[valentinoli](https://github.com/valentinoli) |[nagyv](https://github.com/nagyv) |[dwnste](https://github.com/dwnste) |[willycamargo](https://github.com/willycamargo) |[xhocquet](https://github.com/xhocquet) |[yaegor](https://github.com/yaegor) | +[tomsaleeba](https://github.com/tomsaleeba) |[tvaliasek](https://github.com/tvaliasek) |[vially](https://github.com/vially) |[valentinoli](https://github.com/valentinoli) |[nagyv](https://github.com/nagyv) |[dwnste](https://github.com/dwnste) | :---: |:---: |:---: |:---: |:---: |:---: | -[valentinoli](https://github.com/valentinoli) |[nagyv](https://github.com/nagyv) |[dwnste](https://github.com/dwnste) |[willycamargo](https://github.com/willycamargo) |[xhocquet](https://github.com/xhocquet) |[yaegor](https://github.com/yaegor) | +[tomsaleeba](https://github.com/tomsaleeba) |[tvaliasek](https://github.com/tvaliasek) |[vially](https://github.com/vially) |[valentinoli](https://github.com/valentinoli) |[nagyv](https://github.com/nagyv) |[dwnste](https://github.com/dwnste) | -[YehudaKremer](https://github.com/YehudaKremer) |[zachconner](https://github.com/zachconner) |[zacharylawson](https://github.com/zacharylawson) |[agreene-coursera](https://github.com/agreene-coursera) |[alfatv](https://github.com/alfatv) |[arggh](https://github.com/arggh) | +[willycamargo](https://github.com/willycamargo) |[xhocquet](https://github.com/xhocquet) |[yaegor](https://github.com/yaegor) |[YehudaKremer](https://github.com/YehudaKremer) |[zachconner](https://github.com/zachconner) |[zacharylawson](https://github.com/zacharylawson) | :---: |:---: |:---: |:---: |:---: |:---: | -[YehudaKremer](https://github.com/YehudaKremer) |[zachconner](https://github.com/zachconner) |[zacharylawson](https://github.com/zacharylawson) |[agreene-coursera](https://github.com/agreene-coursera) |[alfatv](https://github.com/alfatv) |[arggh](https://github.com/arggh) | +[willycamargo](https://github.com/willycamargo) |[xhocquet](https://github.com/xhocquet) |[yaegor](https://github.com/yaegor) |[YehudaKremer](https://github.com/YehudaKremer) |[zachconner](https://github.com/zachconner) |[zacharylawson](https://github.com/zacharylawson) | -[avalla](https://github.com/avalla) |[bdirito](https://github.com/bdirito) |[bencergazda](https://github.com/bencergazda) |[c0b41](https://github.com/c0b41) |[canvasbh](https://github.com/canvasbh) |[craigcbrunner](https://github.com/craigcbrunner) | +[agreene-coursera](https://github.com/agreene-coursera) |[alfatv](https://github.com/alfatv) |[arggh](https://github.com/arggh) |[avalla](https://github.com/avalla) |[bdirito](https://github.com/bdirito) |[bencergazda](https://github.com/bencergazda) | :---: |:---: |:---: |:---: |:---: |:---: | -[avalla](https://github.com/avalla) |[bdirito](https://github.com/bdirito) |[bencergazda](https://github.com/bencergazda) |[c0b41](https://github.com/c0b41) |[canvasbh](https://github.com/canvasbh) |[craigcbrunner](https://github.com/craigcbrunner) | +[agreene-coursera](https://github.com/agreene-coursera) |[alfatv](https://github.com/alfatv) |[arggh](https://github.com/arggh) |[avalla](https://github.com/avalla) |[bdirito](https://github.com/bdirito) |[bencergazda](https://github.com/bencergazda) | -[darthf1](https://github.com/darthf1) |[dkisic](https://github.com/dkisic) |[fingul](https://github.com/fingul) |[franckl](https://github.com/franckl) |[gaelicwinter](https://github.com/gaelicwinter) |[green-mike](https://github.com/green-mike) | +[c0b41](https://github.com/c0b41) |[canvasbh](https://github.com/canvasbh) |[christianwengert](https://github.com/christianwengert) |[craigcbrunner](https://github.com/craigcbrunner) |[darthf1](https://github.com/darthf1) |[dkisic](https://github.com/dkisic) | :---: |:---: |:---: |:---: |:---: |:---: | -[darthf1](https://github.com/darthf1) |[dkisic](https://github.com/dkisic) |[fingul](https://github.com/fingul) |[franckl](https://github.com/franckl) |[gaelicwinter](https://github.com/gaelicwinter) |[green-mike](https://github.com/green-mike) | +[c0b41](https://github.com/c0b41) |[canvasbh](https://github.com/canvasbh) |[christianwengert](https://github.com/christianwengert) |[craigcbrunner](https://github.com/craigcbrunner) |[darthf1](https://github.com/darthf1) |[dkisic](https://github.com/dkisic) | -[hxgf](https://github.com/hxgf) |[johnmanjiro13](https://github.com/johnmanjiro13) |[kode-ninja](https://github.com/kode-ninja) |[magumbo](https://github.com/magumbo) |[ninesalt](https://github.com/ninesalt) |[phil714](https://github.com/phil714) | +[fingul](https://github.com/fingul) |[franckl](https://github.com/franckl) |[gaelicwinter](https://github.com/gaelicwinter) |[green-mike](https://github.com/green-mike) |[hxgf](https://github.com/hxgf) |[johnmanjiro13](https://github.com/johnmanjiro13) | :---: |:---: |:---: |:---: |:---: |:---: | -[hxgf](https://github.com/hxgf) |[johnmanjiro13](https://github.com/johnmanjiro13) |[kode-ninja](https://github.com/kode-ninja) |[magumbo](https://github.com/magumbo) |[ninesalt](https://github.com/ninesalt) |[phil714](https://github.com/phil714) | +[fingul](https://github.com/fingul) |[franckl](https://github.com/franckl) |[gaelicwinter](https://github.com/gaelicwinter) |[green-mike](https://github.com/green-mike) |[hxgf](https://github.com/hxgf) |[johnmanjiro13](https://github.com/johnmanjiro13) | -[phil714](https://github.com/phil714) |[luntta](https://github.com/luntta) |[rhymes](https://github.com/rhymes) |[rlebosse](https://github.com/rlebosse) |[rtaieb](https://github.com/rtaieb) |[slawexxx44](https://github.com/slawexxx44) | +[johnmanjiro13](https://github.com/johnmanjiro13) |[kode-ninja](https://github.com/kode-ninja) |[magumbo](https://github.com/magumbo) |[ninesalt](https://github.com/ninesalt) |[phil714](https://github.com/phil714) |[luntta](https://github.com/luntta) | :---: |:---: |:---: |:---: |:---: |:---: | -[phil714](https://github.com/phil714) |[luntta](https://github.com/luntta) |[rhymes](https://github.com/rhymes) |[rlebosse](https://github.com/rlebosse) |[rtaieb](https://github.com/rtaieb) |[slawexxx44](https://github.com/slawexxx44) | +[johnmanjiro13](https://github.com/johnmanjiro13) |[kode-ninja](https://github.com/kode-ninja) |[magumbo](https://github.com/magumbo) |[ninesalt](https://github.com/ninesalt) |[phil714](https://github.com/phil714) |[luntta](https://github.com/luntta) | -[thanhthot](https://github.com/thanhthot) |[tinny77](https://github.com/tinny77) |[vedran555](https://github.com/vedran555) |[yoann-hellopret](https://github.com/yoann-hellopret) |[olitomas](https://github.com/olitomas) |[JimmyLv](https://github.com/JimmyLv) | +[rhymes](https://github.com/rhymes) |[rlebosse](https://github.com/rlebosse) |[rtaieb](https://github.com/rtaieb) |[slawexxx44](https://github.com/slawexxx44) |[thanhthot](https://github.com/thanhthot) |[tinny77](https://github.com/tinny77) | :---: |:---: |:---: |:---: |:---: |:---: | -[thanhthot](https://github.com/thanhthot) |[tinny77](https://github.com/tinny77) |[vedran555](https://github.com/vedran555) |[yoann-hellopret](https://github.com/yoann-hellopret) |[olitomas](https://github.com/olitomas) |[JimmyLv](https://github.com/JimmyLv) | +[rhymes](https://github.com/rhymes) |[rlebosse](https://github.com/rlebosse) |[rtaieb](https://github.com/rtaieb) |[slawexxx44](https://github.com/slawexxx44) |[thanhthot](https://github.com/thanhthot) |[tinny77](https://github.com/tinny77) | + +[vedran555](https://github.com/vedran555) |[yoann-hellopret](https://github.com/yoann-hellopret) |[olitomas](https://github.com/olitomas) |[JimmyLv](https://github.com/JimmyLv) | +:---: |:---: |:---: |:---: | +[vedran555](https://github.com/vedran555) |[yoann-hellopret](https://github.com/yoann-hellopret) |[olitomas](https://github.com/olitomas) |[JimmyLv](https://github.com/JimmyLv) | diff --git a/examples/cdn-example/index.html b/examples/cdn-example/index.html index f51a5c1217..e8702283a3 100644 --- a/examples/cdn-example/index.html +++ b/examples/cdn-example/index.html @@ -4,11 +4,11 @@ - + - + + + + ``` Then, a global `Robodog` variable will be available. For usage instructions, please see the [main Robodog documentation](https://uppy.io/docs/robodog). diff --git a/packages/@uppy/robodog/package.json b/packages/@uppy/robodog/package.json index ddbecff686..6b93c6d72d 100644 --- a/packages/@uppy/robodog/package.json +++ b/packages/@uppy/robodog/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/robodog", "description": "Transloadit SDK for browsers based on Uppy", - "version": "2.0.3", + "version": "2.0.4", "license": "MIT", "main": "lib/index.js", "jsnext:main": "src/index.js", diff --git a/packages/@uppy/screen-capture/package.json b/packages/@uppy/screen-capture/package.json index e94695cba4..e574b77979 100644 --- a/packages/@uppy/screen-capture/package.json +++ b/packages/@uppy/screen-capture/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/screen-capture", "description": "Uppy plugin that captures video from display or application.", - "version": "2.0.1", + "version": "2.0.2", "license": "MIT", "main": "lib/index.js", "style": "dist/style.min.css", diff --git a/packages/@uppy/status-bar/package.json b/packages/@uppy/status-bar/package.json index 2db55dbaaf..926446c67d 100644 --- a/packages/@uppy/status-bar/package.json +++ b/packages/@uppy/status-bar/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/status-bar", "description": "A progress bar for Uppy, with many bells and whistles.", - "version": "2.0.1", + "version": "2.0.2", "license": "MIT", "main": "lib/index.js", "style": "dist/style.min.css", diff --git a/packages/@uppy/status-bar/src/Components.js b/packages/@uppy/status-bar/src/Components.js new file mode 100644 index 0000000000..24b8902be5 --- /dev/null +++ b/packages/@uppy/status-bar/src/Components.js @@ -0,0 +1,446 @@ +const classNames = require('classnames') +const throttle = require('lodash.throttle') +const prettierBytes = require('@transloadit/prettier-bytes') +const prettyETA = require('@uppy/utils/lib/prettyETA') +const { h } = require('preact') + +const statusBarStates = require('./StatusBarStates') + +const DOT = `\u00B7` +const renderDot = () => ` ${DOT} ` + +function UploadBtn (props) { + const { + newFiles, + isUploadStarted, + recoveredState, + i18n, + uploadState, + isSomeGhost, + startUpload, + } = props + + const uploadBtnClassNames = classNames( + 'uppy-u-reset', + 'uppy-c-btn', + 'uppy-StatusBar-actionBtn', + 'uppy-StatusBar-actionBtn--upload', + { + 'uppy-c-btn-primary': uploadState === statusBarStates.STATE_WAITING, + }, + { 'uppy-StatusBar-actionBtn--disabled': isSomeGhost } + ) + + const uploadBtnText + = newFiles && isUploadStarted && !recoveredState + ? i18n('uploadXNewFiles', { smart_count: newFiles }) + : i18n('uploadXFiles', { smart_count: newFiles }) + + return ( + + ) +} + +function RetryBtn (props) { + const { i18n, uppy } = props + + return ( + + ) +} + +function CancelBtn (props) { + const { i18n, uppy } = props + + return ( + + ) +} + +function PauseResumeButton (props) { + const { isAllPaused, i18n, isAllComplete, resumableUploads, uppy } = props + const title = isAllPaused ? i18n('resume') : i18n('pause') + + function togglePauseResume () { + if (isAllComplete) return null + + if (!resumableUploads) { + return uppy.cancelAll() + } + + if (isAllPaused) { + return uppy.resumeAll() + } + + return uppy.pauseAll() + } + + return ( + + ) +} + +function DoneBtn (props) { + const { i18n, doneButtonHandler } = props + + return ( + + ) +} + +function LoadingSpinner () { + return ( + + ) +} + +function ProgressBarProcessing (props) { + const { value, mode, message } = props + const roundedValue = Math.round(value * 100) + const dot = `\u00B7` + + return ( +
+ + {mode === 'determinate' ? `${roundedValue}% ${dot} ` : ''} + {message} +
+ ) +} + +function ProgressDetails (props) { + const { + numUploads, + complete, + totalUploadedSize, + totalSize, + totalETA, + i18n, + } = props + + const ifShowFilesUploadedOfTotal = numUploads > 1 + + return ( +
+ {ifShowFilesUploadedOfTotal + && i18n('filesUploadedOfTotal', { + complete, + smart_count: numUploads, + })} + + {/* When should we render this dot? + 1. .-additionalInfo is shown (happens only on desktops) + 2. AND 'filesUploadedOfTotal' was shown + */} + {ifShowFilesUploadedOfTotal && renderDot()} + + {i18n('dataUploadedOfTotal', { + complete: prettierBytes(totalUploadedSize), + total: prettierBytes(totalSize), + })} + + {renderDot()} + + {i18n('xTimeLeft', { + time: prettyETA(totalETA), + })} + +
+ ) +} + +function UnknownProgressDetails (props) { + const { i18n, complete, numUploads } = props + + return ( +
+ {i18n('filesUploadedOfTotal', { complete, smart_count: numUploads })} +
+ ) +} + +function UploadNewlyAddedFiles (props) { + const { i18n, newFiles, startUpload } = props + const uploadBtnClassNames = classNames( + 'uppy-u-reset', + 'uppy-c-btn', + 'uppy-StatusBar-actionBtn', + 'uppy-StatusBar-actionBtn--uploadNewlyAdded' + ) + + return ( +
+
+ {i18n('xMoreFilesAdded', { smart_count: newFiles })} +
+ +
+ ) +} + +const ThrottledProgressDetails = throttle(ProgressDetails, 500, { + leading: true, + trailing: true, +}) + +function ProgressBarUploading (props) { + const { + i18n, + supportsUploadProgress, + totalProgress, + showProgressDetails, + isUploadStarted, + isAllComplete, + isAllPaused, + newFiles, + numUploads, + complete, + totalUploadedSize, + totalSize, + totalETA, + startUpload, + } = props + const showUploadNewlyAddedFiles = newFiles && isUploadStarted + + if (!isUploadStarted || isAllComplete) { + return null + } + + const title = isAllPaused ? i18n('paused') : i18n('uploading') + + function renderProgressDetails () { + if (!isAllPaused && !showUploadNewlyAddedFiles && showProgressDetails) { + if (supportsUploadProgress) { + return ( + + ) + } + return ( + + ) + } + return null + } + + return ( +
+ {!isAllPaused ? : null} +
+
+ {supportsUploadProgress ? `${title}: ${totalProgress}%` : title} +
+ + {renderProgressDetails()} + + {showUploadNewlyAddedFiles ? ( + + ) : null} +
+
+ ) +} + +function ProgressBarComplete (props) { + const { i18n } = props + + return ( +
+
+
+ + {i18n('complete')} +
+
+
+ ) +} + +function ProgressBarError (props) { + const { error, i18n } = props + + function displayErrorAlert () { + const errorMessage = `${i18n('uploadFailed')} \n\n ${error}` + // eslint-disable-next-line no-alert + alert(errorMessage) // TODO: move to custom alert implementation + } + + return ( +
+
+
+ + {i18n('uploadFailed')} +
+
+ +
+ ) +} + +module.exports = { + UploadBtn, + RetryBtn, + CancelBtn, + PauseResumeButton, + DoneBtn, + LoadingSpinner, + ProgressDetails, + ProgressBarProcessing, + ProgressBarError, + ProgressBarUploading, + ProgressBarComplete, +} diff --git a/packages/@uppy/status-bar/src/StatusBar.js b/packages/@uppy/status-bar/src/StatusBar.js index d87ae6d3d5..bbd412d4bc 100644 --- a/packages/@uppy/status-bar/src/StatusBar.js +++ b/packages/@uppy/status-bar/src/StatusBar.js @@ -1,57 +1,32 @@ -const throttle = require('lodash.throttle') -const classNames = require('classnames') -const prettierBytes = require('@transloadit/prettier-bytes') -const prettyETA = require('@uppy/utils/lib/prettyETA') const { h } = require('preact') +const classNames = require('classnames') const statusBarStates = require('./StatusBarStates') - -function calculateProcessingProgress (files) { - // Collect pre or postprocessing progress states. - const progresses = [] - Object.keys(files).forEach((fileID) => { - const { progress } = files[fileID] - if (progress.preprocess) { - progresses.push(progress.preprocess) - } - if (progress.postprocess) { - progresses.push(progress.postprocess) - } - }) - - // In the future we should probably do this differently. For now we'll take the - // mode and message from the first file… - const { mode, message } = progresses[0] - const value = progresses.filter(isDeterminate).reduce((total, progress, index, all) => { - return total + progress.value / all.length - }, 0) - function isDeterminate (progress) { - return progress.mode === 'determinate' - } - - return { - mode, - message, - value, - } -} - -function togglePauseResume (props) { - if (props.isAllComplete) return - - if (!props.resumableUploads) { - return props.uppy.cancelAll() - } - - if (props.isAllPaused) { - return props.uppy.resumeAll() - } - - return props.uppy.pauseAll() -} - -module.exports = (props) => { - props = props || {} - +const calculateProcessingProgress = require('./calculateProcessingProgress') + +const { + UploadBtn, + RetryBtn, + CancelBtn, + PauseResumeButton, + DoneBtn, + ProgressBarProcessing, + ProgressBarError, + ProgressBarUploading, + ProgressBarComplete, +} = require('./Components') + +const { + STATE_ERROR, + STATE_WAITING, + STATE_PREPROCESSING, + STATE_UPLOADING, + STATE_POSTPROCESSING, + STATE_COMPLETE, +} = statusBarStates + +module.exports = StatusBar + +function StatusBar (props) { const { newFiles, allowNewUpload, @@ -64,68 +39,122 @@ module.exports = (props) => { hideCancelButton, hideRetryButton, recoveredState, + uploadState, + totalProgress, + files, + supportsUploadProgress, + hideAfterFinish, + isSomeGhost, + isTargetDOMEl, + doneButtonHandler, + isUploadStarted, + i18n, + startUpload, + uppy, + isAllComplete, + showProgressDetails, + numUploads, + complete, + totalSize, + totalETA, + totalUploadedSize, } = props - const { uploadState } = props + function getProgressValue () { + switch (uploadState) { + case STATE_POSTPROCESSING: + case STATE_PREPROCESSING: { + const progress = calculateProcessingProgress(files) - let progressValue = props.totalProgress - let progressMode - let progressBarContent + if (progress.mode === 'determinate') { + return progress.value * 100 + } + return totalProgress + } + case STATE_ERROR: { + return null + } + case STATE_UPLOADING: { + if (!supportsUploadProgress) { + return null + } + return totalProgress + } + default: + return totalProgress + } + } - if (uploadState === statusBarStates.STATE_PREPROCESSING || uploadState === statusBarStates.STATE_POSTPROCESSING) { - const progress = calculateProcessingProgress(props.files) - progressMode = progress.mode - if (progressMode === 'determinate') { - progressValue = progress.value * 100 + function getIsIndeterminate () { + switch (uploadState) { + case STATE_POSTPROCESSING: + case STATE_PREPROCESSING: { + const { mode } = calculateProcessingProgress(files) + return mode === 'indeterminate' + } + case STATE_UPLOADING: { + if (!supportsUploadProgress) { + return true + } + return false + } + default: + return false } + } - progressBarContent = ProgressBarProcessing(progress) - } else if (uploadState === statusBarStates.STATE_COMPLETE) { - progressBarContent = ProgressBarComplete(props) - } else if (uploadState === statusBarStates.STATE_UPLOADING) { - if (!props.supportsUploadProgress) { - progressMode = 'indeterminate' - progressValue = null + function getIsHidden () { + if (recoveredState) { + return false } - progressBarContent = ProgressBarUploading(props) - } else if (uploadState === statusBarStates.STATE_ERROR) { - progressValue = undefined - progressBarContent = ProgressBarError(props) + switch (uploadState) { + case STATE_WAITING: + return hideUploadButton || newFiles === 0 + case STATE_COMPLETE: + return hideAfterFinish + default: + return false + } } - const width = typeof progressValue === 'number' ? progressValue : 100 - let isHidden = (uploadState === statusBarStates.STATE_WAITING && props.hideUploadButton) - || (uploadState === statusBarStates.STATE_WAITING && !props.newFiles > 0) - || (uploadState === statusBarStates.STATE_COMPLETE && props.hideAfterFinish) + const progressValue = getProgressValue() - let showUploadBtn = !error && newFiles - && !isUploadInProgress && !isAllPaused - && allowNewUpload && !hideUploadButton + const isHidden = getIsHidden() - if (recoveredState) { - isHidden = false - showUploadBtn = true - } + const width = progressValue ?? 100 + + const showUploadBtn + = !error + && newFiles + && !isUploadInProgress + && !isAllPaused + && allowNewUpload + && !hideUploadButton - const showCancelBtn = !hideCancelButton - && uploadState !== statusBarStates.STATE_WAITING - && uploadState !== statusBarStates.STATE_COMPLETE - const showPauseResumeBtn = resumableUploads && !hidePauseResumeButton - && uploadState === statusBarStates.STATE_UPLOADING + const showCancelBtn + = !hideCancelButton + && uploadState !== STATE_WAITING + && uploadState !== STATE_COMPLETE + + const showPauseResumeBtn + = resumableUploads + && !hidePauseResumeButton + && uploadState === STATE_UPLOADING const showRetryBtn = error && !hideRetryButton - const showDoneBtn = props.doneButtonHandler && uploadState === statusBarStates.STATE_COMPLETE + const showDoneBtn = doneButtonHandler && uploadState === STATE_COMPLETE - const progressClassNames = `uppy-StatusBar-progress - ${progressMode ? `is-${progressMode}` : ''}` + const progressClassNames = classNames('uppy-StatusBar-progress', { + 'is-indeterminate': getIsIndeterminate(), + }) const statusBarClassNames = classNames( - { 'uppy-Root': props.isTargetDOMEl }, + { 'uppy-Root': isTargetDOMEl }, 'uppy-StatusBar', `is-${uploadState}`, - { 'has-ghosts': props.isSomeGhost } + { 'has-ghosts': isSomeGhost } ) return ( @@ -140,291 +169,75 @@ module.exports = (props) => { aria-valuemax="100" aria-valuenow={progressValue} /> - {progressBarContent} -
- {showUploadBtn ? : null} - {showRetryBtn ? : null} - {showPauseResumeBtn ? : null} - {showCancelBtn ? : null} - {showDoneBtn ? : null} -
- - ) -} - -const UploadBtn = (props) => { - const uploadBtnClassNames = classNames( - 'uppy-u-reset', - 'uppy-c-btn', - 'uppy-StatusBar-actionBtn', - 'uppy-StatusBar-actionBtn--upload', - { 'uppy-c-btn-primary': props.uploadState === statusBarStates.STATE_WAITING }, - { 'uppy-StatusBar-actionBtn--disabled': props.isSomeGhost } - ) - - const uploadBtnText = props.newFiles && props.isUploadStarted && !props.recoveredState - ? props.i18n('uploadXNewFiles', { smart_count: props.newFiles }) - : props.i18n('uploadXFiles', { smart_count: props.newFiles }) - - return ( - - ) -} - -const RetryBtn = (props) => { - return ( - - ) -} -const CancelBtn = (props) => { - return ( - - ) -} - -const PauseResumeButton = (props) => { - const { isAllPaused, i18n } = props - const title = isAllPaused ? i18n('resume') : i18n('pause') - - return ( - - ) -} - -const DoneBtn = (props) => { - const { i18n } = props - return ( - - ) -} - -const LoadingSpinner = () => { - return ( - - ) -} - -const ProgressBarProcessing = (props) => { - const value = Math.round(props.value * 100) - - return ( -
- - {props.mode === 'determinate' ? `${value}% \u00B7 ` : ''} - {props.message} -
- ) -} - -const renderDot = () => ' \u00B7 ' - -const ProgressDetails = (props) => { - const ifShowFilesUploadedOfTotal = props.numUploads > 1 - - return ( -
- { - ifShowFilesUploadedOfTotal - && props.i18n('filesUploadedOfTotal', { - complete: props.complete, - smart_count: props.numUploads, - }) - } - - {/* When should we render this dot? - 1. .-additionalInfo is shown (happens only on desktops) - 2. AND 'filesUploadedOfTotal' was shown - */} - {ifShowFilesUploadedOfTotal && renderDot()} - - { - props.i18n('dataUploadedOfTotal', { - complete: prettierBytes(props.totalUploadedSize), - total: prettierBytes(props.totalSize), - }) + {(() => { + switch (uploadState) { + case STATE_PREPROCESSING: + case STATE_POSTPROCESSING: + return ( + + ) + case STATE_COMPLETE: + return + case STATE_ERROR: + return + case STATE_UPLOADING: + return ( + + ) + default: + return null } + })()} - {renderDot()} - - { - props.i18n('xTimeLeft', { - time: prettyETA(props.totalETA), - }) - } - -
- ) -} - -const UnknownProgressDetails = (props) => { - return ( -
- {props.i18n('filesUploadedOfTotal', { complete: props.complete, smart_count: props.numUploads })} -
- ) -} - -const UploadNewlyAddedFiles = (props) => { - const uploadBtnClassNames = classNames( - 'uppy-u-reset', - 'uppy-c-btn', - 'uppy-StatusBar-actionBtn', - 'uppy-StatusBar-actionBtn--uploadNewlyAdded' - ) - - return ( -
-
- {props.i18n('xMoreFilesAdded', { smart_count: props.newFiles })} -
- -
- ) -} - -const ThrottledProgressDetails = throttle(ProgressDetails, 500, { leading: true, trailing: true }) - -const ProgressBarUploading = (props) => { - if (!props.isUploadStarted || props.isAllComplete) { - return null - } - - const title = props.isAllPaused ? props.i18n('paused') : props.i18n('uploading') - const showUploadNewlyAddedFiles = props.newFiles && props.isUploadStarted - - return ( -
- {!props.isAllPaused ? : null} -
-
- {props.supportsUploadProgress ? `${title}: ${props.totalProgress}%` : title} -
- {/* eslint-disable-next-line no-nested-ternary */} - {!props.isAllPaused && !showUploadNewlyAddedFiles && props.showProgressDetails - ? (props.supportsUploadProgress ? : ) - : null} - {showUploadNewlyAddedFiles ? : null} -
-
- ) -} - -const ProgressBarComplete = ({ i18n }) => { - return ( -
-
-
- - {i18n('complete')} -
-
-
- ) -} - -const ProgressBarError = ({ error, i18n }) => { - function displayErrorAlert () { - const errorMessage = `${i18n('uploadFailed')} \n\n ${error}` - // eslint-disable-next-line no-alert - alert(errorMessage) // TODO: move to custom alert implementation - } - - return ( -
-
-
- - {i18n('uploadFailed')} -
+
+ {(recoveredState || showUploadBtn) ? ( + + ) : null} + + {showRetryBtn ? : null} + + {showPauseResumeBtn ? ( + + ) : null} + + {showCancelBtn ? : null} + + {showDoneBtn ? ( + + ) : null}
-
) } diff --git a/packages/@uppy/status-bar/src/calculateProcessingProgress.js b/packages/@uppy/status-bar/src/calculateProcessingProgress.js new file mode 100644 index 0000000000..2864022fbf --- /dev/null +++ b/packages/@uppy/status-bar/src/calculateProcessingProgress.js @@ -0,0 +1,26 @@ +module.export = function calculateProcessingProgress (files) { + const values = [] + let mode + let message + + for (const { progress } of Object.values(files)) { + const { preprocess, postprocess } = progress + // In the future we should probably do this differently. For now we'll take the + // mode and message from the first file… + if (message == null && (preprocess || postprocess)) { + ({ mode, message } = preprocess || postprocess) + } + if (preprocess?.mode === 'determinate') values.push(preprocess.value) + if (postprocess?.mode === 'determinate') values.push(postprocess.value) + } + + const value = values.reduce((total, progressValue) => { + return total + progressValue / values.length + }, 0) + + return { + mode, + message, + value, + } +} diff --git a/packages/@uppy/status-bar/src/index.js b/packages/@uppy/status-bar/src/index.js index a52b47a66e..30ca006ec5 100644 --- a/packages/@uppy/status-bar/src/index.js +++ b/packages/@uppy/status-bar/src/index.js @@ -10,7 +10,8 @@ const StatusBarUI = require('./StatusBar') * progress percentage and time remaining. */ module.exports = class StatusBar extends UIPlugin { - static VERSION = require('../package.json').version + // eslint-disable-next-line global-require + static VERSION = require('../package.json').version; constructor (uppy, opts) { super(uppy, opts) @@ -72,74 +73,18 @@ module.exports = class StatusBar extends UIPlugin { this.install = this.install.bind(this) } - getTotalSpeed (files) { - let totalSpeed = 0 - files.forEach((file) => { - totalSpeed += getSpeed(file.progress) - }) - return totalSpeed - } - - getTotalETA (files) { - const totalSpeed = this.getTotalSpeed(files) - if (totalSpeed === 0) { - return 0 - } - - const totalBytesRemaining = files.reduce((total, file) => { - return total + getBytesRemaining(file.progress) - }, 0) - - return Math.round(totalBytesRemaining / totalSpeed * 10) / 10 - } - startUpload = () => { const { recoveredState } = this.uppy.getState() + if (recoveredState) { this.uppy.emit('restore-confirmed') - return + return undefined } + return this.uppy.upload().catch(() => { // Error logged in Core }) - } - - getUploadingState (isAllErrored, isAllComplete, recoveredState, files) { - if (isAllErrored) { - return statusBarStates.STATE_ERROR - } - - if (isAllComplete) { - return statusBarStates.STATE_COMPLETE - } - - if (recoveredState) { - return statusBarStates.STATE_WAITING - } - - let state = statusBarStates.STATE_WAITING - const fileIDs = Object.keys(files) - for (let i = 0; i < fileIDs.length; i++) { - const { progress } = files[fileIDs[i]] - // If ANY files are being uploaded right now, show the uploading state. - if (progress.uploadStarted && !progress.uploadComplete) { - return statusBarStates.STATE_UPLOADING - } - // If files are being preprocessed AND postprocessed at this time, we show the - // preprocess state. If any files are being uploaded we show uploading. - if (progress.preprocess && state !== statusBarStates.STATE_UPLOADING) { - state = statusBarStates.STATE_PREPROCESSING - } - // If NO files are being preprocessed or uploaded right now, but some files are - // being postprocessed, show the postprocess state. - if (progress.postprocess - && state !== statusBarStates.STATE_UPLOADING - && state !== statusBarStates.STATE_PREPROCESSING) { - state = statusBarStates.STATE_POSTPROCESSING - } - } - return state - } + }; render (state) { const { @@ -168,8 +113,10 @@ module.exports = class StatusBar extends UIPlugin { // If some state was recovered, we want to show Upload button/counter // for all the files, because in this case it’s not an Upload button, // but “Confirm Restore Button” - const newFilesOrRecovered = recoveredState ? Object.values(files) : newFiles - const totalETA = this.getTotalETA(inProgressNotPausedFiles) + const newFilesOrRecovered = recoveredState + ? Object.values(files) + : newFiles + const totalETA = getTotalETA(inProgressNotPausedFiles) const resumableUploads = !!capabilities.resumableUploads const supportsUploadProgress = capabilities.uploadProgress !== false @@ -177,18 +124,23 @@ module.exports = class StatusBar extends UIPlugin { let totalUploadedSize = 0 startedFiles.forEach((file) => { - totalSize += (file.progress.bytesTotal || 0) - totalUploadedSize += (file.progress.bytesUploaded || 0) + totalSize += file.progress.bytesTotal || 0 + totalUploadedSize += file.progress.bytesUploaded || 0 }) return StatusBarUI({ error, - uploadState: this.getUploadingState(isAllErrored, isAllComplete, recoveredState, state.files || {}), + uploadState: getUploadingState( + isAllErrored, + isAllComplete, + recoveredState, + state.files || {} + ), allowNewUpload, totalProgress, totalSize, totalUploadedSize, - isAllComplete, + isAllComplete: false, isAllPaused, isAllErrored, isUploadStarted, @@ -236,3 +188,63 @@ module.exports = class StatusBar extends UIPlugin { this.unmount() } } + +function getTotalSpeed (files) { + let totalSpeed = 0 + files.forEach((file) => { + totalSpeed += getSpeed(file.progress) + }) + return totalSpeed +} + +function getTotalETA (files) { + const totalSpeed = getTotalSpeed(files) + if (totalSpeed === 0) { + return 0 + } + + const totalBytesRemaining = files.reduce((total, file) => { + return total + getBytesRemaining(file.progress) + }, 0) + + return Math.round((totalBytesRemaining / totalSpeed) * 10) / 10 +} + +function getUploadingState (isAllErrored, isAllComplete, recoveredState, files) { + if (isAllErrored) { + return statusBarStates.STATE_ERROR + } + + if (isAllComplete) { + return statusBarStates.STATE_COMPLETE + } + + if (recoveredState) { + return statusBarStates.STATE_WAITING + } + + let state = statusBarStates.STATE_WAITING + const fileIDs = Object.keys(files) + for (let i = 0; i < fileIDs.length; i++) { + const { progress } = files[fileIDs[i]] + // If ANY files are being uploaded right now, show the uploading state. + if (progress.uploadStarted && !progress.uploadComplete) { + return statusBarStates.STATE_UPLOADING + } + // If files are being preprocessed AND postprocessed at this time, we show the + // preprocess state. If any files are being uploaded we show uploading. + if (progress.preprocess && state !== statusBarStates.STATE_UPLOADING) { + state = statusBarStates.STATE_PREPROCESSING + } + // If NO files are being preprocessed or uploaded right now, but some files are + // being postprocessed, show the postprocess state. + if ( + progress.postprocess + && state !== statusBarStates.STATE_UPLOADING + && state !== statusBarStates.STATE_PREPROCESSING + ) { + state = statusBarStates.STATE_POSTPROCESSING + } + } + return state +} diff --git a/packages/@uppy/status-bar/src/style.scss b/packages/@uppy/status-bar/src/style.scss index ece3152fb2..eea2c756e8 100644 --- a/packages/@uppy/status-bar/src/style.scss +++ b/packages/@uppy/status-bar/src/style.scss @@ -6,7 +6,7 @@ position: relative; z-index: $zIndex-2; display: flex; - height: 40px; + height: 46px; color: $white; font-weight: 400; font-size: 12px; @@ -14,10 +14,6 @@ background-color: $white; transition: height 0.2s; - .uppy-size--md & { - height: 46px; - } - [data-uppy-theme="dark"] & { background-color: $gray-900; } diff --git a/packages/@uppy/svelte/package.json b/packages/@uppy/svelte/package.json index 1ada63c0bf..b336ae9b71 100644 --- a/packages/@uppy/svelte/package.json +++ b/packages/@uppy/svelte/package.json @@ -3,7 +3,7 @@ "svelte": "src/index.js", "module": "dist/index.mjs", "main": "dist/index.js", - "version": "1.0.2", + "version": "1.0.3", "scripts": { "build": "rollup -c", "prepublishOnly": "npm run build", diff --git a/packages/@uppy/thumbnail-generator/package.json b/packages/@uppy/thumbnail-generator/package.json index 18f6d9f5ad..481b066c0d 100644 --- a/packages/@uppy/thumbnail-generator/package.json +++ b/packages/@uppy/thumbnail-generator/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/thumbnail-generator", "description": "Uppy plugin that generates small previews of images to show on your upload UI.", - "version": "2.0.2", + "version": "2.0.3", "license": "MIT", "main": "lib/index.js", "types": "types/index.d.ts", diff --git a/packages/@uppy/transloadit/package.json b/packages/@uppy/transloadit/package.json index 23958af27e..a82f26e805 100644 --- a/packages/@uppy/transloadit/package.json +++ b/packages/@uppy/transloadit/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/transloadit", "description": "The Transloadit plugin can be used to upload files to Transloadit for all kinds of processing, such as transcoding video, resizing images, zipping/unzipping, and more", - "version": "2.0.1", + "version": "2.0.2", "license": "MIT", "main": "lib/index.js", "types": "types/index.d.ts", diff --git a/packages/@uppy/transloadit/src/index.js b/packages/@uppy/transloadit/src/index.js index 54b3acbf8f..7507c584b1 100644 --- a/packages/@uppy/transloadit/src/index.js +++ b/packages/@uppy/transloadit/src/index.js @@ -14,6 +14,12 @@ function defaultGetAssemblyOptions (file, options) { } } +const sendErrorToConsole = originalErr => err => { + const error = new Error('Failed to send error to the client') + error.cause = err + console.error(error, originalErr) +} + const COMPANION = 'https://api2.transloadit.com/companion' // Regex matching acceptable postMessage() origins for authentication feedback from companion. const ALLOWED_COMPANION_PATTERN = /\.transloadit\.com$/ @@ -387,7 +393,7 @@ module.exports = class Transloadit extends BasePlugin { #onCancelAll =() => { const { uploadsAssemblies } = this.getPluginState() - const assemblyIDs = Object.values(uploadsAssemblies) + const assemblyIDs = Object.values(uploadsAssemblies).flat(1) const cancelPromises = assemblyIDs.map((assemblyID) => { const assembly = this.getAssembly(assemblyID) @@ -405,10 +411,8 @@ module.exports = class Transloadit extends BasePlugin { * * @param {Function} setData */ - #getPersistentData =(setData) => { - const state = this.getPluginState() - const { assemblies } = state - const { uploadsAssemblies } = state + #getPersistentData = (setData) => { + const { assemblies, uploadsAssemblies } = this.getPluginState() setData({ [this.id]: { @@ -473,11 +477,9 @@ module.exports = class Transloadit extends BasePlugin { // Set up the assembly watchers again for all the ongoing uploads. Object.keys(uploadsAssemblies).forEach((uploadID) => { const assemblyIDs = uploadsAssemblies[uploadID] - const fileIDsInUpload = assemblyIDs.reduce((acc, assemblyID) => { - const fileIDsInAssembly = this.getAssemblyFiles(assemblyID).map((file) => file.id) - acc.push(...fileIDsInAssembly) - return acc - }, []) + const fileIDsInUpload = assemblyIDs.flatMap((assemblyID) => { + return this.getAssemblyFiles(assemblyID).map((file) => file.id) + }) this.#createAssemblyWatcher(assemblyIDs, fileIDsInUpload, uploadID) }) @@ -704,15 +706,17 @@ module.exports = class Transloadit extends BasePlugin { } }) this.client.submitError(err) + // if we can't report the error that sucks + .catch(sendErrorToConsole(err)) } #onTusError =(err) => { if (err && /^tus: /.test(err.message)) { const xhr = err.originalRequest ? err.originalRequest.getUnderlyingObject() : null const url = xhr && xhr.responseURL ? xhr.responseURL : null - this.client.submitError(err, { url, type: 'TUS_ERROR' }).then(() => { + this.client.submitError(err, { url, type: 'TUS_ERROR' }) // if we can't report the error that sucks - }) + .catch(sendErrorToConsole(err)) } } diff --git a/packages/@uppy/transloadit/src/index.test.js b/packages/@uppy/transloadit/src/index.test.js index 4b818c6e62..02790f5dac 100644 --- a/packages/@uppy/transloadit/src/index.test.js +++ b/packages/@uppy/transloadit/src/index.test.js @@ -33,10 +33,11 @@ describe('Transloadit', () => { }) it('Does not leave lingering progress if getAssemblyOptions fails', () => { + const error = new Error('expected failure') const uppy = new Core() uppy.use(Transloadit, { getAssemblyOptions () { - return Promise.reject(new Error('Failure!')) + return Promise.reject(error) }, }) @@ -51,7 +52,7 @@ describe('Transloadit', () => { }).catch((err) => { const fileID = Object.keys(uppy.getState().files)[0] - expect(err.message).toBe('Failure!') + expect(err).toBe(error) expect(uppy.getFile(fileID).progress.uploadStarted).toBe(null) }) }) diff --git a/packages/@uppy/tus/package.json b/packages/@uppy/tus/package.json index 931cb27d7f..9a93ffd5a8 100644 --- a/packages/@uppy/tus/package.json +++ b/packages/@uppy/tus/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/tus", "description": "Resumable uploads for Uppy using Tus.io", - "version": "2.0.1", + "version": "2.0.2", "license": "MIT", "main": "lib/index.js", "types": "types/index.d.ts", diff --git a/packages/@uppy/unsplash/package.json b/packages/@uppy/unsplash/package.json index 3daf08657f..83788724cc 100644 --- a/packages/@uppy/unsplash/package.json +++ b/packages/@uppy/unsplash/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/unsplash", "description": "Import files from Unsplash, the free stock photography resource, into Uppy", - "version": "1.0.1", + "version": "1.0.2", "license": "MIT", "main": "lib/index.js", "types": "types/index.d.ts", diff --git a/packages/@uppy/url/package.json b/packages/@uppy/url/package.json index 20cd7beb33..915c44c93e 100644 --- a/packages/@uppy/url/package.json +++ b/packages/@uppy/url/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/url", "description": "The Url plugin lets users import files from the Internet. Paste any URL and it’ll be added!", - "version": "2.0.1", + "version": "2.0.2", "license": "MIT", "main": "lib/index.js", "style": "dist/style.min.css", diff --git a/packages/@uppy/utils/package.json b/packages/@uppy/utils/package.json index 7f75792ba3..5bb1ce54ab 100644 --- a/packages/@uppy/utils/package.json +++ b/packages/@uppy/utils/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/utils", "description": "Shared utility functions for Uppy Core and plugins maintained by the Uppy team.", - "version": "4.0.0", + "version": "4.0.1", "license": "MIT", "main": "lib/index.js", "types": "types/index.d.ts", diff --git a/packages/@uppy/utils/src/AbortController.js b/packages/@uppy/utils/src/AbortController.js index 5d228469a2..9aaf0423ff 100644 --- a/packages/@uppy/utils/src/AbortController.js +++ b/packages/@uppy/utils/src/AbortController.js @@ -1,6 +1,6 @@ /** * Little AbortController proxy module so we can swap out the implementation easily later. */ -exports.AbortController = AbortController -exports.AbortSignal = AbortSignal +exports.AbortController = globalThis.AbortController +exports.AbortSignal = globalThis.AbortSignal exports.createAbortError = (message = 'Aborted') => new DOMException(message, 'AbortError') diff --git a/packages/@uppy/vue/package.json b/packages/@uppy/vue/package.json index 547256b0e7..0877b06c1f 100644 --- a/packages/@uppy/vue/package.json +++ b/packages/@uppy/vue/package.json @@ -1,6 +1,6 @@ { "name": "@uppy/vue", - "version": "0.4.0", + "version": "0.4.1", "private": false, "main": "lib/index.js", "types": "types/index.d.ts", diff --git a/packages/@uppy/webcam/package.json b/packages/@uppy/webcam/package.json index 1820214ca5..143b9c8a93 100644 --- a/packages/@uppy/webcam/package.json +++ b/packages/@uppy/webcam/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/webcam", "description": "Uppy plugin that takes photos or records videos using the device's camera.", - "version": "2.0.1", + "version": "2.0.2", "license": "MIT", "main": "lib/index.js", "style": "dist/style.min.css", diff --git a/packages/@uppy/xhr-upload/package.json b/packages/@uppy/xhr-upload/package.json index 8259cf18a3..b68ea535f7 100644 --- a/packages/@uppy/xhr-upload/package.json +++ b/packages/@uppy/xhr-upload/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/xhr-upload", "description": "Plain and simple classic HTML multipart form uploads with Uppy, as well as uploads using the HTTP PUT method.", - "version": "2.0.2", + "version": "2.0.3", "license": "MIT", "main": "lib/index.js", "types": "types/index.d.ts", diff --git a/packages/@uppy/xhr-upload/src/index.js b/packages/@uppy/xhr-upload/src/index.js index 02a5877fc7..307e9346a2 100644 --- a/packages/@uppy/xhr-upload/src/index.js +++ b/packages/@uppy/xhr-upload/src/index.js @@ -87,7 +87,7 @@ module.exports = class XHRUpload extends BasePlugin { try { parsedResponse = JSON.parse(responseText) } catch (err) { - this.uppy.log(err) + uppy.log(err) } return parsedResponse diff --git a/packages/@uppy/zoom/package.json b/packages/@uppy/zoom/package.json index 037fc2ed1e..e99dea51bb 100644 --- a/packages/@uppy/zoom/package.json +++ b/packages/@uppy/zoom/package.json @@ -1,7 +1,7 @@ { "name": "@uppy/zoom", "description": "Import files from zoom, into Uppy.", - "version": "1.0.1", + "version": "1.0.2", "license": "MIT", "main": "lib/index.js", "types": "types/index.d.ts", diff --git a/packages/uppy/package.json b/packages/uppy/package.json index 17a95f0b75..950ba9dbdb 100644 --- a/packages/uppy/package.json +++ b/packages/uppy/package.json @@ -1,7 +1,7 @@ { "name": "uppy", "description": "Extensible JavaScript file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Instagram, Dropbox, Google Drive, S3 and more :dog:", - "version": "2.1.0", + "version": "2.1.1", "license": "MIT", "main": "index.js", "module": "index.mjs", diff --git a/test/endtoend/transloadit2/index.html b/test/endtoend/transloadit2/index.html new file mode 100644 index 0000000000..4a38ad102e --- /dev/null +++ b/test/endtoend/transloadit2/index.html @@ -0,0 +1,23 @@ + + + + + + Uppy test page + + + +
+

Uppy Transloadit

+
+
+ + + + + diff --git a/test/endtoend/transloadit2/main.js b/test/endtoend/transloadit2/main.js new file mode 100644 index 0000000000..48986ad68a --- /dev/null +++ b/test/endtoend/transloadit2/main.js @@ -0,0 +1,57 @@ +const Uppy = require('@uppy/core') +const Dashboard = require('@uppy/dashboard') +const Transloadit = require('@uppy/transloadit') + +function initUppyTransloadit (transloaditKey) { + const uppyTransloadit = new Uppy({ + id: 'uppyTransloadit', + debug: true, + autoProceed: true, + }) + + uppyTransloadit + .use(Dashboard, { + target: '#uppy-transloadit', + inline: true, + }) + .use(Transloadit, { + service: 'https://api2-ap-southeast-1.transloadit.com', + params: { + steps: { + crop_thumbed: { + use: [':original'], + robot: '/image/resize', + height: 100, + resize_strategy: 'crop', + width: 100, + }, + }, + }, + getAssemblyOptions () { + return { + params: { + auth: { key: transloaditKey }, + template_id: 'uppyTransloadit', + }, + } + }, + waitForEncoding: true, + }) + + uppyTransloadit.on('transloadit:result', (stepName, result) => { + // use transloadit encoding result here. + console.log('Result here ====>', stepName, result) + console.log('Cropped image url is here ====>', result.url) + + const img = new Image() + img.onload = function onload () { + const result = document.createElement('div') + result.setAttribute('id', 'uppy-result') + result.textContent = 'ok' + document.body.appendChild(result) + } + img.src = result.url + }) +} + +window.initUppyTransloadit = initUppyTransloadit diff --git a/test/endtoend/transloadit2/test.js b/test/endtoend/transloadit2/test.js new file mode 100644 index 0000000000..7623c0d7b5 --- /dev/null +++ b/test/endtoend/transloadit2/test.js @@ -0,0 +1,52 @@ +/* global browser, expect, capabilities, $ */ +const path = require('path') +const fs = require('fs') +const { selectFakeFile, supportsChooseFile, ensureInputVisible } = require('../utils') + +const testURL = 'http://localhost:4567/transloadit' + +function setTransloaditKeyAndInit (transloaditKey) { + window.initUppyTransloadit(transloaditKey) +} + +describe('Transloadit file processing', () => { + beforeEach(async () => { + await browser.url(testURL) + }) + + it('should upload a file to Transloadit and crop it', async function test () { + const transloaditKey = process.env.TRANSLOADIT_KEY + if (transloaditKey === undefined) { + console.log('skipping Transloadit integration test') + return this.skip() + } + + const wrapper = await $('#uppy-transloadit') + await wrapper.waitForExist() + + await browser.execute(setTransloaditKeyAndInit, transloaditKey) + + const input = await $('#uppy-transloadit .uppy-Dashboard-input') + const result = await $('#uppy-result') + + await input.waitForExist() + await browser.execute(ensureInputVisible, '#uppy-transloadit .uppy-Dashboard-input') + + if (supportsChooseFile(capabilities)) { + await input.setValue(path.join(__dirname, '../../resources/image.jpg')) + } else { + const img = path.join(__dirname, '../../resources/image.jpg') + await browser.execute( + selectFakeFile, + 'uppyTransloadit', + path.basename(img), // name + 'image/jpeg', // type + fs.readFileSync(img, 'base64') // b64 + ) + // browser.execute(selectFakeFile, 'uppyTransloadit') + } + await result.waitForExist(25000) + const text = await result.getText() + expect(text).to.be.equal('ok') + }) +}) diff --git a/test/endtoend/wdio.base.conf.js b/test/endtoend/wdio.base.conf.js index 24eee4db28..ac1c0c1d65 100644 --- a/test/endtoend/wdio.base.conf.js +++ b/test/endtoend/wdio.base.conf.js @@ -95,6 +95,7 @@ exports.config = { { mount: '/providers', path: './providers/dist' }, { mount: '/thumbnails', path: './thumbnails/dist' }, { mount: '/transloadit', path: './transloadit/dist' }, + { mount: '/transloadit2', path: './transloadit2/dist' }, { mount: '/tus-drag-drop', path: './tus-drag-drop/dist' }, { mount: '/typescript', path: './typescript/dist' }, { mount: '/url-plugin', path: './url-plugin/dist' }, diff --git a/website/src/docs/index.md b/website/src/docs/index.md index b7a8c99280..a8989ffe00 100644 --- a/website/src/docs/index.md +++ b/website/src/docs/index.md @@ -19,12 +19,12 @@ Here’s the simplest example html page with Uppy (it uses a CDN bundle, while w Uppy - +
- + + ``` 2\. Add CSS to ``: ``` html - + ``` 3\. Initialize at the bottom of the closing `` tag: @@ -184,5 +184,5 @@ export * from '@uppy/core' If you're using Uppy from CDN, those polyfills are already included in the bundle, no need to include anything additionally: ```html - + ``` diff --git a/website/src/docs/locales.md b/website/src/docs/locales.md index ead2159952..e12c8a1ece 100644 --- a/website/src/docs/locales.md +++ b/website/src/docs/locales.md @@ -34,8 +34,8 @@ const uppy = new Uppy({ Add a ` - + + + - - + + ``` Please note that while you may be able to get 2.0 to work in IE11 this way, we do not officially support it anymore. diff --git a/website/src/examples/dashboard/app.es6 b/website/src/examples/dashboard/app.es6 index abbd0c5956..c75abec877 100644 --- a/website/src/examples/dashboard/app.es6 +++ b/website/src/examples/dashboard/app.es6 @@ -213,7 +213,7 @@ function loadLocaleFromCDN (localeName) { const head = document.getElementsByTagName('head')[0] const js = document.createElement('script') js.type = 'text/javascript' - js.src = `https://releases.transloadit.com/uppy/locales/v2.0.0/${localeName}.min.js` + js.src = `https://releases.transloadit.com/uppy/locales/v2.0.1/${localeName}.min.js` head.appendChild(js) } diff --git a/website/src/examples/i18n/app.html b/website/src/examples/i18n/app.html index 63153eed12..6dfb2644dd 100644 --- a/website/src/examples/i18n/app.html +++ b/website/src/examples/i18n/app.html @@ -1,7 +1,7 @@ - +
@@ -12,8 +12,8 @@
Uploaded files:
- - + + + +