Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better email #1367

Merged
merged 55 commits into from
Sep 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
fdf9314
convert email sending to use Nodemailer
jshimko Sep 9, 2016
95908c6
add getShopSettings and getPackageSettings helpers
jshimko Sep 9, 2016
9c62494
replace all Meteor accounts-password email methods
jshimko Sep 9, 2016
f978b32
remove old email api
jshimko Sep 11, 2016
3983670
rewrite mail config methods to use nodemailer-wellknown
jshimko Sep 11, 2016
18dea16
create emails collection for longer term log storage
jshimko Sep 12, 2016
40c99c6
add mail service to shop mail settings schema
jshimko Sep 12, 2016
14b94c9
refactor email sending job to use new API
jshimko Sep 12, 2016
de0469e
add Meteor methods for email API
jshimko Sep 12, 2016
62031f2
add email publication for logs page
jshimko Sep 12, 2016
5c8ca12
build new email dashboard UI plugin for using new API
jshimko Sep 12, 2016
9b501a9
remove old Blaze email settings
jshimko Sep 12, 2016
82d833f
fix alerts arg checks when callback is missing
jshimko Sep 12, 2016
d6c0ba9
add new FieldGroup and Loading React components
jshimko Sep 12, 2016
5085de8
default theme cleanup
jshimko Sep 12, 2016
ed12830
fix variables import order in default theme
jshimko Sep 12, 2016
b94e8cd
dependencies updates
jshimko Sep 12, 2016
d8d1603
clean up job queue workers
jshimko Sep 14, 2016
70fa8cc
update eslint config for more React details
jshimko Sep 14, 2016
0463d33
fix custom email config
jshimko Sep 14, 2016
0875db3
fix type handling for email config port
jshimko Sep 14, 2016
0734174
remove email dashboard nav tabs component until needed
jshimko Sep 14, 2016
05ea418
add saving state and better error handling to email settings
jshimko Sep 14, 2016
af76db8
change email status route name
jshimko Sep 14, 2016
51b4860
remove deprecated mail config hook
jshimko Sep 14, 2016
e3c6c23
Merge branch 'development' into better-email
jshimko Sep 14, 2016
e68fae2
add unblock to email config verify method
jshimko Sep 14, 2016
ff428ef
add host/port to conditions for custom email config check
jshimko Sep 14, 2016
e9cfe00
move email methods to base of methods dir
jshimko Sep 15, 2016
9ea21bd
package updates
jshimko Sep 15, 2016
e0020b0
fix comment typo
jshimko Sep 16, 2016
dd7a9f7
update dockerignore to reflect new location
jshimko Sep 16, 2016
176e236
default vals for mail host/port not needed in registry entry
jshimko Sep 16, 2016
0b1df44
fix optional email save when settings are invalid
jshimko Sep 16, 2016
185bc8c
fix email settings save button state after errors
jshimko Sep 16, 2016
e205345
don’t run email settings verify method if settings are missing
jshimko Sep 16, 2016
2aa5c72
add log when new email settings are saved
jshimko Sep 16, 2016
318e8d2
npm updates
jshimko Sep 16, 2016
9ebb38c
fix text overflow in email config panel
jshimko Sep 16, 2016
b6e2319
fix type checking on email port setting
jshimko Sep 16, 2016
6e80199
fix syntax
jshimko Sep 16, 2016
37cb8f0
i18n-ify all new email components
jshimko Sep 18, 2016
6968651
Merge branch 'development' into better-email
jshimko Sep 18, 2016
a0649fc
fix sweetalert promise
jshimko Sep 18, 2016
56ac5db
fix 118n prop
jshimko Sep 18, 2016
e8f2b4d
remove password from logs
jshimko Sep 18, 2016
b2967c1
force immediate retry of email job
jshimko Sep 19, 2016
43b0f45
add new column in email log table for action buttons
jshimko Sep 19, 2016
58f431c
remove unnecessary braces
jshimko Sep 19, 2016
8e48aec
fix missing email port in UI
jshimko Sep 19, 2016
2039165
package updates
jshimko Sep 19, 2016
948d83c
Merge branch 'development' into better-email
jshimko Sep 19, 2016
0b74c06
restore searching for email templates from the database
jshimko Sep 21, 2016
a5f59d1
clean up imports method
jshimko Sep 21, 2016
b0071ec
Merge branch 'development' into better-email
jshimko Sep 21, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
.git
.build.log
Dockerfile
docker/reaction.*
.reaction/docker/reaction.*
docs
node_modules
packages/*/.npm
Expand Down
10 changes: 5 additions & 5 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,19 @@
"react/no-deprecated": 1,
"react/display-name": 1,
"react/forbid-prop-types": 1,
"react/jsx-boolean-value": [1, "always"],
"react/jsx-closing-bracket-location": 1,
"react/jsx-boolean-value": 0,
"react/jsx-closing-bracket-location": [1, "after-props"],
"react/jsx-curly-spacing": 1,
"react/jsx-indent-props": [1, 2],
"react/jsx-max-props-per-line": [1, {
"maximum": 4
}],
"react/jsx-no-bind": 1,
"react/jsx-no-bind": 0,
"react/jsx-no-duplicate-props": 1,
"react/jsx-no-literals": 1,
"react/jsx-no-literals": 0,
"react/jsx-no-undef": 1,
"react/sort-prop-types": 1,
"react/jsx-sort-props": 1,
"react/jsx-sort-props": 0,
"react/jsx-uses-react": 1,
"react/jsx-uses-vars": 1,
"react/no-danger": 1,
Expand Down
1 change: 0 additions & 1 deletion .meteor/packages
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ [email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
amplify
mdg:validated-method
Expand Down
5 changes: 3 additions & 2 deletions client/modules/accounts/templates/forgot/forgot.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Meteor } from "meteor/meteor";
import { Template } from "meteor/templating";
import { i18next } from "/client/api";
import { LoginFormSharedHelpers } from "/client/modules/accounts/helpers";
import { Template } from "meteor/templating";

Template.loginFormResetPasswordView.events({

Expand Down Expand Up @@ -32,7 +33,7 @@ Template.loginFormResetPasswordView.events({
// return;
}

Accounts.forgotPassword({ email: emailAddress}, (error) => {
Meteor.call("accounts/sendResetPasswordEmail", { email: emailAddress }, (error) => {
// Show some message confirming result
if (error) {
templateInstance.formMessages.set({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import { Accounts } from "meteor/accounts-base";
import { Template } from "meteor/templating";
import { i18next } from "/client/api";
import { LoginFormSharedHelpers } from "/client/modules/accounts/helpers";
import { Template } from "meteor/templating";

ModalHelper = {
closeModal: function (template) {
Blaze.remove(template.view);
}
};

/**
* Accounts Event: onResetPasswordLink When a user uses a password reset link
Expand Down
23 changes: 15 additions & 8 deletions client/modules/core/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,24 @@ export default {
return this.shopName;
},

allowGuestCheckout() {
let allowGuest = false;
const packageRegistry = Packages.findOne({
getShopSettings() {
const settings = Packages.findOne({
name: "core",
shopId: this.shopId
});
}) || {};
return settings.settings || {};
},

getPackageSettings(name) {
return Packages.findOne({ name, shopId: this.getShopId() });
},

allowGuestCheckout() {
let allowGuest = false;
const settings = this.getShopSettings();
// we can disable in admin, let's check.
if (typeof packageRegistry === "object" &&
typeof packageRegistry.settings === "object" &&
packageRegistry.settings.public.allowGuestCheckout) {
allowGuest = packageRegistry.settings.public.allowGuestCheckout;
if (settings.public && settings.public.allowGuestCheckout) {
allowGuest = settings.public.allowGuestCheckout;
}
return allowGuest;
},
Expand Down
2 changes: 1 addition & 1 deletion client/modules/core/startup.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Meteor } from "meteor/meteor";
import { Tracker } from "meteor/tracker";
import Logger from "/client/modules/logger";
import Reaction from "./main";
import { Meteor } from "meteor/meteor";

// @see https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
let hidden;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,32 +82,6 @@
</div>
</div>

<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-title">
<a
href="#mail"
aria-controls="mail"
role="button"
data-toggle="collapse"
data-parent="#shopSettingsAccordian"
data-i18n="shopSettings.mail">Mail</a>
</div>
</div>
<div id="mail" class="panel-collapse collapse" role="tabpanel" aria-labelledby="mail">
<div class="panel-body">
{{#autoForm collection=Collections.Packages schema=Schemas.CorePackageConfig
doc=packageData id="shopEditEmailForm" type="update"}}
{{> afQuickField name='settings.mail.user'}}
{{> afQuickField name='settings.mail.password'}}
{{> afQuickField name='settings.mail.host'}}
{{> afQuickField name='settings.mail.port'}}
{{> shopSettingsSubmitButton}}
{{/autoForm}}
</div>
</div>
</div>

<div class="panel panel-default">
<div class="panel-heading">
<div class="panel-title">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,19 +185,6 @@ AutoForm.hooks({
}
});

AutoForm.hooks({
shopEditEmailForm: {
onSuccess: function () {
return Alerts.toast(i18next.t("shopSettings.shopMailSettingsSaved"),
"success");
},
onError: function (operation, error) {
return Alerts.toast(`${i18next.t("shopSettings.shopMailSettingsFailed")
} ${error}`, "error");
}
}
});

AutoForm.hooks({
shopEditExternalServicesForm: {
onSuccess: function () {
Expand Down
2 changes: 2 additions & 0 deletions imports/plugins/core/email/client/actions/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as logs } from "./logs";
export { default as settings } from "./settings";
35 changes: 35 additions & 0 deletions imports/plugins/core/email/client/actions/logs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Router, i18next } from "/client/api";

export default {

/**
* Update the limit query param in the URL
* @param {Object} event - sythetic React event
* @return {String} returns the updated limit
*/
updateLimit(event) {
return _.debounce(() => {
const limit = event.target.value;
if (!limit) {
Router.setQueryParams({ limit: null });
} else {
Router.setQueryParams({ limit });
}
}, 300, { maxWait: 1000 })();
},


/**
* Restart a failed or cancelled email job
* @param {Object} email - the email job object
* @return {null} triggers an alert
*/
resend(email) {
Meteor.call("emails/retryFailed", email._id, (err) => {
if (err) {
return Alerts.toast(i18next.t("app.error", { error: err.reason }), "error");
}
return Alerts.toast(i18next.t("mail.alerts.resendSuccess", { email: email.data.to }), "success");
});
}
};
87 changes: 87 additions & 0 deletions imports/plugins/core/email/client/actions/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import Alert from "sweetalert2";
import { Reaction, i18next } from "/client/api";

export default {

/**
* Open the email settings menu
* @return {Boolean} returns true if action view toggled
*/
toggleSettings() {
Reaction.showActionView({
label: i18next.t("mail.headers.emailSettings"),
template: "emailSettings"
});
return true;
},

/**
* Save email settings
* @param {Object} settings - object of mail provider settings
* @param {Function} callback - optional callback
* @return {Boolean} returns true if all fields provided and update method called
*/
saveSettings(settings, callback) {
const { service, host, port, user, password } = settings;

if (!service) {
Alert(i18next.t("app.error"), i18next.t("mail.alerts.missingService"), "error");
return callback();
}

if (service !== "custom" && (!user || !password)) {
Alert(i18next.t("app.error"), i18next.t("mail.alerts.userPassRequired", { service }), "error");
return callback();
}

if (service === "custom" && (!host || !port || !user || !password)) {
Alert(i18next.t("app.error"), i18next.t("mail.alerts.allFieldsRequired"), "error");
return callback();
}

// make sure port is a Number
settings.port = Number(settings.port);

if (isNaN(settings.port)) {
Alert(i18next.t("app.error"), i18next.t("mail.alerts.portNaN"), "error");
return callback();
}

const save = () => {
Meteor.call("email/saveSettings", settings, (err) => {
if (err) {
return Alert(i18next.t("app.error"),
i18next.t("mail.alerts.saveFailed", { error: err.reason }),
"error");
}
return Alert({
title: i18next.t("app.success"),
text: i18next.t("mail.alerts.saveSuccess"),
type: "success",
timer: 1700
}).catch(() => null);
});
};

// check if the settings work first
Meteor.call("email/verifySettings", settings, (error) => {
callback();
// if the connection fails
if (error) {
Alert({
title: i18next.t("mail.alerts.connectionFailed"),
text: i18next.t("mail.alerts.saveAnyway"),
type: "warning",
showCancelButton: true,
cancelButtonText: i18next.t("app.cancel"),
confirmButtonColor: "#DD6B55",
confirmButtonText: i18next.t("app.save")
}).then(() => save()).catch(() => true);
} else {
save();
}
});

return true;
}
};
30 changes: 30 additions & 0 deletions imports/plugins/core/email/client/components/email_config.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.email-config-header {
display: flex;
justify-content: space-between;
}

.email-config-title {
font-size: 2rem;
font-weight: 200;
}

.email-config-status {
margin-top: .4rem;
}

.email-status-error {
padding-top: 1rem;
color: #b94628;
}

.email-config-status i {
margin-left: .3rem;
}

.email-config-status i.valid {
color: #2dc378;
}

.email-config-status i.error {
color: #b94628;
}
Loading