fix(bucket-list): wrapped DWP in featureFlag and sorted bucket list (#15769)

* fix(bucket-list): wrapped DWP in featureFlag and sorted bucket list

* chore(changelog): updated the changelog to reflect PR changes

* fix(e2e): skipping tests until featureflag removed from DWP

* chore(tests): refactoring to use selector and add tests

* chore(refactor): created selector for ordering bucketlist and added tests

* fix(bucketsort): updated func and var names to accurately reflect intent

* fix(bucket/selector): renamed func for accuracy
pull/15790/head
Ariel Salem 2019-11-06 15:29:01 -08:00 committed by GitHub
parent bb6aa1df3b
commit afb4667b15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 288 additions and 22 deletions

View File

@ -4,7 +4,6 @@
1. [15777](https://github.com/influxdata/influxdb/pull/15777): Fix long startup when running 'influx help'
1. [15731](https://github.com/influxdata/influxdb/pull/15731): Ensure array cursor iterator stats accumulate all cursor stats
1. [15766](https://github.com/influxdata/influxdb/pull/15766): Reset delete with predicate state after submission
## v2.0.0-alpha.19 [2019-10-30]

View File

@ -109,7 +109,54 @@ describe('Buckets', () => {
})
})
describe('delete with predicate', () => {
// skipping until feature flag feature is removed for deleteWithPredicate
describe.skip('should alphabetize buckets in dropdown', () => {
beforeEach(() => {
cy.get<Organization>('@org').then(({id, name}) => {
cy.createBucket(id, name, 'Funky Town').then(() => {
cy.createBucket(id, name, 'ABC').then(() => {
cy.createBucket(id, name, 'Jimmy Mack')
})
})
})
})
it('alphabetizes buckets', () => {
cy.getByTestID('bucket-delete-task')
.first()
.click()
.then(() => {
cy.getByTestID('dropdown--button')
.contains('ABC')
.click()
.then(() => {
// get the bucket list
cy.get('.cf-dropdown-item--children')
.should('have.length', 6)
.then(el => {
const results = []
// output in an array
el.text((index, currentContent) => {
results[index] = currentContent
})
const expectedOrder = [
'ABC',
'defbuck',
'Funky Town',
'Jimmy Mack',
'_tasks',
'_monitoring',
]
// check the order
expect(results).to.deep.equal(expectedOrder)
})
})
})
})
})
// skipping until feature flag feature is removed for deleteWithPredicate
describe.skip('delete with predicate', () => {
beforeEach(() => {
cy.getByTestID('bucket-delete-task').click()
cy.getByTestID('overlay--container').should('have.length', 1)

View File

@ -417,7 +417,8 @@ describe('DataExplorer', () => {
})
})
describe('delete with predicate', () => {
// skipping until feature flag feature is removed for deleteWithPredicate
describe.skip('delete with predicate', () => {
beforeEach(() => {
cy.getByTestID('delete-data-predicate').click()
cy.getByTestID('overlay--container').should('have.length', 1)

View File

@ -13,6 +13,7 @@ import {
} from '@influxdata/clockface'
import BucketContextMenu from 'src/buckets/components/BucketContextMenu'
import BucketAddDataButton from 'src/buckets/components/BucketAddDataButton'
import {FeatureFlag} from 'src/shared/utils/featureFlag'
// Constants
import {isSystemBucket} from 'src/buckets/constants/index'
@ -114,12 +115,14 @@ class BucketRow extends PureComponent<Props & WithRouterProps> {
size={ComponentSize.ExtraSmall}
onClick={this.handleRenameBucket}
/>
<Button
text="Delete Data By Filter"
testID="bucket-delete-task"
size={ComponentSize.ExtraSmall}
onClick={this.handleDeleteData}
/>
<FeatureFlag name="deleteWithPredicate">
<Button
text="Delete Data By Filter"
testID="bucket-delete-task"
size={ComponentSize.ExtraSmall}
onClick={this.handleDeleteData}
/>
</FeatureFlag>
</FlexBox>
)
}

View File

@ -0,0 +1,175 @@
// Funcs
import {isSystemBucket, getSortedBucketNames, SYSTEM} from './index'
// Types
import {Bucket} from 'src/types'
describe('Bucket Selector', () => {
it('should return true when a default bucket is passed', () => {
expect(isSystemBucket(SYSTEM)).toEqual(true)
})
it('should return false when no default bucket is passed', () => {
expect(isSystemBucket(`_${SYSTEM}`)).toEqual(false)
expect(isSystemBucket(`naming_${SYSTEM}`)).toEqual(false)
expect(isSystemBucket('SYSTEM')).toEqual(false)
})
it('should sort the bucket names alphabetically', () => {
const buckets: Bucket[] = [
{
id: '7902bd683453c00c',
orgID: 'e483753c9bdb47bf',
type: 'user',
name: 'alpha',
retentionRules: [],
createdAt: '2019-11-05T08:57:54.459819-08:00',
updatedAt: '2019-11-05T08:58:09.593805-08:00',
links: {
labels: '/api/v2/buckets/7902bd683453c00c/labels',
logs: '/api/v2/buckets/7902bd683453c00c/logs',
members: '/api/v2/buckets/7902bd683453c00c/members',
org: '/api/v2/orgs/e483753c9bdb47bf',
owners: '/api/v2/buckets/7902bd683453c00c/owners',
self: '/api/v2/buckets/7902bd683453c00c',
write: '/api/v2/write?org=e483753c9bdb47bf&bucket=7902bd683453c00c',
},
labels: [],
},
{
id: '7f44462ac794c7c1',
orgID: 'e483753c9bdb47bf',
type: 'user',
name: 'bucket1',
retentionRules: [],
createdAt: '2019-10-15T11:10:27.970567-07:00',
updatedAt: '2019-10-15T11:10:27.970567-07:00',
links: {
labels: '/api/v2/buckets/7f44462ac794c7c1/labels',
logs: '/api/v2/buckets/7f44462ac794c7c1/logs',
members: '/api/v2/buckets/7f44462ac794c7c1/members',
org: '/api/v2/orgs/e483753c9bdb47bf',
owners: '/api/v2/buckets/7f44462ac794c7c1/owners',
self: '/api/v2/buckets/7f44462ac794c7c1',
write: '/api/v2/write?org=e483753c9bdb47bf&bucket=7f44462ac794c7c1',
},
labels: [],
},
{
id: 'a8fee6b433c16f86',
orgID: 'e483753c9bdb47bf',
type: 'user',
name: 'zebra',
retentionRules: [],
createdAt: '2019-11-05T08:57:59.280485-08:00',
updatedAt: '2019-11-05T08:57:59.280486-08:00',
links: {
labels: '/api/v2/buckets/a8fee6b433c16f86/labels',
logs: '/api/v2/buckets/a8fee6b433c16f86/logs',
members: '/api/v2/buckets/a8fee6b433c16f86/members',
org: '/api/v2/orgs/e483753c9bdb47bf',
owners: '/api/v2/buckets/a8fee6b433c16f86/owners',
self: '/api/v2/buckets/a8fee6b433c16f86',
write: '/api/v2/write?org=e483753c9bdb47bf&bucket=a8fee6b433c16f86',
},
labels: [],
},
{
id: 'adbb0107da2d7d38',
orgID: 'e483753c9bdb47bf',
type: 'user',
name: 'buck2',
retentionRules: [],
createdAt: '2019-10-18T14:05:24.838291-07:00',
updatedAt: '2019-10-18T14:05:24.838292-07:00',
links: {
labels: '/api/v2/buckets/adbb0107da2d7d38/labels',
logs: '/api/v2/buckets/adbb0107da2d7d38/logs',
members: '/api/v2/buckets/adbb0107da2d7d38/members',
org: '/api/v2/orgs/e483753c9bdb47bf',
owners: '/api/v2/buckets/adbb0107da2d7d38/owners',
self: '/api/v2/buckets/adbb0107da2d7d38',
write: '/api/v2/write?org=e483753c9bdb47bf&bucket=adbb0107da2d7d38',
},
labels: [],
},
{
id: 'e2871ad8f92e752a',
orgID: 'e483753c9bdb47bf',
type: 'user',
name: 'disco inferno',
retentionRules: [],
createdAt: '2019-11-05T08:58:16.873502-08:00',
updatedAt: '2019-11-05T08:58:16.873502-08:00',
links: {
labels: '/api/v2/buckets/e2871ad8f92e752a/labels',
logs: '/api/v2/buckets/e2871ad8f92e752a/logs',
members: '/api/v2/buckets/e2871ad8f92e752a/members',
org: '/api/v2/orgs/e483753c9bdb47bf',
owners: '/api/v2/buckets/e2871ad8f92e752a/owners',
self: '/api/v2/buckets/e2871ad8f92e752a',
write: '/api/v2/write?org=e483753c9bdb47bf&bucket=e2871ad8f92e752a',
},
labels: [],
},
{
id: '000000000000000a',
type: 'system',
description: 'System bucket for task logs',
name: '_tasks',
retentionRules: [
{
type: 'expire',
everySeconds: 259200,
},
],
createdAt: '0001-01-01T00:00:00Z',
updatedAt: '0001-01-01T00:00:00Z',
links: {
labels: '/api/v2/buckets/000000000000000a/labels',
logs: '/api/v2/buckets/000000000000000a/logs',
members: '/api/v2/buckets/000000000000000a/members',
org: '/api/v2/orgs/',
owners: '/api/v2/buckets/000000000000000a/owners',
self: '/api/v2/buckets/000000000000000a',
write: '/api/v2/write?org=&bucket=000000000000000a',
},
labels: [],
},
{
id: '000000000000000b',
type: 'system',
description: 'System bucket for monitoring logs',
name: '_monitoring',
retentionRules: [
{
type: 'expire',
everySeconds: 604800,
},
],
createdAt: '0001-01-01T00:00:00Z',
updatedAt: '0001-01-01T00:00:00Z',
links: {
labels: '/api/v2/buckets/000000000000000b/labels',
logs: '/api/v2/buckets/000000000000000b/logs',
members: '/api/v2/buckets/000000000000000b/members',
org: '/api/v2/orgs/',
owners: '/api/v2/buckets/000000000000000b/owners',
self: '/api/v2/buckets/000000000000000b',
write: '/api/v2/write?org=&bucket=000000000000000b',
},
labels: [],
},
]
const results = getSortedBucketNames(buckets)
const expectedResult = [
'alpha',
'buck2',
'bucket1',
'disco inferno',
'zebra',
'_monitoring',
'_tasks',
]
expect(results).toEqual(expectedResult)
})
})

View File

@ -0,0 +1,32 @@
// Types
import {Bucket} from 'src/types'
export const SYSTEM = 'system'
export const isSystemBucket = (type: string): boolean => type === SYSTEM
export const getSortedBucketNames = (buckets: Bucket[]) =>
buckets
.sort((a, b) => {
const firstBucket = `${a.name}`.toLowerCase()
const secondBucket = `${b.name}`.toLowerCase()
if (firstBucket === secondBucket) {
return 0
}
if (isSystemBucket(a.type)) {
// ensures that the default system types are the last buckets
return 1
}
if (isSystemBucket(b.type)) {
// ensures that the default system types are the last buckets
return -1
}
if (firstBucket < secondBucket) {
return -1
}
if (firstBucket > secondBucket) {
return 1
}
return 0
})
.map(bucket => bucket.name)

View File

@ -4,6 +4,7 @@ import {withRouter, WithRouterProps} from 'react-router'
// Components
import {Button} from '@influxdata/clockface'
import {FeatureFlag} from 'src/shared/utils/featureFlag'
const DeleteDataButton: FunctionComponent<WithRouterProps> = ({
location: {pathname},
@ -12,12 +13,14 @@ const DeleteDataButton: FunctionComponent<WithRouterProps> = ({
const onClick = () => router.push(`${pathname}/delete-data`)
return (
<Button
testID="delete-data-predicate"
text="Delete Data"
onClick={onClick}
titleText="Filter and mark data for deletion"
/>
<FeatureFlag name="deleteWithPredicate">
<Button
testID="delete-data-predicate"
text="Delete Data"
onClick={onClick}
titleText="Filter and mark data for deletion"
/>
</FeatureFlag>
)
}

View File

@ -4,10 +4,13 @@ import {connect} from 'react-redux'
import {SelectDropdown} from '@influxdata/clockface'
// Types
import {AppState, Bucket} from 'src/types'
import {AppState} from 'src/types'
// Selectors
import {getSortedBucketNames} from 'src/buckets/selectors/index'
interface StateProps {
buckets: Bucket[]
bucketNames: string[]
}
interface OwnProps {
@ -18,11 +21,10 @@ interface OwnProps {
type Props = StateProps & OwnProps
const BucketsDropdown: FunctionComponent<Props> = ({
buckets,
bucketNames,
bucketName,
onSetBucketName,
}) => {
const bucketNames = buckets.map(bucket => bucket.name)
return (
<SelectDropdown
options={bucketNames}
@ -32,8 +34,12 @@ const BucketsDropdown: FunctionComponent<Props> = ({
)
}
const mstp = (state: AppState): StateProps => ({
buckets: state.buckets.list,
})
const mstp = (state: AppState): StateProps => {
// map names and sort via a selector
const buckets = getSortedBucketNames(state.buckets.list)
return {
bucketNames: buckets,
}
}
export default connect<StateProps, {}, OwnProps>(mstp)(BucketsDropdown)