From 8a996aca526fdcbbf77e69e7dbac443410801fa9 Mon Sep 17 00:00:00 2001 From: Tom Herold Date: Wed, 8 Feb 2023 10:07:22 +0100 Subject: [PATCH] Fix editable text style (#6799) * refactored input component TS types * fix CSS line breaks for dataset description + name * fix some types * fix segment list line breaks * fixed lined breaks in segments list * applied PR feedback * fix ENTER key for multiline text inputs --- CHANGELOG.unreleased.md | 1 + .../admin/dataset/dataset_upload_view.tsx | 2 +- .../components/text_with_description.tsx | 6 +- frontend/javascripts/libs/vector_input.tsx | 17 ++-- .../view/action-bar/dataset_position_view.tsx | 2 - .../view/components/editable_text_label.tsx | 98 +++++++++---------- .../view/components/input_component.tsx | 54 ++++++++-- .../oxalis/view/components/markdown_modal.tsx | 2 +- .../comment_tab/comment_tab_view.tsx | 13 ++- .../dataset_info_tab_view.tsx | 8 +- .../segments_tab/segment_list_item.tsx | 88 +++++++++-------- 11 files changed, 166 insertions(+), 125 deletions(-) diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 3a2328b574a..c27b04d99d8 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -20,6 +20,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released ### Fixed - Fixed saving allowed teams in dataset settings. [#6817](https://github.com/scalableminds/webknossos/pull/6817) - Fixed log streaming in Voxelytics workflow reports. [#6828](https://github.com/scalableminds/webknossos/pull/6828) +- Fixed some layouting issues with line breaks in segment list/dataset info tab [#6799](https://github.com/scalableminds/webknossos/pull/6799) ### Removed diff --git a/frontend/javascripts/admin/dataset/dataset_upload_view.tsx b/frontend/javascripts/admin/dataset/dataset_upload_view.tsx index 04b1fde0ae9..31775d379d6 100644 --- a/frontend/javascripts/admin/dataset/dataset_upload_view.tsx +++ b/frontend/javascripts/admin/dataset/dataset_upload_view.tsx @@ -743,7 +743,7 @@ class DatasetUploadView extends React.Component { width: 400, }} allowDecimals - onChange={(scale) => { + onChange={(scale: Vector3) => { if (this.formRef.current == null) return; this.formRef.current.setFieldsValue({ scale, diff --git a/frontend/javascripts/components/text_with_description.tsx b/frontend/javascripts/components/text_with_description.tsx index 30414e7cdb4..999424c0d63 100644 --- a/frontend/javascripts/components/text_with_description.tsx +++ b/frontend/javascripts/components/text_with_description.tsx @@ -4,11 +4,13 @@ import Markdown from "react-remarkable"; import * as React from "react"; import type { EditableTextLabelProp } from "oxalis/view/components/editable_text_label"; import EditableTextLabel from "oxalis/view/components/editable_text_label"; + type EditableProps = EditableTextLabelProp & { isEditable: true; description: string; }; type NonEditableProps = { + markdown?: boolean; isEditable: false; description: string; value: string; @@ -61,8 +63,7 @@ class TextWithDescription extends React.PureComponent { ) : null} - {/* @ts-expect-error ts-migrate(2322) FIXME: Type 'string | null' is not assignable to type 'st... Remove this comment to see the full error message */} - + {isEditable ? ( // @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call. @@ -73,7 +74,6 @@ class TextWithDescription extends React.PureComponent { display: "inline-block", }} > - {/* @ts-expect-error ts-migrate(2339) FIXME: Property 'markdown' does not exist on type 'Readon... Remove this comment to see the full error message */} {this.props.markdown ? ( = Omit & { +type BaseProps = Omit & { value: T | string; onChange: (value: T) => void; changeOnlyOnBlur?: boolean; allowDecimals?: boolean; + autoSize?: boolean; }; type State = { isEditing: boolean; @@ -51,7 +55,7 @@ class BaseVector extends React.PureComponent { + handleBlur = (_: React.FocusEvent) => { this.setState({ isEditing: false, }); @@ -89,7 +93,7 @@ class BaseVector extends React.PureComponent { + handleFocus = (_event: React.FocusEvent) => { this.setState({ isEditing: true, text: this.getText(this.props.value), @@ -127,7 +131,6 @@ class BaseVector extends React.PureComponent extends React.PureComponent ); } @@ -147,7 +151,7 @@ export class Vector3Input extends BaseVector { export class Vector6Input extends BaseVector { defaultValue: Vector6 = [0, 0, 0, 0, 0, 0]; } -type BoundingBoxInputProps = Omit & { +type BoundingBoxInputProps = Omit & { value: ServerBoundingBoxTypeTuple; onChange: (arg0: ServerBoundingBoxTypeTuple) => void; }; @@ -179,7 +183,6 @@ export class BoundingBoxInput extends React.PureComponent {...props} value={vector6Value} changeOnlyOnBlur - // @ts-expect-error ts-migrate(2322) FIXME: Type '([x, y, z, width, height, depth]: [any, any,... Remove this comment to see the full error message onChange={([x, y, z, width, height, depth]) => onChange({ topLeft: [x, y, z], diff --git a/frontend/javascripts/oxalis/view/action-bar/dataset_position_view.tsx b/frontend/javascripts/oxalis/view/action-bar/dataset_position_view.tsx index 3a49d5f60ec..be90f90322e 100644 --- a/frontend/javascripts/oxalis/view/action-bar/dataset_position_view.tsx +++ b/frontend/javascripts/oxalis/view/action-bar/dataset_position_view.tsx @@ -129,7 +129,6 @@ class DatasetPositionView extends PureComponent { void' is not assignab... Remove this comment to see the full error message onChange={this.handleChangePosition} autoSize // @ts-expect-error ts-migrate(2322) FIXME: Type '{ textAlign: string; }' is not assignable to... Remove this comment to see the full error message @@ -159,7 +158,6 @@ class DatasetPositionView extends PureComponent { void' is not assignab... Remove this comment to see the full error message onChange={this.handleChangeRotation} style={{ textAlign: "center", diff --git a/frontend/javascripts/oxalis/view/components/editable_text_label.tsx b/frontend/javascripts/oxalis/view/components/editable_text_label.tsx index 560c860a954..c49fe557f39 100644 --- a/frontend/javascripts/oxalis/view/components/editable_text_label.tsx +++ b/frontend/javascripts/oxalis/view/components/editable_text_label.tsx @@ -58,9 +58,8 @@ class EditableTextLabel extends React.PureComponent { + handleInputChange = (event: React.ChangeEvent) => { this.setState({ - // @ts-expect-error ts-migrate(2339) FIXME: Property 'value' does not exist on type 'EventTarg... Remove this comment to see the full error message value: event.target.value, }); }; @@ -125,14 +124,12 @@ class EditableTextLabel extends React.PureComponent + {this.props.rows === 1 ? ( this.handleOnChange} /> @@ -159,56 +156,51 @@ class EditableTextLabel extends React.PureComponent - - {this.props.markdown ? ( - + {this.props.markdown ? ( + + ) : ( + {this.props.value} + )} + {this.props.disableEditing ? null : ( + + { + evt.stopPropagation(); + this.setState({ + isEditing: true, + }); }} - container="span" - style={isInvalidStyleMaybe} /> - ) : ( - {this.props.value} - )} - {this.props.disableEditing ? null : ( - - { - evt.stopPropagation(); - this.setState({ - isEditing: true, - }); - }} - /> - - )} - - + + )} + ); } } diff --git a/frontend/javascripts/oxalis/view/components/input_component.tsx b/frontend/javascripts/oxalis/view/components/input_component.tsx index 7a3affafb50..88650198ab8 100644 --- a/frontend/javascripts/oxalis/view/components/input_component.tsx +++ b/frontend/javascripts/oxalis/view/components/input_component.tsx @@ -3,11 +3,36 @@ import * as React from "react"; import _ from "lodash"; import TextArea, { TextAreaProps } from "antd/lib/input/TextArea"; -export type InputComponentProps = InputProps & - TextAreaProps & { - title?: React.ReactNode; - isTextArea?: boolean; - }; +export type InputComponentProps = InputComponentCommonProps & + (InputElementProps | TextAreaElementProps); + +export type InputComponentCommonProps = { + value: React.InputHTMLAttributes["value"]; + title?: React.ReactNode; + style?: React.InputHTMLAttributes["style"]; + placeholder?: React.InputHTMLAttributes["placeholder"]; + disabled?: React.InputHTMLAttributes["disabled"]; + size?: InputProps["size"]; +}; + +export type InputElementProps = { + // The discriminated union + isTextArea?: false; + onChange?: React.ChangeEventHandler; + onBlur?: React.FocusEventHandler; + onFocus?: React.FocusEventHandler; + onPressEnter?: React.KeyboardEventHandler; +}; + +type TextAreaElementProps = { + isTextArea: true; + autoSize: TextAreaProps["autoSize"]; + rows: TextAreaProps["rows"]; + onChange?: React.ChangeEventHandler; + onBlur?: React.FocusEventHandler; + onFocus?: React.FocusEventHandler; + onPressEnter?: React.KeyboardEventHandler; +}; type InputComponentState = { isFocused: boolean; @@ -26,8 +51,6 @@ type InputComponentState = { class InputComponent extends React.PureComponent { static defaultProps: InputComponentProps = { onChange: _.noop, - onFocus: _.noop, - onBlur: _.noop, onPressEnter: undefined, placeholder: "", value: "", @@ -96,9 +119,19 @@ class InputComponent extends React.PureComponent + ) : ( + ); + // The input needs to be wrapped in a span in order for the tooltip to work. See https://github.com/react-component/tooltip/issues/18#issuecomment-140078802. return title != null ? ( diff --git a/frontend/javascripts/oxalis/view/components/markdown_modal.tsx b/frontend/javascripts/oxalis/view/components/markdown_modal.tsx index 197d6878d2e..79e2059beb9 100644 --- a/frontend/javascripts/oxalis/view/components/markdown_modal.tsx +++ b/frontend/javascripts/oxalis/view/components/markdown_modal.tsx @@ -33,7 +33,7 @@ export function MarkdownModal({ label: string; isOpen?: boolean; onOk: () => void; - onChange: (arg0: React.SyntheticEvent) => void; + onChange: React.ChangeEventHandler; }) { return ( this.nextComment(false); }; - handleChangeInput = (evt: React.SyntheticEvent, insertLineBreaks: boolean = false) => { + handleChangeInput = ( + evt: React.ChangeEvent, + insertLineBreaks: boolean = false, + ) => { // @ts-ignore const commentText = evt.target.value; @@ -456,8 +459,12 @@ class CommentTabView extends React.Component ? undefined : messages["tracing.read_only_mode_notification"] } - onChange={(evt) => this.handleChangeInput(evt, true)} - onPressEnter={(evt) => (evt.target as HTMLElement).blur()} + onChange={(evt: React.ChangeEvent) => + this.handleChangeInput(evt, true) + } + onPressEnter={(evt: React.KeyboardEvent) => + (evt.target as HTMLElement).blur() + } placeholder="Add comment" style={{ width: "50%", diff --git a/frontend/javascripts/oxalis/view/right-border-tabs/dataset_info_tab_view.tsx b/frontend/javascripts/oxalis/view/right-border-tabs/dataset_info_tab_view.tsx index 0b6e5f12dda..c9d82eeb89e 100644 --- a/frontend/javascripts/oxalis/view/right-border-tabs/dataset_info_tab_view.tsx +++ b/frontend/javascripts/oxalis/view/right-border-tabs/dataset_info_tab_view.tsx @@ -459,7 +459,11 @@ class DatasetInfoTabView extends React.PureComponent { } else { // Or display the editable explorative tracing name annotationTypeLabel = ( - + Annotation: { descriptionEditField = ( Description: diff --git a/frontend/javascripts/oxalis/view/right-border-tabs/segments_tab/segment_list_item.tsx b/frontend/javascripts/oxalis/view/right-border-tabs/segments_tab/segment_list_item.tsx index c7bd26de746..10577c24540 100644 --- a/frontend/javascripts/oxalis/view/right-border-tabs/segments_tab/segment_list_item.tsx +++ b/frontend/javascripts/oxalis/view/right-border-tabs/segments_tab/segment_list_item.tsx @@ -470,52 +470,54 @@ function _SegmentListItem({ trigger={["contextMenu"]} > - - onSelectSegment(segment)} - onChange={(name) => { - if (visibleSegmentationLayer != null) { - updateSegment( - segment.id, - { - name, - }, - visibleSegmentationLayer.name, - ); - } - }} - margin="0 5px" - disableEditing={!allowUpdate} - /> - - handleSegmentDropdownMenuVisibility(segment.id, true)} +
+ + onSelectSegment(segment)} + onChange={(name) => { + if (visibleSegmentationLayer != null) { + updateSegment( + segment.id, + { + name, + }, + visibleSegmentationLayer.name, + ); + } + }} + margin="0 5px" + disableEditing={!allowUpdate} /> - - {/* Show Default Segment Name if another one is already defined*/} - {getSegmentIdDetails()} - {segment.id === centeredSegmentId ? ( - - - - ) : null} - {segment.id === activeCellId ? ( - - + handleSegmentDropdownMenuVisibility(segment.id, true)} /> - ) : null} + {/* Show Default Segment Name if another one is already defined*/} + {getSegmentIdDetails()} + {segment.id === centeredSegmentId ? ( + + + + ) : null} + {segment.id === activeCellId ? ( + + + + ) : null} +