From 85fd010f2ba9c45f51f9ea751a271b4c70ae2c02 Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Thu, 16 Jun 2022 11:23:32 +0200 Subject: [PATCH 1/9] feat(ui): reuse DB selector between Users and Roles pages --- .../components/influxdb/MultiDBSelector.tsx | 52 +++++++++++++++++++ .../admin/containers/influxdb/RolesPage.tsx | 44 +++------------- .../admin/containers/influxdb/UsersPage.tsx | 43 +++------------ 3 files changed, 65 insertions(+), 74 deletions(-) create mode 100644 ui/src/admin/components/influxdb/MultiDBSelector.tsx diff --git a/ui/src/admin/components/influxdb/MultiDBSelector.tsx b/ui/src/admin/components/influxdb/MultiDBSelector.tsx new file mode 100644 index 000000000..aa72dca5e --- /dev/null +++ b/ui/src/admin/components/influxdb/MultiDBSelector.tsx @@ -0,0 +1,52 @@ +import React, {useCallback} from 'react' +import allOrParticularSelection from 'src/admin/util/allOrParticularSelection' +import {MultiSelectDropdown} from 'src/reusable_ui' +import {Database} from 'src/types/influxAdmin' + +interface Props { + databases: Database[] + selectedDBs: string[] + setSelectedDBs: (changeFn: (oldDBs: string[]) => string[]) => void +} +const MultiDBSelector = ({databases, selectedDBs, setSelectedDBs}: Props) => { + const changeSelectedDBs = useCallback( + (newDBs: string[]) => + setSelectedDBs((oldDBs: string[]) => { + return allOrParticularSelection(oldDBs, newDBs) + }), + [setSelectedDBs] + ) + + return ( +
+ + {databases.reduce( + (acc, db) => { + acc.push( + + {db.name} + + ) + return acc + }, + [ + + All Databases + , + , + ] + )} + +
+ ) +} + +export default MultiDBSelector diff --git a/ui/src/admin/containers/influxdb/RolesPage.tsx b/ui/src/admin/containers/influxdb/RolesPage.tsx index a45b0da0c..e09b6f068 100644 --- a/ui/src/admin/containers/influxdb/RolesPage.tsx +++ b/ui/src/admin/containers/influxdb/RolesPage.tsx @@ -21,14 +21,14 @@ import FancyScrollbar from 'src/shared/components/FancyScrollbar' import NoEntities from 'src/admin/components/influxdb/NoEntities' import RoleRow from 'src/admin/components/RoleRow' import {useCallback} from 'react' -import allOrParticularSelection from '../../util/allOrParticularSelection' import {computeEntitiesDBPermissions} from '../../util/computeEffectiveDBPermissions' import useDebounce from 'src/utils/useDebounce' import useChangeEffect from 'src/utils/useChangeEffect' -import {ComponentSize, MultiSelectDropdown, SlideToggle} from 'src/reusable_ui' +import {ComponentSize, SlideToggle} from 'src/reusable_ui' import CreateRoleDialog, { validateRoleName, } from 'src/admin/components/influxdb/CreateRoleDialog' +import MultiDBSelector from 'src/admin/components/influxdb/MultiDBSelector' const validateRole = ( role: Pick, @@ -88,13 +88,6 @@ const RolesPage = ({ } return selectedDBs }, [databases, selectedDBs]) - const changeSelectedDBs = useCallback( - (newDBs: string[]) => - setSelectedDBs((oldDBs: string[]) => { - return allOrParticularSelection(oldDBs, newDBs) - }), - [setSelectedDBs] - ) // effective permissions const visibleRoles = useMemo(() => roles.filter(x => !x.hidden), [roles]) @@ -159,34 +152,11 @@ const RolesPage = ({ /> -
- - {databases.reduce( - (acc, db) => { - acc.push( - - {db.name} - - ) - return acc - }, - [ - - All Databases - , - , - ] - )} - -
+
, @@ -96,13 +95,6 @@ const UsersPage = ({ } return selectedDBs }, [databases, selectedDBs]) - const changeSelectedDBs = useCallback( - (newDBs: string[]) => - setSelectedDBs((oldDBs: string[]) => { - return allOrParticularSelection(oldDBs, newDBs) - }), - [setSelectedDBs] - ) // effective permissions const visibleUsers = useMemo(() => users.filter(x => !x.hidden), [users]) @@ -169,34 +161,11 @@ const UsersPage = ({ />
-
- - {databases.reduce( - (acc, db) => { - acc.push( - - {db.name} - - ) - return acc - }, - [ - - All Databases - , - , - ] - )} - -
+ {isEnterprise && (
Date: Thu, 16 Jun 2022 13:11:24 +0200 Subject: [PATCH 2/9] feat(ui): remember selected databases in Roles/Users pages --- ui/src/admin/actions/influxdb.js | 7 +++ .../components/influxdb/MultiDBSelector.tsx | 29 ++++++----- .../admin/containers/influxdb/RolesPage.tsx | 16 +++--- .../admin/containers/influxdb/UsersPage.tsx | 16 +++--- ui/src/admin/reducers/influxdb.js | 13 ++++- ui/test/admin/reducers/influxdb.test.js | 51 +++++++++++++++++++ 6 files changed, 100 insertions(+), 32 deletions(-) diff --git a/ui/src/admin/actions/influxdb.js b/ui/src/admin/actions/influxdb.js index 902766659..071a73e23 100644 --- a/ui/src/admin/actions/influxdb.js +++ b/ui/src/admin/actions/influxdb.js @@ -473,3 +473,10 @@ export const updateUserPasswordAsync = (user, password) => async dispatch => { ) } } + +export const changeSelectedDBs = (selectedDBs /* : string[] */) => ({ + type: 'INFLUXDB_CHANGE_SELECTED_DBS', + payload: { + selectedDBs, + }, +}) diff --git a/ui/src/admin/components/influxdb/MultiDBSelector.tsx b/ui/src/admin/components/influxdb/MultiDBSelector.tsx index aa72dca5e..cb51342fd 100644 --- a/ui/src/admin/components/influxdb/MultiDBSelector.tsx +++ b/ui/src/admin/components/influxdb/MultiDBSelector.tsx @@ -1,26 +1,27 @@ -import React, {useCallback} from 'react' -import allOrParticularSelection from 'src/admin/util/allOrParticularSelection' +import React from 'react' +import {connect, ResolveThunks} from 'react-redux' +import {changeSelectedDBs} from 'src/admin/actions/influxdb' import {MultiSelectDropdown} from 'src/reusable_ui' import {Database} from 'src/types/influxAdmin' -interface Props { +interface ConnectedProps { databases: Database[] selectedDBs: string[] - setSelectedDBs: (changeFn: (oldDBs: string[]) => string[]) => void } +const mapStateToProps = ({adminInfluxDB: {databases, selectedDBs}}) => ({ + databases, + selectedDBs, +}) +const mapDispatchToProps = { + setSelectedDBs: changeSelectedDBs, +} +type ReduxDispatchProps = ResolveThunks +type Props = ConnectedProps & ReduxDispatchProps const MultiDBSelector = ({databases, selectedDBs, setSelectedDBs}: Props) => { - const changeSelectedDBs = useCallback( - (newDBs: string[]) => - setSelectedDBs((oldDBs: string[]) => { - return allOrParticularSelection(oldDBs, newDBs) - }), - [setSelectedDBs] - ) - return (
@@ -49,4 +50,4 @@ const MultiDBSelector = ({databases, selectedDBs, setSelectedDBs}: Props) => { ) } -export default MultiDBSelector +export default connect(mapStateToProps, mapDispatchToProps)(MultiDBSelector) diff --git a/ui/src/admin/containers/influxdb/RolesPage.tsx b/ui/src/admin/containers/influxdb/RolesPage.tsx index e09b6f068..7174d033e 100644 --- a/ui/src/admin/containers/influxdb/RolesPage.tsx +++ b/ui/src/admin/containers/influxdb/RolesPage.tsx @@ -41,10 +41,13 @@ const validateRole = ( return true } -const mapStateToProps = ({adminInfluxDB: {databases, users, roles}}) => ({ +const mapStateToProps = ({ + adminInfluxDB: {databases, users, roles, selectedDBs}, +}) => ({ databases, users, roles, + selectedDBs, }) const mapDispatchToProps = { @@ -60,6 +63,7 @@ interface ConnectedProps { databases: Database[] users: User[] roles: UserRole[] + selectedDBs: string[] } type ReduxDispatchProps = ResolveThunks @@ -71,6 +75,7 @@ const RolesPage = ({ users, roles, databases, + selectedDBs, router, filterRoles, createRole, @@ -80,8 +85,7 @@ const RolesPage = ({ () => `/sources/${source.id}/admin-influxdb/roles`, [source] ) - // filter databases - const [selectedDBs, setSelectedDBs] = useState(['*']) + // database columns const visibleDBNames = useMemo(() => { if (selectedDBs.includes('*')) { return databases.map(db => db.name) @@ -152,11 +156,7 @@ const RolesPage = ({ />
- +
({ +const mapStateToProps = ({ + adminInfluxDB: {databases, users, roles, selectedDBs}, +}) => ({ databases, users, roles, + selectedDBs, }) const mapDispatchToProps = { @@ -65,6 +68,7 @@ interface ConnectedProps { databases: Database[] users: User[] roles: UserRole[] + selectedDBs: string[] } type ReduxDispatchProps = ResolveThunks @@ -76,6 +80,7 @@ const UsersPage = ({ databases, users, roles, + selectedDBs, notify, createUser, filterUsers, @@ -87,8 +92,7 @@ const UsersPage = ({ ], [source] ) - // filter databases - const [selectedDBs, setSelectedDBs] = useState(['*']) + // database columns const visibleDBNames = useMemo(() => { if (selectedDBs.includes('*')) { return databases.map(db => db.name) @@ -161,11 +165,7 @@ const UsersPage = ({ />
- + {isEnterprise && (
x function sortQueries(queries, queriesSort) { return (querySorters[queriesSort] || identity)(queries) } - const initialState = { users: [], roles: [], @@ -46,6 +46,7 @@ const initialState = { queriesSort: '-time', queryIDToKill: null, databases: [], + selectedDBs: ['*'], } const adminInfluxDB = (state = initialState, action) => { @@ -63,7 +64,9 @@ const adminInfluxDB = (state = initialState, action) => { } case 'INFLUXDB_LOAD_DATABASES': { - return {...state, ...action.payload} + const databases = action.payload.databases + const selectedDBs = initialState.selectedDBs + return {...state, databases, selectedDBs} } case 'INFLUXDB_ADD_DATABASE': { @@ -359,6 +362,12 @@ const adminInfluxDB = (state = initialState, action) => { case 'INFLUXDB_SET_QUERY_TO_KILL': { return {...state, ...action.payload} } + case 'INFLUXDB_CHANGE_SELECTED_DBS': { + const newDBs = action.payload.selectedDBs + const oldDBs = state.selectedDBs || ['*'] + const selectedDBs = allOrParticularSelection(oldDBs, newDBs) + return {...state, selectedDBs} + } } return state diff --git a/ui/test/admin/reducers/influxdb.test.js b/ui/test/admin/reducers/influxdb.test.js index 41fb88ed6..1bd10fe35 100644 --- a/ui/test/admin/reducers/influxdb.test.js +++ b/ui/test/admin/reducers/influxdb.test.js @@ -19,6 +19,8 @@ import { removeDatabaseDeleteCode, loadQueries, setQueriesSort, + loadDatabases, + changeSelectedDBs, } from 'src/admin/actions/influxdb' import {NEW_DEFAULT_DATABASE, NEW_EMPTY_RP} from 'src/admin/constants' @@ -137,6 +139,17 @@ describe('Admin.InfluxDB.Reducers', () => { state = {databases: [db1, db2]} }) + it('can load databases', () => { + const {databases, selectedDBs} = reducer( + undefined, + loadDatabases([{name: 'db1'}]) + ) + expect({databases, selectedDBs}).toEqual({ + databases: [{name: 'db1'}], + selectedDBs: ['*'], + }) + }) + it('can add a database', () => { const actual = reducer(state, addDatabase()) const expected = [{...NEW_DEFAULT_DATABASE, isEditing: true}, db1, db2] @@ -488,4 +501,42 @@ describe('Admin.InfluxDB.Reducers', () => { expect(actual.queries[2].id).toEqual(1) }) }) + describe('filters', () => { + it('can change selected DBS', () => { + const testPairs = [ + { + prev: undefined, + change: ['db1'], + next: ['db1'], + }, + { + prev: [], + change: ['db1'], + next: ['db1'], + }, + { + prev: ['db1'], + change: ['db1', '*'], + next: ['*'], + }, + { + prev: ['*'], + change: ['db1', '*'], + next: ['db1'], + }, + { + prev: ['db1'], + change: [], + next: [], + }, + ] + testPairs.forEach(({prev, change, next}) => { + const {selectedDBs} = reducer( + {selectedDBs: prev}, + changeSelectedDBs(change) + ) + expect(selectedDBs).toEqual(next) + }) + }) + }) }) From 4665be92d5b0266a1dfe836496aefe6b6b1647c9 Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Thu, 16 Jun 2022 13:36:23 +0200 Subject: [PATCH 3/9] feat(ui/admin): remember showUsers toggle selection --- ui/src/admin/actions/influxdb.js | 4 ++++ ui/src/admin/containers/influxdb/RolesPage.tsx | 17 ++++++++--------- ui/src/admin/reducers/influxdb.js | 4 ++++ ui/test/admin/reducers/influxdb.test.js | 8 ++++++++ 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/ui/src/admin/actions/influxdb.js b/ui/src/admin/actions/influxdb.js index 071a73e23..ead069c74 100644 --- a/ui/src/admin/actions/influxdb.js +++ b/ui/src/admin/actions/influxdb.js @@ -480,3 +480,7 @@ export const changeSelectedDBs = (selectedDBs /* : string[] */) => ({ selectedDBs, }, }) + +export const changeShowUsers = () => ({ + type: 'INFLUXDB_CHANGE_SHOW_USERS', +}) diff --git a/ui/src/admin/containers/influxdb/RolesPage.tsx b/ui/src/admin/containers/influxdb/RolesPage.tsx index 7174d033e..9c277aeb2 100644 --- a/ui/src/admin/containers/influxdb/RolesPage.tsx +++ b/ui/src/admin/containers/influxdb/RolesPage.tsx @@ -6,6 +6,7 @@ import {Source, NotificationAction} from 'src/types' import {UserRole, User, Database} from 'src/types/influxAdmin' import {notify as notifyAction} from 'src/shared/actions/notifications' import { + changeShowUsers, createRoleAsync, filterRoles as filterRolesAction, } from 'src/admin/actions/influxdb' @@ -42,18 +43,20 @@ const validateRole = ( } const mapStateToProps = ({ - adminInfluxDB: {databases, users, roles, selectedDBs}, + adminInfluxDB: {databases, users, roles, selectedDBs, showUsers}, }) => ({ databases, users, roles, selectedDBs, + showUsers, }) const mapDispatchToProps = { filterRoles: filterRolesAction, createRole: createRoleAsync, notify: notifyAction, + toggleShowUsers: changeShowUsers, } interface OwnProps { @@ -64,6 +67,7 @@ interface ConnectedProps { users: User[] roles: UserRole[] selectedDBs: string[] + showUsers: boolean } type ReduxDispatchProps = ResolveThunks @@ -76,9 +80,11 @@ const RolesPage = ({ roles, databases, selectedDBs, + showUsers, router, filterRoles, createRole, + toggleShowUsers, notify, }: Props) => { const rolesPage = useMemo( @@ -110,13 +116,6 @@ const RolesPage = ({ filterRoles(debouncedFilterText) }, [debouncedFilterText]) - // hide users - const [showUsers, setShowUsers] = useState(true) - const changeHideUsers = useCallback(() => setShowUsers(!showUsers), [ - showUsers, - setShowUsers, - ]) - const [createVisible, setCreateVisible] = useState(false) const createNew = useCallback( async (role: {name: string}) => { @@ -160,7 +159,7 @@ const RolesPage = ({
diff --git a/ui/src/admin/reducers/influxdb.js b/ui/src/admin/reducers/influxdb.js index c025fa683..29d93d88e 100644 --- a/ui/src/admin/reducers/influxdb.js +++ b/ui/src/admin/reducers/influxdb.js @@ -47,6 +47,7 @@ const initialState = { queryIDToKill: null, databases: [], selectedDBs: ['*'], + showUsers: true, } const adminInfluxDB = (state = initialState, action) => { @@ -368,6 +369,9 @@ const adminInfluxDB = (state = initialState, action) => { const selectedDBs = allOrParticularSelection(oldDBs, newDBs) return {...state, selectedDBs} } + case 'INFLUXDB_CHANGE_SHOW_USERS': { + return {...state, showUsers: !state.showUsers} + } } return state diff --git a/ui/test/admin/reducers/influxdb.test.js b/ui/test/admin/reducers/influxdb.test.js index 1bd10fe35..4af5e6dd7 100644 --- a/ui/test/admin/reducers/influxdb.test.js +++ b/ui/test/admin/reducers/influxdb.test.js @@ -21,6 +21,7 @@ import { setQueriesSort, loadDatabases, changeSelectedDBs, + changeShowUsers, } from 'src/admin/actions/influxdb' import {NEW_DEFAULT_DATABASE, NEW_EMPTY_RP} from 'src/admin/constants' @@ -538,5 +539,12 @@ describe('Admin.InfluxDB.Reducers', () => { expect(selectedDBs).toEqual(next) }) }) + it('can change showUsers flag', () => { + const vals = [undefined, true, false] + vals.forEach(prev => { + const {showUsers} = reducer({showUsers: prev}, changeShowUsers()) + expect(showUsers).toEqual(!prev) + }) + }) }) }) From f3f3c9bb45851b8de406355ff9df63bef68e09a1 Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Thu, 16 Jun 2022 13:49:48 +0200 Subject: [PATCH 4/9] feat(ui/admin): remember showRoles toggle selection --- ui/src/admin/actions/influxdb.js | 4 ++++ ui/src/admin/containers/influxdb/UsersPage.tsx | 17 ++++++++--------- ui/src/admin/reducers/influxdb.js | 4 ++++ ui/test/admin/reducers/influxdb.test.js | 8 ++++++++ 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/ui/src/admin/actions/influxdb.js b/ui/src/admin/actions/influxdb.js index ead069c74..fa2898664 100644 --- a/ui/src/admin/actions/influxdb.js +++ b/ui/src/admin/actions/influxdb.js @@ -484,3 +484,7 @@ export const changeSelectedDBs = (selectedDBs /* : string[] */) => ({ export const changeShowUsers = () => ({ type: 'INFLUXDB_CHANGE_SHOW_USERS', }) + +export const changeShowRoles = () => ({ + type: 'INFLUXDB_CHANGE_SHOW_ROLES', +}) diff --git a/ui/src/admin/containers/influxdb/UsersPage.tsx b/ui/src/admin/containers/influxdb/UsersPage.tsx index 4d3e21111..e83b783d6 100644 --- a/ui/src/admin/containers/influxdb/UsersPage.tsx +++ b/ui/src/admin/containers/influxdb/UsersPage.tsx @@ -5,6 +5,7 @@ import {Source, NotificationAction} from 'src/types' import {UserRole, User, Database} from 'src/types/influxAdmin' import {notify as notifyAction} from 'src/shared/actions/notifications' import { + changeShowRoles, createUserAsync, filterUsers as filterUsersAction, } from 'src/admin/actions/influxdb' @@ -47,17 +48,19 @@ const validateUser = ( } const mapStateToProps = ({ - adminInfluxDB: {databases, users, roles, selectedDBs}, + adminInfluxDB: {databases, users, roles, selectedDBs, showRoles}, }) => ({ databases, users, roles, selectedDBs, + showRoles, }) const mapDispatchToProps = { filterUsers: filterUsersAction, createUser: createUserAsync, + toggleShowRoles: changeShowRoles, notify: notifyAction, } @@ -69,6 +72,7 @@ interface ConnectedProps { users: User[] roles: UserRole[] selectedDBs: string[] + showRoles: boolean } type ReduxDispatchProps = ResolveThunks @@ -81,9 +85,11 @@ const UsersPage = ({ users, roles, selectedDBs, + showRoles, notify, createUser, filterUsers, + toggleShowRoles, }: Props) => { const [isEnterprise, usersPage] = useMemo( () => [ @@ -118,13 +124,6 @@ const UsersPage = ({ filterUsers(debouncedFilterText) }, [debouncedFilterText]) - // hide role - const [showRoles, setShowRoles] = useState(true) - const changeHideRoles = useCallback(() => setShowRoles(!showRoles), [ - showRoles, - setShowRoles, - ]) - const [createVisible, setCreateVisible] = useState(false) const createNew = useCallback( async (user: {name: string; password: string}) => { @@ -170,7 +169,7 @@ const UsersPage = ({
Show Roles diff --git a/ui/src/admin/reducers/influxdb.js b/ui/src/admin/reducers/influxdb.js index 29d93d88e..2e96d49ba 100644 --- a/ui/src/admin/reducers/influxdb.js +++ b/ui/src/admin/reducers/influxdb.js @@ -48,6 +48,7 @@ const initialState = { databases: [], selectedDBs: ['*'], showUsers: true, + showRoles: true, } const adminInfluxDB = (state = initialState, action) => { @@ -372,6 +373,9 @@ const adminInfluxDB = (state = initialState, action) => { case 'INFLUXDB_CHANGE_SHOW_USERS': { return {...state, showUsers: !state.showUsers} } + case 'INFLUXDB_CHANGE_SHOW_ROLES': { + return {...state, showRoles: !state.showRoles} + } } return state diff --git a/ui/test/admin/reducers/influxdb.test.js b/ui/test/admin/reducers/influxdb.test.js index 4af5e6dd7..b24dc16c3 100644 --- a/ui/test/admin/reducers/influxdb.test.js +++ b/ui/test/admin/reducers/influxdb.test.js @@ -22,6 +22,7 @@ import { loadDatabases, changeSelectedDBs, changeShowUsers, + changeShowRoles, } from 'src/admin/actions/influxdb' import {NEW_DEFAULT_DATABASE, NEW_EMPTY_RP} from 'src/admin/constants' @@ -546,5 +547,12 @@ describe('Admin.InfluxDB.Reducers', () => { expect(showUsers).toEqual(!prev) }) }) + it('can change showRoles flag', () => { + const vals = [undefined, true, false] + vals.forEach(prev => { + const {showRoles} = reducer({showRoles: prev}, changeShowRoles()) + expect(showRoles).toEqual(!prev) + }) + }) }) }) From aa3ba890a4b05a3c8267c5f8966356f3358266f2 Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Thu, 16 Jun 2022 21:10:17 +0200 Subject: [PATCH 5/9] fix(cypress): correct data test lookup of slide toggle --- ui/src/admin/containers/influxdb/RolesPage.tsx | 2 +- .../components/slide_toggle/SlideToggle.tsx | 12 +++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/ui/src/admin/containers/influxdb/RolesPage.tsx b/ui/src/admin/containers/influxdb/RolesPage.tsx index 9c277aeb2..87bb74269 100644 --- a/ui/src/admin/containers/influxdb/RolesPage.tsx +++ b/ui/src/admin/containers/influxdb/RolesPage.tsx @@ -161,7 +161,7 @@ const RolesPage = ({ active={showUsers} onChange={toggleShowUsers} size={ComponentSize.ExtraSmall} - entity="users" + dataTest="show-users--toggle" /> Show Users
diff --git a/ui/src/reusable_ui/components/slide_toggle/SlideToggle.tsx b/ui/src/reusable_ui/components/slide_toggle/SlideToggle.tsx index 86c5d19f7..1b790dc62 100644 --- a/ui/src/reusable_ui/components/slide_toggle/SlideToggle.tsx +++ b/ui/src/reusable_ui/components/slide_toggle/SlideToggle.tsx @@ -14,7 +14,7 @@ interface Props { color?: ComponentColor disabled?: boolean tooltipText?: string - entity?: string + dataTest?: string } @ErrorHandling @@ -27,14 +27,14 @@ class SlideToggle extends Component { } public render() { - const {tooltipText} = this.props + const {tooltipText, dataTest} = this.props return (
@@ -59,12 +59,6 @@ class SlideToggle extends Component { {active, disabled} ) } - - private get dataTest(): string { - const {active, entity} = this.props - - return active ? `hide-${entity}--toggle` : `show-${entity}--toggle` - } } export default SlideToggle From a6303d9bcf9aa74fd4a41ca8462f8d764c231a31 Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Fri, 17 Jun 2022 07:36:46 +0200 Subject: [PATCH 6/9] feat(ui/admin): persist filter toggles value in localStorage --- ui/src/admin/reducers/influxdb.js | 2 +- ui/src/localStorage.ts | 5 ++++- ui/src/types/localStorage.ts | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ui/src/admin/reducers/influxdb.js b/ui/src/admin/reducers/influxdb.js index 2e96d49ba..a2e5df8db 100644 --- a/ui/src/admin/reducers/influxdb.js +++ b/ui/src/admin/reducers/influxdb.js @@ -38,7 +38,7 @@ const identity = x => x function sortQueries(queries, queriesSort) { return (querySorters[queriesSort] || identity)(queries) } -const initialState = { +export const initialState = { users: [], roles: [], permissions: [], diff --git a/ui/src/localStorage.ts b/ui/src/localStorage.ts index 369d85ad5..910fc9438 100644 --- a/ui/src/localStorage.ts +++ b/ui/src/localStorage.ts @@ -10,6 +10,7 @@ import {defaultTableData} from 'src/logs/constants' import {VERSION, GIT_SHA} from 'src/shared/constants' import {LocalStorage} from 'src/types/localStorage' +import {initialState as adminInfluxDBInitialState} from './admin/reducers/influxdb' export const loadLocalStorage = ( errorsQueue: any[] @@ -39,7 +40,7 @@ export const loadLocalStorage = ( delete state.VERSION delete state.GIT_SHA - + state.adminInfluxDB = {...adminInfluxDBInitialState, ...state.adminInfluxDB} return state } catch (error) { console.error(notifyLoadLocalSettingsFailed(error).message) @@ -55,6 +56,7 @@ export const saveToLocalStorage = ({ dashTimeV1: {ranges, refreshes}, logs, script, + adminInfluxDB: {showUsers, showRoles}, }: LocalStorage): void => { try { const dashTimeV1 = { @@ -104,6 +106,7 @@ export const saveToLocalStorage = ({ }, tableTime: minimalLogs.tableTime || {}, }, + adminInfluxDB: {showRoles, showUsers}, }) ) } catch (err) { diff --git a/ui/src/types/localStorage.ts b/ui/src/types/localStorage.ts index 76e01cc64..a12e48892 100644 --- a/ui/src/types/localStorage.ts +++ b/ui/src/types/localStorage.ts @@ -10,6 +10,10 @@ export interface LocalStorage { logs: LogsState telegrafSystemInterval: string hostPageDisabled: boolean + adminInfluxDB: { + showUsers: boolean + showRoles: boolean + } } export type VERSION = string From 2ade4cb61d3515be768311adeeb1a197f1432867 Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Sat, 18 Jun 2022 09:09:07 +0200 Subject: [PATCH 7/9] chore: simplify code --- ui/src/admin/containers/influxdb/RolePage.tsx | 2 +- ui/src/admin/containers/influxdb/RolesPage.tsx | 4 +--- ui/src/admin/containers/influxdb/UserPage.tsx | 2 +- ui/src/admin/containers/influxdb/UsersPage.tsx | 4 +--- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/ui/src/admin/containers/influxdb/RolePage.tsx b/ui/src/admin/containers/influxdb/RolePage.tsx index a84f39a35..cfaeffcf4 100644 --- a/ui/src/admin/containers/influxdb/RolePage.tsx +++ b/ui/src/admin/containers/influxdb/RolePage.tsx @@ -142,7 +142,7 @@ const RolePage = ({ ) ) }, - [roleDBPermissions, changedPermissions, setChangedPermissions] + [roleDBPermissions, changedPermissions] ) const permissionsChanged = !!Object.keys(changedPermissions).length const changePermissions = useMemo( diff --git a/ui/src/admin/containers/influxdb/RolesPage.tsx b/ui/src/admin/containers/influxdb/RolesPage.tsx index 87bb74269..fb1174800 100644 --- a/ui/src/admin/containers/influxdb/RolesPage.tsx +++ b/ui/src/admin/containers/influxdb/RolesPage.tsx @@ -108,9 +108,7 @@ const RolesPage = ({ // filter users const [filterText, setFilterText] = useState('') - const changeFilterText = useCallback(e => setFilterText(e.target.value), [ - setFilterText, - ]) + const changeFilterText = useCallback(e => setFilterText(e.target.value), []) const debouncedFilterText = useDebounce(filterText, 200) useChangeEffect(() => { filterRoles(debouncedFilterText) diff --git a/ui/src/admin/containers/influxdb/UserPage.tsx b/ui/src/admin/containers/influxdb/UserPage.tsx index b03f43811..b84b4bec9 100644 --- a/ui/src/admin/containers/influxdb/UserPage.tsx +++ b/ui/src/admin/containers/influxdb/UserPage.tsx @@ -173,7 +173,7 @@ const UserPage = ({ ) ) }, - [userDBPermissions, changedPermissions, setChangedPermissions] + [userDBPermissions, changedPermissions] ) const permissionsChanged = !!Object.keys(changedPermissions).length const changePermissions = useMemo( diff --git a/ui/src/admin/containers/influxdb/UsersPage.tsx b/ui/src/admin/containers/influxdb/UsersPage.tsx index e83b783d6..dc1aa3605 100644 --- a/ui/src/admin/containers/influxdb/UsersPage.tsx +++ b/ui/src/admin/containers/influxdb/UsersPage.tsx @@ -116,9 +116,7 @@ const UsersPage = ({ // filter users const [filterText, setFilterText] = useState('') - const changeFilterText = useCallback(e => setFilterText(e.target.value), [ - setFilterText, - ]) + const changeFilterText = useCallback(e => setFilterText(e.target.value), []) const debouncedFilterText = useDebounce(filterText, 200) useChangeEffect(() => { filterUsers(debouncedFilterText) From 9af9f409fa2893c9c234635a24063d2f43b8524b Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Sat, 18 Jun 2022 09:32:57 +0200 Subject: [PATCH 8/9] feat(ui): remember filter text in Roles/Users pages --- .../admin/containers/influxdb/RolesPage.tsx | 9 ++++--- .../admin/containers/influxdb/UsersPage.tsx | 7 +++-- ui/src/admin/reducers/influxdb.js | 10 ++++--- ui/test/admin/reducers/influxdb.test.js | 26 ++++++++++++++----- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/ui/src/admin/containers/influxdb/RolesPage.tsx b/ui/src/admin/containers/influxdb/RolesPage.tsx index fb1174800..40a844724 100644 --- a/ui/src/admin/containers/influxdb/RolesPage.tsx +++ b/ui/src/admin/containers/influxdb/RolesPage.tsx @@ -43,13 +43,14 @@ const validateRole = ( } const mapStateToProps = ({ - adminInfluxDB: {databases, users, roles, selectedDBs, showUsers}, + adminInfluxDB: {databases, users, roles, selectedDBs, showUsers, rolesFilter}, }) => ({ databases, users, roles, selectedDBs, showUsers, + rolesFilter, }) const mapDispatchToProps = { @@ -68,6 +69,7 @@ interface ConnectedProps { roles: UserRole[] selectedDBs: string[] showUsers: boolean + rolesFilter: string } type ReduxDispatchProps = ResolveThunks @@ -81,6 +83,7 @@ const RolesPage = ({ databases, selectedDBs, showUsers, + rolesFilter, router, filterRoles, createRole, @@ -106,8 +109,8 @@ const RolesPage = ({ [visibleDBNames, visibleRoles] ) - // filter users - const [filterText, setFilterText] = useState('') + // filter roles + const [filterText, setFilterText] = useState(rolesFilter) const changeFilterText = useCallback(e => setFilterText(e.target.value), []) const debouncedFilterText = useDebounce(filterText, 200) useChangeEffect(() => { diff --git a/ui/src/admin/containers/influxdb/UsersPage.tsx b/ui/src/admin/containers/influxdb/UsersPage.tsx index dc1aa3605..3145d2ee3 100644 --- a/ui/src/admin/containers/influxdb/UsersPage.tsx +++ b/ui/src/admin/containers/influxdb/UsersPage.tsx @@ -48,13 +48,14 @@ const validateUser = ( } const mapStateToProps = ({ - adminInfluxDB: {databases, users, roles, selectedDBs, showRoles}, + adminInfluxDB: {databases, users, roles, selectedDBs, showRoles, usersFilter}, }) => ({ databases, users, roles, selectedDBs, showRoles, + usersFilter, }) const mapDispatchToProps = { @@ -73,6 +74,7 @@ interface ConnectedProps { roles: UserRole[] selectedDBs: string[] showRoles: boolean + usersFilter: string } type ReduxDispatchProps = ResolveThunks @@ -86,6 +88,7 @@ const UsersPage = ({ roles, selectedDBs, showRoles, + usersFilter, notify, createUser, filterUsers, @@ -115,7 +118,7 @@ const UsersPage = ({ ) // filter users - const [filterText, setFilterText] = useState('') + const [filterText, setFilterText] = useState(usersFilter) const changeFilterText = useCallback(e => setFilterText(e.target.value), []) const debouncedFilterText = useDebounce(filterText, 200) useChangeEffect(() => { diff --git a/ui/src/admin/reducers/influxdb.js b/ui/src/admin/reducers/influxdb.js index a2e5df8db..007e47a34 100644 --- a/ui/src/admin/reducers/influxdb.js +++ b/ui/src/admin/reducers/influxdb.js @@ -49,16 +49,18 @@ export const initialState = { selectedDBs: ['*'], showUsers: true, showRoles: true, + usersFilter: '', + rolesFilter: '', } const adminInfluxDB = (state = initialState, action) => { switch (action.type) { case 'INFLUXDB_LOAD_USERS': { - return {...state, ...action.payload} + return {...state, ...action.payload, usersFilter: ''} } case 'INFLUXDB_LOAD_ROLES': { - return {...state, ...action.payload} + return {...state, ...action.payload, rolesFilter: ''} } case 'INFLUXDB_LOAD_PERMISSIONS': { @@ -338,7 +340,7 @@ const adminInfluxDB = (state = initialState, action) => { return u }), } - return {...state, ...newState} + return {...state, ...newState, usersFilter: text} } case 'INFLUXDB_FILTER_ROLES': { @@ -349,7 +351,7 @@ const adminInfluxDB = (state = initialState, action) => { return r }), } - return {...state, ...newState} + return {...state, ...newState, rolesFilter: text} } case 'INFLUXDB_KILL_QUERY': { diff --git a/ui/test/admin/reducers/influxdb.test.js b/ui/test/admin/reducers/influxdb.test.js index b24dc16c3..daad4f8a3 100644 --- a/ui/test/admin/reducers/influxdb.test.js +++ b/ui/test/admin/reducers/influxdb.test.js @@ -7,6 +7,7 @@ import { syncRole, editDatabase, editRetentionPolicyRequested, + loadUsers, loadRoles, loadPermissions, deleteRole, @@ -224,7 +225,15 @@ describe('Admin.InfluxDB.Reducers', () => { expect(actual.databases).toEqual(expected) }) }) + it('it can load users', () => { + const {users: d, usersFilter} = reducer(state, loadUsers({users})) + const expected = { + users, + usersFilter: '', + } + expect({users: d, usersFilter}).toEqual(expected) + }) it('it can sync a stale user', () => { const staleUser = {...u1, roles: []} state = {users: [u2, staleUser], roles: []} @@ -330,13 +339,14 @@ describe('Admin.InfluxDB.Reducers', () => { expect(actual.users).toEqual(expected.users) }) - it('it can load the roles', () => { - const actual = reducer(state, loadRoles({roles})) + it('it can load roles', () => { + const {roles: d, rolesFilter} = reducer(state, loadRoles({roles})) const expected = { roles, + rolesFilter: '', } - expect(actual.roles).toEqual(expected.roles) + expect({roles: d, rolesFilter}).toEqual(expected) }) it('it can delete a non-existing role', () => { @@ -397,15 +407,16 @@ describe('Admin.InfluxDB.Reducers', () => { const text = 'x' - const actual = reducer(state, filterRoles(text)) + const {roles: d, rolesFilter} = reducer(state, filterRoles(text)) const expected = { roles: [ {...r1, hidden: false}, {...r2, hidden: true}, ], + rolesFilter: text, } - expect(actual.roles).toEqual(expected.roles) + expect({roles: d, rolesFilter}).toEqual(expected) }) it('can filter users w/ "zero" text', () => { @@ -415,15 +426,16 @@ describe('Admin.InfluxDB.Reducers', () => { const text = 'zero' - const actual = reducer(state, filterUsers(text)) + const {users: d, usersFilter} = reducer(state, filterUsers(text)) const expected = { users: [ {...u1, hidden: true}, {...u2, hidden: false}, ], + usersFilter: text, } - expect(actual.users).toEqual(expected.users) + expect({users: d, usersFilter}).toEqual(expected) }) // Permissions From cac6b06263a6fcfc6da3dfbfa3b498cb68874b9c Mon Sep 17 00:00:00 2001 From: Pavel Zavora Date: Tue, 21 Jun 2022 09:41:32 +0200 Subject: [PATCH 9/9] feat(ui/cypress): test also show users toggle --- ui/cypress/integration/admin_influxdb.test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui/cypress/integration/admin_influxdb.test.ts b/ui/cypress/integration/admin_influxdb.test.ts index 26f1cffec..53b357c23 100644 --- a/ui/cypress/integration/admin_influxdb.test.ts +++ b/ui/cypress/integration/admin_influxdb.test.ts @@ -289,10 +289,14 @@ describe('InfluxDB', () => { cy.get('th').contains('Users').should('exist') }) - cy.getByTestID('hide-users--toggle').click() + cy.getByTestID('show-users--toggle').click() cy.getByTestID('admin-table--head').within(() => { cy.get('th').contains('Users').should('not.exist') }) + cy.getByTestID('show-users--toggle').click() + cy.getByTestID('admin-table--head').within(() => { + cy.get('th').contains('Users').should('exist') + }) }) }) })