Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 7 commits into from
Nov 6, 2019
1 change: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
### Bug Fixes

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]

Expand Down
49 changes: 48 additions & 1 deletion ui/cypress/e2e/buckets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion ui/cypress/e2e/explorer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
15 changes: 9 additions & 6 deletions ui/src/buckets/components/BucketCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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>
)
}
Expand Down
175 changes: 175 additions & 0 deletions ui/src/buckets/selectors/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// Funcs
import {isSystemBucket, sortBucketNames, SYSTEM} from './index'

// Types
import {Bucket} from 'src/types'

describe('Bucket Selector Tests', () => {
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 = sortBucketNames(buckets)
const expectedResult = [
'alpha',
'buck2',
'bucket1',
'disco inferno',
'zebra',
'_monitoring',
'_tasks',
]
expect(results).toEqual(expectedResult)
})
})
32 changes: 32 additions & 0 deletions ui/src/buckets/selectors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Types
import {Bucket} from 'src/types'

export const SYSTEM = 'system'

export const isSystemBucket = (type: string): boolean => type === SYSTEM

export const sortBucketNames = (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)
15 changes: 9 additions & 6 deletions ui/src/dataExplorer/components/DeleteDataButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -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>
)
}

Expand Down
20 changes: 13 additions & 7 deletions ui/src/shared/components/DeleteDataForm/BucketsDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {sortBucketNames} from 'src/buckets/selectors/index'

interface StateProps {
buckets: Bucket[]
buckets: string[]
}

interface OwnProps {
Expand All @@ -22,18 +25,21 @@ const BucketsDropdown: FunctionComponent<Props> = ({
bucketName,
onSetBucketName,
}) => {
const bucketNames = buckets.map(bucket => bucket.name)
return (
<SelectDropdown
options={bucketNames}
options={buckets}
selectedOption={bucketName}
onSelect={onSetBucketName}
/>
)
}

const mstp = (state: AppState): StateProps => ({
buckets: state.buckets.list,
})
const mstp = (state: AppState): StateProps => {
// map names and sort via a selector
const buckets = sortBucketNames(state.buckets.list)
return {
buckets,
}
}

export default connect<StateProps, {}, OwnProps>(mstp)(BucketsDropdown)