Explorar o código

Merge branch 'master' of github.com:transloadit/uppy

Kevin van Zonneveld %!s(int64=5) %!d(string=hai) anos
pai
achega
77a90e27bb

+ 9 - 2
examples/aws-companion/readme.md

@@ -5,9 +5,16 @@ Files are uploaded to a randomly named directory inside the `whatever/` director
 
 ## Run it
 
-First set up the `COMPANION_AWS_KEY`, `COMPANION_AWS_SECRET`, `COMPANION_AWS_REGION`, and `COMPANION_AWS_BUCKET` environment variables for @uppy/companion.
+To run this example, make sure you've correctly installed the root repository:
 
-Move into this directory, then:
+```bash
+npm install
+npm run bootstrap
+```
+
+Then, set up the `COMPANION_AWS_KEY`, `COMPANION_AWS_SECRET`, `COMPANION_AWS_REGION`, and `COMPANION_AWS_BUCKET` environment variables for @uppy/companion.
+
+Then, navigate to this directory and run:
 
 ```bash
 npm install

+ 7 - 0
examples/aws-presigned-url/readme.md

@@ -4,6 +4,13 @@ This example uses a server-side PHP endpoint to sign uploads to S3.
 
 ## Running It
 
+To run this example, make sure you've correctly installed the root repository:
+
+```bash
+npm install
+npm run bootstrap
+```
+
 This example uses the AWS PHP SDK.
 To install it, [get composer](https://getcomposer.org) and run `composer update` in this folder.
 

+ 7 - 0
examples/custom-provider/readme.md

@@ -5,6 +5,13 @@ This serves as an illustration on how integrating custom providers would work
 
 ## Run it
 
+To run this example, make sure you've correctly installed the root repository:
+
+```bash
+npm install
+npm run bootstrap
+```
+
 Move into this directory, then:
 
 ```bash

+ 8 - 1
examples/digitalocean-spaces/readme.md

@@ -2,7 +2,14 @@
 
 This example uses Uppy to upload files to a DigitolOcean Space. DigitalOcean Spaces has an identical API to S3, so we can use the [AwsS3](https://uppy.io/docs/aws-s3) plugin. We use @uppy/companion with a [custom `endpoint` configuration](./server.js#L32-L33) that points to DigitalOcean.
 
-To try this example, first run:
+To run this example, make sure you've correctly installed the root repository:
+
+```bash
+npm install
+npm run bootstrap
+```
+
+Then navigate to this directory, and run:
 
 ```bash
 npm install

+ 7 - 0
examples/multiple-instances/readme.md

@@ -5,6 +5,13 @@ It has two instances on the same page, side-by-side, but with different `id`s so
 
 ## Run it
 
+To run this example, make sure you've correctly installed the root repository:
+
+```bash
+npm install
+npm run bootstrap
+```
+
 Move into this directory, then:
 
 ```bash

+ 7 - 1
examples/node-xhr/readme.md

@@ -4,7 +4,13 @@ This example uses Node server and `@uppy/xhr-upload` to upload files to the loca
 
 ## Run it
 
-First run `npm install && npm run bootstrap && npm run build` in the root folder of the uppy project.
+To run this example, make sure you've correctly installed the root repository:
+
+```bash
+npm install
+npm run bootstrap
+npm run build
+```
 
 Then move into this directory (`examples/php-xhr`), and:
 

+ 7 - 1
examples/php-xhr/readme.md

@@ -4,7 +4,13 @@ This example uses PHP server and `@uppy/xhr-upload` to upload files to the local
 
 ## Run it
 
-First run `npm install && npm run bootstrap && npm run build` in the root folder of the uppy project.
+To run this example, make sure you've correctly installed the root repository:
+
+```bash
+npm install
+npm run bootstrap
+npm run build
+```
 
 Then move into this directory (`examples/php-xhr`), and:
 

+ 7 - 1
examples/python-xhr/readme.md

@@ -4,7 +4,13 @@ This example uses a Python Flask server and `@uppy/xhr-upload` to upload files t
 
 ## Run it
 
-First run `npm install && npm run bootstrap && npm run build` in the root folder of the uppy project.
+To run this example, make sure you've correctly installed the root repository:
+
+```bash
+npm install
+npm run bootstrap
+npm run build
+```
 
 Then move into this directory (`examples/python-xhr`), and:
 

+ 10 - 0
examples/react-native-expo/readme.md

@@ -6,6 +6,16 @@
 
 ## Run it
 
+To run this example, make sure you've correctly installed the root repository:
+
+```bash
+npm install
+npm run bootstrap
+npm run build
+```
+
+Then navigate to this directory and run it:
+
 ```bash
 cd examples/react-native-expo
 npm install

+ 7 - 0
examples/redux/readme.md

@@ -8,6 +8,13 @@ This example supports the [Redux Devtools extension](https://github.com/zalmoxis
 
 ## Run it
 
+To run this example, make sure you've correctly installed the root repository:
+
+```bash
+npm install
+npm run bootstrap
+```
+
 Move into this directory, then:
 
 ```bash

+ 7 - 0
examples/transloadit/readme.md

@@ -4,6 +4,13 @@ This example shows all the different Robodog APIs in action on a single page.
 
 ## Run it
 
+To run this example, make sure you've correctly installed the root repository:
+
+```bash
+npm install
+npm run bootstrap
+```
+
 Move into this directory, then:
 
 ```bash

+ 12 - 1
examples/uppy-with-companion/README.md

@@ -4,5 +4,16 @@ This is a simple, lean example that combines the usage of @uppy/companion and up
 
 ## Test it
 
-To test it, run `npm install` to install the required dependencies, and then run `npm start`
+To run this example, make sure you've correctly installed the root repository:
 
+```bash
+npm install
+npm run bootstrap
+```
+
+Then, navigate to this directory and run:
+
+```bash
+npm install
+npm start
+```

+ 7 - 0
examples/xhr-bundle/readme.md

@@ -6,6 +6,13 @@ This example uses Uppy with XHRUpload plugin in `bundle` mode. Bundle mode uploa
 
 ## Run it
 
+To run this example, make sure you've correctly installed the root repository:
+
+```bash
+npm install
+npm run bootstrap
+```
+
 Move into this directory, then:
 
 ```bash

+ 11 - 50
packages/@uppy/companion/package-lock.json

@@ -1,59 +1,20 @@
 {
 	"name": "@uppy/companion",
-	"version": "0.17.4",
+	"version": "1.0.2",
 	"lockfileVersion": 1,
 	"requires": true,
 	"dependencies": {
-		"tus-js-client": {
-			"version": "github:ifedapoolarewaju/tus-js-client#888bcf73b66698a165f086f7bbe61951597f5c1b",
-			"from": "github:ifedapoolarewaju/tus-js-client#888bcf73b66698a165f086f7bbe61951597f5c1b",
+		"mime-db": {
+			"version": "1.40.0",
+			"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+			"integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+		},
+		"mime-types": {
+			"version": "2.1.24",
+			"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+			"integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
 			"requires": {
-				"buffer-from": "^0.1.1",
-				"extend": "^3.0.0",
-				"js-base64": "^2.4.9",
-				"lodash.throttle": "^4.1.1",
-				"url-parse": "^1.4.3"
-			},
-			"dependencies": {
-				"buffer-from": {
-					"version": "0.1.2",
-					"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
-					"integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg=="
-				},
-				"extend": {
-					"version": "3.0.2",
-					"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
-					"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
-				},
-				"js-base64": {
-					"version": "2.5.1",
-					"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz",
-					"integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw=="
-				},
-				"lodash.throttle": {
-					"version": "4.1.1",
-					"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
-					"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
-				},
-				"querystringify": {
-					"version": "2.1.1",
-					"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz",
-					"integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA=="
-				},
-				"requires-port": {
-					"version": "1.0.0",
-					"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-					"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
-				},
-				"url-parse": {
-					"version": "1.4.4",
-					"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz",
-					"integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==",
-					"requires": {
-						"querystringify": "^2.0.0",
-						"requires-port": "^1.0.0"
-					}
-				}
+				"mime-db": "1.40.0"
 			}
 		}
 	}

+ 1 - 0
packages/@uppy/companion/package.json

@@ -46,6 +46,7 @@
     "isobject": "3.0.1",
     "jsonwebtoken": "8.3.0",
     "lodash.merge": "4.6.1",
+    "mime-types": "2.1.24",
     "morgan": "1.9.1",
     "ms": "2.1.1",
     "node-redis-pubsub": "2.0.0",

+ 3 - 2
packages/@uppy/companion/src/server/provider/dropbox/adapter.js

@@ -1,3 +1,5 @@
+const mime = require('mime-types')
+
 exports.getUsername = (data) => {
   return data.user_email
 }
@@ -23,8 +25,7 @@ exports.getItemName = (item) => {
 }
 
 exports.getMimeType = (item) => {
-  // mime types aren't supported.
-  return null
+  return mime.lookup(exports.getItemName(item)) || null
 }
 
 exports.getItemId = (item) => {

+ 16 - 0
packages/@uppy/dashboard/src/index.js

@@ -169,6 +169,7 @@ module.exports = class Dashboard extends Plugin {
     this.toggleFileCard = this.toggleFileCard.bind(this)
     this.toggleAddFilesPanel = this.toggleAddFilesPanel.bind(this)
     this.handlePaste = this.handlePaste.bind(this)
+    this.handlePasteOnBody = this.handlePasteOnBody.bind(this)
     this.handleInputChange = this.handleInputChange.bind(this)
     this.render = this.render.bind(this)
     this.install = this.install.bind(this)
@@ -572,12 +573,26 @@ module.exports = class Dashboard extends Plugin {
     }
 
     this.startListeningToResize()
+    document.addEventListener('paste', this.handlePasteOnBody)
 
     this.uppy.on('plugin-remove', this.removeTarget)
     this.uppy.on('file-added', this.handleFileAdded)
     this.uppy.on('complete', this.handleComplete)
   }
 
+  // ___Why do we listen to the 'paste' event on a document instead of onPaste={props.handlePaste} prop, or this.el.addEventListener('paste')?
+  //    Because (at least) Chrome doesn't handle paste if focus is on some button, e.g. 'My Device'.
+  //    => Therefore, the best option is to listen to all 'paste' events, and only react to them when we are focused on our particular Uppy instance.
+  // ___Why do we still need onPaste={props.handlePaste} for the DashboardUi?
+  //    Because if we click on the 'Drop files here' caption e.g., `document.activeElement` will be 'body'. Which means our standard determination of whether we're pasting into our Uppy instance won't work.
+  //    => Therefore, we need a traditional onPaste={props.handlePaste} handler too.
+  handlePasteOnBody (event) {
+    const isFocusInOverlay = this.el.contains(document.activeElement)
+    if (isFocusInOverlay) {
+      this.handlePaste(event)
+    }
+  }
+
   handleFileAdded () {
     this.hideAllPanels()
   }
@@ -596,6 +611,7 @@ module.exports = class Dashboard extends Plugin {
     }
 
     this.stopListeningToResize()
+    document.removeEventListener('paste', this.handlePasteOnBody)
 
     window.removeEventListener('popstate', this.handlePopState, false)
     this.uppy.off('plugin-remove', this.removeTarget)

+ 148 - 0
packages/@uppy/locales/src/pt_BR.js

@@ -0,0 +1,148 @@
+/* eslint camelcase: 0 */
+
+const pt_BR = {}
+
+pt_BR.strings = {
+  addMoreFiles: 'Adicionar mais arquivos',
+  addingMoreFiles: 'Adicionando mais arquivos',
+  allowAccessDescription: 'Para poder tirar fotos e gravar vídeos com sua câmera, por favor permita o acesso a câmera para esse site.',
+  allowAccessTitle: 'Por favor permita o acesso a sua câmera',
+  authenticateWith: 'Conectar com %{pluginName}',
+  authenticateWithTitle: 'Por favor conecte com %{pluginName} para selecionar arquivos',
+  back: 'Voltar',
+  browse: 'navegue',
+  cancel: 'Cancelar',
+  cancelUpload: 'Cancelar envio de arquivos',
+  chooseFiles: 'Selecionar arquivos',
+  closeModal: 'Fechar Modal',
+  companionAuthError: 'Autorização necessária',
+  companionError: 'Conexão com serviço falhou',
+  complete: 'Concluído',
+  connectedToInternet: 'Conectado á internet',
+  copyLink: 'Copiar link',
+  copyLinkToClipboardFallback: 'Copiar URL abaixo',
+  copyLinkToClipboardSuccess: 'Link copiado para a área de transferência',
+  creatingAssembly: 'Preparando envio de arquivos...',
+  creatingAssemblyFailed: 'Transloadit: Não foi possível criar o Assembly',
+  dashboardTitle: 'Envio de arquivos',
+  dashboardWindowTitle: 'Janela para envio de arquivos (Pressione esc para fechar)',
+  dataUploadedOfTotal: '%{complete} de %{total}',
+  done: 'Concluir',
+  dropHereOr: 'Arraste arquivos aqui ou %{browse}',
+  dropHint: 'Solte seus arquivos aqui',
+  dropPaste: 'Solte arquivos aqui, cole ou %{browse}',
+  dropPasteImport: 'Solte arquivos aqui, cole, %{browse} ou importe de',
+  edit: 'Editar',
+  editFile: 'Editar arquivo',
+  editing: 'Editando %{file}',
+  emptyFolderAdded: 'Nenhum arquivo foi adicionado da pasta vazia',
+  encoding: 'Codificando...',
+  enterCorrectUrl: 'URL incorreta: Por favor tenha certeza que inseriu um link direto para um arquivo',
+  enterUrlToImport: 'Coloque a URL para importar um arquivo',
+  exceedsSize: 'Esse arquivo excedeu o tamanho máximo permitido',
+  failedToFetch: 'Serviço falgou para buscar essa URL, por favor tenha certeza que a URL está correta',
+  failedToUpload: 'Falha para enviar %{file}',
+  fileSource: 'Origem do arquivo: %{name}',
+  filesUploadedOfTotal: {
+    '0': '%{complete} de %{smart_count} arquivo enviado',
+    '1': '%{complete} de %{smart_count} arquivos enviados',
+    '2': '%{complete} de %{smart_count} arquivos enviados'
+  },
+  filter: 'Filtrar',
+  finishEditingFile: 'Finalizar edição de arquivo',
+  folderAdded: {
+    '0': 'Adicionado %{smart_count} arquivo de %{folder}',
+    '1': 'Adicionado %{smart_count} arquivos de %{folder}',
+    '2': 'Adicionado %{smart_count} arquivos de %{folder}'
+  },
+  import: 'Importar',
+  importFrom: 'Importar de %{name}',
+  link: 'Link',
+  loading: 'Carregando...',
+  logOut: 'Deslogar',
+  myDevice: 'Meu dispositivo',
+  noFilesFound: 'Você não possui arquivos ou pastas aqui',
+  noInternetConnection: 'Sem conexão com a internet',
+  pause: 'Pausar',
+  pauseUpload: 'Pausar envio de arquivos',
+  paused: 'Pausado',
+  poweredBy: 'Desenvolvido por',
+  preparingUpload: 'Preparando envio de arquivos...',
+  processingXFiles: {
+    '0': 'Processando %{smart_count} arquivo',
+    '1': 'Processando %{smart_count} arquivos',
+    '2': 'Processando %{smart_count} arquivos'
+  },
+  removeFile: 'Remover arquivo',
+  resetFilter: 'Resetar filtro',
+  resume: 'Retomar',
+  resumeUpload: 'Retomar envio de arquivos',
+  retry: 'Tentar novamente',
+  retryUpload: 'Tentar enviar novamente',
+  saveChanges: 'Salvar alterações',
+  selectXFiles: {
+    '0': 'Selecionar %{smart_count} arquivo',
+    '1': 'Selecionar %{smart_count} arquivo',
+    '2': 'Selecionar %{smart_count} arquivos'
+  },
+  smile: 'Sorria!',
+  startRecording: 'Começar gravação de vídeo',
+  stopRecording: 'Parar gravação de vídeo',
+  takePicture: 'Tirar uma foto',
+  timedOut: 'Envio de arquivos parado por %{seconds} segundos, abortando.',
+  upload: 'Enviar arquivos',
+  uploadComplete: 'Envio de arquivos finalizado',
+  uploadFailed: 'Envio de arquivos falhou',
+  uploadPaused: 'Envio de arquivos pausado',
+  uploadXFiles: {
+    '0': 'Enviar %{smart_count} arquivo',
+    '1': 'Enviar %{smart_count} arquivo',
+    '2': 'Enviar %{smart_count} arquivos'
+  },
+  uploadXNewFiles: {
+    '0': 'Enviar +%{smart_count} arquivo',
+    '1': 'Enviar +%{smart_count} arquivos',
+    '2': 'Enviar +%{smart_count} arquivos'
+  },
+  uploading: 'Enviando',
+  uploadingXFiles: {
+    '0': 'Enviando %{smart_count} arquivo',
+    '1': 'Enviando %{smart_count} arquivos',
+    '2': 'Enviando %{smart_count} arquivos'
+  },
+  xFilesSelected: {
+    '0': '%{smart_count} arquivo selecionado',
+    '1': '%{smart_count} arquivos selecionados',
+    '2': '%{smart_count} arquivos selecionados'
+  },
+  xMoreFilesAdded: {
+    '0': '%{smart_count} arquivo adicionados',
+    '1': '%{smart_count} arquivos adicionados',
+    '2': '%{smart_count} arquivos adicionados'
+  },
+  xTimeLeft: '%{time} restantes',
+  youCanOnlyUploadFileTypes: 'Você pode enviar apenas aquivos: %{types}',
+  youCanOnlyUploadX: {
+    '0': 'Você pode enviar apenas %{smart_count} arquivo',
+    '1': 'Você pode enviar apenas %{smart_count} arquivos',
+    '2': 'Você pode enviar apenas %{smart_count} arquivos'
+  },
+  youHaveToAtLeastSelectX: {
+    '0': 'Você precisa selecionar pelo menos %{smart_count} arquivo',
+    '1': 'Você precisa selecionar pelo menos %{smart_count} arquivos',
+    '2': 'Você precisa selecionar pelo menos %{smart_count} arquivos'
+  }
+}
+
+pt_BR.pluralize = function (n) {
+  if (n === 1) {
+    return 0
+  }
+  return 1
+}
+
+if (typeof window !== 'undefined' && typeof window.Uppy !== 'undefined') {
+  window.Uppy.locales.pt_BR = pt_BR
+}
+
+module.exports = pt_BR

+ 3 - 2
website/themes/uppy/layout/index.ejs

@@ -167,11 +167,12 @@
     })
     .use(Uppy.GoogleDrive, { target: Uppy.Dashboard, companionUrl: COMPANION_ENDPOINT })
     .use(Uppy.Instagram, { target: Uppy.Dashboard, companionUrl: COMPANION_ENDPOINT })
+    .use(Uppy.Dropbox, { target: Uppy.Dashboard, companionUrl: COMPANION_ENDPOINT })
     .use(Uppy.Webcam, { target: Uppy.Dashboard })
     .use(Uppy.Url, { target: Uppy.Dashboard, companionUrl: COMPANION_ENDPOINT })
     .use(Uppy.Tus, { endpoint: TUS_ENDPOINT})
 
-  uppy.on('success', (files) => {
-    console.log(`Upload complete! We’ve uploaded these files: ${files}`)
+  uppy.on('success', function (files) {
+    console.log('Upload complete! We’ve uploaded these files:', files)
   })
 </script>