mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-06 20:54:26 +08:00
Summary: Adds Mail Merge Plugin - Adds new table components to component kit - Adds new extension points to allow dragging and dropping into composer contenteditable and participant fields and customizing participant fields - Adds new decorators and other misc updates - #1608 Test Plan: TODO Reviewers: bengotow, evan Reviewed By: bengotow, evan Differential Revision: https://phab.nylas.com/D2895
149 lines
3.8 KiB
JavaScript
149 lines
3.8 KiB
JavaScript
import React, {Component, PropTypes} from 'react';
|
|
import classnames from 'classnames'
|
|
import {RegExpUtils} from 'nylas-exports'
|
|
import {DropZone, TokenizingTextField} from 'nylas-component-kit'
|
|
import {DataTransferTypes} from './mail-merge-constants'
|
|
import {mailMergeSessionForDraft} from './mail-merge-draft-editing-session'
|
|
|
|
|
|
class MailMergeParticipantToken extends Component {
|
|
static propTypes = {
|
|
token: PropTypes.shape({
|
|
selectionValue: PropTypes.any,
|
|
}),
|
|
}
|
|
|
|
render() {
|
|
const {token: {selectionValue}} = this.props
|
|
if (!selectionValue) {
|
|
return <span>No value selected</span>
|
|
}
|
|
return <span>{selectionValue}</span>
|
|
}
|
|
}
|
|
|
|
|
|
class MailMergeParticipantsTextField extends Component {
|
|
static displayName = 'MailMergeParticipantsTextField'
|
|
|
|
static propTypes = {
|
|
className: PropTypes.string,
|
|
field: PropTypes.string,
|
|
session: PropTypes.object,
|
|
draftClientId: PropTypes.string,
|
|
onAdd: PropTypes.func,
|
|
onRemove: PropTypes.func,
|
|
}
|
|
|
|
static defaultProps = {
|
|
className: '',
|
|
}
|
|
|
|
constructor(props) {
|
|
super(props)
|
|
this.session = mailMergeSessionForDraft(props.draftClientId, props.session)
|
|
this.state = {isDropping: false, ...this.session.state}
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.unsubscribers = [
|
|
this.session.listen(::this.onSessionChange),
|
|
]
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this.unsubscribers.forEach(unsub => unsub())
|
|
}
|
|
|
|
// Called when a token is dragged and dropped in a new field
|
|
onAddToken(...args) {
|
|
const tokenToAdd = args[0][0]
|
|
if (args.length > 1 || !tokenToAdd) { return }
|
|
|
|
const {field} = this.props
|
|
const {colIdx} = tokenToAdd
|
|
this.session.unlinkFromDraft({colIdx, field: tokenToAdd.field})
|
|
this.session.linkToDraft({colIdx, field})
|
|
}
|
|
|
|
onRemoveToken([tokenToDelete]) {
|
|
const {field} = this.props
|
|
const {colIdx} = tokenToDelete
|
|
this.session.unlinkFromDraft({colIdx, field})
|
|
}
|
|
|
|
onDrop(event) {
|
|
const {dataTransfer} = event
|
|
const {field} = this.props
|
|
const colIdx = dataTransfer.getData(DataTransferTypes.ColIdx)
|
|
this.session.linkToDraft({colIdx, field})
|
|
}
|
|
|
|
onSessionChange() {
|
|
this.setState(this.session.state)
|
|
}
|
|
|
|
onDragStateChange({isDropping}) {
|
|
this.setState({isDropping})
|
|
}
|
|
|
|
tokenIsValid({selectionValue}) {
|
|
return (
|
|
selectionValue &&
|
|
selectionValue.match(RegExpUtils.emailRegex()) != null
|
|
)
|
|
}
|
|
|
|
focus() {
|
|
this.refs.textField.focus()
|
|
}
|
|
|
|
shouldAcceptDrop(event) {
|
|
const {dataTransfer} = event
|
|
return !!dataTransfer.getData(DataTransferTypes.ColIdx)
|
|
}
|
|
|
|
render() {
|
|
const {field, className} = this.props
|
|
const {isWorkspaceOpen, tableData: {rows}, selection, linkedFields, isDropping} = this.state
|
|
|
|
if (!isWorkspaceOpen) {
|
|
return <TokenizingTextField ref="textField" {...this.props} />
|
|
}
|
|
|
|
const classes = classnames({
|
|
'mail-merge-participants-text-field': true,
|
|
'is-dropping': isDropping,
|
|
[className]: true,
|
|
})
|
|
const tokens = (
|
|
Array.from(linkedFields[field])
|
|
.map(colIdx => ({field, colIdx, selectionValue: rows[selection.row][colIdx]}))
|
|
)
|
|
|
|
return (
|
|
<DropZone
|
|
onDrop={::this.onDrop}
|
|
onDragStateChange={::this.onDragStateChange}
|
|
shouldAcceptDrop={::this.shouldAcceptDrop}
|
|
>
|
|
<TokenizingTextField
|
|
{...this.props}
|
|
ref="textField"
|
|
className={classes}
|
|
tokens={tokens}
|
|
tokenKey={(f) => `${f.colIdx}-${f.field}`}
|
|
tokenRenderer={MailMergeParticipantToken}
|
|
tokenIsValid={::this.tokenIsValid}
|
|
onRequestCompletions={() => []}
|
|
completionNode={() => <span />}
|
|
onAdd={::this.onAddToken}
|
|
onRemove={::this.onRemoveToken}
|
|
/>
|
|
</DropZone>
|
|
)
|
|
}
|
|
}
|
|
MailMergeParticipantsTextField.containerRequired = false
|
|
|
|
export default MailMergeParticipantsTextField
|