diff --git a/app/scenes/CollectionExport.tsx b/app/scenes/CollectionExport.tsx
index cf8458684..b1148dd49 100644
--- a/app/scenes/CollectionExport.tsx
+++ b/app/scenes/CollectionExport.tsx
@@ -25,7 +25,9 @@ function CollectionExport({ collection, onSubmit }: Props) {
setIsLoading(false);
showToast(
- t("Export started, you will receive an email when it’s complete.")
+ t(
+ "Export started. If you have notifications enabled, you will receive an email when it's complete."
+ )
);
onSubmit();
},
diff --git a/app/scenes/Settings/Export.tsx b/app/scenes/Settings/Export.tsx
index 160f44b97..05b8d3907 100644
--- a/app/scenes/Settings/Export.tsx
+++ b/app/scenes/Settings/Export.tsx
@@ -56,7 +56,7 @@ function Export() {
{t("Export")}
{
+ protected async beforeSend({ userId, teamId }: Props) {
+ const notificationSetting = await NotificationSetting.findOne({
+ where: {
+ userId,
+ teamId,
+ event: "emails.export_completed",
+ },
+ });
+
+ return notificationSetting !== null;
+ }
+
protected subject() {
return "Your requested export";
}
diff --git a/server/emails/templates/ExportSuccessEmail.tsx b/server/emails/templates/ExportSuccessEmail.tsx
index f39381990..a992790f9 100644
--- a/server/emails/templates/ExportSuccessEmail.tsx
+++ b/server/emails/templates/ExportSuccessEmail.tsx
@@ -1,4 +1,5 @@
import * as React from "react";
+import { NotificationSetting } from "@server/models";
import BaseEmail from "./BaseEmail";
import Body from "./components/Body";
import Button from "./components/Button";
@@ -10,8 +11,10 @@ import Heading from "./components/Heading";
type Props = {
to: string;
+ userId: string;
id: string;
teamUrl: string;
+ teamId: string;
};
/**
@@ -19,6 +22,18 @@ type Props = {
* for download in the settings section.
*/
export default class ExportSuccessEmail extends BaseEmail {
+ protected async beforeSend({ userId, teamId }: Props) {
+ const notificationSetting = await NotificationSetting.findOne({
+ where: {
+ userId,
+ teamId,
+ event: "emails.export_completed",
+ },
+ });
+
+ return notificationSetting !== null;
+ }
+
protected subject() {
return "Your requested export";
}
diff --git a/server/models/NotificationSetting.ts b/server/models/NotificationSetting.ts
index f42f98f6e..461503a3c 100644
--- a/server/models/NotificationSetting.ts
+++ b/server/models/NotificationSetting.ts
@@ -41,6 +41,7 @@ class NotificationSetting extends Model {
"emails.invite_accepted",
"emails.onboarding",
"emails.features",
+ "emails.export_completed",
],
])
@Column(DataType.STRING)
diff --git a/server/models/User.ts b/server/models/User.ts
index 2497107c5..dd907c954 100644
--- a/server/models/User.ts
+++ b/server/models/User.ts
@@ -497,7 +497,9 @@ class User extends ParanoidModel {
};
// By default when a user signs up we subscribe them to email notifications
- // when documents they created are edited by other team members and onboarding
+ // when documents they created are edited by other team members and onboarding.
+ // If the user is an admin, they will also be subscribed to export_completed
+ // notifications.
@AfterCreate
static subscribeToNotifications = async (
model: User,
@@ -537,6 +539,17 @@ class User extends ParanoidModel {
transaction: options.transaction,
}),
]);
+
+ if (model.isAdmin) {
+ await NotificationSetting.findOrCreate({
+ where: {
+ userId: model.id,
+ teamId: model.teamId,
+ event: "emails.export_completed",
+ },
+ transaction: options.transaction,
+ });
+ }
};
static getCounts = async function (teamId: string) {
diff --git a/server/queues/tasks/ExportMarkdownZipTask.ts b/server/queues/tasks/ExportMarkdownZipTask.ts
index 1f5c4c651..d5d562a65 100644
--- a/server/queues/tasks/ExportMarkdownZipTask.ts
+++ b/server/queues/tasks/ExportMarkdownZipTask.ts
@@ -72,8 +72,10 @@ export default class ExportMarkdownZipTask extends BaseTask {
await ExportSuccessEmail.schedule({
to: user.email,
+ userId: user.id,
id: fileOperation.id,
teamUrl: team.url,
+ teamId: team.id,
});
} catch (error) {
await this.updateFileOperation(fileOperation, {
@@ -82,7 +84,9 @@ export default class ExportMarkdownZipTask extends BaseTask {
});
await ExportFailureEmail.schedule({
to: user.email,
+ userId: user.id,
teamUrl: team.url,
+ teamId: team.id,
});
throw error;
}
diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json
index 1cc80c1f8..f67953cb3 100644
--- a/shared/i18n/locales/en_US/translation.json
+++ b/shared/i18n/locales/en_US/translation.json
@@ -343,7 +343,7 @@
"Sort": "Sort",
"Saving": "Saving",
"Save": "Save",
- "Export started, you will receive an email when it’s complete.": "Export started, you will receive an email when it’s complete.",
+ "Export started. If you have notifications enabled, you will receive an email when it's complete.": "Export started. If you have notifications enabled, you will receive an email when it's complete.",
"Exporting the collection {{collectionName}} may take a few seconds. Your documents will be a zip of folders with files in Markdown format. Please visit the Export section on settings to get the zip.": "Exporting the collection {{collectionName}} may take a few seconds. Your documents will be a zip of folders with files in Markdown format. Please visit the Export section on settings to get the zip.",
"Exporting": "Exporting",
"Export Collection": "Export Collection",
@@ -620,7 +620,7 @@
"This is the screen that team members will first see when they sign in.": "This is the screen that team members will first see when they sign in.",
"Export in progress…": "Export in progress…",
"Export deleted": "Export deleted",
- "A full export might take some time, consider exporting a single document or collection. The exported data is a zip of your documents in Markdown format. You may leave this page once the export has started – we will email a link to {{ userEmail }} when it’s complete.": "A full export might take some time, consider exporting a single document or collection. The exported data is a zip of your documents in Markdown format. You may leave this page once the export has started – we will email a link to {{ userEmail }} when it’s complete.",
+ "A full export might take some time, consider exporting a single document or collection. The exported data is a zip of your documents in Markdown format. You may leave this page once the export has started – if you have notifications enabled, we will email a link to {{ userEmail }} when it’s complete.": "A full export might take some time, consider exporting a single document or collection. The exported data is a zip of your documents in Markdown format. You may leave this page once the export has started – if you have notifications enabled, we will email a link to {{ userEmail }} when it’s complete.",
"Export Requested": "Export Requested",
"Requesting Export": "Requesting Export",
"Export Data": "Export Data",
@@ -650,6 +650,8 @@
"Receive a notification whenever a new collection is created": "Receive a notification whenever a new collection is created",
"Invite accepted": "Invite accepted",
"Receive a notification when someone you invited creates an account": "Receive a notification when someone you invited creates an account",
+ "Export completed": "Export completed",
+ "Receive a notification when an export you requested has been completed": "Receive a notification when an export you requested has been completed",
"Getting started": "Getting started",
"Tips on getting started with Outline’s features and functionality": "Tips on getting started with Outline’s features and functionality",
"New features": "New features",