From f9f488d9aa8feb6f33ed9648da7e15991b324e49 Mon Sep 17 00:00:00 2001 From: Sergey Petushkov Date: Sun, 3 Apr 2022 10:58:13 +0100 Subject: [PATCH 1/2] fix(hadron-document, compass-components): Call Editor.start / stop when changing element value; Keep editing state inside Editor --- .../document-list/document.spec.tsx | 124 ++++++++++++++++++ .../src/components/document-list/document.tsx | 12 +- .../document-list/element-editors.tsx | 12 +- .../src/components/document-list/element.tsx | 8 ++ packages/hadron-document/src/editor/date.js | 6 +- .../hadron-document/src/editor/decimal128.js | 1 + packages/hadron-document/src/editor/double.js | 1 + packages/hadron-document/src/editor/int64.js | 1 + .../hadron-document/src/editor/objectid.js | 2 + .../hadron-document/src/editor/standard.js | 9 +- 10 files changed, 164 insertions(+), 12 deletions(-) create mode 100644 packages/compass-components/src/components/document-list/document.spec.tsx diff --git a/packages/compass-components/src/components/document-list/document.spec.tsx b/packages/compass-components/src/components/document-list/document.spec.tsx new file mode 100644 index 00000000000..592e977892e --- /dev/null +++ b/packages/compass-components/src/components/document-list/document.spec.tsx @@ -0,0 +1,124 @@ +import React from 'react'; +import { expect } from 'chai'; +import { render, cleanup, screen, within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import HadronDocument from 'hadron-document'; +import Document from './document'; + +describe('Document', function () { + let doc: HadronDocument; + beforeEach(function () { + doc = new HadronDocument({ str: 'abc', num: 123, date: new Date(0) }); + }); + + afterEach(cleanup); + + it('should render HadronDocument keys and values', function () { + render(); + expect(screen.getByText('str')).to.exist; + expect(screen.getByTitle('abc')).to.exist; + + expect(screen.getByText('num')).to.exist; + expect(screen.getByTitle('123')).to.exist; + + expect(screen.getByText('date')).to.exist; + expect(screen.getByTitle('1970-01-01T00:00:00.000+00:00')).to.exist; + }); + + describe('edit mode', function () { + it('should change element key name on edit', function () { + render(); + + const el = document.querySelector( + `[data-id="${doc.get('str').uuid}"]` + ); + const keyEditor = within(el).getByTestId('hadron-document-key-editor'); + + userEvent.clear(keyEditor); + userEvent.keyboard('new_name'); + userEvent.tab(); + + expect(screen.getByDisplayValue('new_name')).to.exist; + + expect(doc.get('new_name').key).to.eq('str'); + expect(doc.get('new_name').currentKey).to.eq('new_name'); + }); + + it('should change element string value on edit', function () { + render(); + + const el = document.querySelector( + `[data-id="${doc.get('str').uuid}"]` + ); + + const valueEditor = within(el).getByTestId( + 'hadron-document-value-editor' + ); + + userEvent.clear(valueEditor); + userEvent.keyboard('bla'); + userEvent.tab(); + + expect(doc.get('str').currentValue).to.eq('bla'); + expect(doc.get('str').currentType).to.eq('String'); + }); + + it('should change element number value on edit', function () { + render(); + + const el = document.querySelector( + `[data-id="${doc.get('num').uuid}"]` + ); + + const valueEditor = within(el).getByTestId( + 'hadron-document-value-editor' + ); + + userEvent.clear(valueEditor); + userEvent.keyboard('321'); + userEvent.tab(); + + expect(doc.get('num').currentValue.valueOf()).to.eq(321); + expect(doc.get('num').currentType).to.eq('Int32'); + }); + + it('should change element date value on edit', function () { + render(); + + const el = document.querySelector( + `[data-id="${doc.get('date').uuid}"]` + ); + + const valueEditor = within(el).getByTestId( + 'hadron-document-value-editor' + ); + + userEvent.clear(valueEditor); + userEvent.keyboard('2000-01-01'); + userEvent.tab(); + + expect((doc.get('date').currentValue as Date).toISOString()).to.eq( + '2000-01-01T00:00:00.000Z' + ); + expect(doc.get('date').currentType).to.eq('Date'); + }); + + it('should change element type on edit', function () { + render(); + + const el = document.querySelector( + `[data-id="${doc.get('num').uuid}"]` + ); + + const typeEditor = within(el).getByTestId( + 'hadron-document-type-editor' + ); + + userEvent.selectOptions(typeEditor, 'String') + userEvent.tab(); + + expect(doc.get('num').currentValue.valueOf()).to.eq('123'); + expect(doc.get('num').currentType).to.eq('String'); + }); + }); +}); diff --git a/packages/compass-components/src/components/document-list/document.tsx b/packages/compass-components/src/components/document-list/document.tsx index e253b484f42..01bbb4b710d 100644 --- a/packages/compass-components/src/components/document-list/document.tsx +++ b/packages/compass-components/src/components/document-list/document.tsx @@ -57,17 +57,17 @@ const hadronDocument = css({ const HadronDocument: React.FunctionComponent<{ value: HadronDocumentType; visibleFieldsCount?: number; - expanded: boolean; - editable: boolean; + expanded?: boolean; + editable?: boolean; + editing?: boolean; onEditStart?: () => void; - editing: boolean; }> = ({ value: document, visibleFieldsCount, - expanded, - editable, + expanded = false, + editable = false, + editing = false, onEditStart, - editing, }) => { const { elements } = useHadronDocument(document); const visibleElements = useMemo(() => { diff --git a/packages/compass-components/src/components/document-list/element-editors.tsx b/packages/compass-components/src/components/document-list/element-editors.tsx index 01c2b75df44..0318fbc3756 100644 --- a/packages/compass-components/src/components/document-list/element-editors.tsx +++ b/packages/compass-components/src/components/document-list/element-editors.tsx @@ -158,8 +158,10 @@ export const ValueEditor: React.FunctionComponent<{ valid: boolean; validationMessage: string | null; originalValue: TypeCastMap[keyof TypeCastMap]; - onChange(newVal: string): void; autoFocus?: boolean; + onChange(newVal: string): void; + onFocus(): void; + onBlur(): void; }> = ({ editing, onEditStart, @@ -168,8 +170,10 @@ export const ValueEditor: React.FunctionComponent<{ valid, validationMessage, originalValue, - onChange, autoFocus, + onChange, + onFocus, + onBlur }) => { const val = String(value); @@ -230,6 +234,8 @@ export const ValueEditor: React.FunctionComponent<{ onChange={(evt) => { onChange(evt.currentTarget.value); }} + onFocus={onFocus} + onBlur={onBlur} // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus={autoFocus} className={cx( @@ -251,6 +257,8 @@ export const ValueEditor: React.FunctionComponent<{ onChange={(evt) => { onChange(evt.currentTarget.value); }} + onFocus={onFocus} + onBlur={onBlur} // eslint-disable-next-line jsx-a11y/no-autofocus autoFocus={autoFocus} className={cx( diff --git a/packages/compass-components/src/components/document-list/element.tsx b/packages/compass-components/src/components/document-list/element.tsx index e7a14190452..cb6c6f195c3 100644 --- a/packages/compass-components/src/components/document-list/element.tsx +++ b/packages/compass-components/src/components/document-list/element.tsx @@ -139,6 +139,8 @@ function useHadronElement(el: HadronElementType) { el.currentType !== 'Array', valid: isValid, validationMessage: !isValid ? el.invalidTypeMessage ?? null : null, + startEdit: editor.start.bind(editor), + completeEdit: editor.complete.bind(editor), }, type: { value: el.currentType, @@ -486,6 +488,12 @@ export const HadronElement: React.FunctionComponent<{ onEditStart={() => { onEditStart?.(element.uuid, 'value'); }} + onFocus={() => { + value.startEdit(); + }} + onBlur={() => { + value.completeEdit(); + }} > ) : ( Date: Sun, 3 Apr 2022 11:13:47 +0100 Subject: [PATCH 2/2] chore(compass-components): Reformat --- .../src/components/document-list/document.spec.tsx | 6 ++---- .../src/components/document-list/element-editors.tsx | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/compass-components/src/components/document-list/document.spec.tsx b/packages/compass-components/src/components/document-list/document.spec.tsx index 592e977892e..5aab0a0e56c 100644 --- a/packages/compass-components/src/components/document-list/document.spec.tsx +++ b/packages/compass-components/src/components/document-list/document.spec.tsx @@ -110,11 +110,9 @@ describe('Document', function () { `[data-id="${doc.get('num').uuid}"]` ); - const typeEditor = within(el).getByTestId( - 'hadron-document-type-editor' - ); + const typeEditor = within(el).getByTestId('hadron-document-type-editor'); - userEvent.selectOptions(typeEditor, 'String') + userEvent.selectOptions(typeEditor, 'String'); userEvent.tab(); expect(doc.get('num').currentValue.valueOf()).to.eq('123'); diff --git a/packages/compass-components/src/components/document-list/element-editors.tsx b/packages/compass-components/src/components/document-list/element-editors.tsx index 0318fbc3756..f18bb0695c0 100644 --- a/packages/compass-components/src/components/document-list/element-editors.tsx +++ b/packages/compass-components/src/components/document-list/element-editors.tsx @@ -173,7 +173,7 @@ export const ValueEditor: React.FunctionComponent<{ autoFocus, onChange, onFocus, - onBlur + onBlur, }) => { const val = String(value);