From 0da66ff9bda728e57b0992bb63f158a08c4fc8f3 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Mon, 22 Aug 2022 16:55:19 +0200 Subject: [PATCH] website: replace Robodog example with Uppy plugins (#4026) Co-authored-by: Artur Paikin --- .github/CONTRIBUTING.md | 2 +- website/src/_template/contributing.md | 58 +++++++- .../src/examples/markdown-snippets/app.es6 | 133 ++++++++---------- .../src/examples/markdown-snippets/app.html | 6 +- .../src/examples/markdown-snippets/index.ejs | 6 +- 5 files changed, 122 insertions(+), 83 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index f25844283b..35085c80db 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -50,7 +50,7 @@ To start the testing suite run: This will run Cypress in watch-mode, and it will pick up and rebuild any changes to JS files. If you need to change other files (like CSS for example), you need to run the respective `yarn build:*` scripts. -Alternatively the following command is the same as the above, except it doesn't run `build` first: +Alternatively the following command is the same as the above, except it doesn’t run `build` first: yarn e2e:skip-build diff --git a/website/src/_template/contributing.md b/website/src/_template/contributing.md index 62c515f78a..6509cbde7b 100644 --- a/website/src/_template/contributing.md +++ b/website/src/_template/contributing.md @@ -42,7 +42,7 @@ yarn run test:unit ### End-to-End tests -We use [Cypress](cypress.io/) for our e2e test suite. Be sure to checkout “[Writing your first test](https://docs.cypress.io/guides/getting-started/writing-your-first-test#Add-a-test-file)” and the “[Introduction to Cypress](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress#Cypress-Can-Be-Simple-Sometimes)”. You should also be aware of the “[Best Practices](https://docs.cypress.io/guides/references/best-practices)”. +We use [Cypress](https://www.cypress.io/) for our e2e test suite. Be sure to checkout “[Writing your first test](https://docs.cypress.io/guides/getting-started/writing-your-first-test#Add-a-test-file)” and the “[Introduction to Cypress](https://docs.cypress.io/guides/core-concepts/introduction-to-cypress#Cypress-Can-Be-Simple-Sometimes)”. You should also be aware of the “[Best Practices](https://docs.cypress.io/guides/references/best-practices)”. To get started make sure you have your `.env` set up. Copy the contents of `.env.example` to a file named `.env` and add the values relevant for the test(s) you are trying to run. @@ -50,15 +50,59 @@ To start the testing suite run: yarn e2e +This will run Cypress in watch-mode, and it will pick up and rebuild any changes to JS files. If you need to change other files (like CSS for example), you need to run the respective `yarn build:*` scripts. + +Alternatively the following command is the same as the above, except it doesn’t run `build` first: + + yarn e2e:skip-build + To generate the boilerplate for a new test run: yarn e2e:generate ## Development +### Companion + +To start the Companion server along with Uppy, run: + +```bash +yarn run dev:with-companion +``` + +or if you only want to run Companion + +```bash +yarn run start:companion +``` + +This would get the Companion instance running on `http://localhost:3020`. It uses [nodemon](https://github.com/remy/nodemon) so it will automatically restart when files are changed. + +### Live example + +An example server is running at , which is deployed with [Kubernetes](https://github.com/transloadit/uppy/blob/main/packages/%40uppy/companion/KUBERNETES.md) + +### How the Authentication and Token mechanism works + +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! + ### Instagram integration -Even though facebook [allows using](https://developers.facebook.com/blog/post/2018/06/08/enforce-https-facebook-login/) http://localhost in dev mode, Instagram doesn’t seem to support that, and seems to need a publically available domain name with HTTPS. +Even though facebook [allows using](https://developers.facebook.com/blog/post/2018/06/08/enforce-https-facebook-login/) http://localhost in dev mode, Instagram doesn’t seem to support that, and seems to need a publically available domain name with HTTPS. So we will tunnel requests to localhost using `ngrok`. Make sure that you are using a development facebook app at @@ -67,6 +111,8 @@ Go to “Instagram Basic Display” and find `Instagram App ID` and `Instagram A COMPANION_INSTAGRAM_KEY="Instagram App ID" COMPANION_INSTAGRAM_SECRET="Instagram App Secret" +**Note!** `ngrok` seems to be blocked by Instagram now, so you may have to find an alternative. + Run ```bash @@ -94,6 +140,14 @@ Tester invites -> Accept Now you should be able to test the Instagram integration. +## Zoom + +See above Instagram instructions for setting up a tunnel, but replace `instagram` with `zoom` in the URL. Note that **you also have to add the OAuth redirect URL to `OAuth allow list`** in the Zoom Oauth app settings or it will not work. + +Add the following scopes: `recording:read`, `user:read`, `user_info:read` + +To test recording a meeting, you need to sign up for a Zoom Pro trial (can be cancelled later), for example using their iOS app. + ## Releases Before doing a release, check that the examples on the website work: diff --git a/website/src/examples/markdown-snippets/app.es6 b/website/src/examples/markdown-snippets/app.es6 index bcdb483156..b4ee453e4c 100644 --- a/website/src/examples/markdown-snippets/app.es6 +++ b/website/src/examples/markdown-snippets/app.es6 @@ -1,24 +1,18 @@ /* eslint-env browser */ import marked from 'marked' import dragdrop from 'drag-drop' -// Add Robodog JS. It is advisable to install Robodog from npm/yarn. -// But for experimenting, you can use also Transloadit’s CDN, Edgly: -// -import robodog from '@uppy/robodog' +import Uppy from '@uppy/core' +import Dashboard from '@uppy/dashboard' +import Transloadit from '@uppy/transloadit' +import RemoteSources from '@uppy/remote-sources' +import Webcam from '@uppy/webcam' +import ImageEditor from '@uppy/image-editor' const TRANSLOADIT_EXAMPLE_KEY = '35c1aed03f5011e982b6afe82599b6a0' const TRANSLOADIT_EXAMPLE_TEMPLATE = '0b2ee2bc25dc43619700c2ce0a75164a' /** * A textarea for markdown text, with support for file attachments. - * - * ## Usage - * - * ```js - * const element = document.querySelector('textarea') - * const mdtxt = new MarkdownTextarea(element) - * mdtxt.install() - * ``` */ class MarkdownTextarea { constructor (element) { @@ -43,19 +37,45 @@ class MarkdownTextarea { wrapper.appendChild(element) wrapper.appendChild(this.uploadLine) - this.setupUploadLine() this.setupTextareaDrop() + this.setupUppy() } - setupTextareaDrop () { - dragdrop(this.element, (files) => { - this.uploadFiles(files) + setupUppy = () => { + this.uppy = new Uppy({ autoProceed: true }) + .use(Transloadit, { + waitForEncoding: true, + params: { + auth: { key: TRANSLOADIT_EXAMPLE_KEY }, + template_id: TRANSLOADIT_EXAMPLE_TEMPLATE, + }, + }) + .use(Dashboard, { closeAfterFinish: true, trigger: '.form-upload' }) + .use(ImageEditor, { target: Dashboard }) + .use(Webcam, { target: Dashboard }) + .use(RemoteSources, { + companionUrl: 'https://api2.transloadit.com/companion', + }) + + this.uppy.on('complete', (result) => { + const { successful, failed, transloadit } = result + if (successful.length !== 0) { + this.insertAttachments( + matchFilesAndThumbs(transloadit[0].results), + ) + } else { + failed.forEach(error => { + console.error(error) + this.reportUploadError(error) + }) + } + this.uppy.cancelAll() }) } - setupUploadLine () { - this.uploadLine.addEventListener('click', () => { - this.pickFiles() + setupTextareaDrop () { + dragdrop(this.element, (files) => { + this.uploadFiles(files) }) } @@ -87,53 +107,16 @@ class MarkdownTextarea { }) } - uploadFiles (files) { - robodog.upload(files, { - waitForEncoding: true, - params: { - auth: { key: TRANSLOADIT_EXAMPLE_KEY }, - template_id: TRANSLOADIT_EXAMPLE_TEMPLATE, - }, - }).then((result) => { - if (result === null) return - this.insertAttachments( - // eslint-disable-next-line no-use-before-define - matchFilesAndThumbs(result.results), - ) - }).catch((err) => { - console.error(err) - this.reportUploadError(err) - }) - } - - pickFiles () { - robodog.pick({ - waitForEncoding: true, - params: { - auth: { key: TRANSLOADIT_EXAMPLE_KEY }, - template_id: TRANSLOADIT_EXAMPLE_TEMPLATE, - }, - providers: [ - 'webcam', - 'url', - 'instagram', - 'google-drive', - 'dropbox', - 'box', - 'unsplash', - 'audio', - 'screen-capture', - ], - }).then((result) => { - if (result === null) return - this.insertAttachments( - // eslint-disable-next-line no-use-before-define - matchFilesAndThumbs(result.results), - ) - }).catch((err) => { - console.error(err) - this.reportUploadError(err) + uploadFiles = (files) => { + const filesForUppy = files.map(file => { + return { + data: file, + type: file.type, + name: file.name, + meta: file.meta || {}, + } }) + this.uppy.addFiles(filesForUppy) } } @@ -170,17 +153,19 @@ function matchFilesAndThumbs (results) { const filesById = {} const thumbsById = {} - results.forEach((result) => { - if (result.stepName === 'thumbnails') { - thumbsById[result.original_id] = result - } else { - filesById[result.original_id] = result - } - }) + for (const [stepName, result] of Object.entries(results)) { + result.forEach(result => { + if (stepName === 'thumbnails') { + thumbsById[result.original_id] = result + } else { + filesById[result.original_id] = result + } + }) + } return Object.keys(filesById).map((key) => ({ - file : filesById[key], - thumb : thumbsById[key], + file: filesById[key], + thumb: thumbsById[key], })) } diff --git a/website/src/examples/markdown-snippets/app.html b/website/src/examples/markdown-snippets/app.html index 39f4708fc8..e5c70029aa 100644 --- a/website/src/examples/markdown-snippets/app.html +++ b/website/src/examples/markdown-snippets/app.html @@ -1,7 +1,7 @@ - - + --> +

Create a new snippet