mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-11-12 04:25:31 +08:00
d03049b403
Summary: With the fix to the delta-processor, this is all that's needed to get mail rules working! Some places were trying to use 'accountId' to access an account object's id, but it needs to be 'id' instead. Test Plan: tested locally Reviewers: jackie Reviewed By: jackie Differential Revision: https://phab.nylas.com/D3525
306 lines
8.9 KiB
JavaScript
306 lines
8.9 KiB
JavaScript
import React from 'react';
|
|
import _ from 'underscore';
|
|
|
|
import {Actions,
|
|
AccountStore,
|
|
MailRulesStore,
|
|
MailRulesTemplates,
|
|
TaskQueueStatusStore,
|
|
ReprocessMailRulesTask} from 'nylas-exports';
|
|
|
|
import {Flexbox,
|
|
EditableList,
|
|
RetinaImg,
|
|
ScrollRegion,
|
|
ScenarioEditor} from 'nylas-component-kit';
|
|
|
|
const {
|
|
ActionTemplatesForAccount,
|
|
ConditionTemplatesForAccount,
|
|
} = MailRulesTemplates;
|
|
|
|
|
|
class PreferencesMailRules extends React.Component {
|
|
static displayName = 'PreferencesMailRules';
|
|
|
|
constructor() {
|
|
super();
|
|
this.state = this._getStateFromStores();
|
|
}
|
|
|
|
componentDidMount() {
|
|
this._unsubscribers = [];
|
|
this._unsubscribers.push(MailRulesStore.listen(this._onRulesChanged));
|
|
this._unsubscribers.push(TaskQueueStatusStore.listen(this._onTasksChanged));
|
|
}
|
|
|
|
componentWillUnmount() {
|
|
this._unsubscribers.forEach(unsubscribe => unsubscribe());
|
|
}
|
|
|
|
_getStateFromStores() {
|
|
const accounts = AccountStore.accounts();
|
|
const state = this.state || {};
|
|
let {currentAccount} = state;
|
|
if (!accounts.find(acct => acct === currentAccount)) {
|
|
currentAccount = accounts[0];
|
|
}
|
|
const rules = MailRulesStore.rulesForAccountId(currentAccount.id);
|
|
const selectedRule = this.state && this.state.selectedRule ? _.findWhere(rules, {id: this.state.selectedRule.id}) : rules[0];
|
|
|
|
return {
|
|
accounts: accounts,
|
|
currentAccount: currentAccount,
|
|
rules: rules,
|
|
selectedRule: selectedRule,
|
|
tasks: TaskQueueStatusStore.tasksMatching(ReprocessMailRulesTask, {}),
|
|
actionTemplates: ActionTemplatesForAccount(currentAccount),
|
|
conditionTemplates: ConditionTemplatesForAccount(currentAccount),
|
|
}
|
|
}
|
|
|
|
_onSelectAccount = (event) => {
|
|
const accountId = event.target.value;
|
|
const currentAccount = this.state.accounts.find(acct => acct.id === accountId);
|
|
this.setState({currentAccount: currentAccount}, () => {
|
|
this.setState(this._getStateFromStores())
|
|
});
|
|
}
|
|
|
|
_onReprocessRules = () => {
|
|
const needsMessageBodies = () => {
|
|
for (const rule of this.state.rules) {
|
|
for (const condition of rule.conditions) {
|
|
if (condition.templateKey === 'body') {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (needsMessageBodies()) {
|
|
NylasEnv.showErrorDialog("One or more of your mail rules requires the bodies of messages being processed. These rules can't be run on your entire mailbox.");
|
|
}
|
|
|
|
const task = new ReprocessMailRulesTask(this.state.currentAccount.id)
|
|
Actions.queueTask(task);
|
|
}
|
|
|
|
_onAddRule = () => {
|
|
Actions.addMailRule({accountId: this.state.currentAccount.id});
|
|
}
|
|
|
|
_onSelectRule = (rule) => {
|
|
this.setState({selectedRule: rule});
|
|
}
|
|
|
|
_onReorderRule = (rule, startIdx, endIdx) => {
|
|
Actions.reorderMailRule(rule.id, endIdx);
|
|
}
|
|
|
|
_onDeleteRule = (rule) => {
|
|
Actions.deleteMailRule(rule.id);
|
|
}
|
|
|
|
_onRuleNameEdited = (newName, rule) => {
|
|
Actions.updateMailRule(rule.id, {name: newName});
|
|
}
|
|
|
|
_onRuleConditionModeEdited = (event) => {
|
|
Actions.updateMailRule(this.state.selectedRule.id, {conditionMode: event.target.value});
|
|
}
|
|
|
|
_onRuleEnabled = () => {
|
|
Actions.updateMailRule(this.state.selectedRule.id, {disabled: false, disabledReason: null});
|
|
}
|
|
|
|
_onRulesChanged = () => {
|
|
const next = this._getStateFromStores();
|
|
const nextRules = next.rules;
|
|
const prevRules = this.state.rules ? this.state.rules : [];
|
|
|
|
const added = _.difference(nextRules, prevRules);
|
|
if (added.length === 1) {
|
|
next.selectedRule = added[0];
|
|
}
|
|
|
|
this.setState(next);
|
|
}
|
|
|
|
_onTasksChanged = () => {
|
|
this.setState({tasks: TaskQueueStatusStore.tasksMatching(ReprocessMailRulesTask, {})})
|
|
}
|
|
|
|
_renderAccountPicker() {
|
|
const options = this.state.accounts.map(account =>
|
|
<option value={account.id} key={account.id}>{account.label}</option>
|
|
);
|
|
|
|
return (
|
|
<select
|
|
value={this.state.currentAccount.id}
|
|
onChange={this._onSelectAccount}
|
|
style={{margin: 0, minWidth: 200}}
|
|
>
|
|
{options}
|
|
</select>
|
|
);
|
|
}
|
|
|
|
_renderMailRules() {
|
|
if (this.state.rules.length === 0) {
|
|
return (
|
|
<div className="empty-list">
|
|
<RetinaImg
|
|
className="icon-mail-rules"
|
|
name="rules-big.png"
|
|
mode={RetinaImg.Mode.ContentDark}
|
|
/>
|
|
<h2>No rules</h2>
|
|
<button className="btn btn-small" onMouseDown={this._onAddRule}>
|
|
Create a new rule
|
|
</button>
|
|
</div>
|
|
);
|
|
}
|
|
return (
|
|
<Flexbox>
|
|
<EditableList
|
|
showEditIcon
|
|
className="rule-list"
|
|
items={this.state.rules}
|
|
itemContent={this._renderListItemContent}
|
|
onCreateItem={this._onAddRule}
|
|
onReorderItem={this._onReorderRule}
|
|
onDeleteItem={this._onDeleteRule}
|
|
onItemEdited={this._onRuleNameEdited}
|
|
selected={this.state.selectedRule}
|
|
onSelectItem={this._onSelectRule}
|
|
/>
|
|
{this._renderDetail()}
|
|
</Flexbox>
|
|
);
|
|
}
|
|
|
|
_renderListItemContent(rule) {
|
|
if (rule.disabled) {
|
|
return (<div className="item-rule-disabled">{rule.name}</div>);
|
|
}
|
|
return rule.name;
|
|
}
|
|
|
|
_renderDetail() {
|
|
const rule = this.state.selectedRule;
|
|
|
|
if (rule) {
|
|
return (
|
|
<ScrollRegion className="rule-detail">
|
|
{this._renderDetailDisabledNotice()}
|
|
<div className="inner">
|
|
<span>If </span>
|
|
<select value={rule.conditionMode} onChange={this._onRuleConditionModeEdited}>
|
|
<option value="any">Any</option>
|
|
<option value="all">All</option>
|
|
</select>
|
|
<span> of the following conditions are met:</span>
|
|
<ScenarioEditor
|
|
instances={rule.conditions}
|
|
templates={this.state.conditionTemplates}
|
|
onChange={(conditions) => Actions.updateMailRule(rule.id, {conditions})}
|
|
className="well well-matchers"
|
|
/>
|
|
<span>Perform the following actions:</span>
|
|
<ScenarioEditor
|
|
instances={rule.actions}
|
|
templates={this.state.actionTemplates}
|
|
onChange={(actions) => Actions.updateMailRule(rule.id, {actions})}
|
|
className="well well-actions"
|
|
/>
|
|
</div>
|
|
</ScrollRegion>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="rule-detail">
|
|
<div className="no-selection">Create a rule or select one to get started</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
_renderDetailDisabledNotice() {
|
|
if (!this.state.selectedRule.disabled) return false;
|
|
return (
|
|
<div className="disabled-reason">
|
|
<button className="btn" onClick={this._onRuleEnabled}>Enable</button>
|
|
This rule has been disabled. Make sure the actions below are valid
|
|
and re-enable the rule.
|
|
<div>({this.state.selectedRule.disabledReason})</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
_renderTasks() {
|
|
if (this.state.tasks.length === 0) return false;
|
|
return (
|
|
<div style={{flex: 1, paddingLeft: 20}}>
|
|
{this.state.tasks.map((task) => {
|
|
return (
|
|
<Flexbox style={{alignItems: 'baseline'}}>
|
|
<div style={{paddingRight: "12px"}}>
|
|
<RetinaImg name="sending-spinner.gif" width={18} mode={RetinaImg.Mode.ContentPreserve} />
|
|
</div>
|
|
<div>
|
|
<strong>{AccountStore.accountForId(task.accountId).emailAddress}</strong>
|
|
{` — ${Number(task.numberOfImpactedItems()).toLocaleString()} processed...`}
|
|
</div>
|
|
<div style={{flex: 1}} />
|
|
<button className="btn btn-sm" onClick={() => Actions.dequeueTask(task.id)}>
|
|
Cancel
|
|
</button>
|
|
</Flexbox>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
render() {
|
|
const processDisabled = _.any(this.state.tasks, (task) => {
|
|
return (task.accountId === this.state.currentAccount.id);
|
|
});
|
|
|
|
return (
|
|
<div className="container-mail-rules">
|
|
<section>
|
|
<Flexbox className="container-dropdown">
|
|
<div>Account:</div>
|
|
<div className="dropdown">{this._renderAccountPicker()}</div>
|
|
</Flexbox>
|
|
<p>Rules only apply to the selected account.</p>
|
|
|
|
{this._renderMailRules()}
|
|
|
|
<Flexbox style={{marginTop: 40, maxWidth: 600}}>
|
|
<div>
|
|
<button disabled={processDisabled} className="btn" style={{'float': 'right'}} onClick={this._onReprocessRules}>
|
|
Process entire inbox
|
|
</button>
|
|
</div>
|
|
{this._renderTasks()}
|
|
</Flexbox>
|
|
|
|
<p style={{marginTop: 10}}>
|
|
By default, mail rules are only applied to new mail as it arrives.
|
|
Applying rules to your entire inbox may take a long time and
|
|
degrade performance.
|
|
</p>
|
|
</section>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
export default PreferencesMailRules;
|