Skip to content

Commit

Permalink
fix(admin): more work toward chat users
Browse files Browse the repository at this point in the history
  • Loading branch information
allardy committed Oct 15, 2019
1 parent 65aee67 commit 0a8dc7a
Show file tree
Hide file tree
Showing 25 changed files with 1,085 additions and 753 deletions.
1 change: 1 addition & 0 deletions jest-puppeteer.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module.exports = {
password: '123456',
botId: 'test-bot',
host: 'http://localhost:3000',
apiHost: 'http://localhost:3000', // When testing the Admin UI on port 3001, set this to the correct port
recreateBot: true // When testing something specific, set to false to keep the existing bot
}
}
4 changes: 4 additions & 0 deletions src/bp/common/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ export interface WorkspaceUser {
workspaceName?: string
}

export type WorkspaceUserInfo = {
attributes: any
} & WorkspaceUser

export interface AuthStrategyConfig {
strategyType: string
strategyId: string
Expand Down
19 changes: 14 additions & 5 deletions src/bp/core/routers/admin/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,28 +35,37 @@ export class UsersRouter extends CustomRouter {
'/',
this.needPermissions('read', this.resource),
this.asyncMiddleware(async (req, res) => {
const filterRoles = req.query.roles && req.query.roles.split(',')
const users = await this.workspaceService.getWorkspaceUsersAttributes(req.workspace!, [
'last_logon',
'firstname',
'lastname',
'picture_url',
'created_at'
])
return sendSuccess(res, 'Retrieved users', users)

return sendSuccess(
res,
'Retrieved users',
filterRoles ? users.filter(x => filterRoles.includes(x.role)) : users
)
})
)

router.get(
'/listAvailableUsers',
this.needPermissions('read', this.resource),
this.asyncMiddleware(async (req, res) => {
const filterRoles = req.query.roles && req.query.roles.split(',')
const allUsers = await this.authService.getAllUsers()
const workspaceUsers = await this.workspaceService.getWorkspaceUsers(req.workspace!)
const available = _.filter(allUsers, x => !_.find(workspaceUsers, x)) as WorkspaceUser[]

return sendSuccess(res, 'Retrieved users', _.filter(
allUsers,
x => !_.find(workspaceUsers, x)
) as WorkspaceUser[])
return sendSuccess(
res,
'Retrieved available users',
filterRoles ? available.filter(x => filterRoles.includes(x.role)) : available
)
})
)

Expand Down
32 changes: 32 additions & 0 deletions src/bp/ui-admin/src/Pages/Components/BaseDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Classes, Dialog, IDialogProps } from '@blueprintjs/core'
import React, { FC } from 'react'

type Props = {
onSubmit?: (event: any) => void
} & Partial<IDialogProps>

export const BaseDialog: FC<Props> = props => {
return (
<Dialog transitionDuration={0} canOutsideClickClose={false} enforceFocus={false} {...props}>
{props.onSubmit ? <form onSubmit={props.onSubmit}>{props.children}</form> : props.children}
</Dialog>
)
}

export const DialogBody = ({ children }) => {
return <div className={Classes.DIALOG_BODY}>{children}</div>
}

export const DialogFooter = ({ children }) => {
return (
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>{children}</div>
</div>
)
}

export const BPDialog = {
Container: BaseDialog,
Body: DialogBody,
Footer: DialogFooter
}
190 changes: 0 additions & 190 deletions src/bp/ui-admin/src/Pages/Components/UserList.tsx

This file was deleted.

4 changes: 4 additions & 0 deletions src/bp/ui-admin/src/Pages/Components/WorkspaceSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ const WorkspaceSelect: FC<Props> = props => {
}, [props.workspaces, urlWorkspaceId])

useEffect(() => {
if (!props.currentWorkspace) {
return
}

if (isOperationAllowed({ operation: 'read', resource: 'admin.collaborators' })) {
props.fetchUsers()
}
Expand Down
92 changes: 92 additions & 0 deletions src/bp/ui-admin/src/Pages/Workspace/Users/AuthStrategyDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { Button, Classes, MenuItem } from '@blueprintjs/core'
import { ItemPredicate, ItemRenderer, Select } from '@blueprintjs/select'
import { AuthStrategyConfig } from 'common/typings'
import React, { FC, useEffect, useState } from 'react'
import { connect } from 'react-redux'

import { fetchAuthConfig } from '../../../reducers/user'

interface OwnProps {
onChange: (strategy: AuthStrategyConfig) => void
}

interface DispatchProps {
fetchAuthConfig: () => void
}

interface StateProps {
authConfig: AuthStrategyConfig[]
}

type Props = DispatchProps & StateProps & OwnProps

const SelectDropdown = Select.ofType<AuthStrategyConfig>()

const AuthStrategyDropdown: FC<Props> = props => {
const [selected, setSelected] = useState<AuthStrategyConfig>()

useEffect(() => {
if (!props.authConfig) {
props.fetchAuthConfig()
} else if (props.authConfig.length) {
selectOption(props.authConfig[0])
}
}, [props.authConfig])

const selectOption = item => {
if (item) {
setSelected(item)
props.onChange(item)
}
}

if (!props.authConfig || !selected) {
return null
}

return (
<SelectDropdown
items={props.authConfig}
itemPredicate={filterOptions}
itemRenderer={renderOption}
activeItem={selected}
popoverProps={{ minimal: true }}
noResults={<MenuItem disabled={true} text="No results." />}
onItemSelect={option => selectOption(option)}
onActiveItemChange={option => selectOption(option)}
>
<Button text={selected.label || selected.strategyId} rightIcon="double-caret-vertical" />
</SelectDropdown>
)
}

const filterOptions: ItemPredicate<AuthStrategyConfig> = (query, option, _index) => {
const normalizedLabel = option.label && option.label.toLowerCase()
const normalizedQuery = query.toLowerCase()

return `${normalizedLabel} ${option.strategyId}`.indexOf(normalizedQuery) >= 0
}

const renderOption: ItemRenderer<AuthStrategyConfig> = (option, { handleClick, modifiers, query }) => {
if (!modifiers.matchesPredicate) {
return null
}

return (
<MenuItem
className={Classes.SMALL}
active={modifiers.active}
disabled={modifiers.disabled}
key={option.strategyId}
onClick={handleClick}
text={option.label || option.strategyId}
/>
)
}

const mapStateToProps = state => ({ authConfig: state.user.authConfig })

export default connect<StateProps, DispatchProps>(
mapStateToProps,
{ fetchAuthConfig }
)(AuthStrategyDropdown)
Loading

0 comments on commit 0a8dc7a

Please sign in to comment.