This repository has been archived by the owner on Feb 28, 2020. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a modal to alert failed login attempts. #1
- Loading branch information
1 parent
f4723f7
commit 1b63fbe
Showing
13 changed files
with
186 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { Component, createRef } from 'react' | ||
import { ModalHeader, ModalBody, Button } from 'reactstrap' | ||
|
||
export default class Alert extends Component { | ||
constructor(props) { | ||
super(props) | ||
this.dismissButtonRef = createRef() | ||
} | ||
handleDismissClick = () => { | ||
this.props.close() | ||
} | ||
componentDidMount() { | ||
setTimeout(() => this.dismissButtonRef.current.focus()) | ||
} | ||
render() { | ||
const { message } = this.props | ||
const { handleDismissClick, dismissButtonRef } = this | ||
return ( | ||
<> | ||
<ModalHeader className="py-4 justify-content-center"> | ||
{ message } | ||
</ModalHeader> | ||
<ModalBody className="d-flex justify-content-center"> | ||
<Button | ||
color="secondary" | ||
innerRef={dismissButtonRef} | ||
name="dismiss-modal" | ||
onClick={handleDismissClick}>Dismiss</Button> | ||
</ModalBody> | ||
</> | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default as Alert } from './alert' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export { default as Authenticate } from './authenticate' | ||
export { default as Modal } from './modal' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import noop from 'lodash/noop' | ||
import { Component } from 'react' | ||
import { Modal as ReactstrapModal } from 'reactstrap' | ||
import { withServices } from '../services' | ||
|
||
class Modal extends Component { | ||
constructor(props) { | ||
super(props) | ||
this.state = { | ||
isOpen: false, | ||
response: null | ||
} | ||
this.unsubscribe = noop | ||
} | ||
onClosed = () => { | ||
this.props.modal.close(this.state.response) | ||
} | ||
close = response => { | ||
this.setState({ isOpen: false, response }) | ||
} | ||
componentDidMount() { | ||
this.unsubscribe = this.props.modal.subscribe(({ isOpen }) => { | ||
this.setState({ isOpen }) | ||
}) | ||
} | ||
componentWillUnmount() { | ||
this.unsubscribe() | ||
} | ||
render() { | ||
const { isOpen } = this.state | ||
const { modal: { render } } = this.props | ||
const { close, onClosed, onOpened } = this | ||
return ( | ||
<ReactstrapModal | ||
autoFocus | ||
centered | ||
isOpen={isOpen} | ||
onClosed={onClosed} | ||
onOpened={onOpened}> | ||
{ render({ close }) } | ||
</ReactstrapModal> | ||
) | ||
} | ||
} | ||
|
||
export default withServices(Modal, ({ modal }) => ({ | ||
modal | ||
})) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export { default as authorize } from './authorize' | ||
export { default as isServer } from './is-server' | ||
export { default as Model } from './model' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
export default class Model { | ||
constructor() { | ||
this._listeners = [] | ||
this._model = this.init | ||
} | ||
get init() { | ||
return {} | ||
} | ||
subscribe(listener) { | ||
const listenerIndex = this._listeners.push(listener) - 1 | ||
listener(this._model) | ||
return () => { | ||
this._listeners.splice(listenerIndex, 1) | ||
} | ||
} | ||
update(updater) { | ||
switch (typeof updater) { | ||
case 'function': | ||
this._model = { ...this._model, ...updater(this._model) } | ||
break | ||
case 'object': | ||
this._model = { ...this._model, ...updater } | ||
break | ||
default: | ||
throw new Error('updater passed to StateModel.setState must be a Function or an Object.') | ||
} | ||
this._listeners.forEach(listener => listener(this._model)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * from './context' | ||
export { default as initApi } from './api' | ||
export { default as initModal } from './modal' | ||
export { default as initSession } from './session' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import noop from 'lodash/noop' | ||
import { Model, isServer } from '../lib' | ||
|
||
class Modal extends Model { | ||
get init() { | ||
return { | ||
onClose: noop, | ||
isOpen: false, | ||
render: noop | ||
} | ||
} | ||
get render() { | ||
return this._model.render | ||
} | ||
open({ onClose = noop, render = noop }) { | ||
if (this._model.isOpen) return | ||
this.update({ | ||
isOpen: true, | ||
onClose, | ||
render | ||
}) | ||
} | ||
close(response) { | ||
if (!this._model.isOpen) return | ||
this._model.onClose(response) | ||
this.update(this.init) | ||
} | ||
} | ||
|
||
let modal | ||
|
||
export default function initModal() { | ||
if (isServer) return new Modal() | ||
modal = modal || new Modal() | ||
return modal | ||
} |