Skip to content

Commit

Permalink
Merge branch 'main' into status-error-state
Browse files Browse the repository at this point in the history
* main:
  @uppy/aws-s3: use `Promise.allSettled` insead of custom utils (#3079)
  Convert sets to arrays prior to using spread operator to enable transpilation to ES5 (#3297)
  Add showRecordingLength to webcam types (#3303)
  Required meta fields UI (#3285)
  Update BACKLOG.md
  Release [email protected]
  @uppy/[email protected]
  • Loading branch information
Murderlon committed Nov 8, 2021
2 parents 7b1c153 + bc67c5e commit c1e2296
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 58 deletions.
24 changes: 2 additions & 22 deletions BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,12 @@
These are ideas that are planned for specific versions or act as a backlog without a clear date.
PRs are welcome! Please do open an issue to discuss first if it's a big feature, priorities may have changed after something was added here.

## `2.0.0`

- [x] Drop IE10 (officially), drop IE11 polyfills? (@aduh95)
- [x] *: upgrade to Preact X (@murderlon)
- [x] chore: hunt down most `@TODO`s and either fix, or remove, or move to github issues/changelog backlog (@murderlon)
- [x] core: consider removing Preact from `Plugin` (maybe have a `(ui)Plugin extends BasePlugin`?) as pointed out on Reddit https://www.reddit.com/r/javascript/comments/bhkx5k/uppy_10_your_best_friend_in_file_uploading/ (@murderlon)
- [x] core: force the `new` keyword when instantiating Uppy — now we support both `new Uppy()` and `Uppy()` which is harder to maintain and might lead to confusion (@arturi)
- [ ] core: maybe we remove `file.name` and only keep `file.meta.name`; we can change the file.name here actually because it's just a plain object. we can't change the file.data.name where data is a File instance from an input or something. For XHRUpload, where we put the File instance in a FormData object and it uses the unchangeable .name property (@arturi)
- [x] core: pass full file object to `onBeforeFileAdded`. Maybe also check restrictions before calling the callbacks: https://github.com/transloadit/uppy/pull/1594 (@arturi)
- [x] core/dashboard: replace `poweredBy` and `exceedsSize` locale keys by word order aware versions, see PR #2077 (@goto-bus-stop)
- [x] dashboard: set default `trigger: null`, see https://github.com/transloadit/uppy/pull/2144#issuecomment-600581690 (@arturi)
- [x] form: make the `multipleResults` option `true` by default (@arturi)
- [x] locales: Remove the old es_GL name alias for gl_ES. Keep gl_ES only (@arturi)
- [x] providers: remove `serverHeaders` https://github.com/transloadit/uppy/pull/1861 (@mifi)
- [x] transloadit: remove `UPPY_SERVER` constant (@mifi)
- [x] tus: set the `limit` option to a sensible default, like 5 (10?) (@arturi)
- [x] xhr: set the `limit` option to a sensible default, like 5 (10?) (@arturi)
- [x] xhr: change default name depending on whether `bundle` is set `files[]` (`true`) vs `file` (default) (#782) (@aduh95)
- [x] providers: allow changing provider name title through locale https://github.com/transloadit/uppy/issues/2279 (@goto-bus-stop)
- [x] tus: remove `autoRetry` option (throw error at runtime if it is explicitly given) (@aduh95)
- [x] dashboard: showing links to files should be turned off by default (it's great for devs, they can opt-in, but for end-user UI it's weird and can even lead to problems) (@arturi)

## `3.0.0`

- [ ] Switch to ES Modules (ESM)
- [ ] @uppy/image-editor: Remove silly hack to work around non-ESM.
- [ ] Consider updating the name of @uppy/aws-s3 and @uppy/aws-s3-multipart to reflect it also supports Google Cloud Storage, Wasabi, and other cloud providers.
- [ ] Consider fixing all locale files to follow the bcp-47 standard (nl_NL --> nl-NL)

## `4.0.0`

Expand Down
4 changes: 2 additions & 2 deletions packages/@uppy/aws-s3/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@

const BasePlugin = require('@uppy/core/lib/BasePlugin')
const { RateLimitedQueue, internalRateLimitedQueue } = require('@uppy/utils/lib/RateLimitedQueue')
const settle = require('@uppy/utils/lib/settle')
const { RequestClient } = require('@uppy/companion-client')
const MiniXHRUpload = require('./MiniXHRUpload')
const isXml = require('./isXml')
Expand Down Expand Up @@ -175,7 +174,7 @@ module.exports = class AwsS3 extends BasePlugin {

const numberOfFiles = fileIDs.length

return settle(fileIDs.map((id, index) => {
return Promise.allSettled(fileIDs.map((id, index) => {
paramsPromises[id] = getUploadParameters(this.uppy.getFile(id))
return paramsPromises[id].then((params) => {
delete paramsPromises[id]
Expand Down Expand Up @@ -211,6 +210,7 @@ module.exports = class AwsS3 extends BasePlugin {

const file = this.uppy.getFile(id)
this.uppy.emit('upload-error', file, error)
return Promise.reject(error)
})
})).finally(() => {
// cleanup.
Expand Down
49 changes: 34 additions & 15 deletions packages/@uppy/core/src/Uppy.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ class RestrictionError extends Error {
if (typeof AggregateError === 'undefined') {
// eslint-disable-next-line no-global-assign
globalThis.AggregateError = class AggregateError extends Error {
constructor (message, errors) {
constructor (errors, message) {
super(message)
this.errors = errors
}
}
}

class AggregateRestrictionError extends AggregateError {
constructor (...args) {
super(...args)
Expand Down Expand Up @@ -557,27 +558,39 @@ class Uppy {
}

/**
* Check if requiredMetaField restriction is met before uploading.
* Check if requiredMetaField restriction is met for a specific file.
*
*/
#checkRequiredMetaFields (files) {
#checkRequiredMetaFieldsOnFile (file) {
const { requiredMetaFields } = this.opts.restrictions
const { hasOwnProperty } = Object.prototype

const errors = []
for (const fileID of Object.keys(files)) {
const file = this.getFile(fileID)
for (let i = 0; i < requiredMetaFields.length; i++) {
if (!hasOwnProperty.call(file.meta, requiredMetaFields[i]) || file.meta[requiredMetaFields[i]] === '') {
const err = new RestrictionError(`${this.i18n('missingRequiredMetaFieldOnFile', { fileName: file.name })}`)
errors.push(err)
this.#showOrLogErrorAndThrow(err, { file, showInformer: false, throwErr: false })
}
const missingFields = []
for (let i = 0; i < requiredMetaFields.length; i++) {
if (!hasOwnProperty.call(file.meta, requiredMetaFields[i]) || file.meta[requiredMetaFields[i]] === '') {
const err = new RestrictionError(`${this.i18n('missingRequiredMetaFieldOnFile', { fileName: file.name })}`)
errors.push(err)
missingFields.push(requiredMetaFields[i])
this.#showOrLogErrorAndThrow(err, { file, showInformer: false, throwErr: false })
}
}
this.setFileState(file.id, { missingRequiredMetaFields: missingFields })
return errors
}

/**
* Check if requiredMetaField restriction is met before uploading.
*
*/
#checkRequiredMetaFields (files) {
const errors = Object.keys(files).flatMap((fileID) => {
const file = this.getFile(fileID)
return this.#checkRequiredMetaFieldsOnFile(file)
})

if (errors.length) {
throw new AggregateRestrictionError(`${this.i18n('missingRequiredMetaField')}`, errors)
throw new AggregateRestrictionError(errors, `${this.i18n('missingRequiredMetaField')}`)
}
}

Expand Down Expand Up @@ -1277,6 +1290,12 @@ class Uppy {
this.calculateTotalProgress()
})

this.on('dashboard:file-edit-complete', (file) => {
if (file) {
this.#checkRequiredMetaFieldsOnFile(file)
}
})

// show informer if offline
if (typeof window !== 'undefined' && window.addEventListener) {
window.addEventListener('online', this.#updateOnlineStatus)
Expand Down Expand Up @@ -1592,9 +1611,9 @@ class Uppy {
const restoreStep = currentUpload.step || 0

const steps = [
...this.#preProcessors,
...this.#uploaders,
...this.#postProcessors,
...Array.from(this.#preProcessors),
...Array.from(this.#uploaders),
...Array.from(this.#postProcessors),
]
try {
for (let step = restoreStep; step < steps.length; step++) {
Expand Down
2 changes: 2 additions & 0 deletions packages/@uppy/core/src/__snapshots__/Uppy.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Object {
"name": "foo.jpg",
"type": "image/jpeg",
},
"missingRequiredMetaFields": Array [],
"name": "foo.jpg",
"preview": undefined,
"progress": Object {
Expand All @@ -47,6 +48,7 @@ Object {
"name": "bar.jpg",
"type": "image/jpeg",
},
"missingRequiredMetaFields": Array [],
"name": "bar.jpg",
"preview": undefined,
"progress": Object {
Expand Down
35 changes: 21 additions & 14 deletions packages/@uppy/dashboard/src/components/FileItem/FileInfo/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { h, Fragment } = require('preact')
const prettierBytes = require('@transloadit/prettier-bytes')
const MetaErrorMessage = require('../MetaErrorMessage')
const truncateString = require('@uppy/utils/lib/truncateString')

const renderFileName = (props) => {
Expand Down Expand Up @@ -54,22 +55,22 @@ const renderAuthor = (props) => {
}

const renderFileSize = (props) => props.file.size && (
<div className="uppy-Dashboard-Item-statusSize">
{prettierBytes(props.file.size)}
</div>
<div className="uppy-Dashboard-Item-statusSize">
{prettierBytes(props.file.size)}
</div>
)

const ReSelectButton = (props) => props.file.isGhost && (
<span>
{' \u2022 '}
<button
className="uppy-u-reset uppy-c-btn uppy-Dashboard-Item-reSelect"
type="button"
onClick={props.toggleAddFilesPanel}
>
{props.i18n('reSelect')}
</button>
</span>
<span>
{' \u2022 '}
<button
className="uppy-u-reset uppy-c-btn uppy-Dashboard-Item-reSelect"
type="button"
onClick={props.toggleAddFilesPanel}
>
{props.i18n('reSelect')}
</button>
</span>
)

const ErrorButton = ({ file, onClick }) => {
Expand Down Expand Up @@ -100,7 +101,7 @@ module.exports = function FileInfo (props) {
<div className="uppy-Dashboard-Item-fileName">
{renderFileName(props)}
<ErrorButton
file={file}
file={props.file}
// eslint-disable-next-line no-alert
onClick={() => alert(props.file.error)} // TODO: move to a custom alert implementation
/>
Expand All @@ -110,6 +111,12 @@ module.exports = function FileInfo (props) {
{renderFileSize(props)}
{ReSelectButton(props)}
</div>
<MetaErrorMessage
file={props.file}
i18n={props.i18n}
toggleFileCard={props.toggleFileCard}
metaFields={props.metaFields}
/>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
display: inline-block;
text-transform: uppercase;
vertical-align: bottom;
margin-bottom: 5px;
}

.uppy-Dashboard-Item-reSelect {
Expand All @@ -63,5 +64,49 @@
font-size: inherit;
font-family: inherit;
}
// ...uppy-Dashboard-Item-status|
// ...uppy-Dashboard-Item-fileInfo|

.uppy-Dashboard-Item-errorMessage {
font-size: 11px;
font-weight: 500;
line-height: 1.3;
color: darken($red, 15%);
background-color: lighten($red, 45%);
padding: 5px 6px;
}

.uppy-Dashboard-Item-errorMessageBtn {
text-decoration: underline;
cursor: pointer;
font-weight: 500;
}

// Error message desktop / large screen
.uppy-Dashboard-Item-preview .uppy-Dashboard-Item-errorMessage {
display: none;

.uppy-size--md & {
display: block;
border-top: 1px solid lighten($red, 35%);
padding: 6px 8px;
line-height: 1.4;
position: absolute;
bottom: 0;
left: 0;
right: 0;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
}
}

// Error message mobile / small screen
.uppy-Dashboard-Item-fileInfo .uppy-Dashboard-Item-errorMessage {
display: inline-block;
position: static;
border: 1px solid lighten($red, 35%);
border-radius: 3px;

.uppy-size--md & {
display: none;
}
}

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { h } = require('preact')
const FilePreview = require('../../FilePreview')
const MetaErrorMessage = require('../MetaErrorMessage')
const getFileTypeIcon = require('../../../utils/getFileTypeIcon')

module.exports = function FilePreviewAndLink (props) {
Expand All @@ -19,11 +20,17 @@ module.exports = function FilePreviewAndLink (props) {
target="_blank"
aria-label={props.file.meta.name}
>
<span hidden>props.file.meta.name</span>
<span hidden>{props.file.meta.name}</span>
</a>
)
}
<FilePreview file={props.file} />
<MetaErrorMessage
file={props.file}
i18n={props.i18n}
toggleFileCard={props.toggleFileCard}
metaFields={props.metaFields}
/>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const { h } = require('preact')

const metaFieldIdToName = (metaFieldId, metaFields) => {
const field = metaFields.filter(f => f.id === metaFieldId)
return field[0].name
}

module.exports = function renderMissingMetaFieldsError (props) {
const { file, toggleFileCard, i18n, metaFields } = props
const { missingRequiredMetaFields } = file
if (!missingRequiredMetaFields?.length) {
return null
}

const metaFieldsString = missingRequiredMetaFields.map(missingMetaField => (
metaFieldIdToName(missingMetaField, metaFields)
)).join(', ')

return (
<div className="uppy-Dashboard-Item-errorMessage">
{i18n('missingRequiredMetaFields', {
smart_count: missingRequiredMetaFields.length,
fields: metaFieldsString,
})}
{' '}
<button
type="button"
class="uppy-u-reset uppy-Dashboard-Item-errorMessageBtn"
onClick={() => toggleFileCard(true, file.id)}
>
{i18n('editFile')}
</button>
</div>
)
}
5 changes: 5 additions & 0 deletions packages/@uppy/dashboard/src/components/FileItem/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ module.exports = class FileItem extends Component {
<FilePreviewAndLink
file={file}
showLinkToFileUploadResult={this.props.showLinkToFileUploadResult}
i18n={this.props.i18n}
toggleFileCard={this.props.toggleFileCard}
metaFields={this.props.metaFields}
/>
<FileProgress
uppy={this.props.uppy}
Expand All @@ -101,6 +104,8 @@ module.exports = class FileItem extends Component {
containerWidth={this.props.containerWidth}
i18n={this.props.i18n}
toggleAddFilesPanel={this.props.toggleAddFilesPanel}
toggleFileCard={this.props.toggleFileCard}
metaFields={this.props.metaFields}
/>
<Buttons
file={file}
Expand Down
4 changes: 4 additions & 0 deletions packages/@uppy/dashboard/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ module.exports = class Dashboard extends UIPlugin {
sessionRestored: 'Session restored',
reSelect: 'Re-select',
poweredBy: 'Powered by %{uppy}',
missingRequiredMetaFields: {
0: 'Missing required meta field: %{fields}.',
1: 'Missing required meta fields: %{fields}.',
},
},
}

Expand Down
4 changes: 4 additions & 0 deletions packages/@uppy/locales/src/en_US.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ en_US.strings = {
micDisabled: 'Microphone access denied by user',
missingRequiredMetaField: 'Missing required meta fields',
missingRequiredMetaFieldOnFile: 'Missing required meta fields in %{fileName}',
missingRequiredMetaFields: {
'0': 'Missing required meta field: %{fields}.',
'1': 'Missing required meta fields: %{fields}.',
},
myDevice: 'My Device',
noCameraDescription: 'In order to take pictures or record video, please connect a camera device',
noCameraTitle: 'Camera Not Available',
Expand Down
Loading

0 comments on commit c1e2296

Please sign in to comment.