diff --git a/app/scenes/Settings/ImportExport.js b/app/scenes/Settings/ImportExport.js
index 0ba4966a..a25bc652 100644
--- a/app/scenes/Settings/ImportExport.js
+++ b/app/scenes/Settings/ImportExport.js
@@ -23,17 +23,22 @@ function ImportExport() {
const { showToast } = ui;
const [isLoading, setLoading] = React.useState(false);
const [isImporting, setImporting] = React.useState(false);
+ const [importedDetails, setImported] = React.useState(false);
const [isExporting, setExporting] = React.useState(false);
const [file, setFile] = React.useState();
const [importDetails, setImportDetails] = React.useState();
const handleImport = React.useCallback(
async (ev) => {
+ setImported(undefined);
setImporting(true);
try {
- await documents.batchImport(file);
+ const { documentCount, collectionCount } = await documents.batchImport(
+ file
+ );
showToast(t("Import completed"));
+ setImported({ documentCount, collectionCount });
} catch (err) {
showToast(err.message);
} finally {
@@ -116,6 +121,17 @@ function ImportExport() {
accept="application/zip"
/>
+ {importedDetails && (
+
+
+ Import successful, {{ count: importedDetails.documentCount }}{" "}
+ documents were imported to your knowledge base.
+
+
+ )}
{file && !isImportable && (
@@ -126,7 +142,7 @@ function ImportExport() {
)}
{file && importDetails && isImportable ? (
<>
-
+
{{ fileName: file.name }} looks good, the
following collections and their documents will be imported:
diff --git a/app/stores/DocumentsStore.js b/app/stores/DocumentsStore.js
index 5b5a2c72..3c76189e 100644
--- a/app/stores/DocumentsStore.js
+++ b/app/stores/DocumentsStore.js
@@ -508,6 +508,8 @@ export default class DocumentsStore extends BaseStore {
this.addPolicies(res.policies);
res.data.collections.forEach(this.rootStore.collections.add);
+
+ return res.data;
};
@action
diff --git a/server/api/documents.js b/server/api/documents.js
index b1a3ec43..d9e642de 100644
--- a/server/api/documents.js
+++ b/server/api/documents.js
@@ -1124,7 +1124,7 @@ router.post("documents.batchImport", auth(), async (ctx) => {
const user = ctx.state.user;
authorize(user, "batchImport", Document);
- const { collections } = await documentBatchImporter({
+ const { documents, attachments, collections } = await documentBatchImporter({
file,
user,
type,
@@ -1133,6 +1133,9 @@ router.post("documents.batchImport", auth(), async (ctx) => {
ctx.body = {
data: {
+ attachmentCount: attachments.length,
+ documentCount: documents.length,
+ collectionCount: collections.length,
collections: collections.map((collection) =>
presentCollection(collection)
),
@@ -1189,6 +1192,7 @@ router.post("documents.import", auth(), async (ctx) => {
});
const document = await documentCreator({
+ source: "import",
title,
text,
publish,
diff --git a/server/commands/attachmentCreator.js b/server/commands/attachmentCreator.js
index 46f0215c..906054cb 100644
--- a/server/commands/attachmentCreator.js
+++ b/server/commands/attachmentCreator.js
@@ -8,12 +8,14 @@ export default async function attachmentCreator({
type,
buffer,
user,
+ source,
ip,
}: {
name: string,
type: string,
buffer: Buffer,
user: User,
+ source?: "import",
ip: string,
}) {
const key = `uploads/${user.id}/${uuid.v4()}/${name}`;
@@ -32,7 +34,7 @@ export default async function attachmentCreator({
await Event.create({
name: "attachments.create",
- data: { name },
+ data: { name, source },
modelId: attachment.id,
teamId: user.teamId,
actorId: user.id,
diff --git a/server/commands/documentBatchImporter.js b/server/commands/documentBatchImporter.js
index 884a5822..a34b1502 100644
--- a/server/commands/documentBatchImporter.js
+++ b/server/commands/documentBatchImporter.js
@@ -114,6 +114,7 @@ export default async function documentBatchImporter({
}
const document = await documentCreator({
+ source: "import",
title,
text,
publish: true,
@@ -134,6 +135,7 @@ export default async function documentBatchImporter({
if (item.type === "attachment") {
const buffer = await item.item.async("nodebuffer");
const attachment = await attachmentCreator({
+ source: "import",
name: item.name,
type,
buffer,
diff --git a/server/commands/documentCreator.js b/server/commands/documentCreator.js
index 805af277..3c986c3f 100644
--- a/server/commands/documentCreator.js
+++ b/server/commands/documentCreator.js
@@ -14,6 +14,7 @@ export default async function documentCreator({
index,
user,
editorVersion,
+ source,
ip,
}: {
title: string,
@@ -28,6 +29,7 @@ export default async function documentCreator({
index?: number,
user: User,
editorVersion?: string,
+ source?: "import",
ip: string,
}): Document {
const templateId = templateDocument ? templateDocument.id : undefined;
@@ -53,7 +55,7 @@ export default async function documentCreator({
collectionId: document.collectionId,
teamId: document.teamId,
actorId: user.id,
- data: { title: document.title, templateId },
+ data: { source, title: document.title, templateId },
ip,
});
@@ -66,7 +68,7 @@ export default async function documentCreator({
collectionId: document.collectionId,
teamId: document.teamId,
actorId: user.id,
- data: { title: document.title },
+ data: { source, title: document.title },
ip,
});
}
diff --git a/server/events.js b/server/events.js
index f60181c5..0d671f5d 100644
--- a/server/events.js
+++ b/server/events.js
@@ -47,6 +47,10 @@ export type DocumentEvent =
teamId: string,
actorId: string,
ip: string,
+ data: {
+ title: string,
+ source?: "import",
+ },
}
| {
name: "documents.move",
diff --git a/server/services/notifications.js b/server/services/notifications.js
index 9629ad40..2cd9d833 100644
--- a/server/services/notifications.js
+++ b/server/services/notifications.js
@@ -27,6 +27,9 @@ export default class Notifications {
}
async documentUpdated(event: DocumentEvent) {
+ // never send notifications when batch importing documents
+ if (event.data && event.data.source === "import") return;
+
const document = await Document.findByPk(event.documentId);
if (!document) return;
diff --git a/server/services/slack.js b/server/services/slack.js
index 3b552eb6..fd29ec13 100644
--- a/server/services/slack.js
+++ b/server/services/slack.js
@@ -55,6 +55,9 @@ export default class Slack {
}
async documentUpdated(event: DocumentEvent) {
+ // never send notifications when batch importing documents
+ if (event.data && event.data.source === "import") return;
+
const document = await Document.findByPk(event.documentId);
if (!document) return;
diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json
index ae74c485..80cfee22 100644
--- a/shared/i18n/locales/en_US/translation.json
+++ b/shared/i18n/locales/en_US/translation.json
@@ -279,6 +279,8 @@
"Export in progress…": "Export in progress…",
"Import": "Import",
"It is possible to import a zip file of folders and Markdown files previously exported from an Outline instance. Support will soon be added for importing from other services.": "It is possible to import a zip file of folders and Markdown files previously exported from an Outline instance. Support will soon be added for importing from other services.",
+ "importSuccessful": "Import successful, {{ count }} document was imported into your knowledge base.",
+ "importSuccessful_plural": "Import successful, {{ count }} documents were imported into your knowledge base.",
"Sorry, the file <1>{{fileName}}1> is missing valid collections or documents.": "Sorry, the file <1>{{fileName}}1> is missing valid collections or documents.",
"<0>{{fileName}}0> looks good, the following collections and their documents will be imported:": "<0>{{fileName}}0> looks good, the following collections and their documents will be imported:",
"Importing": "Importing",
@@ -309,4 +311,4 @@
"Suspended": "Suspended",
"Edit Profile": "Edit Profile",
"{{ userName }} hasn’t updated any documents yet.": "{{ userName }} hasn’t updated any documents yet."
-}
+}
\ No newline at end of file