Skip to content

Commit

Permalink
Merge branch 'main' into new-react-hook
Browse files Browse the repository at this point in the history
* main:
  @uppy/vue: export FileInput (#4736)
  examples: update `server.py` (#4732)
  @uppy/aws-s3-multipart: fix `uploadURL` when using `PUT` (#4701)
  @uppy/dashboard: auto discover and install plugins without target (#4343)
  e2e: upgrade Cypress (#4731)
  @uppy/core: mark the package as side-effect free (#4730)
  Bump postcss from 8.4.16 to 8.4.31 (#4723)
  meta: test with the latest versions of Node.js (#4729)
  • Loading branch information
Murderlon committed Oct 16, 2023
2 parents 9ec06ea + 8e8f178 commit 395795f
Show file tree
Hide file tree
Showing 19 changed files with 211 additions and 104 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
# todo put back?
node-version: [18.16.0, 20.x]
node-version: [18.x, 20.x]
steps:
- name: Checkout sources
uses: actions/checkout@v3
Expand Down
6 changes: 5 additions & 1 deletion e2e/clients/react/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ import Uppy from '@uppy/core'
import React, { useState } from 'react'
import { Dashboard, DashboardModal, DragDrop, useUppyState } from '@uppy/react'
import ThumbnailGenerator from '@uppy/thumbnail-generator'
import RemoteSources from '@uppy/remote-sources'

import '@uppy/core/dist/style.css'
import '@uppy/dashboard/dist/style.css'
import '@uppy/drag-drop/dist/style.css'

const uppyDashboard = new Uppy({ id: 'dashboard' })
const uppyDashboard = new Uppy({ id: 'dashboard' }).use(RemoteSources, {
companionUrl: 'http://companion.uppy.io',
sources: ['GoogleDrive', 'OneDrive', 'Unsplash', 'Zoom', 'Url'],
})
const uppyModal = new Uppy({ id: 'modal' })
const uppyDragDrop = new Uppy({ id: 'drag-drop' }).use(ThumbnailGenerator)

Expand Down
16 changes: 16 additions & 0 deletions e2e/cypress/integration/react.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ describe('@uppy/react', () => {
.each((element) => expect(element).attr('src').to.include('blob:'))
})

it('should render Dashboard with Remote Sources plugin pack', () => {
const sources = [
'My Device',
'Google Drive',
'OneDrive',
'Unsplash',
'Zoom',
'Link',
]
cy.get('#dashboard .uppy-DashboardTab-name').each((item, index, list) => {
expect(list).to.have.length(6)
// Returns the current element from the loop
expect(Cypress.$(item).text()).to.eq(sources[index])
})
})

it('should render Modal in React and show thumbnails', () => {
cy.get('#open').click()
cy.get('@modal-input').selectFile(
Expand Down
4 changes: 2 additions & 2 deletions e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
"devDependencies": {
"@parcel/transformer-vue": "^2.9.3",
"@types/react": "^18.2.23",
"cypress": "^12.9.0",
"cypress-terminal-report": "^4.1.2",
"cypress": "^13.0.0",
"cypress-terminal-report": "^5.0.0",
"deep-freeze": "^0.0.1",
"execa": "^6.1.0",
"parcel": "^2.9.3",
Expand Down
37 changes: 19 additions & 18 deletions examples/python-xhr/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,33 @@
from flask_cors import CORS

UPLOAD_FOLDER = 'uploads'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = os.path.join(os.path.dirname(__file__), UPLOAD_FOLDER)
CORS(app)

def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/upload', methods=['POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
print (request.files)
if len(request.files) == 0:
return jsonify(
error="No file n request"
), 400
for fi in request.files:
file = request.files[fi]
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return jsonify(
message="ok"
), 201
uploaded_files = request.files.getlist('file')
if not uploaded_files:
return jsonify(error="No files in the request"), 400

uploaded_filenames = []
for file in uploaded_files:
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
uploaded_filenames.append(filename)

if uploaded_filenames:
return jsonify(message="Files uploaded successfully", uploaded_files=uploaded_filenames), 201
else:
return jsonify(error="No valid files uploaded"), 400

if __name__ == '__main__':
app.run(port=3020)
app.run(port=3020)
8 changes: 6 additions & 2 deletions examples/react-example/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
import React from'react'
import Uppy from'@uppy/core'
import Tus from'@uppy/tus'
import GoogleDrive from'@uppy/google-drive'
import GoogleDrive from '@uppy/google-drive'
import Webcam from '@uppy/webcam'
import RemoteSources from '@uppy/remote-sources'
import { Dashboard, DashboardModal, DragDrop, ProgressBar, FileInput } from'@uppy/react'

import '@uppy/core/dist/style.css'
Expand All @@ -22,7 +24,9 @@ export default class App extends React.Component {

this.uppy = new Uppy({ id: 'uppy1', autoProceed: true, debug: true })
.use(Tus, { endpoint: 'https://tusd.tusdemo.net/files/' })
.use(GoogleDrive, { companionUrl: 'https://companion.uppy.io' })
.use(Webcam)
.use(RemoteSources, { companionUrl: 'https://companion.uppy.io', sources: ['GoogleDrive', 'Box', 'Dropbox', 'Facebook', 'Instagram', 'OneDrive', 'Unsplash', 'Zoom', 'Url'],
})

this.uppy2 = new Uppy({ id: 'uppy2', autoProceed: false, debug: true })
.use(Tus, { endpoint: 'https://tusd.tusdemo.net/files/' })
Expand Down
2 changes: 1 addition & 1 deletion examples/svelte-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"@rollup/plugin-typescript": "^8.0.0",
"@tsconfig/svelte": "^1.0.0",
"npm-run-all": "^4.1.5",
"postcss": "^8.2.1",
"postcss": "^8.4.31",
"postcss-import": "^13.0.0",
"postcss-load-config": "^3.0.0",
"rollup": "^2.60.2",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
"npm-run-all": "^4.1.5",
"onchange": "^7.1.0",
"pacote": "^13.0.0",
"postcss": "^8.2.10",
"postcss": "^8.4.31",
"postcss-dir-pseudo-class": "^6.0.0",
"postcss-logical": "^5.0.0",
"pre-commit": "^1.2.2",
Expand Down
14 changes: 13 additions & 1 deletion packages/@uppy/aws-s3-multipart/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ function assertServerError (res) {
return res
}

function removeMetadataFromURL (urlString) {
const urlObject = new URL(urlString)
urlObject.search = ''
urlObject.hash = ''
return urlObject.href
}

/**
* Computes the expiry time for a request signed with temporary credentials. If
* no expiration was provided, or an invalid value (e.g. in the past) is
Expand Down Expand Up @@ -260,14 +267,19 @@ class HTTPCommunicationQueue {

const { onProgress, onComplete } = chunk

return this.#uploadPartBytes({
const result = await this.#uploadPartBytes({
signature: { url, headers, method },
body,
size: data.size,
onProgress,
onComplete,
signal,
}).abortOn(signal)

return 'location' in result ? result : {
location: removeMetadataFromURL(url),
...result,
}
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/@uppy/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"style": "dist/style.min.css",
"types": "types/index.d.ts",
"type": "module",
"sideEffects": false,
"keywords": [
"file uploader",
"uppy",
Expand Down
2 changes: 2 additions & 0 deletions packages/@uppy/core/src/Uppy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,8 @@ class Uppy {
}
plugin.install()

this.emit('plugin-added', plugin)

return this
}

Expand Down
2 changes: 2 additions & 0 deletions packages/@uppy/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
"devDependencies": {
"@uppy/google-drive": "workspace:^",
"@uppy/status-bar": "workspace:^",
"@uppy/url": "workspace:^",
"@uppy/webcam": "workspace:^",
"resize-observer-polyfill": "^1.5.0",
"vitest": "^0.34.5"
},
Expand Down
47 changes: 32 additions & 15 deletions packages/@uppy/dashboard/src/Dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ export default class Dashboard extends UIPlugin {
this.startListeningToResize()
document.addEventListener('paste', this.handlePasteOnBody)

this.uppy.on('plugin-added', this.#addSupportedPluginIfNoTarget)
this.uppy.on('plugin-remove', this.removeTarget)
this.uppy.on('file-added', this.hideAllPanels)
this.uppy.on('dashboard:modal-closed', this.hideAllPanels)
Expand Down Expand Up @@ -780,8 +781,9 @@ export default class Dashboard extends UIPlugin {

this.stopListeningToResize()
document.removeEventListener('paste', this.handlePasteOnBody)

window.removeEventListener('popstate', this.handlePopState, false)

this.uppy.off('plugin-added', this.#addSupportedPluginIfNoTarget)
this.uppy.off('plugin-remove', this.removeTarget)
this.uppy.off('file-added', this.hideAllPanels)
this.uppy.off('dashboard:modal-closed', this.hideAllPanels)
Expand Down Expand Up @@ -1015,14 +1017,37 @@ export default class Dashboard extends UIPlugin {
})
}

discoverProviderPlugins = () => {
this.uppy.iteratePlugins((plugin) => {
if (plugin && !plugin.target && plugin.opts && plugin.opts.target === this.constructor) {
this.addTarget(plugin)
#addSpecifiedPluginsFromOptions = () => {
const plugins = this.opts.plugins || []

plugins.forEach((pluginID) => {
const plugin = this.uppy.getPlugin(pluginID)
if (plugin) {
plugin.mount(this, plugin)
} else {
this.uppy.log(`[Uppy] Dashboard could not find plugin '${pluginID}', make sure to uppy.use() the plugins you are specifying`, 'warning')
}
})
}

#autoDiscoverPlugins = () => {
this.uppy.iteratePlugins(this.#addSupportedPluginIfNoTarget)
}

#addSupportedPluginIfNoTarget = (plugin) => {
// Only these types belong on the Dashboard,
// we wouldn’t want to try and mount Compressor or Tus, for example.
const typesAllowed = ['acquirer', 'editor']
if (plugin && !plugin.opts?.target && typesAllowed.includes(plugin.type)) {
const pluginAlreadyAdded = this.getPluginState().targets.some(
installedPlugin => plugin.id === installedPlugin.id,
)
if (!pluginAlreadyAdded) {
plugin.mount(this, plugin)
}
}
}

install = () => {
// Set default state for Dashboard
this.setPluginState({
Expand Down Expand Up @@ -1055,15 +1080,6 @@ export default class Dashboard extends UIPlugin {
this.mount(target, this)
}

const plugins = this.opts.plugins || []

plugins.forEach((pluginID) => {
const plugin = this.uppy.getPlugin(pluginID)
if (plugin) {
plugin.mount(this, plugin)
}
})

if (!this.opts.disableStatusBar) {
this.uppy.use(StatusBar, {
id: `${this.id}:StatusBar`,
Expand Down Expand Up @@ -1111,7 +1127,8 @@ export default class Dashboard extends UIPlugin {
this.darkModeMediaQuery.addListener(this.handleSystemDarkModeChange)
}

this.discoverProviderPlugins()
this.#addSpecifiedPluginsFromOptions()
this.#autoDiscoverPlugins()
this.initEvents()
}

Expand Down
36 changes: 36 additions & 0 deletions packages/@uppy/dashboard/src/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { afterAll, beforeAll, describe, it, expect } from 'vitest'
import Core from '@uppy/core'
import StatusBarPlugin from '@uppy/status-bar'
import GoogleDrivePlugin from '@uppy/google-drive'
import WebcamPlugin from '@uppy/webcam'
import Url from '@uppy/url'

import resizeObserverPolyfill from 'resize-observer-polyfill'
import DashboardPlugin from '../lib/index.js'

Expand Down Expand Up @@ -66,6 +69,39 @@ describe('Dashboard', () => {
core.close()
})

it('should automatically add plugins which have no target', () => {
const core = new Core()
core.use(Url, { companionUrl: 'https://companion.uppy.io' })
core.use(DashboardPlugin, { inline: false })
core.use(WebcamPlugin)

const dashboardPlugins = core.getState().plugins['Dashboard'].targets

// two built-in plugins + these ones below
expect(dashboardPlugins.length).toEqual(4)
expect(dashboardPlugins.some((plugin) => plugin.id === 'Url')).toEqual(true)
expect(dashboardPlugins.some((plugin) => plugin.id === 'Webcam')).toEqual(true)

core.close()
})

it('should not automatically add plugins which have a non-Dashboard target', () => {
const core = new Core()
WebcamPlugin.prototype.start = () => {}
core.use(Url, { companionUrl: 'https://companion.uppy.io' })
core.use(DashboardPlugin, { inline: false })
core.use(WebcamPlugin, { target: 'body' })

const dashboardPlugins = core.getState().plugins['Dashboard'].targets

// two built-in plugins + these ones below
expect(dashboardPlugins.length).toEqual(3)
expect(dashboardPlugins.some((plugin) => plugin.id === 'Url')).toEqual(true)
expect(dashboardPlugins.some((plugin) => plugin.id === 'Webcam')).toEqual(false)

core.close()
})

it('should change options on the fly', () => {
const core = new Core()
core.use(DashboardPlugin, {
Expand Down
4 changes: 2 additions & 2 deletions packages/@uppy/image-editor/src/ImageEditor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ export default class ImageEditor extends UIPlugin {
...opts,
actions: {
...defaultActions,
...opts.actions,
...opts?.actions,
},
cropperOptions: {
...defaultCropperOptions,
...opts.cropperOptions,
...opts?.cropperOptions,
},
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ export default class ProviderView extends View {
// and that will allow the user to start the upload, so we need to make sure we have
// finished all async operations before we add any file
// see https://github.com/transloadit/uppy/pull/4384
this.plugin.uppy.log('Adding remote provider files')
this.plugin.uppy.log('Adding files from a remote provider')
this.plugin.uppy.addFiles(newFiles.map((file) => this.getTagFile(file)))

this.plugin.setPluginState({ filterInput: '' })
Expand Down
4 changes: 1 addition & 3 deletions packages/@uppy/remote-sources/src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { BasePlugin } from '@uppy/core'
import Dashboard from '@uppy/dashboard'
import Dropbox from '@uppy/dropbox'
import GoogleDrive from '@uppy/google-drive'
import Instagram from '@uppy/instagram'
Expand Down Expand Up @@ -34,11 +33,10 @@ export default class RemoteSources extends BasePlugin {
constructor (uppy, opts) {
super(uppy, opts)
this.id = this.opts.id || 'RemoteSources'
this.type = 'acquirer'
this.type = 'preset'

const defaultOptions = {
sources: Object.keys(availablePlugins),
target: Dashboard,
}
this.opts = { ...defaultOptions, ...opts }

Expand Down
1 change: 1 addition & 0 deletions packages/@uppy/vue/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export { default as DashboardModal } from './dashboard-modal.js'
export { default as DragDrop } from './drag-drop.js'
export { default as ProgressBar } from './progress-bar.js'
export { default as StatusBar } from './status-bar.js'
export { default as FileInput } from './file-input.js'
Loading

0 comments on commit 395795f

Please sign in to comment.