From 23b548bdcbbaaef25935ccd36dbd4881a285c01e Mon Sep 17 00:00:00 2001 From: Basit Date: Wed, 17 Aug 2022 10:31:25 +0200 Subject: [PATCH 01/23] use tg table for indexes --- .../components/drop-column/drop-column.jsx | 68 --------- .../src/components/drop-column/index.js | 2 - .../index-component/index-component.jsx | 71 --------- .../index-component/index-component.spec.jsx | 64 -------- .../src/components/index-component/index.js | 2 - .../index-header-column.jsx | 71 --------- .../index-header-column.spec.jsx | 55 ------- .../components/index-header-column/index.js | 2 - .../components/index-header/index-header.jsx | 80 ---------- .../index-header/index-header.spec.jsx | 95 ------------ .../src/components/index-header/index.js | 2 - .../src/components/index-list/index-list.jsx | 44 ------ .../components/index-list/index-list.spec.jsx | 53 ------- .../src/components/index-list/index.js | 2 - .../indexes-table/badge-with-icon-link.tsx | 49 ++++++ .../components/indexes-table/drop-field.tsx | 24 +++ .../indexes-table/indexes-table.tsx | 143 ++++++++++++++++++ .../components/indexes-table/name-field.tsx | 49 ++++++ .../indexes-table/property-field.tsx | 84 ++++++++++ .../components/indexes-table/size-field.tsx | 35 +++++ .../components/indexes-table/type-field.tsx | 56 +++++++ .../components/indexes-table/usage-field.tsx | 42 +++++ .../src/components/indexes/indexes.jsx | 121 +++------------ .../src/components/name-column/index.js | 2 - .../components/name-column/name-column.jsx | 59 -------- .../src/components/property-column/index.js | 2 - .../property-column/property-column.jsx | 122 --------------- .../src/components/size-column/index.js | 2 - .../components/size-column/size-column.jsx | 46 ------ .../src/components/type-column/index.js | 2 - .../components/type-column/type-column.jsx | 93 ------------ .../src/components/usage-column/index.js | 2 - .../components/usage-column/usage-column.jsx | 60 -------- .../compass-indexes/src/modules/indexes.js | 30 ++-- .../src/utils/index-link-helper.ts | 4 +- 35 files changed, 520 insertions(+), 1118 deletions(-) delete mode 100644 packages/compass-indexes/src/components/drop-column/drop-column.jsx delete mode 100644 packages/compass-indexes/src/components/drop-column/index.js delete mode 100644 packages/compass-indexes/src/components/index-component/index-component.jsx delete mode 100644 packages/compass-indexes/src/components/index-component/index-component.spec.jsx delete mode 100644 packages/compass-indexes/src/components/index-component/index.js delete mode 100644 packages/compass-indexes/src/components/index-header-column/index-header-column.jsx delete mode 100644 packages/compass-indexes/src/components/index-header-column/index-header-column.spec.jsx delete mode 100644 packages/compass-indexes/src/components/index-header-column/index.js delete mode 100644 packages/compass-indexes/src/components/index-header/index-header.jsx delete mode 100644 packages/compass-indexes/src/components/index-header/index-header.spec.jsx delete mode 100644 packages/compass-indexes/src/components/index-header/index.js delete mode 100644 packages/compass-indexes/src/components/index-list/index-list.jsx delete mode 100644 packages/compass-indexes/src/components/index-list/index-list.spec.jsx delete mode 100644 packages/compass-indexes/src/components/index-list/index.js create mode 100644 packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/drop-field.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/indexes-table.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/name-field.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/property-field.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/size-field.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/type-field.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/usage-field.tsx delete mode 100644 packages/compass-indexes/src/components/name-column/index.js delete mode 100644 packages/compass-indexes/src/components/name-column/name-column.jsx delete mode 100644 packages/compass-indexes/src/components/property-column/index.js delete mode 100644 packages/compass-indexes/src/components/property-column/property-column.jsx delete mode 100644 packages/compass-indexes/src/components/size-column/index.js delete mode 100644 packages/compass-indexes/src/components/size-column/size-column.jsx delete mode 100644 packages/compass-indexes/src/components/type-column/index.js delete mode 100644 packages/compass-indexes/src/components/type-column/type-column.jsx delete mode 100644 packages/compass-indexes/src/components/usage-column/index.js delete mode 100644 packages/compass-indexes/src/components/usage-column/usage-column.jsx diff --git a/packages/compass-indexes/src/components/drop-column/drop-column.jsx b/packages/compass-indexes/src/components/drop-column/drop-column.jsx deleted file mode 100644 index 769ba93bd91..00000000000 --- a/packages/compass-indexes/src/components/drop-column/drop-column.jsx +++ /dev/null @@ -1,68 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { IconButton, Icon } from '@mongodb-js/compass-components'; - -/** - * Component for the drop column. - */ -class DropColumn extends PureComponent { - static displayName = 'DropColumn'; - - static propTypes = { - indexName: PropTypes.string.isRequired, - isReadonly: PropTypes.bool.isRequired, - isWritable: PropTypes.bool.isRequired, - localAppRegistry: PropTypes.object.isRequired, - }; - - /** - * Show drop index modal when drop button is clicked. - * - * @param {Object} evt - The click event. - */ - clickDropHandler(evt) { - evt.preventDefault(); - evt.stopPropagation(); - this.props.localAppRegistry.emit( - 'toggle-drop-index-modal', - true, - this.props.indexName - ); - } - - /** - * Is the index droppable? - * - * @returns {Boolean} If the index can be dropped. - */ - isDroppable() { - return ( - this.props.isWritable && - this.props.indexName !== '_id_' && - !this.props.isReadonly - ); - } - - /** - * Render the drop column. - * - * @returns {React.Component} The drop column. - */ - render() { - return ( - - {this.isDroppable() ? ( - - - - ) : null} - - ); - } -} - -export default DropColumn; diff --git a/packages/compass-indexes/src/components/drop-column/index.js b/packages/compass-indexes/src/components/drop-column/index.js deleted file mode 100644 index f699f609125..00000000000 --- a/packages/compass-indexes/src/components/drop-column/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import DropColumn from './drop-column'; -export default DropColumn; diff --git a/packages/compass-indexes/src/components/index-component/index-component.jsx b/packages/compass-indexes/src/components/index-component/index-component.jsx deleted file mode 100644 index a346f3d3620..00000000000 --- a/packages/compass-indexes/src/components/index-component/index-component.jsx +++ /dev/null @@ -1,71 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import NameColumn from '../name-column'; -import TypeColumn from '../type-column'; -import SizeColumn from '../size-column'; -import UsageColumn from '../usage-column'; -import PropertyColumn from '../property-column'; -import DropColumn from '../drop-column'; - -import { css, spacing, uiColors } from '@mongodb-js/compass-components'; - -const containerStyles = css({ - backgroundColor: uiColors.white, - boxShadow: '0 2px 10px 0 rgba(0, 0, 0, 0.075)', - td: { - padding: spacing[3], - }, -}); - -/** - * Component for the index. - */ -class IndexComponent extends PureComponent { - static displayName = 'IndexComponent'; - static propTypes = { - index: PropTypes.object.isRequired, - isReadonly: PropTypes.bool.isRequired, - isWritable: PropTypes.bool.isRequired, - localAppRegistry: PropTypes.object.isRequired, - changeName: PropTypes.func.isRequired, - openLink: PropTypes.func.isRequired, - }; - - /** - * Render the index. - * - * @returns {React.Component} The index. - */ - render() { - return ( - - - - - - - - - ); - } -} - -export default IndexComponent; diff --git a/packages/compass-indexes/src/components/index-component/index-component.spec.jsx b/packages/compass-indexes/src/components/index-component/index-component.spec.jsx deleted file mode 100644 index f8cdaa3444b..00000000000 --- a/packages/compass-indexes/src/components/index-component/index-component.spec.jsx +++ /dev/null @@ -1,64 +0,0 @@ -import React from 'react'; -import { mount } from 'enzyme'; -import { expect } from 'chai'; -import AppRegistry from 'hadron-app-registry'; - -import IndexComponent from '../index-component'; - -import NameColumn from '../name-column'; -import TypeColumn from '../type-column'; -import SizeColumn from '../size-column'; -import UsageColumn from '../usage-column'; -import PropertyColumn from '../property-column'; -import DropColumn from '../drop-column'; - -const index = { - name: 'a', - type: 'regular', - fields: { serialize: () => [] }, - size: 10, - relativeSize: 10, - properties: [], -}; - -describe('index-component [Component]', function () { - const localAppRegistry = new AppRegistry(); - let component; - - describe('render', function () { - beforeEach(function () { - component = mount( - {}} - changeName={() => {}} - openLink={() => {}} - index={index} - /> - ); - }); - afterEach(function () { - component = null; - }); - it('renders the type column', function () { - expect(component.find(TypeColumn)).to.be.present(); - }); - it('renders the size column', function () { - expect(component.find(SizeColumn)).to.be.present(); - }); - it('renders the usage column', function () { - expect(component.find(UsageColumn)).to.be.present(); - }); - it('renders the property column', function () { - expect(component.find(PropertyColumn)).to.be.present(); - }); - it('renders the drop column', function () { - expect(component.find(DropColumn)).to.be.present(); - }); - it('renders the name column', function () { - expect(component.find(NameColumn)).to.be.present(); - }); - }); -}); diff --git a/packages/compass-indexes/src/components/index-component/index.js b/packages/compass-indexes/src/components/index-component/index.js deleted file mode 100644 index 3fb0007ed3c..00000000000 --- a/packages/compass-indexes/src/components/index-component/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import IndexComponent from './index-component'; -export default IndexComponent; diff --git a/packages/compass-indexes/src/components/index-header-column/index-header-column.jsx b/packages/compass-indexes/src/components/index-header-column/index-header-column.jsx deleted file mode 100644 index 698032ad0ca..00000000000 --- a/packages/compass-indexes/src/components/index-header-column/index-header-column.jsx +++ /dev/null @@ -1,71 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { css, cx, uiColors, spacing } from '@mongodb-js/compass-components'; - -import { DEFAULT, DESC, ASC } from '../../modules/indexes'; - -const headerStyles = css({ - paddingTop: spacing[2], - paddingBottom: spacing[2], - paddingRight: spacing[4], - paddingLeft: spacing[4], -}); - -const sortStyles = css({ - display: 'inline-block', - color: uiColors.gray.base, -}); - -/** - * Component for an index header column. - */ -class IndexHeaderColumn extends PureComponent { - static displayName = 'IndexHeaderColumn'; - static propTypes = { - indexes: PropTypes.array.isRequired, - sortOrder: PropTypes.string.isRequired, - sortColumn: PropTypes.string.isRequired, - dataTestId: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - sortIndexes: PropTypes.func.isRequired, - }; - - /** - * Handle the index sort click. - * - * @param {Event} evt - The event. - */ - handleIndexSort(evt) { - evt.preventDefault(); - evt.stopPropagation(); - let order; - if (this.props.sortColumn === this.props.name) { - order = this.props.sortOrder === ASC ? DESC : ASC; - } else { - order = this.props.sortColumn === DEFAULT ? ASC : DESC; - } - this.props.sortIndexes(this.props.indexes, this.props.name, order); - } - - /** - * Render the index header column. - * - * @returns {React.Component} The index header column. - */ - render() { - return ( - - {this.props.name} - {this.props.sortColumn === this.props.name && ( - - )} - - ); - } -} - -export default IndexHeaderColumn; diff --git a/packages/compass-indexes/src/components/index-header-column/index-header-column.spec.jsx b/packages/compass-indexes/src/components/index-header-column/index-header-column.spec.jsx deleted file mode 100644 index 6ce69ad24ba..00000000000 --- a/packages/compass-indexes/src/components/index-header-column/index-header-column.spec.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import React from 'react'; -import { mount } from 'enzyme'; -import { expect } from 'chai'; -import sinon from 'sinon'; - -import IndexHeaderColumn from '../index-header-column'; - -describe('index-header-column [Component]', function () { - let component; - let sortSpy; - describe('not active', function () { - beforeEach(function () { - sortSpy = sinon.spy(); - component = mount( - - ); - }); - afterEach(function () { - component = null; - sortSpy = null; - }); - it('renders the correct root classname', function () { - expect(component.find('[data-test-id="testid"]')).to.be.present(); - }); - }); - describe('active', function () { - beforeEach(function () { - sortSpy = sinon.spy(); - component = mount( - - ); - }); - afterEach(function () { - component = null; - sortSpy = null; - }); - it('renders the correct root classname', function () { - expect(component.find('[data-test-id="testid"]')).to.be.present(); - }); - }); -}); diff --git a/packages/compass-indexes/src/components/index-header-column/index.js b/packages/compass-indexes/src/components/index-header-column/index.js deleted file mode 100644 index 0c720ada8c1..00000000000 --- a/packages/compass-indexes/src/components/index-header-column/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import IndexHeaderColumn from './index-header-column'; -export default IndexHeaderColumn; diff --git a/packages/compass-indexes/src/components/index-header/index-header.jsx b/packages/compass-indexes/src/components/index-header/index-header.jsx deleted file mode 100644 index 7e75b444371..00000000000 --- a/packages/compass-indexes/src/components/index-header/index-header.jsx +++ /dev/null @@ -1,80 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { css } from '@mongodb-js/compass-components'; -import IndexHeaderColumn from '../index-header-column'; - -const containerStyles = css({ - textAlign: 'left', -}); - -/** - * Component for the index header. - */ -class IndexHeader extends PureComponent { - static displayName = 'IndexHeader'; - static propTypes = { - isWritable: PropTypes.bool.isRequired, - isReadonly: PropTypes.bool.isRequired, - indexes: PropTypes.array.isRequired, - sortOrder: PropTypes.string.isRequired, - sortColumn: PropTypes.string.isRequired, - sortIndexes: PropTypes.func.isRequired, - }; - - /** - * Render the index header. - * - * @returns {React.Component} The index header. - */ - render() { - return ( - - - - - - - - {!this.props.isReadonly && this.props.isWritable ? : null} - - - ); - } -} - -export default IndexHeader; diff --git a/packages/compass-indexes/src/components/index-header/index-header.spec.jsx b/packages/compass-indexes/src/components/index-header/index-header.spec.jsx deleted file mode 100644 index e39f59987d3..00000000000 --- a/packages/compass-indexes/src/components/index-header/index-header.spec.jsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from 'react'; -import { mount } from 'enzyme'; -import { expect } from 'chai'; - -import IndexHeader from '../index-header'; - -describe('index-header [Component]', function () { - let component; - describe('isReadable', function () { - beforeEach(function () { - component = mount( - {}} - /> - ); - }); - afterEach(function () { - component = null; - }); - - it('renders name column header', function () { - expect( - component.find('[data-test-id="index-header-name"]') - ).to.be.present(); - }); - it('renders type column header', function () { - expect( - component.find('[data-test-id="index-header-type"]') - ).to.be.present(); - }); - it('renders size column header', function () { - expect( - component.find('[data-test-id="index-header-size"]') - ).to.be.present(); - }); - it('renders usage column header', function () { - expect( - component.find('[data-test-id="index-header-usage"]') - ).to.be.present(); - }); - it('renders properties column header', function () { - expect( - component.find('[data-test-id="index-header-properties"]') - ).to.be.present(); - }); - }); - describe('isReadonly', function () { - beforeEach(function () { - component = mount( - {}} - /> - ); - }); - afterEach(function () { - component = null; - }); - - it('renders name column header', function () { - expect( - component.find('[data-test-id="index-header-name"]') - ).to.be.present(); - }); - it('renders type column header', function () { - expect( - component.find('[data-test-id="index-header-type"]') - ).to.be.present(); - }); - it('renders size column header', function () { - expect( - component.find('[data-test-id="index-header-size"]') - ).to.be.present(); - }); - it('renders usage column header', function () { - expect( - component.find('[data-test-id="index-header-usage"]') - ).to.be.present(); - }); - it('renders properties column header', function () { - expect( - component.find('[data-test-id="index-header-properties"]') - ).to.be.present(); - }); - }); -}); diff --git a/packages/compass-indexes/src/components/index-header/index.js b/packages/compass-indexes/src/components/index-header/index.js deleted file mode 100644 index e20ae7ac2a0..00000000000 --- a/packages/compass-indexes/src/components/index-header/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import IndexHeader from './index-header'; -export default IndexHeader; diff --git a/packages/compass-indexes/src/components/index-list/index-list.jsx b/packages/compass-indexes/src/components/index-list/index-list.jsx deleted file mode 100644 index c597e186571..00000000000 --- a/packages/compass-indexes/src/components/index-list/index-list.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import map from 'lodash.map'; -import IndexComponent from '../index-component'; - -/** - * Component for the index list. - */ -class IndexList extends PureComponent { - static displayName = 'IndexList'; - - static propTypes = { - indexes: PropTypes.array.isRequired, - isReadonly: PropTypes.bool.isRequired, - isWritable: PropTypes.bool.isRequired, - localAppRegistry: PropTypes.object.isRequired, - changeName: PropTypes.func.isRequired, - openLink: PropTypes.func.isRequired, - }; - - /** - * Render the index list. - * - * @returns {React.Component} The index list. - */ - render() { - const indexes = map(this.props.indexes, (model) => { - return ( - - ); - }); - return {indexes}; - } -} - -export default IndexList; diff --git a/packages/compass-indexes/src/components/index-list/index-list.spec.jsx b/packages/compass-indexes/src/components/index-list/index-list.spec.jsx deleted file mode 100644 index d399588a59c..00000000000 --- a/packages/compass-indexes/src/components/index-list/index-list.spec.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from 'react'; -import { mount } from 'enzyme'; -import { expect } from 'chai'; -import AppRegistry from 'hadron-app-registry'; - -import IndexList from '../index-list'; -import IndexComponent from '../index-component'; - -const indexes = [ - { - name: 'a', - type: 'regular', - fields: { serialize: () => [] }, - size: 10, - relativeSize: 10, - properties: [], - }, - { - name: 'b', - type: 'regular', - fields: { serialize: () => [] }, - size: 20, - relativeSize: 20, - properties: [], - }, -]; - -describe('index-list [Component]', function () { - const localAppRegistry = new AppRegistry(); - let component; - - describe('render', function () { - beforeEach(function () { - component = mount( - {}} - changeName={() => {}} - indexes={indexes} - openLink={() => {}} - /> - ); - }); - afterEach(function () { - component = null; - }); - it('renders the list', function () { - expect(component.find(IndexComponent)).to.have.lengthOf(2); - }); - }); -}); diff --git a/packages/compass-indexes/src/components/index-list/index.js b/packages/compass-indexes/src/components/index-list/index.js deleted file mode 100644 index 00e0f1e12d3..00000000000 --- a/packages/compass-indexes/src/components/index-list/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import IndexList from './index-list'; -export default IndexList; diff --git a/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx b/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx new file mode 100644 index 00000000000..7c13603cb84 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { + css, + Badge, + BadgeVariant, + Icon, + Link, + uiColors, + spacing, +} from '@mongodb-js/compass-components'; + +const badgeStyles = css({ + gap: spacing[2], +}); + +const linkStyles = css({ + lineHeight: 0, + color: uiColors.white, + span: { + // LG uses backgroundImage instead of textDecoration + backgroundImage: 'none !important', + }, +}); + +type BadgeWithIconLinkProps = { + text: string; + link: string; +}; + +const BadgeWithIconLink: React.FunctionComponent = ({ + text, + link, +}) => { + return ( + + {text} + + + + + ); +}; + +export default BadgeWithIconLink; diff --git a/packages/compass-indexes/src/components/indexes-table/drop-field.tsx b/packages/compass-indexes/src/components/indexes-table/drop-field.tsx new file mode 100644 index 00000000000..aaef6686606 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/drop-field.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { IconButton, Icon } from '@mongodb-js/compass-components'; + +type DropFieldProps = { + name: string; + onDelete: () => void; +}; + +const DropField: React.FunctionComponent = ({ + name, + onDelete, +}) => { + return ( + + + + ); +}; + +export default DropField; diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx new file mode 100644 index 00000000000..2e57c5ac518 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx @@ -0,0 +1,143 @@ +import React, { useMemo } from 'react'; +import { + css, + Table, + TableHeader, + Row, + Cell, + spacing, +} from '@mongodb-js/compass-components'; +import type { IndexDirection } from 'mongodb'; +import { connect } from 'react-redux'; +import type AppRegistry from 'hadron-app-registry'; + +import NameField from './name-field'; +import TypeField from './type-field'; +import SizeField from './size-field'; +import UsageField from './usage-field'; +import PropertyField from './property-field'; +import DropField from './drop-field'; + +import { sortIndexes } from '../../modules/indexes'; + +const tableCellStyles = css({ + padding: spacing[3], +}); + +// todo: move to redux store when converting that to ts +export type IndexModel = { + name: string; + fields: { + serialize: () => { field: string; value: IndexDirection }[]; + }; + type: 'geo' | 'hashed' | 'text' | 'wildcard' | 'clustered' | 'columnstore'; + cardinality: 'single' | 'compound'; + properties: ('unique' | 'sparse' | 'partial' | 'ttl' | 'collation')[]; + extra: Record; + size: number; + relativeSize: number; + usageCount?: number; + usageSince?: Date; +}; + +type IndexesTableProps = { + indexes: IndexModel[]; + isReadonly: boolean; + isWritable: boolean; + localAppRegistry: AppRegistry; + onSortTable: (name: string, direction: 'asc' | 'desc') => void; +}; + +export const IndexesTable: React.FunctionComponent = ({ + indexes, + isReadonly, + isWritable, + localAppRegistry, + onSortTable, +}) => { + const columns = useMemo(() => { + const _columns = [ + 'Name and Definition', + 'Type', + 'Size', + 'Usage', + 'Properties', + ].map((name) => { + return ( + { + onSortTable(name, direction); + }} + /> + ); + }); + // The delete column + if (!isReadonly && isWritable) { + _columns.push(); + } + return _columns; + }, [isReadonly, isWritable, onSortTable]); + + return ( + + {({ datum: index }) => ( + + + + + + + + + + + + + + + + + {/* Delete column is conditional */} + {index.name !== '_id_' && isWritable && !isReadonly && ( + + + localAppRegistry.emit( + 'toggle-drop-index-modal', + true, + index.name + ) + } + /> + + )} + + )} +
+ ); +}; + +const mapState = ({ + indexes, + isReadonly, + isWritable, + appRegistry: { localAppRegistry }, +}: any) => ({ + indexes, + isReadonly, + isWritable, + localAppRegistry, +}); + +const mapDispatch = { + onSortTable: sortIndexes, +}; +export default connect(mapState, mapDispatch)(IndexesTable as any); diff --git a/packages/compass-indexes/src/components/indexes-table/name-field.tsx b/packages/compass-indexes/src/components/indexes-table/name-field.tsx new file mode 100644 index 00000000000..1f2a7e6d8c7 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/name-field.tsx @@ -0,0 +1,49 @@ +import React from 'react'; +import { + spacing, + css, + Accordion, + Badge, + BadgeVariant, + IndexIcon, +} from '@mongodb-js/compass-components'; + +import type { IndexModel } from './indexes-table'; + +const keyListStyles = css({ + marginTop: spacing[1], + marginBottom: spacing[1], +}); + +const keyItemStyles = css({ + paddingTop: spacing[1], + paddingLeft: spacing[4], +}); + +type NameFieldProps = { + name: string; + keys: ReturnType; +}; + +const NameField: React.FunctionComponent = ({ name, keys }) => { + return ( + +
    + {keys.map(({ field, value }) => ( +
  • + + {field} +   + + +
  • + ))} +
+
+ ); +}; + +export default NameField; diff --git a/packages/compass-indexes/src/components/indexes-table/property-field.tsx b/packages/compass-indexes/src/components/indexes-table/property-field.tsx new file mode 100644 index 00000000000..90ca47517e0 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/property-field.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import getIndexHelpLink from '../../utils/index-link-helper'; + +import { spacing, css, Tooltip, Body } from '@mongodb-js/compass-components'; +import type { IndexModel } from './indexes-table'; +import BadgeWithIconLink from './badge-with-icon-link'; + +const containerStyles = css({ + display: 'flex', + gap: spacing[1], +}); + +const partialTooltip = (partialFilterExpression: JSON) => { + return `partialFilterExpression: ${JSON.stringify(partialFilterExpression)}`; +}; + +const ttlTooltip = (expireAfterSeconds: number) => { + return `expireAfterSeconds: ${expireAfterSeconds}`; +}; + +const PropertyBadgeWithTooltip: React.FunctionComponent<{ + text: string; + link: string; + tooltip?: string | null; +}> = ({ text, link, tooltip }) => { + return ( + ( + + {children} + + + )} + > + {tooltip} + + ); +}; + +type PropertyFieldProps = { + extra: IndexModel['extra']; + properties: IndexModel['properties']; + cardinality: IndexModel['cardinality']; +}; + +const PropertyField: React.FunctionComponent = ({ + extra, + properties, + cardinality, +}) => { + return ( +
+ {properties.map((property) => { + const tooltip = + property === 'ttl' + ? ttlTooltip(extra.expireAfterSeconds as number) + : property === 'partial' + ? partialTooltip(extra.partialFilterExpression as JSON) + : null; + + return ( + + ); + })} + {cardinality === 'compound' && ( + + )} +
+ ); +}; + +export default PropertyField; diff --git a/packages/compass-indexes/src/components/indexes-table/size-field.tsx b/packages/compass-indexes/src/components/indexes-table/size-field.tsx new file mode 100644 index 00000000000..5037ee75d39 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/size-field.tsx @@ -0,0 +1,35 @@ +import numeral from 'numeral'; +import React from 'react'; +import { Body, Tooltip } from '@mongodb-js/compass-components'; + +type SizeFieldProps = { + size: number; + relativeSize: number; +}; + +const format = (size: number) => { + const precision = size <= 1000 ? '0' : '0.0'; + return numeral(size).format(precision + ' b'); +}; + +const SizeField: React.FunctionComponent = ({ + relativeSize, + size, +}) => { + const indexSize = format(size); + const tooltip = `${relativeSize.toFixed(2)}% compared to largest index`; + return ( + ( + + {children} + {indexSize} + + )} + > + {tooltip} + + ); +}; + +export default SizeField; diff --git a/packages/compass-indexes/src/components/indexes-table/type-field.tsx b/packages/compass-indexes/src/components/indexes-table/type-field.tsx new file mode 100644 index 00000000000..424c5fac396 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/type-field.tsx @@ -0,0 +1,56 @@ +import map from 'lodash.map'; +import pick from 'lodash.pick'; +import React from 'react'; +import getIndexHelpLink from '../../utils/index-link-helper'; +import { Tooltip, Body } from '@mongodb-js/compass-components'; + +import type { IndexModel } from './indexes-table'; +import BadgeWithIconLink from './badge-with-icon-link'; + +const canRenderTooltip = (type: IndexModel['type']) => { + return ['text', 'wildcard', 'columnstore'].indexOf(type) !== -1; +}; + +type TypeFieldProps = { + type: IndexModel['type']; + extra: IndexModel['extra']; +}; + +const IndexTypeTooltip: React.FunctionComponent<{ + extra: IndexModel['extra']; +}> = ({ extra }) => { + const info = pick(extra, [ + 'weights', + 'default_language', + 'language_override', + 'wildcardProjection', + 'columnstoreProjection', + ]); + const items = map(info, (v: unknown, k: string) => { + return {`${k}: ${JSON.stringify(v)}`}; + }); + return <>{items}; +}; + +const TypeField: React.FunctionComponent = ({ + type, + extra, +}) => { + // todo: align index types across + const link = getIndexHelpLink(type.toUpperCase() as any); + return ( + ( + + {children} + + + )} + > + + + ); +}; + +export default TypeField; diff --git a/packages/compass-indexes/src/components/indexes-table/usage-field.tsx b/packages/compass-indexes/src/components/indexes-table/usage-field.tsx new file mode 100644 index 00000000000..9c4bbd993a5 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/usage-field.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { Tooltip, Body } from '@mongodb-js/compass-components'; + +const NO_USAGE_STATS = + 'Either the server does not support the $indexStats command' + + 'or the user is not authorized to execute it.'; + +type UsageFieldProps = { + usage?: number; + since?: Date; +}; + +const UsageField: React.FunctionComponent = ({ + usage, + since, +}) => { + return ( + ( + + {children} + + {usage || 0} ( + + since  + {since ? since.toDateString() : 'N/A'} + + ) + + + )} + > + + {!usage + ? NO_USAGE_STATS + : `${usage} index hits since index creation or last server restart`} + + + ); +}; + +export default UsageField; diff --git a/packages/compass-indexes/src/components/indexes/indexes.jsx b/packages/compass-indexes/src/components/indexes/indexes.jsx index d42f20d2d80..80864fed648 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.jsx +++ b/packages/compass-indexes/src/components/indexes/indexes.jsx @@ -1,40 +1,20 @@ -/* eslint dot-notation: 0 */ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; -import { writeStateChanged } from '../../modules/is-writable'; -import { dataServiceConnected } from '../../modules/data-service'; -import { sortIndexes } from '../../modules/indexes'; -import { reset } from '../../modules/reset'; -import { changeName } from '../../modules/drop-index/name'; -import { openLink } from '../../modules/link'; - -import IndexHeader from '../index-header'; -import IndexList from '../index-list'; import { IndexesToolbar } from '../indexes-toolbar'; +import IndexesTable from '../indexes-table/indexes-table'; -import { css, spacing } from '@mongodb-js/compass-components'; +import { css, Card, spacing } from '@mongodb-js/compass-components'; const containerStyles = css({ - height: '100%', + margin: spacing[3], + padding: spacing[3], display: 'flex', flexDirection: 'column', - flexGrow: 1, - overflow: 'hidden', -}); -const indexesStyles = css({ - width: '100%', - padding: spacing[3], - paddingTop: 0, - flexGrow: 1, - overflow: 'auto', -}); -const indexesTableStyles = css({ - tableLayout: 'auto', - borderCollapse: 'separate', - borderSpacing: '0 3px', width: '100%', + height: 'auto', + overflowY: 'scroll', }); class Indexes extends PureComponent { @@ -44,99 +24,46 @@ class Indexes extends PureComponent { isWritable: PropTypes.bool.isRequired, isReadonly: PropTypes.bool.isRequired, isReadonlyView: PropTypes.bool.isRequired, - indexes: PropTypes.array.isRequired, - sortColumn: PropTypes.string.isRequired, - sortOrder: PropTypes.string.isRequired, - sortIndexes: PropTypes.func.isRequired, localAppRegistry: PropTypes.object.isRequired, - reset: PropTypes.func.isRequired, errorMessage: PropTypes.string, - changeName: PropTypes.func.isRequired, - openLink: PropTypes.func.isRequired, writeStateDescription: PropTypes.string.isRequired, }; - renderComponent() { - return ( -
- - - -
-
- ); - } - - /** - * Render the indexes. - * - * @returns {React.Component} The indexes. - */ render() { + const { + isWritable, + isReadonly, + isReadonlyView, + errorMessage, + localAppRegistry, + writeStateDescription, + } = this.props; return ( -
+ - {!this.props.isReadonlyView && - !this.props.errorMessage && - this.renderComponent()} -
+ {!isReadonlyView && !errorMessage && } + ); } } -/** - * Map the store state to properties to pass to the components. - * - * @param {Object} state - The store state. - * - * @returns {Object} The mapped properties. - */ const mapStateToProps = (state) => ({ - indexes: state.indexes, isWritable: state.isWritable, isReadonly: state.isReadonly, isReadonlyView: state.isReadonlyView, writeStateDescription: state.description, errorMessage: state.error, - dataService: state.dataService, - sortColumn: state.sortColumn, - sortOrder: state.sortOrder, localAppRegistry: state.appRegistry.localAppRegistry, }); -/** - * Connect the redux store to the component. - * (dispatch) - */ -const MappedIndexes = connect(mapStateToProps, { - writeStateChanged, - dataServiceConnected, - sortIndexes, - reset, - changeName, - openLink, -})(Indexes); +const MappedIndexes = connect(mapStateToProps)(Indexes); export default MappedIndexes; export { Indexes }; diff --git a/packages/compass-indexes/src/components/name-column/index.js b/packages/compass-indexes/src/components/name-column/index.js deleted file mode 100644 index 5d2fd30b7cd..00000000000 --- a/packages/compass-indexes/src/components/name-column/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import NameColumn from './name-column'; -export default NameColumn; diff --git a/packages/compass-indexes/src/components/name-column/name-column.jsx b/packages/compass-indexes/src/components/name-column/name-column.jsx deleted file mode 100644 index cf9c7d1f7bf..00000000000 --- a/packages/compass-indexes/src/components/name-column/name-column.jsx +++ /dev/null @@ -1,59 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { - spacing, - css, - IndexIcon, - BadgeVariant, - Badge, - Accordion, -} from '@mongodb-js/compass-components'; - -const keyListStyles = css({ - marginTop: spacing[1], - marginBottom: spacing[1], -}); - -const keyItemStyles = css({ - paddingTop: spacing[1], - paddingLeft: spacing[4], -}); - -class NameColumn extends PureComponent { - static displayName = 'NameColumn'; - - static propTypes = { - index: PropTypes.object.isRequired, - }; - - render() { - const indexName = this.props.index.name; - const indexKeys = this.props.index.fields.serialize(); - return ( - - -
    - {indexKeys.map(({ field, value }) => ( -
  • - - {field} -   - - -
  • - ))} -
-
- - ); - } -} - -export default NameColumn; diff --git a/packages/compass-indexes/src/components/property-column/index.js b/packages/compass-indexes/src/components/property-column/index.js deleted file mode 100644 index 1e3d67f9e2e..00000000000 --- a/packages/compass-indexes/src/components/property-column/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import PropertyColumn from './property-column'; -export default PropertyColumn; diff --git a/packages/compass-indexes/src/components/property-column/property-column.jsx b/packages/compass-indexes/src/components/property-column/property-column.jsx deleted file mode 100644 index a8c507e1fbe..00000000000 --- a/packages/compass-indexes/src/components/property-column/property-column.jsx +++ /dev/null @@ -1,122 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import getIndexHelpLink from '../../utils/index-link-helper'; - -import { - spacing, - css, - Tooltip, - Body, - Badge, - BadgeVariant, - Icon, - Link, - uiColors, -} from '@mongodb-js/compass-components'; - -const contentStyles = css({ - display: 'flex', - gap: spacing[1], -}); - -const badgeStyles = css({ - gap: spacing[2], -}); - -const iconLinkStyles = css({ - lineHeight: 0, - color: uiColors.white, - span: { - // LG uses backgroundImage instead of textDecoration - backgroundImage: 'none !important', - }, -}); - -class PropertyColumn extends PureComponent { - static displayName = 'PropertyColumn'; - - static propTypes = { - index: PropTypes.object.isRequired, - openLink: PropTypes.func.isRequired, - }; - - _partialTooltip() { - const { partialFilterExpression } = this.props.index.extra; - return `partialFilterExpression: ${JSON.stringify( - partialFilterExpression - )}`; - } - - _ttlTooltip() { - const { expireAfterSeconds } = this.props.index.extra; - return `expireAfterSeconds: ${expireAfterSeconds}`; - } - - renderItemWithTooltip(text, link, tooltip) { - return ( - ( - - {children} - - {text} - - - - - - )} - > - {tooltip} - - ); - } - - renderCardinality() { - const { cardinality } = this.props.index; - if (cardinality !== 'compound') { - return null; - } - return this.renderItemWithTooltip( - cardinality, - getIndexHelpLink('COMPOUND') - ); - } - - renderProperty(prop) { - const tooltip = - prop === 'ttl' - ? this._ttlTooltip() - : prop === 'partial' - ? this._partialTooltip() - : null; - - return this.renderItemWithTooltip( - prop, - getIndexHelpLink(prop.toUpperCase()), - tooltip - ); - } - - render() { - const properties = this.props.index.properties.map( - this.renderProperty.bind(this) - ); - return ( - -
- {properties} - {this.renderCardinality()} -
- - ); - } -} - -export default PropertyColumn; diff --git a/packages/compass-indexes/src/components/size-column/index.js b/packages/compass-indexes/src/components/size-column/index.js deleted file mode 100644 index 044cc84c4a4..00000000000 --- a/packages/compass-indexes/src/components/size-column/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import SizeColumn from './size-column'; -export default SizeColumn; diff --git a/packages/compass-indexes/src/components/size-column/size-column.jsx b/packages/compass-indexes/src/components/size-column/size-column.jsx deleted file mode 100644 index 9023ca4716f..00000000000 --- a/packages/compass-indexes/src/components/size-column/size-column.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import numeral from 'numeral'; -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; - -import { Body, Tooltip } from '@mongodb-js/compass-components'; - -/** - * Component for the size column. - */ -class SizeColumn extends PureComponent { - static displayName = 'SizeColumn'; - - static propTypes = { - size: PropTypes.number.isRequired, - relativeSize: PropTypes.number.isRequired, - }; - - _format(size) { - const precision = size <= 1000 ? '0' : '0.0'; - return numeral(size).format(precision + ' b'); - } - - render() { - const indexSize = this._format(this.props.size); - const tooltip = `${this.props.relativeSize.toFixed( - 2 - )}% compared to largest index`; - return ( - - ( - - {children} - {indexSize} - - )} - > - {tooltip} - - - ); - } -} - -export default SizeColumn; diff --git a/packages/compass-indexes/src/components/type-column/index.js b/packages/compass-indexes/src/components/type-column/index.js deleted file mode 100644 index 01de3d8b138..00000000000 --- a/packages/compass-indexes/src/components/type-column/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import TypeColumn from './type-column'; -export default TypeColumn; diff --git a/packages/compass-indexes/src/components/type-column/type-column.jsx b/packages/compass-indexes/src/components/type-column/type-column.jsx deleted file mode 100644 index 88f13ae276d..00000000000 --- a/packages/compass-indexes/src/components/type-column/type-column.jsx +++ /dev/null @@ -1,93 +0,0 @@ -import map from 'lodash.map'; -import pick from 'lodash.pick'; -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import getIndexHelpLink from '../../utils/index-link-helper'; -import { - spacing, - css, - Tooltip, - Body, - Badge, - BadgeVariant, - Icon, - Link, - uiColors, -} from '@mongodb-js/compass-components'; - -const badgeStyles = css({ - gap: spacing[2], -}); - -const iconLinkStyles = css({ - lineHeight: 0, - color: uiColors.white, - span: { - // LG uses backgroundImage instead of textDecoration - backgroundImage: 'none !important', - }, -}); - -/** - * Component for the type column. - */ -class TypeColumn extends PureComponent { - static displayName = 'TypeColumn'; - - static propTypes = { - index: PropTypes.object.isRequired, - openLink: PropTypes.func.isRequired, - }; - - canRenderTooltip() { - return ( - ['text', 'wildcard', 'columnstore'].indexOf(this.props.index.type) !== -1 - ); - } - - renderTooltip() { - const info = pick(this.props.index.extra, [ - 'weights', - 'default_language', - 'language_override', - 'wildcardProjection', - 'columnstoreProjection', - ]); - const items = map(info, (v, k) => { - return {`${k}: ${JSON.stringify(v)}`}; - }); - return <>{items}; - } - - render() { - const helpLink = getIndexHelpLink(this.props.index.type.toUpperCase()); - return ( - - ( - - {children} - - {this.props.index.type} - - - - - - )} - > - {this.renderTooltip()} - - - ); - } -} - -export default TypeColumn; diff --git a/packages/compass-indexes/src/components/usage-column/index.js b/packages/compass-indexes/src/components/usage-column/index.js deleted file mode 100644 index f9017806f5f..00000000000 --- a/packages/compass-indexes/src/components/usage-column/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import UsageColumn from './usage-column'; -export default UsageColumn; diff --git a/packages/compass-indexes/src/components/usage-column/usage-column.jsx b/packages/compass-indexes/src/components/usage-column/usage-column.jsx deleted file mode 100644 index cafab04e2d6..00000000000 --- a/packages/compass-indexes/src/components/usage-column/usage-column.jsx +++ /dev/null @@ -1,60 +0,0 @@ -import isUndefined from 'lodash.isundefined'; -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; - -import { Tooltip, Body } from '@mongodb-js/compass-components'; - -const NO_USAGE_STATS = - 'Either the server does not support the $indexStats command' + - 'or the user is not authorized to execute it.'; - -class UsageColumn extends PureComponent { - static displayName = 'UsageColumn'; - - static propTypes = { - usage: PropTypes.any, - since: PropTypes.any, - }; - - tooltip() { - if (isUndefined(this.props.usage)) { - return NO_USAGE_STATS; - } - return `${this.props.usage} index hits since index creation or last\n server restart`; - } - - renderSince() { - if (isUndefined(this.props.since)) { - return null; - } - return ( - - (since  - {this.props.since ? this.props.since.toDateString() : 'N/A'}) - - ); - } - - render() { - const usage = isUndefined(this.props.usage) ? '0' : this.props.usage; - const tooltip = this.tooltip(); - return ( - - ( - - {children} - - {usage} {this.renderSince()} - - - )} - > - {tooltip} - - - ); - } -} - -export default UsageColumn; diff --git a/packages/compass-indexes/src/modules/indexes.js b/packages/compass-indexes/src/modules/indexes.js index 62cd86139ec..dad8f8f53b7 100644 --- a/packages/compass-indexes/src/modules/indexes.js +++ b/packages/compass-indexes/src/modules/indexes.js @@ -25,8 +25,8 @@ export const SORT_INDEXES = `${PREFIX}/indexes/SORT_INDEXES`; * Default sortOrder */ export const DEFAULT = 'Name and Definition'; -export const ASC = 'fa-sort-asc'; -export const DESC = 'fa-sort-desc'; +export const ASC = 'asc'; +export const DESC = 'desc'; export const USAGE = 'Usage'; /** @@ -171,21 +171,17 @@ export const loadIndexes = (indexes) => ({ indexes: indexes, }); -/** - * Action creator for sort indexes events. - * - * @param {Array} indexes - The raw indexes list. - * @param {String} column - The column. - * @param {String} order - The order. - * - * @returns {Object} The load indexes action. - */ -export const sortIndexes = (indexes, column, order) => ({ - type: SORT_INDEXES, - indexes: indexes, - column: column, - order: order, -}); +export const sortIndexes = (column, order) => { + return (dispatch, getState) => { + const { indexes } = getState(); + dispatch({ + type: SORT_INDEXES, + indexes, + column, + order, + }); + }; +}; /** * Load indexes from DB. diff --git a/packages/compass-indexes/src/utils/index-link-helper.ts b/packages/compass-indexes/src/utils/index-link-helper.ts index 4d8d7efe965..18d546c6faf 100644 --- a/packages/compass-indexes/src/utils/index-link-helper.ts +++ b/packages/compass-indexes/src/utils/index-link-helper.ts @@ -30,10 +30,8 @@ const HELP_URLS = { * The function looks up index help links. * * @param {String} section - The name of the section to open. - * @returns {String} - the link. */ -function getIndexHelpLink(section: keyof typeof HELP_URLS) { +export default function getIndexHelpLink(section: keyof typeof HELP_URLS) { return HELP_URLS[section] || null; } -module.exports = getIndexHelpLink; From dc21419712926d6b5390a5100e1023a45a49dade Mon Sep 17 00:00:00 2001 From: Basit Date: Wed, 17 Aug 2022 10:55:30 +0200 Subject: [PATCH 02/23] restructure --- .../indexes-table/indexes-table.tsx | 25 +----- .../indexes-toolbar.spec.tsx | 0 .../{ => indexes-toolbar}/indexes-toolbar.tsx | 0 .../src/components/indexes/index.js | 4 - .../src/components/indexes/indexes.jsx | 69 --------------- .../src/components/indexes/indexes.tsx | 88 +++++++++++++++++++ packages/compass-indexes/src/plugin.jsx | 2 +- 7 files changed, 90 insertions(+), 98 deletions(-) rename packages/compass-indexes/src/components/{ => indexes-toolbar}/indexes-toolbar.spec.tsx (100%) rename packages/compass-indexes/src/components/{ => indexes-toolbar}/indexes-toolbar.tsx (100%) delete mode 100644 packages/compass-indexes/src/components/indexes/index.js delete mode 100644 packages/compass-indexes/src/components/indexes/indexes.jsx create mode 100644 packages/compass-indexes/src/components/indexes/indexes.tsx diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx index 2e57c5ac518..222c70505a1 100644 --- a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx @@ -5,10 +5,8 @@ import { TableHeader, Row, Cell, - spacing, } from '@mongodb-js/compass-components'; import type { IndexDirection } from 'mongodb'; -import { connect } from 'react-redux'; import type AppRegistry from 'hadron-app-registry'; import NameField from './name-field'; @@ -18,11 +16,7 @@ import UsageField from './usage-field'; import PropertyField from './property-field'; import DropField from './drop-field'; -import { sortIndexes } from '../../modules/indexes'; - -const tableCellStyles = css({ - padding: spacing[3], -}); +const tableCellStyles = css({}); // todo: move to redux store when converting that to ts export type IndexModel = { @@ -124,20 +118,3 @@ export const IndexesTable: React.FunctionComponent = ({ ); }; - -const mapState = ({ - indexes, - isReadonly, - isWritable, - appRegistry: { localAppRegistry }, -}: any) => ({ - indexes, - isReadonly, - isWritable, - localAppRegistry, -}); - -const mapDispatch = { - onSortTable: sortIndexes, -}; -export default connect(mapState, mapDispatch)(IndexesTable as any); diff --git a/packages/compass-indexes/src/components/indexes-toolbar.spec.tsx b/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.spec.tsx similarity index 100% rename from packages/compass-indexes/src/components/indexes-toolbar.spec.tsx rename to packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.spec.tsx diff --git a/packages/compass-indexes/src/components/indexes-toolbar.tsx b/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx similarity index 100% rename from packages/compass-indexes/src/components/indexes-toolbar.tsx rename to packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx diff --git a/packages/compass-indexes/src/components/indexes/index.js b/packages/compass-indexes/src/components/indexes/index.js deleted file mode 100644 index f8fe808ce5d..00000000000 --- a/packages/compass-indexes/src/components/indexes/index.js +++ /dev/null @@ -1,4 +0,0 @@ -import MappedIndexes, { Indexes } from './indexes'; - -export default MappedIndexes; -export { Indexes }; diff --git a/packages/compass-indexes/src/components/indexes/indexes.jsx b/packages/compass-indexes/src/components/indexes/indexes.jsx deleted file mode 100644 index 80864fed648..00000000000 --- a/packages/compass-indexes/src/components/indexes/indexes.jsx +++ /dev/null @@ -1,69 +0,0 @@ -import React, { PureComponent } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; - -import { IndexesToolbar } from '../indexes-toolbar'; -import IndexesTable from '../indexes-table/indexes-table'; - -import { css, Card, spacing } from '@mongodb-js/compass-components'; - -const containerStyles = css({ - margin: spacing[3], - padding: spacing[3], - display: 'flex', - flexDirection: 'column', - width: '100%', - height: 'auto', - overflowY: 'scroll', -}); - -class Indexes extends PureComponent { - static displayName = 'IndexesComponent'; - - static propTypes = { - isWritable: PropTypes.bool.isRequired, - isReadonly: PropTypes.bool.isRequired, - isReadonlyView: PropTypes.bool.isRequired, - localAppRegistry: PropTypes.object.isRequired, - errorMessage: PropTypes.string, - writeStateDescription: PropTypes.string.isRequired, - }; - - render() { - const { - isWritable, - isReadonly, - isReadonlyView, - errorMessage, - localAppRegistry, - writeStateDescription, - } = this.props; - return ( - - - {!isReadonlyView && !errorMessage && } - - ); - } -} - -const mapStateToProps = (state) => ({ - isWritable: state.isWritable, - isReadonly: state.isReadonly, - isReadonlyView: state.isReadonlyView, - writeStateDescription: state.description, - errorMessage: state.error, - localAppRegistry: state.appRegistry.localAppRegistry, -}); - -const MappedIndexes = connect(mapStateToProps)(Indexes); - -export default MappedIndexes; -export { Indexes }; diff --git a/packages/compass-indexes/src/components/indexes/indexes.tsx b/packages/compass-indexes/src/components/indexes/indexes.tsx new file mode 100644 index 00000000000..3e0dcb96159 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes/indexes.tsx @@ -0,0 +1,88 @@ +import React from 'react'; +import { css, Card, spacing } from '@mongodb-js/compass-components'; +import { connect } from 'react-redux'; +import type AppRegistry from 'hadron-app-registry'; + +import { sortIndexes } from '../../modules/indexes'; + +import { IndexesToolbar } from '../indexes-toolbar/indexes-toolbar'; +import { IndexesTable } from '../indexes-table/indexes-table'; +import type { IndexModel } from '../indexes-table/indexes-table'; + +const containerStyles = css({ + margin: spacing[3], + padding: spacing[3], + display: 'flex', + flexDirection: 'column', + width: '100%', + height: 'auto', + overflowY: 'scroll', +}); + +type IndexesProps = { + indexes: IndexModel[]; + isWritable: boolean; + isReadonly: boolean; + isReadonlyView: boolean; + description: string; + error?: string; + localAppRegistry: AppRegistry; + onSortTable: (name: string, direction: 'asc' | 'desc') => void; +}; + +export const Indexes: React.FunctionComponent = ({ + indexes, + isWritable, + isReadonly, + isReadonlyView, + description, + error, + localAppRegistry, + onSortTable, +}) => { + return ( + + + {!isReadonlyView && !error && ( + + )} + + ); +}; + +const mapState = ({ + indexes, + isWritable, + isReadonly, + isReadonlyView, + description, + error, + appRegistry: { localAppRegistry }, +}: any) => ({ + indexes, + isWritable, + isReadonly, + isReadonlyView, + description, + error, + localAppRegistry, +}); + +const mapDispatch = { + onSortTable: sortIndexes, +}; + +export default connect(mapState, mapDispatch)(Indexes as any); diff --git a/packages/compass-indexes/src/plugin.jsx b/packages/compass-indexes/src/plugin.jsx index 7759ba3b4b7..e3ecf97b314 100644 --- a/packages/compass-indexes/src/plugin.jsx +++ b/packages/compass-indexes/src/plugin.jsx @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { Provider } from 'react-redux'; import PropTypes from 'prop-types'; -import Indexes from './components/indexes'; +import Indexes from './components/indexes/indexes'; class Plugin extends Component { static displayName = 'IndexesPlugin'; From a3ad50b20de47258edb1316e13374fcded7a38fe Mon Sep 17 00:00:00 2001 From: Basit Date: Wed, 17 Aug 2022 11:26:49 +0200 Subject: [PATCH 03/23] show delete button on row hover --- .../indexes-table/indexes-table.tsx | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx index 222c70505a1..131ed7f80c8 100644 --- a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx @@ -5,6 +5,7 @@ import { TableHeader, Row, Cell, + cx, } from '@mongodb-js/compass-components'; import type { IndexDirection } from 'mongodb'; import type AppRegistry from 'hadron-app-registry'; @@ -18,6 +19,19 @@ import DropField from './drop-field'; const tableCellStyles = css({}); +// When row is hovered, we show the delete button +const rowStyles = css({ + ':hover': { + '.delete-cell': { + visibility: 'visible', + }, + }, +}); +// When row is not hovered, we hide the delete button +const deletFieldStyles = css({ + visibility: 'hidden', +}); + // todo: move to redux store when converting that to ts export type IndexModel = { name: string; @@ -78,7 +92,11 @@ export const IndexesTable: React.FunctionComponent = ({ return ( {({ datum: index }) => ( - + @@ -101,16 +119,18 @@ export const IndexesTable: React.FunctionComponent = ({ {/* Delete column is conditional */} {index.name !== '_id_' && isWritable && !isReadonly && ( - - localAppRegistry.emit( - 'toggle-drop-index-modal', - true, - index.name - ) - } - /> +
+ + localAppRegistry.emit( + 'toggle-drop-index-modal', + true, + index.name + ) + } + /> +
)}
From 56a1c947ad04b8de937bd96f04b521aa284550ef Mon Sep 17 00:00:00 2001 From: Basit Date: Wed, 17 Aug 2022 11:34:22 +0200 Subject: [PATCH 04/23] clean up --- packages/compass-components/src/components/index-icon.tsx | 2 +- .../src/components/indexes-table/drop-field.tsx | 2 +- .../src/components/indexes-table/indexes-table.tsx | 2 +- .../src/components/indexes-table/name-field.tsx | 6 +++++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/compass-components/src/components/index-icon.tsx b/packages/compass-components/src/components/index-icon.tsx index 5ad63b3c392..3f66ad02155 100644 --- a/packages/compass-components/src/components/index-icon.tsx +++ b/packages/compass-components/src/components/index-icon.tsx @@ -9,7 +9,7 @@ const IndexIcon = ({ direction }: { direction: IndexDirection }) => { ) : direction === -1 ? ( ) : ( - <>({String(direction)}) + ({String(direction)}) ); }; diff --git a/packages/compass-indexes/src/components/indexes-table/drop-field.tsx b/packages/compass-indexes/src/components/indexes-table/drop-field.tsx index aaef6686606..f6ee3a42d00 100644 --- a/packages/compass-indexes/src/components/indexes-table/drop-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/drop-field.tsx @@ -14,7 +14,7 @@ const DropField: React.FunctionComponent = ({ diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx index 131ed7f80c8..72734ae82a3 100644 --- a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx @@ -90,7 +90,7 @@ export const IndexesTable: React.FunctionComponent = ({ }, [isReadonly, isWritable, onSortTable]); return ( -
+
{({ datum: index }) => ( ; @@ -34,9 +38,9 @@ const NameField: React.FunctionComponent = ({ name, keys }) => { {field} -   From 7dfa100a55a5b5361f8b9b69a22c32fdc7bdd331 Mon Sep 17 00:00:00 2001 From: Basit Date: Wed, 17 Aug 2022 12:20:14 +0200 Subject: [PATCH 05/23] clean up --- .../indexes-table/indexes-table.tsx | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx index 72734ae82a3..c604373ab17 100644 --- a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx @@ -17,8 +17,6 @@ import UsageField from './usage-field'; import PropertyField from './property-field'; import DropField from './drop-field'; -const tableCellStyles = css({}); - // When row is hovered, we show the delete button const rowStyles = css({ ':hover': { @@ -90,26 +88,31 @@ export const IndexesTable: React.FunctionComponent = ({ }, [isReadonly, isWritable, onSortTable]); return ( -
+
{({ datum: index }) => ( - + - + - + - + - + = ({ {/* Delete column is conditional */} {index.name !== '_id_' && isWritable && !isReadonly && ( - +
Date: Wed, 17 Aug 2022 12:45:56 +0200 Subject: [PATCH 06/23] indexes card test --- .../indexes-toolbar/indexes-toolbar.tsx | 2 +- .../src/components/indexes/indexes.spec.jsx | 189 ------------------ .../src/components/indexes/indexes.spec.tsx | 92 +++++++++ .../src/components/indexes/indexes.tsx | 4 +- 4 files changed, 95 insertions(+), 192 deletions(-) delete mode 100644 packages/compass-indexes/src/components/indexes/indexes.spec.jsx create mode 100644 packages/compass-indexes/src/components/indexes/indexes.spec.tsx diff --git a/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx b/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx index 86a6eb3f25b..1de31a794a6 100644 --- a/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx +++ b/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx @@ -44,7 +44,7 @@ export const IndexesToolbar: React.FunctionComponent = ({ const showCreateIndexButton = !isReadonly && !isReadonlyView && !errorMessage; return ( - + {showCreateIndexButton ? ( - ); - }); - - afterEach(function () { - component = null; - }); - - it('renders a create-index-button', function () { - expect( - component - .find('button') - .findWhere((node) => node.text() === 'Create Index') - ).to.be.present(); - }); - - it('does not render errors or warnings', function () { - expect(component.find(ErrorSummary)).to.not.be.present(); - expect(component.find(WarningSummary)).to.not.be.present(); - }); - - it('renders the list and header', function () { - expect(component.find(IndexHeader)).to.be.present(); - expect(component.find(IndexList)).to.be.present(); - }); - }); - - context('when the collection is a readonly view', function () { - beforeEach(function () { - component = mount( - - ); - }); - - afterEach(function () { - component = null; - }); - - it('does not render a create-index-button', function () { - expect( - component - .find('button') - .findWhere((node) => node.text() === 'Create Index') - ).to.not.be.present(); - }); - - it('renders a warning summary', function () { - expect(component.find(WarningSummary)).to.be.present(); - expect(component.find(WarningSummary).text()).to.equal( - 'Readonly views may not contain indexes.' - ); - }); - - it('does not render the list or header', function () { - expect(component.find(IndexHeader)).to.not.be.present(); - expect(component.find(IndexList)).to.not.be.present(); - }); - }); - - context('when the distribution is readonly', function () { - beforeEach(function () { - component = mount( - - ); - }); - - afterEach(function () { - component = null; - }); - - it('does not render a create-index-button', function () { - expect( - component - .find('button') - .findWhere((node) => node.text() === 'Create Index') - ).to.not.be.present(); - }); - - it('does not render errors or warnings', function () { - expect(component.find(ErrorSummary)).to.not.be.present(); - expect(component.find(WarningSummary)).to.not.be.present(); - }); - - it('renders the main column', function () { - expect(component.find(IndexHeader)).to.be.present(); - expect(component.find(IndexList)).to.be.present(); - }); - }); - - context('when there is an error', function () { - beforeEach(function () { - component = mount( - - ); - }); - - afterEach(function () { - component = null; - }); - - it('renders an error summary', function () { - expect(component.find(ErrorSummary)).to.be.present(); - expect(component.find(ErrorSummary).text()).to.equal('a test error'); - }); - }); -}); diff --git a/packages/compass-indexes/src/components/indexes/indexes.spec.tsx b/packages/compass-indexes/src/components/indexes/indexes.spec.tsx new file mode 100644 index 00000000000..46c091d2c6b --- /dev/null +++ b/packages/compass-indexes/src/components/indexes/indexes.spec.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { cleanup, render, screen, within } from '@testing-library/react'; +import { expect } from 'chai'; +import AppRegistry from 'hadron-app-registry'; + +import { Indexes } from './indexes'; + +const renderIndexes = ( + props: Partial> = {} +) => { + const appRegistry = new AppRegistry(); + render( + {}} + {...props} + /> + ); +}; + +describe('Indexes Component', function () { + before(cleanup); + afterEach(cleanup); + + it('renders indexes card', function () { + renderIndexes(); + expect(screen.getByTestId('indexes')).to.exist; + }); + + it('renders indexes toolbar', function () { + renderIndexes(); + expect(screen.getByTestId('indexes-toolbar')).to.exist; + }); + + it('does not render indexes list when its a readonly view', function () { + renderIndexes({ + indexes: [], + isReadonlyView: true, + error: undefined, + }); + expect(() => { + screen.getByTestId('indexes-list'); + }).to.throw; + }); + it('does not render indexes list when there is an error', function () { + renderIndexes({ + indexes: [], + isReadonlyView: false, + error: 'Some random error', + }); + expect(() => { + screen.getByTestId('indexes-list'); + }).to.throw; + }); + it('renders indexes list', function () { + renderIndexes({ + indexes: [ + { + cardinality: 'compound', + name: '_id_', + size: 12, + relativeSize: 20, + type: 'hashed', + extra: {}, + properties: ['unique'], + fields: { + serialize() { + return [ + { + field: '_id', + value: 1, + }, + ]; + }, + }, + }, + ], + isReadonlyView: false, + error: undefined, + }); + + const indexesList = screen.getByTestId('indexes-list'); + expect(indexesList).to.exist; + expect(within(indexesList).getByTestId('index-row-_id_')).to.exist; + }); +}); diff --git a/packages/compass-indexes/src/components/indexes/indexes.tsx b/packages/compass-indexes/src/components/indexes/indexes.tsx index 3e0dcb96159..08ac0a775b2 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.tsx +++ b/packages/compass-indexes/src/components/indexes/indexes.tsx @@ -24,7 +24,7 @@ type IndexesProps = { isWritable: boolean; isReadonly: boolean; isReadonlyView: boolean; - description: string; + description?: string; error?: string; localAppRegistry: AppRegistry; onSortTable: (name: string, direction: 'asc' | 'desc') => void; @@ -41,7 +41,7 @@ export const Indexes: React.FunctionComponent = ({ onSortTable, }) => { return ( - + Date: Wed, 17 Aug 2022 15:34:10 +0200 Subject: [PATCH 07/23] tests --- .../indexes-table/indexes-table.spec.tsx | 202 ++++++++++++++++++ .../indexes-table/indexes-table.tsx | 27 +-- .../src/components/indexes/indexes.spec.tsx | 2 +- .../src/components/indexes/indexes.tsx | 8 +- .../compass-indexes/src/modules/indexes.js | 2 +- .../src/modules/indexes.spec.js | 62 ++++-- .../src/modules/sort-column.spec.js | 8 +- .../src/modules/sort-order.spec.js | 8 +- 8 files changed, 277 insertions(+), 42 deletions(-) create mode 100644 packages/compass-indexes/src/components/indexes-table/indexes-table.spec.tsx diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.spec.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.spec.tsx new file mode 100644 index 00000000000..b569c9af300 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.spec.tsx @@ -0,0 +1,202 @@ +import React from 'react'; +import { cleanup, render, screen, within } from '@testing-library/react'; +import { expect } from 'chai'; +import userEvent from '@testing-library/user-event'; +import { spy } from 'sinon'; + +import { IndexesTable } from './indexes-table'; +import type { IndexModel } from './indexes-table'; + +const indexes: IndexModel[] = [ + { + cardinality: 'single', + name: '_id_', + size: 12, + relativeSize: 20, + type: 'hashed', + extra: {}, + properties: ['unique'], + fields: { + serialize() { + return [ + { + field: '_id', + value: 1, + }, + ]; + }, + }, + }, + { + cardinality: 'compound', + name: 'album_id_artist_id', + size: 20, + relativeSize: 25, + type: 'text', + extra: {}, + properties: [], + fields: { + serialize() { + return [ + { + field: 'album_id', + value: 1, + }, + { + field: 'artist_id', + value: -1, + }, + ]; + }, + }, + }, + { + cardinality: 'compound', + name: 'partial_with_ttl', + size: 20, + relativeSize: 25, + type: 'text', + extra: { + expireAfterSeconds: 3600, + partialFilterExpression: { + play_count: 30, + }, + }, + properties: ['ttl', 'partial'], + fields: { + serialize() { + return [ + { + field: 'views', + value: 1, + }, + ]; + }, + }, + }, + { + cardinality: 'single', + name: 'wildcard_index', + size: 20, + relativeSize: 25, + type: 'wildcard', + extra: { + wildcardProjection: { + fieldA: true, + _id: false, + }, + }, + properties: [], + fields: { + serialize() { + return [ + { + field: '$**', + value: 1, + }, + ]; + }, + }, + }, +]; + +const renderIndexList = ( + props: Partial> = {} +) => { + render( + {}} + onDeleteIndex={() => {}} + {...props} + /> + ); +}; + +describe('IndexesTable Component', function () { + before(cleanup); + afterEach(cleanup); + + it('renders indexes list', function () { + renderIndexList({ canDeleteIndex: true, indexes: indexes }); + + const indexesList = screen.getByTestId('indexes-list'); + expect(indexesList).to.exist; + + // Renders indexes list (table rows) + indexes.forEach((index) => { + const indexRow = screen.getByTestId(`index-row-${index.name}`); + expect(indexRow, 'it renders each index in a row').to.exist; + + // Renders index fields (table cells) + [ + 'index-name-field', + 'index-type-field', + 'index-size-field', + 'index-usage-field', + 'index-property-field', + 'index-drop-field', + ].forEach((indexCell) => { + // For _id index we always hide drop index field + if (index.name !== '_id_' && indexCell !== 'index-drop-field') { + expect(within(indexRow).getByTestId(indexCell)).to.exist; + } else { + expect(() => { + within(indexRow).getByTestId(indexCell); + }).to.throw; + } + }); + }); + }); + + it('does not render delete button when a user can not delete indexes', function () { + renderIndexList({ canDeleteIndex: false, indexes: indexes }); + const indexesList = screen.getByTestId('indexes-list'); + expect(indexesList).to.exist; + indexes.forEach((index) => { + const indexRow = screen.getByTestId(`index-row-${index.name}`); + expect(() => { + within(indexRow).getByTestId('index-drop-field'); + }).to.throw; + }); + }); + + ['Name and Definition', 'Type', 'Size', 'Usage', 'Properties'].forEach( + (column) => { + it(`sorts table by ${column}`, function () { + const onSortTableSpy = spy(); + renderIndexList({ + canDeleteIndex: true, + indexes: indexes, + onSortTable: onSortTableSpy, + }); + + const indexesList = screen.getByTestId('indexes-list'); + + const columnheader = within(indexesList).getByTestId( + `index-header-${column}` + ); + const sortButton = within(columnheader).getByRole('button', { + name: /sort/i, + }); + + expect(onSortTableSpy.callCount).to.equal(0); + + userEvent.click(sortButton); + expect(onSortTableSpy.callCount).to.equal(1); + expect(onSortTableSpy.getCalls()[0].args).to.deep.equal([ + column, + 'desc', + ]); + + userEvent.click(sortButton); + expect(onSortTableSpy.callCount).to.equal(2); + expect(onSortTableSpy.getCalls()[1].args).to.deep.equal([ + column, + 'asc', + ]); + }); + } + ); +}); diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx index c604373ab17..2b7acf54506 100644 --- a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx @@ -8,7 +8,6 @@ import { cx, } from '@mongodb-js/compass-components'; import type { IndexDirection } from 'mongodb'; -import type AppRegistry from 'hadron-app-registry'; import NameField from './name-field'; import TypeField from './type-field'; @@ -39,7 +38,7 @@ export type IndexModel = { type: 'geo' | 'hashed' | 'text' | 'wildcard' | 'clustered' | 'columnstore'; cardinality: 'single' | 'compound'; properties: ('unique' | 'sparse' | 'partial' | 'ttl' | 'collation')[]; - extra: Record; + extra: Record>; size: number; relativeSize: number; usageCount?: number; @@ -48,18 +47,16 @@ export type IndexModel = { type IndexesTableProps = { indexes: IndexModel[]; - isReadonly: boolean; - isWritable: boolean; - localAppRegistry: AppRegistry; + canDeleteIndex: boolean; onSortTable: (name: string, direction: 'asc' | 'desc') => void; + onDeleteIndex: (name: string) => void; }; export const IndexesTable: React.FunctionComponent = ({ indexes, - isReadonly, - isWritable, - localAppRegistry, + canDeleteIndex, onSortTable, + onDeleteIndex, }) => { const columns = useMemo(() => { const _columns = [ @@ -81,11 +78,11 @@ export const IndexesTable: React.FunctionComponent = ({ ); }); // The delete column - if (!isReadonly && isWritable) { + if (canDeleteIndex) { _columns.push(); } return _columns; - }, [isReadonly, isWritable, onSortTable]); + }, [canDeleteIndex, onSortTable]); return (
= ({ /> {/* Delete column is conditional */} - {index.name !== '_id_' && isWritable && !isReadonly && ( + {index.name !== '_id_' && canDeleteIndex && (
- localAppRegistry.emit( - 'toggle-drop-index-modal', - true, - index.name - ) - } + onDelete={() => onDeleteIndex(index.name)} />
diff --git a/packages/compass-indexes/src/components/indexes/indexes.spec.tsx b/packages/compass-indexes/src/components/indexes/indexes.spec.tsx index 46c091d2c6b..5c2f73e6712 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.spec.tsx +++ b/packages/compass-indexes/src/components/indexes/indexes.spec.tsx @@ -62,7 +62,7 @@ describe('Indexes Component', function () { renderIndexes({ indexes: [ { - cardinality: 'compound', + cardinality: 'single', name: '_id_', size: 12, relativeSize: 20, diff --git a/packages/compass-indexes/src/components/indexes/indexes.tsx b/packages/compass-indexes/src/components/indexes/indexes.tsx index 08ac0a775b2..88e0f079cef 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.tsx +++ b/packages/compass-indexes/src/components/indexes/indexes.tsx @@ -40,6 +40,9 @@ export const Indexes: React.FunctionComponent = ({ localAppRegistry, onSortTable, }) => { + const onDeleteIndex = (name: string) => { + return localAppRegistry.emit('toggle-drop-index-modal', true, name); + }; return ( = ({ {!isReadonlyView && !error && ( )} diff --git a/packages/compass-indexes/src/modules/indexes.js b/packages/compass-indexes/src/modules/indexes.js index dad8f8f53b7..53c6e9c5619 100644 --- a/packages/compass-indexes/src/modules/indexes.js +++ b/packages/compass-indexes/src/modules/indexes.js @@ -174,7 +174,7 @@ export const loadIndexes = (indexes) => ({ export const sortIndexes = (column, order) => { return (dispatch, getState) => { const { indexes } = getState(); - dispatch({ + return dispatch({ type: SORT_INDEXES, indexes, column, diff --git a/packages/compass-indexes/src/modules/indexes.spec.js b/packages/compass-indexes/src/modules/indexes.spec.js index 8775ee56d8b..60d6fd1baf9 100644 --- a/packages/compass-indexes/src/modules/indexes.spec.js +++ b/packages/compass-indexes/src/modules/indexes.spec.js @@ -31,17 +31,33 @@ describe('indexes module', function () { context('when the column is Usage', function () { context('when sorting asc', function () { it('returns the sorted indexes list', function () { - expect( - reducer(undefined, sortIndexes(defaultSort, USAGE, ASC)) - ).to.deep.equal(usageSort); + const dispatch = (args) => args; + const getState = () => { + return { + indexes: defaultSort, + }; + }; + const result = reducer( + undefined, + sortIndexes(USAGE, ASC)(dispatch, getState) + ); + expect(result).to.deep.equal(usageSort); }); }); context('when sorting desc', function () { it('returns the sorted indexes list', function () { - expect( - reducer(undefined, sortIndexes(defaultSort, USAGE, DESC)) - ).to.deep.equal(usageSortDesc); + const dispatch = (args) => args; + const getState = () => { + return { + indexes: defaultSort, + }; + }; + const result = reducer( + undefined, + sortIndexes(USAGE, DESC)(dispatch, getState) + ); + expect(result).to.deep.equal(usageSortDesc); }); }); }); @@ -49,17 +65,33 @@ describe('indexes module', function () { context('when the column is Name and Definition', function () { context('when sorting asc', function () { it('returns the sorted indexes list', function () { - expect( - reducer(undefined, sortIndexes(usageSort, DEFAULT, ASC)) - ).to.deep.equal(defaultSort); + const dispatch = (args) => args; + const getState = () => { + return { + indexes: usageSort, + }; + }; + const result = reducer( + undefined, + sortIndexes(DEFAULT, ASC)(dispatch, getState) + ); + expect(result).to.deep.equal(defaultSort); }); }); context('when sorting desc', function () { it('returns the sorted indexes list', function () { - expect( - reducer(undefined, sortIndexes(usageSort, DEFAULT, DESC)) - ).to.deep.equal(defaultSortDesc); + const dispatch = (args) => args; + const getState = () => { + return { + indexes: usageSort, + }; + }; + const result = reducer( + undefined, + sortIndexes(DEFAULT, DESC)(dispatch, getState) + ); + expect(result).to.deep.equal(defaultSortDesc); }); }); }); @@ -84,7 +116,11 @@ describe('indexes module', function () { describe('#sortIndexes', function () { it('returns the action', function () { - expect(sortIndexes([], 'Database Name', DESC)).to.deep.equal({ + const dispatch = (x) => x; + const getState = () => ({ indexes: [] }); + expect( + sortIndexes('Database Name', DESC)(dispatch, getState) + ).to.deep.equal({ type: SORT_INDEXES, indexes: [], column: 'Database Name', diff --git a/packages/compass-indexes/src/modules/sort-column.spec.js b/packages/compass-indexes/src/modules/sort-column.spec.js index b51d1390b31..6c5ad7e5541 100644 --- a/packages/compass-indexes/src/modules/sort-column.spec.js +++ b/packages/compass-indexes/src/modules/sort-column.spec.js @@ -7,9 +7,11 @@ describe('sort column module', function () { describe('#reducer', function () { context('when an action is provided', function () { it('returns the new column', function () { - expect(reducer(undefined, sortIndexes(null, 'Size', ''))).to.equal( - 'Size' - ); + const dispatch = (x) => x; + const getState = () => ({}); + expect( + reducer(undefined, sortIndexes('Size', '')(dispatch, getState)) + ).to.equal('Size'); }); }); diff --git a/packages/compass-indexes/src/modules/sort-order.spec.js b/packages/compass-indexes/src/modules/sort-order.spec.js index e0b4e9e6c4c..32dcec67430 100644 --- a/packages/compass-indexes/src/modules/sort-order.spec.js +++ b/packages/compass-indexes/src/modules/sort-order.spec.js @@ -7,9 +7,11 @@ describe('sort order module', function () { describe('#reducer', function () { context('when an action is provided', function () { it('returns the new order', function () { - expect(reducer(undefined, sortIndexes(null, '', 'desc'))).to.equal( - 'desc' - ); + const dispatch = (x) => x; + const getState = () => ({}); + expect( + reducer(undefined, sortIndexes('', 'desc')(dispatch, getState)) + ).to.equal('desc'); }); }); From 53e2d8ab7d893e9d500dea99d1cac454f0156e03 Mon Sep 17 00:00:00 2001 From: Basit Date: Wed, 17 Aug 2022 17:12:30 +0200 Subject: [PATCH 08/23] component tests --- .../badge-with-icon-link.spec.tsx | 20 +++++++ .../indexes-table/badge-with-icon-link.tsx | 6 +- .../indexes-table/drop-field.spec.tsx | 24 ++++++++ .../indexes-table/name-field.spec.tsx | 60 +++++++++++++++++++ .../indexes-table/property-field.spec.tsx | 59 ++++++++++++++++++ .../indexes-table/property-field.tsx | 1 - .../indexes-table/size-field.spec.tsx | 21 +++++++ .../indexes-table/type-field.spec.tsx | 39 ++++++++++++ .../indexes-table/usage-field.spec.tsx | 34 +++++++++++ .../components/indexes-table/usage-field.tsx | 9 +-- 10 files changed, 265 insertions(+), 8 deletions(-) create mode 100644 packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.spec.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/drop-field.spec.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/name-field.spec.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/size-field.spec.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx create mode 100644 packages/compass-indexes/src/components/indexes-table/usage-field.spec.tsx diff --git a/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.spec.tsx b/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.spec.tsx new file mode 100644 index 00000000000..2f5587767c7 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.spec.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { cleanup, render, screen, within } from '@testing-library/react'; +import { expect } from 'chai'; + +import BadgeWithIconLink from './badge-with-icon-link'; + +describe('BadgeWithIconLink Component', function () { + before(cleanup); + afterEach(cleanup); + it('render a badge with icon', function () { + render(); + const container = screen.getByTestId('mongodb-badge'); + expect(within(container).getByText(/mongodb/i)).to.exist; + const infoIcon = within(container).getByRole('img', { + name: /info with circle icon/i, + }); + expect(infoIcon).to.exist; + expect(infoIcon.closest('a')?.href).to.equal('https://mongodb.com/'); + }); +}); diff --git a/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx b/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx index 7c13603cb84..c30c6c81a10 100644 --- a/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx +++ b/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx @@ -32,7 +32,11 @@ const BadgeWithIconLink: React.FunctionComponent = ({ link, }) => { return ( - + {text} ); + const button = screen.getByTestId('drop-index-button'); + expect(button).to.exist; + expect(button.getAttribute('aria-label')).to.equal( + 'Drop Index artist_id_index' + ); + expect(onDeleteSpy.callCount).to.equal(0); + userEvent.click(button); + expect(onDeleteSpy.callCount).to.equal(1); + }); +}); diff --git a/packages/compass-indexes/src/components/indexes-table/name-field.spec.tsx b/packages/compass-indexes/src/components/indexes-table/name-field.spec.tsx new file mode 100644 index 00000000000..a0a243e08bf --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/name-field.spec.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { cleanup, render, screen, within } from '@testing-library/react'; +import { expect } from 'chai'; +import userEvent from '@testing-library/user-event'; + +import NameField from './name-field'; + +describe('NameField Component', function () { + before(cleanup); + afterEach(cleanup); + it('renders name with keys', function () { + const name = 'album_artist_title_index'; + const keys = [ + { + field: 'album_id', + value: 1, + }, + { + field: 'artist_id', + value: -1, + }, + { + field: 'title', + value: 'text', + }, + ]; + render(); + + const accordianButton = screen.getByRole('button', { + name: `Show/Hide index ${name} keys`, + }); + + expect(accordianButton).to.exist; + userEvent.click(accordianButton); + + const keysList = screen.getByRole('list'); + + const albumBadge = within(keysList).getByTestId('album_id-key'); + expect(albumBadge).to.exist; + expect( + within(albumBadge).getByRole('img', { + name: /ascending index/i, + }) + ).to.exist; + expect(albumBadge.textContent).to.equal('album_id'); + + const artistBadge = within(keysList).getByTestId('artist_id-key'); + expect(artistBadge).to.exist; + expect( + within(artistBadge).getByRole('img', { + name: /descending index/i, + }) + ).to.exist; + expect(artistBadge.textContent).to.equal('artist_id'); + + const titleBadge = within(keysList).getByTestId('title-key'); + expect(titleBadge).to.exist; + expect(titleBadge.textContent).to.equal('title(text)'); + }); +}); diff --git a/packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx b/packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx new file mode 100644 index 00000000000..dbd14a6efd4 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { cleanup, render, screen, within } from '@testing-library/react'; +import { expect } from 'chai'; + +import PropertyField from './property-field'; +import getIndexHelpLink from '../../utils/index-link-helper'; + +describe('PropertyField Component', function () { + before(cleanup); + afterEach(cleanup); + it('renders index properties', function () { + render( + + ); + + ['ttl', 'partial'].forEach((type) => { + const badge = screen.getByTestId(`${type}-badge`); + expect(badge).to.exist; + expect(badge.textContent).to.equal(type); + const infoIcon = within(badge).getByRole('img', { + name: /info with circle icon/i, + }); + expect(infoIcon).to.exist; + expect(infoIcon.closest('a')?.href).to.equal( + getIndexHelpLink(type.toUpperCase() as any) + ); + + // todo: tooltip tests + }); + }); + + it('does not render cardinality badge when its single', function () { + render(); + expect(() => { + screen.getByTestId('compound-badge'); + }).to.throw; + }); + + it('renders cardinality badge when its compound', function () { + render( + + ); + const badge = screen.getByTestId('compound-badge'); + expect(badge).to.exist; + expect(badge.textContent).to.equal('compound'); + const infoIcon = within(badge).getByRole('img', { + name: /info with circle icon/i, + }); + expect(infoIcon).to.exist; + expect(infoIcon.closest('a')?.href).to.equal(getIndexHelpLink('COMPOUND')); + }); +}); diff --git a/packages/compass-indexes/src/components/indexes-table/property-field.tsx b/packages/compass-indexes/src/components/indexes-table/property-field.tsx index 90ca47517e0..b4799392526 100644 --- a/packages/compass-indexes/src/components/indexes-table/property-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/property-field.tsx @@ -25,7 +25,6 @@ const PropertyBadgeWithTooltip: React.FunctionComponent<{ }> = ({ text, link, tooltip }) => { return ( ( diff --git a/packages/compass-indexes/src/components/indexes-table/size-field.spec.tsx b/packages/compass-indexes/src/components/indexes-table/size-field.spec.tsx new file mode 100644 index 00000000000..928df54b900 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/size-field.spec.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { cleanup, render, screen } from '@testing-library/react'; +import { expect } from 'chai'; + +import SizeField from './size-field'; + +describe('SizeField Component', function () { + before(cleanup); + afterEach(cleanup); + it('renders size - less than 1000', function () { + render(); + expect(screen.getByText(/20 b/i)).to.exist; + // todo: tooltip tests + }); + + it('renders size - greater than 1000', function () { + render(); + expect(screen.getByText(/2.0 kb/i)).to.exist; + // todo: tooltip tests + }); +}); diff --git a/packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx b/packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx new file mode 100644 index 00000000000..769af066585 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { cleanup, render, screen, within } from '@testing-library/react'; +import { expect } from 'chai'; + +import TypeField from './type-field'; +import getIndexHelpLink from '../../utils/index-link-helper'; + +describe('TypeField Component', function () { + before(cleanup); + afterEach(cleanup); + it('renders index type', function () { + render(); + + const badge = screen.getByTestId('text-badge'); + expect(badge).to.exist; + + expect(badge.textContent).to.equal('text'); + const infoIcon = within(badge).getByRole('img', { + name: /info with circle icon/i, + }); + expect(infoIcon).to.exist; + expect(infoIcon.closest('a')?.href).to.equal(getIndexHelpLink('TEXT')); + }); + + it('renders index type - with extra information', function () { + render( + + ); + + const badge = screen.getByTestId('hashed-badge'); + expect(badge).to.exist; + // todo: tooltip test + }); +}); diff --git a/packages/compass-indexes/src/components/indexes-table/usage-field.spec.tsx b/packages/compass-indexes/src/components/indexes-table/usage-field.spec.tsx new file mode 100644 index 00000000000..8931ad8ff06 --- /dev/null +++ b/packages/compass-indexes/src/components/indexes-table/usage-field.spec.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { cleanup, render, screen } from '@testing-library/react'; +import { expect } from 'chai'; + +import UsageField from './usage-field'; + +describe('UsageField Component', function () { + before(cleanup); + afterEach(cleanup); + it('renders usage', function () { + const since = new Date(); + render(); + + const renderedText = `20 (since ${since.toDateString()})`; + expect(screen.getByText(renderedText)).to.exist; + // todo: tooltip tests + }); + + it('renders zero when usage is not defined', function () { + const since = new Date(); + render(); + + const renderedText = `0 (since ${since.toDateString()})`; + expect(screen.getByText(renderedText)).to.exist; + // todo: tooltip tests + }); + + it('renders N/A when since is not defined', function () { + render(); + const renderedText = '30 (N/A)'; + expect(screen.getByText(renderedText)).to.exist; + // todo: tooltip tests + }); +}); diff --git a/packages/compass-indexes/src/components/indexes-table/usage-field.tsx b/packages/compass-indexes/src/components/indexes-table/usage-field.tsx index 9c4bbd993a5..308b30c1b91 100644 --- a/packages/compass-indexes/src/components/indexes-table/usage-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/usage-field.tsx @@ -10,6 +10,7 @@ type UsageFieldProps = { since?: Date; }; +const nbsp = '\u00a0'; const UsageField: React.FunctionComponent = ({ usage, since, @@ -20,12 +21,8 @@ const UsageField: React.FunctionComponent = ({ {children} - {usage || 0} ( - - since  - {since ? since.toDateString() : 'N/A'} - - ) + {usage || 0} + {nbsp}(<>{since ? `since ${since.toDateString()}` : 'N/A'}) )} From 020900a8077c1686ce0e036a5681f1a402e861fe Mon Sep 17 00:00:00 2001 From: Basit Date: Wed, 17 Aug 2022 19:48:44 +0200 Subject: [PATCH 09/23] e2e tests --- .../compass-e2e-tests/helpers/selectors.ts | 18 ++++++-------- .../tests/collection-indexes-tab.test.ts | 24 ++++++++++++------- .../tests/database-collections-tab.test.ts | 2 +- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/packages/compass-e2e-tests/helpers/selectors.ts b/packages/compass-e2e-tests/helpers/selectors.ts index 6aa8f05f18f..03f722d0819 100644 --- a/packages/compass-e2e-tests/helpers/selectors.ts +++ b/packages/compass-e2e-tests/helpers/selectors.ts @@ -770,10 +770,12 @@ export const ExplainDocumentsReturnedSummary = '[data-test-id="documents-returned-summary"]'; // Indexes tab -export const IndexList = '[data-test-id="index-list"]'; -export const IndexComponent = '[data-test-id="index-list"] tr'; -export const IndexFieldName = '[data-testid="index-field-name"]'; -export const IndexFieldType = '[data-testid="index-field-type"]'; +export const IndexList = '[data-testid="indexes-list"]'; +export const IndexComponent = (name: string): string => { + return `[data-testid="index-row-${name}"]`; +}; +export const IndexFieldName = '[data-testid="index-name-field"]'; +export const IndexFieldType = '[data-testid="index-type-field"]'; export const IndexToggleOptions = '[data-test-id="create-index-modal-toggle-options"]'; export const IndexToggleIsWildcard = @@ -801,13 +803,7 @@ export const DropIndexModalConfirmName = export const DropIndexModalConfirmButton = '[data-testid="drop_index_modal"] [role=dialog] > div:nth-child(2) button:first-child'; -export const indexComponent = (indexName: string): string => { - return `[data-test-id="index-component-${indexName}"]`; -}; - -export const dropIndexButton = (indexName: string): string => { - return `[data-testid="drop-index-button-${indexName}"]`; -}; +export const DropIndexButton = '[data-testid="drop-index-button"]'; // Validation tab export const AddRuleButton = '[data-test-id="add-rule-button"]'; diff --git a/packages/compass-e2e-tests/tests/collection-indexes-tab.test.ts b/packages/compass-e2e-tests/tests/collection-indexes-tab.test.ts index cdbecdb802d..ef50a3c7b2b 100644 --- a/packages/compass-e2e-tests/tests/collection-indexes-tab.test.ts +++ b/packages/compass-e2e-tests/tests/collection-indexes-tab.test.ts @@ -41,10 +41,12 @@ describe('Collection indexes tab', function () { const element = await browser.$(Selectors.IndexList); await element.waitForDisplayed(); - const indexes = await browser.$$(Selectors.IndexComponent); + const indexes = await browser.$$(Selectors.IndexComponent('_id_')); expect(indexes).to.have.lengthOf(1); - const indexFieldNameElement = await browser.$(Selectors.IndexFieldName); + const indexFieldNameElement = await browser.$( + `${Selectors.IndexComponent('_id_')} ${Selectors.IndexFieldName}` + ); expect(await indexFieldNameElement.getText()).to.equal('_id_'); }); @@ -82,10 +84,12 @@ describe('Collection indexes tab', function () { await createModal.waitForDisplayed({ reverse: true }); - const indexComponent = await browser.$(Selectors.indexComponent('i_text')); + const indexComponent = await browser.$(Selectors.IndexComponent('i_text')); await indexComponent.waitForDisplayed(); - await browser.clickVisible(Selectors.dropIndexButton('i_text')); + await browser.clickVisible( + `${Selectors.IndexComponent('i_text')} ${Selectors.DropIndexButton}` + ); const dropModal = await browser.$(Selectors.DropIndexModal); await dropModal.waitForDisplayed(); @@ -156,10 +160,10 @@ describe('Collection indexes tab', function () { await createModal.waitForDisplayed({ reverse: true }); - const indexComponent = await browser.$(Selectors.indexComponent('$**_1')); + const indexComponent = await browser.$(Selectors.IndexComponent('$**_1')); await indexComponent.waitForDisplayed(); - const indexFieldTypeSelector = `${Selectors.indexComponent('$**_1')} ${ + const indexFieldTypeSelector = `${Selectors.IndexComponent('$**_1')} ${ Selectors.IndexFieldType }`; const indexFieldTypeElement = await browser.$(indexFieldTypeSelector); @@ -211,11 +215,15 @@ describe('Collection indexes tab', function () { await createModal.waitForDisplayed({ reverse: true }); const indexComponent = await browser.$( - Selectors.indexComponent('columnstore') + Selectors.IndexComponent('columnstore') ); await indexComponent.waitForDisplayed(); - await browser.clickVisible(Selectors.dropIndexButton('columnstore')); + await browser.clickVisible( + `${Selectors.IndexComponent('columnstore')} ${ + Selectors.DropIndexButton + }` + ); const dropModal = await browser.$(Selectors.DropIndexModal); await dropModal.waitForDisplayed(); diff --git a/packages/compass-e2e-tests/tests/database-collections-tab.test.ts b/packages/compass-e2e-tests/tests/database-collections-tab.test.ts index f201e44b2bb..227459592ee 100644 --- a/packages/compass-e2e-tests/tests/database-collections-tab.test.ts +++ b/packages/compass-e2e-tests/tests/database-collections-tab.test.ts @@ -250,7 +250,7 @@ describe('Database collections tab', function () { await browser.navigateToCollectionTab('test', collectionName, 'Indexes'); - const typeElementSelector = `${Selectors.indexComponent(indexName)} ${ + const typeElementSelector = `${Selectors.IndexComponent(indexName)} ${ Selectors.IndexFieldType }`; const typeElement = await browser.$(typeElementSelector); From d70b1f5695d43dbd2fd685d9f7cccbf77ddc3646 Mon Sep 17 00:00:00 2001 From: Basit Date: Wed, 17 Aug 2022 19:49:27 +0200 Subject: [PATCH 10/23] lint --- packages/compass-indexes/src/utils/index-link-helper.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/compass-indexes/src/utils/index-link-helper.ts b/packages/compass-indexes/src/utils/index-link-helper.ts index 18d546c6faf..0150b3f2049 100644 --- a/packages/compass-indexes/src/utils/index-link-helper.ts +++ b/packages/compass-indexes/src/utils/index-link-helper.ts @@ -34,4 +34,3 @@ const HELP_URLS = { export default function getIndexHelpLink(section: keyof typeof HELP_URLS) { return HELP_URLS[section] || null; } - From 41201e1f637b5f780baacd045a90c61e3d4ce2c5 Mon Sep 17 00:00:00 2001 From: Basit Date: Wed, 17 Aug 2022 21:01:00 +0200 Subject: [PATCH 11/23] clean up --- package-lock.json | 4 ---- packages/compass-indexes/package.json | 2 -- .../components/indexes-table/indexes-table.tsx | 3 +-- .../src/components/indexes-table/type-field.tsx | 15 ++++++++------- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index e936eeebaba..68a6dbc98b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70381,10 +70381,8 @@ "hadron-app": "^5.0.0", "hadron-app-registry": "^9.0.0", "lodash.contains": "^2.4.3", - "lodash.isundefined": "^3.0.1", "lodash.map": "^4.6.0", "lodash.max": "^4.0.1", - "lodash.pick": "^4.4.0", "lodash.pluck": "^3.1.2", "mocha": "^8.4.0", "mongodb-query-parser": "^2.4.6", @@ -108337,10 +108335,8 @@ "hadron-react-buttons": "^6.0.0", "hadron-react-components": "^6.0.0", "lodash.contains": "^2.4.3", - "lodash.isundefined": "^3.0.1", "lodash.map": "^4.6.0", "lodash.max": "^4.0.1", - "lodash.pick": "^4.4.0", "lodash.pluck": "^3.1.2", "mocha": "^8.4.0", "mongodb-index-model": "^4.0.0", diff --git a/packages/compass-indexes/package.json b/packages/compass-indexes/package.json index 5da6aac704d..8f8fbb56a8e 100644 --- a/packages/compass-indexes/package.json +++ b/packages/compass-indexes/package.json @@ -81,10 +81,8 @@ "hadron-app": "^5.0.0", "hadron-app-registry": "^9.0.0", "lodash.contains": "^2.4.3", - "lodash.isundefined": "^3.0.1", "lodash.map": "^4.6.0", "lodash.max": "^4.0.1", - "lodash.pick": "^4.4.0", "lodash.pluck": "^3.1.2", "mocha": "^8.4.0", "mongodb-query-parser": "^2.4.6", diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx index 2b7acf54506..f7a2015f85b 100644 --- a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx @@ -7,7 +7,6 @@ import { Cell, cx, } from '@mongodb-js/compass-components'; -import type { IndexDirection } from 'mongodb'; import NameField from './name-field'; import TypeField from './type-field'; @@ -33,7 +32,7 @@ const deletFieldStyles = css({ export type IndexModel = { name: string; fields: { - serialize: () => { field: string; value: IndexDirection }[]; + serialize: () => { field: string; value: number | string }[]; }; type: 'geo' | 'hashed' | 'text' | 'wildcard' | 'clustered' | 'columnstore'; cardinality: 'single' | 'compound'; diff --git a/packages/compass-indexes/src/components/indexes-table/type-field.tsx b/packages/compass-indexes/src/components/indexes-table/type-field.tsx index 424c5fac396..6a3d9714c4a 100644 --- a/packages/compass-indexes/src/components/indexes-table/type-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/type-field.tsx @@ -1,5 +1,3 @@ -import map from 'lodash.map'; -import pick from 'lodash.pick'; import React from 'react'; import getIndexHelpLink from '../../utils/index-link-helper'; import { Tooltip, Body } from '@mongodb-js/compass-components'; @@ -19,16 +17,19 @@ type TypeFieldProps = { const IndexTypeTooltip: React.FunctionComponent<{ extra: IndexModel['extra']; }> = ({ extra }) => { - const info = pick(extra, [ + const allowedProps = [ 'weights', 'default_language', 'language_override', 'wildcardProjection', 'columnstoreProjection', - ]); - const items = map(info, (v: unknown, k: string) => { - return {`${k}: ${JSON.stringify(v)}`}; - }); + ]; + const items: JSX.Element[] = []; + for (const k in extra) { + if (allowedProps.includes(k)) { + items.push({`${k}: ${JSON.stringify(extra[k])}`}); + } + } return <>{items}; }; From 426790a7dd66b230d323b2987c6a859e9b2e131c Mon Sep 17 00:00:00 2001 From: Basit Date: Thu, 18 Aug 2022 10:07:08 +0200 Subject: [PATCH 12/23] test fix --- .../src/components/pipeline-explain/index.spec.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/compass-aggregations/src/components/pipeline-explain/index.spec.tsx b/packages/compass-aggregations/src/components/pipeline-explain/index.spec.tsx index 0c24e10db7e..5f539d7a676 100644 --- a/packages/compass-aggregations/src/components/pipeline-explain/index.spec.tsx +++ b/packages/compass-aggregations/src/components/pipeline-explain/index.spec.tsx @@ -147,7 +147,8 @@ describe('PipelineExplain', function () { name: /ascending index/i, // host_id index direction 1 }) ).to.exist; - expect(within(indexContent1).getByText(/location \(2dsphere\)/i)).to.exist; + expect(within(indexContent1).getByText(/location/i)).to.exist; + expect(within(indexContent1).getByText(/\(2dsphere\)/i)).to.exist; // Toggle second accordian userEvent.click( @@ -164,6 +165,7 @@ describe('PipelineExplain', function () { name: /descending index/i, // city_id index direction -1 }) ).to.exist; - expect(within(indexContent2).getByText(/title \(text\)/i)).to.exist; + expect(within(indexContent2).getByText(/title/i)).to.exist; + expect(within(indexContent2).getByText(/\(text\)/i)).to.exist; }); }); From 29be66606e4c4fcc9bdced4eaed527f38bd673dd Mon Sep 17 00:00:00 2001 From: Basit Date: Thu, 18 Aug 2022 11:33:08 +0200 Subject: [PATCH 13/23] ux changes --- .../src/components/indexes/indexes.tsx | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes/indexes.tsx b/packages/compass-indexes/src/components/indexes/indexes.tsx index 88e0f079cef..56c2e88c653 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.tsx +++ b/packages/compass-indexes/src/components/indexes/indexes.tsx @@ -12,11 +12,21 @@ import type { IndexModel } from '../indexes-table/indexes-table'; const containerStyles = css({ margin: spacing[3], padding: spacing[3], - display: 'flex', - flexDirection: 'column', + display: 'grid', + gridTemplateAreas: ` + 'toolbar' + 'indexTable' + `, width: '100%', - height: 'auto', - overflowY: 'scroll', + overflow: 'hidden', + alignContent: 'start', +}); +const toolbarStyles = css({ + gridArea: 'toolbar', +}); +const indexTableStyles = css({ + gridArea: 'indexTable', + overflow: 'auto', }); type IndexesProps = { @@ -45,21 +55,25 @@ export const Indexes: React.FunctionComponent = ({ }; return ( - - {!isReadonlyView && !error && ( - + + + {!isReadonlyView && !error && ( +
+ +
)}
); From ba73251f218c9e6f340011b4ac26ef459ee1d8f8 Mon Sep 17 00:00:00 2001 From: Basit Date: Thu, 18 Aug 2022 13:29:58 +0200 Subject: [PATCH 14/23] align table data to top --- .../indexes-table/indexes-table.tsx | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx index f7a2015f85b..14068c37167 100644 --- a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx @@ -6,6 +6,7 @@ import { Row, Cell, cx, + spacing, } from '@mongodb-js/compass-components'; import NameField from './name-field'; @@ -28,6 +29,15 @@ const deletFieldStyles = css({ visibility: 'hidden', }); +const cellStyles = css({ + verticalAlign: 'top', +}); + +const nameFieldStyles = css({ + paddingTop: spacing[2], + paddingBottom: spacing[2], +}); + // todo: move to redux store when converting that to ts export type IndexModel = { name: string; @@ -96,19 +106,21 @@ export const IndexesTable: React.FunctionComponent = ({ data-testid={`index-row-${index.name}`} className={rowStyles} > - - + +
+ +
- + - + - + - + = ({ {/* Delete column is conditional */} {index.name !== '_id_' && canDeleteIndex && ( - +
Date: Thu, 18 Aug 2022 15:29:54 +0200 Subject: [PATCH 15/23] more tests --- .../indexes-table/property-field.spec.tsx | 102 ++++++++++------- .../indexes-table/property-field.tsx | 20 ++-- .../indexes-table/size-field.spec.tsx | 28 +++-- .../components/indexes-table/size-field.tsx | 12 +- .../indexes-table/type-field.spec.tsx | 103 ++++++++++++++---- .../components/indexes-table/type-field.tsx | 4 +- .../indexes-table/usage-field.spec.tsx | 52 +++++---- .../components/indexes-table/usage-field.tsx | 12 +- 8 files changed, 222 insertions(+), 111 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx b/packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx index dbd14a6efd4..a9cf3f0cc72 100644 --- a/packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx +++ b/packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx @@ -2,58 +2,86 @@ import React from 'react'; import { cleanup, render, screen, within } from '@testing-library/react'; import { expect } from 'chai'; -import PropertyField from './property-field'; +import PropertyField, { getPropertyTooltip } from './property-field'; import getIndexHelpLink from '../../utils/index-link-helper'; -describe('PropertyField Component', function () { +describe('PropertyField', function () { before(cleanup); afterEach(cleanup); - it('renders index properties', function () { - render( - - ); - - ['ttl', 'partial'].forEach((type) => { - const badge = screen.getByTestId(`${type}-badge`); + describe('PropertyField Component', function () { + it('renders index properties', function () { + render( + + ); + + ['ttl', 'partial'].forEach((type) => { + const badge = screen.getByTestId(`${type}-badge`); + expect(badge).to.exist; + expect(badge.textContent).to.equal(type); + const infoIcon = within(badge).getByRole('img', { + name: /info with circle icon/i, + }); + expect(infoIcon).to.exist; + expect(infoIcon.closest('a')?.href).to.equal( + getIndexHelpLink(type.toUpperCase() as any) + ); + }); + }); + + it('does not render cardinality badge when its single', function () { + render( + + ); + expect(() => { + screen.getByTestId('compound-badge'); + }).to.throw; + }); + + it('renders cardinality badge when its compound', function () { + render( + + ); + const badge = screen.getByTestId('compound-badge'); expect(badge).to.exist; - expect(badge.textContent).to.equal(type); + expect(badge.textContent).to.equal('compound'); const infoIcon = within(badge).getByRole('img', { name: /info with circle icon/i, }); expect(infoIcon).to.exist; expect(infoIcon.closest('a')?.href).to.equal( - getIndexHelpLink(type.toUpperCase() as any) + getIndexHelpLink('COMPOUND') ); - - // todo: tooltip tests }); }); - it('does not render cardinality badge when its single', function () { - render(); - expect(() => { - screen.getByTestId('compound-badge'); - }).to.throw; - }); + describe('getPropertyTooltip', function () { + it('returns ttl tooltip', function () { + expect( + getPropertyTooltip('ttl', { + expireAfterSeconds: 200, + }) + ).to.equal('expireAfterSeconds: 200'); + }); - it('renders cardinality badge when its compound', function () { - render( - - ); - const badge = screen.getByTestId('compound-badge'); - expect(badge).to.exist; - expect(badge.textContent).to.equal('compound'); - const infoIcon = within(badge).getByRole('img', { - name: /info with circle icon/i, + it('returns partial tooltip', function () { + expect( + getPropertyTooltip('partial', { + partialFilterExpression: { _id: true }, + }) + ).to.equal(`partialFilterExpression: ${JSON.stringify({ _id: true })}`); + }); + + it('returns null for unsupported properties', function () { + ['unique', 'sparse', 'collation'].forEach( + (prop) => expect(getPropertyTooltip(prop, {})).to.be.null + ); }); - expect(infoIcon).to.exist; - expect(infoIcon.closest('a')?.href).to.equal(getIndexHelpLink('COMPOUND')); }); }); diff --git a/packages/compass-indexes/src/components/indexes-table/property-field.tsx b/packages/compass-indexes/src/components/indexes-table/property-field.tsx index b4799392526..45e9cd17b3e 100644 --- a/packages/compass-indexes/src/components/indexes-table/property-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/property-field.tsx @@ -18,6 +18,17 @@ const ttlTooltip = (expireAfterSeconds: number) => { return `expireAfterSeconds: ${expireAfterSeconds}`; }; +export const getPropertyTooltip = ( + property: IndexModel['properties'][0], + extra: IndexModel['extra'] +): string | null => { + return property === 'ttl' + ? ttlTooltip(extra.expireAfterSeconds as number) + : property === 'partial' + ? partialTooltip(extra.partialFilterExpression as JSON) + : null; +}; + const PropertyBadgeWithTooltip: React.FunctionComponent<{ text: string; link: string; @@ -52,20 +63,13 @@ const PropertyField: React.FunctionComponent = ({ return (
{properties.map((property) => { - const tooltip = - property === 'ttl' - ? ttlTooltip(extra.expireAfterSeconds as number) - : property === 'partial' - ? partialTooltip(extra.partialFilterExpression as JSON) - : null; - return ( ); })} diff --git a/packages/compass-indexes/src/components/indexes-table/size-field.spec.tsx b/packages/compass-indexes/src/components/indexes-table/size-field.spec.tsx index 928df54b900..61b993c127c 100644 --- a/packages/compass-indexes/src/components/indexes-table/size-field.spec.tsx +++ b/packages/compass-indexes/src/components/indexes-table/size-field.spec.tsx @@ -2,20 +2,28 @@ import React from 'react'; import { cleanup, render, screen } from '@testing-library/react'; import { expect } from 'chai'; -import SizeField from './size-field'; +import SizeField, { formatSize, getSizeTooltip } from './size-field'; -describe('SizeField Component', function () { +describe('SizeField', function () { before(cleanup); afterEach(cleanup); - it('renders size - less than 1000', function () { - render(); - expect(screen.getByText(/20 b/i)).to.exist; - // todo: tooltip tests + describe('SizeField Component', function () { + it('renders size', function () { + render(); + expect(screen.getByText(/20 b/i)).to.exist; + }); }); - it('renders size - greater than 1000', function () { - render(); - expect(screen.getByText(/2.0 kb/i)).to.exist; - // todo: tooltip tests + describe('SizeField functions', function () { + it('formats size', function () { + expect(formatSize(908)).to.equal('908 B'); + expect(formatSize(2020)).to.equal('2.0 KB'); + expect(formatSize(202020)).to.equal('202.0 KB'); + }); + + it('returns correct tooltip', function () { + expect(getSizeTooltip(20)).to.equal('20.00% compared to largest index'); + expect(getSizeTooltip(8)).to.equal('8.00% compared to largest index'); + }); }); }); diff --git a/packages/compass-indexes/src/components/indexes-table/size-field.tsx b/packages/compass-indexes/src/components/indexes-table/size-field.tsx index 5037ee75d39..ab9d39984b1 100644 --- a/packages/compass-indexes/src/components/indexes-table/size-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/size-field.tsx @@ -7,27 +7,29 @@ type SizeFieldProps = { relativeSize: number; }; -const format = (size: number) => { +export const formatSize = (size: number) => { const precision = size <= 1000 ? '0' : '0.0'; return numeral(size).format(precision + ' b'); }; +export const getSizeTooltip = (relativeSize: number): string => { + return `${relativeSize.toFixed(2)}% compared to largest index`; +}; + const SizeField: React.FunctionComponent = ({ relativeSize, size, }) => { - const indexSize = format(size); - const tooltip = `${relativeSize.toFixed(2)}% compared to largest index`; return ( ( {children} - {indexSize} + {formatSize(size)} )} > - {tooltip} + {getSizeTooltip(relativeSize)} ); }; diff --git a/packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx b/packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx index 769af066585..645c78935d0 100644 --- a/packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx +++ b/packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx @@ -2,38 +2,93 @@ import React from 'react'; import { cleanup, render, screen, within } from '@testing-library/react'; import { expect } from 'chai'; -import TypeField from './type-field'; +import TypeField, { IndexTypeTooltip, canRenderTooltip } from './type-field'; import getIndexHelpLink from '../../utils/index-link-helper'; -describe('TypeField Component', function () { +describe('TypeField', function () { before(cleanup); afterEach(cleanup); - it('renders index type', function () { - render(); + describe('TypeField Component', function () { + it('renders index type', function () { + render(); - const badge = screen.getByTestId('text-badge'); - expect(badge).to.exist; + const badge = screen.getByTestId('text-badge'); + expect(badge).to.exist; - expect(badge.textContent).to.equal('text'); - const infoIcon = within(badge).getByRole('img', { - name: /info with circle icon/i, + expect(badge.textContent).to.equal('text'); + const infoIcon = within(badge).getByRole('img', { + name: /info with circle icon/i, + }); + expect(infoIcon).to.exist; + expect(infoIcon.closest('a')?.href).to.equal(getIndexHelpLink('TEXT')); + }); + + it('renders index type - with extra information', function () { + render( + + ); + + const badge = screen.getByTestId('hashed-badge'); + expect(badge).to.exist; + }); + }); + + describe('IndexTypeTooltip Component', function () { + it('renders allowed props in tooltip', function () { + const extras = { + weights: 20, + default_language: 'de', + language_override: 'en', + wildcardProjection: { _id: true }, + columnstoreProjection: { name: false }, + }; + render(); + for (const key in extras) { + expect( + screen.getByText(`${key}: ${JSON.stringify(extras[key])}`), + `it renders ${key} prop in tooltip` + ).to.exist; + } + }); + + it('does not render disallowed props in tooltip', function () { + const extras = { + expireAfterSeconds: 200, + partialFilterExpression: { _id: true }, + }; + render(); + for (const key in extras) { + expect( + () => screen.getByText(`${key}: ${JSON.stringify(extras[key])}`), + `it does not render ${key} prop in tooltip` + ).to.throw; + } }); - expect(infoIcon).to.exist; - expect(infoIcon.closest('a')?.href).to.equal(getIndexHelpLink('TEXT')); }); - it('renders index type - with extra information', function () { - render( - - ); - - const badge = screen.getByTestId('hashed-badge'); - expect(badge).to.exist; - // todo: tooltip test + describe('canRenderTooltip function', function () { + it('renders tooltip', function () { + ['text', 'wildcard', 'columnstore'].forEach( + (x) => + expect( + canRenderTooltip(x as any), + `it renders tooltip when type is ${x}` + ).to.be.true + ); + }); + it('does not render tooltip', function () { + ['geo', 'hashed', 'clustered'].forEach( + (x) => + expect( + canRenderTooltip(x as any), + `it does not render tooltip when type is ${x}` + ).to.be.false + ); + }); }); }); diff --git a/packages/compass-indexes/src/components/indexes-table/type-field.tsx b/packages/compass-indexes/src/components/indexes-table/type-field.tsx index 6a3d9714c4a..30266f1fb6c 100644 --- a/packages/compass-indexes/src/components/indexes-table/type-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/type-field.tsx @@ -5,7 +5,7 @@ import { Tooltip, Body } from '@mongodb-js/compass-components'; import type { IndexModel } from './indexes-table'; import BadgeWithIconLink from './badge-with-icon-link'; -const canRenderTooltip = (type: IndexModel['type']) => { +export const canRenderTooltip = (type: IndexModel['type']) => { return ['text', 'wildcard', 'columnstore'].indexOf(type) !== -1; }; @@ -14,7 +14,7 @@ type TypeFieldProps = { extra: IndexModel['extra']; }; -const IndexTypeTooltip: React.FunctionComponent<{ +export const IndexTypeTooltip: React.FunctionComponent<{ extra: IndexModel['extra']; }> = ({ extra }) => { const allowedProps = [ diff --git a/packages/compass-indexes/src/components/indexes-table/usage-field.spec.tsx b/packages/compass-indexes/src/components/indexes-table/usage-field.spec.tsx index 8931ad8ff06..76a89f3924f 100644 --- a/packages/compass-indexes/src/components/indexes-table/usage-field.spec.tsx +++ b/packages/compass-indexes/src/components/indexes-table/usage-field.spec.tsx @@ -2,33 +2,45 @@ import React from 'react'; import { cleanup, render, screen } from '@testing-library/react'; import { expect } from 'chai'; -import UsageField from './usage-field'; +import UsageField, { getUsageTooltip } from './usage-field'; -describe('UsageField Component', function () { +describe('UsageField', function () { before(cleanup); afterEach(cleanup); - it('renders usage', function () { - const since = new Date(); - render(); - const renderedText = `20 (since ${since.toDateString()})`; - expect(screen.getByText(renderedText)).to.exist; - // todo: tooltip tests - }); + describe('UsageField Component', function () { + it('renders usage', function () { + const since = new Date(); + render(); + + const renderedText = `20 (since ${since.toDateString()})`; + expect(screen.getByText(renderedText)).to.exist; + }); + + it('renders zero when usage is not defined', function () { + const since = new Date(); + render(); - it('renders zero when usage is not defined', function () { - const since = new Date(); - render(); + const renderedText = `0 (since ${since.toDateString()})`; + expect(screen.getByText(renderedText)).to.exist; + }); - const renderedText = `0 (since ${since.toDateString()})`; - expect(screen.getByText(renderedText)).to.exist; - // todo: tooltip tests + it('renders N/A when since is not defined', function () { + render(); + const renderedText = '30 (N/A)'; + expect(screen.getByText(renderedText)).to.exist; + }); }); - it('renders N/A when since is not defined', function () { - render(); - const renderedText = '30 (N/A)'; - expect(screen.getByText(renderedText)).to.exist; - // todo: tooltip tests + describe('getUsageTooltip', function () { + it('returns correct tooltip', function () { + expect(getUsageTooltip()).to.equal( + 'Either the server does not support the $indexStats command' + + 'or the user is not authorized to execute it.' + ); + expect(getUsageTooltip(30)).to.equal( + '30 index hits since index creation or last server restart' + ); + }); }); }); diff --git a/packages/compass-indexes/src/components/indexes-table/usage-field.tsx b/packages/compass-indexes/src/components/indexes-table/usage-field.tsx index 308b30c1b91..86d1253135b 100644 --- a/packages/compass-indexes/src/components/indexes-table/usage-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/usage-field.tsx @@ -5,6 +5,12 @@ const NO_USAGE_STATS = 'Either the server does not support the $indexStats command' + 'or the user is not authorized to execute it.'; +export const getUsageTooltip = (usage?: number): string => { + return !usage + ? NO_USAGE_STATS + : `${usage} index hits since index creation or last server restart`; +}; + type UsageFieldProps = { usage?: number; since?: Date; @@ -27,11 +33,7 @@ const UsageField: React.FunctionComponent = ({ )} > - - {!usage - ? NO_USAGE_STATS - : `${usage} index hits since index creation or last server restart`} - + {getUsageTooltip(usage)} ); }; From 9345d123ef032561da2a5feccf0b83c7ebed3d68 Mon Sep 17 00:00:00 2001 From: Basit Date: Thu, 18 Aug 2022 15:33:33 +0200 Subject: [PATCH 16/23] checks --- .../src/components/indexes-table/property-field.spec.tsx | 2 +- .../src/components/indexes-table/type-field.spec.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx b/packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx index a9cf3f0cc72..6eb9b4c7481 100644 --- a/packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx +++ b/packages/compass-indexes/src/components/indexes-table/property-field.spec.tsx @@ -80,7 +80,7 @@ describe('PropertyField', function () { it('returns null for unsupported properties', function () { ['unique', 'sparse', 'collation'].forEach( - (prop) => expect(getPropertyTooltip(prop, {})).to.be.null + (prop) => expect(getPropertyTooltip(prop as any, {})).to.be.null ); }); }); diff --git a/packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx b/packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx index 645c78935d0..53d4267bf77 100644 --- a/packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx +++ b/packages/compass-indexes/src/components/indexes-table/type-field.spec.tsx @@ -40,7 +40,7 @@ describe('TypeField', function () { describe('IndexTypeTooltip Component', function () { it('renders allowed props in tooltip', function () { - const extras = { + const extras: any = { weights: 20, default_language: 'de', language_override: 'en', @@ -57,7 +57,7 @@ describe('TypeField', function () { }); it('does not render disallowed props in tooltip', function () { - const extras = { + const extras: any = { expireAfterSeconds: 200, partialFilterExpression: { _id: true }, }; From 600c3e09a81c76d5e027e2c5c0129b1aeb373479 Mon Sep 17 00:00:00 2001 From: Basit Date: Mon, 22 Aug 2022 09:48:15 +0200 Subject: [PATCH 17/23] review changes --- .../indexes-table/badge-with-icon-link.tsx | 6 +- .../indexes-table/indexes-table.tsx | 15 +++- .../indexes-table/property-field.tsx | 2 - .../components/indexes-table/type-field.tsx | 1 - .../indexes-toolbar/indexes-toolbar.tsx | 71 +++++++++++-------- 5 files changed, 57 insertions(+), 38 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx b/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx index c30c6c81a10..c0b63d2aea2 100644 --- a/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx +++ b/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx @@ -7,6 +7,9 @@ import { Link, uiColors, spacing, + cx, + focusRingStyles, + focusRingVisibleStyles, } from '@mongodb-js/compass-components'; const badgeStyles = css({ @@ -20,6 +23,7 @@ const linkStyles = css({ // LG uses backgroundImage instead of textDecoration backgroundImage: 'none !important', }, + '&:focus': focusRingVisibleStyles, }); type BadgeWithIconLinkProps = { @@ -34,7 +38,7 @@ const BadgeWithIconLink: React.FunctionComponent = ({ return ( {text} diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx index 14068c37167..27fcda46245 100644 --- a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx @@ -20,13 +20,21 @@ import DropField from './drop-field'; const rowStyles = css({ ':hover': { '.delete-cell': { - visibility: 'visible', + opacity: 1, }, }, }); // When row is not hovered, we hide the delete button const deletFieldStyles = css({ - visibility: 'hidden', + opacity: 0, +}); + +const tableHeaderStyles = css({ + borderWidth: 0, + borderBottomWidth: 3, + '> div': { + justifyContent: 'space-between', + }, }); const cellStyles = css({ @@ -80,6 +88,7 @@ export const IndexesTable: React.FunctionComponent = ({ data-testid={`index-header-${name}`} label={name} key={name} + className={tableHeaderStyles} handleSort={(direction) => { onSortTable(name, direction); }} @@ -88,7 +97,7 @@ export const IndexesTable: React.FunctionComponent = ({ }); // The delete column if (canDeleteIndex) { - _columns.push(); + _columns.push(); } return _columns; }, [canDeleteIndex, onSortTable]); diff --git a/packages/compass-indexes/src/components/indexes-table/property-field.tsx b/packages/compass-indexes/src/components/indexes-table/property-field.tsx index 45e9cd17b3e..49bf53dc9af 100644 --- a/packages/compass-indexes/src/components/indexes-table/property-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/property-field.tsx @@ -67,7 +67,6 @@ const PropertyField: React.FunctionComponent = ({ @@ -76,7 +75,6 @@ const PropertyField: React.FunctionComponent = ({ {cardinality === 'compound' && ( )} diff --git a/packages/compass-indexes/src/components/indexes-table/type-field.tsx b/packages/compass-indexes/src/components/indexes-table/type-field.tsx index 30266f1fb6c..d0a6381bc30 100644 --- a/packages/compass-indexes/src/components/indexes-table/type-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/type-field.tsx @@ -37,7 +37,6 @@ const TypeField: React.FunctionComponent = ({ type, extra, }) => { - // todo: align index types across const link = getIndexHelpLink(type.toUpperCase() as any); return ( = ({ return ( - {showCreateIndexButton ? ( - ( -
- - {children} -
- )} - > - {writeStateDescription} -
- ) : ( -
- )} + + {children} +
+ )} + > + {writeStateDescription} +
+ )} +
{isReadonlyView ? ( Date: Mon, 22 Aug 2022 10:52:00 +0200 Subject: [PATCH 18/23] fix focus on icon --- .../indexes-table/badge-with-icon-link.tsx | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx b/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx index c0b63d2aea2..7a59e8674a0 100644 --- a/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx +++ b/packages/compass-indexes/src/components/indexes-table/badge-with-icon-link.tsx @@ -7,7 +7,6 @@ import { Link, uiColors, spacing, - cx, focusRingStyles, focusRingVisibleStyles, } from '@mongodb-js/compass-components'; @@ -16,15 +15,18 @@ const badgeStyles = css({ gap: spacing[2], }); -const linkStyles = css({ - lineHeight: 0, - color: uiColors.white, - span: { - // LG uses backgroundImage instead of textDecoration - backgroundImage: 'none !important', +const linkStyles = css( + { + lineHeight: 0, + color: uiColors.white, + span: { + // LG uses backgroundImage instead of textDecoration + backgroundImage: 'none !important', + }, + '&:focus': focusRingVisibleStyles, }, - '&:focus': focusRingVisibleStyles, -}); + focusRingStyles +); type BadgeWithIconLinkProps = { text: string; @@ -38,7 +40,7 @@ const BadgeWithIconLink: React.FunctionComponent = ({ return ( {text} From 478f811b059a931e650d2dc5b08842ee551a021a Mon Sep 17 00:00:00 2001 From: Basit Date: Mon, 22 Aug 2022 10:52:54 +0200 Subject: [PATCH 19/23] dark mode --- .../components/indexes-table/drop-field.tsx | 3 ++ .../indexes-table/indexes-table.tsx | 29 ++++++++++++++++--- .../components/indexes-table/name-field.tsx | 13 +++++++-- .../indexes-table/property-field.tsx | 8 ++++- .../components/indexes-table/size-field.tsx | 3 ++ .../components/indexes-table/type-field.tsx | 3 ++ .../components/indexes-table/usage-field.tsx | 3 ++ .../src/components/indexes/indexes.tsx | 8 +++-- 8 files changed, 61 insertions(+), 9 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes-table/drop-field.tsx b/packages/compass-indexes/src/components/indexes-table/drop-field.tsx index f6ee3a42d00..45104964d8e 100644 --- a/packages/compass-indexes/src/components/indexes-table/drop-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/drop-field.tsx @@ -2,16 +2,19 @@ import React from 'react'; import { IconButton, Icon } from '@mongodb-js/compass-components'; type DropFieldProps = { + darkMode?: boolean; name: string; onDelete: () => void; }; const DropField: React.FunctionComponent = ({ + darkMode, name, onDelete, }) => { return ( void; @@ -70,6 +71,7 @@ type IndexesTableProps = { }; export const IndexesTable: React.FunctionComponent = ({ + darkMode, indexes, canDeleteIndex, onSortTable, @@ -104,6 +106,7 @@ export const IndexesTable: React.FunctionComponent = ({ return (
= ({ >
- +
- + - + - + = ({
onDeleteIndex(index.name)} /> diff --git a/packages/compass-indexes/src/components/indexes-table/name-field.tsx b/packages/compass-indexes/src/components/indexes-table/name-field.tsx index 271bb5556e5..3c466779147 100644 --- a/packages/compass-indexes/src/components/indexes-table/name-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/name-field.tsx @@ -25,13 +25,22 @@ const badgeStyles = css({ }); type NameFieldProps = { + darkMode?: boolean; name: string; keys: ReturnType; }; -const NameField: React.FunctionComponent = ({ name, keys }) => { +const NameField: React.FunctionComponent = ({ + darkMode, + name, + keys, +}) => { return ( - +
    {keys.map(({ field, value }) => (
  • diff --git a/packages/compass-indexes/src/components/indexes-table/property-field.tsx b/packages/compass-indexes/src/components/indexes-table/property-field.tsx index 49bf53dc9af..d4faa6ace1a 100644 --- a/packages/compass-indexes/src/components/indexes-table/property-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/property-field.tsx @@ -30,12 +30,14 @@ export const getPropertyTooltip = ( }; const PropertyBadgeWithTooltip: React.FunctionComponent<{ + darkMode?: boolean; text: string; link: string; tooltip?: string | null; -}> = ({ text, link, tooltip }) => { +}> = ({ darkMode, text, link, tooltip }) => { return ( ( @@ -50,12 +52,14 @@ const PropertyBadgeWithTooltip: React.FunctionComponent<{ }; type PropertyFieldProps = { + darkMode?: boolean; extra: IndexModel['extra']; properties: IndexModel['properties']; cardinality: IndexModel['cardinality']; }; const PropertyField: React.FunctionComponent = ({ + darkMode, extra, properties, cardinality, @@ -65,6 +69,7 @@ const PropertyField: React.FunctionComponent = ({ {properties.map((property) => { return ( = ({ })} {cardinality === 'compound' && ( diff --git a/packages/compass-indexes/src/components/indexes-table/size-field.tsx b/packages/compass-indexes/src/components/indexes-table/size-field.tsx index ab9d39984b1..5d49f053dca 100644 --- a/packages/compass-indexes/src/components/indexes-table/size-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/size-field.tsx @@ -3,6 +3,7 @@ import React from 'react'; import { Body, Tooltip } from '@mongodb-js/compass-components'; type SizeFieldProps = { + darkMode?: boolean; size: number; relativeSize: number; }; @@ -17,11 +18,13 @@ export const getSizeTooltip = (relativeSize: number): string => { }; const SizeField: React.FunctionComponent = ({ + darkMode, relativeSize, size, }) => { return ( ( {children} diff --git a/packages/compass-indexes/src/components/indexes-table/type-field.tsx b/packages/compass-indexes/src/components/indexes-table/type-field.tsx index d0a6381bc30..afd63df62ed 100644 --- a/packages/compass-indexes/src/components/indexes-table/type-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/type-field.tsx @@ -10,6 +10,7 @@ export const canRenderTooltip = (type: IndexModel['type']) => { }; type TypeFieldProps = { + darkMode?: boolean; type: IndexModel['type']; extra: IndexModel['extra']; }; @@ -34,12 +35,14 @@ export const IndexTypeTooltip: React.FunctionComponent<{ }; const TypeField: React.FunctionComponent = ({ + darkMode, type, extra, }) => { const link = getIndexHelpLink(type.toUpperCase() as any); return ( ( diff --git a/packages/compass-indexes/src/components/indexes-table/usage-field.tsx b/packages/compass-indexes/src/components/indexes-table/usage-field.tsx index 86d1253135b..6be0d1cb941 100644 --- a/packages/compass-indexes/src/components/indexes-table/usage-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/usage-field.tsx @@ -12,17 +12,20 @@ export const getUsageTooltip = (usage?: number): string => { }; type UsageFieldProps = { + darkMode?: boolean; usage?: number; since?: Date; }; const nbsp = '\u00a0'; const UsageField: React.FunctionComponent = ({ + darkMode, usage, since, }) => { return ( ( {children} diff --git a/packages/compass-indexes/src/components/indexes/indexes.tsx b/packages/compass-indexes/src/components/indexes/indexes.tsx index 56c2e88c653..24dd0ff8582 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.tsx +++ b/packages/compass-indexes/src/components/indexes/indexes.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { css, Card, spacing } from '@mongodb-js/compass-components'; +import { css, Card, spacing, withTheme } from '@mongodb-js/compass-components'; import { connect } from 'react-redux'; import type AppRegistry from 'hadron-app-registry'; @@ -30,6 +30,7 @@ const indexTableStyles = css({ }); type IndexesProps = { + darkMode?: boolean; indexes: IndexModel[]; isWritable: boolean; isReadonly: boolean; @@ -40,7 +41,8 @@ type IndexesProps = { onSortTable: (name: string, direction: 'asc' | 'desc') => void; }; -export const Indexes: React.FunctionComponent = ({ +const UnthemedIndexes: React.FunctionComponent = ({ + darkMode, indexes, isWritable, isReadonly, @@ -68,6 +70,7 @@ export const Indexes: React.FunctionComponent = ({ {!isReadonlyView && !error && (
    Date: Mon, 22 Aug 2022 13:56:48 +0200 Subject: [PATCH 20/23] focus delete button on tab --- .../src/components/indexes-table/indexes-table.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx index 70f3773ce4d..8896921d1ae 100644 --- a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx @@ -25,8 +25,13 @@ const rowStyles = css({ }, }); // When row is not hovered, we hide the delete button -const deletFieldStyles = css({ - opacity: 0, +const deleteFieldStyles = css({ + button: { + opacity: 0, + '&:focus': { + opacity: 1, + }, + }, }); const tableHeaderStyles = css({ @@ -159,7 +164,7 @@ export const IndexesTable: React.FunctionComponent = ({ {/* Delete column is conditional */} {index.name !== '_id_' && canDeleteIndex && ( -
    +
    Date: Mon, 22 Aug 2022 14:42:05 +0200 Subject: [PATCH 21/23] fix tests --- packages/compass-e2e-tests/helpers/selectors.ts | 13 +++---------- .../tests/collection-indexes-tab.test.ts | 7 +++++-- .../src/components/indexes-table/indexes-table.tsx | 4 +++- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/packages/compass-e2e-tests/helpers/selectors.ts b/packages/compass-e2e-tests/helpers/selectors.ts index ed73e64f832..09d0c1e2cd3 100644 --- a/packages/compass-e2e-tests/helpers/selectors.ts +++ b/packages/compass-e2e-tests/helpers/selectors.ts @@ -777,11 +777,11 @@ export const IndexComponent = (name: string): string => { export const IndexFieldName = '[data-testid="index-name-field"]'; export const IndexFieldType = '[data-testid="index-type-field"]'; export const IndexToggleOptions = - '[data-test-id="create-index-modal-toggle-options"]'; + '[data-testid="create-index-modal-toggle-options"]'; export const IndexToggleIsWildcard = - '[data-test-id="wildcard-projection"] input[type="checkbox"]'; + '[data-testid="create-index-modal-use-wildcard-checkbox-fieldset"] #create-index-modal-use-wildcard-checkbox-label'; export const IndexWildcardProjectionEditor = - '[data-test-id="create-index-modal-options-param-wrapper-editor"] .ace_editor'; + '[data-testid="create-index-modal-use-wildcard-checkbox-fieldset"] .ace_editor'; export const CreateIndexButton = '[data-testid="open-create-index-modal-button"]'; @@ -799,13 +799,6 @@ export const CreateIndexModalFieldTypeSelectMenu = (idx: number): string => { return `[data-testid="create-index-fields-type-${idx}"] #create-index-fields-type-select-${idx}-menu`; }; -export const IndexToggleOptions = - '[data-testid="create-index-modal-toggle-options"]'; -export const IndexToggleIsWildcard = - '[data-testid="create-index-modal-use-wildcard-checkbox-fieldset"] #create-index-modal-use-wildcard-checkbox-label'; -export const IndexWildcardProjectionEditor = - '[data-testid="create-index-modal-use-wildcard-checkbox-fieldset"] .ace_editor'; - export const CreateIndexErrorMessage = `${CreateIndexModal} [role="alert"]`; export const CreateIndexConfirmButton = `${CreateIndexModal} [role=dialog] > div:nth-child(2) button:first-child`; export const CreateIndexCancelButton = `${CreateIndexModal} [role=dialog] > div:nth-child(2) button:last-child`; diff --git a/packages/compass-e2e-tests/tests/collection-indexes-tab.test.ts b/packages/compass-e2e-tests/tests/collection-indexes-tab.test.ts index d911ae2506c..799f225c552 100644 --- a/packages/compass-e2e-tests/tests/collection-indexes-tab.test.ts +++ b/packages/compass-e2e-tests/tests/collection-indexes-tab.test.ts @@ -83,11 +83,14 @@ describe('Collection indexes tab', function () { await createModal.waitForDisplayed({ reverse: true }); - const indexComponent = await browser.$(Selectors.IndexComponent('i_text')); + const indexComponentSelector = Selectors.IndexComponent('i_text'); + + const indexComponent = await browser.$(indexComponentSelector); await indexComponent.waitForDisplayed(); + await browser.hover(indexComponentSelector); await browser.clickVisible( - `${Selectors.IndexComponent('i_text')} ${Selectors.DropIndexButton}` + `${indexComponentSelector} ${Selectors.DropIndexButton}` ); const dropModal = await browser.$(Selectors.DropIndexModal); diff --git a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx index 8896921d1ae..0e6cd1a94a0 100644 --- a/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx +++ b/packages/compass-indexes/src/components/indexes-table/indexes-table.tsx @@ -20,7 +20,9 @@ import DropField from './drop-field'; const rowStyles = css({ ':hover': { '.delete-cell': { - opacity: 1, + button: { + opacity: 1, + } }, }, }); From 6df0303d971cc52425d5cd8dbc6871451996c1d9 Mon Sep 17 00:00:00 2001 From: Basit Date: Mon, 22 Aug 2022 16:32:20 +0200 Subject: [PATCH 22/23] clean up --- .../components/indexes-table/drop-field.tsx | 3 -- .../indexes-table/indexes-table.tsx | 30 ++++--------------- .../components/indexes-table/name-field.tsx | 13 ++------ .../indexes-table/property-field.tsx | 8 +---- .../components/indexes-table/size-field.tsx | 3 -- .../components/indexes-table/type-field.tsx | 3 -- .../components/indexes-table/usage-field.tsx | 3 -- .../indexes-toolbar/indexes-toolbar.tsx | 3 +- .../src/components/indexes/indexes.tsx | 8 ++--- 9 files changed, 11 insertions(+), 63 deletions(-) diff --git a/packages/compass-indexes/src/components/indexes-table/drop-field.tsx b/packages/compass-indexes/src/components/indexes-table/drop-field.tsx index 45104964d8e..f6ee3a42d00 100644 --- a/packages/compass-indexes/src/components/indexes-table/drop-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/drop-field.tsx @@ -2,19 +2,16 @@ import React from 'react'; import { IconButton, Icon } from '@mongodb-js/compass-components'; type DropFieldProps = { - darkMode?: boolean; name: string; onDelete: () => void; }; const DropField: React.FunctionComponent = ({ - darkMode, name, onDelete, }) => { return ( = ({ - darkMode, indexes, canDeleteIndex, onSortTable, @@ -113,7 +112,6 @@ export const IndexesTable: React.FunctionComponent = ({ return (
= ({ >
- +
- + - + - + = ({
onDeleteIndex(index.name)} /> diff --git a/packages/compass-indexes/src/components/indexes-table/name-field.tsx b/packages/compass-indexes/src/components/indexes-table/name-field.tsx index 3c466779147..271bb5556e5 100644 --- a/packages/compass-indexes/src/components/indexes-table/name-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/name-field.tsx @@ -25,22 +25,13 @@ const badgeStyles = css({ }); type NameFieldProps = { - darkMode?: boolean; name: string; keys: ReturnType; }; -const NameField: React.FunctionComponent = ({ - darkMode, - name, - keys, -}) => { +const NameField: React.FunctionComponent = ({ name, keys }) => { return ( - +
    {keys.map(({ field, value }) => (
  • diff --git a/packages/compass-indexes/src/components/indexes-table/property-field.tsx b/packages/compass-indexes/src/components/indexes-table/property-field.tsx index d4faa6ace1a..49bf53dc9af 100644 --- a/packages/compass-indexes/src/components/indexes-table/property-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/property-field.tsx @@ -30,14 +30,12 @@ export const getPropertyTooltip = ( }; const PropertyBadgeWithTooltip: React.FunctionComponent<{ - darkMode?: boolean; text: string; link: string; tooltip?: string | null; -}> = ({ darkMode, text, link, tooltip }) => { +}> = ({ text, link, tooltip }) => { return ( ( @@ -52,14 +50,12 @@ const PropertyBadgeWithTooltip: React.FunctionComponent<{ }; type PropertyFieldProps = { - darkMode?: boolean; extra: IndexModel['extra']; properties: IndexModel['properties']; cardinality: IndexModel['cardinality']; }; const PropertyField: React.FunctionComponent = ({ - darkMode, extra, properties, cardinality, @@ -69,7 +65,6 @@ const PropertyField: React.FunctionComponent = ({ {properties.map((property) => { return ( = ({ })} {cardinality === 'compound' && ( diff --git a/packages/compass-indexes/src/components/indexes-table/size-field.tsx b/packages/compass-indexes/src/components/indexes-table/size-field.tsx index 5d49f053dca..ab9d39984b1 100644 --- a/packages/compass-indexes/src/components/indexes-table/size-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/size-field.tsx @@ -3,7 +3,6 @@ import React from 'react'; import { Body, Tooltip } from '@mongodb-js/compass-components'; type SizeFieldProps = { - darkMode?: boolean; size: number; relativeSize: number; }; @@ -18,13 +17,11 @@ export const getSizeTooltip = (relativeSize: number): string => { }; const SizeField: React.FunctionComponent = ({ - darkMode, relativeSize, size, }) => { return ( ( {children} diff --git a/packages/compass-indexes/src/components/indexes-table/type-field.tsx b/packages/compass-indexes/src/components/indexes-table/type-field.tsx index afd63df62ed..d0a6381bc30 100644 --- a/packages/compass-indexes/src/components/indexes-table/type-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/type-field.tsx @@ -10,7 +10,6 @@ export const canRenderTooltip = (type: IndexModel['type']) => { }; type TypeFieldProps = { - darkMode?: boolean; type: IndexModel['type']; extra: IndexModel['extra']; }; @@ -35,14 +34,12 @@ export const IndexTypeTooltip: React.FunctionComponent<{ }; const TypeField: React.FunctionComponent = ({ - darkMode, type, extra, }) => { const link = getIndexHelpLink(type.toUpperCase() as any); return ( ( diff --git a/packages/compass-indexes/src/components/indexes-table/usage-field.tsx b/packages/compass-indexes/src/components/indexes-table/usage-field.tsx index 6be0d1cb941..86d1253135b 100644 --- a/packages/compass-indexes/src/components/indexes-table/usage-field.tsx +++ b/packages/compass-indexes/src/components/indexes-table/usage-field.tsx @@ -12,20 +12,17 @@ export const getUsageTooltip = (usage?: number): string => { }; type UsageFieldProps = { - darkMode?: boolean; usage?: number; since?: Date; }; const nbsp = '\u00a0'; const UsageField: React.FunctionComponent = ({ - darkMode, usage, since, }) => { return ( ( {children} diff --git a/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx b/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx index cbfc3b202c9..d7ad4cf0144 100644 --- a/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx +++ b/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx @@ -8,13 +8,12 @@ import { css, mergeProps, spacing, - uiColors, } from '@mongodb-js/compass-components'; import type AppRegistry from 'hadron-app-registry'; const toolbarStyles = css({ padding: spacing[3], - backgroundColor: uiColors.white, + backgroundColor: 'transparent', }); const toolbarButtonsContainer = css({ diff --git a/packages/compass-indexes/src/components/indexes/indexes.tsx b/packages/compass-indexes/src/components/indexes/indexes.tsx index 24dd0ff8582..56c2e88c653 100644 --- a/packages/compass-indexes/src/components/indexes/indexes.tsx +++ b/packages/compass-indexes/src/components/indexes/indexes.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { css, Card, spacing, withTheme } from '@mongodb-js/compass-components'; +import { css, Card, spacing } from '@mongodb-js/compass-components'; import { connect } from 'react-redux'; import type AppRegistry from 'hadron-app-registry'; @@ -30,7 +30,6 @@ const indexTableStyles = css({ }); type IndexesProps = { - darkMode?: boolean; indexes: IndexModel[]; isWritable: boolean; isReadonly: boolean; @@ -41,8 +40,7 @@ type IndexesProps = { onSortTable: (name: string, direction: 'asc' | 'desc') => void; }; -const UnthemedIndexes: React.FunctionComponent = ({ - darkMode, +export const Indexes: React.FunctionComponent = ({ indexes, isWritable, isReadonly, @@ -70,7 +68,6 @@ const UnthemedIndexes: React.FunctionComponent = ({ {!isReadonlyView && !error && (
    Date: Mon, 22 Aug 2022 21:07:26 +0200 Subject: [PATCH 23/23] use less padding in toolbar Co-authored-by: Rhys --- .../src/components/indexes-toolbar/indexes-toolbar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx b/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx index d7ad4cf0144..3c10a168f73 100644 --- a/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx +++ b/packages/compass-indexes/src/components/indexes-toolbar/indexes-toolbar.tsx @@ -12,7 +12,7 @@ import { import type AppRegistry from 'hadron-app-registry'; const toolbarStyles = css({ - padding: spacing[3], + padding: spacing[2], backgroundColor: 'transparent', });