diff --git a/lit_nlp/client/modules/datapoint_editor_module.css b/lit_nlp/client/modules/datapoint_editor_module.css index 4ae9f921..a7499263 100644 --- a/lit_nlp/client/modules/datapoint_editor_module.css +++ b/lit_nlp/client/modules/datapoint_editor_module.css @@ -213,3 +213,12 @@ mwc-icon.google-icon { margin-bottom: 1px; margin-left: 4px; } + +.hidden { + display: none; +} + +.image-button { + margin-left: 0; +} + diff --git a/lit_nlp/client/modules/datapoint_editor_module.ts b/lit_nlp/client/modules/datapoint_editor_module.ts index edac1a28..ac876bb7 100644 --- a/lit_nlp/client/modules/datapoint_editor_module.ts +++ b/lit_nlp/client/modules/datapoint_editor_module.ts @@ -253,6 +253,7 @@ export class DatapointEditorModule extends LitModule { }; const onClickReset = () => { this.resetEditedData( + this.selectionService.primarySelectedInputData == null ? null : this.selectionService.primarySelectedInputData!.data); }; const onClickClear = () => { @@ -346,18 +347,55 @@ export class DatapointEditorModule extends LitModule { this.maximizedImageFields.add(key); } }; + const uploadClicked = () => { + (this.shadowRoot!.querySelector( + '#uploadimage') as HTMLInputElement).click(); + }; + const handleUpload = (e: Event) => { + const inputElem = e.target as HTMLInputElement; + const file = inputElem.files == null || inputElem.files.length === 0 ? + null : + inputElem.files[0]; + if (file == null) { + return; + } + const reader = new FileReader(); + reader.addEventListener('load', () => { + const result = reader.result as string; + this.datapointEdited = true; + this.editedData[key] = result; + }); + reader.readAsDataURL(file); + inputElem.value = ''; + }; const maximizeImage = this.maximizedImageFields.has(key); + const imageSource = (value == null) ? '' : value.toString() as string; + const noImage = imageSource === ''; const imageClasses = classMap({ 'image-min': !maximizeImage, + 'hidden': noImage }); - const imageSource = (value == null) ? '' : value.toString() as string; + const toggleClasses = classMap({ + 'image-toggle': true, + 'hidden': noImage + }); + const uploadLabel = noImage ? 'Upload image' : 'Replace image'; return html`
- - ${maximizeImage ? 'close_fullscreen' : 'open_in_full'} + ${maximizeImage ? + 'photo_size_select_small' : 'photo_size_select_large'} +
+ + +
`; }; diff --git a/lit_nlp/client/modules/scalar_module.ts b/lit_nlp/client/modules/scalar_module.ts index 7dce2691..e7286f39 100644 --- a/lit_nlp/client/modules/scalar_module.ts +++ b/lit_nlp/client/modules/scalar_module.ts @@ -98,6 +98,7 @@ export class ScalarModule extends LitModule { // there are multiple pred keys). private readonly brushObjects: BrushObject[] = []; + @observable private readonly isPlotHidden = new Map(); @observable private preds: Preds[] = []; @observable private plotWidth = ScalarModule.maxPlotWidth; @observable private plotHeight = ScalarModule.minPlotHeight; @@ -859,16 +860,29 @@ export class ScalarModule extends LitModule { const plotLabel = `${axisTitle}${selectedValue ? ` - ${selectedValue}` : ''}`; + const toggleCollapse = () => { + const isHidden = (this.isPlotHidden.get(axisTitle) == null) ? + collapseByDefault : this.isPlotHidden.get(axisTitle); + this.isPlotHidden.set(axisTitle, !isHidden); + }; + // This plot's value in isPlotHidden gets set in toggleCollapse and is null + // before the user opens/closes it for the first time. This uses the + // collapseByDefault setting if isPlotHidden hasn't been set yet. + const isHidden = (this.isPlotHidden.get(axisTitle) == null) ? + collapseByDefault : this.isPlotHidden.get(axisTitle); + // clang-format off return html`
- + + ${isHidden ? null : html`
${svg` `} -
+
`} `; // clang-format on