From 31128e41fb09dbe4556d2e251b08926b5c1ad0d0 Mon Sep 17 00:00:00 2001 From: Azhar Rizqullah <98894677+kaiserinn@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:40:46 +0800 Subject: [PATCH 1/3] docs: typo (#5523) --- docs/sources/file-input.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/file-input.mdx b/docs/sources/file-input.mdx index c764b23b98..cfab8b9154 100644 --- a/docs/sources/file-input.mdx +++ b/docs/sources/file-input.mdx @@ -115,7 +115,7 @@ export default { }; ``` -## Custom file inpt +## Custom file input If you don’t like the look/feel of the button rendered by `@uppy/file-input`, feel free to forgo the plugin and use your own custom button on a page, like so: From fb8e446067818d98ff838aca242881d011c9d47e Mon Sep 17 00:00:00 2001 From: Merlijn Vos Date: Tue, 26 Nov 2024 10:41:47 +0100 Subject: [PATCH 2/3] Put docs back in uppy.io repository where they belong (#5527) * Move docs back into uppy.io repo * Undo tooling * Remove last file --- .eslintrc.js | 7 - .github/workflows/linters.yml | 21 - .prettierrc.js | 7 - docs/README.md | 4 - docs/companion.md | 991 ---------- docs/compressor.mdx | 125 -- docs/form.mdx | 181 -- docs/framework-integrations/_category_.json | 4 - docs/framework-integrations/angular.mdx | 117 -- docs/framework-integrations/nextjs.mdx | 434 ----- docs/framework-integrations/react.mdx | 247 --- docs/framework-integrations/svelte.mdx | 71 - docs/framework-integrations/vue.mdx | 73 - docs/golden-retriever.mdx | 150 -- docs/guides/_category_.json | 4 - docs/guides/browser-support.mdx | 51 - docs/guides/building-plugins.md | 382 ---- docs/guides/building-your-own-ui-with-uppy.md | 11 - docs/guides/choosing-uploader.md | 84 - docs/guides/custom-stores.md | 136 -- docs/guides/migration-guides.md | 868 --------- docs/locales.mdx | 1562 ---------------- docs/presets/_category_.json | 4 - docs/presets/remote-sources.mdx | 179 -- docs/quick-start.mdx | 58 - docs/sources/_category_.json | 4 - docs/sources/audio.mdx | 133 -- .../sources/companion-plugins/_category_.json | 5 - docs/sources/companion-plugins/box.mdx | 226 --- docs/sources/companion-plugins/dropbox.mdx | 226 --- docs/sources/companion-plugins/facebook.mdx | 223 --- .../companion-plugins/google-drive.mdx | 227 --- .../companion-plugins/google-photos.mdx | 223 --- docs/sources/companion-plugins/instagram.mdx | 236 --- docs/sources/companion-plugins/onedrive.mdx | 224 --- docs/sources/companion-plugins/unsplash.mdx | 202 -- docs/sources/companion-plugins/url.mdx | 188 -- docs/sources/companion-plugins/zoom.mdx | 227 --- docs/sources/file-input.mdx | 166 -- docs/sources/screen-capture.mdx | 150 -- docs/sources/webcam.mdx | 252 --- docs/uploader/_category_.json | 4 - docs/uploader/aws-s3-multipart.mdx | 487 ----- docs/uploader/transloadit.mdx | 662 ------- docs/uploader/tus.mdx | 332 ---- docs/uploader/xhr.mdx | 383 ---- docs/uppy-core.mdx | 1617 ----------------- docs/user-interfaces/_category_.json | 4 - docs/user-interfaces/dashboard.mdx | 755 -------- docs/user-interfaces/drag-drop.mdx | 149 -- docs/user-interfaces/elements/_category_.json | 5 - docs/user-interfaces/elements/drop-target.mdx | 113 -- .../user-interfaces/elements/image-editor.mdx | 179 -- docs/user-interfaces/elements/informer.mdx | 94 - .../user-interfaces/elements/progress-bar.mdx | 91 - docs/user-interfaces/elements/status-bar.mdx | 202 -- .../elements/thumbnail-generator.mdx | 168 -- 57 files changed, 13928 deletions(-) delete mode 100644 docs/README.md delete mode 100644 docs/companion.md delete mode 100644 docs/compressor.mdx delete mode 100644 docs/form.mdx delete mode 100644 docs/framework-integrations/_category_.json delete mode 100644 docs/framework-integrations/angular.mdx delete mode 100644 docs/framework-integrations/nextjs.mdx delete mode 100644 docs/framework-integrations/react.mdx delete mode 100644 docs/framework-integrations/svelte.mdx delete mode 100644 docs/framework-integrations/vue.mdx delete mode 100644 docs/golden-retriever.mdx delete mode 100644 docs/guides/_category_.json delete mode 100644 docs/guides/browser-support.mdx delete mode 100644 docs/guides/building-plugins.md delete mode 100644 docs/guides/building-your-own-ui-with-uppy.md delete mode 100644 docs/guides/choosing-uploader.md delete mode 100644 docs/guides/custom-stores.md delete mode 100644 docs/guides/migration-guides.md delete mode 100644 docs/locales.mdx delete mode 100644 docs/presets/_category_.json delete mode 100644 docs/presets/remote-sources.mdx delete mode 100644 docs/quick-start.mdx delete mode 100644 docs/sources/_category_.json delete mode 100644 docs/sources/audio.mdx delete mode 100644 docs/sources/companion-plugins/_category_.json delete mode 100644 docs/sources/companion-plugins/box.mdx delete mode 100644 docs/sources/companion-plugins/dropbox.mdx delete mode 100644 docs/sources/companion-plugins/facebook.mdx delete mode 100644 docs/sources/companion-plugins/google-drive.mdx delete mode 100644 docs/sources/companion-plugins/google-photos.mdx delete mode 100644 docs/sources/companion-plugins/instagram.mdx delete mode 100644 docs/sources/companion-plugins/onedrive.mdx delete mode 100644 docs/sources/companion-plugins/unsplash.mdx delete mode 100644 docs/sources/companion-plugins/url.mdx delete mode 100644 docs/sources/companion-plugins/zoom.mdx delete mode 100644 docs/sources/file-input.mdx delete mode 100644 docs/sources/screen-capture.mdx delete mode 100644 docs/sources/webcam.mdx delete mode 100644 docs/uploader/_category_.json delete mode 100644 docs/uploader/aws-s3-multipart.mdx delete mode 100644 docs/uploader/transloadit.mdx delete mode 100644 docs/uploader/tus.mdx delete mode 100644 docs/uploader/xhr.mdx delete mode 100644 docs/uppy-core.mdx delete mode 100644 docs/user-interfaces/_category_.json delete mode 100644 docs/user-interfaces/dashboard.mdx delete mode 100644 docs/user-interfaces/drag-drop.mdx delete mode 100644 docs/user-interfaces/elements/_category_.json delete mode 100644 docs/user-interfaces/elements/drop-target.mdx delete mode 100644 docs/user-interfaces/elements/image-editor.mdx delete mode 100644 docs/user-interfaces/elements/informer.mdx delete mode 100644 docs/user-interfaces/elements/progress-bar.mdx delete mode 100644 docs/user-interfaces/elements/status-bar.mdx delete mode 100644 docs/user-interfaces/elements/thumbnail-generator.mdx diff --git a/.eslintrc.js b/.eslintrc.js index 98c06b7d1f..98adc34c4d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -384,15 +384,8 @@ module.exports = { files: ['**/*.md', '*.md'], processor: 'markdown/markdown', }, - { - files: ['docs/**/*.md/*.js'], - parserOptions: { - sourceType: 'module', - }, - }, { files: ['**/*.md/*.js', '**/*.md/*.javascript'], - excludedFiles: ["docs/**/*"], parserOptions: { sourceType: 'module', }, diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 12a96650b7..8aa2843c4a 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -57,24 +57,3 @@ jobs: run: corepack yarn workspaces focus @uppy-dev/build - name: Run linter run: corepack yarn run lint:markdown - - lint_docs: - name: Lint Docs - runs-on: ubuntu-latest - steps: - - name: Checkout Uppy.io sources - uses: actions/checkout@v4 - with: - repository: transloadit/uppy.io - - run: rm -rf docs # the other PR has not landed - - name: Checkout docs - uses: actions/checkout@v4 - with: - path: uppy - - run: mv uppy /tmp/uppy && ln -s /tmp/uppy/docs docs - - name: Install dependencies - run: corepack yarn --immutable - - name: Lint files - run: corepack yarn lint - - name: Test build website - run: corepack yarn build diff --git a/.prettierrc.js b/.prettierrc.js index a64dbe40c8..ba4df7a5f3 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -12,13 +12,6 @@ module.exports = { semi: true, }, }, - { - files: 'docs/**', - options: { - semi: true, - useTabs: true, - }, - }, { files: ['tsconfig.json'], options: { diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index ee7415a35a..0000000000 --- a/docs/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Uppy documentation - -See instructions for linting this documentation and seeing this documentation in -the browser in . diff --git a/docs/companion.md b/docs/companion.md deleted file mode 100644 index 83aa31c900..0000000000 --- a/docs/companion.md +++ /dev/null @@ -1,991 +0,0 @@ ---- -sidebar_position: 4 ---- - -# Companion - -Companion is an open source server application which **takes away the complexity -of authentication and the cost of downloading files from remote sources**, such -as Instagram, Google Drive, and others. Companion is a server-to-server -orchestrator that streams files from a source to a destination, and files are -never stored in Companion. Companion can run either as a standalone -(self-hosted) application, [Transloadit-hosted](#hosted), or plugged in as an -Express middleware into an existing application. The Uppy client requests remote -files from Companion, which it will download and simultaneously upload to your -[Tus server](/docs/tus), [AWS bucket](/docs/aws-s3), or any server that supports -[PUT, POST or Multipart uploads](/docs/xhr-upload). - -This means a user uploading a 5GB video from Google Drive from their phone isn’t -eating into their data plans and you don’t have to worry about implementing -OAuth. - -## When should I use it? - -If you want to let users download files from [Box][], [Dropbox][], [Facebook][], -[Google Drive][googledrive], [Google Photos][googlephotos], [Instagram][], -[OneDrive][], [Unsplash][], [Import from URL][url], or [Zoom][] — you need -Companion. - -Companion supports the same [uploaders](/docs/guides/choosing-uploader) as Uppy: -[Tus](/docs/tus), [AWS S3](/docs/aws-s3), and [regular multipart](/docs/tus). -But instead of manually setting a plugin, Uppy sends along a header with the -uploader and Companion will use the same on the server. This means if you are -using [Tus](/docs/tus) for your local uploads, you can send your remote uploads -to the same Tus server (and likewise for your AWS S3 bucket). - -:::note - -Companion only deals with _remote_ files, _local_ files are still uploaded from -the client with your upload plugin. - -::: - -## Hosted - -Using [Transloadit][] services comes with a hosted version of Companion so you -don’t have to worry about hosting your own server. Whether you are on a free or -paid Transloadit [plan](https://transloadit.com/pricing/), you can use -Companion. It’s not possible to rent a Companion server without a Transloadit -plan. - -[**Sign-up for a (free) plan**](https://transloadit.com/pricing/). - -:::tip - -Choosing Transloadit for your file services also comes with credentials for all -remote providers. This means you don’t have to waste time going through the -approval process of every app. You can still add your own credentials in the -Transloadit admin page if you want. - -::: - -:::info - -Downloading and uploading files through Companion doesn’t count towards your -[monthly quota](https://transloadit.com/docs/faq/1gb-worth/), it’s a way for -files to arrive at Transloadit servers, much like Uppy. - -::: - -To do so each provider plugin must be configured with Transloadit’s Companion -URLs: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Dropbox from '@uppy/dropbox'; - -uppy.use(Dropbox, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Dropbox from '@uppy/dropbox'; - -uppy.use(Dropbox, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -## Installation & use - -Companion is installed from npm. Depending on how you want to run Companion, the -install process is slightly different. Companion can be integrated as middleware -into your [Express](https://expressjs.com/) app or as a standalone server. Most -people probably want to run it as a standalone server, while the middleware -could be used to further customise Companion or integrate it into your own HTTP -server code. - -:::note - -Since v2, you need to be running `node.js >= v10.20.1` to use Companion. More -information in the -[migrating to 2.0](/docs/guides/migration-guides/#migrate-from-uppy-1x-to-2x) -guide. - -Windows is not a supported platform right now. It may work, and we’re happy to -accept improvements in this area, but we can’t provide support. - -::: - -### Standalone mode - -You can use the standalone version if you want to run Companion as it’s own -Node.js process. It’s a configured Express server with sessions, logging, and -security best practices. First you’ll typically want to install it globally: - -```bash -npm install -g @uppy/companion -``` - -Standalone Companion will always serve HTTP (not HTTPS) and expects a reverse -proxy with SSL termination in front of it when running in production. See -[`COMPANION_PROTOCOL`](#server) for more information. - -Companion ships with an executable file (`bin/companion`) which is the -standalone server. Unlike the middleware version, options are set via -environment variables. - -:::info - -Checkout [options](#options) for the available options in JS and environment -variable formats. - -::: - -You need at least these three to get started: - -```bash -export COMPANION_SECRET="shh!Issa Secret!" -export COMPANION_DOMAIN="YOUR SERVER DOMAIN" -export COMPANION_DATADIR="PATH/TO/DOWNLOAD/DIRECTORY" -``` - -Then run: - -```bash -companion -``` - -You can also pass in the path to your JSON config file, like so: - -```bash -companion --config /path/to/companion.json -``` - -You may also want to run Companion in a process manager like -[PM2](https://pm2.keymetrics.io/) to make sure it gets restarted on upon -crashing as well as allowing scaling to many instances. - -### Express middleware mode - -First install it into your Node.js project with your favorite package manager: - -```bash -npm install @uppy/companion -``` - -To plug Companion into an existing server, call its `.app` method, passing in an -[options](#options) object as a parameter. This returns a server instance that -you can mount on a route in your Express app. Note: do **not** use the `cors` -module in your project, because Companion already includes it. Use the -`corsOrigins` Companion option to customise CORS behavior. - -```js -import express from 'express'; -import bodyParser from 'body-parser'; -import session from 'express-session'; -import companion from '@uppy/companion'; - -const app = express(); - -// Companion requires body-parser and express-session middleware. -// You can add it like this if you use those throughout your app. -// -// If you are using something else in your app, you can add these -// middlewares in the same subpath as Companion instead. -app.use(bodyParser.json()); -app.use(session({ secret: 'some secrety secret' })); - -const companionOptions = { - providerOptions: { - drive: { - key: 'GOOGLE_DRIVE_KEY', - secret: 'GOOGLE_DRIVE_SECRET', - }, - }, - server: { - host: 'localhost:3020', - protocol: 'http', - // Default installations normally don't need a path. - // However if you specify a `path`, you MUST specify - // the same path in `app.use()` below, - // e.g. app.use('/companion', companionApp) - // path: '/companion', - }, - filePath: '/path/to/folder/', -}; - -const { app: companionApp } = companion.app(companionOptions); -app.use(companionApp); -``` - -Companion uses WebSockets to communicate progress, errors, and successes to the -client. This is what Uppy listens to to update it’s internal state and UI. - -Add the Companion WebSocket server using the `companion.socket` function: - -```js -const server = app.listen(PORT); - -companion.socket(server); -``` - -If WebSockets fail for some reason Uppy and Companion will fallback to HTTP -polling. - -### Running many instances - -We recommend running at least two instances in production, so that if the -Node.js event loop gets blocked by one or more requests (due to a bug or spike -in traffic), it doesn’t also block or slow down all other requests as well (as -Node.js is single threaded). - -As an example for scale, one enterprise customer of Transloadit, who self-hosts -Companion to power an education service that is used by many universities -globally, deploys 7 Companion instances. Their earlier solution ran on 35 -instances. In our general experience Companion will saturate network interface -cards before other resources on commodity virtual servers (`c5d.2xlarge` for -instance). - -Your mileage may vary, so we recommend to add observability. You can let -Prometheus crawl the `/metrics` endpoint and graph that with Grafana for -instance. - -#### Using unique endpoints - -One option is to run many instances with each instance having its own unique -endpoint. This could be on separate ports, (sub)domain names, or IPs. With this -setup, you can either: - -1. Implement your own logic that will direct each upload to a specific Companion - endpoint by setting the `companionUrl` option -2. Setting the Companion option `COMPANION_SELF_ENDPOINT`. This option will - cause Companion to respond with a `i-am` HTTP header containing the value - from `COMPANION_SELF_ENDPOINT`. When Uppy’s sees this header, it will pin all - requests for the upload to this endpoint. - -In either case, you would then also typically configure a single Companion -instance (one endpoint) to handle all OAuth authentication requests, so that you -only need to specify a single OAuth callback URL. See also `oauthDomain` and -`validHosts`. - -#### Using a load balancer - -The other option is to set up a load balancer in front of many Companion -instances. Then Uppy will only see a single endpoint and send all requests to -the associated load balancer, which will then distribute them between Companion -instances. The companion instances coordinate their messages and events over -Redis so that any instance can serve the client’s requests. Note that sticky -sessions are **not** needed with this setup. Here are the requirements for this -setup: - -- The instances need to be connected to the same Redis server. -- You need to set `COMPANION_SECRET` to the same value on both servers. -- if you use the `companionKeysParams` feature (Transloadit), you also need - `COMPANION_PREAUTH_SECRET` to be the same on each instance. -- All other configuration needs to be the same, except if you’re running many - instances on the same machine, then `COMPANION_PORT` should be different for - each instance. - -## API - -### Options - -:::tip - -The headings display the JS and environment variable options (`option` -`ENV_OPTION`). When integrating Companion into your own server, you pass the -options to `companion.app()`. If you are using the standalone version, you -configure Companion using environment variables. Some options only exist as -environment variables or only as a JS option. - -::: - -
- Default configuration - -```javascript -const options = { - server: { - protocol: 'http', - path: '', - }, - providerOptions: {}, - s3: { - endpoint: 'https://{service}.{region}.amazonaws.com', - conditions: [], - useAccelerateEndpoint: false, - getKey: ({ filename }) => `${crypto.randomUUID()}-${filename}`, - expires: 800, // seconds - }, - allowLocalUrls: false, - logClientVersion: true, - periodicPingUrls: [], - streamingUpload: true, - clientSocketConnectTimeout: 60000, - metrics: true, -}; -``` - -
- -#### `filePath` `COMPANION_DATADIR` - -Full path to the directory to which provider files will be downloaded -temporarily. - -#### `secret` `COMPANION_SECRET` `COMPANION_SECRET_FILE` - -A secret string which Companion uses to generate authorization tokens. You -should generate a long random string for this. For example: - -```js -const crypto = require('node:crypto'); - -const secret = crypto.randomBytes(64).toString('hex'); -``` - -:::caution - -Omitting the `secret` in the standalone version will generate a secret for you, -using the above `crypto` string. But when integrating with Express you must -provide it yourself. This is an essential security measure. - -::: - -:::note - -Using a secret file means passing an absolute path to a file with any extension, -which has only the secret, nothing else. - -::: - -#### `preAuthSecret` `COMPANION_PREAUTH_SECRET` `COMPANION_PREAUTH_SECRET_FILE` - -If you are using the [Transloadit](/docs/transloadit) `companionKeysParams` -feature (Transloadit-hosted Companion using your own custom OAuth credentials), -set this variable to a strong randomly generated secret. See also -`COMPANION_SECRET` (but do not use the same secret!) - -:::note - -Using a secret file means passing an absolute path to a file with any extension, -which has only the secret, nothing else. - -::: - -#### `uploadUrls` `COMPANION_UPLOAD_URLS` - -An allowlist (array) of strings (exact URLs) or regular expressions. Companion -will only accept uploads to these URLs. This ensures that your Companion -instance is only allowed to upload to your trusted servers and prevents -[SSRF](https://en.wikipedia.org/wiki/Server-side_request_forgery) attacks. - -#### `COMPANION_PORT` - -The port on which to start the standalone server, defaults to 3020. This is a -standalone-only option. - -#### `COMPANION_COOKIE_DOMAIN` - -Allows you to customize the domain of the cookies created for Express sessions. -This is a standalone-only option. - -#### `COMPANION_HIDE_WELCOME` - -Setting this to `true` disables the welcome message shown at `/`. This is a -standalone-only option. - -#### `redisUrl` `COMPANION_REDIS_URL` - -URL to running Redis server. This can be used to scale Companion horizontally -using many instances. See [How to scale Companion](#how-to-scale-companion). - -#### `COMPANION_REDIS_EXPRESS_SESSION_PREFIX` - -Set a custom prefix for redis keys created by -[connect-redis](https://github.com/tj/connect-redis). Defaults to -`companion-session:`. Sessions are used for storing authentication state and for -allowing thumbnails to be loaded by the browser via Companion and for OAuth2. -See also `COMPANION_REDIS_PUBSUB_SCOPE`. - -#### `redisOptions` `COMPANION_REDIS_OPTIONS` - -An object of -[options supported by the `ioredis` client](https://github.com/redis/ioredis). -See also -[`RedisOptions`](https://github.com/redis/ioredis/blob/af832752040e616daf51621681bcb40cab965a9b/lib/redis/RedisOptions.ts#L8). - -#### `redisPubSubScope` `COMPANION_REDIS_PUBSUB_SCOPE` - -Use a scope for the companion events at the Redis server. Setting this option -will prefix all events with the name provided and a colon. See also -`COMPANION_REDIS_EXPRESS_SESSION_PREFIX`. - -#### `server` - -Configuration options for the underlying server. - -| Key / Environment variable | Value | Description | -| ---------------------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `protocol` `COMPANION_PROTOCOL` | `http` or `https` | Used to build a URL to reference the Companion instance itself, which is used for headers and cookies. Companion itself always runs as a HTTP server, so locally you should use `http`. You must to set this to `https` once you enabled SSL/HTTPS for your domain in production by running a reverse https-proxy in front of Companion, or with a built-in HTTPS feature of your hosting service. | -| `host` `COMPANION_DOMAIN` | `String` | Your server’s publicly facing hostname (for example `example.com`). | -| `oauthDomain` `COMPANION_OAUTH_DOMAIN` | `String` | If you have several instances of Companion with different (and perhaps dynamic) subdomains, you can set a single fixed subdomain and server (such as `sub1.example.com`) to handle your OAuth authentication for you. This would then redirect back to the correct instance with the required credentials on completion. This way you only need to configure a single callback URL for OAuth providers. | -| `path` `COMPANION_PATH` | `String` | The server path to where the Companion app is sitting. For instance, if Companion is at `example.com/companion`, then the path would be `/companion`). | -| `implicitPath` `COMPANION_IMPLICIT_PATH` | `String` | If the URL’s path in your reverse proxy is different from your Companion path in your express app, then you need to set this path as `implicitPath`. For instance, if your Companion URL is `example.com/mypath/companion`. Where the path `/mypath` is defined in your NGINX server, while `/companion` is set in your express app. Then you need to set the option `implicitPath` to `/mypath`, and set the `path` option to `/companion`. | -| `validHosts` `COMPANION_DOMAINS` | `Array` | If you are setting an `oauthDomain`, you need to set a list of valid hosts, so the oauth handler can validate the host of the Uppy instance requesting the authentication. This is essentially a list of valid domains running your Companion instances. The list may also contain regex patterns. e.g `['sub2.example.com', 'sub3.example.com', '(\\w+).example.com']` | - -#### `sendSelfEndpoint` `COMPANION_SELF_ENDPOINT` - -This is essentially the same as the `server.host + server.path` attributes. The -major reason for this attribute is that, when set, it adds the value as the -`i-am` header of every request response. - -#### `providerOptions` - -Object to enable providers with their keys and secrets. For example: - -```json -{ - "drive": { - "key": "***", - "secret": "***" - } -} -``` - -When using the standalone version you use the corresponding environment -variables or point to a secret file (such as `COMPANION_GOOGLE_SECRET_FILE`). - -:::note - -Secret files need an absolute path to a file with any extension which only has -the secret, nothing else. - -::: - -| Service | Key | Environment variables | -| ------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Box | `box` | `COMPANION_BOX_KEY`, `COMPANION_BOX_SECRET`, `COMPANION_BOX_SECRET_FILE` | -| Dropbox | `dropbox` | `COMPANION_DROPBOX_KEY`, `COMPANION_DROPBOX_SECRET`, `COMPANION_DROPBOX_SECRET_FILE` | -| Facebook | `facebook` | `COMPANION_FACEBOOK_KEY`, `COMPANION_FACEBOOK_SECRET`, `COMPANION_FACEBOOK_SECRET_FILE` | -| Google Drive | `drive` | `COMPANION_GOOGLE_KEY`, `COMPANION_GOOGLE_SECRET`, `COMPANION_GOOGLE_SECRET_FILE` | -| Google Photos | `googlephotos` | `COMPANION_GOOGLE_KEY`, `COMPANION_GOOGLE_SECRET`, `COMPANION_GOOGLE_SECRET_FILE` | -| Instagram | `instagram` | `COMPANION_INSTAGRAM_KEY`, `COMPANION_INSTAGRAM_SECRET`, `COMPANION_INSTAGRAM_SECRET_FILE` | -| OneDrive | `onedrive` | `COMPANION_ONEDRIVE_KEY`, `COMPANION_ONEDRIVE_SECRET`, `COMPANION_ONEDRIVE_SECRET_FILE`, `COMPANION_ONEDRIVE_DOMAIN_VALIDATION` (Settings this variable to `true` enables a route that can be used to validate your app with OneDrive) | -| Zoom | `zoom` | `COMPANION_ZOOM_KEY`, `COMPANION_ZOOM_SECRET`, `COMPANION_ZOOM_SECRET_FILE`, `COMPANION_ZOOM_VERIFICATION_TOKEN` | - -#### `s3` - -Companion comes with signature endpoints for AWS S3. These can be used by the -Uppy client to sign requests to upload files directly to S3, without exposing -secret S3 keys in the browser. Companion also supports uploading files from -providers like Dropbox and Instagram directly into S3. - -##### `s3.key` `COMPANION_AWS_KEY` - -The S3 access key ID. - -##### `s3.secret` `COMPANION_AWS_SECRET` `COMPANION_AWS_SECRET_FILE` - -The S3 secret access key. - -:::note - -Using a secret file means passing an absolute path to a file with any extension, -which has only the secret, nothing else. - -::: - -##### `s3.endpoint` `COMPANION_AWS_ENDPOINT` - -Optional URL to a custom S3 (compatible) service. Otherwise uses the default -from the AWS SDK. - -##### `s3.bucket` `COMPANION_AWS_BUCKET` - -The name of the bucket to store uploaded files in. - -A `string` or function that returns the name of the bucket as a `string` and -takes one argument which is an object with the following properties: - -- `filename`, the original name of the uploaded file; -- `metadata` provided by the user for the file (will only be provided during the - initial calls for each uploaded files, otherwise it will be `undefined`). -- `req`, Express.js `Request` object. Do not use any Companion internals from - the req object, as these might change in any minor version of Companion. - -#### `s3.forcePathStyle` `COMPANION_AWS_FORCE_PATH_STYLE` - -This adds support for setting the S3 client’s `forcePathStyle` option. That is -necessary to use Uppy/Companion alongside localstack in development -environments. **Default**: `false`. - -##### `s3.region` `COMPANION_AWS_REGION` - -The datacenter region where the target bucket is located. - -##### `COMPANION_AWS_PREFIX` - -An optional prefix for all uploaded keys. This is a standalone-only option. The -same can be achieved by the `getKey` option when using the express middleware. - -##### `s3.awsClientOptions` - -You can supply any -[S3 option supported by the AWS SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property) -in the `providerOptions.s3.awsClientOptions` object, _except for_ the below: - -- `accessKeyId`. Instead, use the `providerOptions.s3.key` property. This is to - make configuration names consistent between different Companion features. -- `secretAccessKey`. Instead, use the `providerOptions.s3.secret` property. This - is to make configuration names consistent between different Companion - features. - -Be aware that some options may cause wrong behaviour if they conflict with -Companion’s assumptions. If you find that a particular option does not work as -expected, please -[open an issue on the Uppy repository](https://github.com/transloadit/uppy/issues/new) -so we can document it here. - -##### `s3.getKey({ filename, metadata, req })` - -Get the key name for a file. The key is the file path to which the file will be -uploaded in your bucket. This option should be a function receiving three -arguments: - -- `filename`, the original name of the uploaded file; -- `metadata`, user-provided metadata for the file. -- `req`, Express.js `Request` object. Do not use any Companion internals from - the req object, as these might change in any minor version of Companion. - -This function should return a string `key`. The `req` parameter can be used to -upload to a user-specific folder in your bucket, for example: - -```js -app.use(authenticationMiddleware); -app.use( - uppy.app({ - providerOptions: { - s3: { - getKey: ({ req, filename, metadata }) => `${req.user.id}/${filename}`, - /* auth options */ - }, - }, - }), -); -``` - -The default implementation returns the `filename`, so all files will be uploaded -to the root of the bucket as their original file name. - -```js -app.use( - uppy.app({ - providerOptions: { - s3: { - getKey: ({ filename, metadata }) => filename, - }, - }, - }), -); -``` - -When signing on the client, this function will only be called for multipart -uploads. - -#### `COMPANION_AWS_USE_ACCELERATE_ENDPOINT` - -Enable S3 -[Transfer Acceleration](https://docs.aws.amazon.com/AmazonS3/latest/userguide/transfer-acceleration.html). -This is a standalone-only option. - -#### `COMPANION_AWS_EXPIRES` - -Set `X-Amz-Expires` query parameter in the presigned urls (in seconds, default: -300\). This is a standalone-only option. - -#### `COMPANION_AWS_ACL` - -Set a -[Canned ACL](https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl) -for uploaded objects. This is a standalone-only option. - -#### `customProviders` - -This option enables you to add custom providers along with the already supported -providers. See [adding custom providers](#how-to-add-custom-providers) for more -information. - -#### `logClientVersion` - -A boolean flag to tell Companion whether to log its version upon startup. - -#### `metrics` `COMPANION_HIDE_METRICS` - -A boolean flag to tell Companion whether to provide an endpoint `/metrics` with -Prometheus metrics (by default metrics are enabled.) - -#### `streamingUpload` `COMPANION_STREAMING_UPLOAD` - -A boolean flag to tell Companion whether to enable streaming uploads. If -enabled, it will lead to _faster uploads_ because companion will start uploading -at the same time as downloading using `stream.pipe`. If `false`, files will be -fully downloaded first, then uploaded. Defaults to `true`. - -#### `maxFileSize` `COMPANION_MAX_FILE_SIZE` - -If this value is set, companion will limit the maximum file size to process. If -unset, it will process files without any size limit (this is the default). - -#### `periodicPingUrls` `COMPANION_PERIODIC_PING_URLS` - -If this value is set, companion will periodically send POST requests to the -specified URLs. Useful for keeping track of companion instances as a keep-alive. - -#### `periodicPingInterval` `COMPANION_PERIODIC_PING_INTERVAL` - -Interval for periodic ping requests (in ms). - -#### `periodicPingStaticPayload` `COMPANION_PERIODIC_PING_STATIC_JSON_PAYLOAD` - -A `JSON.stringify`-able JavaScript Object that will be sent as part of the JSON -body in the period ping requests. - -#### `allowLocalUrls` `COMPANION_ALLOW_LOCAL_URLS` - -A boolean flag to tell Companion whether to allow requesting local URLs -(non-internet IPs). - -:::caution - -Only enable this in development. **Enabling it in production is a security -risk.** - -::: - -#### `corsOrigins` (required) - -Allowed CORS Origins. Passed as the `origin` option in -[cors](https://github.com/expressjs/cors#configuration-options). - -Note this is used for both CORS’ `Access-Control-Allow-Origin` header, and for -the -[`targetOrigin`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#targetorigin) -for `postMessage` calls in the context of OAuth. - -Setting it to `true` treats any origin as a trusted one, making it easier to -impersonate your brand. Setting it to `false` disables cross-origin support, use -this if you’re serving Companion and Uppy from the same domain name. - -##### `COMPANION_CLIENT_ORIGINS` - -Stand-alone alternative to the `corsOrigins` option. A comma-separated string of -origins, or `'true'` (which will be interpreted as the boolean value `true`), or -`'false'` (which will be interpreted as the boolean value `false`). -`COMPANION_CLIENT_ORIGINS_REGEX` will be ignored if this option is used. - -##### `COMPANION_CLIENT_ORIGINS_REGEX` - -:::note - -In most cases, you should not be using a regex, and instead provide the list of -accepted origins to `COMPANION_CLIENT_ORIGINS`. If you have to use this option, -have in mind that this regex will be used to parse unfiltered user input, so -make sure you’re validating the entirety of the string. - -::: - -Stand-alone alternative to the `corsOrigins` option. Like -`COMPANION_CLIENT_ORIGINS`, but allows a single regex instead. - -#### `chunkSize` `COMPANION_CHUNK_SIZE` - -Controls how big the uploaded chunks are for AWS S3 Multipart and Tus. Smaller -values lead to more overhead, but larger values lead to slower retries in case -of bad network connections. Passed to tus-js-client -[`chunkSize`](https://github.com/tus/tus-js-client/blob/master/docs/api.md#chunksize) -as well as -[AWS S3 Multipart](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html) -`partSize`. - -#### `enableUrlEndpoint` `COMPANION_ENABLE_URL_ENDPOINT` - -Set this to `true` to enable the [URL functionalily](https://uppy.io/docs/url/). -Default: `false`. - -### Events - -The object returned by `companion.app()` also has a property `companionEmitter` -which is an `EventEmitter` that emits the following events: - -- `upload-start` - When an upload starts, this event is emitted with an object - containing the property `token`, which is a unique ID for the upload. -- **token** - The event name is the token from `upload-start`. The event has an - object with the following properties: - - `action` - One of the following strings: - - `success` - When the upload succeeds. - - `error` - When the upload fails with an error. - - `payload` - the error or success payload. - -Example code for using the `EventEmitter` to handle a finished file upload: - -```js -const companionApp = companion.app(options); -const { companionEmitter: emitter } = companionApp; - -emitter.on('upload-start', ({ token }) => { - console.log('Upload started', token); - - function onUploadEvent({ action, payload }) { - if (action === 'success') { - emitter.off(token, onUploadEvent); // avoid listener leak - console.log('Upload finished', token, payload.url); - } else if (action === 'error') { - emitter.off(token, onUploadEvent); // avoid listener leak - console.error('Upload failed', payload); - } - } - emitter.on(token, onUploadEvent); -}); -``` - - - -## Frequently asked questions - -### Do you have a live example? - -An example server is running at . - -### How does the Authentication and Token mechanism work? - -This section describes how Authentication works between Companion and Providers. -While this behaviour is the same for all Providers (Dropbox, Instagram, Google -Drive, etc.), we are going to be referring to Dropbox in place of any Provider -throughout this section. - -The following steps describe the actions that take place when a user -Authenticates and Uploads from Dropbox through Companion: - -- The visitor to a website with Uppy clicks `Connect to Dropbox`. -- Uppy sends a request to Companion, which in turn sends an OAuth request to - Dropbox (Requires that OAuth credentials from Dropbox have been added to - Companion). -- Dropbox asks the visitor to log in, and whether the Website should be allowed - to access your files -- If the visitor agrees, Companion will receive a token from Dropbox, with which - we can temporarily download files. -- Companion encrypts the token with a secret key and sends the encrypted token - to Uppy (client) -- Every time the visitor clicks on a folder in Uppy, it asks Companion for the - new list of files, with this question, the token (still encrypted by - Companion) is sent along. -- Companion decrypts the token, requests the list of files from Dropbox and - sends it to Uppy. -- When a file is selected for upload, Companion receives the token again - according to this procedure, decrypts it again, and thereby downloads the file - from Dropbox. -- As the bytes arrive, Companion uploads the bytes to the final destination - (depending on the configuration: Apache, a Tus server, S3 bucket, etc). -- Companion reports progress to Uppy, as if it were a local upload. -- Completed! - -### How to use provider redirect URIs? - -When generating your provider API keys on their corresponding developer -platforms (e.g -[Google Developer Console](https://console.developers.google.com/)), you’d need -to provide a `redirect URI` for the OAuth authorization process. In general the -redirect URI for each provider takes the format: - -`http(s)://$YOUR_COMPANION_HOST_NAME/$PROVIDER_NAME/redirect` - -For example, if your Companion server is hosted on -`https://my.companion.server.com`, then the redirect URI you would supply for -your OneDrive provider would be: - -`https://my.companion.server.com/onedrive/redirect` - -Please see -[Supported Providers](https://uppy.io/docs/companion/#Supported-providers) for a -list of all Providers and their corresponding names. - -### How to use Companion with Kubernetes? - -We have a detailed -[guide](https://github.com/transloadit/uppy/blob/main/packages/%40uppy/companion/KUBERNETES.md) -on running Companion in Kubernetes. - -### How to add custom providers? - -As of now, Companion supports the -[providers listed here](https://uppy.io/docs/companion/#Supported-providers) out -of the box, but you may also choose to add your own custom providers. You can do -this by passing the `customProviders` option when calling the Uppy `app` method. -The custom provider is expected to support Oauth 1 or 2 for -authentication/authorization. - -```javascript -import providerModule from './path/to/provider/module'; - -const options = { - customProviders: { - myprovidername: { - config: { - authorize_url: 'https://mywebsite.com/authorize', - access_url: 'https://mywebsite.com/token', - oauth: 2, - key: '***', - secret: '***', - scope: ['read', 'write'], - }, - module: providerModule, - }, - }, -}; - -uppy.app(options); -``` - -The `customProviders` option should be an object containing each custom -provider. Each custom provider would, in turn, be an object with two keys, -`config` and `module`. The `config` option would contain Oauth API settings, -while the `module` would point to the provider module. - -To work well with Companion, the **module** must be a class with the following -methods. Note that the methods must be `async`, return a `Promise` or reject -with an `Error`): - -1. `async list ({ token, directory, query })` - Returns a object containing a - list of user files (such as a list of all the files in a particular - directory). See [example returned list data structure](#list-data). `token` - - authorization token (retrieved from oauth process) to send along with your - request - - `directory` - the id/name of the directory from which data is to be - retrieved. This may be ignored if it doesn’t apply to your provider - - `query` - expressjs query params object received by the server (in case - some data you need in there). -2. `async download ({ token, id, query })` - Downloads a particular file from - the provider. Returns an object with a single property `{ stream }` - a - [`stream.Readable`](https://nodejs.org/api/stream.html#stream_class_stream_readable), - which will be read from and uploaded to the destination. To prevent memory - leaks, make sure you release your stream if you reject this method with an - error. - - `token` - authorization token (retrieved from oauth process) to send along - with your request. - - `id` - ID of the file being downloaded. - - `query` - expressjs query params object received by the server (in case - some data you need in there). -3. `async size ({ token, id, query })` - Returns the byte size of the file that - needs to be downloaded as a `Number`. If the size of the object is not known, - `null` may be returned. - - `token` - authorization token (retrieved from oauth process) to send along - with your request. - - `id` - ID of the file being downloaded. - - `query` - expressjs query params object received by the server (in case - some data you need in there). - -The class must also have: - -- A unique `static authProvider` string property - a lowercased value which - indicates name of the [`grant`](https://github.com/simov/grant) OAuth2 - provider to use (e.g `google` for Google). If your provider doesn’t use - OAuth2, you can omit this property. -- A `static` property `static version = 2`, which is the current version of the - Companion Provider API. - -See also -[example code with a custom provider](https://github.com/transloadit/uppy/blob/main/examples/custom-provider/server). - -#### list data - -```json -{ - // username or email of the user whose provider account is being accessed - "username": "johndoe", - // list of files and folders in the directory. An item is considered a folder - // if it mainly exists as a collection to contain sub-items - "items": [ - { - // boolean value of whether or NOT it's a folder - "isFolder": false, - // icon image URL - "icon": "https://random-api.url.com/fileicon.jpg", - // name of the item - "name": "myfile.jpg", - // the mime type of the item. Only relevant if the item is NOT a folder - "mimeType": "image/jpg", - // the id (in string) of the item - "id": "uniqueitemid", - // thumbnail image URL. Only relevant if the item is NOT a folder - "thumbnail": "https://random-api.url.com/filethumbnail.jpg", - // for folders this is typically the value that will be passed as "directory" in the list(...) method. - // For files, this is the value that will be passed as id in the download(...) method. - "requestPath": "file-or-folder-requestpath", - // datetime string (in ISO 8601 format) of when this item was last modified - "modifiedDate": "2020-06-29T19:59:58Z", - // the size in bytes of the item. Only relevant if the item is NOT a folder - "size": 278940, - "custom": { - // an object that may contain some more custom fields that you may need to send to the client. Only add this object if you have a need for it. - "customData1": "the value", - "customData2": "the value" - } - // more items here - } - ], - // if the "items" list is paginated, this is the request path needed to fetch the next page. - "nextPagePath": "directory-name?cursor=cursor-to-next-page" -} -``` - -### How to run Companion locally? - -1. To set up Companion for local development, please clone the Uppy repo and - install, like so: - - ```bash - git clone https://github.com/transloadit/uppy - cd uppy - yarn install - ``` - -2. Configure your environment variables by copying the `env.example.sh` file to - `env.sh` and edit it to its correct values. - - ```bash - cp .env.example .env - $EDITOR .env - ``` - -3. To start the server, run: - - ```bash - yarn run start:companion - ``` - -This would get the Companion instance running on `http://localhost:3020`. It -uses [`node --watch`](https://nodejs.org/api/cli.html#--watch) so it will -automatically restart when files are changed. - -[box]: /docs/box -[dropbox]: /docs/dropbox -[facebook]: /docs/facebook -[googledrive]: /docs/google-drive -[googlephotos]: /docs/google-photos -[instagram]: /docs/instagram -[onedrive]: /docs/onedrive -[unsplash]: /docs/unsplash -[url]: /docs/url -[zoom]: /docs/zoom -[transloadit]: https://transloadit.com -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/compressor.mdx b/docs/compressor.mdx deleted file mode 100644 index ab817db02f..0000000000 --- a/docs/compressor.mdx +++ /dev/null @@ -1,125 +0,0 @@ ---- -sidebar_position: 12 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Compressor - -The `@uppy/compressor` plugin optimizes images (JPEG, PNG, and any other format -supported by the client’s browser) before upload, saving up to 60% in size -(roughly 18 MB for 10 images). It uses [Compressor.js][] library under the hood. - -## When should I use it? - -When your users are likely to upload images, potentially on mobile devices, and -saving data and faster uploads are important. - -## Install - - - - -```shell -npm install @uppy/compressor -``` - - - - - -```shell -yarn add @uppy/compressor -``` - - - - - - {` - import { Uppy, Compressor } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Compressor, { - // Options - }) - `} - - - - -## Use - -```js {7} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Compressor from '@uppy/compressor'; - -new Uppy() - .use(Dashboard, {inline:true, target: '#dashboard') - .use(Compressor); -``` - -No action is needed from the user — Uppy will automatically optimize images, -show an [Informer](/docs/informer) message with saved bytes, and then begin the -upload as usual. - -## API - -### Options - -:::tip - -You can also pass any of the [Compressor.js options][] here as well. - -::: - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Compressor'`). - -#### `quality` - -The quality of the output image passed to [Compressor.js][] (`number`, default: -`0.6`). - -It must be a number between `0` and `1`. Be careful to use `1` as it may make -the size of the output image become larger. In most cases, going with the -default value is best. - -:::note - -This option is only available for `image/jpeg` and `image/webp` images. - -::: - -#### `limit` - -Number of images that will be compressed in parallel (`number`, default: `10`). - -You likely don’t need to change this, unless you are experiencing performance -issues. - -#### `locale` - -```js -export default { - strings: { - // Shown in the Status Bar - compressingImages: 'Compressing images...', - compressedX: 'Saved %{size} by compressing images', - }, -}; -``` - -## Events - -#### `compressor:complete` - -The event is emitted when all files are compressed. You can use it for side -effects or custom UI notifications. - -[compressor.js]: https://github.com/fengyuanchen/compressorjs -[compressor.js options]: https://github.com/fengyuanchen/compressorjs#options diff --git a/docs/form.mdx b/docs/form.mdx deleted file mode 100644 index 1253004de3..0000000000 --- a/docs/form.mdx +++ /dev/null @@ -1,181 +0,0 @@ -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Form - -The `@uppy/form` plugin integrates with an existing HTML `
` element to -extract input data from it, and send along with the Uppy upload. It then appends -the upload result back to the form via a hidden input. - -## When should I use this? - -When you have an existing HTML `` element and you would like to: - -- **Attach the form input values to the files.** This is useful if you want to - associate meta data from the form (for example, name, location, id) with the - uploaded file, so you can process it on the backend. `@uppy/form` extracts the - input values before uploading/processing files and adds them to Uppy meta data - state (`uppy.state.meta`), as well as and each file’s meta, and appends to the - upload in an object with `[file input name attribute]` -> `[file input value]` - key/values. -- **Upload the files and put the response (such as the file URLs) into a hidden - field** (``). Then you can POST and - handle the form yourself. The appended result is a stringified version of a - result returned from calling `uppy.upload()` or listening to `complete` event. -- **Automatically start the file upload on submit or submit the form after file - upload.** This is off by default. See [`submitOnSuccess`](#submitOnSuccess) - and [`triggerUploadOnSubmit`](#triggerUploadOnSubmit) options respectively for - details. - -:::note - -If you are using a UI framework or library like React, Vue or Svelte, you’ll -most likely handle form data there as well, and thus won’t need this plugin. -Instead, pass meta data to Uppy via [`uppy.setMeta()`](/docs/uppy#setmetadata) -and listen to [`uppy.on('complete')`](/docs/uppy#complete) to get the upload -results back. - -::: - -## Install - - - - -```shell -npm install @uppy/form -``` - - - - - -```shell -yarn add @uppy/form -``` - - - - - - {` - import { Uppy, Form } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Form, { - // Options - }) - `} - - - - -## Use - -```js title="app.js" -import Uppy from '@uppy/core'; -import Form from '@uppy/form'; -import DragDrop from '@uppy/drag-drop'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/drag-drop/dist/style.min.css'; - -new Uppy().use(Form, { - target: '#my-form', -}); -``` - -```html title="index.html" - - - - - - - - -
-``` - -By default the code above will: - -1. Extract meta data from the form `#my-form`. -2. Send it with the Uppy upload. -3. Those fields will then be added to Uppy meta data state (`uppy.state.meta`) - and each file’s meta, and appended as (meta)data to the upload in an object - with `[file input name attribute]` -> `[file input value]` key/values. -4. When Uppy completes upload/processing, it will add an - `` with the stringified upload result - object back to the form. - -:::note - -You can disable both of these features, see options below. - -::: - -:::tip - -`@uppy/form` can also start Uppy upload automatically once the form is -submitted, and even submit the form after the upload is complete. This is off by -default. See [`triggerUploadOnSubmit`](#triggerUploadOnSubmit) and -[`submitOnSuccess`](#submitOnSuccess) options below for details. - -::: - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Form'`). - -#### `target` - -DOM element or CSS selector for the form element (`string` or `Element`, -default: `null`). - -This is required for the plugin to work. - -#### `resultName` - -The `name` attribute for the `` where the result will be -added (`string`, default: `uppyResult`). - -#### `getMetaFromForm` - -Configures whether to extract metadata from the form (`boolean`, default: -`true`). - -When set to `true`, the Form plugin will extract all fields from a `
` -element before upload begins. Those fields will then be added to Uppy meta data -state (`uppy.state.meta`) and each file’s meta, and appended as (meta)data to -the upload in an object with `[file input name attribute]` -> -`[file input value]` key/values. - -#### `addResultToForm` - -Configures whether to add upload/encoding results back to the form in an -`` element (`boolean`, default: `true`). - -#### `triggerUploadOnSubmit` - -Configures whether to start the upload when the form is submitted (`boolean`, -default: `false`). - -When a user submits the form (via a submit button, the Enter key or -otherwise), this option will prevent form submission, and instead upload files -via Uppy. Then you could: - -- Set `submitOnSuccess: true` if you need the form to _actually_ be submitted - once all files have been uploaded. -- Listen for `uppy.on('complete')` event to do something else if the file - uploads are all you need. For example, if the form is used for file metadata - only. - -#### `submitOnSuccess` - -Configures whether to submit the form after Uppy finishes uploading/encoding -(`boolean`, default: `false`). diff --git a/docs/framework-integrations/_category_.json b/docs/framework-integrations/_category_.json deleted file mode 100644 index 7ec3e898d5..0000000000 --- a/docs/framework-integrations/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Framework integrations", - "position": 8 -} diff --git a/docs/framework-integrations/angular.mdx b/docs/framework-integrations/angular.mdx deleted file mode 100644 index bcb154e42f..0000000000 --- a/docs/framework-integrations/angular.mdx +++ /dev/null @@ -1,117 +0,0 @@ ---- -slug: /angular ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Angular - -[Angular][] components for Uppy UI plugins. - -## When should I use it? - -When you are using the Angular framework and you would like to use one of the UI -components. - -## Install - - - - -```shell -npm install @uppy/angular -``` - - - - - -```shell -yarn add @uppy/angular -``` - - - - -:::note - -You also need to install the UI plugin you want to use. For instance, -`@uppy/dashboard`. - -::: - -## Use - -Instead of adding a UI plugin to an Uppy instance with `.use()`, the Uppy -instance can be passed into components as a `props` prop. - -The following plugins are available as Angular component wrappers: - -- Import `UppyAngularDashboardModule` used as `` renders - [`@uppy/dashboard`](/docs/dashboard) -- Import `UppyAngularDashboardModalModule` used as `` - renders [`@uppy/dashboard`](/docs/dashboard) as a modal -- Import `UppyAngularProgressBarModule` used as `` renders - [`@uppy/progress-bar`](/docs/progress-bar) -- Import `UppyAngularStatusBarModule` used as `` renders - [`@uppy/status-bar`](/docs/status-bar) -- Import `UppyAngularDragDropModule` used as `` renders - [`@uppy/drag-drop`](/docs/drag-drop) - -Each component takes a `props` prop that will be passed to the UI Plugin. - -```typescript title="app.module.ts" showLineNumbers -import { NgModule } from '@angular/core'; -import { UppyAngularDashboardModule } from '@uppy/angular'; - -import { BrowserModule } from '@angular/platform-browser'; -import { AppComponent } from './app.component'; - -@NgModule({ - declarations: [AppComponent], - imports: [BrowserModule, UppyAngularDashboardModule], - providers: [], - bootstrap: [AppComponent], -}) -class {} -``` - -```html title="app.component.html" showLineNumbers - -``` - -You should initialize Uppy as a property of your component. - -```typescript title="app.component.ts" showLineNumbers -import { Component } from '@angular/core'; -import { Uppy } from '@uppy/core'; - -@Component({ - selector: 'app-root', -}) -export class AppComponent { - uppy: Uppy = new Uppy({ debug: true, autoProceed: true }); -} -``` - -### CSS - -All components have their own styling and should be added to your component -decorator. You can find the CSS import statements in the docs of the UI plugin -you want to use. For instance, for `@uppy/dashboard`: - -```typescript -import { Component, ViewEncapsulation } from '@angular/core'; -//... -@Component({ - // ... - encapsulation: ViewEncapsulation.None, - styleUrls: [ - '../node_modules/@uppy/core/dist/style.css', - '../node_modules/@uppy/dashboard/dist/style.css', - ], -}) -``` - -[angular]: https://angular.io diff --git a/docs/framework-integrations/nextjs.mdx b/docs/framework-integrations/nextjs.mdx deleted file mode 100644 index 1aa9040fec..0000000000 --- a/docs/framework-integrations/nextjs.mdx +++ /dev/null @@ -1,434 +0,0 @@ ---- -slug: /nextjs ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Next.js - -Integration guide for [Next.js][] featuring the [dashboard](/docs/dashboard), -the [tus](/docs/tus) uploader, [transloadit](/docs/transloadit), multipart -uploads to a Next.js route, the Uppy UI components, and the -[React hooks](/docs/react). - -:::tip - -Uppy also has hooks and more React examples in the [React docs](/docs/react). - -::: - -## Install - - - - -```shell -npm install @uppy/core @uppy/dashboard @uppy/react -``` - - - - - -```shell -yarn add @uppy/core @uppy/dashboard @uppy/react -``` - - - - -## Tus - -[Tus][tus] is an open protocol for resumable uploads built on HTTP. This means -accidentally closing your tab or losing connection let’s you continue, for -instance, your 10GB upload instead of starting all over. - -Tus supports any language, any platform, and any network. It requires a client -and server integration to work. We will be using [tus Node.js][]. - -Checkout the [`@uppy/tus` docs](/docs/tus) for more information. - -```tsx -'use client'; - -import Uppy from '@uppy/core'; -// For now, if you do not want to install UI components you -// are not using import from lib directly. -import Dashboard from '@uppy/react/lib/Dashboard'; -import Tus from '@uppy/tus'; -import { useState } from 'react'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -function createUppy() { - return new Uppy().use(Tus, { endpoint: '/api/upload' }); -} - -export default function UppyDashboard() { - // Important: use an initializer function to prevent the state from recreating. - const [uppy] = useState(createUppy); - - return ; -} -``` - -[`@tus/server`][] does not not support the Next.js app router yet, which is -based on the fetch `Request` API instead of `http.IncomingMessage` and -`http.ServerResponse`. - -Even if you are fully comitting to the app router, there is no downside to still -having the pages router next to it for some Node.js style API routes. - -Attach the tus server handler to a Next.js route handler in an -[optional catch-all route file](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes#optional-catch-all-routes). - -`/pages/api/upload/[[...file]].ts` - -```ts -import type { NextApiRequest, NextApiResponse } from 'next'; -import { Server, Upload } from '@tus/server'; -import { FileStore } from '@tus/file-store'; - -/** - * !Important. This will tell Next.js NOT Parse the body as tus requires - * @see https://nextjs.org/docs/api-routes/request-helpers - */ -export const config = { - api: { - bodyParser: false, - }, -}; - -const tusServer = new Server({ - // `path` needs to match the route declared by the next file router - path: '/api/upload', - datastore: new FileStore({ directory: './files' }), -}); - -export default function handler(req: NextApiRequest, res: NextApiResponse) { - return tusServer.handle(req, res); -} -``` - -## Transloadit - -:::note - -Before continuing you should have a [Transloadit](https://transloadit.com) -account and a -[Template](https://transloadit.com/docs/getting-started/my-first-app/) setup. - -::: - -Transloadit’s strength is versatility. By doing video, audio, images, documents, -and more, you only need one vendor for [all your file processing -needs][transloadit-services]. The [`@uppy/transloadit`](/docs/transloadit) -plugin directly uploads to Transloadit so you only have to worry about creating -a [template][transloadit-concepts]. It uses -[Tus](#i-want-reliable-resumable-uploads) under the hood so you don’t have to -sacrifice reliable, resumable uploads for convenience. - -When you go to production always make sure to set the `signature`. **Not using -[Signature Authentication](https://transloadit.com/docs/topics/signature-authentication/) -can be a security risk**. Signature Authentication is a security measure that -can prevent outsiders from tampering with your Assembly Instructions. - -Generating a signature should be done on the server to avoid leaking secrets. - - - - -`/app/api/transloadit/route.ts` - -```ts -import { NextResponse, NextRequest } from 'next/server'; -import crypto from 'crypto'; - -function utcDateString(ms: number): string { - return new Date(ms) - .toISOString() - .replace(/-/g, '/') - .replace(/T/, ' ') - .replace(/\.\d+Z$/, '+00:00'); -} - -export async function POST(request: NextRequest) { - // expire 1 hour from now (this must be milliseconds) - const expires = utcDateString(Date.now() + 1 * 60 * 60 * 1000); - const authKey = process.env.TRANSLOADIT_KEY; - const authSecret = process.env.TRANSLOADIT_SECRET; - const templateId = process.env.TRANSLOADIT_TEMPLATE_ID; - - // Typically, here you would also deny generating a signature for improper use - if (!authKey || !authSecret || !templateId) { - return NextResponse.json( - { error: 'Missing Transloadit credentials' }, - { status: 500 }, - ); - } - - const body = await request.json(); - const params = JSON.stringify({ - auth: { - key: authKey, - expires, - }, - template_id: templateId, - fields: { - // This becomes available in your Template as `${fields.customValue}` - // and could be used to have a storage directory per user for example - customValue: body.customValue, - }, - // your other params like notify_url, etc. - }); - - const signatureBytes = crypto - .createHmac('sha384', authSecret) - .update(Buffer.from(params, 'utf-8')); - // The final signature needs the hash name in front, so - // the hashing algorithm can be updated in a backwards-compatible - // way when old algorithms become insecure. - const signature = `sha384:${signatureBytes.digest('hex')}`; - - return NextResponse.json({ expires, signature, params }); -} -``` - - - - - -`/pages/api/transloadit/params.ts` - -```ts -import type { NextApiRequest, NextApiResponse } from 'next'; -import crypto from 'node:crypto'; - -function utcDateString(ms: number): string { - return new Date(ms) - .toISOString() - .replace(/-/g, '/') - .replace(/T/, ' ') - .replace(/\.\d+Z$/, '+00:00'); -} - -export default function handler(req: NextApiRequest, res: NextApiResponse) { - // Typically, here you would also deny generating a signature for improper use - if (req.method !== 'POST') { - return res.status(405).json({ error: 'Method Not Allowed' }); - } - - // expire 1 hour from now (this must be milliseconds) - const expires = utcDateString(Date.now() + 1 * 60 * 60 * 1000); - const authKey = process.env.TRANSLOADIT_KEY; - const authSecret = process.env.TRANSLOADIT_SECRET; - const templateId = process.env.TRANSLOADIT_TEMPLATE_ID; - - if (!authKey || !authSecret || !templateId) { - return res.status(500).json({ error: 'Missing Transloadit credentials' }); - } - - const params = JSON.stringify({ - auth: { - key: authKey, - expires, - }, - template_id: templateId, - fields: { - // This becomes available in your Template as `${fields.customValue}` - // and could be used to have a storage directory per user for example - customValue: req.body.customValue, - }, - // your other params like notify_url, etc. - }); - - const signatureBytes = crypto - .createHmac('sha384', authSecret) - .update(Buffer.from(params, 'utf-8')); - // The final signature needs the hash name in front, so - // the hashing algorithm can be updated in a backwards-compatible - // way when old algorithms become insecure. - const signature = `sha384:${signatureBytes.digest('hex')}`; - - res.status(200).json({ expires, signature, params }); -} -``` - - - - -On the client we want to fetch the signature and params from the server. You may -want to send values from React state along to your endpoint, for instance to add -[`fields`](https://transloadit.com/docs/topics/assembly-variables/) which you -can use in your template as global variables. - -```js -// ... -function createUppy() { - const uppy = new Uppy(); - uppy.use(Transloadit, { - async assemblyOptions() { - // You can send meta data along for use in your template. - // https://transloadit.com/docs/topics/assembly-instructions/#form-fields-in-instructions - const { meta } = uppy.getState(); - const body = JSON.stringify({ customValue: meta.customValue }); - const res = await fetch('/transloadit-params', { method: 'POST', body }); - return response.json(); - }, - }); - return uppy; -} - -function Component({ customValue }) { - // IMPORTANT: passing an initializer function to prevent the state from recreating. - const [uppy] = useState(createUppy); - - useEffect(() => { - if (customValue) { - uppy.setOptions({ meta: { customValue } }); - } - }, [uppy, customValue]); -} -``` - -## HTTP uploads to your backend - -If you want to handle uploads yourself, in Next.js or another server in any -language, you can use [`@uppy/xhr-upload`](/docs/xhr-upload). - -:::warning - -The server-side examples are simplified for demonstration purposes and assume a -regular file upload while `@uppy/xhr-upload` can also send `FormData` through -the `formData` or `bundle` options. - -::: - - - - -```ts -import { NextRequest, NextResponse } from 'next/server'; -import { writeFile } from 'node:fs/promises'; -import path from 'node:path'; - -export const config = { - api: { - bodyParser: false, - }, -}; - -export async function POST(request: NextRequest) { - const formData = await request.formData(); - const file = formData.get('file') as File | null; - - if (!file) { - return NextResponse.json({ error: 'No file uploaded' }, { status: 400 }); - } - - const buffer = Buffer.from(await file.arrayBuffer()); - const filename = file.name.replace(/\s/g, '-'); - const filepath = path.join(process.cwd(), 'public', 'uploads', filename); - - try { - await writeFile(filepath, buffer); - return NextResponse.json({ - message: 'File uploaded successfully', - filename, - }); - } catch (error) { - console.error('Error saving file:', error); - return NextResponse.json({ error: 'Error saving file' }, { status: 500 }); - } -} -``` - - - - - -```ts -import type { NextApiRequest, NextApiResponse } from 'next'; -import { createWriteStream } from 'fs'; -import { pipeline } from 'stream/promises'; -import path from 'path'; - -export const config = { - api: { - bodyParser: false, - }, -}; - -export default async function handler( - req: NextApiRequest, - res: NextApiResponse, -) { - if (req.method !== 'POST') { - return res.status(405).json({ error: 'Method Not Allowed' }); - } - - try { - const filename = `file-${Date.now()}.txt`; - const filepath = path.join(process.cwd(), 'public', 'uploads', filename); - const writeStream = createWriteStream(filepath); - - await pipeline(req, writeStream); - - res.status(200).json({ message: 'File uploaded successfully', filename }); - } catch (error) { - console.error('Error saving file:', error); - res.status(500).json({ error: 'Error saving file' }); - } -} -``` - - - - -```tsx -'use client'; - -import Uppy from '@uppy/core'; -// For now, if you do not want to install UI components you -// are not using import from lib directly. -import Dashboard from '@uppy/react/lib/Dashboard'; -import Xhr from '@uppy/xhr-upload'; -import { useState } from 'react'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -function createUppy() { - return new Uppy().use(Xhr, { endpoint: '/api/upload' }); -} - -export default function UppyDashboard() { - // Important: use an initializer function to prevent the state from recreating. - const [uppy] = useState(createUppy); - - return ; -} -``` - -## Next steps - -- Add client-side file [restrictions](/docs/uppy/#restrictions). -- Upload files together with other form fields with [`@uppy/form`](/docs/form). -- Use your [language of choice](/docs/locales) instead of English. -- Add an [image editor](docs/image-editor) for cropping and resizing images. -- Download files from remote sources, such as [Google Drive](docs/google-drive) - and [Dropbox](docs/dropbox), with [Companion](/docs/companion). -- Add [Golden Retriever](/docs/golden-retriever) to save selected files in your - browser cache, so that if the browser crashes, or the user accidentally closes - the tab, Uppy can restore everything and continue uploading as if nothing - happened. - -[transloadit-concepts]: https://transloadit.com/docs/getting-started/concepts/ -[transloadit-services]: https://transloadit.com/services/ -[Next.js]: https://nextjs.org/ -[tus]: https://tus.io/ -[tus Node.js]: https://github.com/tus/tus-node-server -[`@tus/server`]: - https://github.com/tus/tus-node-server/tree/main/packages/server diff --git a/docs/framework-integrations/react.mdx b/docs/framework-integrations/react.mdx deleted file mode 100644 index 5d2267ea33..0000000000 --- a/docs/framework-integrations/react.mdx +++ /dev/null @@ -1,247 +0,0 @@ ---- -slug: /react ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# React - -[React][] components for the Uppy UI plugins and hooks. - -## Install - - - - -```shell -npm install @uppy/react -``` - - - - - -```shell -yarn add @uppy/react -``` - - - - -:::note - -You also need to install the UI plugin you want to use. For instance, -`@uppy/dashboard`. - -::: - -## Use - -`@uppy/react` exposes component wrappers for `Dashboard`, `DragDrop`, and all -other UI elements. The components can be used with either [React][] or -API-compatible alternatives such as [Preact][]. - -:::caution - -If you find yourself writing many instances of `useState` and `useEffect` to -achieve something with Uppy in React, you are most likely breaking React best -practices. Consider reading -“[You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect)” -and looking at our examples below. - -::: - -### Components - -The following components are exported from `@uppy/react`: - -- `` renders [`@uppy/dashboard`](/docs/dashboard) -- `` renders [`@uppy/dashboard`](/docs/dashboard) as a modal -- `` renders [`@uppy/drag-drop`](/docs/drag-drop) -- `` renders [`@uppy/progress-bar`](/docs/progress-bar) -- `` renders [`@uppy/status-bar`](/docs/status-bar) - -### Hooks - -#### `useUppyState(uppy, selector)` - -Use this hook when you need to access Uppy’s state reactively. Most of the -times, this is needed if you are building a custom UI for Uppy in React. - -```js -// IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render. -const [uppy] = useState(() => new Uppy()); - -const files = useUppyState(uppy, (state) => state.files); -const totalProgress = useUppyState(uppy, (state) => state.totalProgress); -// We can also get specific plugin state. -// Note that the value on `plugins` depends on the `id` of the plugin. -const metaFields = useUppyState( - uppy, - (state) => state.plugins?.Dashboard?.metaFields, -); -``` - -You can see all the values you can access on the -[`State`](https://github.com/transloadit/uppy/blob/c45407d099d87e25cecaf03c5d9ce59c582ca0dc/packages/%40uppy/core/src/Uppy.ts#L155-L181) -type. If you are accessing plugin state, you would have to look at the types of -the plugin. - -#### `useUppyEvent(uppy, event, callback)` - -Listen to Uppy events in a React component. - -The first item in the array is an array of results from the event. Depending on -the event, that can be empty or have up to three values. The second item is a -function to clear the results. Values remain in state until the next event (if -that ever comes). Depending on your use case, you may want to keep the values in -state or clear the state after something else happenend. - -```ts -// IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render. -const [uppy] = useState(() => new Uppy()); - -const [results, clearResults] = useUppyEvent(uppy, 'transloadit:result'); -const [stepName, result, assembly] = results; // strongly typed - -useUppyEvent(uppy, 'cancel-all', clearResults); -``` - -## Examples - -### Example: basic component - -Here we have a basic component which ties Uppy’s state to the component. This -means you can render multiple instances. But be aware that as your component -unmounts, for instance because the user navigates to a different page, Uppy’s -state will be lost and uploads will stop. - -:::note - -If you render multiple instances of Uppy, make sure to give each instance a -unique `id`. - -::: - -```js -import React, { useEffect, useState } from 'react'; -import Uppy from '@uppy/core'; -import Webcam from '@uppy/webcam'; -import { Dashboard } from '@uppy/react'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; -import '@uppy/webcam/dist/style.min.css'; - -function Component() { - // IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render. - const [uppy] = useState(() => new Uppy().use(Webcam)); - - return ; -} -``` - -### Example: keep Uppy state and uploads while navigating between pages - -When you want Uppy’s state to persist and keep uploads running between pages, -you can -[lift the state up](https://react.dev/learn/sharing-state-between-components#lifting-state-up-by-example). - -```js -import React, { useState, useEffect } from 'react'; -import Uppy from '@uppy/core'; -import { Dashboard } from '@uppy/react'; - -function Page1() { - // ... -} - -function Page2({ uppy }) { - return ( - <> -

{totalProgress}

- - - ); -} - -export default function App() { - // keeping the uppy instance alive above the pages the user can switch during uploading - const [uppy] = useState(() => new Uppy()); - - return ( - // Add your router here - <> - - - - ); -} -``` - -### Example: updating Uppy’s options dynamically based on props - -```js -// ... -function Component(props) { - // IMPORTANT: passing an initializer function to prevent the state from recreating. - const [uppy] = useState(() => new Uppy().use(Webcam)); - - useEffect(() => { - uppy.setOptions({ restrictions: props.restrictions }); - }, [props.restrictions]); - - useEffect(() => { - uppy.getPlugin('Webcam').setOptions({ modes: props.webcamModes }); - }, [props.webcamModes]); - - return ; -} -``` - -### Example: dynamic params and signature for Transloadit - -When you go to production always make sure to set the `signature`. **Not using -[Signature Authentication](https://transloadit.com/docs/topics/signature-authentication/) -can be a security risk**. Signature Authentication is a security measure that -can prevent outsiders from tampering with your Assembly Instructions. - -Generating a signature should be done on the server to avoid leaking secrets. In -React, this could get awkward with a `fetch` in a `useEffect` and setting it to -`useState`. Instead, it’s easier to use the -[`assemblyOptions`](/docs/transloadit#assemblyoptions) option to `fetch` the -params. - -```js -// ... -function createUppy() { - const uppy = new Uppy(); - uppy.use(Transloadit, { - async assemblyOptions() { - // You can send meta data along for use in your template. - // https://transloadit.com/docs/topics/assembly-instructions/#form-fields-in-instructions - const { meta } = uppy.getState(); - const body = JSON.stringify({ userId: meta.userId }); - const res = await fetch('/transloadit-params', { method: 'POST', body }); - return response.json(); - }, - }); - return uppy; -} - -function Component({ userId }) { - // IMPORTANT: passing an initializer function to prevent Uppy from being reinstantiated on every render. - const [uppy] = useState(createUppy); - - useEffect(() => { - if (userId) { - // Adding to global `meta` will add it to every file. - uppy.setOptions({ meta: { userId } }); - } - }, [uppy, userId]); -} -``` - -[react]: https://facebook.github.io/react -[preact]: https://preactjs.com/ diff --git a/docs/framework-integrations/svelte.mdx b/docs/framework-integrations/svelte.mdx deleted file mode 100644 index 6d8922bc36..0000000000 --- a/docs/framework-integrations/svelte.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -slug: /svelte ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Svelte - -[Svelte][] components for the Uppy UI plugins. - -## Install - - - - -```shell -npm install @uppy/svelte -``` - - - - - -```shell -yarn add @uppy/svelte -``` - - - - -:::note - -You also need to install the UI plugin you want to use. For instance, -`@uppy/dashboard`. - -::: - -## Use - -The following plugins are available as Svelte component wrappers: - -- `` renders [`@uppy/dashboard`](/docs/dashboard) -- `` renders [`@uppy/dashboard`](/docs/dashboard) as a modal -- `` renders [`@uppy/drag-drop`](/docs/drag-drop) -- `` renders [`@uppy/progress-bar`](/docs/progress-bar) -- `` renders [`@uppy/status-bar`](/docs/status-bar) - -Instead of adding a UI plugin to an Uppy instance with `.use()`, the Uppy -instance can be passed into components as an `uppy` prop. Due to the way Svelte -handles reactivity, you can initialize Uppy the same way you would with vanilla -JavaScript. - -```svelte - - -
-``` - -[svelte]: https://svelte.dev diff --git a/docs/framework-integrations/vue.mdx b/docs/framework-integrations/vue.mdx deleted file mode 100644 index 2d348f8022..0000000000 --- a/docs/framework-integrations/vue.mdx +++ /dev/null @@ -1,73 +0,0 @@ ---- -slug: /vue ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -# Vue - -[Vue][] components for the Uppy UI plugins. - -## Install - - - - -```shell -npm install @uppy/vue -``` - - - - - -```shell -yarn add @uppy/vue -``` - - - - -:::note - -You also need to install the UI plugin you want to use. For instance, -`@uppy/dashboard`. - -::: - -## Use - -The following plugins are available as Vue component wrappers: - -- `` renders [`@uppy/dashboard`](/docs/dashboard) inline -- `` renders [`@uppy/dashboard`](/docs/dashboard) as a modal -- `` renders [`@uppy/drag-drop`](/docs/drag-drop) -- `` renders [`@uppy/progress-bar`](/docs/progress-bar) -- `` renders [`@uppy/status-bar`](/docs/status-bar) - -Instead of adding a UI plugin to an Uppy instance with `.use()`, the Uppy -instance can be passed into components as an `uppy` prop. Due to the way Vue -handles reactivity, you can initialize Uppy the same way you would with vanilla -JavaScript. - -```html - - - -``` - -[vue]: https://vuejs.org diff --git a/docs/golden-retriever.mdx b/docs/golden-retriever.mdx deleted file mode 100644 index 33387d2804..0000000000 --- a/docs/golden-retriever.mdx +++ /dev/null @@ -1,150 +0,0 @@ ---- -sidebar_position: 11 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Golden Retriever - -The `@uppy/golden-retriever` plugin saves selected files in your browser cache, -so that if the browser crashes, or the user accidentally closes the tab, Uppy -can restore everything and continue uploading as if nothing happened. You can -read more about it -[on our blog](https://uppy.io/blog/2017/07/golden-retriever/). - -The Golden Retriever uses three methods of browser data storage: - -- `LocalStorage` to store file metadata and Uppy state only. -- `IndexedDB` for small files, usually under 5MiB. -- `Service Worker` (_optional_) for _all_ files because, unlike `IndexedDB`, - `Service Worker` can keep references to large files. Service Worker storage is - _quite_ temporary though, and doesn’t persist across browser crashes or - restarts. It works well, however, for accidental refreshes or closed tabs. - -Upon restore, the plugin first restores state from `LocalStorage` and then -checks both file storages — `IndexedDB` and `ServiceWorker` — merging the -results. - -If restore is unsuccessful for certain files, they will be marked as “ghosts” in -the Dashboard UI, and a message + button offering to re-select those files will -be displayed. - -Checkout the -[storage quotas](https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria#other_web_technologies) -on MDN to see how much data can be stored depending on the device and browser. - -## When should I use this? - -When you want extra insurance for the user-selected files. If you feel like -users might spend some time picking files, tweaking descriptions etc, and will -not appreciate having to do it over again if something crashes. Another use case -might be when you think user might want to pick a few files, navigate away to do -something else in your app or otherwise, and then come back to the same -selection. - -## Install - - - - -```shell -npm install @uppy/golden-retriever -``` - - - - - -```shell -yarn add @uppy/golden-retriever -``` - - - - - - {` - import { Uppy, GoldenRetriever } from "{{UPPY_JS_URL}}" - new Uppy().use(GoldenRetriever) - `} - - - - -## Use - -```js {7} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import GoldenRetriever from '@uppy/golden-retriever'; - -new Uppy() - .use(Dashboard, {inline:true, target: '#dashboard') - .use(GoldenRetriever); -``` - -By default, Golden Retriever will only use the `IndexedDB` storage, which is -good enough for files up to 5 MiB. `Service Worker` is optional and requires -setup. - -### Enabling Service Worker - -With the Service Worker storage, Golden Retriever will be able to temporary -store references to large files. - -1. Bundle your own service worker `sw.js` file with Uppy GoldenRetriever’s - service worker. - - :::tip - - For Webpack, check out - [serviceworker-webpack-plugin](https://github.com/oliviertassinari/serviceworker-webpack-plugin). - - ::: - - ```js title="sw.js" - import '@uppy/golden-retriever/lib/ServiceWorker'; - ``` - -2. Register it in your app’s entry point: - - ```js - // you app.js entry point - uppy.use(GoldenRetriever, { serviceWorker: true }); - - if ('serviceWorker' in navigator) { - navigator.serviceWorker - .register('/sw.js') // path to your bundled service worker with GoldenRetriever service worker - .then((registration) => { - console.log( - 'ServiceWorker registration successful with scope: ', - registration.scope, - ); - }) - .catch((error) => { - console.log(`Registration failed with ${error}`); - }); - } - ``` - -Voilà, that’s it. Happy retrieving! - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'GoldenRetriever'`). - -#### `expires` - -How long to store metadata and files for. Used for `LocalStorage` and -`IndexedDB` (`number`, default: `24 * 60 * 60 * 1000` // 24 hours). - -#### `serviceWorker` - -Whether to enable `Service Worker` storage (`boolean`, default: `false`). diff --git a/docs/guides/_category_.json b/docs/guides/_category_.json deleted file mode 100644 index 82e09efaaf..0000000000 --- a/docs/guides/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Guides", - "position": 2 -} diff --git a/docs/guides/browser-support.mdx b/docs/guides/browser-support.mdx deleted file mode 100644 index aa963d51bd..0000000000 --- a/docs/guides/browser-support.mdx +++ /dev/null @@ -1,51 +0,0 @@ ---- -sidebar_position: 7 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Supporting IE11 - -We officially support recent versions of Chrome, Firefox, Safari and Edge. - -Internet Explorer is not officially supported, as in we don’t run tests for it, -but you can be mostly confident it works with the right polyfills. But it does -come with a risk of unexpected results in styling or functionality. - -## Polyfills - - - - -```shell -npm install core-js whatwg-fetch abortcontroller-polyfill md-gum-polyfill resize-observer-polyfill -``` - - - - - -```shell -yarn add core-js whatwg-fetch abortcontroller-polyfill md-gum-polyfill resize-observer-polyfill -``` - - - - -```js -import 'core-js'; -import 'whatwg-fetch'; -import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'; -// Order matters: AbortController needs fetch which needs Promise (provided by core-js). - -import 'md-gum-polyfill'; -import ResizeObserver from 'resize-observer-polyfill'; - -window.ResizeObserver ??= ResizeObserver; - -export { default } from '@uppy/core'; -export * from '@uppy/core'; -``` diff --git a/docs/guides/building-plugins.md b/docs/guides/building-plugins.md deleted file mode 100644 index d6b44178cf..0000000000 --- a/docs/guides/building-plugins.md +++ /dev/null @@ -1,382 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Building plugins - -You can find already a few useful Uppy plugins out there, but there might come a -time when you will want to build your own. Plugins can hook into the upload -process or render a custom UI, typically to: - -- Render some custom UI element, such as [StatusBar](/docs/status-bar) or - [Dashboard](/docs/dashboard). -- Do the actual uploading, such as [XHRUpload](/docs/xhr-upload) or - [Tus](/docs/tus). -- Do work before the upload, like compressing an image or calling external API. -- Interact with a third-party service to process uploads correctly, such as - [Transloadit](/docs/transloadit) or [AwsS3](/docs/aws-s3). - -See a [full example of a plugin](#example-of-a-custom-plugin) below. - -## Creating A Plugin - -Uppy has two classes to create plugins with. `BasePlugin` for plugins that don’t -need a user interface, and `UIPlugin` for ones that do. Each plugin has an `id` -and a `type`. `id`s are used to uniquely identify plugins. A `type` can be -anything—some plugins use `type`s to decide whether to do something to some -other plugin. For example, when targeting plugins at the built-in `Dashboard` -plugin, the Dashboard uses the `type` to figure out where to mount different UI -elements. `'acquirer'`-type plugins are mounted into the tab bar, while -`'progressindicator'`-type plugins are mounted into the progress bar area. - -The plugin constructor receives the Uppy instance in the first parameter, and -any options passed to `uppy.use()` in the second parameter. - -```js -import BasePlugin from '@uppy/core'; - -export default class MyPlugin extends BasePlugin { - constructor(uppy, opts) { - super(uppy, opts); - this.id = opts.id || 'MyPlugin'; - this.type = 'example'; - } -} -``` - -## Methods - -Plugins can define methods to execute certain tasks. The most important method -is `install()`, which is called when a plugin is `.use`d. - -All the below methods are optional! Only define the methods you need. - -### `BasePlugin` - -#### `install()` - -Called when the plugin is `.use`d. Do any setup work here, like attaching events -or adding [upload hooks](#Upload-Hooks). - -```js -export default class MyPlugin extends UIPlugin { - // ... - install() { - this.uppy.on('upload-progress', this.onProgress); - this.uppy.addPostProcessor(this.afterUpload); - } -} -``` - -#### `uninstall()` - -Called when the plugin is removed, or the Uppy instance is closed. This should -undo all the work done in the `install()` method. - -```js -export default class MyPlugin extends UIPlugin { - // ... - uninstall() { - this.uppy.off('upload-progress', this.onProgress); - this.uppy.removePostProcessor(this.afterUpload); - } -} -``` - -#### `afterUpdate()` - -Called after every state update with a debounce, after everything has mounted. - -#### `addTarget()` - -Use this to add your plugin to another plugin’s target. This is what -`@uppy/dashboard` uses to add other plugins to its UI. - -### `UIPlugin` - -`UIPlugin` extends the `BasePlugin` class so it will also contain all the above -methods. - -#### `mount(target)` - -Mount this plugin to the `target` element. `target` can be a CSS query selector, -a DOM element, or another Plugin. If `target` is a Plugin, the source (current) -plugin will register with the target plugin, and the latter can decide how and -where to render the source plugin. - -This method can be overridden to support for different render engines. - -#### `render()` - -Render this plugin’s UI. Uppy uses [Preact](https://preactjs.com) as its view -engine, so `render()` should return a Preact element. `render` is automatically -called by Uppy on each state change. - -#### `onMount()` - -Called after Preact has rendered the components of the plugin. - -#### `update(state)` - -Called on each state update. You will rarely need to use this, unless if you -want to build a UI plugin using something other than Preact. - -#### `onUnmount()` - -Called after the elements have been removed from the DOM. Can be used to do some -clean up or other side-effects. - -## Upload Hooks - -When creating an upload, Uppy runs files through an upload pipeline. The -pipeline consists of three parts, each of which can be hooked into: -Preprocessing, Uploading, and Postprocessing. Preprocessors can be used to -configure uploader plugins, encrypt files, resize images, etc., before uploading -them. Uploaders do the actual uploading work, such as creating an XMLHttpRequest -object and sending the file. Postprocessors do their work after files have been -uploaded completely. This could be anything from waiting for a file to propagate -across a CDN, to sending another request to relate some metadata to the file. - -Each hook is a function that receives an array containing the file IDs that are -being uploaded, and returns a Promise to signal completion. Hooks are added and -removed through `Uppy` methods: -[`addPreProcessor`](/docs/uppy#addpreprocessorfn), -[`addUploader`](/docs/uppy#adduploaderfn), -[`addPostProcessor`](/docs/uppy#addpostprocessorfn), and their -[`remove*`](/docs/uppy#removepreprocessorremoveuploaderremovepostprocessorfn) -counterparts. Normally, hooks should be added during the plugin `install()` -method, and removed during the `uninstall()` method. - -Additionally, upload hooks can fire events to signal progress. - -When adding hooks, make sure to bind the hook `fn` beforehand! Otherwise, it -will be impossible to remove. For example: - -```js -class MyPlugin extends BasePlugin { - constructor(uppy, opts) { - super(uppy, opts); - this.id = opts.id || 'MyPlugin'; - this.type = 'example'; - this.prepareUpload = this.prepareUpload.bind(this); // ← this! - } - - prepareUpload(fileIDs) { - console.log(this); // `this` refers to the `MyPlugin` instance. - return Promise.resolve(); - } - - install() { - this.uppy.addPreProcessor(this.prepareUpload); - } - - uninstall() { - this.uppy.removePreProcessor(this.prepareUpload); - } -} -``` - -Or you can define the method as a class field: - -```js -class MyPlugin extends UIPlugin { - constructor(uppy, opts) { - super(uppy, opts); - this.id = opts.id || 'MyPlugin'; - this.type = 'example'; - } - - prepareUpload = (fileIDs) => { - // ← this! - console.log(this); // `this` refers to the `MyPlugin` instance. - return Promise.resolve(); - }; - - install() { - this.uppy.addPreProcessor(this.prepareUpload); - } - - uninstall() { - this.uppy.removePreProcessor(this.prepareUpload); - } -} -``` - -## Progress events - -Progress events can be fired for individual files to show feedback to the user. -For upload progress events, only emitting how many bytes are expected and how -many have been uploaded is enough. Uppy will handle calculating progress -percentages, upload speed, etc. - -Preprocessing and postprocessing progress events are plugin-dependent and can -refer to anything, so Uppy doesn’t try to be smart about them. Processing -progress events can be of two types: determinate or indeterminate. Some -processing does not have meaningful progress beyond “not done” and “done”. For -example, sending a request to initialize a server-side resource that will serve -as the upload destination. In those situations, indeterminate progress is -suitable. Other processing does have meaningful progress. For example, -encrypting a large file. In those situations, determinate progress is suitable. - -Here are the relevant events: - -- [`preprocess-progress`](/docs/uppy#preprocess-progress) -- [`upload-progress`](/docs/uppy#upload-progress) -- [`postprocess-progress`](/docs/uppy#postprocess-progress) - -## JSX - -Since Uppy uses Preact and not React, the default Babel configuration for JSX -elements does not work. You have to import the Preact `h` function and tell -Babel to use it by adding a `/** @jsx h */` comment at the top of the file. - -See the Preact -[Getting Started Guide](https://preactjs.com/guide/getting-started) for more on -Babel and JSX. - - - -```jsx -/** @jsx h */ -import { UIPlugin } from '@uppy/core'; -import { h } from 'preact'; - -class NumFiles extends UIPlugin { - render() { - const numFiles = Object.keys(this.uppy.state.files).length; - - return
Number of files: {numFiles}
; - } -} -``` - -## Locales - -For any user facing language that you use while writing your Plugin, please -provide them as strings in the `defaultLocale` property like so: - -```js -this.defaultLocale = { - strings: { - youCanOnlyUploadFileTypes: 'You can only upload: %{types}', - youCanOnlyUploadX: { - 0: 'You can only upload %{smart_count} file', - 1: 'You can only upload %{smart_count} files', - 2: 'You can only upload %{smart_count} files', - }, - }, -}; -``` - -This allows them to be overridden by Locale Packs, or directly when users pass -`locale: { strings: youCanOnlyUploadFileTypes: 'Something else completely about %{types}'} }`. -For this to work, it’s also required that you call `this.i18nInit()` in the -plugin constructor. - -## Example of a custom plugin - -Below is a full example of a -[small plugin](https://github.com/arturi/uppy-plugin-image-compressor) that -compresses images before uploading them. You can replace `compressorjs` method -with any other work you need to do. This works especially well for async stuff, -like calling an external API. - - - -```js -import { UIPlugin } from '@uppy/core'; -import Translator from '@uppy/utils/lib/Translator'; -import Compressor from 'compressorjs/dist/compressor.esm.js'; - -class UppyImageCompressor extends UIPlugin { - constructor(uppy, opts) { - const defaultOptions = { - quality: 0.6, - }; - super(uppy, { ...defaultOptions, ...opts }); - - this.id = this.opts.id || 'ImageCompressor'; - this.type = 'modifier'; - - this.defaultLocale = { - strings: { - compressingImages: 'Compressing images...', - }, - }; - - // we use those internally in `this.compress`, so they - // should not be overridden - delete this.opts.success; - delete this.opts.error; - - this.i18nInit(); - } - - compress(blob) { - return new Promise( - (resolve, reject) => - new Compressor(blob, { - ...this.opts, - success(result) { - return resolve(result); - }, - error(err) { - return reject(err); - }, - }), - ); - } - - prepareUpload = (fileIDs) => { - const promises = fileIDs.map((fileID) => { - const file = this.uppy.getFile(fileID); - this.uppy.emit('preprocess-progress', file, { - mode: 'indeterminate', - message: this.i18n('compressingImages'), - }); - - if (!file.type.startsWith('image/')) { - return; - } - - return this.compress(file.data) - .then((compressedBlob) => { - this.uppy.log( - `[Image Compressor] Image ${file.id} size before/after compression: ${file.data.size} / ${compressedBlob.size}`, - ); - this.uppy.setFileState(fileID, { data: compressedBlob }); - }) - .catch((err) => { - this.uppy.log( - `[Image Compressor] Failed to compress ${file.id}:`, - 'warning', - ); - this.uppy.log(err, 'warning'); - }); - }); - - const emitPreprocessCompleteForAll = () => { - fileIDs.forEach((fileID) => { - const file = this.uppy.getFile(fileID); - this.uppy.emit('preprocess-complete', file); - }); - }; - - // Why emit `preprocess-complete` for all files at once, instead of - // above when each is processed? - // Because it leads to StatusBar showing a weird “upload 6 files” button, - // while waiting for all the files to complete pre-processing. - return Promise.all(promises).then(emitPreprocessCompleteForAll); - }; - - install() { - this.uppy.addPreProcessor(this.prepareUpload); - } - - uninstall() { - this.uppy.removePreProcessor(this.prepareUpload); - } -} - -export default UppyImageCompressor; -``` diff --git a/docs/guides/building-your-own-ui-with-uppy.md b/docs/guides/building-your-own-ui-with-uppy.md deleted file mode 100644 index fc8389c0f6..0000000000 --- a/docs/guides/building-your-own-ui-with-uppy.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -sidebar_position: 4 ---- - -# Building your own UI with Uppy - -:::note - -This guide is in progress. - -::: diff --git a/docs/guides/choosing-uploader.md b/docs/guides/choosing-uploader.md deleted file mode 100644 index 692265365f..0000000000 --- a/docs/guides/choosing-uploader.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -sidebar_position: 1 ---- - -# Choosing the uploader you need - -Versatile, reliable uploading is at the heart of Uppy. It has many configurable -plugins to suit your needs. In this guide we will explain the different plugins, -their strategies, and when to use them based on use cases. - -## Use cases - -### I want worry-free, plug-and-play uploads with Transloadit services - -Transloadit’s strength is versatility. By doing video, audio, images, documents, -and more, you only need one vendor for [all your file processing -needs][transloadit-services]. The [`@uppy/transloadit`][] plugin directly -uploads to Transloadit so you only have to worry about creating a -[template][transloadit-concepts]. It uses -[Tus](#i-want-reliable-resumable-uploads) under the hood so you don’t have to -sacrifice reliable, resumable uploads for convenience. - -You should use [`@uppy/transloadit`][] if you don’t want to host your own -server, (optionally) need file processing, and store it in the service (such as -S3 or GCS) of your liking. All with minimal effort. - -### I want reliable, resumable uploads - -[Tus][tus] is a new open protocol for resumable uploads built on HTTP. This -means accidentally closing your tab or losing connection let’s you continue, for -instance, your 10GB upload instead of starting all over. - -Tus supports any language, any platform, and any network. It requires a client -and server integration to work. You can checkout the client and server -[implementations][tus-implementations] to find the server in your preferred -language. You can store files on the Tus server itself, but you can also use -service integrations (such as S3) to store files externally. - -If you want reliable, resumable uploads: use [`@uppy/tus`][] to connect to your -Tus server in a few lines of code. - -:::tip - -If you plan to let people upload _a lot_ of files, [`@uppy/tus`][] has -exponential backoff built-in. Meaning if your server (or proxy) returns HTTP 429 -because it’s being overloaded, [`@uppy/tus`][] will find the ideal sweet spot to -keep uploading without overloading. - -::: - -### I want to upload to AWS S3 (or S3-compatible storage) directly - -When you prefer a _client-to-storage_ over a _client-to-server-to-storage_ (such -as [Transloadit](/docs/transloadit) or [Tus](/docs/tus)) setup. This may in some -cases be preferable, for instance, to reduce costs or the complexity of running -a server and load balancer with [Tus](/docs/tus). - -Uppy has two plugins to make this happen [`@uppy/aws-s3`][] and -[`@uppy/aws-s3-multipart`][], but we are planning to merge the two plugins in -the next major. You should use [`@uppy/aws-s3`][] with the new -`shouldUseMultipart` option. - -:::info - -You can also save files in S3 with the [`/s3/store`][s3-robot] robot while still -using the powers of Transloadit services. - -::: - -### I want to send regular HTTP uploads to my own server - -[`@uppy/xhr-upload`][] handles classic HTML multipart form uploads as well as -uploads using the HTTP `PUT` method. - -[s3-robot]: https://transloadit.com/services/file-exporting/s3-store/ -[transloadit-services]: https://transloadit.com/services/ -[transloadit-concepts]: https://transloadit.com/docs/getting-started/concepts/ -[`@uppy/transloadit`]: /docs/transloadit -[`@uppy/tus`]: /docs/tus -[`@uppy/aws-s3-multipart`]: /docs/aws-s3-multipart -[`@uppy/aws-s3`]: /docs/aws-s3-multipart -[`@uppy/xhr-upload`]: /docs/xhr-upload -[tus]: https://tus.io/ -[tus-implementations]: https://tus.io/implementations.html diff --git a/docs/guides/custom-stores.md b/docs/guides/custom-stores.md deleted file mode 100644 index 2370f92621..0000000000 --- a/docs/guides/custom-stores.md +++ /dev/null @@ -1,136 +0,0 @@ -# Custom stores - -If your app uses a state management library such as -[Redux](https://redux.js.org), it can be useful to have Uppy store its state -there instead—that way, you could write custom uploader UI components in the -same way as the other components in the application. - -Uppy comes with two state management solutions (stores): - -- `@uppy/store-default`, a basic object-based store. -- `@uppy/store-redux`, a store that uses a key in a Redux store. - -You can also use a third-party store: - -- [uppy-store-ngrx](https://github.com/rimlin/uppy-store-ngrx/), keeping Uppy - state in a key in an [Ngrx](https://github.com/ngrx/platform) store for use - with Angular. - -## Using stores - -To use a store, pass an instance to the -[`store` option](/docs/uppy#store-defaultstore) in the Uppy constructor: - -```js -import DefaultStore from '@uppy/store-default'; - -const uppy = new Uppy({ - store: new DefaultStore(), -}); -``` - -### `DefaultStore` - -Uppy uses the `DefaultStore` by default! You do not need to do anything to use -it. It does not take any options. - -### `ReduxStore` - -The `ReduxStore` stores Uppy state on a key in an existing Redux store. The -`ReduxStore` dispatches `uppy/STATE_UPDATE` actions to update state. When the -state in Redux changes, it notifies Uppy. This way, you get most of the benefits -of Redux, including support for the Redux Devtools and time traveling! - -Checkout our -[Redux example](https://github.com/transloadit/uppy/tree/main/examples/redux) -for a working demo. - -#### `opts.store` - -Pass a Redux store instance, from `Redux.createStore`. This instance should have -the Uppy reducer mounted somewhere already. - -#### `opts.id` - -By default, the `ReduxStore` assumes Uppy state is stored on a `state.uppy[id]` -key. `id` is randomly generated by the store constructor, but can be specified -by passing an `id` option if it should be predictable. - -```js -ReduxStore({ - store, - id: 'avatarUpload', -}); -``` - -#### `opts.selector` - -If you’d rather not store the Uppy state under the `state.uppy` key at all, use -the `selector` option to the `ReduxStore` constructor to tell it where to find -state instead: - -```js -const uppy = new Uppy({ - store: ReduxStore({ - store, - id: 'avatarUpload', - selector: (state) => state.pages.profile.uppy.avatarUpload, - }), -}); -``` - -Note that when specifying a custom selector, you **must** also specify a custom -store ID. The store `id` tells the reducer in which property it should put -Uppy’s state. The selector must then take the state from that property. In the -example, we set the ID to `avatarUpload` and take the state from the -`[reducer mount path].avatarUpload`. - -If your app uses [`reselect`](https://npmjs.com/package/reselect), its selectors -work well with this! - -## Implementing Stores - -An Uppy store is an object with three methods. - -- `getState()` - Return the current state object. -- `setState(patch)` - Merge the object `patch` into the current state. -- `subscribe(listener)` - Call `listener` whenever the state changes. `listener` - is a function that should receive three parameters: - `(prevState, nextState, patch)` - - The `subscribe()` method should return a function that “unsubscribes” - (removes) the `listener`. - -The default store implementation, for example, looks a bit like this: - -```js -function createDefaultStore() { - let state = {}; - const listeners = new Set(); - - return { - getState: () => state, - setState: (patch) => { - const prevState = state; - const nextState = { ...prevState, ...patch }; - - state = nextState; - - listeners.forEach((listener) => { - listener(prevState, nextState, patch); - }); - }, - subscribe: (listener) => { - listeners.add(listener); - return () => listeners.remove(listener); - }, - }; -} -``` - -A pattern like this, where users can pass options via a function call if -necessary, is recommended. - -See the -[@uppy/store-default](https://github.com/transloadit/uppy/tree/main/packages/%40uppy/store-default) -package for more inspiration. diff --git a/docs/guides/migration-guides.md b/docs/guides/migration-guides.md deleted file mode 100644 index 596aa60b43..0000000000 --- a/docs/guides/migration-guides.md +++ /dev/null @@ -1,868 +0,0 @@ -# Migration guides - -These cover all the major Uppy versions and how to migrate to them. - -## Migrate from Companion 4.x to 5.x - -- End-of-Life versions of Node.js are no longer supported (use latest 18.x LTS, - 20.x LTS, or 22.x current). -- Setting the `corsOrigin` (`COMPANION_CLIENT_ORIGINS`) option is now required. - You should define the list of origins you expect your app to be served from, - otherwise it can be impersonated from a different origin you don’t control. - Set it to `true` if you don’t care about impersonating. If you’re using - Companion as an express middleware, do **not** use the `cors` module in your - project, because Companion already includes it. Use the `corsOrigins` - Companion option to customise CORS behavior. -- `COMPANION_REDIS_EXPRESS_SESSION_PREFIX` now defaults to `companion-session:` - (before `sess:`). To revert keep backwards compatibility, set the environment - variable `COMPANION_REDIS_EXPRESS_SESSION_PREFIX=sess:`. -- The URL endpoint (used by the `Url`/`Link` plugin) is now turned off by - default and must be explicitly enabled with - `COMPANION_ENABLE_URL_ENDPOINT=true` or `enableUrlEndpoint: true`. -- The option `streamingUpload` / `COMPANION_STREAMING_UPLOAD` now defaults to - `true`. -- The option `getKey(req, filename, metadata)` has changed signature to - `getKey({ filename, metadata, req })`. -- The option `bucket(req, metadata)` has changed signature to - `bucketOrFn({ req, metadata, filename })`. -- Custom provider breaking changes. If you have not implemented a custom - provider, you should not be affected. - - The static `getExtraConfig` property has been renamed to - `getExtraGrantConfig`. - - The static `authProvider` property has been renamed to `oauthProvider`. -- Endpoint `GET /s3/params` now returns `{ method: "POST" }` instead of - `{ method: "post" }`. This will not affect most people. -- `access-control-allow-headers` is no longer included in - `Access-Control-Expose-Headers`, and `uppy-versions` is no longer an allowed - header. We are not aware of any issues this might cause. -- Internal refactoring (probably won’t affect you) - - `getProtectedGot` parameter `blockLocalIPs` changed to `allowLocalIPs` - (inverted boolean). - - `getURLMeta` 2nd (boolean) argument inverted. - - `getProtectedHttpAgent` parameter `blockLocalIPs` changed to `allowLocalIPs` - (inverted boolean). - - `downloadURL` 2nd (boolean) argument inverted. - - `StreamHttpJsonError` renamed to `HttpError`. -- Removed the `oauthOrigin` option, as well as the (undocumented) option - `clients`. Use `corsOrigin` instead. - -### `@uppy/companion-client` - -:::info - -Unless you built a custom provider, you don’t use `@uppy/companion-client` -directly but through provider plugins such as `@uppy/google-drive`. In which -case you don’t have to do anything. - -::: - -- `supportsRefreshToken` now defaults to `false` instead of `true`. If you have - implemented a custom provider, this might affect you. -- `Socket` class is no longer in use and has been removed. Unless you used this - class you don’t need to do anything. -- Remove deprecated options `serverUrl` and `serverPattern` (they were merely - defined in Typescript, not in use). -- `RequestClient` methods `get`, `post`, `delete` no longer accepts a boolean as - the third argument. Instead, pass `{ skipPostResponse: true | false }`. This - won’t affect you unless you’ve been using `RequestClient`. -- When pausing uploads, the WebSocket towards companion will no longer be - closed. This allows paused uploads to be cancelled, but once a file has been - paused it will still occupy its place in the concurrency queue. - -## Migrate from Uppy 3.x to 4.x - -### TypeScript rewrite - -Almost all plugins have been completely rewritten in TypeScript! This means you -may run into type error all over the place, but the types now accurately show -Uppy’s state and files. - -There are too many small changes to cover, so you have to upgrade and see where -TypeScript complains. - -One important thing to note are the new generics on `@uppy/core`. - - - - - -```ts -import Uppy from '@uppy/core'; -// xhr-upload is for uploading to your own backend. -import XHRUpload from '@uppy/xhr-upload'; - -// Your own metadata on files -type Meta = { myCustomMetadata: string }; -// The response from your server -type Body = { someThingMyBackendReturns: string }; - -const uppy = new Uppy().use(XHRUpload, { - endpoint: '/upload', -}); - -const id = uppy.addFile({ - name: 'example.jpg', - data: new Blob(), - meta: { myCustomMetadata: 'foo' }, -}); - -// This is now typed -const { myCustomMetadata } = uppy.getFile(id).meta; - -await uppy.upload(); - -// This is strictly typed too -const { someThingMyBackendReturns } = uppy.getFile(id).response.body!; -``` - -### `@uppy/aws-s3` and `@uppy/aws-s3-multipart` - -- `@uppy/aws-s3` and `@uppy/aws-s3-multipart` have been combined into a single - plugin. You should now only use `@uppy/aws-s3` with the new option, - [`shouldUseMultipart()`](/docs/aws-s3-multipart/#shouldusemultipartfile), to - allow you to switch between regular and multipart uploads. You can read more - about this in the - [plugin docs](https://uppy.io/docs/aws-s3-multipart/#when-should-i-use-it). -- Remove deprecated `prepareUploadParts` option. -- Companion’s options (`companionUrl`, `companionHeaders`, and - `companionCookieRules`) are renamed to more generic names (`endpoint`, - `headers`, and `cookieRules`). - - Using Companion with the `@uppy/aws-s3` plugin only makes sense if you already - need Companion for remote providers (such as Google Drive). When using your - own backend, you can let Uppy do all the heavy lifting on the client which it - would normally do for Companion, so you don’t have to implement that yourself. - - As long as you return the JSON for the expected endpoints (see our - [server example](https://github.com/transloadit/uppy/blob/main/examples/aws-nodejs/index.js)), - you only need to set `endpoint`. - - If you are using Companion, rename the options. If you have a lot of - client-side complexity (`createMultipartUpload`, `signPart`, etc), consider - letting Uppy do this for you. - -### `@uppy/core` - -- The `close()` method has been renamed to `destroy()` to more accurately - reflect you can not recover from it without creating a new `Uppy` instance. -- The `clearUploadedFiles()` method has been renamed to `clear()` as a - convenience method to clear all the state. This can be useful when a user - navigates away and you want to clear the state on success. -- `bytesUploaded`, in `file.progress.bytesUploaded`, is now always a `boolean`, - instead of a `boolean` or `number`. - -### `@uppy/xhr-upload` - -Before the plugin had the options `getResponseData`, `getResponseError`, -`validateStatus` and `responseUrlFieldName`. These were inflexible and too -specific. Now we have hooks similar to `@uppy/tus`: - -- `onBeforeRequest` to manipulate the request before it is sent. -- `shouldRetry` to determine if a request should be retried. By default 3 - retries with exponential backoff. After three attempts it will throw an error, - regardless of whether you returned `true`. -- `onAfterResponse` called after a successful response but before Uppy resolves - the upload. - -Checkout the [docs](/docs/xhr-upload/) for more info. - -### `@uppy/transloadit` - -The options `signature`, `params`, `fields`, and `getAssemblyOptions` have been -removed in favor of [`assemblyOptions`](/docs/transloadit/#assemblyoptions), -which can be an object or an (async) function returning an object. - -When using `assemblyOptions()` as a function, it is now called only once for all -files, instead of per file. Before `@uppy/transloadit` was trying to be too -smart, creating multiple assemblies in which each assembly has files with -identical `fields`. This was done so you can use `fields` dynamically in your -template per file, instead of per assembly. - -Now we sent all metadata of a file inside the tus upload (which -`@uppy/transloadit` uses under the hood) and make it accessible in your -Transloadit template as `file_user_meta`. You should use `fields` for global -values in your template and `file_user_meta` for per file values. - -Another benefit of running `assemblyOptions()` only once, is that when -generating a -[secret](https://transloadit.com/docs/topics/signature-authentication/) on your -server (which you should), a network request is made only once for all files, -instead of per file. - -### CDN - -- We no longer build and serve the legacy build, made for IE11, on our CDN. - -### Miscellaneous - -- All uploaders plugins now consistently use - [`allowedMetaFields`](/docs/xhr-upload/#allowedmetafields). Before there were - inconsistencies between plugins. -- All plugin `titles` (what you see in the Dashboard when you open a plugin) are - now set from the `locale` option. See the - [docs](/docs/locales/#overriding-locale-strings-for-a-specific-plugin) on how - to overide a string. - -### `@uppy/angular` - -- Upgrade to Angular 18.x (17.x is still supported too) and to TS 5.4 - -### `@uppy/react` - -- Remove deprecated `useUppy` -- You can no longer set `inline` on the `Dashboard` component, use `Dashboard` - or `DashboardModal` components respectively. - -### `@uppy/svelte` - -- Make Svelte 5 the peer dependency -- Remove UMD output - -### `@uppy/vue` - -- Migrate to Composition API with TypeScript & drop Vue 2 support -- Drop Vue 2 support - -## Migrate from Robodog to Uppy plugins - -Uppy is flexible and extensible through plugins. But the integration code could -sometimes be daunting. This is what brought Robodog to life. An alternative with -the same features, but with a more ergonomic and minimal API. - -But, it didn’t come with its own set of new problems: - -- It tries to do the exact same, but it looks like a different product. -- It’s confusing for users whether they want to use Robodog or Uppy directly. -- Robodog is more ergonomic because it’s limited. When you hit such a limit, you - need to refactor everything to Uppy with plugins. - -This has now led us to deprecating Robodog and embrace Uppy for its strong -suits; modularity and flexibility. At the same time, we also introduced -something to take away some repetitive integration code: -[`@uppy/remote-sources`](/docs/remote-sources). - -To mimic the Robodog implementation with all its features, you can use the code -snippet below. But chances are Robodog did more than you need so feel free to -remove things or go through the [list of plugins](/docs/companion/) and install -and use the ones you need. - -You can also checkout how we migrated the Robodog example ourselves in this -[commit](https://github.com/transloadit/uppy/commit/089aaed615c77bafaf905e291b6b4e82aaeb2f6f). - -```js -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import RemoteSources from '@uppy/remote-sources'; -import Webcam from '@uppy/webcam'; -import ScreenCapture from '@uppy/screen-capture'; -import GoldenRetriever from '@uppy/golden-retriever'; -import ImageEditor from '@uppy/image-editor'; -import Audio from '@uppy/audio'; -import Transloadit, { - COMPANION_URL, - COMPANION_ALLOWED_HOSTS, -} from '@uppy/transloadit'; - -import '@uppy/core/dist/style.css'; -import '@uppy/dashboard/dist/style.css'; -import '@uppy/audio/dist/style.css'; -import '@uppy/screen-capture/dist/style.css'; -import '@uppy/image-editor/dist/style.css'; - -new Uppy() - .use(Dashboard, { - inline: true, - target: '#app', - showProgressDetails: true, - proudlyDisplayPoweredByUppy: true, - }) - .use(RemoteSources, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - }) - .use(Webcam, { - showVideoSourceDropdown: true, - showRecordingLength: true, - }) - .use(Audio, { - showRecordingLength: true, - }) - .use(ScreenCapture) - .use(ImageEditor) - .use(Transloadit, { - service: 'https://api2.transloadit.com', - async getAssemblyOptions(file) { - // This is where you configure your auth key, auth secret, and template ID - // /uppy/docs/transloadit/#getAssemblyOptions-file - // - // It is important to set the secret in production: - // https://transloadit.com/docs/topics/signature-authentication/ - const response = await fetch('/some-endpoint'); - return response.json(); - }, - }); -``` - -## Migrate from Uppy 2.x to 3.x - -### Uppy is pure ESM - -Following the footsteps of many packages, we now only ship Uppy core and its -plugins as -[ECMAScript Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) -(ESM). On Uppy 2.x, we were shipping CommonJS. - -If are already using ESM yourself, or are using the CDN builds, nothing changes -for you! - -If you are using CommonJS, you might need to add some tooling for everything to -work, or you might want to refactor your codebase to ESM – refer to the -[Pure ESM package](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c) -gist for added information and help on how to do that. - -### Robodog is deprecated - -See the [Robodog migration guide](#Migrate-from-Robodog-to-Uppy-plugins). - -### `@uppy/core` - -#### Remove `AggregateError` polyfill. - -It’s supported by most modern browsers and -[can be polyfilled by the user](https://github.com/transloadit/uppy/pull/3532#discussion_r818602636) -if needed. - -To migrate: install a `AggregateError` polyfill or use `core-js`. - -#### Remove `reset()` method. - -It’s a duplicate of `cancelAll`, but with a less intention revealing name. - -To migrate: use `cancelAll`. - -#### Remove backwards compatible exports (static properties on `Uppy`)\` - -`Uppy`, `UIPlugin`, `BasePlugin`, and `debugLogger` used to also be accessible -on the `Uppy` export. This has now been removed due to the transition to ESM. - -To migrate: import the `Uppy` class by default and/or use named exports for -everything else. - -#### `uppy.validateRestrictions()` now returns a `RestrictionError` - -This method used to return `{ result: false, reason: err.message }`, but that -felt strange as it tries to mimic an error. Instead it now return a -`RestrictionError`, which is extended `Error` class. - -To migrate: check the return value, if it’s defined you have an error, otherwise -all went well. Note that the error is `return`’ed, it’s not `throw`’n, so you -don’t have to `catch` it. - -### `@uppy/transloadit` - -Remove export of `ALLOWED_COMPANION_PATTERN`, `COMPANION`, and -`COMPANION_PATTERN` in favor of `COMPANION_URL` and `COMPANION_ALLOWED_HOSTS`. -This is to have more intention revealing names, `COMPANION` sounds like the -Companion instance, `COMPANION_URL` makes it more clear that it’s a URL. - -These are properties can now be imported and used for remote sources plugins -when using Transloadit: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; - -// ... -uppy.use(Dropbox, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -### `@uppy/aws-s3-multipart` - -#### Make `headers` inside the return value of [`prepareUploadParts`](/docs/aws-s3-multipart/#prepareUploadParts-file-partData) part-indexed too. - -This is to allow custom headers to be set per part. See this -[issue](https://github.com/transloadit/uppy/issues/3881) for details. - -To migrate: make headers part indexed like `presignedUrls`: -`{ "headers": { "1": { "Content-MD5": "foo" } }}`. - -#### Remove `client` getter and setter. - -It’s internal usage only. - -To migrate: use exposed options only. - -### `@uppy/tus/`, `@uppy/aws-s3`, `@uppy/xhr-upload` - -Rename `metaFields` option to `allowedMetaFields`. Counter intuitively, -`metaFields` is for _filtering_ which `metaFields` to send along with the -request, not for adding extra meta fields to a request. As a lot of people were -confused by this, and the name overlaps with the -[`metaFields` option from Dashboard](/docs/dashboard/#metaFields), we renamed -it. - -To migrate: use `allowedMetaFields`. - -### `@uppy/react` - -#### Uppy dependencies have become peer dependencies - -`@uppy/dashboard`, `@uppy/drag-drop`, `@uppy/file-input`, `@uppy/progress-bar`, -and `@uppy/status-bar` are now peer dependencies. This means you don’t install -all these packages if you only need one. - -To migrate: install only the packages you need. If you use the Dashboard -component, you need `@uppy/dashboard`, and so onwards. - -#### Don’t expose `validProps` on the exported components. - -It’s internal usage only. - -To migrate: use exposed options only. - -### `@uppy/svelte` - -`@uppy/dashboard`, `@uppy/drag-drop`, `@uppy/progress-bar`, and -`@uppy/status-bar` are now peer dependencies. This means you don’t install all -these packages if you only need one. - -To migrate: install only the packages you need. If you use the Dashboard -component, you need `@uppy/dashboard`, and so onwards. - -### `@uppy/vue` - -`@uppy/dashboard`, `@uppy/drag-drop`, `@uppy/file-input`, `@uppy/progress-bar`, -and `@uppy/status-bar` are now peer dependencies. This means you don’t install -all these packages if you only need one. - -To migrate: install only the packages you need. If you use the Dashboard -component, you need `@uppy/dashboard`, and so onwards. - -### `@uppy/store-redux` - -Remove backwards compatible exports (static properties on `ReduxStore`). -Exports, such as `reducer`, used to also be accessible on the `ReduxStore` -export. This has now been removed due to the transition to ESM. - -To migrate: use named imports. - -### `@uppy/thumbnail-generator` - -Remove `rotateImage`, `protect`, and `canvasToBlob` from the plugin prototype. -They are internal usage only. - -To migrate: use exposed options only. - -### Known issues - -- [`ERESOLVE could not resolve` on npm install](https://github.com/transloadit/uppy/issues/4057). -- [@uppy/svelte reports a broken dependency with the Vite bundler](https://github.com/transloadit/uppy/issues/4069). - -## Migrate from Companion 3.x to 4.x - -### Minimum required Node.js version is v14.20.0 - -Aligning with the Node.js -[Long Term Support (LTS) schedule](https://nodejs.org/en/about/releases/) and to -use modern syntax features. - -### `companion.app()` returns `{ app, emitter }` instead of `app` - -Companion 3.x provides the emitter as `companionEmitter` on `app`. As of 4.x, an -object is returned with an `app` property (express middleware) and an `emitter` -property (event emitter). This provides more flexibility in the future and -follows best practices. - -### Removed `searchProviders` wrapper object inside `providerOptions` - -To use [`@uppy/unsplash`](/docs/unsplash), you had to configure Unsplash in -Companion inside `providerOptions.searchProviders`. This is redundant, Unsplash -is a provider as well so we removed the wrapper object. - -### Moved the `s3` options out of `providerOptions` - -To use AWS S3 for storage, you configured the `s3` object inside -`providerOptions`. But as S3 is not a provider but a destination. To avoid -confusion we moved the `s3` settings to the root settings object. - -### Removed compatibility for legacy Custom Provider implementations - -[Custom Provider](/docs/companion/#Adding-custom-providers) implementations must -use the Promise API. The callback API is no longer supported. - -### Default to no ACL for AWS S3 - -Default to no -[ACL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html) -for S3 uploads. Before the default was `public-read` but AWS now discourages -ACLs. The environment variable `COMPANION_AWS_DISABLE_ACL` is also removed, -instead Companion only uses `COMPANION_AWS_ACL`. - -### `protocol` sent from Uppy in any `get` request is now required (before it would default to Multipart). - -If you use any official Uppy plugins, then no migration is needed. For custom -plugins that talk to Companion, make to send along the `protocol` header with a -value of `multipart`, `s3Multipart`, or `tus`. - -### `emitSuccess` and `emitError` are now private methods on the `Uploader` class. - -It’s unlikely you’re using this, but it’s technically a breaking change. In -general, don’t depend on implicitly internal methods, use exposed APIs instead. - -### Removed `chunkSize` backwards compatibility for AWS S3 Multipart - -`chunkSize` option will now be used as `partSize` in AWS multipart. Before only -valid values would be respected. Invalid values would be ignored. Now any value -will be passed on to the AWS SDK, possibly throwing an error on invalid values. - -### Removed backwards compatibility for `/metrics` endpoint - -The `metrics` option is a boolean flag to tell Companion whether to provide an -endpoint `/metrics` with Prometheus metrics. Metrics will now always be served -under `options.server.path`. Before v4.x, it would always be served under the -root. - -For example: if `{ options: { metrics: true, server: { path: '/companion' }}}`, -metrics will now be served under `/companion/metrics`. In v3.x, the metrics -would be served under `/metrics`. - -## Migrate from Uppy 1.x to 2.x - -### New bundle requires manual polyfilling - -With 2.0, following in the footsteps of Microsoft, we are dropping support for -IE11. As a result, we are able to remove all built-in polyfills, and the new -bundle size is **25% smaller**! If you want your app to still support older -browsers (such as IE11), you may need to add the following polyfills to your -bundle: - -- [abortcontroller-polyfill](https://github.com/mo/abortcontroller-polyfill) -- [core-js](https://github.com/zloirock/core-js) -- [md-gum-polyfill](https://github.com/mozdevs/mediaDevices-getUserMedia-polyfill) -- [resize-observer-polyfill](https://github.com/que-etc/resize-observer-polyfill) -- [whatwg-fetch](https://github.com/github/fetch) - -If you’re using a bundler, you need import these before Uppy: - -```js -import 'core-js'; -import 'whatwg-fetch'; -import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'; -// Order matters here: AbortController needs fetch, which needs Promise (provided by core-js). - -import 'md-gum-polyfill'; -import ResizeObserver from 'resize-observer-polyfill'; - -window.ResizeObserver ??= ResizeObserver; - -export { default } from '@uppy/core'; -export * from '@uppy/core'; -``` - -If you’re using Uppy from a CDN, we now provide two bundles: one for up-to-date -browsers that do not include polyfills and use modern syntax, and one for legacy -browsers. When migrating, be mindful about the types of browsers you want to -support: - -```html - - - - - - -``` - -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. - -### Use `BasePlugin` or `UIPlugin` instead of `Plugin` - -[`@uppy/core`][core] used to provide a `Plugin` class for creating plugins. This -was used for any official plugin, but also for users who want to create their -own custom plugin. But, `Plugin` always came bundled with Preact, even if the -plugin itself didn’t add any UI elements. - -`Plugin` has been replaced with `BasePlugin` and `UIPlugin`. `BasePlugin` is the -minimum you need to create a plugin and `UIPlugin` adds Preact for rendering -user interfaces. - -You can import them from [`@uppy/core`][core]: - -```js -import { BasePlugin, UIPlugin } from '@uppy/core'; -``` - -**Note:** some bundlers will include `UIPlugin` (and thus Preact) if you import -from `@uppy/core`. To make sure this does not happen, you can import `Uppy` and -`BasePlugin` directly: - -```js -import Uppy from '@uppy/core/lib/Uppy.js'; -import BasePlugin from '@uppy/core/lib/BasePlugin.js'; -``` - -### Use the latest Preact for your Uppy plugins - -Official plugins have already been upgraded. If you are using any custom -plugins, upgrade Preact to the latest version. At the time of writing this is -`10.5.13`. - -### Set plugin titles from locales - -Titles for plugins used to be set with the `title` property in the plugin -options, but all other strings are set in `locale`. This has now been aligned. -You should set your plugin title from the `locale` property. - -Before - -```js -import Webcam from '@uppy/webcam'; - -uppy.use(Webcam, { - title: 'Some title', -}); -``` - -After - -```js -import Webcam from '@uppy/webcam'; - -uppy.use(Webcam, { - locale: { - strings: { - title: 'Some title', - }, - }, -}); -``` - -### Initialize Uppy with the `new` keyword - -The default export `Uppy` is no longer callable as a function. This means you -construct the `Uppy` instance using the `new` keyword. - -```js -import Uppy from '@uppy/core'; - -const uppy = new Uppy(); // correct. - -const otherUppy = Uppy(); // incorrect, will throw. -``` - -### Rename `allowMultipleUploads` to `allowMultipleUploadBatches` - -[`allowMultipleUploadBatches`](/docs/uppy/#allowmultipleuploadbatches) means -allowing several calls to [`.upload()`](/docs/uppy/#upload), in other words, a -user can add more files after already having uploaded some. - - - -We have renamed this to be more intention revealing that this is about uploads, -and not whether a user can choose multiple files for one upload. - -```js -const uppy = new Uppy({ - allowMultipleUploadBatches: true, -}); -``` - -### New default limits for [`@uppy/xhr-upload`][xhr] and [`@uppy/tus`][tus] - -The default limit has been changed from `0` to `5`. Setting this to `0` means no -limit on concurrent uploads. - -You can change the limit on the Tus and XHR plugin options. - -```js -uppy.use(Tus, { - // ... - limit: 10, -}); -``` - -```js -uppy.use(XHRUpload, { - // ... - limit: 10, -}); -``` - -### TypeScript changes - -Uppy used to have loose types by default and strict types as an opt-in. The -default export was a function that returned the `Uppy` class, and the types came -bundled with the default export (`Uppy.SomeType`). - -```ts -import Uppy from '@uppy/core'; -import Tus from '@uppy/tus'; - -const uppy = Uppy(); - -uppy.use(Tus, { - invalidOption: null, // this will make the compilation fail! -}); -``` - -Uppy is now strictly typed by default and loose types have been removed. - -```ts -// ... - -const uppy = new Uppy(); - -uppy.use(Tus, { - invalidOption: null, // this will make the compilation fail! -}); -``` - -Uppy types are now individual exports and should be imported separately. - - - -```ts -import type { PluginOptions, UIPlugin, PluginTarget } from '@uppy/core'; -``` - -#### Event types - -[`@uppy/core`][core] provides an [`.on`](/docs/uppy/#uppy-on-39-event-39-action) -method to listen to [events](/docs/uppy/#Events). The types for these events -were loose and allowed for invalid events to be passed, such as -`uppy.on('upload-errrOOOoooOOOOOrrrr')`. - - - -```ts -// Before: - -type Meta = { myCustomMetadata: string }; - -// Invalid event -uppy.on('upload-errrOOOoooOOOOOrrrr', () => { - // ... -}); - -// After: - -// Normal event signature -uppy.on('complete', (result) => { - const successResults = result.successful; -}); - -// Custom signature -type Meta = { myCustomMetadata: string }; - -// Notice how the custom type has now become the second argument -uppy.on<'complete', Meta>('complete', (result) => { - // The passed type is now merged into the `meta` types. - const meta = result.successful[0].meta.myCustomMetadata; -}); -``` - -Plugins that add their own events can merge with existing ones in `@uppy/core` -with `declare module '@uppy/core' { ... }`. This is a TypeScript pattern called -[module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation). -For instance, when using [`@uppy/dashboard`][dashboard]: - - - -```ts -uppy.on('dashboard:file-edit-start', (file) => { - const fileName = file.name; -}); -``` - -### Changes to pre-signing URLs for [`@uppy/aws-s3-multipart`][aws-s3-multipart] - -See the Uppy 2.0.0 announcement post about the batch -[pre-signing URLs change](/blog/2021/08/2.0/#Batch-pre-signing-URLs-for-AWS-S3-Multipart). - -`prepareUploadPart` has been renamed to -[`prepareUploadParts`](/docs/aws-s3-multipart/#prepareUploadParts-file-partData) -(plural). See the documentation link on how to use this function. - -### Removed the `.run` method from [`@uppy/core`][core] - -The `.run` method on the `Uppy` instance has been removed. This method was -already obsolete and only logged a warning. As of this major version, it no -longer exists. - -### Removed `resume` and `removeFingerprintOnSuccess` options from [`@uppy/tus`][tus] - -Tus will now by default try to resume uploads if the upload has been started in -the past. - -This also means tus will store some data in localStorage for each upload, which -will automatically be removed on success. Making `removeFingerprintOnSuccess` -obsolete too. - -### That’s it! - -Uppy 1.0 will continue to receive bug fixes for three more months (until -), security fixes for one more -year (until ), but no more -new features after today. Exceptions are unlikely, but _can_ be made – to -accommodate those with commercial support contracts, for example. - -We hope you’ll waste no time in taking Uppy 2.0 out for a walk. When you do, -please let us know what you thought of it on -[Reddit](https://www.reddit.com/r/javascript/comments/penbr7/uppy_file_uploader_20_smaller_and_faster_modular/), -[HN](https://news.ycombinator.com/item?id=28359287), ProductHunt, or -[Twitter](https://twitter.com/uppy_io/status/1432399270846603264). We’re howling -at the moon to hear from you! - -## Migrate from Companion 1.x to 2.x - -### Prerequisite - -Since v2, you now need to be running `node.js >= v10.20.1` to use Companion. - -### ProviderOptions - -In v2 the `google` and `microsoft` [providerOptions](/docs/companion/#Options) -have been changed to `drive` and `onedrive` respectively. - -### OAuth Redirect URIs - -On your Providers’ respective developer platforms, the OAuth redirect URIs that -you should supply has now changed from: - -`http(s)://$COMPANION_HOST_NAME/connect/$AUTH_PROVIDER/callback` in v1 - -to: - -`http(s)://$COMPANION_HOST_NAME/$PROVIDER_NAME/redirect` in v2 - -#### New Redirect URIs - -
- -| Provider | New Redirect URI | -| ------------- | ---------------------------------------------------- | -| Dropbox | `https://$COMPANION_HOST_NAME/dropbox/redirect` | -| Google Drive | `https://$COMPANION_HOST_NAME/drive/redirect` | -| Google Photos | `https://$COMPANION_HOST_NAME/googlephotos/redirect` | -| OneDrive | `https://$COMPANION_HOST_NAME/onedrive/redirect` | -| Box | `https://$YOUR_COMPANION_HOST_NAME/box/redirect` | -| Facebook | `https://$COMPANION_HOST_NAME/facebook/redirect` | -| Instagram | `https://$COMPANION_HOST_NAME/instagram/redirect` | - -
- - - -[core]: /docs/uppy/ -[xhr]: /docs/xhr-upload/ -[dashboard]: /docs/dashboard/ -[aws-s3-multipart]: /docs/aws-s3-multipart/ -[tus]: /docs/tus/ diff --git a/docs/locales.mdx b/docs/locales.mdx deleted file mode 100644 index b3b7c6c21f..0000000000 --- a/docs/locales.mdx +++ /dev/null @@ -1,1562 +0,0 @@ ---- -sidebar_position: 10 ---- - -# Internationalisation - -Uppy speaks many languages, English being the default. You can use a locale pack -to translate Uppy into your language of choice. - -:::tip - -Checkout -[`@uppy/locales`](https://github.com/transloadit/uppy/tree/main/packages/%40uppy/locales) -on GitHub to see the list of supported languages. - -::: - -## Using a locale pack from npm - -This is the recommended way. Install `@uppy/locales` package from npm, then -choose the locale you’d like to use: `@uppy/locales/lib/LANGUAGE_CODE`. - -```bash -npm i @uppy/core @uppy/locales -``` - -```js -import Uppy from '@uppy/core'; -import German from '@uppy/locales/lib/de_DE'; -// see below for the full list of locales -const uppy = new Uppy({ - debug: true, - locale: German, -}); -``` - -## Using a locale pack from CDN - -Add a ` - - - -``` - -## Overriding locale strings for a specific plugin - -Many plugins come with their own locale strings, and the packs we provide -consist of most of those strings. You can, however, override a locale string for -a specific plugin, regardless of whether you are using locale pack or not. See -the plugin documentation for the list of locale strings it uses. - -```js -import Uppy from '@uppy/core'; -import DragDrop from '@uppy/drag-drop'; -import Russian from '@uppy/locales/lib/ru_RU'; - -const uppy = new Uppy({ - debug: true, - autoProceed: true, - locale: Russian, -}); -uppy.use(DragDrop, { - target: '.UppyDragDrop', - // We are using the ru_RU locale pack (set above in Uppy options), - // but you can also override specific strings like so: - locale: { - strings: { - browse: 'выберите ;-)', - }, - }, -}); -``` - -## List of locales - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
38 LocalesNPMCDNSource on GitHub
- Arabic Saudi Arabia - - - - @uppy/locales - - /lib/ar_SA - - - - ar_SA.min.js - - - ✏️{' '} - - ar_SA.ts - -
- Bulgarian Bulgaria - - - - @uppy/locales - - /lib/bg_BG - - - - bg_BG.min.js - - - ✏️{' '} - - bg_BG.ts - -
- Chinese China - - - - @uppy/locales - - /lib/zh_CN - - - - zh_CN.min.js - - - ✏️{' '} - - zh_CN.ts - -
- Chinese Taiwan - - - - @uppy/locales - - /lib/zh_TW - - - - zh_TW.min.js - - - ✏️{' '} - - zh_TW.ts - -
- Croatian Croatia - - - - @uppy/locales - - /lib/hr_HR - - - - hr_HR.min.js - - - ✏️{' '} - - hr_HR.ts - -
- Czech Czechia - - - - @uppy/locales - - /lib/cs_CZ - - - - cs_CZ.min.js - - - ✏️{' '} - - cs_CZ.ts - -
- Danish Denmark - - - - @uppy/locales - - /lib/da_DK - - - - da_DK.min.js - - - ✏️{' '} - - da_DK.ts - -
- Dutch Netherlands - - - - @uppy/locales - - /lib/nl_NL - - - - nl_NL.min.js - - - ✏️{' '} - - nl_NL.ts - -
- English United States - - - - @uppy/locales - - /lib/en_US - - - - en_US.min.js - - - ✏️{' '} - - en_US.ts - -
- Finnish Finland - - - - @uppy/locales - - /lib/fi_FI - - - - fi_FI.min.js - - - ✏️{' '} - - fi_FI.ts - -
- French France - - - - @uppy/locales - - /lib/fr_FR - - - - fr_FR.min.js - - - ✏️{' '} - - fr_FR.ts - -
- Galician Spain - - - - @uppy/locales - - /lib/gl_ES - - - - gl_ES.min.js - - - ✏️{' '} - - gl_ES.ts - -
- German Germany - - - - @uppy/locales - - /lib/de_DE - - - - de_DE.min.js - - - ✏️{' '} - - de_DE.ts - -
- Greek Greece - - - - @uppy/locales - - /lib/el_GR - - - - el_GR.min.js - - - ✏️{' '} - - el_GR.ts - -
- Hebrew Israel - - - - @uppy/locales - - /lib/he_IL - - - - he_IL.min.js - - - ✏️{' '} - - he_IL.ts - -
- Hindi India - - - - @uppy/locales - - /lib/hi_IN - - - - hi_IN.min.js - - - ✏️{' '} - - hi_IN.ts - -
- Hungarian Hungary - - - - @uppy/locales - - /lib/hu_HU - - - - hu_HU.min.js - - - ✏️{' '} - - hu_HU.ts - -
- Icelandic Iceland - - - - @uppy/locales - - /lib/is_IS - - - - is_IS.min.js - - - ✏️{' '} - - is_IS.ts - -
- Indonesian Indonesia - - - - @uppy/locales - - /lib/id_ID - - - - id_ID.min.js - - - ✏️{' '} - - id_ID.ts - -
- Italian Italy - - - - @uppy/locales - - /lib/it_IT - - - - it_IT.min.js - - - ✏️{' '} - - it_IT.ts - -
- Japanese Japan - - - - @uppy/locales - - /lib/ja_JP - - - - ja_JP.min.js - - - ✏️{' '} - - ja_JP.ts - -
- Korean South Korea - - - - @uppy/locales - - /lib/ko_KR - - - - ko_KR.min.js - - - ✏️{' '} - - ko_KR.ts - -
- Norwegian Bokmål Norway - - - - @uppy/locales - - /lib/nb_NO - - - - nb_NO.min.js - - - ✏️{' '} - - nb_NO.ts - -
- Persian Iran - - - - @uppy/locales - - /lib/fa_IR - - - - fa_IR.min.js - - - ✏️{' '} - - fa_IR.ts - -
- Polish Poland - - - - @uppy/locales - - /lib/pl_PL - - - - pl_PL.min.js - - - ✏️{' '} - - pl_PL.ts - -
- Portuguese Brazil - - - - @uppy/locales - - /lib/pt_BR - - - - pt_BR.min.js - - - ✏️{' '} - - pt_BR.ts - -
- Portuguese Portugal - - - - @uppy/locales - - /lib/pt_PT - - - - pt_PT.min.js - - - ✏️{' '} - - pt_PT.ts - -
- Romanian Romania - - - - @uppy/locales - - /lib/ro_RO - - - - ro_RO.min.js - - - ✏️{' '} - - ro_RO.ts - -
- Russian Russia - - - - @uppy/locales - - /lib/ru_RU - - - - ru_RU.min.js - - - ✏️{' '} - - ru_RU.ts - -
- Serbian Serbia - (Cyrillic) - - - - @uppy/locales - - /lib/sr_RS_Cyrillic - - - - sr_RS_Cyrillic.min.js - - - ✏️{' '} - - sr_RS_Cyrillic.ts - -
- Serbian Serbia - (Latin) - - - - @uppy/locales - - /lib/sr_RS_Latin - - - - sr_RS_Latin.min.js - - - ✏️{' '} - - sr_RS_Latin.ts - -
- Slovak Slovakia - - - - @uppy/locales - - /lib/sk_SK - - - - sk_SK.min.js - - - ✏️{' '} - - sk_SK.ts - -
- Spanish Spain - - - - @uppy/locales - - /lib/es_ES - - - - es_ES.min.js - - - ✏️{' '} - - es_ES.ts - -
- Spanish Mexico - - - - @uppy/locales - - /lib/es_MX - - - - es_MX.min.js - - - ✏️{' '} - - es_MX.ts - -
- Swedish Sweden - - - - @uppy/locales - - /lib/sv_SE - - - - sv_SE.min.js - - - ✏️{' '} - - sv_SE.ts - -
- Thai Thailand - - - - @uppy/locales - - /lib/th_TH - - - - th_TH.min.js - - - ✏️{' '} - - th_TH.ts - -
- Turkish Turkey - - - - @uppy/locales - - /lib/tr_TR - - - - tr_TR.min.js - - - ✏️{' '} - - tr_TR.ts - -
- Ukrainian Ukraine - - - - @uppy/locales - - /lib/uk_UA - - - - uk_UA.min.js - - - ✏️{' '} - - uk_UA.ts - -
- Uzbek Uzbekistan - - - - @uppy/locales - - /lib/uz_UZ - - - - uz_UZ.min.js - - - ✏️{' '} - - uz_UZ.ts - -
- Vietnamese Vietnam - - - - @uppy/locales - - /lib/vi_VN - - - - vi_VN.min.js - - - ✏️{' '} - - vi_VN.ts - -
- -## Contributing a new language - -If you speak a language we don’t yet support, you can contribute! Here’s how you -do it: - -1. Go to the - [uppy/locales](https://github.com/transloadit/uppy/tree/main/packages/%40uppy/locales/src) - directory in the Uppy GitHub repo. -2. Go to `en_US.js` and copy its contents, as English is the most up-to-date - locale. -3. Press “Create new file”, name it according to the - [`language_COUNTRY` format](http://www.i18nguy.com/unicode/language-identifiers.html), - make sure to use underscore `_` as a divider. Examples: `en_US`, `en_GB`, - `ru_RU`, `ar_AE`. Variants should be trailing, for example `sr_RS_Latin` for - Serbian Latin vs Cyrillic. -4. If your language has different pluralization rules than English, update the - `pluralize` implementation. If you are unsure how to do this, please ask us - for help in a [GitHub issue](https://github.com/transloadit/uppy/issues/new). -5. Paste what you’ve copied from `en_US.js` and use it as a starting point to - translate strings into your language. -6. When you are ready, save the file — this should create a PR that we’ll then - review 🎉 Thanks! diff --git a/docs/presets/_category_.json b/docs/presets/_category_.json deleted file mode 100644 index 467a5e48ab..0000000000 --- a/docs/presets/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Presets", - "position": 9 -} diff --git a/docs/presets/remote-sources.mdx b/docs/presets/remote-sources.mdx deleted file mode 100644 index 5bcb0423d0..0000000000 --- a/docs/presets/remote-sources.mdx +++ /dev/null @@ -1,179 +0,0 @@ ---- -sidebar_position: 1 -slug: /remote-sources ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Remote sources - -`@uppy/remote-sources` is a preset plugin (meaning it bundles and sets up other -plugins) to add all the available remote sources, such Instagram, Google Drive, -Dropbox, and others to Uppy Dashboard in one package. - -:::note - -Remote Sources requires Dashboard and automatically installs all its plugins to -it. - -::: - -## When should I use it? - -`@uppy/remote-sources` aims to simplify the setup for adding Companion plugins, -when you want to share the configuration between plugins. If you want your users -to upload files from any of the remote sources that Uppy offers, this plugin is -recommended. - -A [Companion](/docs/companion) instance is required for the Remote Sources -plugin to work. Companion handles authentication with the remote services (such -as Facebook, Dropbox, etc.), downloads the files, and uploads them to the -destination. This saves the user bandwidth, especially helpful if they are on a -mobile connection. - -You can self-host Companion or get a hosted version with any -[Transloadit plan](https://transloadit.com/pricing/). - -## Install - - - - -```shell -npm install @uppy/remote-sources -``` - - - - - -```shell -yarn add @uppy/remote-sources -``` - - - - - - {` - import { RemoteSources } from "{{UPPY_JS_URL}}" - const RemoteSources = new Uppy().use(RemoteSources) - `} - - - - -## Use - -```js {10} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import RemoteSources from '@uppy/remote-sources'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy(); - .use(Dashboard); - .use(RemoteSources, { companionUrl: 'https://your-companion-url' }); -``` - -### Use with Transloadit - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import RemoteSources from '@uppy/remote-sources'; - -uppy.use(RemoteSources, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import RemoteSources from '@uppy/remote-sources'; - -uppy.use(RemoteSources, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - GoogleDrive: { key: '...', credentialsName: '...' }, - Dropbox: { key: '...', credentialsName: '...' }, - // ...etc - }, -}); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `RemoteSources`). - -#### `sources` - -List of remote sources that will be enabled (`array`, default: -`['Box', 'Dropbox', 'Facebook', 'GoogleDrive','Instagram', 'OneDrive', 'Unsplash', 'Url', 'Zoom']`). - -You don’t need to specify them manually or change them, but if you want to alter -the order in which they appear in the Dashboard, or disable some sources, this -option is for you. - -```js -uppy.use(RemoteSources, { - companionUrl: 'https://your-companion-url', - sources: ['Instagram', 'GoogleDrive', 'Unsplash', 'Url'], -}); -``` - -#### `companionUrl` - -URL to a [Companion](/docs/companion) instance (`string`, default: `null`). - -#### `companionHeaders` - -Custom headers that should be sent along to [Companion](/docs/companion) on -every request (`object`, default: `{}`). - -#### `companionAllowedHosts` - -The valid and authorized URL(s)/URL pattern(s) from which OAuth responses should -be accepted (`string | RegExp | Array`, Default: -`companionUrl`). - -This value can be a `string`, a `RegExp` object, or an array of both. - -This is useful when you have your [Companion](/docs/companion) running on -several hosts. Otherwise, the default value, which is `companionUrl`, should do -fine. - -#### `companionCookiesRule` - -This option correlates to the [`Request.credentials` value][], which tells the plugin -whether to send cookies to [Companion](/docs/companion) (`string`, default: `same-origin`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -[`request.credentials` value]: - https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/quick-start.mdx b/docs/quick-start.mdx deleted file mode 100644 index 5236cf52c9..0000000000 --- a/docs/quick-start.mdx +++ /dev/null @@ -1,58 +0,0 @@ ---- -sidebar_position: 1 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import UppyCdnExample from '/src/components/UppyCdnExample'; -import { QuickStartLinks } from '../src/components/QuickStartLinks/QuickStartLinks.tsx'; - -# Quick start - -Uppy is a sleek, modular JavaScript file uploader that integrates seamlessly -with any application. It’s fast, has a comprehensible API and lets you worry -about more important problems than building a file uploader. - -:::tip - -You can take Uppy for a walk inside StackBlitz with a -[minimal drag & drop](https://stackblitz.com/edit/vitejs-vite-yzbujq?file=main.js/g) -experience or a -[full featured dashboard](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - - diff --git a/docs/sources/_category_.json b/docs/sources/_category_.json deleted file mode 100644 index e3db04f462..0000000000 --- a/docs/sources/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Sources", - "position": 6 -} diff --git a/docs/sources/audio.mdx b/docs/sources/audio.mdx deleted file mode 100644 index c9528d3f22..0000000000 --- a/docs/sources/audio.mdx +++ /dev/null @@ -1,133 +0,0 @@ ---- -sidebar_position: 3 -slug: /audio ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Audio - -The `@uppy/audio` plugin lets you record audio using a built-in or external -microphone, or any other audio device, on desktop and mobile. The UI shows real -time sound wavelength when recording. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want users to record audio on their computer. - -## Install - - - - -```shell -npm install @uppy/audio -``` - - - - - -```shell -yarn add @uppy/audio -``` - - - - - - {` - import { Uppy, Dashboard, Audio } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Dashboard, { inline: true, target: 'body' }) - uppy.use(Audio) - `} - - - - -## Use - -```js {3,7,11} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Audio from '@uppy/audio'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; -import '@uppy/audio/dist/style.min.css'; - -new Uppy().use(Dashboard, { inline: true, target: 'body' }).use(Audio); -``` - -### API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'audio'`). - -#### `title` - -Configures the title / name shown in the UI, for instance, on Dashboard tabs -(`string`, default: `'Audio'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `showAudioSourceDropdown` - -Configures whether to show a dropdown to select audio device (`boolean`, -default: `false`). - -#### `locale` - -```js -export default { - strings: { - pluginNameAudio: 'Audio', - // Used as the label for the button that starts an audio recording. - // This is not visibly rendered but is picked up by screen readers. - startAudioRecording: 'Begin audio recording', - // Used as the label for the button that stops an audio recording. - // This is not visibly rendered but is picked up by screen readers. - stopAudioRecording: 'Stop audio recording', - // Title on the “allow access” screen - allowAudioAccessTitle: 'Please allow access to your microphone', - // Description on the “allow access” screen - allowAudioAccessDescription: - 'In order to record audio, please allow microphone access for this site.', - // Title on the “device not available” screen - noAudioTitle: 'Microphone Not Available', - // Description on the “device not available” screen - noAudioDescription: - 'In order to record audio, please connect a microphone or another audio input device', - // Message about file size will be shown in an Informer bubble - recordingStoppedMaxSize: - 'Recording stopped because the file size is about to exceed the limit', - // Used as the label for the counter that shows recording length (`1:25`). - // This is not visibly rendered but is picked up by screen readers. - recordingLength: 'Recording length %{recording_length}', - // Used as the label for the submit checkmark button. - // This is not visibly rendered but is picked up by screen readers. - submitRecordedFile: 'Submit recorded file', - // Used as the label for the discard cross button. - // This is not visibly rendered but is picked up by screen readers. - discardRecordedFile: 'Discard recorded file', - }, -}; -``` diff --git a/docs/sources/companion-plugins/_category_.json b/docs/sources/companion-plugins/_category_.json deleted file mode 100644 index 22219e8a8f..0000000000 --- a/docs/sources/companion-plugins/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "label": "Companion plugins", - "position": 3, - "collapsed": false -} diff --git a/docs/sources/companion-plugins/box.mdx b/docs/sources/companion-plugins/box.mdx deleted file mode 100644 index 9312bbdbd9..0000000000 --- a/docs/sources/companion-plugins/box.mdx +++ /dev/null @@ -1,226 +0,0 @@ ---- -slug: /box ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Box - -The `@uppy/box` plugin lets users import files from their -[Box](https://www.box.com/en-nl/home) account. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want to let users import files from their -[Box](https://www.box.com/en-nl/home) account. - -A [Companion](/docs/companion) instance is required for the Box plugin to work. -Companion handles authentication with Box, downloads the files, and uploads them -to the destination. This saves the user bandwidth, especially helpful if they -are on a mobile connection. - -You can self-host Companion or get a hosted version with any -[Transloadit plan](https://transloadit.com/pricing/). - - - - -```shell -npm install @uppy/box -``` - - - - - -```shell -yarn add @uppy/box -``` - - - - - - {` - import { Uppy, Box } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Box, { - // Options - }) - `} - - - - -## Use - -Using Box requires setup in both Uppy and Companion. - -### Use in Uppy - -```js {10-13} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Box from '@uppy/box'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: '#dashboard' }) - .use(Box, { companionUrl: 'https://your-companion.com' }); -``` - -### Use with Transloadit - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Box from '@uppy/box'; - -uppy.use(Box, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Box from '@uppy/box'; - -uppy.use(Box, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -### Use in Companion - -You can create a Box App on the -[Box Developers site](https://app.box.com/developers/console). - -Things to note: - -- Choose `Custom App` and select the `User Authentication (OAuth 2.0)` app type. -- You must enable full write access, or you will get - [403 when downloading files](https://support.box.com/hc/en-us/community/posts/360049195613-403-error-while-file-download-API-Call) - -You’ll be redirected to the app page. This page lists the client ID (app key) -and client secret (app secret), which you should use to configure Companion. - -The app page has a `"Redirect URIs"` field. Here, add: - -``` -https://$YOUR_COMPANION_HOST_NAME/box/redirect -``` - -If you are using Transloadit hosted Companion: - -``` -https://api2.transloadit.com/companion/box/redirect -``` - -You can only use the integration with your own account initially. Make sure to -apply for production status on the app page before you publish your app, or your -users will not be able to sign in! - -Configure the Box key and secret. With the standalone Companion server, specify -environment variables: - -```shell -export COMPANION_BOX_KEY="Box API key" -export COMPANION_BOX_SECRET="Box API secret" -``` - -When using the Companion Node.js API, configure these options: - -```js -companion.app({ - providerOptions: { - box: { - key: 'Box API key', - secret: 'Box API secret', - }, - }, -}); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Box'`). - -#### `title` - -Title / name shown in the UI, such as Dashboard tabs (`string`, default: -`'Box'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `companionUrl` - -URL to a [Companion](/docs/companion) instance (`string`, default: `null`). - -#### `companionHeaders` - -Custom headers that should be sent along to [Companion](/docs/companion) on -every request (`Object`, default: `{}`). - -#### `companionAllowedHosts` - -The valid and authorised URL(s) from which OAuth responses should be accepted -(`string` or `RegExp` or `Array`, default: `companionUrl`). - -This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is -useful when you have your [Companion](/docs/companion) running on several hosts. -Otherwise, the default value should do fine. - -#### `companionCookiesRule` - -This option correlates to the -[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -(`string`, default: `'same-origin'`). - -This tells the plugin whether to send cookies to [Companion](/docs/companion). - -#### `locale` - -```js -export default { - strings: { - pluginNameBox: 'Box', - }, -}; -``` - -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/sources/companion-plugins/dropbox.mdx b/docs/sources/companion-plugins/dropbox.mdx deleted file mode 100644 index 4a111f35d5..0000000000 --- a/docs/sources/companion-plugins/dropbox.mdx +++ /dev/null @@ -1,226 +0,0 @@ ---- -slug: /dropbox ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Dropbox - -The `@uppy/dropbox` plugin lets users import files from their -[Dropbox](https://www.dropbox.com) account. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want to let users import files from their -[Dropbox](https://www.dropbox.com) account. - -A [Companion](/docs/companion) instance is required for the Dropbox plugin to -work. Companion handles authentication with Dropbox, downloads the files, and -uploads them to the destination. This saves the user bandwidth, especially -helpful if they are on a mobile connection. - -You can self-host Companion or get a hosted version with any -[Transloadit plan](https://transloadit.com/pricing/). - - - - -```shell -npm install @uppy/dropbox -``` - - - - - -```shell -yarn add @uppy/dropbox -``` - - - - - - {` - import { Uppy, Dropbox } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Dropbox, { - // Options - }) - `} - - - - -## Use - -Using Dropbox requires setup in both Uppy and Companion. - -### Use in Uppy - -```js {10-13} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Dropbox from '@uppy/dropbox'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: '#dashboard' }) - .use(Dropbox, { companionUrl: 'https://your-companion.com' }); -``` - -### Use with Transloadit - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Dropbox from '@uppy/dropbox'; - -uppy.use(Dropbox, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Dropbox from '@uppy/dropbox'; - -uppy.use(Dropbox, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -### Use in Companion - -You can create a Dropbox App on the -[Dropbox Developers site](https://www.dropbox.com/developers/apps/create). - -Things to note: - -- Choose the “Dropbox API”, not the business variant. -- Typically you’ll want “Full Dropbox” access, unless you are absolutely certain - that you need the other one. - -You’ll be redirected to the app page. This page lists the app key and app -secret, which you should use to configure Companion as shown above. - -The app page has a “Redirect URIs” field. Here, add: - -``` -https://$YOUR_COMPANION_HOST_NAME/dropbox/redirect -``` - -If you are using Transloadit hosted Companion: - -``` -https://api2.transloadit.com/companion/dropbox/redirect -``` - -You can only use the integration with your own account initially. Make sure to -apply for production status on the app page before you publish your app, or your -users will not be able to sign in! - -Configure the Dropbox key and secret. With the standalone Companion server, -specify environment variables: - -```shell -export COMPANION_DROPBOX_KEY="Dropbox API key" -export COMPANION_DROPBOX_SECRET="Dropbox API secret" -``` - -When using the Companion Node.js API, configure these options: - -```js -companion.app({ - providerOptions: { - dropbox: { - key: 'Dropbox API key', - secret: 'Dropbox API secret', - }, - }, -}); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Dropbox'`). - -#### `title` - -Title / name shown in the UI, such as Dashboard tabs (`string`, default: -`'Dropbox'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `companionUrl` - -URL to a [Companion](/docs/companion) instance (`string`, default: `null`). - -#### `companionHeaders` - -Custom headers that should be sent along to [Companion](/docs/companion) on -every request (`Object`, default: `{}`). - -#### `companionAllowedHosts` - -The valid and authorised URL(s) from which OAuth responses should be accepted -(`string` or `RegExp` or `Array`, default: `companionUrl`). - -This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is -useful when you have your [Companion](/docs/companion) running on several hosts. -Otherwise, the default value should do fine. - -#### `companionCookiesRule` - -This option correlates to the -[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -(`string`, default: `'same-origin'`). - -This tells the plugin whether to send cookies to [Companion](/docs/companion). - -#### `locale` - -```js -export default { - strings: { - pluginNameDropbox: 'Dropbox', - }, -}; -``` - -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/sources/companion-plugins/facebook.mdx b/docs/sources/companion-plugins/facebook.mdx deleted file mode 100644 index dcc4968094..0000000000 --- a/docs/sources/companion-plugins/facebook.mdx +++ /dev/null @@ -1,223 +0,0 @@ ---- -slug: /facebook ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Facebook - -The `@uppy/facebook` plugin lets users import files from their -[Facebook](https://www.facebook.com) account. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want to let users import files from their -[Facebook](https://www.facebook.com) account. - -A [Companion](/docs/companion) instance is required for the Facebook plugin to -work. Companion handles authentication with Facebook, downloads the files, and -uploads them to the destination. This saves the user bandwidth, especially -helpful if they are on a mobile connection. - -You can self-host Companion or get a hosted version with any -[Transloadit plan](https://transloadit.com/pricing/). - - - - -```shell -npm install @uppy/facebook -``` - - - - - -```shell -yarn add @uppy/facebook -``` - - - - - - {` - import { Uppy, Facebook } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Facebook, { - // Options - }) - `} - - - - -## Use - -Using Facebook requires setup in both Uppy and Companion. - -### Use in Uppy - -```js {10-13} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Facebook from '@uppy/facebook'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: '#dashboard' }) - .use(Facebook, { companionUrl: 'https://your-companion.com' }); -``` - -### Use with Transloadit - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Facebook from '@uppy/facebook'; - -uppy.use(Facebook, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Facebook from '@uppy/facebook'; - -uppy.use(Facebook, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -### Use in Companion - -You can create a Facebook App on the -[Facebook Developers site](https://developers.facebook.com/apps). - -The app page has a “Redirect URIs” field. Here, add: - -``` -https://$YOUR_COMPANION_HOST_NAME/facebook/redirect -``` - -If you are using Transloadit hosted Companion: - -``` -https://api2.transloadit.com/companion/facebook/redirect -``` - -You can only use the integration with your own account initially. Make sure to -apply for production status on the app page before you publish your app, or your -users will not be able to sign in! - -You need to set up OAuth in your Facebook app for Companion to be able to -connect to users’ Facebook accounts. You have to enable “Advanced Access” for -the `user_photos` permission. A precondition of that is “Business Verification” -which involves setting up a Meta Business Account and submitting documents to -prove business ownership. - -Configure the Facebook key and secret. With the standalone Companion server, -specify environment variables: - -```shell -export COMPANION_FACEBOOK_KEY="Facebook API key" -export COMPANION_FACEBOOK_SECRET="Facebook API secret" -``` - -When using the Companion Node.js API, configure these options: - -```js -companion.app({ - providerOptions: { - facebook: { - key: 'Facebook API key', - secret: 'Facebook API secret', - }, - }, -}); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Facebook'`). - -#### `title` - -Title / name shown in the UI, such as Dashboard tabs (`string`, default: -`'Facebook'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `companionUrl` - -URL to a [Companion](/docs/companion) instance (`string`, default: `null`). - -#### `companionHeaders` - -Custom headers that should be sent along to [Companion](/docs/companion) on -every request (`Object`, default: `{}`). - -#### `companionAllowedHosts` - -The valid and authorised URL(s) from which OAuth responses should be accepted -(`string` or `RegExp` or `Array`, default: `companionUrl`). - -This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is -useful when you have your [Companion](/docs/companion) running on several hosts. -Otherwise, the default value should do fine. - -#### `companionCookiesRule` - -This option correlates to the -[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -(`string`, default: `'same-origin'`). - -This tells the plugin whether to send cookies to [Companion](/docs/companion). - -#### `locale` - -```js -export default { - strings: { - pluginNameFacebook: 'Facebook', - }, -}; -``` - -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/sources/companion-plugins/google-drive.mdx b/docs/sources/companion-plugins/google-drive.mdx deleted file mode 100644 index c682464ecb..0000000000 --- a/docs/sources/companion-plugins/google-drive.mdx +++ /dev/null @@ -1,227 +0,0 @@ ---- -slug: /google-drive ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Google Drive - -The `@uppy/google-drive` plugin lets users import files from their -[Google Drive](https://drive.google.com) account. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want to let users import files from their -[Google Drive](https://drive.google.com) account. - -A [Companion](/docs/companion) instance is required for the Google Drive plugin -to work. Companion handles authentication with Google Drive, downloads the -files, and uploads them to the destination. This saves the user bandwidth, -especially helpful if they are on a mobile connection. - -You can self-host Companion or get a hosted version with any -[Transloadit plan](https://transloadit.com/pricing/). - - - - -```shell -npm install @uppy/google-drive -``` - - - - - -```shell -yarn add @uppy/google-drive -``` - - - - - - {` - import { Uppy, GoogleDrive } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(GoogleDrive, { - // Options - }) - `} - - - - -## Use - -Using Google Drive requires setup in both Uppy and Companion. - -### Use in Uppy - -```js {10-13} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import GoogleDrive from '@uppy/google-drive'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: '#dashboard' }) - .use(GoogleDrive, { companionUrl: 'https://your-companion.com' }); -``` - -### Use with Transloadit - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import GoogleDrive from '@uppy/google-drive'; - -uppy.use(GoogleDrive, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import GoogleDrive from '@uppy/google-drive'; - -uppy.use(GoogleDrive, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -### Use in Companion - -To sign up for API keys, go to the -[Google Developer Console](https://console.developers.google.com/). - -Create a project for your app if you don’t have one yet. - -- On the project’s dashboard, - [enable the Google Drive API](https://developers.google.com/drive/api/v3/enable-drive-api). -- [Set up OAuth authorization](https://developers.google.com/drive/api/v3/about-auth). - - Under scopes, add the `https://www.googleapis.com/auth/drive.readonly` Drive - API scope. - - Due to this being a sensitive scope, your app must complete Google’s OAuth - app verification before being granted access. See - [OAuth App Verification Help Center](https://support.google.com/cloud/answer/13463073) - for more information. - -The app page has a `"Redirect URIs"` field. Here, add: - -``` -https://$YOUR_COMPANION_HOST_NAME/drive/redirect -``` - -If you are using Transloadit hosted Companion: - -``` -https://api2.transloadit.com/companion/drive/redirect -``` - -Google will give you an OAuth client ID and client secret. - -Configure the Google key and secret in Companion. With the standalone Companion -server, specify environment variables: - -```shell -export COMPANION_GOOGLE_KEY="Google OAuth client ID" -export COMPANION_GOOGLE_SECRET="Google OAuth client secret" -``` - -When using the Companion Node.js API, configure these options: - -```js -companion.app({ - providerOptions: { - drive: { - key: 'Google OAuth client ID', - secret: 'Google OAuth client secret', - }, - }, -}); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'GoogleDrive'`). - -#### `title` - -Title / name shown in the UI, such as Dashboard tabs (`string`, default: -`'GoogleDrive'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `companionUrl` - -URL to a [Companion](/docs/companion) instance (`string`, default: `null`). - -#### `companionHeaders` - -Custom headers that should be sent along to [Companion](/docs/companion) on -every request (`Object`, default: `{}`). - -#### `companionAllowedHosts` - -The valid and authorised URL(s) from which OAuth responses should be accepted -(`string` or `RegExp` or `Array`, default: `companionUrl`). - -This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is -useful when you have your [Companion](/docs/companion) running on several hosts. -Otherwise, the default value should do fine. - -#### `companionCookiesRule` - -This option correlates to the -[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -(`string`, default: `'same-origin'`). - -This tells the plugin whether to send cookies to [Companion](/docs/companion). - -#### `locale` - -```js -export default { - strings: { - pluginNameGoogleDrive: 'GoogleDrive', - }, -}; -``` - -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/sources/companion-plugins/google-photos.mdx b/docs/sources/companion-plugins/google-photos.mdx deleted file mode 100644 index e90cfb6e65..0000000000 --- a/docs/sources/companion-plugins/google-photos.mdx +++ /dev/null @@ -1,223 +0,0 @@ ---- -slug: /google-photos ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Google Photos - -The `@uppy/google-photos` plugin lets users import files from their -[Google Photos](https://photos.google.com) account. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want to let users import files from their -[Google Photos](https://photos.google.com) account. - -A [Companion](/docs/companion) instance is required for the Google Photos plugin -to work. Companion handles authentication with Google Photos, downloads the -photos/videos, and uploads them to the destination. This saves the user -bandwidth, especially helpful if they are on a mobile connection. - -You can self-host Companion or get a hosted version with any -[Transloadit plan](https://transloadit.com/pricing/). - - - - -```shell -npm install @uppy/google-photos -``` - - - - - -```shell -yarn add @uppy/google-photos -``` - - - - - - {` - import { Uppy, GooglePhotos } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(GooglePhotos, { - // Options - }) - `} - - - - -## Use - -Using Google Photos requires setup in both Uppy and Companion. - -### Use in Uppy - -```js {10-13} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import GooglePhotos from '@uppy/google-photos'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: '#dashboard' }) - .use(GooglePhotos, { - target: Dashboard, - companionUrl: 'https://your-companion.com', - }); -``` - -### Use with Transloadit - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import GooglePhotos from '@uppy/google-photos'; - -uppy.use(GooglePhotos, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import GooglePhotos from '@uppy/google-photos'; - -uppy.use(GooglePhotos, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -### Use in Companion - -To sign up for API keys, go to the -[Google Developer Console](https://console.developers.google.com/). - -Create a project for your app if you don’t have one yet. - -- On the project’s dashboard, - [enable the Google Photos API](https://developers.google.com/photos). -- [Set up OAuth authorization](https://developers.google.com/photos/library/guides/authorization). - -The app page has a `"Redirect URIs"` field. Here, add: - -``` -https://$YOUR_COMPANION_HOST_NAME/googlephotos/redirect -``` - -If you are using Transloadit hosted Companion: - -``` -https://api2.transloadit.com/companion/googlephotos/redirect -``` - -Google will give you an OAuth client ID and client secret. - -Configure the Google key and secret in Companion. With the standalone Companion -server, specify environment variables: - -```shell -export COMPANION_GOOGLE_KEY="Google OAuth client ID" -export COMPANION_GOOGLE_SECRET="Google OAuth client secret" -``` - -When using the Companion Node.js API, configure these options: - -```js -companion.app({ - providerOptions: { - googlephotos: { - key: 'Google OAuth client ID', - secret: 'Google OAuth client secret', - }, - }, -}); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'GooglePhotos'`). - -#### `title` - -Title / name shown in the UI, such as Dashboard tabs (`string`, default: -`'GooglePhotos'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string` or `Element`, default: `null`). - -#### `companionUrl` - -URL to a [Companion](/docs/companion) instance (`string`, default: `null`). - -#### `companionHeaders` - -Custom headers that should be sent along to [Companion](/docs/companion) on -every request (`Object`, default: `{}`). - -#### `companionAllowedHosts` - -The valid and authorised URL(s) from which OAuth responses should be accepted -(`string` or `RegExp` or `Array`, default: `companionUrl`). - -This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is -useful when you have your [Companion](/docs/companion) running on several hosts. -Otherwise, the default value should do fine. - -#### `companionCookiesRule` - -This option correlates to the -[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -(`string`, default: `'same-origin'`). - -This tells the plugin whether to send cookies to [Companion](/docs/companion). - -#### `locale` - -```js -export default { - strings: { - pluginNameGooglePhotos: 'GooglePhotos', - }, -}; -``` - -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/sources/companion-plugins/instagram.mdx b/docs/sources/companion-plugins/instagram.mdx deleted file mode 100644 index ca920d86cf..0000000000 --- a/docs/sources/companion-plugins/instagram.mdx +++ /dev/null @@ -1,236 +0,0 @@ ---- -slug: /instagram ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Instagram - -The `@uppy/instagram` plugin lets users import files from their -[Instagram](https://instagram.com) account. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want to let users import files from their -[Instagram](https://instagram.com) account. - -A [Companion](/docs/companion) instance is required for the Instagram plugin to -work. Companion handles authentication with Instagram, downloads the files, and -uploads them to the destination. This saves the user bandwidth, especially -helpful if they are on a mobile connection. - -You can self-host Companion or get a hosted version with any -[Transloadit plan](https://transloadit.com/pricing/). - - - - -```shell -npm install @uppy/instagram -``` - - - - - -```shell -yarn add @uppy/instagram -``` - - - - - - {` - import { Uppy, Instagram } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Instagram, { - // Options - }) - `} - - - - -## Use - -Using Instagram requires setup in both Uppy and Companion. - -### Use in Uppy - -```js {10-13} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Instagram from '@uppy/instagram'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: '#dashboard' }) - .use(Instagram, { companionUrl: 'https://your-companion.com' }); -``` - -### Use with Transloadit - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Instagram from '@uppy/instagram'; - -uppy.use(Instagram, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Instagram from '@uppy/instagram'; - -uppy.use(Instagram, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -### Use in Companion - -To sign up for API keys, go to the -[Instagram Platform from Meta](https://developers.facebook.com/products/instagram/). - -Create a project for your app if you don’t have one yet. - -The app page has a `"Redirect URIs"` field. Here, add: - -``` -https://$YOUR_COMPANION_HOST_NAME/instagram/redirect -``` - -If you are using Transloadit hosted Companion: - -``` -https://api2.transloadit.com/companion/instagram/redirect -``` - -Meta will give you an OAuth client ID and client secret. - -Configure the Instagram key and secret in Companion. With the standalone -Companion server, specify environment variables: - -```shell -export COMPANION_INSTAGRAM_KEY="Instagram OAuth client ID" -export COMPANION_INSTAGRAM_SECRET="Instagram OAuth client secret" -``` - -When using the Companion Node.js API, configure these options: - -```js -companion.app({ - providerOptions: { - instagram: { - key: 'Instagram OAuth client ID', - secret: 'Instagram OAuth client secret', - }, - }, -}); -``` - -### Development - -Among Uppy-supported providers, Instagram is the only provider at the time of -writing that requires https even in dev mode. So, to test your integration in -development, you need to use some reverse proxy. The easiest way to do it is to -use [https://redirectmeto.com](https://redirectmeto.com). - -In your `.env`, set: - -```sh -COMPANION_DOMAIN="redirectmeto.com/http://localhost:3020" -COMPANION_PROTOCOL="https" -``` - -On -[https://developers.facebook.com/apps/.../instagram-basic-display/basic-display](https://developers.facebook.com/apps/.../instagram-basic-display/basic-display) -page, in the “Valid OAuth Redirect URIs” field, add -`https://redirectmeto.com/http://localhost:3020/instagram/redirect`. - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Instagram'`). - -#### `title` - -Title / name shown in the UI, such as Dashboard tabs (`string`, default: -`'Instagram'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `companionUrl` - -URL to a [Companion](/docs/companion) instance (`string`, default: `null`). - -#### `companionHeaders` - -Custom headers that should be sent along to [Companion](/docs/companion) on -every request (`Object`, default: `{}`). - -#### `companionAllowedHosts` - -The valid and authorised URL(s) from which OAuth responses should be accepted -(`string` or `RegExp` or `Array`, default: `companionUrl`). - -This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is -useful when you have your [Companion](/docs/companion) running on several hosts. -Otherwise, the default value should do fine. - -#### `companionCookiesRule` - -This option correlates to the -[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -(`string`, default: `'same-origin'`). - -This tells the plugin whether to send cookies to [Companion](/docs/companion). - -#### `locale` - -```js -export default { - strings: { - pluginNameInstagram: 'Instagram', - }, -}; -``` - -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/sources/companion-plugins/onedrive.mdx b/docs/sources/companion-plugins/onedrive.mdx deleted file mode 100644 index b91c3931e3..0000000000 --- a/docs/sources/companion-plugins/onedrive.mdx +++ /dev/null @@ -1,224 +0,0 @@ ---- -slug: /onedrive ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# OneDrive - -The `@uppy/onedrive` plugin lets users import files from their -[OneDrive](https://onedrive.com) account. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want to let users import files from their -[OneDrive](https://onedrive.com) account. - -A [Companion](/docs/companion) instance is required for the OneDrive plugin to -work. Companion handles authentication with OneDrive, downloads the files, and -uploads them to the destination. This saves the user bandwidth, especially -helpful if they are on a mobile connection. - -You can self-host Companion or get a hosted version with any -[Transloadit plan](https://transloadit.com/pricing/). - - - - -```shell -npm install @uppy/onedrive -``` - - - - - -```shell -yarn add @uppy/onedrive -``` - - - - - - {` - import { Uppy, OneDrive } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(OneDrive, { - // Options - }) - `} - - - - -## Use - -Using OneDrive requires setup in both Uppy and Companion. - -### Use in Uppy - -```js {10-13} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import OneDrive from '@uppy/onedrive'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: '#dashboard' }) - .use(OneDrive, { companionUrl: 'https://your-companion.com' }); -``` - -### Use with Transloadit - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import OneDrive from '@uppy/onedrive'; - -uppy.use(OneDrive, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import OneDrive from '@uppy/onedrive'; - -uppy.use(OneDrive, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -### Use in Companion - -To sign up for API keys, go to the -[Azure Platform from Microsoft](https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade). - -Create a project for your app if you don’t have one yet. - -The app page has a `"Redirect URIs"` field. Here, add: - -``` -https://$YOUR_COMPANION_HOST_NAME/onedrive/redirect -``` - -If you are using Transloadit hosted Companion: - -``` -https://api2.transloadit.com/companion/onedrive/redirect -``` - -Go to the “Manifest” tab, and find the `"signInAudience"` key. Change it to -`"signInAudience": "AzureADandPersonalMicrosoftAccount"`, and click “Save”. - -Go to the “Overview” tab. Copy the `Application (client) ID` field - this will -be your Oauth client ID. - -Go to the “Certificates & secrets” tab, and click “+ New client secret”. Copy -the `Value` field - this will be your OAuth client secret. - -Configure the OneDrive key and secret in Companion. With the standalone -Companion server, specify environment variables: - -```shell -export COMPANION_ONEDRIVE_KEY="OneDrive Application ID" -export COMPANION_ONEDRIVE_SECRET="OneDrive OAuth client secret value" -``` - -When using the Companion Node.js API, configure these options: - -```js -companion.app({ - providerOptions: { - onedrive: { - key: 'OneDrive Application ID', - secret: 'OneDrive OAuth client secret value', - }, - }, -}); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'OneDrive'`). - -#### `title` - -Title / name shown in the UI, such as Dashboard tabs (`string`, default: -`'OneDrive'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `companionUrl` - -URL to a [Companion](/docs/companion) instance (`string`, default: `null`). - -#### `companionHeaders` - -Custom headers that should be sent along to [Companion](/docs/companion) on -every request (`Object`, default: `{}`). - -#### `companionAllowedHosts` - -The valid and authorised URL(s) from which OAuth responses should be accepted -(`string` or `RegExp` or `Array`, default: `companionUrl`). - -This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is -useful when you have your [Companion](/docs/companion) running on several hosts. -Otherwise, the default value should do fine. - -#### `companionCookiesRule` - -This option correlates to the -[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -(`string`, default: `'same-origin'`). - -This tells the plugin whether to send cookies to [Companion](/docs/companion). - -#### `locale` - -```js -export default { - strings: { - pluginNameOneDrive: 'OneDrive', - }, -}; -``` - -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/sources/companion-plugins/unsplash.mdx b/docs/sources/companion-plugins/unsplash.mdx deleted file mode 100644 index 1287729aeb..0000000000 --- a/docs/sources/companion-plugins/unsplash.mdx +++ /dev/null @@ -1,202 +0,0 @@ ---- -slug: /unsplash ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Unsplash - -The `@uppy/unsplash` plugin lets users import files from their -[Unsplash](https://unsplash.com) account. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want to let users import files from their -[Unsplash](https://unsplash.com) account. - -A [Companion](/docs/companion) instance is required for the Unsplash plugin to -work. Companion handles authentication with Unsplash, downloads the files, and -uploads them to the destination. This saves the user bandwidth, especially -helpful if they are on a mobile connection. - -You can self-host Companion or get a hosted version with any -[Transloadit plan](https://transloadit.com/pricing/). - - - - -```shell -npm install @uppy/unsplash -``` - - - - - -```shell -yarn add @uppy/unsplash -``` - - - - - - {` - import { Uppy, Unsplash } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Unsplash, { - // Options - }) - `} - - - - -## Use - -Using Unsplash requires setup in both Uppy and Companion. - -### Use in Uppy - -```js {10-13} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Unsplash from '@uppy/unsplash'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: '#dashboard' }) - .use(Unsplash, { companionUrl: 'https://your-companion.com' }); -``` - -### Use with Transloadit - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Unsplash from '@uppy/unsplash'; - -uppy.use(Unsplash, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Unsplash from '@uppy/unsplash'; - -uppy.use(Unsplash, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -### Use in Companion - -You can create a Unsplash App on the -[Unsplash Developers site](https://unsplash.com/developers). You’ll be -redirected to the app page, this page lists the app key and app secret. - -Configure the Unsplash key and secret. With the standalone Companion server, -specify environment variables: - -```shell -export COMPANION_UNSPLASH_KEY="Unsplash API key" -export COMPANION_UNSPLASH_SECRET="Unsplash API secret" -``` - -When using the Companion Node.js API, configure these options: - -```js -companion.app({ - providerOptions: { - unsplash: { - key: 'Unsplash API key', - secret: 'Unsplash API secret', - }, - }, -}); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Unsplash'`). - -#### `title` - -Title / name shown in the UI, such as Dashboard tabs (`string`, default: -`'Unsplash'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `companionUrl` - -URL to a [Companion](/docs/companion) instance (`string`, default: `null`). - -#### `companionHeaders` - -Custom headers that should be sent along to [Companion](/docs/companion) on -every request (`Object`, default: `{}`). - -#### `companionAllowedHosts` - -The valid and authorised URL(s) from which OAuth responses should be accepted -(`string` or `RegExp` or `Array`, default: `companionUrl`). - -This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is -useful when you have your [Companion](/docs/companion) running on several hosts. -Otherwise, the default value should do fine. - -#### `companionCookiesRule` - -This option correlates to the -[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -(`string`, default: `'same-origin'`). - -This tells the plugin whether to send cookies to [Companion](/docs/companion). - -#### `locale` - -```js -export default { - strings: { - pluginNameUnsplash: 'Unsplash', - }, -}; -``` - -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/sources/companion-plugins/url.mdx b/docs/sources/companion-plugins/url.mdx deleted file mode 100644 index 52892db586..0000000000 --- a/docs/sources/companion-plugins/url.mdx +++ /dev/null @@ -1,188 +0,0 @@ ---- -slug: /url ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Import from URL - -The `@uppy/url` plugin allows users to import files from the internet. Paste any -URL and it will be added! - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want to let users import files any URL. - -A [Companion](/docs/companion) instance is required for the URL plugin to work. -This saves the user bandwidth, especially helpful if they are on a mobile -connection. - -You can self-host Companion or get a hosted version with any -[Transloadit plan](https://transloadit.com/pricing/). - -:::note - -Companion has -[Server Side Request Forgery](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery) -(SSRF) protections built-in so you don’t have to worry about the security -implications of arbitrary URLs. - -::: - - - - -```shell -npm install @uppy/url -``` - - - - - -```shell -yarn add @uppy/url -``` - - - - - - {` - import { Uppy, Url } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Url, { - // Options - }) - `} - - - - -## Use - -Using `@uppy/url` only requires setup in Uppy. - -### Use in Uppy - -```js {10-13} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Url from '@uppy/url'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; -import '@uppy/url/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: '#dashboard' }) - .use(Url, { companionUrl: 'https://your-companion.com' }); -``` - -### Use with Transloadit - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Url from '@uppy/url'; - -uppy.use(Url, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Url from '@uppy/url'; - -uppy.use(Url, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -### Use in Companion - -Companion supports this plugin out-of-the-box, however it must be enabled in -Companion with the `enableUrlEndpoint` / `COMPANION_ENABLE_URL_ENDPOINT` option. - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Url'`). - -#### `title` - -Title / name shown in the UI, such as Dashboard tabs (`string`, default: -`'Url'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `companionUrl` - -URL to a [Companion](/docs/companion) instance (`string`, default: `null`). - -#### `companionHeaders` - -Custom headers that should be sent along to [Companion](/docs/companion) on -every request (`Object`, default: `{}`). - -#### `companionAllowedHosts` - -The valid and authorised URL(s) from which OAuth responses should be accepted -(`string` or `RegExp` or `Array`, default: `companionUrl`). - -This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is -useful when you have your [Companion](/docs/companion) running on several hosts. -Otherwise, the default value should do fine. - -#### `companionCookiesRule` - -This option correlates to the -[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -(`string`, default: `'same-origin'`). - -This tells the plugin whether to send cookies to [Companion](/docs/companion). - -#### `locale` - -```js -export default { - strings: { - pluginNameUrl: 'Url', - }, -}; -``` - -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/sources/companion-plugins/zoom.mdx b/docs/sources/companion-plugins/zoom.mdx deleted file mode 100644 index 83dbbc7c04..0000000000 --- a/docs/sources/companion-plugins/zoom.mdx +++ /dev/null @@ -1,227 +0,0 @@ ---- -slug: /zoom ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Zoom - -The `@uppy/zoom` plugin lets users import cloud video recordings from their -[Zoom](https://zoom.com) account. Note that -[only licensed](https://support.zoom.com/hc/en/article?id=zm_kb&sysparm_article=KB0063923) -Zoom accounts can store their recordings in the cloud, so this functionality -will only be available to users with a paid Zoom account. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want to let users import cloud video recordings from their -[Zoom](https://zoom.com) account. - -A [Companion](/docs/companion) instance is required for the Zoom plugin to work. -Companion handles authentication with Zoom, downloads the files, and uploads -them to the destination. This saves the user bandwidth, especially helpful if -they are on a mobile connection. - -You can self-host Companion or get a hosted version with any -[Transloadit plan](https://transloadit.com/pricing/). - - - - -```shell -npm install @uppy/zoom -``` - - - - - -```shell -yarn add @uppy/zoom -``` - - - - - - {` - import { Uppy, Zoom } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Zoom, { - // Options - }) - `} - - - - -## Use - -Using Zoom requires setup in both Uppy and Companion. - -### Use in Uppy - -```js {10-13} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Zoom from '@uppy/zoom'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: '#dashboard' }) - .use(Zoom, { companionUrl: 'https://your-companion.com' }); -``` - -### Use with Transloadit - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Zoom from '@uppy/zoom'; - -uppy.use(Zoom, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -You may also hit rate limits, because the OAuth application is shared between -everyone using Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Zoom from '@uppy/zoom'; - -uppy.use(Zoom, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -### Use in Companion - -To sign up for API keys, go through the following steps: - -1. Sign up on [Zoom Marketplace](https://marketplace.zoom.us) - -2. Go to [https://marketplace.zoom.us](https://marketplace.zoom.us). There will - be a dropdown in the header called “Develop”. From that dropdown, select - “Build app”. - -3. In the “Basic Information” tab, Zoom shows your new “Client ID” and “Client - Secret” - copy them. - - With the standalone Companion server, specify environment variables: - - ```shell - export COMPANION_ZOOM_KEY="Zoom API key" - export COMPANION_ZOOM_SECRET="Zoom API secret" - ``` - - When using the Companion Node.js API, configure these options: - - ```js - companion.app({ - providerOptions: { - zoom: { - key: 'Zoom API key', - secret: 'Zoom API secret', - }, - }, - }); - ``` - -4. In the “Basic Information” tab, set “OAuth Redirect URL” input field to: - - ``` - https://$YOUR_COMPANION_HOST_NAME/zoom/redirect - ``` - - If you are using Transloadit hosted Companion: - - ``` - https://api2.transloadit.com/companion/zoom/redirect - ``` - -5. In the “Scopes” tab, add “cloud_recording:read:list_user_recordings” and - “user:read:user” scopes. If Zoom asks for further permissions when you - interact with your Zoom integration - add those too. - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Zoom'`). - -#### `title` - -Title / name shown in the UI, such as Dashboard tabs (`string`, default: -`'Zoom'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `companionUrl` - -URL to a [Companion](/docs/companion) instance (`string`, default: `null`). - -#### `companionHeaders` - -Custom headers that should be sent along to [Companion](/docs/companion) on -every request (`Object`, default: `{}`). - -#### `companionAllowedHosts` - -The valid and authorised URL(s) from which OAuth responses should be accepted -(`string` or `RegExp` or `Array`, default: `companionUrl`). - -This value can be a `string`, a `RegExp` pattern, or an `Array` of both. This is -useful when you have your [Companion](/docs/companion) running on several hosts. -Otherwise, the default value should do fine. - -#### `companionCookiesRule` - -This option correlates to the -[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -(`string`, default: `'same-origin'`). - -This tells the plugin whether to send cookies to [Companion](/docs/companion). - -#### `locale` - -```js -export default { - strings: { - pluginNameZoom: 'Zoom', - }, -}; -``` - -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials diff --git a/docs/sources/file-input.mdx b/docs/sources/file-input.mdx deleted file mode 100644 index cfab8b9154..0000000000 --- a/docs/sources/file-input.mdx +++ /dev/null @@ -1,166 +0,0 @@ ---- -sidebar_position: 3 -slug: /file-input ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# File input - -The `@uppy/file-input` plugin is the most barebones UI for selecting files — it -shows a single button that, when clicked, opens up the browser’s file selector. - -## When should I use it? - -When you want users to select files from their local machine with a minimal UI. - -## Install - - - - -```shell -npm install @uppy/file-input -``` - - - - - -```shell -yarn add @uppy/file-input -``` - - - - - - {` - import { Uppy, FileInput } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(FileInput, { target: document.body }) - `} - - - - -## Use - -```js showLineNumbers -import Uppy from '@uppy/core'; -import FileInput from '@uppy/file-input'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/file-input/dist/style.css'; - -new Uppy().use(FileInput, { target: '#uppy-file-input' }); -``` - -:::note - -The `@uppy/file-input` plugin includes some basic styles for use with the -[`pretty`](#pretty-true) option, like shown in the -[example](/examples/xhrupload). You can also choose not to use it and provide -your own styles instead. - -Import general Core styles from `@uppy/core/dist/style.css` first, then add the -File Input styles from `@uppy/file-input/dist/style.css`. A minified version is -also available as `style.min.css` at the same path. The way to do import depends -on your build system. - -::: - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'FileInput'`). - -#### `title` - -Configures the title / name shown in the UI, for instance, on Dashboard tabs -(`string`, default: `'File Input'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the audio into (`string` or -`Element`, default: `null`). - -#### `pretty` - -When true, display a styled button that, when clicked, opens the file selector -UI. When false, a plain old browser `` element is shown -(`boolean`, default: `true`). - -#### `inputName` - -The `name` attribute for the `` element (`string`, default: -`'files[]'`). - -#### `locale` - -```js -export default { - strings: { - // The same key is used for the same purpose by @uppy/robodog's `form()` API, but our - // locale pack scripts can't access it in Robodog. If it is updated here, it should - // also be updated there! - chooseFiles: 'Choose files', - }, -}; -``` - -## Custom file input - -If you don’t like the look/feel of the button rendered by `@uppy/file-input`, -feel free to forgo the plugin and use your own custom button on a page, like so: - -```html - -``` - -Then add this JS to attach it to Uppy: - -```js -const uppy = new Uppy(/* ... */); -const fileInput = document.querySelector('#my-file-input'); - -fileInput.addEventListener('change', (event) => { - const files = Array.from(event.target.files); - - files.forEach((file) => { - try { - uppy.addFile({ - source: 'file input', - name: file.name, - type: file.type, - data: file, - }); - } catch (err) { - if (err.isRestriction) { - // handle restrictions - console.log('Restriction error:', err); - } else { - // handle other errors - console.error(err); - } - } - }); -}); - -// Clear the `` after the upload or when the file was removed -// so the file can be uploaded again (see -// https://github.com/transloadit/uppy/issues/2640#issuecomment-731034781). -uppy.on('file-removed', () => { - fileInput.value = null; -}); - -uppy.on('complete', () => { - fileInput.value = null; -}); -``` diff --git a/docs/sources/screen-capture.mdx b/docs/sources/screen-capture.mdx deleted file mode 100644 index a2329f7336..0000000000 --- a/docs/sources/screen-capture.mdx +++ /dev/null @@ -1,150 +0,0 @@ ---- -sidebar_position: 2 -slug: /screen-capture ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Screen capture - -The `@uppy/screen-capture` plugin can record your screen or an application and -save it as a video. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -When you want users record their screen on their computer. This plugin only -works on desktop browsers which support -[`getDisplayMedia API`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia). -If no support for the API is detected, Screen Capture won’t be installed, so you -don’t have to do anything. - -:::note - -To use the screen capture plugin in a Chromium-based browser, -[your site must be served over https](https://developers.google.com/web/updates/2015/10/chrome-47-webrtc#public_service_announcements). -This restriction does not apply on `localhost`, so you don’t have to jump -through many hoops during development. - -::: - -## Install - - - - -```shell -npm install @uppy/screen-capture -``` - - - - - -```shell -yarn add @uppy/screen-capture -``` - - - - - - {` - import { Uppy, Dashboard, ScreenCapture } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Dashboard, { inline: true, target: 'body' }) - uppy.use(ScreenCapture) - `} - - - - -## Use - -```js {3,7,11} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import ScreenCapture from '@uppy/screen-capture'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; -import '@uppy/screen-capture/dist/style.min.css'; - -new Uppy().use(Dashboard, { inline: true, target: 'body' }).use(ScreenCapture); -``` - -### API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'ScreenCapture'`). - -#### `title` - -Configures the title / name shown in the UI, for instance, on Dashboard tabs -(`string`, default: `'Screen Capture'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `displayMediaConstraints` - -Options passed to -[`MediaDevices.getDisplayMedia()`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia) -(`Object`, default: `null`). - -See the -[`MediaTrackConstraints`](https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints) -for a list of options. - -#### `userMediaConstraints` - -Options passed to -[`MediaDevices.getUserMedia()`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia) -(`Object`, default: `null`). - -See the -[`MediaTrackConstraints`](https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints) -for a list of options. - -#### `preferredVideoMimeType` - -Set the preferred mime type for video recordings, for example `'video/webm'` -(`string`, default: `null`). - -If the browser supports the given mime type, the video will be recorded in this -format. If the browser does not support it, it will use the browser default. - -If no preferred video mime type is given, the ScreenCapture plugin will prefer -types listed in the [`allowedFileTypes` restriction](/docs/uppy/#restrictions), -if any. - -#### `locale` - -```js -export default { - strings: { - startCapturing: 'Begin screen capturing', - stopCapturing: 'Stop screen capturing', - submitRecordedFile: 'Submit recorded file', - streamActive: 'Stream active', - streamPassive: 'Stream passive', - micDisabled: 'Microphone access denied by user', - recording: 'Recording', - }, -}; -``` diff --git a/docs/sources/webcam.mdx b/docs/sources/webcam.mdx deleted file mode 100644 index 08cf5e3bf4..0000000000 --- a/docs/sources/webcam.mdx +++ /dev/null @@ -1,252 +0,0 @@ ---- -sidebar_position: 1 -slug: /webcam ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Webcam - -The `@uppy/webcam` plugin lets you take photos and record videos with a built-in -camera on desktop and mobile devices. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use it? - -When you want your users to able to use their camera. This plugin is published -separately but made specifically for the [Dashboard](/docs/dashboard). You can -technically use it without it, but it’s not officially supported. - -## Install - - - - -```shell -npm install @uppy/webcam -``` - - - - - -```shell -yarn add @uppy/webcam -``` - - - - - - {` - import { Uppy, Dashboard, Webcam } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Dashboard, { inline: true, target: 'body' }) - uppy.use(Webcam) - `} - - - - -## Use - -:::note - -To use the Webcam plugin in Chrome, -[your site must be served over https](https://developers.google.com/web/updates/2015/10/chrome-47-webrtc#public_service_announcements). -This restriction does not apply on `localhost`, so you don’t have to jump -through many hoops during development. - -::: - -```js {3,7,11} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Webcam from '@uppy/webcam'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; -import '@uppy/webcam/dist/style.min.css'; - -new Uppy().use(Dashboard, { inline: true, target: 'body' }).use(Webcam); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Webcam'`). - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `countdown` - -When taking a picture: the amount of seconds to wait before actually taking a -snapshot (`boolean`, default: `false`). - -If set to `false` or 0, the snapshot is taken right away. This also shows a -`Smile!` message through the [Informer](/docs/informer) before the picture is -taken. - -#### `onBeforeSnapshot` - -A hook function to call before a snapshot is taken (`Function`, default: -`Promise.resolve`). - -The Webcam plugin will wait for the returned Promise to resolve before taking -the snapshot. This can be used to carry out variations on the `countdown` option -for example. - -#### `modes` - -The types of recording modes to allow (`Array`, default: `[]`). - -- `video-audio` - Record a video file, capturing both audio and video. -- `video-only` - Record a video file with the webcam, but don’t record audio. -- `audio-only` - Record an audio file with the user’s microphone. -- `picture` - Take a picture with the webcam. - -By default, all modes are allowed, and the Webcam plugin will show controls for -recording video as well as taking pictures. - -#### `mirror` - -Configures whether to mirror preview image from the camera (`boolean`, default: -`true`). - -This option is useful when taking a selfie with a front camera: when you wave -your right hand, you will see your hand on the right on the preview screen, like -in the mirror. But when you actually take a picture, it will not be mirrored. -This is how smartphone selfie cameras behave. - -#### `videoConstraints` - -Configure the [`MediaTrackConstraints`][] (`Object`, default: `{}`). - -You can specify acceptable ranges for the resolution of the video stream using -the [`aspectRatio`][], [`width`][], and [`height`][] properties. Each property -takes an object with `{ min, ideal, max }` properties. For example, use -`width: { min: 720, max: 1920, ideal: 1920 }` to allow any width between 720 and -1920 pixels wide, while preferring the highest resolution. - -Devices sometimes have several cameras, front and back, for example. -[`facingMode`][] lets you specify which should be used: - -- `user`: The video source is facing toward the user; this includes, for - example, the front-facing camera on a smartphone. -- `environment`: The video source is facing away from the user, thereby viewing - their environment. This is the back camera on a smartphone. -- `left`: The video source is facing toward the user but to their left, such as - a camera aimed toward the user but over their left shoulder. -- `right`: The video source is facing toward the user but to their right, such - as a camera aimed toward the user but over their right shoulder. - -For a full list of available properties, check out MDN documentation for -[`MediaTrackConstraints`][]. - -[`mediatrackconstraints`]: - https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints#Properties_of_video_tracks -[`aspectratio`]: - https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/aspectRatio -[`width`]: - https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/width -[`height`]: - https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/height -[`facingmode`]: - https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/facingMode - -#### `showVideoSourceDropdown` - -Configures whether to show a dropdown which enables to choose the video device -to use (`boolean`, default: `false`). - -This option will have priority over `facingMode` if enabled. - -#### `showRecordingLength` - -Configures whether to show the length of the recording while the recording is in -progress (`boolean`, default: `false`). - -#### `preferredVideoMimeType` - -Set the preferred mime type for video recordings, for example `'video/webm'` -(`string`, default: `null`). - -If the browser supports the given mime type, the video will be recorded in this -format. If the browser does not support it, it will use the browser default. If -no preferred video mime type is given, the Webcam plugin will prefer types -listed in the [`allowedFileTypes` restriction](/docs/uppy/#restrictions), if -any. - -#### `preferredImageMimeType` - -Set the preferred mime type for images, for example `'image/png'` (`string`, -default: `image/jpeg`). - -If the browser supports rendering the given mime type, the image will be stored -in this format. Else `image/jpeg` is used by default. If no preferred image mime -type is given, the Webcam plugin will prefer types listed in the -[`allowedFileTypes` restriction](/docs/uppy/#restrictions), if any. - -#### `mobileNativeCamera` - -Replaces Uppy’s custom camera UI on mobile and tablet with the native device -camera (`Function: boolean` or `boolean`, default: `isMobile()`). - -This will show the “Take Picture” and / or “Record Video” buttons, which ones -show depends on the [`modes`](#modes) option. - -You can set a boolean to forcefully enable / disable this feature, or a function -which returns a boolean. By default we use the -[`is-mobile`](https://github.com/juliangruber/is-mobile) package. - -#### `locale` - -```js -export default { - strings: { - pluginNameCamera: 'Camera', - noCameraTitle: 'Camera Not Available', - noCameraDescription: - 'In order to take pictures or record video, please connect a camera device', - recordingStoppedMaxSize: - 'Recording stopped because the file size is about to exceed the limit', - submitRecordedFile: 'Submit recorded file', - discardRecordedFile: 'Discard recorded file', - // Shown before a picture is taken when the `countdown` option is set. - smile: 'Smile!', - // Used as the label for the button that takes a picture. - // This is not visibly rendered but is picked up by screen readers. - takePicture: 'Take a picture', - // Used as the label for the button that starts a video recording. - // This is not visibly rendered but is picked up by screen readers. - startRecording: 'Begin video recording', - // Used as the label for the button that stops a video recording. - // This is not visibly rendered but is picked up by screen readers. - stopRecording: 'Stop video recording', - // Used as the label for the recording length counter. See the showRecordingLength option. - // This is not visibly rendered but is picked up by screen readers. - recordingLength: 'Recording length %{recording_length}', - // Title on the “allow access” screen - allowAccessTitle: 'Please allow access to your camera', - // Description on the “allow access” screen - allowAccessDescription: - 'In order to take pictures or record video with your camera, please allow camera access for this site.', - }, -}; -``` diff --git a/docs/uploader/_category_.json b/docs/uploader/_category_.json deleted file mode 100644 index 6b7e5d3288..0000000000 --- a/docs/uploader/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Uploaders", - "position": 7 -} diff --git a/docs/uploader/aws-s3-multipart.mdx b/docs/uploader/aws-s3-multipart.mdx deleted file mode 100644 index 8a3b4cbb74..0000000000 --- a/docs/uploader/aws-s3-multipart.mdx +++ /dev/null @@ -1,487 +0,0 @@ ---- -sidebar_position: 4 -slug: /aws-s3 ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# AWS S3 - -The `@uppy/aws-s3` plugin can be used to upload files directly to a S3 bucket or -a S3-compatible provider, such as Google Cloud Storage or DigitalOcean Spaces. -Uploads can be signed using either [Companion][companion docs], temporary -credentials, or a custom signing function. - -## When should I use it? - -:::tip - -Not sure which uploader is best for you? Read -“[Choosing the uploader you need](/docs/guides/choosing-uploader)”. - -::: - -You can use this plugin when you prefer a _client-to-storage_ over a -_client-to-server-to-storage_ (such as [Transloadit](/docs/transloadit) or -[Tus](/docs/tus)) setup. This may in some cases be preferable, for instance, to -reduce costs or the complexity of running a server and load balancer with -[Tus](/docs/tus). - -Multipart uploads start to become valuable for larger files (100 MiB+) as -it uploads a single object as a set of parts. This has certain benefits, such as -improved throughput (uploading parts in parallel) and quick recovery from -network issues (only the failed parts need to be retried). The downside is -request overhead, as it needs to do creation, signing (unless you are [signing -on the client][]), and completion requests besides the upload requests. For example, -if you are uploading files that are only a couple kilobytes with a 100ms roundtrip -latency, you are spending 400ms on overhead and only a few milliseconds on uploading. - -**In short** - -- We recommend the default value of [`shouldUseMultipart`][], which enable - multipart uploads only for large files. -- If you prefer to have less overhead (+20% upload speed) you can use temporary - S3 credentials with [`getTemporarySecurityCredentials`][]. This means users - get a single token which allows them to do bucket operations for longer, - instead of short lived signed URL per resource. This is a security trade-off. - -## Install - - - - -```shell -npm install @uppy/aws-s3 -``` - - - - - -```shell -yarn add @uppy/aws-s3 -``` - - - - - - {` - import { Uppy, AwsS3 } from "{{UPPY_JS_URL}}" - new Uppy().use(AwsS3, { /* see options */ }) - `} - - - - -## Use - -### Setting up your S3 bucket - -To use this plugin with S3 we need to setup a bucket with the right permissions -and CORS settings. - -S3 buckets do not allow public uploads for security reasons. To allow Uppy and -the browser to upload directly to a bucket, its CORS permissions need to be -configured. - -CORS permissions can be found in the -[S3 Management Console](https://console.aws.amazon.com/s3/home). Click the -bucket that will receive the uploads, then go into the `Permissions` tab and -select the `CORS configuration` button. A JSON document will be shown that -defines the CORS configuration. (AWS used to use XML but now only allow JSON). -More information about the -[S3 CORS format here](https://docs.amazonaws.cn/en_us/AmazonS3/latest/userguide/ManageCorsUsing.html). - -The configuration required for Uppy and Companion is this: - -```json -[ - { - "AllowedOrigins": ["https://my-app.com"], - "AllowedMethods": ["GET", "PUT", "POST"], - "MaxAgeSeconds": 3000, - "AllowedHeaders": [ - "Authorization", - "x-amz-date", - "x-amz-content-sha256", - "content-type" - ], - "ExposeHeaders": ["ETag", "Location"] - }, - { - "AllowedOrigins": ["*"], - "AllowedMethods": ["GET"], - "MaxAgeSeconds": 3000 - } -] -``` - -A good practice is to use two CORS rules: one for viewing the uploaded files, -and one for uploading files. This is done above where the first object in the -array defines the rules for uploading, and the second for viewing. The example -above **makes files publicly viewable**. You can change it according to your -needs. - -If you are using an IAM policy to allow access to the S3 bucket, the policy must -have at least the `s3:PutObject` and `s3:PutObjectAcl` permissions scoped to the -bucket in question. In-depth documentation about CORS rules is available on the -[AWS documentation site](https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html). - -### Use with your own server - -The recommended approach is to integrate `@uppy/aws-s3` with your own server. -You will need to do the following things: - -1. [Setup a S3 bucket](#setting-up-your-s3-bucket). -2. [Setup your server](https://github.com/transloadit/uppy/blob/main/examples/aws-nodejs/index.js) -3. [Setup Uppy client](https://github.com/transloadit/uppy/blob/main/examples/aws-nodejs/public/index.html). - -### Use with Companion - -[Companion](/docs/companion) has S3 routes built-in for a plug-and-play -experience with Uppy. - -:::caution - -Generally it’s better for access control, observability, and scaling to -integrate `@uppy/aws-s3` with your own server. You may want to use -[Companion](/docs/companion) for creating, signing, and completing your S3 -uploads if you already need Companion for remote files (such as from Google -Drive). Otherwise it’s not worth the hosting effort. - -::: - -```js {10} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import AwsS3 from '@uppy/aws-s3'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -const uppy = new Uppy() - .use(Dashboard, { inline: true, target: 'body' }) - .use(AwsS3, { - endpoint: 'https://companion.uppy.io', - }); -``` - -### Use with TypeScript - -Uppy always puts the response to an upload in `file.response.body`. If you want -this to be type safe with `@uppy/aws-s3`, you can import the `AwsBody` type and -pass it as the second genric to `Uppy`. - -```ts {3,12} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import AwsS3, { type AwsBody } from '@uppy/aws-s3'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -// Set this to `any` or `Record` -// if you do not set any metadata yourself -type Meta = { license: string }; - -const uppy = new Uppy() - .use(Dashboard, { inline: true, target: 'body' }) - .use(AwsS3, { endpoint: '...' }); - -const id = uppy.addFile(/* ... */); - -await uppy.upload(); - -const body = uppy.getFile(id).response.body!; -const { location } = body; // This is now type safe -``` - -## API - -### Options - -#### `shouldUseMultipart(file)` - -A boolean, or a function that returns a boolean which is called for each file -that is uploaded with the corresponding `UppyFile` instance as argument. - -By default, all files with a `file.size` ≤ 100 MiB will be uploaded in a -single chunk, all files larger than that as multipart. - -Here’s how to use it: - -```js -uppy.use(AwsS3, { - shouldUseMultipart(file) { - // Use multipart only for files larger than 100MiB. - return file.size > 100 * 2 ** 20; - }, -}); -``` - -#### `limit` - -The maximum amount of files to upload in parallel (`number`, default: `6`). - -Note that the amount of files is not the same as the amount of concurrent -connections. Multipart uploads can use many requests per file. For example, for -a 100 MiB file with a part size of 5 MiB: - -- 1 `createMultipartUpload` request -- 100/5 = 20 sign requests (unless you are [signing on the client][]) -- 100/5 = 20 upload requests -- 1 `completeMultipartUpload` request - -:::caution - -Unless you have a good reason and are well informed about the average internet -speed of your users, do not set this higher. S3 uses HTTP/1.1, which means a -limit to concurrent connections and your uploads may expire before they are -uploaded. - -::: - -#### `endpoint` - -URL to your backend or to [Companion](/docs/companion) (`string`, default: -`null`). - -#### `headers` - -Custom headers that should be sent along to the [`endpoint`](#endpoint) on every -request (`Object`, default: `{}`). - -#### `cookiesRule` - -This option correlates to the -[RequestCredentials value](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -(`string`, default: `'same-origin'`). - -This tells the plugin whether to send cookies to the [`endpoint`](#endpoint). - -#### `retryDelays` - -`retryDelays` are the intervals in milliseconds used to retry a failed chunk -(`array`, default: `[0, 1000, 3000, 5000]`). - -This is also used for [`signPart()`](#signpartfile-partdata). Set to `null` to -disable automatic retries, and fail instantly if any chunk fails to upload. - -#### `getChunkSize(file)` - -A function that returns the minimum chunk size to use when uploading the given -file as multipart. - -For multipart uploads, chunks are sent in batches to have presigned URLs -generated with [`signPart()`](#signpartfile-partdata). To reduce the amount of -requests for large files, you can choose a larger chunk size, at the cost of -having to re-upload more data if one chunk fails to upload. - -S3 requires a minimum chunk size of 5MiB, and supports at most 10,000 chunks per -multipart upload. If `getChunkSize()` returns a size that’s too small, Uppy will -increase it to S3’s minimum requirements. - -#### `getUploadParameters(file, options)` - -:::note - -When using [Companion][companion docs] to sign S3 uploads, you should not define -this option. - -::: - -A function that will be called for each non-multipart upload. - -- `file`: `UppyFile` the file that will be uploaded -- `options`: `object` - - `signal`: `AbortSignal` -- **Returns:** `object | Promise` - - `method`: `string`, the HTTP method to be used for the upload. This should - be one of either `PUT` or `POST`, depending on the type of upload used. - - `url`: `string`, the URL to which the upload request will be sent. When - using a presigned PUT upload, this should be the URL to the S3 object with - signing parameters included in the query string. When using a POST upload - with a policy document, this should be the root URL of the bucket. - - `fields` `object`, an object with form fields to send along with the upload - request. For presigned PUT uploads (which are default), this should be left - empty. - - `headers`: `object`, an object with request headers to send along with the - upload request. When using a presigned PUT upload, it’s a good idea to - provide `headers['content-type']`. That will make sure that the request uses - the same content-type that was used to generate the signature. Without it, - the browser may decide on a different content-type instead, causing S3 to - reject the upload. - -#### `createMultipartUpload(file)` - -A function that calls the S3 Multipart API to create a new upload. - -`file` is the file object from Uppy’s state. The most relevant keys are -`file.name` and `file.type`. - -Return a Promise for an object with keys: - -- `uploadId` - The UploadID returned by S3. -- `key` - The object key for the file. This needs to be returned to allow it to - be different from the `file.name`. - -The default implementation calls out to Companion’s S3 signing endpoints. - -#### `listParts(file, { uploadId, key })` - -A function that calls the S3 Multipart API to list the parts of a file that have -already been uploaded. - -Receives the `file` object from Uppy’s state, and an object with keys: - -- `uploadId` - The UploadID of this Multipart upload. -- `key` - The object key of this Multipart upload. - -Return a Promise for an array of S3 Part objects, as returned by the S3 -Multipart API. Each object has keys: - -- `PartNumber` - The index in the file of the uploaded part. -- `Size` - The size of the part in bytes. -- `ETag` - The ETag of the part, used to identify it when completing the - multipart upload and combining all parts into a single file. - -The default implementation calls out to Companion’s S3 signing endpoints. - -#### `signPart(file, partData)` - -A function that generates a signed URL for the specified part number. The -`partData` argument is an object with the keys: - -- `uploadId` - The UploadID of this Multipart upload. -- `key` - The object key in the S3 bucket. -- `partNumber` - can’t be zero. -- `body` – The data that will be signed. -- `signal` – An `AbortSignal` that may be used to abort an ongoing request. - -This function should return a object, or a promise that resolves to an object, -with the following keys: - -- `url` – the presigned URL, as a `string`. -- `headers` – **(Optional)** Custom headers to send along with the request to S3 - endpoint. - -An example of what the return value should look like: - -```json -{ - "url": "https://bucket.region.amazonaws.com/path/to/file.jpg?partNumber=1&...", - "headers": { "Content-MD5": "foo" } -} -``` - -#### `abortMultipartUpload(file, { uploadId, key })` - -A function that calls the S3 Multipart API to abort a Multipart upload, and -removes all parts that have been uploaded so far. - -Receives the `file` object from Uppy’s state, and an object with keys: - -- `uploadId` - The UploadID of this Multipart upload. -- `key` - The object key of this Multipart upload. - -This is typically called when the user cancels an upload. Cancellation cannot -fail in Uppy, so the result of this function is ignored. - -The default implementation calls out to Companion’s S3 signing endpoints. - -#### `completeMultipartUpload(file, { uploadId, key, parts })` - -A function that calls the S3 Multipart API to complete a Multipart upload, -combining all parts into a single object in the S3 bucket. - -Receives the `file` object from Uppy’s state, and an object with keys: - -- `uploadId` - The UploadID of this Multipart upload. -- `key` - The object key of this Multipart upload. -- `parts` - S3-style list of parts, an array of objects with `ETag` and - `PartNumber` properties. This can be passed straight to S3’s Multipart API. - -Return a Promise for an object with properties: - -- `location` - **(Optional)** A publicly accessible URL to the object in the S3 - bucket. - -The default implementation calls out to Companion’s S3 signing endpoints. - -#### `allowedMetaFields: null` - -Pass an array of field names to limit the metadata fields that will be added to -upload as query parameters. - -- Set it to `false` to not send any fields (or an empty array). -- Set it to `['name']` to only send the `name` field. -- Set it to `true` (the default) to send _all_ metadata fields. - -#### `getTemporarySecurityCredentials(options)` - -:::note - -When using [Companion][companion docs] as a backend, you can pass `true` instead -of a function. Setting up Companion will not simplify the process of getting -signing on the client. - -::: - -A boolean (when using Companion), or an (async) function to retrieve temporary -security credentials used for all uploads instead of signing every part. This -results in less request overhead which can lead to around 20% faster uploads. -This is a security tradeoff. We recommend to not use this option unless you are -familiar with the security implications of temporary credentials, and how to -setup your bucket to make it work. See the -[Requesting temporary security credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html) -AWS guide for more information. - -It’s strongly recommended to have some sort of caching process to avoid -requesting more temporary token than necessary. - -- `options`: `object` - - `signal`: `AbortSignal` -- **Returns:** `object | Promise` - - `credentials`: `object` - - `AccessKeyId`: `string` - - `SecretAccessKey`: `string` - - `SessionToken`: `string` - - `Expiration`: `string` - - `bucket`: `string` - - `region`: `string` - -If you are using Companion (for example because you want to support remote -upload sources), you can pass a boolean: - -```js -uppy.use(AwsS3, { - // This is an example using Companion: - endpoint: 'http://companion.uppy.io', - getTemporarySecurityCredentials: true, - shouldUseMultipart: (file) => file.size > 100 * 2 ** 20, -}); -``` - -In the most common case, you are using a different backend, in which case you -need to specify a function: - -```js -uppy.use(AwsS3, { - // This is an example not using Companion: - async getTemporarySecurityCredentials({ signal }) { - const response = await fetch('/sts-token', { signal }); - if (!response.ok) - throw new Error('Failed to fetch STS', { cause: response }); - return response.json(); - }, - shouldUseMultipart: (file) => file.size > 100 * 2 ** 20, -}); -``` - -[`gettemporarysecuritycredentials`]: #gettemporarysecuritycredentialsoptions -[`shouldusemultipart`]: #shouldusemultipartfile -[companion docs]: /docs/companion -[signing on the client]: #gettemporarysecuritycredentialsoptions diff --git a/docs/uploader/transloadit.mdx b/docs/uploader/transloadit.mdx deleted file mode 100644 index 4113406b9c..0000000000 --- a/docs/uploader/transloadit.mdx +++ /dev/null @@ -1,662 +0,0 @@ ---- -sidebar_position: 1 -slug: /transloadit ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Transloadit - -The `@uppy/transloadit` plugin can be used to upload files directly to -[Transloadit](https://transloadit.com/) for all kinds of processing, such as -transcoding video, resizing images, zipping/unzipping, [and much -more][transloadit-services]. - -## When should I use it? - -:::tip - -Not sure which uploader is best for you? Read -“[Choosing the uploader you need](/docs/guides/choosing-uploader)”. - -::: - -Transloadit’s strength is versatility. By doing video, audio, images, documents, -and more, you only need one vendor for [all your file processing -needs][transloadit-services]. The `@uppy/transloadit` plugin directly uploads to -Transloadit so you only have to worry about creating a -[Template][transloadit-concepts]. Transloadit accepts the files, processes -according to the instructions in the Template, and stores the results in storage -of your choosing, such as a self-owned S3 bucket. The Transloadit plugin uses -[Tus](/docs/tus) under the hood so you don’t have to sacrifice reliable, -resumable uploads. - -You should use `@uppy/transloadit` if you don’t want to host your own Tus or -Companion servers, (optionally) need file processing, and store it in the -service (such as S3 or GCS) of your liking. All with minimal effort. - -## Install - - - - -```shell -npm install @uppy/transloadit -``` - - - - - -```shell -yarn add @uppy/transloadit -``` - - - - - - {` - import { Uppy, Transloadit } from "{{UPPY_JS_URL}}" - new Uppy().use(Transloadit, { /* see options */ }) - `} - - - - -## Use - -A quick overview of the complete API. - -```js {10-17} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Transloadit from '@uppy/transloadit'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -const uppy = new Uppy() - .use(Dashboard, { inline: true, target: 'body' }) - .use(Transloadit, { - assemblyOptions: { - params: { - auth: { key: 'your-transloadit-key' }, - template_id: 'your-template-id', - }, - }, - }); -// Optionally listen to events -uppy.on('transloadit:assembly-created', (assembly, fileIDs) => {}); -uppy.on('transloadit:upload', (file, assembly) => {}); -uppy.on('transloadit:assembly-executing', (assembly) => {}); -uppy.on('transloadit:result', (stepName, result, assembly) => {}); -uppy.on('transloadit:complete', (assembly) => {}); -``` - -### Use with Companion - -:::note - -All [Transloadit plans](https://transloadit.com/pricing/) come with a hosted -version of Companion. - -::: - -You can use this plugin together with Transloadit’s hosted Companion service to -let your users import files from third party sources across the web. To do so -each provider plugin must be configured with Transloadit’s Companion URLs: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Dropbox from '@uppy/dropbox'; - -uppy.use(Dropbox, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -This will already work. Transloadit’s OAuth applications are used to -authenticate your users by default. Your users will be asked to provide -Transloadit access to their files. Since your users are probably not aware of -Transloadit, this may be confusing or decrease trust. You may also hit rate -limits, because the OAuth application is shared between everyone using -Transloadit. - -To solve that, you can use your own OAuth keys with Transloadit’s hosted -Companion servers by using Transloadit Template Credentials. [Create a Template -Credential][template-credentials] on the Transloadit site. Select “Companion -OAuth” for the service, and enter the key and secret for the provider you want -to use. Then you can pass the name of the new credentials to that provider: - -```js -import { COMPANION_URL, COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; -import Dropbox from '@uppy/dropbox'; - -uppy.use(Dropbox, { - companionUrl: COMPANION_URL, - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, - companionKeysParams: { - key: 'YOUR_TRANSLOADIT_API_KEY', - credentialsName: 'my_companion_dropbox_creds', - }, -}); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Transloadit'`). - -#### `service` - -The Transloadit API URL to use (`string`, default: -`https://api2.transloadit.com`). - -The default will try to route traffic efficiently based on the location of your -users. You could for instance set it to `https://api2-us-east-1.transloadit.com` -if you need the traffic to stay inside a particular region. - -#### `limit` - -Limit the amount of uploads going on at the same time (`number`, default: `20`). - -Setting this to `0` means no limit on concurrent uploads, but we recommend a -value between `5` and `20`. This option is passed through to the -[`@uppy/tus`](/docs/tus) plugin, which this plugin uses internally. - -#### `assemblyOptions` - -Configure the -[Assembly Instructions](https://transloadit.com/docs/topics/assembly-instructions/), -the fields to send along to the assembly, and authentication -(`object | function`, default: `null`). - -The object you can pass or return from a function has this structure: - -```js -{ - params: { - auth: { key: 'key-from-transloadit' }, - template_id: 'id-from-transloadit', - steps: { - // Overruling Template at runtime - }, - notify_url: 'https://your-domain.com/assembly-status', - }, - signature: 'generated-signature', - fields: { - // Dynamic or static fields to send along - }, -} -``` - -- `params` is used to authenticate with Transloadit and using your desired - [template](https://transloadit.com/docs/topics/templates/). - - `auth.key` _(required)_ is your authentication key which you can find on the - “Credentials” page of your account. - - `template_id` _(required)_ is the unique identifier to use the right - template from your account. - - `steps` _(optional)_ can be used to - [overrule Templates at runtime](https://transloadit.com/docs/topics/templates/#overruling-templates-at-runtime). - A typical use case might be changing the storage path on the fly based on - the session user id. For most use cases, we recommend to let your Templates - handle dynamic cases (they can accept `fields` and execute arbitrary - JavaScript as well), and not pass in `steps` from a browser. The template - editor also has extra validations and context. - - `notify_url` _(optional)_ is a pingback with the assembly status as JSON. - For instance, if you don’t want to block the user experience by letting them - wait for your template to complete with - [`waitForEncoding`](#waitForEncoding), but you do want to want to - asynchrounously have an update, you can provide an URL which will be - “pinged” with the assembly status. -- `signature` _(optional, but recommended)_ is a cryptographic signature to - provide further trust in unstrusted environments. Refer to - “[Signature Authentication”](https://transloadit.com/docs/topics/signature-authentication/) - for more information. -- `fields` _(optional)_ can be used to to send along key/value pairs, which can - be - [used dynamically in your template](https://transloadit.com/docs/topics/assembly-instructions/#form-fields-in-instructions). - -:::info - -All your files end up in a single assembly and your `fields` are available -globally in your template. The metadata in your Uppy files is also sent along so -you can do things dynamically per file with `file.user_meta` in your template. - -::: - -
- Examples - -**As a function** - -Most likely you want to use a function to call your backend to generate a -signature and return your configuration. - -```js -uppy.use(Transloadit, { - async assemblyOptions() { - const res = await fetch('/transloadit-params'); - return res.json(); - }, -}); -``` - -**As an object** - -If you don’t need to change anything dynamically, you can also pass an object -directly. - -```js -uppy.use(Transloadit, { - assemblyOptions: { - params: { auth: { key: 'transloadit-key' } }, - }, -}); -``` - -**Use with @uppy/form** - -Combine the `assemblyOptions()` option with the [Form](/docs/form) plugin to -pass user input from a `` to a Transloadit Assembly: - -```js -// This will add form field values to each file's `.meta` object: -uppy.use(Form, { getMetaFromForm: true }); -uppy.use(Transloadit, { - async assemblyOptions() { - const res = await fetch('/transloadit-params'); - return res.json(); - }; -}); -``` - -
- -:::caution - -When you go to production always make sure to set the `signature`. **Not using -[Signature Authentication](https://transloadit.com/docs/topics/signature-authentication/) -can be a security risk**. Signature Authentication is a security measure that -can prevent outsiders from tampering with your Assembly Instructions. While -Signature Authentication is not implemented (yet), we recommend to disable -`allow_steps_override` in your Templates to avoid outsiders being able to pass -in any Instructions and storage targets on your behalf. - -::: - -#### `waitForEncoding` - -Wait for the template to finish, rather than only the upload, before marking the -upload complete (`boolean`, default: `false`). - -- When `false`, the Assemblies will complete (or error) in the background but - Uppy won’t know or care about it. You may have to let Transloadit ping you via - a `notify_url` and asynchronously inform your user (email, in-app - notification). -- When `true`, the Transloadit plugin waits for Assemblies to complete before - the files are marked as completed. This means users have to wait for a - potentially long time, depending on how complicated your Assembly instructions - are. But, you can receive the final status and transcoding results on the - client side with less effort. - -When this is enabled, you can listen for the -[`transloadit:result`](#transloaditresult) and -[`transloadit:complete`](#transloaditcomplete) events. - -#### `waitForMetadata` - -Wait for Transloadit’s backend to catch early errors, not the entire Assembly to -complete. (`boolean`, default: `false`) - -When set to `true`, the Transloadit plugin waits for Transloadit’s backend to -extract metadata from all the uploaded files. This is mostly handy if you want -to have a quick user experience (so your users don’t necessarily need to wait -for all the encoding to complete), but you do want to let users know about some -types of errors that can be caught early on, like file format issues. - -You you can listen for the [`transloadit:upload`](#transloaditupload) event when -this or `waitForEncoding` is enabled. - -#### `importFromUploadURLs` - -Allow another plugin to upload files, and then import those files into the -Transloadit Assembly (`boolean`, default: `false`). - -When enabling this option, Transloadit will _not_ configure the Tus plugin to -upload to Transloadit. Instead, a separate upload plugin must be used. Once the -upload completes, the Transloadit plugin adds the uploaded file to the Assembly. - -For example, to upload files to an S3 bucket and then transcode them: - -```js -uppy.use(AwsS3, { - getUploadParameters(file) { - return { - /* upload parameters */ - }; - }, -}); -uppy.use(Transloadit, { - importFromUploadURLs: true, - assemblyOptions: { - params: { - auth: { key: 'YOUR_API_KEY' }, - template_id: 'YOUR_TEMPLATE_ID', - }, - }, -}); -``` - -Tranloadit will download the files and expose them to your Template as -`:original`, as if they were directly uploaded from the Uppy client. - -:::note - -For this to work, the upload plugin must assign a publicly accessible -`uploadURL` property to the uploaded file object. The Tus and S3 plugins both do -this automatically, but you must configure your S3 bucket to have publicly -readable objects. For the XHRUpload plugin, you may have to specify a custom -`getResponseData` function. - -::: - -#### `alwaysRunAssembly` - -Always create and run an Assembly when `uppy.upload()` is called, even if no -files were selected (`boolean`, default: `false`). - -This allows running Assemblies that do not receive files, but instead use a -robot like [`/s3/import`](https://transloadit.com/docs/transcoding/#s3-import) -to download the files from elsewhere, for example, for a bulk transcoding job. - -#### `locale` - -```js -export default { - strings: { - // Shown while Assemblies are being created for an upload. - creatingAssembly: 'Preparing upload...', - // Shown if an Assembly could not be created. - creatingAssemblyFailed: 'Transloadit: Could not create Assembly', - // Shown after uploads have succeeded, but when the Assembly is still executing. - // This only shows if `waitForMetadata` or `waitForEncoding` was enabled. - encoding: 'Encoding...', - }, -}; -``` - -#### `clientName` - -Append a custom client name to the `Transloadit-Client` header field when -creating an Assembly (`string`, default: `null`). - -The `Transloadit-Client` header includes by default information about the used -SDK and is included in the Assembly Status under the `transloadit_client` -property. By providing a value, such as `homepage-file-uploader`, you can -identify the client and SDK that created a given Assembly. - -
- Deprecated options - -These options have been deprecated in favor of -[`assemblyOptions`](#assemblyoptions), which we now recommend for all use cases. -You can still use these options, but they will be removed in the next major -version. - -#### `getAssemblyOptions` - -This function behaves the same as passing a function to -[`assemblyOptions`](#assemblyoptions). - -#### `params` - -The Assembly parameters to use for the upload (`object`, default: `null`) See -the Transloadit documentation on -[Assembly Instructions](https://transloadit.com/docs/#14-assembly-instructions) -for further information. - -The `auth.key` Assembly parameter is required. You can also use the `steps` or -`template_id` options here as described in the Transloadit documentation. - -```js -uppy.use(Transloadit, { - params: { - auth: { key: 'YOUR_TRANSLOADIT_KEY' }, - steps: { - encode: { - robot: '/video/encode', - use: { - steps: [':original'], - fields: ['file_input_field2'], - }, - preset: 'iphone', - }, - }, - }, -}); -``` - -#### `signature` - -An optional signature for the Assembly parameters. See the Transloadit -documentation on -[Signature Authentication](https://transloadit.com/docs/#26-signature-authentication) -for further information. - -If a `signature` is provided, `params` should be a JSON string instead of a -JavaScript object, as otherwise the generated JSON in the browser may be -different from the JSON string that was used to generate the signature. - -#### `fields` - -An object of form fields to send along to the Assembly. Keys are field names, -and values are field values. See also the Transloadit documentation on -[Form Fields In Instructions](https://transloadit.com/docs/#23-form-fields-in-instructions). - -```js -uppy.use(Transloadit, { - // ... - fields: { - message: 'This is a form field', - }, -}); -``` - -You can also pass an array of field names to send global or file metadata along -to the Assembly. Global metadata is set using the -[`meta` option](/docs/uppy/#meta) in the Uppy constructor, or using the -[`setMeta` method](/docs/uppy/#uppy-setMeta-data). File metadata is set using -the [`setFileMeta`](/docs/uppy/#uppy-setFileMeta-fileID-data) method. The -[Form](/docs/form) plugin also sets global metadata based on the values of -``s in the form, providing a handy way to use values from HTML form -fields: - -```js -uppy.use(Form, { target: 'form#upload-form', getMetaFromForm: true }); -uppy.use(Transloadit, { - fields: ['field_name', 'other_field_name'], - params: { - /* ... */ - }, -}); -``` - -Form fields can also be computed dynamically using custom logic, by using the -[`getAssemblyOptions(file)`](/docs/transloadit/#getAssemblyOptions-file) option. - -
- -### Static exports - -#### `COMPANION_URL` - -The main endpoint for Transloadit’s hosted companions. You can use this constant -in remote provider options, like so: - -```js -import Dropbox from '@uppy/dropbox'; -import { COMPANION_URL } from '@uppy/transloadit'; - -uppy.use(Dropbox, { - companionUrl: COMPANION_URL, -}); -``` - -When using `COMPANION_URL`, you should also configure -[`companionAllowedHosts`](#companion_allowed_hosts). - -The value of this constant is `https://api2.transloadit.com/companion`. If you -are using a custom [`service`](#service) option, you should also set a custom -host option in your provider plugins, by taking a Transloadit API url and -appending `/companion`: - -```js -uppy.use(Dropbox, { - companionUrl: 'https://api2-us-east-1.transloadit.com/companion', -}); -``` - -#### `COMPANION_ALLOWED_HOSTS` - -A RegExp pattern matching Transloadit’s hosted companion endpoints. The pattern -is used in remote provider `companionAllowedHosts` options, to make sure that -third party authentication messages cannot be faked by an attacker’s page but -can only originate from Transloadit’s servers. - -Use it whenever you use `companionUrl: COMPANION_URL`, like so: - -```js -import Dropbox from '@uppy/dropbox'; -import { COMPANION_ALLOWED_HOSTS } from '@uppy/transloadit'; - -uppy.use(Dropbox, { - companionAllowedHosts: COMPANION_ALLOWED_HOSTS, -}); -``` - -The value of this constant covers _all_ Transloadit’s Companion servers, so it -does not need to be changed if you are using a custom [`service`](#service) -option. But, if you are not using the Transloadit Companion servers at -`*.transloadit.com`, make sure to set the `companionAllowedHosts` option to -something that matches what you do use. - -### Events - -#### `transloadit:assembly-created` - -Fired when an Assembly is created. - -**Parameters** - -- `assembly` - The initial [Assembly Status][assembly-status]. -- `fileIDs` - The IDs of the files that will be uploaded to this Assembly. - -```js -uppy.on('transloadit:assembly-created', (assembly, fileIDs) => { - console.group('Created', assembly.assembly_id, 'for files:'); - for (const id of fileIDs) { - console.log(uppy.getFile(id).name); - } - console.groupEnd(); -}); -``` - -#### `transloadit:upload` - -Fired when Transloadit has received an upload. Requires -[`waitForMetadata`](#waitformetadata) to be set. - -**Parameters** - -- `file` - The Transloadit file object that was uploaded. -- `assembly` - The [Assembly Status][assembly-status] of the Assembly to which - the file was uploaded. - -#### `transloadit:assembly-executing` - -Fired when Transloadit has received all uploads, and is executing the Assembly. - -**Parameters** - -- `assembly` - The - [Assembly Status](https://transloadit.com/docs/api/#assembly-status-response) - of the Assembly that is executing. - -#### `transloadit:result` - -Fired when a result came in from an Assembly. Requires -[`waitForEncoding`](#waitforencoding) to be set. - -**Parameters** - -- `stepName` - The name of the Assembly step that generated this result. -- `result` - The result object from Transloadit. This result object has one more - property, namely `localId`. This is the ID of the file in Uppy’s local state, - and can be used with `uppy.getFile(id)`. -- `assembly` - The [Assembly Status][assembly-status] of the Assembly that - generated this result. - -```js -uppy.on('transloadit:result', (stepName, result) => { - const file = uppy.getFile(result.localId); - document.body.appendChild(html` -
-

From ${file.name}

- View -
- `); -}); -``` - -#### `transloadit:complete` - -Fired when an Assembly completed. Requires [`waitForEncoding`](#waitForEncoding) -to be set. - -**Parameters** - -- `assembly` - The final [Assembly Status][assembly-status] of the completed - Assembly. - -```js -uppy.on('transloadit:complete', (assembly) => { - // Could do something fun with this! - console.log(assembly.results); -}); -``` - -## Frequently Asked Questions - -### Accessing the assembly when an error occurred - -If an error occurs when an Assembly has already started, you can find the -Assembly Status on the error object’s `assembly` property. - -```js -uppy.on('error', (error) => { - if (error.assembly) { - console.log(`Assembly ID ${error.assembly.assembly_id} failed!`); - console.log(error.assembly); - } -}); -``` - -### Assembly behavior when Uppy is closed - -When integrating `@uppy/transloadit` with `@uppy/dashboard`, closing the -dashboard will result in continuing assemblies on the server. When the user -manually cancels the upload any running assemblies will be cancelled. - -[assembly-status]: https://transloadit.com/docs/api/#assembly-status-response -[template-credentials]: - https://transloadit.com/docs/#how-to-create-template-credentials -[transloadit-services]: https://transloadit.com/services/ -[transloadit-concepts]: https://transloadit.com/docs/getting-started/concepts/ diff --git a/docs/uploader/tus.mdx b/docs/uploader/tus.mdx deleted file mode 100644 index 3f0e95b306..0000000000 --- a/docs/uploader/tus.mdx +++ /dev/null @@ -1,332 +0,0 @@ ---- -sidebar_position: 2 -slug: /tus ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Tus - -The `@uppy/tus` plugin brings resumable file uploading with [Tus](http://tus.io) -to Uppy by wrapping the [`tus-js-client`][]. - -## When should I use it? - -:::tip - -Not sure which uploader is best for you? Read -“[Choosing the uploader you need](/docs/guides/choosing-uploader)”. - -::: - -[Tus][tus] is an open protocol for resumable uploads built on HTTP. This means -accidentally closing your tab or losing connection let’s you continue, for -instance, your 10GB upload instead of starting all over. - -Tus supports any language, any platform, and any network. It requires a client -and server integration to work. You can checkout the client and server -[implementations][] to find the server in your preferred language. You can store -files on the Tus server itself, but you can also use service integrations (such -as S3) to store files externally. If you don’t want to host your own server, see -“[Are there hosted Tus servers?](#are-there-hosted-tus-servers)”. - -If you want reliable, resumable uploads: use `@uppy/tus` to connect to your Tus -server in a few lines of code. - -## Install - - - - -```shell -npm install @uppy/tus -``` - - - - - -```shell -yarn add @uppy/tus -``` - - - - - - {` - import { Uppy, Tus } from "{{UPPY_JS_URL}}" - new Uppy().use(Tus, { endpoint: 'https://tusd.tusdemo.net/files' }) - `} - - - - -## Use - -A quick overview of the complete API. - -```js {10} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import Tus from '@uppy/tus'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: 'body' }) - .use(Tus, { endpoint: 'https://tusd.tusdemo.net/files/' }); -``` - -### TypeScript - -If you want the `response` argument on the `upload-success` event and -`file.response.body` to be typed, you have to pass a generic to the Uppy class. - -```ts showLineNumbers -// ... -import Tus, { type TusBody } from '@uppy/tus'; - -type MyMeta = { - /* your added meta data */ -}; - -const uppy = new Uppy().use(Tus, { - endpoint: 'https://tusd.tusdemo.net/files/', -}); - -const [firstFile] = uppy.getFiles(); - -// Correctly typed as XMLHttpRequest. -// Populated after uppy.upload() -firstFile.response.body.xhr; -``` - -## API - -### Options - -:::info - -All options are passed to `tus-js-client` and we document the ones here that are -required, added, or changed. This means you can also pass functions like -[`onAfterResponse`](https://github.com/tus/tus-js-client/blob/master/docs/api.md#onafterresponse). - -We recommended taking a look at the -[API reference](https://github.com/tus/tus-js-client/blob/master/docs/api.md) -from `tus-js-client` to know what is supported. - -::: - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Tus'`). - -#### `endpoint` - -URL of the tus server (`string`, default: `null`). - -#### `headers` - -An object or function returning an object with HTTP headers to send along -requests (`object | function`, default: `null`). - -Keys are header names, values are header values. - -```js -const headers = { - authorization: `Bearer ${window.getCurrentUserToken()}`, -}; -``` - -Header values can also be derived from file data by providing a function. The -function receives an [Uppy file][] and must return an object where the keys are header -names, and values are header values. - -```js -const headers = (file) => { - return { - authorization: `Bearer ${window.getCurrentUserToken()}`, - expires: file.meta.expires, - }; -}; -``` - -#### `chunkSize` - -A number indicating the maximum size of a `PATCH` request body in bytes -(`number`, default: `Infinity`). Note that this option only affects local -browser uploads. If you need a max chunk size for remote (Companion) uploads, -you must set the `chunkSize` Companion option as well. - -:::caution - -Do not set this value unless you are forced to. The two valid reasons are -described in the -[`tus-js-client` docs](https://github.com/tus/tus-js-client/blob/master/docs/api.md#chunksize). - -::: - -#### `withCredentials` - -Configure the requests to send Cookies using the -[`xhr.withCredentials`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials) -property (`boolean`, default: `false`). - -The remote server must accept CORS and credentials. - -#### `retryDelays` - -When uploading a chunk fails, automatically try again after the defined -millisecond intervals (`Array`, default: `[0, 1000, 3000, 5000]`). - -By default, we first retry instantly; if that fails, we retry after 1 second; if -that fails, we retry after 3 seconds, etc. - -Set to `null` to disable automatic retries, and fail instantly if any chunk -fails to upload. - -#### `onBeforeRequest(req, file)` - -Behaves like the -[`onBeforeRequest`](https://github.com/tus/tus-js-client/blob/master/docs/api.md#onbeforerequest) -function from `tus-js-client` but with the added `file` argument. - -#### `onShouldRetry: (err, retryAttempt, options, next)` - -When an upload fails `onShouldRetry` is called with the error and the default -retry logic as the last argument (`function`). - -The default retry logic is an -[exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) -algorithm triggered on HTTP 429 (Too Many Requests) errors. Meaning if your -server (or proxy) returns HTTP 429 because it’s being overloaded, @uppy/tus will -find the ideal sweet spot to keep uploading without overloading. - -If you want to extend this functionality, for instance to retry on unauthorized -requests (to retrieve a new authentication token): - -```js -import Uppy from '@uppy/core'; -import Tus from '@uppy/tus'; -new Uppy().use(Tus, { - endpoint: '', - async onBeforeRequest(req) { - const token = await getAuthToken(); - req.setHeader('Authorization', `Bearer ${token}`); - }, - onShouldRetry(err, retryAttempt, options, next) { - if (err?.originalResponse?.getStatus() === 401) { - return true; - } - return next(err); - }, - async onAfterResponse(req, res) { - if (res.getStatus() === 401) { - await refreshAuthToken(); - } - }, -}); -``` - -#### `allowedMetaFields` - -Pass an array of field names to limit the metadata fields that will be added to -uploads as -[Tus Metadata](https://tus.io/protocols/resumable-upload.html#upload-metadata) -(`Array`, default: `null`). - -- Set it to `false` to not send any fields (or an empty array). -- Set it to `['name']` to only send the `name` field. -- Set it to `true` (the default) to send _all_ metadata fields. - -#### `limit` - -Limit the amount of uploads going on at the same time (`number`, default: `20`). - -Setting this to `0` means no limit on concurrent uploads (not recommended). - -## Frequently Asked Questions - -:::info - -The Tus website has extensive [FAQ section](https://tus.io/faq.html), we -recommend taking a look there as well if something is unclear. - -::: - -### How is file meta data stored? - -Tus uses unique identifiers for the file names to prevent naming collisions. To -still keep the meta data in place, Tus also uploads an extra `.info` file with -the original file name and other meta data: - -```json -{ - "ID": "00007a99d16d4eeb5a3e3c080b6f69da+JHZavdqPSK4VMtarg2yYcNiP8t_kDjN51lBYMJdEyr_wqEotVl8ZBRBSTnWKWenZBwHvbLNz5tQXYp2N7Vdol.04ysQAuw__suTJ4IsCljj0rjyWA6LvV4IwF5P2oom2", - "Size": 1679852, - "SizeIsDeferred": false, - "Offset": 0, - "MetaData": { - "filename": "cat.jpg", - "filetype": "image/jpeg" - }, - "IsPartial": false, - "IsFinal": false, - "PartialUploads": null, - "Storage": { - "Bucket": "your-bucket", - "Key": "some-key", - "Type": "s3store" - } -} -``` - -### How do I change files before sending them? - -If you want to change the file names, you want to do that in -[`onBeforeFileAdded`](/docs/uppy#onbeforefileaddedfile-files). - -If you want to send extra headers with the request, use [`headers`](#headers) or -[`onBeforeRequest`](#onbeforerequestreq-file). - -### How do I change (or move) files after sending them? - -If you want to preserve files names, extract meta data, or move files to a -different place you generally can with hooks or events. It depends on the Tus -server you use how it’s done exactly. [`tusd`][], for instance, exposes -[hooks](https://github.com/tus/tusd/blob/master/docs/hooks.md) and -[`tus-node-server`](https://github.com/tus/tus-node-server) has -[events](https://github.com/tus/tus-node-server#events). - -### Which server do you recommend? - -[Transloadit](https://transloadit.com) runs [`tusd`][] in production, where it -serves millions of requests globally. So we recommend `tusd` as battle-tested -from our side, but other companies have had success with other -[implementations][] so it depends on your needs. - -### Are there hosted Tus servers? - -All [Transloadit plans](https://transloadit.com/pricing) come with a hosted -[`tusd`][] server. You don’t have to do anything to leverage it, using -[`@uppy/transloadit`](/docs/transloadit) automatically uses Tus under the hood. - -### Why Tus instead of directly uploading to AWS S3? - -First: reliable, resumable uploads. This means accidentally closing your tab or -losing connection let’s you continue, for instance, your 10GB upload instead of -starting all over. - -Tus is also efficient with lots of files (such as 8K) and large files. Uploading -to AWS S3 directly from the client also introduces quite a bit of overhead, as -more requests are needed for the flow to work. - -[`tus-js-client`]: https://github.com/tus/tus-js-client -[uppy file]: /docs/uppy#working-with-uppy-files -[tus]: https://tus.io/ -[`tusd`]: https://github.com/tus/tusd -[implementations]: https://tus.io/implementations.html diff --git a/docs/uploader/xhr.mdx b/docs/uploader/xhr.mdx deleted file mode 100644 index c62c2aed45..0000000000 --- a/docs/uploader/xhr.mdx +++ /dev/null @@ -1,383 +0,0 @@ ---- -sidebar_position: 5 -slug: /xhr-upload ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# XHR - -The `@uppy/xhr-upload` plugin is for regular uploads to a HTTP server. - -## When should I use it? - -:::tip - -Not sure which uploader is best for you? Read -“[Choosing the uploader you need](/docs/guides/choosing-uploader)”. - -::: - -When you have an existing HTTP server and you don’t need Transloadit services or -want to run a [tus][] server. Note that it’s still possible to use [tus][] -without running an extra server by integrating tus into your existing one. For -instance, if you have a Node.js server (or server-side framework like Next.js) -you could integrate [tus-node-server][]. - -## Install - - - - -```shell -npm install @uppy/xhr-upload -``` - - - - - -```shell -yarn add @uppy/xhr-upload -``` - - - - - - {` - import { Uppy, XHRUpload } from "{{UPPY_JS_URL}}" - new Uppy().use(XHRUpload, { endpoint: 'https://tusd.tusdemo.net/files' }) - `} - - - - -## Use - -A quick overview of the complete API. - -```js {10} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import XHR from '@uppy/xhr-upload'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: 'body' }) - .use(XHR, { endpoint: 'https://your-domain.com/upload' }); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'XHRUpload'`). - -#### `endpoint` - -URL of the HTTP server (`string`, default: `null`). - -#### `method` - -Configures which HTTP method to use for the upload (`string`, default: -`'POST'`). - -#### `formData` - -Configures whether to use a multipart form upload, using [FormData][] -(`boolean`, default: `true`). - -This works similarly to using a `` element with an `` -for uploads. When set to `true`, file metadata is also sent to the endpoint as -separate form fields. When set to `false`, only the file contents are sent. - -#### `fieldName` - -When [`formData`](#formData-true) is set to true, this is used as the form field -name for the file to be uploaded. - -It defaults to `'files[]'` if `bundle` option is set to `true`, otherwise it -defaults to `'file'`. - -#### `allowedMetaFields` - -Pass an array of field names to limit the metadata fields that will be added to -upload. - -- Set it to `false` to not send any fields (or an empty array). -- Set it to `['name']` to only send the `name` field. -- Set it to `true` (the default) to send _all_ metadata fields. - -If the [`formData`](#formData-true) option is set to false, `metaFields` is -ignored. - -#### `headers` - -An object containing HTTP headers to use for the upload request. Keys are header -names, values are header values. - -```js -const headers = { - authorization: `Bearer ${window.getCurrentUserToken()}`, -}; -``` - -Header values can also be derived from file data by providing a function. The -function receives an [Uppy file][] and must return an object where the keys are header -names, and values are header values. - -```js -const headers = (file) => { - return { - authorization: `Bearer ${window.getCurrentUserToken()}`, - expires: file.meta.expires, - }; -}; -``` - -:::note - -The function syntax is not available when [`bundle`](#bundle) is set to `true`. - -::: - -:::note - -Failed requests are retried with the same headers. If you want to change the -headers on retry, -[such as refreshing an auth token](#how-can-I-refresh-auth-tokens-after-they-expire), -you can use [`onBeforeRequest`](#onbeforerequest). - -::: - -#### `bundle` - -Send all files in a single multipart request (`boolean`, default: `false`). - -All files will be appended to the provided `fieldName` field in the request. - -:::caution - -When `bundle` is set to `true`: - -- [`formData`](#formData-true) must also be set to `true`. -- Uppy won’t be able to bundle remote files (such as Google Drive) and will - throw an error in this case. -- Only [global uppy metadata](/docs/uppy/#meta) is sent to the endpoint. - Individual per-file metadata is ignored. - -::: - -To upload files on different fields, use -[`uppy.setFileState()`](/docs/uppy#uppy-setFileState-fileID-state) to set the -`xhrUpload.fieldName` property on the file: - -```js -uppy.setFileState(fileID, { - xhrUpload: { fieldName: 'pic0' }, -}); -``` - -#### `timeout: 30 * 1000` - -Abort the connection if no upload progress events have been received for this -milliseconds amount (`number`, default: `30_000`). - -Note that unlike the [`XMLHttpRequest.timeout`][xhr.timeout] property, this is a -timer between progress events: the total upload can take longer than this value. -Set to `0` to disable this check. - -#### `limit` - -The maximum amount of files to upload in parallel (`number`, default: `5`). - -#### `responseType` - -The response type expected from the server, determining how the `xhr.response` -property should be filled (`string`, default: `'text'`). - -The `xhr.response` property can be accessed in a custom -[`getResponseData()`](#getResponseData-responseText-response) callback. This -option sets the [`XMLHttpRequest.responseType`][xhr.responsetype] property. Only -`''`, `'text'`, `'arraybuffer'`, `'blob'` and `'document'` are widely supported -by browsers, so it’s recommended to use one of those. - -#### `withCredentials` - -Indicates whether cross-site Access-Control requests should be made using -credentials (`boolean`, default: `false`). - -#### `onBeforeRequest` - -An optional function that will be called before a HTTP request is sent out -(`(xhr: XMLHttpRequest, retryCount: number, files: UppyFile[]) => void | Promise`). - -The third argument, `files`, is an array of all Uppy files when `bundle` is -`true`. When `false`, it only contains one file. - -#### `shouldRetry` - -An optional function called once an error appears and before retrying -(`(xhr: XMLHttpRequesT) => boolean`). - -The amount of retries is 3, even if you continue to return `true`. The default -behavior uses -[exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff) with a -maximum of 3 retries. - -#### `onAfterResponse` - -An optional function that will be called after a HTTP response has been received -(`(xhr: XMLHttpRequest, retryCount: number) => void | Promise`). - -#### `locale: {}` - -```js -export default { - strings: { - // Shown in the Informer if an upload is being canceled because it stalled for too long. - timedOut: 'Upload stalled for %{seconds} seconds, aborting.', - }, -}; -``` - -#### `getResponseData` - -An optional function to turn your non-JSON response into JSON with a `url` -property pointing to the uploaded file -(`(xhr: XMLHttpRequest) => { url: string }`). - -You can also return properties other than `url` and they will end up in -`file.response.body`. If you do, make sure to set the `Body` generic on `Uppy` -to make it typesafe when using TS. - -## Frequently Asked Questions - -### How can I refresh auth tokens after they expire? - -```js -import Uppy from '@uppy/core'; -import XHR from '@uppy/xhr-upload'; - -let token = null; - -async function getAuthToken() { - const res = await fetch('/auth/token'); - const json = await res.json(); - return json.token; -} - -new Uppy().use(XHR, { - endpoint: '', - // Called again for every retry too. - async onBeforeRequest(xhr) { - if (!token) { - token = await getAuthToken(); - } - xhr.setRequestHeader('Authorization', `Bearer ${token}`); - }, - async onAfterResponse(xhr) { - if (xhr.status === 401) { - token = await getAuthToken(); - } - }, -}); -``` - -### How to send along meta data with the upload? - -When using XHRUpload with [`formData: true`](#formData-true), file metadata is -sent along with each upload request. You can set metadata for a file using -[`uppy.setFileMeta(fileID, data)`](/docs/uppy#uppy-setFileMeta-fileID-data), or -for all files simultaneously using -[`uppy.setMeta(data)`](/docs/uppy#uppy-setMeta-data). - -It may be useful to set metadata depending on some file properties, such as the -size. You can use the [`file-added`](/docs/uppy/#file-added) event and the -[`uppy.setFileMeta(fileID, data)`](/docs/uppy#uppy-setFileMeta-fileID-data) -method to do this: - -```js -uppy.on('file-added', (file) => { - uppy.setFileMeta(file.id, { - size: file.size, - }); -}); -``` - -Now, a form field named `size` will be sent along to the -[`endpoint`](#endpoint-39-39) once the upload starts. - -By default, all metadata is sent, including Uppy’s default `name` and `type` -metadata. If you do not want the `name` and `type` metadata properties to be -sent to your upload endpoint, you can use the [`metaFields`](#metaFields-null) -option to restrict the field names that should be sent. - -```js -uppy.use(XHRUpload, { - // Only send our own `size` metadata field. - allowedMetaFields: ['size'], -}); -``` - -### How to upload to a PHP server? - -The XHRUpload plugin works similarly to a `` upload. You can use the -`$_FILES` variable on the server to work with uploaded files. See the PHP -documentation on [Handling file uploads][php.file-upload]. - -The default form field for file uploads is `files[]`, which means you have to -access the `$_FILES` array as described in [Uploading many files][php.multiple]: - -```php - - - -```shell -npm install @uppy/core -``` - - - - - -```shell -yarn add @uppy/core -``` - - - - - - {` - import { Uppy } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - `} - - - - -## Use - -`@uppy/core` has four exports: `Uppy`, `UIPlugin`, `BasePlugin`, and -`debugLogger`. The default export is the `Uppy` class. - -### Working with Uppy files - -Uppy keeps files in state with the [`File`][] browser API, but it’s wrapped in -an `Object` to be able to add more data to it, which we call an _Uppy file_. All -these properties can be useful for plugins and side-effects (such as -[events](#events)). - -Mutating these properties should be done through [methods](#methods). - -
- Uppy file properties - -#### `file.source` - -Name of the plugin that was responsible for adding this file. Typically a remote -provider plugin like `'GoogleDrive'` or a UI plugin like `'DragDrop'`. - -#### `file.id` - -Unique ID for the file. - -#### `file.name` - -The name of the file. - -#### `file.meta` - -Object containing standard as well as user-defined metadata for each file. Any -custom file metadata should be JSON-serializable. The following standard -metadata will be stored on all file objects, but plugins may add more metadata. - -- `file.meta.name` - - Same as `file.name`. -- `file.meta.type` - - Same as `file.type`. -- `file.meta.relativePath` - - For any local folder that was drag-dropped or opened in Uppy, the files - inside the folder will have the `relativePath` metadata field set to their - path, relative to the folder. `relativePath` begins with the folder’s name - and ends with the file’s name. If opening or drag-dropping a file instead of - a folder, `relativePath` will be `null`. The same behaviour exists for - remote (provider) files, but the path will instead be relative to the user’s - selection (checkboxes). No leading or trailing slashes. - - **Local file example:** When drag-dropping a local folder `folder1` which - has a folder inside of it named `folder2` which has a file named `file` - inside of it, the `relativePath` meta field of the file will be - `folder1/folder2/file`. However if drag-dropping or opening `file` directly, - `relativePath` will be `null`. - - **Remote file example:** Suppose we have a remote provider folder structure - such as `/folder1/folder2/file`. Then, if the user checks the checkbox next - to `folder1`, `file`’s `relativePath` will be `"folder1/folder2/file"`. - However if the user first navigates into `folder1`, and only then checks the - checkbox next to `folder2`, `relativePath` will be `"folder2/file"`. -- `file.meta.absolutePath` - - The `absolutePath` meta field will only be set for remote files. Regardless - of user selection, it will always be the path relative to the root of the - provider’s list of files, as presented to the user. `absolutePath` always - begins with a `/` and will always end with the file’s name. To clarify: The - difference between `absolutePath` and `relativePath` is that `absolutePath` - only exists for remote files, and always has the full path to the file, - while `relativePath` is the file’s path _relative to the user’s selected - folder_. - -#### `file.type` - -MIME type of the file. This may actually be guessed if a file type was not -provided by the user’s browser, so this is a best-effort value and not -guaranteed to be correct. - -#### `file.data` - -For local files, this is the actual [`File`][] or [`Blob`][] object representing -the file contents. - -For files that are imported from remote providers, the file data is not -available in the browser. - -[`file`]: https://developer.mozilla.org/en-US/docs/Web/API/File -[`blob`]: https://developer.mozilla.org/en-US/docs/Web/API/Blob - -#### `file.progress` - -An object with upload progress data. - -**Properties** - -- `bytesUploaded` - Number of bytes uploaded so far. -- `bytesTotal` - Number of bytes that must be uploaded in total. -- `uploadStarted` - Null if the upload has not started yet. Once started, this - property stores a UNIX timestamp. Note that this is only set _after_ - preprocessing. -- `uploadComplete` - Boolean indicating if the upload has completed. Note this - does _not_ mean that postprocessing has completed, too. -- `percentage` - Integer percentage between 0 and 100. - -#### `file.size` - -Size in bytes of the file. - -#### `file.isRemote` - -Boolean: is this file imported from a remote provider? - -#### `file.remote` - -Grab bag of data for remote providers. Generally not interesting for end users. - -#### `file.preview` - -An optional URL to a visual thumbnail for the file. - -#### `file.uploadURL` - -When an upload is completed, this may contain a URL to the uploaded file. -Depending on server configuration it may not be accessible or correct. - -
- -## `new Uppy(options?)` - -```js -import Uppy from '@uppy/core'; - -const uppy = new Uppy(); -``` - -### Options - -#### `id` - -A site-wide unique ID for the instance (`string`, default: `uppy`). - -:::note - -If several Uppy instances are being used, for instance, on two different pages, -an `id` should be specified. This allows Uppy to store information in -`localStorage` without colliding with other Uppy instances. - -This ID should be persistent across page reloads and navigation—it shouldn’t be -a random number that is different every time Uppy is loaded. - -::: - -#### `autoProceed` - -Upload as soon as files are added (`boolean`, default: `false`). - -By default Uppy will wait for an upload button to be pressed in the UI, or the -`.upload()` method to be called before starting an upload. Setting this to -`true` will start uploading automatically after the first file is selected - -#### `allowMultipleUploadBatches` - -Whether to allow several upload batches (`boolean`, default: `true`). - -This means several calls to `.upload()`, or a user adding more files after -already uploading some. An upload batch is made up of the files that were added -since the earlier `.upload()` call. - -With this option set to `true`, users can upload some files, and then add _more_ -files and upload those as well. A model use case for this is uploading images to -a gallery or adding attachments to an email. - -With this option set to `false`, users can upload some files, and you can listen -for the [`'complete'`](#complete) event to continue to the next step in your -app’s upload flow. A typical use case for this is uploading a new profile -picture. If you are integrating with an existing HTML form, this option gives -the closest behaviour to a bare ``. - -#### `debug` - -Whether to send debugging and warning logs (`boolean`, default: `false`). - -Setting this to `true` sets the [`logger`](#logger) to -[`debugLogger`](#debuglogger). - -#### `logger` - -Logger used for [`uppy.log`](#logmessage-type) (`Object`, default: -`justErrorsLogger`). - -By providing your own `logger`, you can send the debug information to a server, -choose to log errors only, etc. - -:::note - -Set `logger` to [`debugLogger`](#debuglogger) to get debug info output to the -browser console: - -::: - -:::note - -You can also provide your own logger object: it should expose `debug`, `warn` -and `error` methods, as shown in the examples below. - -Here’s an example of a `logger` that does nothing: - -```js -const nullLogger = { - debug: (...args) => {}, - warn: (...args) => {}, - error: (...args) => {}, -}; -``` - -::: - -#### `restrictions` - -Conditions for restricting an upload (`Object`, default: `{}`). - -| Property | Value | Description | -| -------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------- | -| `maxFileSize` | `number` | maximum file size in bytes for each individual file | -| `minFileSize` | `number` | minimum file size in bytes for each individual file | -| `maxTotalFileSize` | `number` | maximum file size in bytes for all the files that can be selected for upload | -| `maxNumberOfFiles` | `number` | total number of files that can be selected | -| `minNumberOfFiles` | `number` | minimum number of files that must be selected before the upload | -| `allowedFileTypes` | `Array` | wildcards `image/*`, or exact mime types `image/jpeg`, or file extensions `.jpg`: `['image/*', '.jpg', '.jpeg', '.png', '.gif']` | -| `requiredMetaFields` | `Array` | make keys from the `meta` object in every file required before uploading | - -:::note - -`maxNumberOfFiles` also affects the number of files a user is able to select via -the system file dialog in UI plugins like `DragDrop`, `FileInput` and -`Dashboard`. When set to `1`, they will only be able to select a single file. -When `null` or another number is provided, they will be able to select several -files. - -::: - -:::note - -`allowedFileTypes` gets passed to the file system dialog via the -[``](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Limiting_accepted_file_types) -accept attribute, so only types supported by the browser will work. - -::: - -:::tip - -If you’d like to force a certain meta field data to be entered before the -upload, you can -[do so using `onBeforeUpload`](https://github.com/transloadit/uppy/issues/1703#issuecomment-507202561). - -::: - -:::tip - -If you need to restrict `allowedFileTypes` to a file extension with double dots, -like `.nii.gz`, you can do so by -[setting `allowedFileTypes` to the last part of the extension, `allowedFileTypes: ['.gz']`, and then using `onBeforeFileAdded` to filter for `.nii.gz`](https://github.com/transloadit/uppy/issues/1822#issuecomment-526801208). - -::: - -#### `meta` - -Key/value pairs to add to each file’s `metadata` (`Object`, default: `{}`). - -:::note - -Metadata from each file is then attached to uploads in the [Tus](/docs/tus) and -[XHR](/docs/xhr-upload) plugins. - -::: - -:::info - -Two methods also exist for updating `metadata`: [`setMeta`](#setmetadata) and -[`setFileMeta`](#setfilemetafileid-data). - -::: - -:::info - -Metadata can also be added from a `` element on your page, through the -[Form](#) plugin or through the UI if you are using Dashboard with the -[`metaFields`](/docs/dashboard#metafields) option. - -::: - - - -#### `onBeforeFileAdded(file, files)` - -A function called before a file is added to Uppy (`Function`, default: -`(files, file) => !Object.hasOwn(files, file.id)`). - -Use this function to run any number of custom checks on the selected file, or -manipulate it, for instance, by optimizing a file name. You can also allow -duplicate files with this. - -You can return `true` to keep the file as is, `false` to remove the file, or -return a modified file. - -:::caution - -This method is intended for quick synchronous checks and modifications only. If -you need to do an async API call, or heavy work on a file (like compression or -encryption), you should use a [custom plugin](/docs/guides/building-plugins) -instead. - -::: - -:::info - -No notification will be shown to the user about a file not passing validation by -default. We recommend showing a message using -[`uppy.info()`](#infomessage-type-duration) and logging to console for debugging -purposes via [`uppy.log()`](#logmessage-type). - -::: - -
- Filter, change, and abort example - -Allow all files, also duplicate files. This will replace the file if it has not -been uploaded. If you upload a duplicate file again it depends on your upload -plugin and backend how it is handled. - -```js -const uppy = new Uppy({ - // ... - onBeforeFileAdded: () => true, -``` - -Keep only files under a condition: - -```js -const uppy = new Uppy({ - // ... - onBeforeFileAdded: (currentFile, files) => { - if (currentFile.name === 'forest-IMG_0616.jpg') { - return true - } - return false - }, -``` - -Change all file names: - -```js -const uppy = new Uppy({ - // ... - onBeforeFileAdded: (currentFile, files) => { - const modifiedFile = { - ...currentFile, - name: `${currentFile.name}__${Date.now()}`, - } - return modifiedFile - }, -``` - -Abort a file: - -```js -const uppy = new Uppy({ - // ... - onBeforeFileAdded: (currentFile, files) => { - if (!currentFile.type) { - // log to console - uppy.log(`Skipping file because it has no type`); - // show error message to the user - uppy.info(`Skipping file because it has no type`, 'error', 500); - return false; - } - }, -}); -``` - -
- -#### `onBeforeUpload(files)` - -A function called before when upload is initiated (`Function`, default: -`(files) => files`). - -Use this to check if all files or their total number match your requirements, or -manipulate all the files at once before upload. - -You can return `true` to continue the upload, `false` to cancel it, or return -modified files. - -:::caution - -This method is intended for quick synchronous checks and modifications only. If -you need to do an async API call, or heavy work on a file (like compression or -encryption), you should use a [custom plugin](/docs/guides/building-plugins) -instead. - -::: - -:::info - -No notification will be shown to the user about a file not passing validation by -default. We recommend showing a message using -[`uppy.info()`](#infomessage-type-duration) and logging to console for debugging -purposes via [`uppy.log()`](#logmessage-type). - -::: - -
- Change and abort example - -Change all file names: - -```js -const uppy = new Uppy({ - // ... - onBeforeUpload: (files) => { - // We’ll be careful to return a new object, not mutating the original `files` - const updatedFiles = {}; - Object.keys(files).forEach((fileID) => { - updatedFiles[fileID] = { - ...files[fileID], - name: `${myCustomPrefix}__${files[fileID].name}`, - }; - }); - return updatedFiles; - }, -}); -``` - -Abort an upload: - -```js -const uppy = new Uppy({ - // ... - onBeforeUpload: (files) => { - if (Object.keys(files).length < 2) { - // log to console - uppy.log( - `Aborting upload because only ${ - Object.keys(files).length - } files were selected`, - ); - // show error message to the user - uppy.info(`You have to select at least 2 files`, 'error', 500); - return false; - } - return true; - }, -}); -``` - -
- -#### `locale` - -You can override locale strings by passing the `strings` object with the keys -you want to override. - -:::note - -Array indexed objects are used for pluralisation. - -::: - -:::info - -If you want a different language it’s better to use [locales](/docs/locales). - -::: - -```js -module.exports = { - strings: { - addBulkFilesFailed: { - 0: 'Failed to add %{smart_count} file due to an internal error', - 1: 'Failed to add %{smart_count} files due to internal errors', - }, - youCanOnlyUploadX: { - 0: 'You can only upload %{smart_count} file', - 1: 'You can only upload %{smart_count} files', - }, - youHaveToAtLeastSelectX: { - 0: 'You have to select at least %{smart_count} file', - 1: 'You have to select at least %{smart_count} files', - }, - exceedsSize: '%{file} exceeds maximum allowed size of %{size}', - missingRequiredMetaField: 'Missing required meta fields', - missingRequiredMetaFieldOnFile: - 'Missing required meta fields in %{fileName}', - inferiorSize: 'This file is smaller than the allowed size of %{size}', - youCanOnlyUploadFileTypes: 'You can only upload: %{types}', - noMoreFilesAllowed: 'Cannot add more files', - noDuplicates: - "Cannot add the duplicate file '%{fileName}', it already exists", - companionError: 'Connection with Companion failed', - authAborted: 'Authentication aborted', - companionUnauthorizeHint: - 'To unauthorize to your %{provider} account, please go to %{url}', - failedToUpload: 'Failed to upload %{file}', - noInternetConnection: 'No Internet connection', - connectedToInternet: 'Connected to the Internet', - // Strings for remote providers - noFilesFound: 'You have no files or folders here', - selectX: { - 0: 'Select %{smart_count}', - 1: 'Select %{smart_count}', - }, - allFilesFromFolderNamed: 'All files from folder %{name}', - openFolderNamed: 'Open folder %{name}', - cancel: 'Cancel', - logOut: 'Log out', - filter: 'Filter', - resetFilter: 'Reset filter', - loading: 'Loading...', - authenticateWithTitle: - 'Please authenticate with %{pluginName} to select files', - authenticateWith: 'Connect to %{pluginName}', - signInWithGoogle: 'Sign in with Google', - searchImages: 'Search for images', - enterTextToSearch: 'Enter text to search for images', - search: 'Search', - emptyFolderAdded: 'No files were added from empty folder', - folderAlreadyAdded: 'The folder "%{folder}" was already added', - folderAdded: { - 0: 'Added %{smart_count} file from %{folder}', - 1: 'Added %{smart_count} files from %{folder}', - }, - }, -}; -``` - -#### `store` - -The store that is used to keep track of internal state (`Object`, default: -[`DefaultStore`](/docs/guides/custom-stores)). - -This option can be used to plug Uppy state into an external state management -library, such as [Redux](/docs/guides/custom-stores). - -{/* TODO document store API */} - -#### `infoTimeout` - -How long an [Informer](/docs/informer) notification will be visible (`number`, -default: `5000`). - -### Methods - -#### `use(plugin, opts)` - -Add a plugin to Uppy, with an optional plugin options object. - -```js -import Uppy from '@uppy/core'; -import DragDrop from '@uppy/drag-drop'; - -const uppy = new Uppy(); -uppy.use(DragDrop, { target: 'body' }); -``` - -#### `removePlugin(instance)` - -Uninstall and remove a plugin. - -#### `getPlugin(id)` - -Get a plugin by its `id` to access its methods. - -#### `getID()` - -Get the Uppy instance ID, see the [`id`](#id) option. - -#### `addFile(file)` - -Add a new file to Uppy’s internal state. `addFile` will return the generated id -for the file that was added. - -`addFile` gives an error if the file cannot be added, either because -`onBeforeFileAdded(file)` gave an error, or because `uppy.opts.restrictions` -checks failed. - -```js -uppy.addFile({ - name: 'my-file.jpg', // file name - type: 'image/jpeg', // file type - data: blob, // file blob - meta: { - // optional, store the directory path of a file so Uppy can tell identical files in different directories apart. - relativePath: webkitFileSystemEntry.relativePath, - }, - source: 'Local', // optional, determines the source of the file, for example, Instagram. - isRemote: false, // optional, set to true if actual file is not in the browser, but on some remote server, for example, - // when using companion in combination with Instagram. -}); -``` - -:::note - -If you try to add a file that already exists, `addFile` will throw an error. -Unless that duplicate file was dropped with a folder — duplicate files from -different folders are allowed, when selected with that folder. This is because -we add `file.meta.relativePath` to the `file.id`. - -::: - -:::info - -Checkout [working with Uppy files](#working-with-uppy-files). - -::: - -:::info - -If `uppy.opts.autoProceed === true`, Uppy will begin uploading automatically -when files are added. - -::: - -:::info - -Sometimes you might need to add a remote file to Uppy. This can be achieved by -[fetching the file, then creating a Blob object, or using the Url plugin with Companion](https://github.com/transloadit/uppy/issues/1006#issuecomment-413495493). - -::: - -:::info - -Sometimes you might need to mark some files as “already uploaded”, so that the -user sees them, but they won’t actually be uploaded by Uppy. This can be -achieved by -[looping through files and setting `uploadComplete: true, uploadStarted: true` on them](https://github.com/transloadit/uppy/issues/1112#issuecomment-432339569) - -::: - -#### `removeFile(fileID)` - -Remove a file from Uppy. Removing a file that is already being uploaded cancels -that upload. - -```js -uppy.removeFile('uppyteamkongjpg1501851828779'); -``` - -#### `clear()` - -Clear the state. Can be useful for manually resetting Uppy after a successful -upload. Note that this method might throw an error if you try to call it while -an upload is ongoing. - -Upload plugins may choose to throw an error if called during an upload. - -#### `getFile(fileID)` - -Get a specific [Uppy file](#working-with-uppy-files) by its ID. - -```js -const file = uppy.getFile('uppyteamkongjpg1501851828779'); -``` - -#### `getFiles()` - -Get an array of all added [Uppy files](#working-with-uppy-files). - -```js -const files = uppy.getFiles(); -``` - -#### `upload()` - -Start uploading added files. - -Returns a Promise `result` that resolves with an object containing two arrays of -uploaded files: - -- `result.successful` - Files that were uploaded successfully. -- `result.failed` - Files that did not upload successfully. These files will - have a `.error` property describing what went wrong. - -```js -uppy.upload().then((result) => { - console.info('Successful uploads:', result.successful); - - if (result.failed.length > 0) { - console.error('Errors:'); - result.failed.forEach((file) => { - console.error(file.error); - }); - } -}); -``` - -#### `pauseResume(fileID)` - -Toggle pause/resume on an upload. Will only work if resumable upload plugin, -such as [Tus](/docs/tus/), is used. - -#### `pauseAll()` - -Pause all uploads. Will only work if a resumable upload plugin, such as -[Tus](/docs/tus/), is used. - -#### `resumeAll()` - -Resume all uploads. Will only work if resumable upload plugin, such as -[Tus](/docs/tus/), is used. - -#### `retryUpload(fileID)` - -Retry an upload (after an error, for example). - -#### `retryAll()` - -Retry all uploads (after an error, for example). - -#### `cancelAll()` - -Cancel all uploads, reset progress and remove all files. If you are using the -Transloadit plugin, this will also cancel all running assemblies, even after an -upload has finished. - -#### `setState(patch)` - -Update Uppy’s internal state. Usually, this method is called internally, but in -some cases it might be useful to alter something directly, especially when -implementing your own plugins. - -Uppy’s default state on initialization: - -```js -const state = { - plugins: {}, - files: {}, - currentUploads: {}, - capabilities: { - resumableUploads: false, - }, - totalProgress: 0, - meta: { ...this.opts.meta }, - info: { - isHidden: true, - type: 'info', - message: '', - }, -}; -``` - -Updating state: - -```js -uppy.setState({ smth: true }); -``` - -:::note - -State in Uppy is considered to be immutable. When updating values, make sure not -mutate them, but instead create copies. See -[Redux docs](http://redux.js.org/docs/recipes/UsingObjectSpreadOperator.html) -for more info on this. - -::: - -#### `getState()` - -Returns the current state from the [Store](#store). - -#### `setFileState(fileID, state)` - -Update the state for a single file. This is mostly useful for plugins that may -want to store data on [Uppy files](#working-with-uppy-files), or need to pass -file-specific configurations to other plugins that support it. - -`fileID` is the string file ID. `state` is an object that will be merged into -the file’s state object. - -#### `setMeta(data)` - -Alters global `meta` object in state, the one that can be set in Uppy options -and gets merged with all newly added files. Calling `setMeta` will also merge -newly added meta data with files that had been selected before. - -```js -uppy.setMeta({ resize: 1500, token: 'ab5kjfg' }); -``` - -#### `setFileMeta(fileID, data)` - -Update metadata for a specific file. - -```js -uppy.setFileMeta('myfileID', { resize: 1500 }); -``` - -#### `setOptions(opts)` - -Change the options Uppy initialized with. - -```js -const uppy = new Uppy(); - -uppy.setOptions({ - restrictions: { maxNumberOfFiles: 3 }, - autoProceed: true, -}); - -uppy.setOptions({ - locale: { - strings: { - cancel: 'Отмена', - }, - }, -}); -``` - -You can also change options for plugin: - -```js -// Change width of the Dashboard drag-and-drop aread on the fly -uppy.getPlugin('Dashboard').setOptions({ - width: 300, -}); -``` - -#### `destroy()` - -Uninstall all plugins and close down this Uppy instance. Also runs -`uppy.cancelAll()` before uninstalling. Note that this method should not -normally be used. If you only want reset the Uppy instance so that you can start -a new upload, you probably want to use `clear()` method instead. - -#### `logout()` - -Calls `provider.logout()` on each remote provider plugin (Google Drive, -Instagram, etc). Useful, for example, after your users log out of their account -in your app — this will clean things up with Uppy cloud providers as well, for -extra security. - -#### `log(message, type)` - -| Argument | Type | Description | -| --------- | --------- | --------------------------- | -| `message` | `string` | message to log | -| `type` | `string?` | `debug`, `warn`, or `error` | - -See [`logger`](#logger) docs for details. - -```js -uppy.log('[Dashboard] adding files...'); -``` - -#### `info(message, type, duration)` - -Sets a message in state, with optional details, that can be shown by -notification UI plugins. It’s using the [Informer](/docs/informer) plugin, -included by default in Dashboard. - -| Argument | Type | Description | -| ---------- | ------------------ | --------------------------------------------------------------------------------- | -| `message` | `string`, `Object` | `'info message'` or `{ message: 'Oh no!', details: 'File couldn’t be uploaded' }` | -| `type` | `string?` | `'info'`, `'warning'`, `'success'` or `'error'` | -| `duration` | `number?` | in milliseconds | - -`info-visible` and `info-hidden` events are emitted when this info message -should be visible or hidden. - -```js -this.info('Oh my, something good happened!', 'success', 3000); -``` - -```js -this.info( - { - message: 'Oh no, something bad happened!', - details: - 'File couldn’t be uploaded because there is no internet connection', - }, - 'error', - 5000, -); -``` - -#### `addPreProcessor(fn)` - -Add a preprocessing function. `fn` gets called with a list of file IDs before an -upload starts. `fn` should return a Promise. Its resolution value is ignored. - -:::info - -To change file data and such, use Uppy state updates, for example using -[`setFileState`](#setfilestatefileid-state). - -::: - -#### `addUploader(fn)` - -Add an uploader function. `fn` gets called with a list of file IDs when an -upload should start. Uploader functions should do the actual uploading work, -such as creating and sending an XMLHttpRequest or calling into some upload -service SDK. `fn` should return a Promise that resolves once all files have been -uploaded. - -:::tip - -You may choose to still resolve the Promise if some file uploads fail. This way, -any postprocessing will still run on the files that were uploaded successfully, -while uploads that failed will be retried when [`retryAll`](#retryall) is -called. - -::: - -#### `addPostProcessor(fn)` - -Add a postprocessing function. `fn` is called with a list of file IDs when an -upload has finished. `fn` should return a Promise that resolves when the -processing work is complete. The value of the Promise is ignored. - -For example, you could wait for file encoding or CDN propagation to complete, or -you could do an HTTP API call to create an album containing all images that were -uploaded. - -#### `removePreProcessor/removeUploader/removePostProcessor(fn)` - -Remove a processor or uploader function that was added before. Normally, this -should be done in the [`uninstall()`](#uninstall) method. - -#### `on('event', action)` - -Subscribe to an uppy-event. See below for the full list of events. - -#### `once('event', action)` - -Create an event listener that fires once. See below for the full list of events. - -#### `off('event', action)` - -Unsubscribe to an uppy-event. See below for the full list of events. - -### Events - -Uppy exposes events that you can subscribe to for side-effects. - -#### `file-added` - -Fired each time a file is added. - -**Parameters** - -- `file` - The [Uppy file](#working-with-uppy-files) that was added. - -```js -uppy.on('file-added', (file) => { - console.log('Added file', file); -}); -``` - -#### `files-added` - -**Parameters** - -- `files` - Array of [Uppy files](#working-with-uppy-files) which were added at - once, in a batch. - -Fired each time when one or more files are added — one event, for all files - -#### `file-removed` - -Fired each time a file is removed. - -**Parameters** - -- `file` - The [Uppy file](#working-with-uppy-files) that was removed. - -**Example** - -```js -uppy.on('file-removed', (file) => { - console.log('Removed file', file); -}); -``` - -```js -uppy.on('file-removed', (file) => { - removeFileFromUploadingCounterUI(file); - sendDeleteRequestForFile(file); -}); -``` - -#### `upload` - -Fired when the upload starts. - -**Parameters** - -- `uploadID` (`string)` -- `files` (`UppyFile`) - -#### `preprocess-progress` - -Progress of the pre-processors. - -**Parameters** - -`progress` is an object with properties: - -- `mode` - Either `'determinate'` or `'indeterminate'`. -- `message` - A message to show to the user. Something like - `'Preparing upload...'`, but be more specific if possible. - -When `mode` is `'determinate'`, also add the `value` property: - -- `value` - A progress value between 0 and 1. - -#### `progress` - -Fired each time the total upload progress is updated: - -**Parameters** - -- `progress` - An integer (0-100) representing the total upload progress. - -**Example** - -```js -uppy.on('progress', (progress) => { - // progress: integer (total progress percentage) - console.log(progress); -}); -``` - -#### `upload-progress` - -Fired each time an individual file upload progress is available: - -**Parameters** - -- `file` - The [Uppy file](#working-with-uppy-files) that has progressed. -- `progress` - The same object as in `file.progress`. - -**Example** - -```js -uppy.on('upload-progress', (file, progress) => { - // file: { id, name, type, ... } - // progress: { uploader, bytesUploaded, bytesTotal } - console.log(file.id, progress.bytesUploaded, progress.bytesTotal); -}); -``` - -#### `upload-pause` - -Fired when an individual upload is (un)paused. - -**Parameters** - -- `file` (`UppyFile`) -- `isPaused` (`boolean`) - -#### `postprocess-progress` - -Progress of the post-processors. - -**Parameters** - -`progress` is an object with properties: - -- `mode` - Either `'determinate'` or `'indeterminate'`. -- `message` - A message to show to the user. Something like - `'Preparing upload...'`, but be more specific if possible. - -When `mode` is `'determinate'`, also add the `value` property: - -- `value` - A progress value between 0 and 1. - -#### `upload-success` - -Fired each time a single upload is completed. - -**Parameters** - -- `file` - The [Uppy file](#working-with-uppy-files) that was uploaded. -- `response` - An object with response data from the remote endpoint. The actual - contents depend on the upload plugin that is used. - -For `@uppy/xhr-upload`, the shape is: - -```json -{ - "status": 200, // HTTP status code (0, 200, 300) - "body": "…", // response body - "uploadURL": "…" // the file url, if it was returned -} -``` - -**Example** - -```js -uppy.on('upload-success', (file, response) => { - console.log(file.name, response.uploadURL); - const img = new Image(); - img.width = 300; - img.alt = file.id; - img.src = response.uploadURL; - document.body.appendChild(img); -}); -``` - -#### `complete` - -Fired when all uploads are complete. - -The `result` parameter is an object with arrays of `successful` and `failed` -files, as in [`uppy.upload()`](#upload)’s return value. - -```js -uppy.on('complete', (result) => { - console.log('successful files:', result.successful); - console.log('failed files:', result.failed); -}); -``` - -#### `error` - -Fired when Uppy fails to upload/encode the entire upload. - -**Parameters** - -- `error` - The error object. - -**Example** - -```js -uppy.on('error', (error) => { - console.error(error.stack); -}); -``` - -#### `upload-error` - -Fired each time a single upload failed. - -**Parameters** - -- `file` - The [Uppy file](#working-with-uppy-files) which didn’t upload. -- `error` - The error object. -- `response` - an optional parameter with response data from the upload - endpoint. - -It may be undefined or contain different data depending on the upload plugin in -use. - -For `@uppy/xhr-upload`, the shape is: - -```json -{ - "status": 200, // HTTP status code (0, 200, 300) - "body": "…" // response body -} -``` - -**Example** - -```js -uppy.on('upload-error', (file, error, response) => { - console.log('error with file:', file.id); - console.log('error message:', error); -}); -``` - -If the error is related to network conditions — endpoint unreachable due to -firewall or ISP blockage, for instance — the error will have -`error.isNetworkError` property set to `true`. Here’s how you can check for -network errors: - -```js -uppy.on('upload-error', (file, error, response) => { - if (error.isNetworkError) { - // Let your users know that file upload could have failed - // due to firewall or ISP issues - alertUserAboutPossibleFirewallOrISPIssues(error); - } -}); -``` - -#### `upload-retry` - -Fired when an upload has been retried (after an error, for example). - -:::note - -This event is not triggered when the user retries all uploads, it will trigger -the `retry-all` event instead. - -::: - -**Parameters** - -- `file` (`UppyFile`) - -**Example** - -```js -uppy.on('upload-retry', (fileID) => { - console.log('upload retried:', fileID); -}); -``` - -#### `upload-stalled` - -Fired when an upload has not received any progress in some time (in -`@uppy/xhr-upload`, the delay is defined by the `timeout` option). Use this -event to display a message on the UI to tell the user they might want to retry -the upload. - -```js -uppy.on('upload-stalled', (error, files) => { - console.log('upload seems stalled', error, files); - const noLongerStalledEventHandler = (file) => { - if (files.includes(file)) { - console.log('upload is no longer stalled'); - uppy.off('upload-progress', noLongerStalledEventHandler); - } - }; - uppy.on('upload-progress', noLongerStalledEventHandler); -}); -``` - -#### `retry-all` - -Fired when all failed uploads are retried - -**Parameters** - -- `files` (`UppyFile[]`) - -**Example** - -```js -uppy.on('retry-all', (fileIDs) => { - console.log('upload retried:', fileIDs); -}); -``` - -#### `info-visible` - -Fired when “info” message should be visible in the UI. By default, `Informer` -plugin is displaying these messages (enabled by default in `Dashboard` plugin). -You can use this event to show messages in your custom UI: - -```js -uppy.on('info-visible', () => { - const { info } = uppy.getState(); - // info: { - // isHidden: false, - // type: 'error', - // message: 'Failed to upload', - // details: 'Error description' - // } - console.log(`${info.message} ${info.details}`); -}); -``` - -#### `info-hidden` - -Fired when “info” message should be hidden in the UI. See -[`info-visible`](#info-visible). - -#### `cancel-all` - -Fired when `cancelAll()` is called, all uploads are canceled, files removed and -progress is reset. - -#### `restriction-failed` - -Fired when a file violates certain restrictions when added. This event is -providing another choice for those who want to customize the behavior of file -upload restrictions. - -```js -uppy.on('restriction-failed', (file, error) => { - // do some customized logic like showing system notice to users -}); -``` - -## `new BasePlugin(uppy, options?)` - -The initial building block for a plugin. - -`BasePlugin` does not contain DOM rendering so it can be used for plugins -without an user interface. - -:::info - -See [`UIPlugin`][] for the extended version with Preact rendering for -interfaces. - -::: - -:::info - -Checkout the [building plugins](/docs/guides/building-plugins) guide. - -::: - -:::note - -If you don’t use any UI plugins, any modern bundler should be able to tree-shake -Preact code away. If you are not using a bundler that supports tree-shaking, -it’s also possible to import `BasePlugin` like this: -`import BasePlugin from '@uppy/core/lib/BasePlugin.js`. - -::: - -### Options - -The options passed to `BasePlugin` are all you options you wish to support in -your plugin. - -You should pass the options to `super` in your plugin class: - -```js -class MyPlugin extends BasePlugin { - constructor(uppy, opts) { - super(uppy, opts); - } -} -``` - -### Methods - -#### `setOptions(options)` - -Options passed during initialization can also be altered dynamically with -`setOptions`. - -#### `getPluginState()` - -Retrieves the plugin state from the `Uppy` class. Uppy keeps a `plugins` object -in state in which each key is the plugin’s `id`, and the value its state. - -#### `setPluginState()` - -Set the plugin state in the `Uppy` class. Uppy keeps a `plugins` object in state -in which each key is the plugin’s `id`, and the value its state. - -#### `install()` - -The `install` method is ran once, when the plugin is added to Uppy with -`.use()`. Use this to initialize the plugin. - -For example, if you are creating a pre-processor (such as -[@uppy/compressor](/docs/compressor)) you must add it: - -```js -install () { - this.uppy.addPreProcessor(this.prepareUpload) -} -``` - -Another common thing to do when creating a -[UI plugin](#new-uipluginuppy-options) is to [`mount`](#mounttarget) it to the -DOM: - -```js -install () { - const { target } = this.opts - if (target) { - this.mount(target, this) - } -} -``` - -#### `uninstall()` - -The `uninstall` method is ran once, when the plugin is removed from Uppy. This -happens when `.close()` is called or when the plugin is destroyed in a framework -integration. - -Use this to clean things up. - -For instance when creating a pre-processor, uploader, or post-processor to -remove it: - -```js -uninstall () { - this.uppy.removePreProcessor(this.prepareUpload) -} -``` - -When creating a [UI plugin](#new-uipluginuppy-options) you should -[`unmount`](#unmount) it from the DOM: - -```js -uninstall () { - this.unmount() -} -``` - -#### `i18nInit` - -Call `this.i18nInit()` once in the constructor of your plugin class to -initialize [internationalisation](/docs/locales). - -#### `addTarget` - -You can use this method to make your plugin a `target` for other plugins. This -is what `@uppy/dashboard` uses to add other plugins to its UI. - -#### `update` - -Called on each state update. You will rarely need to use this, unless if you -want to build a UI plugin using something other than Preact. - -#### `afterUpdate` - -Called after every state update with a debounce, after everything has mounted. - -## `new UIPlugin(uppy, options?)` - -`UIPlugin` extends [`BasePlugin`][] to add rendering with -[Preact](https://preactjs.com/). Use this when you want to create an user -interface or an addition to one, such as [Dashboard][]. - -:::info - -See [`BasePlugin`][] for the initial building block for all plugins. - -::: - -:::info - -Checkout the [building plugins](/docs/guides/building-plugins) guide. - -::: - -### Options - -The options passed to `UIPlugin` are all you options you wish to support in your -plugin. - -You should pass the options to `super` in your plugin class: - -```js -class MyPlugin extends UIPlugin { - constructor(uppy, opts) { - super(uppy, opts); - } -} -``` - -In turn these are also passed to the underlying `BasePlugin`. - -### Methods - -All the methods from [`BasePlugin`][] are also inherited into `UIPlugin`. - -#### `mount(target)` - -Mount this plugin to the `target` element. `target` can be a CSS query selector, -a DOM element, or another Plugin. If `target` is a Plugin, the source (current) -plugin will register with the target plugin, and the latter can decide how and -where to render the source plugin. - -#### `onMount()` - -Called after Preact has rendered the components of the plugin. - -#### `unmount` - -Removing the plugin from the DOM. You generally don’t need to override it but -you should call it from [`uninstall`](#uninstall). - -The default is: - -```js -unmount () { - if (this.isTargetDOMEl) { - this.el?.remove() - } - this.onUnmount() -} -``` - -#### `onUnmount()` - -Called after the elements have been removed from the DOM. Can be used to do some -clean up or other side-effects. - -#### `render()` - -Render the UI of the plugin. Uppy uses [Preact](https://preactjs.com) as its -view engine, so `render()` should return a Preact element. `render` is -automatically called by Uppy on each state change. - -#### `update(state)` - -Called on each state update. You will rarely need to use this, unless if you -want to build a UI plugin using something other than Preact. - -## `debugLogger()` - -Logger with extra debug and warning logs for during development. - -```js -import { Uppy, debugLogger } from '@uppy/core'; - -new Uppy({ logger: debugLogger }); -``` - -:::info - -You can also enable this logger by setting [`debug`](#debug) to `true`. - -::: - -The default value of [`logger`](#logger) is `justErrorsLogger`, which looks like -this: - -```js -// Swallow all logs, except errors. -// default if logger is not set or debug: false -const justErrorsLogger = { - debug: () => {}, - warn: () => {}, - error: (...args) => console.error(`[Uppy] [${getTimeStamp()}]`, ...args), -}; -``` - -`debugLogger` sends extra debugging and warning logs which could be helpful -during development: - -```js -// Print logs to console with namespace + timestamp, -// set by logger: Uppy.debugLogger or debug: true -const debugLogger = { - debug: (...args) => console.debug(`[Uppy] [${getTimeStamp()}]`, ...args), - warn: (...args) => console.warn(`[Uppy] [${getTimeStamp()}]`, ...args), - error: (...args) => console.error(`[Uppy] [${getTimeStamp()}]`, ...args), -}; -``` - -## Frequently asked questions - -### How do I allow duplicate files? - -You can allow all files, even duplicate files, with -[`onBeforeFileAdded`](#onbeforefileadded). This will override the file if it has -not been uploaded. If you upload a duplicate file again it depends on your -upload plugin and backend how it is handled. - -```js -const uppy = new Uppy({ - // ... - onBeforeFileAdded: () => true, -``` - -[dashboard]: /docs/dashboard -[`baseplugin`]: #new-basepluginuppy-options -[`uiplugin`]: #new-uipluginuppy-options diff --git a/docs/user-interfaces/_category_.json b/docs/user-interfaces/_category_.json deleted file mode 100644 index 7ffa7b4ce4..0000000000 --- a/docs/user-interfaces/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "User interfaces", - "position": 5 -} diff --git a/docs/user-interfaces/dashboard.mdx b/docs/user-interfaces/dashboard.mdx deleted file mode 100644 index 340efbd4e4..0000000000 --- a/docs/user-interfaces/dashboard.mdx +++ /dev/null @@ -1,755 +0,0 @@ ---- -sidebar_position: 1 -slug: /dashboard ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Dashboard - -The all you need Dashboard — powerful, responsive, and pluggable. Kickstart your -uploading experience and gradually add more functionality. Add files from -[remote sources](/docs/companion), [edit images](/docs/image-editor), -[generate thumbnails](/docs/thumbnail-generator), and more. - -Checkout [integrations](#integrations) for the full list of plugins you can -integrate. - -:::tip - -[Try out the live example with all plugins](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-zaqyaf?file=main.js). - -::: - -## When should I use this? - -There could be many reasons why you may want to use the Dashboard, but some -could be: - -- when you need a battle tested plug-and-play uploading UI to save time. -- when your users need to add files from [remote sources](/docs/companion), such - [Google Drive](/docs/google-drive), [Dropbox](/docs/dropbox), and others. -- when you need to collect [meta data](#metafields) from your users per file. -- when your users want to take a picture with their [webcam](/docs/webcam) or - [capture their screen](/docs/screen-capture). - -## Install - - - - -```shell -npm install @uppy/core @uppy/dashboard -``` - - - - - -```shell -yarn add @uppy/core @uppy/dashboard -``` - - - - - - {` - import { Uppy, Dashboard } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Dashboard, { target: '#uppy', inline: true }) - `} - - - - -## Use - -```js showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; - -new Uppy().use(Dashboard, { inline: true, target: '#uppy-dashboard' }); -``` - -:::note - -The `@uppy/dashboard` plugin includes CSS for the Dashboard itself, and the -various plugins used by the Dashboard, such as -([`@uppy/status-bar`](/docs/status-bar) and [`@uppy/informer`](/docs/informer)). -If you also use the `@uppy/status-bar` or `@uppy/informer` plugin directly, you -should not include their CSS files, but instead only use the one from the -`@uppy/dashboard` plugin. - -::: - -:::note - -Styles for Provider plugins, like Google Drive and Instagram, are also bundled -with Dashboard styles. Styles for other plugins, such as `@uppy/url` and -`@uppy/webcam`, are not included. If you are using those, please see their docs -and make sure to include styles for them as well. - -::: - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'Dashboard'`). - -Plugins that are added by the Dashboard get unique IDs based on this ID, like -`'Dashboard:StatusBar'` and `'Dashboard:Informer'`. - -#### `target` - -Where to render the Dashboard (`string` or `Element`, default: `'body'`). - -You can pass an element, class, or id as a string. Dashboard is rendered into -`body`, because it’s hidden by default and only opened as a modal when `trigger` -is clicked. - -#### `inline` - -Render the Dashboard as a modal or inline (`boolean`, default: `false`). - -When `false`, Dashboard is opened by clicking on [`trigger`](#trigger). If -`inline: true`, Dashboard will be rendered into [`target`](#target) and fit -right in. - -#### `trigger` - -A CSS selector for a button that will trigger opening the Dashboard modal -(`string`, default: `null`). - -Several buttons or links can be used, as long as they are selected using the -same selector (`.select-file-button`, for example). - -#### `width` - -Width of the Dashboard in pixels (`number`, default: `750`). Used when -`inline: true`. - -#### `height` - -Height of the Dashboard in pixels (`number`, default: `550`). Used when -`inline: true`. - -#### `waitForThumbnailsBeforeUpload` - -Whether to wait for all thumbnails from `@uppy/thumbnail-generator` to be ready -before starting the upload (`boolean`, default `false`). - -If set to `true`, Thumbnail Generator will envoke Uppy’s internal processing -stage, displaying “Generating thumbnails...” message, and wait for -`thumbnail:all-generated` event, before proceeding to the uploading stage. - -This is useful because Thumbnail Generator also adds EXIF data to images, and if -we wait until it’s done processing, this data will be available on the server -after the upload. - -#### `showLinkToFileUploadResult` - -Turn the file icon and thumbnail in the Dashboard into a link to the uploaded -file (`boolean`, default: `false`). - -Please make sure to return the `url` key (or the one set via -`responseUrlFieldName`) from your server. - -#### `showProgressDetails` - -Show or hide progress details in the status bar (`boolean`, default: `false`). - -By default, progress in Status Bar is shown as a percentage. If you would like -to also display remaining upload size and time, set this to `true`. - -`showProgressDetails: false`: Uploading: 45% - -`showProgressDetails: true`: Uploading: 45%・43 MB of 101 MB・8s left - -#### `hideUploadButton` - -Show or hide the upload button (`boolean`, default: `false`). - -Use this if you are providing a custom upload button somewhere, and are using -the `uppy.upload()` API. - -#### `hideRetryButton` - -Hide the retry button in the status bar and on each individual file (`boolean`, -default: `false`). - -Use this if you are providing a custom retry button somewhere and if you are -using the `uppy.retryAll()` or `uppy.retryUpload(fileID)` API. - -#### `hidePauseResumeButton` - -Hide the pause/resume button (for resumable uploads, via [tus](http://tus.io), -for example) in the status bar and on each individual file (`boolean`, default: -`false`). - -Use this if you are providing custom cancel or pause/resume buttons somewhere, -and using the `uppy.pauseResume(fileID)` or `uppy.removeFile(fileID)` API. - -#### `hideCancelButton` - -Hide the cancel button in status bar and on each individual file (`boolean`, -default: `false`). - -Use this if you are providing a custom retry button somewhere, and using the -`uppy.cancelAll()` API. - -#### `hideProgressAfterFinish` - -Hide the status bar after the upload has finished (`boolean`, default: `false`). - -#### `doneButtonHandler` - -This option is passed to the status bar and will render a “Done” button in place -of pause/resume/cancel buttons, once the upload/encoding is done. The behaviour -of this “Done” button is defined by this handler function, for instance to close -the file picker modals or clear the upload state. - -This is what the Dashboard sets by default: - -```js -const doneButtonHandler = () => { - this.uppy.cancelAll(); - this.requestCloseModal(); -}; -``` - -Set to `null` to disable the “Done” button. - -#### `showSelectedFiles` - -Show the list of added files with a preview and file information (`boolean`, -default: `true`). - -In case you are showing selected files in your own app’s UI and want the Uppy -Dashboard to only be a picker, the list can be hidden with this option. - -See also [`disableStatusBar`](#disablestatusbar) option, which can hide the -progress and upload button. - -#### `showRemoveButtonAfterComplete` - -Show the remove button on every file after a successful upload (`boolean`, -default: `false`). - -Enabling this option only shows the remove `X` button in the Dashboard UI, but -to actually send a request you should listen to -[`file-removed`](https://uppy.io/docs/uppy/#file-removed) event and add your -logic there. - -Example: - -```js -uppy.on('file-removed', (file, reason) => { - if (reason === 'removed-by-user') { - sendDeleteRequestForFile(file); - } -}); -``` - -For an implementation example, please see -[#2301](https://github.com/transloadit/uppy/issues/2301#issue-628931176). - -#### `singleFileFullScreen` - -When only one file is selected, its preview and meta information will be -centered and enlarged (`boolean`, default: `true`). - -Often times Uppy used for photo / profile image uploads, or maybe a single -document. Then it makes sense to occupy the whole space of the available -Dashboard UI, giving the stage to this one file. This feature is automatically -disabled when Dashboard is small in height, since there’s not enough room. - -#### `note` - -A string of text to be placed in the Dashboard UI (`string`, default: `null`). - -This could for instance be used to explain any [`restrictions`](#restrictions) -that are put in place. For example: -`'Images and video only, 2–3 files, up to 1 MB'`. - -#### `metaFields` - -Create text or custom input fields for the user to fill in (`Array` or -`Function`, default: `null`). - -This will be shown when a user clicks the “edit” button on that file. - -:::note - -The meta data will only be set on a file object if it’s entered by the user. If -the user doesn’t edit a file’s metadata, it will not have default values; -instead everything will be `undefined`. If you want to set a certain meta field -to each file regardless of user actions, set -[`meta` in the Uppy constructor options](/docs/uppy/#meta). - -::: - -Each object can contain: - -- `id`. The name of the meta field. This will also be used in CSS/HTML as part - of the `id` attribute, so it’s better to - [avoid using characters like periods, semicolons, etc](https://stackoverflow.com/a/79022). -- `name`. The label shown in the interface. -- `placeholder`. The text shown when no value is set in the field. (Not needed - when a custom render function is provided) -- `render: ({value, onChange, required, form}, h) => void` (optional). A - function for rendering a custom form element. - - `value` is the current value of the meta field - - `onChange: (newVal) => void` is a function saving the new value and `h` is - the `createElement` function from - [Preact](https://preactjs.com/guide/v10/api-reference#h--createelement). - - `required` is a boolean that’s true if the field `id` is in the - `restrictedMetaFields` restriction - - `form` is the `id` of the associated `` element. - - `h` can be useful when using Uppy from plain JavaScript, where you cannot - write JSX. - -
-Example: meta fields configured as an `Array` - -```js -uppy.use(Dashboard, { - trigger: '#pick-files', - metaFields: [ - { id: 'name', name: 'Name', placeholder: 'file name' }, - { id: 'license', name: 'License', placeholder: 'specify license' }, - { - id: 'caption', - name: 'Caption', - placeholder: 'describe what the image is about', - }, - { - id: 'public', - name: 'Public', - render({ value, onChange, required, form }, h) { - return h('input', { - type: 'checkbox', - required, - form, - onChange: (ev) => onChange(ev.target.checked ? 'on' : ''), - defaultChecked: value === 'on', - }); - }, - }, - ], -}); -``` - -
- -
-Example: dynamic meta fields based on file type with a `Function` - -```js -uppy.use(Dashboard, { - trigger: '#pick-files', - metaFields: (file) => { - const fields = [{ id: 'name', name: 'File name' }]; - if (file.type.startsWith('image/')) { - fields.push({ id: 'location', name: 'Photo Location' }); - fields.push({ id: 'alt', name: 'Alt text' }); - fields.push({ - id: 'public', - name: 'Public', - render: ({ value, onChange, required, form }, h) => { - return h('input', { - type: 'checkbox', - onChange: (ev) => onChange(ev.target.checked ? 'on' : ''), - defaultChecked: value === 'on', - required, - form, - }); - }, - }); - } - return fields; - }, -}); -``` - -
- -#### `closeModalOnClickOutside` - -Set to true to automatically close the modal when the user clicks outside of it -(`boolean`, default: `false`). - -#### `closeAfterFinish` - -Set to true to automatically close the modal when all current uploads are -complete (`boolean`, default: `false`). - -With this option, the modal is only automatically closed when uploads are -complete _and successful_. If some uploads failed, the modal stays open so the -user can retry failed uploads or cancel the current batch and upload an entirely -different set of files instead. - -:::info - -You can use this together with the -[`allowMultipleUploads: false`](/docs/uppy/#allowmultipleuploads) option in Uppy -Core to create a smooth experience when uploading a single (batch of) file(s). - -This is recommended. With several upload batches, the auto-closing behavior can -be quite confusing for users. - -::: - -#### `disablePageScrollWhenModalOpen` - -Disable page scroll when the modal is open (`boolean`, default: `true`). - -Page scrolling is disabled by default when the Dashboard modal is open, so when -you scroll a list of files in Uppy, the website in the background stays still. -Set to false to override this behaviour and leave page scrolling intact. - -#### `animateOpenClose` - -Add animations when the modal dialog is opened or closed, for a more satisfying -user experience (`boolean`, default: `true`). - -#### `fileManagerSelectionType` - -Configure the type of selections allowed when browsing your file system via the -file manager selection window (`string`, default: `'files'`). - -May be either `'files'`, `'folders'`, or `'both'`. Selecting entire folders for -upload may not be supported on all -[browsers](https://caniuse.com/#feat=input-file-directory). - -#### `proudlyDisplayPoweredByUppy` - -Show the Uppy logo with a link (`boolean`, default: `true`). - -Uppy is provided to the world for free by the team behind -[Transloadit](https://transloadit.com). In return, we ask that you consider -keeping a tiny Uppy logo at the bottom of the Dashboard, so that more people can -discover and use Uppy. - -#### `disableStatusBar` - -Disable the status bar completely (`boolean`, default: `false`). - -Dashboard ships with the `StatusBar` plugin that shows upload progress and -pause/resume/cancel buttons. If you want, you can disable the StatusBar to -provide your own custom solution. - -#### `disableInformer` - -Disable informer (shows notifications in the form of toasts) completely -(`boolean`, default: `false`). - -Dashboard ships with the `Informer` plugin that notifies when the browser is -offline, or when it’s time to say cheese if `Webcam` is taking a picture. If you -want, you can disable the Informer and/or provide your own custom solution. - -#### `disableThumbnailGenerator` - -Disable the thumbnail generator completely (`boolean`, default: `false`). - -Dashboard ships with the `ThumbnailGenerator` plugin that adds small resized -image thumbnails to images, for preview purposes only. If you want, you can -disable the `ThumbnailGenerator` and/or provide your own custom solution. - -#### `locale` - -```js -module.exports = { - strings: { - // When `inline: false`, used as the screen reader label for the button that closes the modal. - closeModal: 'Close Modal', - // Used as the screen reader label for the plus (+) button that shows the “Add more files” screen - addMoreFiles: 'Add more files', - addingMoreFiles: 'Adding more files', - // Used as the header for import panels, e.g., “Import from Google Drive”. - importFrom: 'Import from %{name}', - // When `inline: false`, used as the screen reader label for the dashboard modal. - dashboardWindowTitle: 'Uppy Dashboard Window (Press escape to close)', - // When `inline: true`, used as the screen reader label for the dashboard area. - dashboardTitle: 'Uppy Dashboard', - // Shown in the Informer when a link to a file was copied to the clipboard. - copyLinkToClipboardSuccess: 'Link copied to clipboard.', - // Used when a link cannot be copied automatically — the user has to select the text from the - // input element below this string. - copyLinkToClipboardFallback: 'Copy the URL below', - // Used as the hover title and screen reader label for buttons that copy a file link. - copyLink: 'Copy link', - back: 'Back', - // Used as the screen reader label for buttons that remove a file. - removeFile: 'Remove file', - // Used as the screen reader label for buttons that open the metadata editor panel for a file. - editFile: 'Edit file', - // Shown in the panel header for the metadata editor. Rendered as “Editing image.png”. - editing: 'Editing %{file}', - // Used as the screen reader label for the button that saves metadata edits and returns to the - // file list view. - finishEditingFile: 'Finish editing file', - saveChanges: 'Save changes', - // Used as the label for the tab button that opens the system file selection dialog. - myDevice: 'My Device', - dropHint: 'Drop your files here', - // Used as the hover text and screen reader label for file progress indicators when - // they have been fully uploaded. - uploadComplete: 'Upload complete', - uploadPaused: 'Upload paused', - // Used as the hover text and screen reader label for the buttons to resume paused uploads. - resumeUpload: 'Resume upload', - // Used as the hover text and screen reader label for the buttons to pause uploads. - pauseUpload: 'Pause upload', - // Used as the hover text and screen reader label for the buttons to retry failed uploads. - retryUpload: 'Retry upload', - // Used as the hover text and screen reader label for the buttons to cancel uploads. - cancelUpload: 'Cancel upload', - // Used in a title, how many files are currently selected - xFilesSelected: { - 0: '%{smart_count} file selected', - 1: '%{smart_count} files selected', - }, - uploadingXFiles: { - 0: 'Uploading %{smart_count} file', - 1: 'Uploading %{smart_count} files', - }, - processingXFiles: { - 0: 'Processing %{smart_count} file', - 1: 'Processing %{smart_count} files', - }, - // The "powered by Uppy" link at the bottom of the Dashboard. - poweredBy: 'Powered by %{uppy}', - addMore: 'Add more', - editFileWithFilename: 'Edit file %{file}', - save: 'Save', - cancel: 'Cancel', - dropPasteFiles: 'Drop files here or %{browseFiles}', - dropPasteFolders: 'Drop files here or %{browseFolders}', - dropPasteBoth: 'Drop files here, %{browseFiles} or %{browseFolders}', - dropPasteImportFiles: 'Drop files here, %{browseFiles} or import from:', - dropPasteImportFolders: 'Drop files here, %{browseFolders} or import from:', - dropPasteImportBoth: - 'Drop files here, %{browseFiles}, %{browseFolders} or import from:', - importFiles: 'Import files from:', - browseFiles: 'browse files', - browseFolders: 'browse folders', - recoveredXFiles: { - 0: 'We could not fully recover 1 file. Please re-select it and resume the upload.', - 1: 'We could not fully recover %{smart_count} files. Please re-select them and resume the upload.', - }, - recoveredAllFiles: 'We restored all files. You can now resume the upload.', - sessionRestored: 'Session restored', - reSelect: 'Re-select', - missingRequiredMetaFields: { - 0: 'Missing required meta field: %{fields}.', - 1: 'Missing required meta fields: %{fields}.', - }, - }, -}; -``` - -#### `theme` - -Light or dark theme for the Dashboard (`string`, default: `'light'`). - -Uppy Dashboard supports “Dark Mode”. You can try it live on -[the Dashboard example page](https://uppy.io/examples/). - -It supports the following values: - -- `light` — the default -- `dark` -- `auto` — will respect the user’s system settings and switch automatically - -#### `autoOpen` - -Automatically open file editor for the file user just dropped/selected. -If one file is added, editor opens for that file; if 10 files are added, editor -opens only for the first file. - -This option supports the following values: - -- `null` - the default -- `"metaEditor"` - open the meta fields editor if - [meta fields](/docs/dashboard/#metafields) are enabled. -- `"imageEditor"` - open [`@uppy/image-editor`](/docs/image-editor) if the - plugin is enabled. - -#### `disabled` - -Enabling this option makes the Dashboard grayed-out and non-interactive -(`boolean`, default: `false`). - -Users won’t be able to click on buttons or drop files. Useful when you need to -conditionally enable/disable file uploading or manipulation, based on a -condition in your app. Can be set on init or via API: - -```js -const dashboard = uppy.getPlugin('Dashboard'); -dashboard.setOptions({ disabled: true }); - -userNameInput.addEventListener('change', () => { - dashboard.setOptions({ disabled: false }); -}); -``` - -#### `disableLocalFiles` - -Disable local files (`boolean`, default: `false`). - -Enabling this option will disable drag & drop, hide the “browse” and “My Device” -button, allowing only uploads from plugins, such as Webcam, Screen Capture, -Google Drive, Instagram. - -#### `onDragOver(event)` - -Callback for the [`ondragover`][ondragover] event handler. - -#### `onDrop(event)` - -Callback for the [`ondrop`][ondrop] event handler. - -#### `onDragLeave(event)` - -Callback for the [`ondragleave`][ondragleave] event handler. - -### Methods - -:::info - -Dashboard also has the methods described in -[`UIPlugin`](/docs/uppy#new-uipluginuppy-options) and -[`BasePlugin`](/docs/uppy#new-basepluginuppy-options). - -::: - -#### `openModal()` - -Shows the Dashboard modal. Use it like this: - -`uppy.getPlugin('Dashboard').openModal()` - -#### `closeModal()` - -Hides the Dashboard modal. Use it like this: - -`uppy.getPlugin('Dashboard').closeModal()` - -#### `isModalOpen()` - -Returns `true` if the Dashboard modal is open, `false` otherwise. - -```js -const dashboard = uppy.getPlugin('Dashboard'); -if (dashboard.isModalOpen()) { - dashboard.closeModal(); -} -``` - -### Events - -:::info - -You can use [`on`](/docs/uppy#onevent-action) and -[`once`](/docs/uppy#onceevent-action) to listen to these events. - -::: - -#### `dashboard:modal-open` - -Fired when the Dashboard modal is open. - -```js -uppy.on('dashboard:modal-open', () => { - console.log('Modal is open'); -}); -``` - -#### `dashboard:modal-closed` - -Fired when the Dashboard modal is closed. - -#### `dashboard:file-edit-start` - -**Parameters:** - -- `file` — The [File Object](https://uppy.io/docs/uppy/#File-Objects) - representing the file that was opened for editing. - -Fired when the user clicks “edit” icon next to a file in the Dashboard. The -FileCard panel is then open with file metadata available for editing. - -#### `dashboard:file-edit-complete` - -**Parameters:** - -- `file` — The [File Object](https://uppy.io/docs/uppy/#File-Objects) - representing the file that was edited. - -Fired when the user finished editing the file metadata. - -## Integrations - -These are the plugins specifically made for the Dashboard. This is not a list of -all Uppy plugins. - -### Sources - -- [`@uppy/audio`](/docs/audio) — record audio. -- [`@uppy/box`](/docs/box) — import files from - [Box](https://www.box.com/en-nl/home). -- [`@uppy/dropbox`](/docs/dropbox) — import from [Dropbox](https://dropbox.com). -- [`@uppy/facebook`](/docs/facebook) — import from - [Facebook](https://facebook.com). -- [`@uppy/google-drive`](/docs/google-drive) — import from - [Google Drive](https://drive.google.com). -- [`@uppy/google-photos`](/docs/google-photos) — import from - [Google Photos](https://photos.google.com). -- [`@uppy/instagram`](/docs/instagram) — import from - [Instagram](https://instagram.com). -- [`@uppy/onedrive`](/docs/onedrive) — import from - [OneDrive](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage). -- [`@uppy/screen-capture`](/docs/screen-capture) — Record your screen, including - (optionally) your microphone. -- [`@uppy/unsplash`](/docs/unsplash) — import files from - [Unsplash](https://unsplash.com/) -- [`@uppy/url`](/docs/url) — import files from any URL. -- [`@uppy/webcam`](/docs/webcam) — Record or make a picture with your webcam. -- [`@uppy/zoom`](/docs/zoom) — import files from [Zoom](https://zoom.us). - -### UI - -- [`@uppy/image-editor`](/docs/image-editor) — allows users to crop, rotate, - zoom and flip images that are added to Uppy. -- [`@uppy/informer`](/docs/informer) — show notifications. -- [`@uppy/status-bar`](/docs/status-bar) — advanced upload progress status bar. -- [`@uppy/thumbnail-generator`](/docs/thumbnail-generator) — generate preview - thumbnails for images to be uploaded. - -### Frameworks - -- [`@uppy/angular`](/docs/angular) — Dashboard component for - [Angular](https://angular.io/). -- [`@uppy/react`](/docs/react) — Dashboard component for - [React](https://reactjs.org/). -- [`@uppy/svelte`](/docs/svelte) — Dashboard component for - [Svelte](https://svelte.dev/). -- [`@uppy/vue`](/docs/vue) — Dashboard component for [Vue](https://vuejs.org/). - -[ondragover]: - https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragover -[ondragleave]: - https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragleave -[ondrop]: - https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondrop diff --git a/docs/user-interfaces/drag-drop.mdx b/docs/user-interfaces/drag-drop.mdx deleted file mode 100644 index dbaba69233..0000000000 --- a/docs/user-interfaces/drag-drop.mdx +++ /dev/null @@ -1,149 +0,0 @@ ---- -sidebar_position: 2 -slug: /drag-drop ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Drag & Drop - -The `@uppy/drag-drop` plugin renders a drag and drop area for file selection. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-yzbujq?file=main.js/g). - -::: - -## When should I use this? - -It can be useful when you only want the local device as a file source, don’t -need file previews and a UI for metadata editing, or the -[Dashboard](/docs/dashboard/) is too much. But it can be too minimal too. By -default it doesn’t show that a file has been added nor is there a progress bar. - -## Install - - - - -```shell -npm install @uppy/core @uppy/drag-drop -``` - - - - - -```shell -yarn add @uppy/core @uppy/drag-drop -``` - - - - - - {` - import { Uppy, DragDrop } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(DragDrop, { target: '#uppy' }) - `} - - - - -## Use - -```js showLineNumbers -import Uppy from '@uppy/core'; -import DragDrop from '@uppy/drag-drop'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/drag-drop/dist/style.min.css'; - -new Uppy().use(DragDrop, { target: '#drag-drop' }); -``` - -:::info - -Certain [restrictions](/docs/uppy#restrictions) set in Uppy’s options, namely -`maxNumberOfFiles` and `allowedFileTypes`, affect the system file picker dialog. -If `maxNumberOfFiles: 1`, users will only be able to select one file, and -`allowedFileTypes: ['video/*', '.gif']` means only videos or gifs (files with -`.gif` extension) will be selectable. - -::: - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, Default: `'DragDrop'`). - -Use this if you need to add several DragDrop instances. - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string` or `Element`, default: `null`). - -#### `width` - -Drag and drop area width (`string`, default: `'100%'`). - -Set in inline CSS, so feel free to use percentage, pixels or other values that -you like. - -#### `height` - -Drag and drop area height (`string`, default: `'100%'`). - -Set in inline CSS, so feel free to use percentage, pixels or other values that -you like. - -#### `note` - -Optionally, specify a string of text that explains something about the upload -for the user (`string`, default: `null`). - -This is a place to explain any `restrictions` that are put in place. For -example: `'Images and video only, 2–3 files, up to 1 MB'`. - -#### `locale` - -```js -export default { - strings: { - // Text to show on the droppable area. - // `%{browse}` is replaced with a link that opens the system file selection dialog. - dropHereOr: 'Drop here or %{browse}', - // Used as the label for the link that opens the system file selection dialog. - browse: 'browse', - }, -}; -``` - -#### `onDragOver(event)` - -Callback for the [`ondragover`][ondragover] event handler. - -#### `onDragLeave(event)` - -Callback for the [`ondragleave`][ondragleave] event handler. - -#### `onDrop(event)` - -Callback for the [`ondrop`][ondrop] event handler. - -[ondragover]: - https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragover -[ondragleave]: - https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondragleave -[ondrop]: - https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/ondrop diff --git a/docs/user-interfaces/elements/_category_.json b/docs/user-interfaces/elements/_category_.json deleted file mode 100644 index 4250be1476..0000000000 --- a/docs/user-interfaces/elements/_category_.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "label": "Elements", - "position": 3, - "collapsed": false -} diff --git a/docs/user-interfaces/elements/drop-target.mdx b/docs/user-interfaces/elements/drop-target.mdx deleted file mode 100644 index 9a891eec4d..0000000000 --- a/docs/user-interfaces/elements/drop-target.mdx +++ /dev/null @@ -1,113 +0,0 @@ ---- -sidebar_position: 2 -slug: /drop-target ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Drop target - -The `@uppy/drop-target` plugin lets your users drag-and-drop files on any -element on the page, for example the whole page, `document.body`. - -Can be used together with Uppy Dashboard or Drag & Drop plugins, or your custom -solution targeting any DOM element. - -:::tip - -[Try out the live example](/examples) or take it for a spin in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-yzbujq?file=main.js/g). - -::: - -## When should I use this? - -When you want to allow users to drag and drop files in your own UI, rather than -in the [`Dashboard`](/docs/dashboard) UI, or catch dropped files from anywhere -on the page. - -## Install - - - - -```shell -npm install @uppy/drop-target -``` - - - - - -```shell -yarn add @uppy/drop-target -``` - - - - - - {` - import { DropTarget } from "{{UPPY_JS_URL}}" - const DropTarget = new Uppy().use(DropTarget) - `} - - - - -## Use - -This module has one default export: the `DropTarget` plugin class. - -```js {8-10} showLineNumbers -import Uppy from '@uppy/core'; -import DropTarget from '@uppy/drop-target'; - -import '@uppy/core/dist/style.css'; -import '@uppy/drop-target/dist/style.css'; - -const uppy = new Uppy(); -uppy.use(DropTarget, { - target: document.body, -}); -``` - -## API - -### Options - -#### `onDragLeave` - -Event listener for the [`dragleave` event][]. - -```js {3-5} showLineNumbers -uppy.use(DropTarget, { - target: document.body, - onDragLeave: (event) => { - event.stopPropagation(); - }, -}); -``` - -#### `onDragOver` - -Event listener for the [`dragover` event][]. - -#### `onDrop` - -Event listener for the [`drop` event][]. - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: `null`). - -[`dragover` event]: - https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragover_event -[`dragleave` event]: - https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragleave_event -[`drop` event]: - https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/drop_event diff --git a/docs/user-interfaces/elements/image-editor.mdx b/docs/user-interfaces/elements/image-editor.mdx deleted file mode 100644 index 033dd635ee..0000000000 --- a/docs/user-interfaces/elements/image-editor.mdx +++ /dev/null @@ -1,179 +0,0 @@ ---- -sidebar_position: 1 -slug: /image-editor ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Image editor - -Image editor. Designed to be used with the Dashboard UI. - -
- -![Screenshot of the Image Editor plugin UI in Dashboard](https://user-images.githubusercontent.com/1199054/87208710-654db400-c307-11ea-9471-6e3c6582d2a5.png) - -
- -## When should I use this? - -When you want to allow users to crop, rotate, zoom and flip images that are -added to Uppy. - -## Install - - - - -```shell -npm install @uppy/core @uppy/dashboard @uppy/image-editor -``` - - - - - -```shell -yarn add @uppy/core @uppy/dashboard @uppy/image-editor -``` - - - - - - {` - import { Uppy, Dashboard, ImageEditor } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Dashboard, { target: '#uppy', inline: true }) - uppy.use(ImageEditor) - `} - - - - -## Use - -```js {3,7,11} showLineNumbers -import Uppy from '@uppy/core'; -import Dashboard from '@uppy/dashboard'; -import ImageEditor from '@uppy/image-editor'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/dashboard/dist/style.min.css'; -import '@uppy/image-editor/dist/style.min.css'; - -new Uppy() - .use(Dashboard, { inline: true, target: '#dashboard' }) - .use(ImageEditor); -``` - -## API - -### Options - -:::info - -If you automatically want to open the image editor when an image is added, see -the [`autoOpen`](/docs/dashboard#autoopen) Dashboard option. - -::: - -#### `id` - -A unique identifier for this plugin (`string`, default: `'ImageEditor'`). - -#### `quality` - -Quality Of the resulting blob that will be saved in Uppy after editing/cropping -(`number`, default: `0.8`). - -#### `cropperOptions` - -Image Editor is using the excellent -[Cropper.js](https://fengyuanchen.github.io/cropperjs/). `cropperOptions` will -be directly passed to `Cropper` and thus can expect the same values as -documented in their -[README](https://github.com/fengyuanchen/cropperjs/blob/HEAD/README.md#options), -with the addition of `croppedCanvasOptions`, which will be passed to -[`getCroppedCanvas`](https://github.com/fengyuanchen/cropperjs/blob/HEAD/README.md#getcroppedcanvasoptions). - -#### `actions` - -Show action buttons (`Object` or `boolean`). - -If you you’d like to hide all actions, pass `false` to it. By default all the -actions are visible. Or enable/disable them individually: - -```js -{ - revert: true, - rotate: true, - granularRotate: true, - flip: true, - zoomIn: true, - zoomOut: true, - cropSquare: true, - cropWidescreen: true, - cropWidescreenVertical: true, -} -``` - -#### `locale: {}` - -```js -export default { - strings: { - revert: 'Revert', - rotate: 'Rotate', - zoomIn: 'Zoom in', - zoomOut: 'Zoom out', - flipHorizontal: 'Flip horizontal', - aspectRatioSquare: 'Crop square', - aspectRatioLandscape: 'Crop landscape (16:9)', - aspectRatioPortrait: 'Crop portrait (9:16)', - }, -}; -``` - -### Events - -:::info - -You can use [`on`](/docs/uppy#onevent-action) and -[`once`](/docs/uppy#onceevent-action) to listen to these events. - -::: - -#### `file-editor:start` - -Emitted when `selectFile(file)` is called. - -```js -uppy.on('file-editor:start', (file) => { - console.log(file); -}); -``` - -#### `file-editor:complete` - -Emitted after `save(blob)` is called. - -```js -uppy.on('file-editor:complete', (updatedFile) => { - console.log(updatedFile); -}); -``` - -#### `file-editor:cancel` - -Emitted when `uninstall` is called or when the current image editing changes are -discarded. - -```js -uppy.on('file-editor:cancel', (file) => { - console.log(file); -}); -``` diff --git a/docs/user-interfaces/elements/informer.mdx b/docs/user-interfaces/elements/informer.mdx deleted file mode 100644 index 99304ea913..0000000000 --- a/docs/user-interfaces/elements/informer.mdx +++ /dev/null @@ -1,94 +0,0 @@ ---- -sidebar_position: 3 -slug: /informer ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Informer - -The `@uppy/informer` plugin is a pop-up bar for showing notifications for the -[Dashboard](/docs/dashboard). When plugins have some exciting news (or errors) -to share, they can with Informer - -## When should I use it? - -When you use the [Dashboard](/docs/dashboard) it’s already included by default. -This plugin is published separately but made specifically for the Dashboard. You -can technically use it without it, but it’s not officially supported. - -## Install - - - - -```shell -npm install @uppy/informer -``` - - - - - -```shell -yarn add @uppy/informer -``` - - - - - - {` - import { Uppy, Informer } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(Informer, { target: '#informer' }) - `} - - - - -## Use - -```js -import Uppy from '@uppy/core'; -import Informer from '@uppy/informer'; - -// The `@uppy/informer` plugin includes some basic styles. -// You can also choose not to use it and provide your own styles instead. -import '@uppy/core/dist/style.min.css'; -import '@uppy/informer/dist/style.min.css'; - -new Uppy().use(Informer, { target: '#informer' }); -``` - -Informer gets its data from `uppy.state.info`, which is updated by various -plugins via [`uppy.info`](/docs/uppy#infomessage-type-duration) method. - -In the [compressor](/docs/compressor) plugin we use it like this for instance: - -```js -const size = prettierBytes(totalCompressedSize); -this.uppy.info(this.i18n('compressedX', { size }), 'info'); -``` - -When calling `uppy.info`, [Uppy](/docs/uppy) emits -[`info-visible`](/docs/uppy#info-visible) and will emit -[`info-hidden`](/docs/uppy#info-hidden) after the timeout. - -## API - -### Options - -### `id` - -A unique identifier for this plugin (`string`, default: `'Informer'`). - -Use this if you need several `Informer` instances. - -### `target` - -DOM element, CSS selector, or plugin to mount the Informer into (`string` or -`Element`, default: `null`). diff --git a/docs/user-interfaces/elements/progress-bar.mdx b/docs/user-interfaces/elements/progress-bar.mdx deleted file mode 100644 index b8cb23dcc7..0000000000 --- a/docs/user-interfaces/elements/progress-bar.mdx +++ /dev/null @@ -1,91 +0,0 @@ ---- -sidebar_position: 5 -slug: /progress-bar ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Progress bar - -`@uppy/progress-bar` is a minimalist plugin that shows the current upload -progress in a thin bar element, like the ones used by YouTube and GitHub when -navigating between pages. - -## When should I use it? - -When you need a minimalistec progress indicator and you’re -[building your own UI](/docs/guides/building-your-own-ui-with-uppy). For most -cases, [Dashboard](/docs/dashboard) or [Drag & Drop](/docs/drag-drop) (with -[Status Bar](/docs/status-bar)) is more likely what you need. - -## Install - - - - -```shell -npm install @uppy/progress-bar -``` - - - - - -```shell -yarn add @uppy/progress-bar -``` - - - - - - {` - import { Uppy, ProgressBar } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(ProgressBar, { target: '#progress-bar' }) - `} - - - - -## Use - -```js -import Uppy from '@uppy/core'; -import ProgressBar from '@uppy/progress-bar'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/progress-bar/dist/style.min.css'; - -new Uppy().use(ProgressBar, { target: '#progress-bar' }); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this Progress Bar (`string`, default: `'ProgressBar'`). - -Use this if you need to add several ProgressBar instances. - -#### `target` - -DOM element, CSS selector, or plugin to mount the Progress Bar into (`Element`, -`string`, default: `null`). - -#### `fixed` - -Show the progress bar at the top of the page with `position: fixed` (`boolean`, -default: `false`). - -When set to false, show the progress bar inline wherever it’s mounted. - -#### `hideAfterFinish` - -Hides the progress bar after the upload has finished (`boolean`, default: -`true`). diff --git a/docs/user-interfaces/elements/status-bar.mdx b/docs/user-interfaces/elements/status-bar.mdx deleted file mode 100644 index b740672feb..0000000000 --- a/docs/user-interfaces/elements/status-bar.mdx +++ /dev/null @@ -1,202 +0,0 @@ ---- -sidebar_position: 4 -slug: /status-bar ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Status bar - -The `@uppy/status-bar` plugin shows upload progress and speed, estimated time, -pre- and post-processing information, and allows users to control -(pause/resume/cancel) the upload. - -:::tip - -Try it out together with [`@uppy/drag-drop`](/docs/drag-drop) in -[StackBlitz](https://stackblitz.com/edit/vitejs-vite-yzbujq?file=main.js/g) - -::: - -## When should I use it? - -When you use the [Dashboard](/docs/dashboard) it’s already included by default. -This plugin is published separately but made specifically for the Dashboard. You -can still use it without it but it may need some (CSS) tweaking for your use -case. - -## Install - - - - -```shell -npm install @uppy/status-bar -``` - - - - - -```shell -yarn add @uppy/status-bar -``` - - - - - - {` - import { Uppy, StatusBar } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(StatusBar, { target: '#status-bar' }) - `} - - - - -## Use - -```js showLineNumbers -import Uppy from '@uppy/core'; -import StatusBar from '@uppy/status-bar'; - -import '@uppy/core/dist/style.min.css'; -import '@uppy/status-bar/dist/style.min.css'; - -new Uppy().use(StatusBar, { target: '#status-bar' }); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this Status Bar (`string`, default: `'StatusBar'`). - -Use this if you need to add several StatusBar instances. - -#### `target` - -DOM element, CSS selector, or plugin to place the drag and drop area into -(`string`, `Element`, `Function`, or `UIPlugin`, default: -[`Dashboard`](/docs/dashboard)). - -#### `hideAfterFinish` - -Hide the Status Bar after the upload is complete (`boolean`, default: `true`). - -#### `showProgressDetails` - -Display remaining upload size and estimated time (`boolean`, default: `false`) - -:::note - -`false`: Uploading: 45% - -`true`: Uploading: 45%・43 MB of 101 MB・8s left - -::: - -#### `hideUploadButton` - -Hide the upload button (`boolean`, default: `false`). - -Use this if you are providing a custom upload button somewhere, and using the -`uppy.upload()` API. - -#### `hideRetryButton` - -Hide the retry button (`boolean`, default: `false`). - -Use this if you are providing a custom retry button somewhere, and using the -`uppy.retryAll()` or `uppy.retryUpload(fileID)` API. - -#### `hidePauseResumeButton` - -Hide pause/resume buttons (for resumable uploads, via [tus](http://tus.io), for -example) (`boolean`, default: `false`). - -Use this if you are providing custom cancel or pause/resume buttons somewhere, -and using the `uppy.pauseResume(fileID)` or `uppy.removeFile(fileID)` API. - -#### `hideCancelButton` - -Hide the cancel button (`boolean`, default: `false`). - -Use this if you are providing a custom retry button somewhere, and using the -`uppy.cancelAll()` API. - -#### `doneButtonHandler` - -Status Bar will render a “Done” button in place of pause/resume/cancel buttons, -once the upload/encoding is done (`Function`, default: `null`). - -The behaviour of this “Done” button is defined by the handler function — can be -used to close file picker modals or clear the upload state. This is what the -Dashboard plugin, which uses Status Bar internally, sets: - -```js -const doneButtonHandler = () => { - this.uppy.reset(); - this.requestCloseModal(); -}; -``` - -#### `locale` - -```js -export default { - strings: { - // Shown in the status bar while files are being uploaded. - uploading: 'Uploading', - // Shown in the status bar once all files have been uploaded. - complete: 'Complete', - // Shown in the status bar if an upload failed. - uploadFailed: 'Upload failed', - // Shown in the status bar while the upload is paused. - paused: 'Paused', - // Used as the label for the button that retries an upload. - retry: 'Retry', - // Used as the label for the button that cancels an upload. - cancel: 'Cancel', - // Used as the label for the button that pauses an upload. - pause: 'Pause', - // Used as the label for the button that resumes an upload. - resume: 'Resume', - // Used as the label for the button that resets the upload state after an upload - done: 'Done', - // When `showProgressDetails` is set, shows the number of files that have been fully uploaded so far. - filesUploadedOfTotal: { - 0: '%{complete} of %{smart_count} file uploaded', - 1: '%{complete} of %{smart_count} files uploaded', - }, - // When `showProgressDetails` is set, shows the amount of bytes that have been uploaded so far. - dataUploadedOfTotal: '%{complete} of %{total}', - // When `showProgressDetails` is set, shows an estimation of how long the upload will take to complete. - xTimeLeft: '%{time} left', - // Used as the label for the button that starts an upload. - uploadXFiles: { - 0: 'Upload %{smart_count} file', - 1: 'Upload %{smart_count} files', - }, - // Used as the label for the button that starts an upload, if another upload has been started in the past - // and new files were added later. - uploadXNewFiles: { - 0: 'Upload +%{smart_count} file', - 1: 'Upload +%{smart_count} files', - }, - upload: 'Upload', - retryUpload: 'Retry upload', - xMoreFilesAdded: { - 0: '%{smart_count} more file added', - 1: '%{smart_count} more files added', - }, - showErrorDetails: 'Show error details', - }, -}; -``` diff --git a/docs/user-interfaces/elements/thumbnail-generator.mdx b/docs/user-interfaces/elements/thumbnail-generator.mdx deleted file mode 100644 index a1aeb7ddb8..0000000000 --- a/docs/user-interfaces/elements/thumbnail-generator.mdx +++ /dev/null @@ -1,168 +0,0 @@ ---- -sidebar_position: 2 -slug: /thumbnail-generator ---- - -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -import UppyCdnExample from '/src/components/UppyCdnExample'; - -# Thumbnail generator - -`@uppy/thumbnail-generator` generates proportional thumbnails (file previews) -for images that are added to Uppy. - -## When should I use this? - -This plugin is included by default with the [Dashboard](/docs/dashboard) plugin, -and can also be useful to display image previews in a custom UI. - -:::note - -Thumbnails are only generated for _local_ files. Remote files through -[Companion](/docs/companion) generally won’t have thumbnails because they are -downloaded on the server. Some providers, such as Google Drive, have baked in -thumbnails into their API responses. - -::: - -## Install - - - - -```shell -npm install @uppy/thumbnail-generator -``` - - - - - -```shell -yarn add @uppy/thumbnail-generator -``` - - - - - - {` - import { Uppy, ThumbnailGenerator } from "{{UPPY_JS_URL}}" - const uppy = new Uppy() - uppy.use(ThumbnailGenerator) - `} - - - - -## Use - -If you use the [Dashboard](/docs/dashboard) then it’s already installed. If you -want to use it programmatically for your own UI: - -```js showLineNumbers -import Uppy from '@uppy/core'; -import ThumbnailGenerator from '@uppy/thumbnail-generator'; - -const uppy = new Uppy(); - -uppy.use(ThumbnailGenerator); -uppy.on('thumbnail:generated', (file, preview) => doSomething(file, preview)); -``` - -## API - -### Options - -#### `id` - -A unique identifier for this plugin (`string`, default: `'ThumbnailGenerator'`). - -#### `locale` - -```js -export default { - strings: { - generatingThumbnails: 'Generating thumbnails...', - }, -}; -``` - -#### `thumbnailWidth` - -Width of the resulting thumbnail (`number`, default: `200`). - -Thumbnails are always proportional and not cropped. If width is provided, height -is calculated automatically to match ratio. If both width and height are given, -only width is taken into account. - -#### `thumbnailHeight` - -Height of the resulting thumbnail (`number`, default: `200`). - -Thumbnails are always proportional and not cropped. If height is provided, width -is calculated automatically to match ratio. If both width and height are given, -only width is taken into account. - -:::note - -Produce a 300px height thumbnail with calculated width to match ratio: - -```js -uppy.use(ThumbnailGenerator, { thumbnailHeight: 300 }); -``` - -Produce a 300px width thumbnail with calculated height to match ratio (and -ignore the given height): - -```js -uppy.use(ThumbnailGenerator, { thumbnailWidth: 300, thumbnailHeight: 300 }); -``` - -See issue [#979](https://github.com/transloadit/uppy/issues/979) and -[#1096](https://github.com/transloadit/uppy/pull/1096) for details on this -feature. - -::: - -#### `thumbnailType` - -MIME type of the resulting thumbnail (`string`, default: `'image/jpeg'`). - -This is useful if you want to support transparency in your thumbnails by -switching to `image/png`. - -#### `waitForThumbnailsBeforeUpload` - -Whether to wait for all thumbnails to be ready before starting the upload -(`boolean`, default: `false`). - -If set to `true`, Thumbnail Generator will invoke Uppy’s internal processing -stage and wait for `thumbnail:all-generated` event, before proceeding to the -uploading stage. This is useful because Thumbnail Generator also adds EXIF data -to images, and if we wait until it’s done processing, this data will be -available on the server after the upload. - -### Events - -:::info - -You can use [`on`](/docs/uppy#onevent-action) and -[`once`](/docs/uppy#onceevent-action) to listen to these events. - -::: - -#### `thumbnail:generated` - -Emitted with `file` and `preview` local url as arguments: - -```js -uppy.on('thumbnail:generated', (file, preview) => { - const img = document.createElement('img'); - img.src = preview; - img.width = 100; - document.body.appendChild(img); -}); -``` From 44a378af9efc522b8f6b0627b7dd51d4af4cfcc5 Mon Sep 17 00:00:00 2001 From: Merlijn Vos Date: Tue, 26 Nov 2024 10:42:17 +0100 Subject: [PATCH 3/3] @uppy/aws-s3: console.error instead of throw for missing etag (#5521) * @uppy/aws-s3: console.error instead of throw for missing etag * Improve --- packages/@uppy/aws-s3/src/index.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/@uppy/aws-s3/src/index.ts b/packages/@uppy/aws-s3/src/index.ts index b20f71bf14..153a7399f1 100644 --- a/packages/@uppy/aws-s3/src/index.ts +++ b/packages/@uppy/aws-s3/src/index.ts @@ -760,18 +760,19 @@ export default class AwsS3Multipart< } const { etag, location } = headersMap + // More info bucket settings when this is not present: + // https://github.com/transloadit/uppy/issues/5388#issuecomment-2464885562 if (method.toUpperCase() === 'POST' && location == null) { // Not being able to read the Location header is not a fatal error. // eslint-disable-next-line no-console - console.warn( - 'AwsS3/Multipart: Could not read the Location header. This likely means CORS is not configured correctly on the S3 Bucket. See https://uppy.io/docs/aws-s3-multipart#S3-Bucket-Configuration for instructions.', + console.error( + '@uppy/aws-s3: Could not read the Location header. This likely means CORS is not configured correctly on the S3 Bucket. See https://uppy.io/docs/aws-s3/#setting-up-your-s3-bucket', ) } if (etag == null) { - reject( - new Error( - 'AwsS3/Multipart: Could not read the ETag header. This likely means CORS is not configured correctly on the S3 Bucket. See https://uppy.io/docs/aws-s3-multipart#S3-Bucket-Configuration for instructions.', - ), + // eslint-disable-next-line no-console + console.error( + '@uppy/aws-s3: Could not read the ETag header. This likely means CORS is not configured correctly on the S3 Bucket. See https://uppy.io/docs/aws-s3/#setting-up-your-s3-bucket', ) return }