Skip to content
This repository has been archived by the owner on Dec 28, 2022. It is now read-only.

Commit

Permalink
feat(entity-browser): Confirmation dialog if touched form is left
Browse files Browse the repository at this point in the history
To show a confirmation box, only the `<Prompt>` component has to be added with
the desired message.

However, by default, the native confirmation dialog of the browser is displayed
which is not that pretty. To display a nicer toastr confirmation box, we have
to use the `getUserConfirmation` option when we create the history.

At the moment, there is an ongoing discussion about how to use a custom
component for the dialog here:
remix-run/react-router#4635
  • Loading branch information
rzueger committed Apr 11, 2017
1 parent 7917a5d commit b962bb0
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 6 deletions.
3 changes: 3 additions & 0 deletions packages/entity-browser/src/dev/rest-responses/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
"client.entity-browser.saveSuccessfulMessage",
"client.entity-browser.lastSave",
"client.entity-browser.backToList",
"client.entity-browser.confirmTouchedFormLeave",
"client.entity-browser.confirmationOk",
"client.entity-browser.confirmationCancel",
"client.component.remoteselect.searchPromptText",
"client.component.remoteselect.clearValueText",
"client.component.remoteselect.clearAllText",
Expand Down
27 changes: 24 additions & 3 deletions packages/entity-browser/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,37 @@ import React from 'react'

import {appFactory} from 'tocco-util'
import {Router} from 'react-router'
import createHistory from 'history/createHashHistory'
import createHashHistory from 'history/createHashHistory'
import RouteWithSubRoutes from './components/RouteWithSubRoutes'
import {createConfirmationAction} from './util/notification'

const packageName = 'entity-browser'

const initApp = (id, input, events, publicPath) => {
const history = createHistory()
const textResourceSelector = (state, key) => state.intl.messages[key] || key

const createHistory = store => createHashHistory({
getUserConfirmation: (message, callback) => {
const state = store.getState()

const okText = textResourceSelector(state, 'client.entity-browser.confirmationOk')
const cancelText = textResourceSelector(state, 'client.entity-browser.confirmationCancel')

const action = createConfirmationAction(
message,
okText,
cancelText,
() => callback(true), // eslint-disable-line standard/no-callback-literal
() => callback(false) // eslint-disable-line standard/no-callback-literal
)
store.dispatch(action)
}
})

const initApp = (id, input, events, publicPath) => {
const store = appFactory.createStore(undefined, undefined, input)

const history = createHistory(store)

const routes = require('./routes/index').default(store, input)

const content = (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import {reduxForm, Field} from 'redux-form'
import {intlShape, FormattedRelative, FormattedMessage} from 'react-intl'
import {Prompt} from 'react-router-dom'
import {Button, LayoutBox} from 'tocco-ui'

import ReduxFormFieldAdapter from '../ReduxFormFieldAdapter'
Expand Down Expand Up @@ -102,6 +103,10 @@ export class DetailForm extends React.Component {

return (
<form tabIndex="0" onSubmit={this.handleSubmit} className="form-horizontal" onKeyDown={this.handleKeyPress}>
<Prompt
when={props.anyTouched}
message={this.msg('client.entity-browser.confirmTouchedFormLeave')}
/>
{getForm(props.formDefinition, this.createField, this.createLayoutComponent)}
{!props.valid && props.anyTouched && <ErrorBox formErrors={props.formErrors} showErrors={this.showErrors}/>}
<Button
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react'
import {Field} from 'redux-form'
import {Field, reducer as formReducer, touch} from 'redux-form'
import {Provider} from 'react-redux'
import {createStore} from 'redux'
import {createStore, combineReducers} from 'redux'
import DetailForm from './DetailForm'

import {mount} from 'enzyme'
import {IntlStub} from 'tocco-test-util'
import {IntlStub, context} from 'tocco-test-util'

const EMPTY_FUNC = () => {
}
Expand Down Expand Up @@ -104,6 +104,76 @@ describe('entity-browser', () => {
expect(wrapper.find('form')).to.have.length(1)
expect(wrapper.find(Field)).to.have.length(2)
})

it('should request user confirmation when touched form is left', () => {
const formDefinition = {
'name': 'UserSearch_detail',
'type': 'ch.tocco.nice2.model.form.components.Form',
'displayType': 'READONLY',
'children': [
{
'name': 'firstname',
'type': 'ch.tocco.nice2.model.form.components.simple.TextField',
'displayType': 'READONLY',
'children': [],
'label': 'Vorname',
'useLabel': 'YES'
}
]
}

const entity = {
'key': 6,
'model': 'User',
'paths': {}
}

const store = createStore(combineReducers({form: formReducer}))

const testFn = touched => {
const block = sinon.mock()

if (touched) {
block.once().withExactArgs('client.entity-browser.confirmTouchedFormLeave')
}

const fakeContext = {router: {block}}
const contextTypes = {router: React.PropTypes.object}

const formComponent = context.wrapWithContext(fakeContext, contextTypes,
<DetailForm
submitting={false}
submitForm={EMPTY_FUNC}
formDefinition={formDefinition}
entity={entity}
entityModel={{}}
logError={EMPTY_FUNC}
loadRelationEntities={EMPTY_FUNC}
relationEntities={{}}
form="detailForm"
intl={IntlStub}
/>
)

mount(
<Provider store={store}>
{formComponent}
</Provider>
)

if (touched) {
store.dispatch(touch('detailForm'), 'firstname')
}

block.verify()
}

// field touched -> confirmation requested
testFn(true)

// no field touched -> no confirmation requested
testFn(false)
})
})
})
})

0 comments on commit b962bb0

Please sign in to comment.