diff --git a/src/browser/modules/Frame/FrameSuccess.jsx b/src/browser/modules/Frame/FrameSuccess.jsx index b3112cc643a..60e73beaee1 100644 --- a/src/browser/modules/Frame/FrameSuccess.jsx +++ b/src/browser/modules/Frame/FrameSuccess.jsx @@ -20,7 +20,11 @@ import React from 'react' const FrameSuccess = props => { if (!props || !props.message) return null - return {props.message} + return ( + + {props.message} + + ) } export default FrameSuccess diff --git a/src/browser/modules/Stream/Auth/ConnectForm.tsx b/src/browser/modules/Stream/Auth/ConnectForm.tsx index 9de13413c42..b51f2950d53 100644 --- a/src/browser/modules/Stream/Auth/ConnectForm.tsx +++ b/src/browser/modules/Stream/Auth/ConnectForm.tsx @@ -187,7 +187,6 @@ export default function ConnectForm(props: ConnectFormProps): JSX.Element { data-testid="username" onChange={props.onUsernameChange} defaultValue={props.username} - required /> @@ -202,7 +201,6 @@ export default function ConnectForm(props: ConnectFormProps): JSX.Element { onChange={props.onPasswordChange} defaultValue={props.password} type="password" - required /> diff --git a/src/browser/modules/User/UserAdd.jsx b/src/browser/modules/User/UserAdd.jsx index bfa67f98c88..75f85196f13 100644 --- a/src/browser/modules/User/UserAdd.jsx +++ b/src/browser/modules/User/UserAdd.jsx @@ -32,7 +32,7 @@ import { createDatabaseUser, addRoleToUser } from 'shared/modules/cypher/boltUserHelper' -import { CYPHER_REQUEST } from 'shared/modules/cypher/cypherDuck' +import { ROUTED_CYPHER_WRITE_REQUEST } from 'shared/modules/cypher/cypherDuck' import RolesSelector from './RolesSelector' import FrameTemplate from 'browser/modules/Frame/FrameTemplate' @@ -111,7 +111,7 @@ export class UserAdd extends Component { this.state.roles.forEach(role => { this.props.bus && this.props.bus.self( - CYPHER_REQUEST, + ROUTED_CYPHER_WRITE_REQUEST, { query: addRoleToUser( this.state.username, @@ -149,7 +149,7 @@ export class UserAdd extends Component { getRoles() { this.props.bus && this.props.bus.self( - CYPHER_REQUEST, + ROUTED_CYPHER_WRITE_REQUEST, { query: listRolesQuery(Boolean(this.props.useSystemDb)), queryType: NEO4J_BROWSER_USER_ACTION_QUERY, @@ -174,7 +174,9 @@ export class UserAdd extends Component { ) } - submit() { + submit = event => { + event.preventDefault() + this.setState({ isLoading: true, success: null, errors: null }) const errors = [] if (!this.state.username) errors.push('Missing username') @@ -193,7 +195,7 @@ export class UserAdd extends Component { createUser() { this.props.bus && this.props.bus.self( - CYPHER_REQUEST, + ROUTED_CYPHER_WRITE_REQUEST, { query: createDatabaseUser( this.state, @@ -297,7 +299,7 @@ export class UserAdd extends Component { /> ) frameContents = ( - + Username - + @@ -402,9 +400,4 @@ const mapStateToProps = state => { } } -export default withBus( - connect( - mapStateToProps, - null - )(UserAdd) -) +export default withBus(connect(mapStateToProps, null)(UserAdd)) diff --git a/src/browser/modules/User/UserAdd.test.js b/src/browser/modules/User/UserAdd.test.js index 11fbc5d099f..a1cc4d0be23 100644 --- a/src/browser/modules/User/UserAdd.test.js +++ b/src/browser/modules/User/UserAdd.test.js @@ -23,7 +23,7 @@ import React from 'react' import { createBus } from 'suber' import { UserAdd } from './UserAdd' -import { CYPHER_REQUEST } from 'shared/modules/cypher/cypherDuck' +import { ROUTED_CYPHER_WRITE_REQUEST } from 'shared/modules/cypher/cypherDuck' import { listRolesQuery } from 'shared/modules/cypher/boltUserHelper' // Stubbing out title bar as it depends on store @@ -41,7 +41,7 @@ describe('', () => { } const busCallback = jest.fn() - bus.one(CYPHER_REQUEST, busCallback) + bus.one(ROUTED_CYPHER_WRITE_REQUEST, busCallback) render() diff --git a/src/browser/modules/User/UserList.jsx b/src/browser/modules/User/UserList.jsx index b721eae6d99..bf7629d290e 100644 --- a/src/browser/modules/User/UserList.jsx +++ b/src/browser/modules/User/UserList.jsx @@ -29,7 +29,7 @@ import { } from 'shared/modules/cypher/boltUserHelper' import UserInformation from './UserInformation' import bolt from 'services/bolt/bolt' -import { CYPHER_REQUEST } from 'shared/modules/cypher/cypherDuck' +import { ROUTED_CYPHER_WRITE_REQUEST } from 'shared/modules/cypher/cypherDuck' import { StyledLink } from 'browser-components/buttons' import { StyledTable, StyledTh } from 'browser-components/DataTables' import { StyledButtonContainer } from './styled' @@ -100,7 +100,7 @@ export class UserList extends Component { getUserList() { this.props.bus.self( - CYPHER_REQUEST, + ROUTED_CYPHER_WRITE_REQUEST, { query: listUsersQuery(Boolean(this.props.useSystemDb)), queryType: NEO4J_BROWSER_USER_ACTION_QUERY, @@ -119,7 +119,7 @@ export class UserList extends Component { getRoles() { this.props.bus.self( - CYPHER_REQUEST, + ROUTED_CYPHER_WRITE_REQUEST, { query: listRolesQuery(Boolean(this.props.useSystemDb)), queryType: NEO4J_BROWSER_USER_ACTION_QUERY, diff --git a/src/browser/modules/User/UserList.test.js b/src/browser/modules/User/UserList.test.js index 9902ed41802..d77d9b319e8 100644 --- a/src/browser/modules/User/UserList.test.js +++ b/src/browser/modules/User/UserList.test.js @@ -23,7 +23,7 @@ import React from 'react' import { createBus } from 'suber' import { UserList } from './UserList' -import { CYPHER_REQUEST } from 'shared/modules/cypher/cypherDuck' +import { ROUTED_CYPHER_WRITE_REQUEST } from 'shared/modules/cypher/cypherDuck' import { listRolesQuery, listUsersQuery @@ -44,7 +44,7 @@ describe('', () => { } const busCallback = jest.fn() - bus.take(CYPHER_REQUEST, busCallback) + bus.take(ROUTED_CYPHER_WRITE_REQUEST, busCallback) render() @@ -68,7 +68,7 @@ describe('', () => { } const busCallback = jest.fn() - bus.take(CYPHER_REQUEST, busCallback) + bus.take(ROUTED_CYPHER_WRITE_REQUEST, busCallback) render() diff --git a/src/shared/modules/cypher/cypherDuck.js b/src/shared/modules/cypher/cypherDuck.js index 9d5dcf3d692..f8e831adece 100644 --- a/src/shared/modules/cypher/cypherDuck.js +++ b/src/shared/modules/cypher/cypherDuck.js @@ -42,6 +42,7 @@ import { const NAME = 'cypher' export const CYPHER_REQUEST = `${NAME}/REQUEST` +export const ROUTED_CYPHER_WRITE_REQUEST = `${NAME}/ROUTED_WRITE_REQUEST` export const AD_HOC_CYPHER_REQUEST = `${NAME}/AD_HOC_REQUEST` export const CLUSTER_CYPHER_REQUEST = `${NAME}/CLUSTER_REQUEST` export const FORCE_CHANGE_PASSWORD = `${NAME}/FORCE_CHANGE_PASSWORD` @@ -117,6 +118,35 @@ export const cypherRequestEpic = (some$, store) => })) }) +export const routedCypherRequestEpic = (some$, store) => + some$.ofType(ROUTED_CYPHER_WRITE_REQUEST).mergeMap(action => { + if (!action.$$responseChannel) return Rx.Observable.of(null) + + const [id, promise] = bolt.routedWriteTransaction( + action.query, + action.params, + { + useCypherThread: shouldUseCypherThread(store.getState()), + ...getUserTxMetadata(action.queryType || null)({ + hasServerSupport: canSendTxMetadata(store.getState()) + }), + cancelable: true, + useDb: action.useDb + } + ) + return promise + .then(result => ({ + type: action.$$responseChannel, + success: true, + result + })) + .catch(error => ({ + type: action.$$responseChannel, + success: false, + error + })) + }) + export const adHocCypherRequestEpic = (some$, store) => some$.ofType(AD_HOC_CYPHER_REQUEST).mergeMap(action => { const connection = getActiveConnectionData(store.getState()) diff --git a/src/shared/rootEpic.js b/src/shared/rootEpic.js index f3a737aa595..02c5af45bfe 100644 --- a/src/shared/rootEpic.js +++ b/src/shared/rootEpic.js @@ -58,6 +58,7 @@ import { clearLocalstorageEpic } from './modules/localstorage/localstorageDuck' import { populateEditorFromUrlEpic } from './modules/editor/editorDuck' import { adHocCypherRequestEpic, + routedCypherRequestEpic, cypherRequestEpic, clusterCypherRequestEpic, handleForcePasswordChangeEpic @@ -121,6 +122,7 @@ export default combineEpics( injectDiscoveryEpic, populateEditorFromUrlEpic, adHocCypherRequestEpic, + routedCypherRequestEpic, cypherRequestEpic, clusterCypherRequestEpic, clearLocalstorageEpic,