diff --git a/ipywidgets/widgets/widget_upload.py b/ipywidgets/widgets/widget_upload.py index 67b0f84ed0..965c16a4f2 100644 --- a/ipywidgets/widgets/widget_upload.py +++ b/ipywidgets/widgets/widget_upload.py @@ -15,15 +15,7 @@ from .widget_core import CoreWidget from .widget_button import ButtonStyle from .widget import register, widget_serialization -from .trait_types import bytes_serialization, InstanceDict - -def content_from_json(value, widget): - """ - deserialize file content - """ - from_json = bytes_serialization['from_json'] - output = [from_json(e, None) for e in value] - return output +from .trait_types import InstanceDict @register @@ -33,7 +25,6 @@ class FileUpload(DescriptionWidget, ValueWidget, CoreWidget): """ _model_name = Unicode('FileUploadModel').tag(sync=True) _view_name = Unicode('FileUploadView').tag(sync=True) - _counter = Int().tag(sync=True) accept = Unicode(help='File types to accept, empty string for all').tag(sync=True) multiple = Bool(help='If True, allow for multiple files upload').tag(sync=True) @@ -43,25 +34,8 @@ class FileUpload(DescriptionWidget, ValueWidget, CoreWidget): values=['primary', 'success', 'info', 'warning', 'danger', ''], default_value='', help="""Use a predefined styling for the button.""").tag(sync=True) style = InstanceDict(ButtonStyle).tag(sync=True, **widget_serialization) - metadata = List(Dict(), help='List of file metadata').tag(sync=True) - data = List(Bytes(), help='List of file content (bytes)').tag( - sync=True, from_json=content_from_json - ) error = Unicode(help='Error message').tag(sync=True) - value = Dict(read_only=True) - - @observe('_counter') - def on_incr_counter(self, change): - """ - counter increment triggers the update of trait value - """ - res = {} - msg = 'Error: length of metadata and data must be equal' - assert len(self.metadata) == len(self.data), msg - for metadata, content in zip(self.metadata, self.data): - name = metadata['name'] - res[name] = {'metadata': metadata, 'content': content} - self.set_trait('value', res) + value = List(Dict(), help="The file upload value").tag(sync=True) @default('description') def _default_description(self): diff --git a/packages/controls/src/widget_upload.ts b/packages/controls/src/widget_upload.ts index bdfba88b21..1d37ecba37 100644 --- a/packages/controls/src/widget_upload.ts +++ b/packages/controls/src/widget_upload.ts @@ -12,15 +12,13 @@ export class FileUploadModel extends CoreDOMWidgetModel { _model_name: 'FileUploadModel', _view_name: 'FileUploadView', - _counter: 0, accept: '', description: 'Upload', disabled: false, icon: 'upload', button_style: '', multiple: false, - metadata: [], - data: [], + value: [], error: '', style: null }); @@ -28,7 +26,8 @@ export class FileUploadModel extends CoreDOMWidgetModel { static serializers = { ...CoreDOMWidgetModel.serializers, - data: { serialize: (buffers: any): any[] => { return [...buffers]; } }, + // use a dummy serializer for value to circumvent the default serializer. + value: { serialize: (x: T): T => x }, }; } @@ -95,17 +94,14 @@ export class FileUploadView extends DOMWidgetView { Promise.all(promisesFile) .then(contents => { - const metadata: any[] = []; - const li_buffer: any[] = []; - contents.forEach(c => { - metadata.push(c.metadata); - li_buffer.push(c.buffer); + const value = contents.map(c => { + return { + metadata: c.metadata, + content: c.buffer + }; }); - const counter = this.model.get('_counter'); this.model.set({ - _counter: counter + contents.length, - metadata, - data: li_buffer, + value, error: '', }); this.touch(); @@ -128,8 +124,10 @@ export class FileUploadView extends DOMWidgetView { this.el.disabled = this.model.get('disabled'); this.el.setAttribute('title', this.model.get('tooltip')); - const description = `${this.model.get('description')} (${this.model.get('_counter')})` + const value: [] = this.model.get('value'); + const description = `${this.model.get('description')} (${value.length})`; const icon = this.model.get('icon'); + if (description.length || icon.length) { this.el.textContent = ''; if (icon.length) { diff --git a/packages/schema/jupyterwidgetmodels.latest.md b/packages/schema/jupyterwidgetmodels.latest.md index 46d1cc31f9..a8b3b56937 100644 --- a/packages/schema/jupyterwidgetmodels.latest.md +++ b/packages/schema/jupyterwidgetmodels.latest.md @@ -393,7 +393,6 @@ Attribute | Type | Default | Help Attribute | Type | Default | Help -----------------|------------------|------------------|---- -`_counter` | number (integer) | `0` | `_dom_classes` | array of string | `[]` | CSS classes applied to widget DOM element `_model_module` | string | `'@jupyter-widgets/controls'` | `_model_module_version` | string | `'1.5.0'` | @@ -403,17 +402,16 @@ Attribute | Type | Default | Help `_view_name` | string | `'FileUploadView'` | `accept` | string | `''` | File types to accept, empty string for all `button_style` | string (one of `'primary'`, `'success'`, `'info'`, `'warning'`, `'danger'`, `''`) | `''` | Use a predefined styling for the button. -`data` | array | `[]` | List of file content (bytes) `description` | string | `''` | Description of the control. `disabled` | boolean | `false` | Enable or disable button `error` | string | `''` | Error message `icon` | string | `'upload'` | Font-awesome icon name, without the 'fa-' prefix. `layout` | reference to Layout widget | reference to new instance | -`metadata` | array | `[]` | List of file metadata `multiple` | boolean | `false` | If True, allow for multiple files upload `style` | reference to ButtonStyle widget | reference to new instance | `tabbable` | `null` or boolean | `null` | Is widget tabbable? `tooltip` | `null` or string | `null` | A tooltip caption. +`value` | array | `[]` | The file upload value ### FloatLogSliderModel (@jupyter-widgets/controls, 1.5.0); FloatLogSliderView (@jupyter-widgets/controls, 1.5.0)