Store import<->document relationship (#4415)
* Store import<->document relationship * Update 20221112152649-import-document-relationship.js * Store importId on collection, UI tweaks on import screen
This commit is contained in:
@@ -83,7 +83,7 @@ function Import() {
|
|||||||
subtitle={t("Import pages from a Confluence instance")}
|
subtitle={t("Import pages from a Confluence instance")}
|
||||||
actions={
|
actions={
|
||||||
<Button type="submit" disabled neutral>
|
<Button type="submit" disabled neutral>
|
||||||
{t("Coming soon")}
|
{t("Enterprise")}
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ const FileOperationListItem = ({ fileOperation, handleDelete }: Props) => {
|
|||||||
const user = useCurrentUser();
|
const user = useCurrentUser();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const stateMapping = {
|
const stateMapping = {
|
||||||
|
complete: t("Completed"),
|
||||||
creating: t("Processing"),
|
creating: t("Processing"),
|
||||||
expired: t("Expired"),
|
expired: t("Expired"),
|
||||||
uploading: t("Processing"),
|
uploading: t("Processing"),
|
||||||
@@ -46,9 +47,7 @@ const FileOperationListItem = ({ fileOperation, handleDelete }: Props) => {
|
|||||||
image={iconMapping[fileOperation.state]}
|
image={iconMapping[fileOperation.state]}
|
||||||
subtitle={
|
subtitle={
|
||||||
<>
|
<>
|
||||||
{fileOperation.state !== "complete" && (
|
{stateMapping[fileOperation.state]} •
|
||||||
<>{stateMapping[fileOperation.state]} • </>
|
|
||||||
)}
|
|
||||||
{fileOperation.error && <>{fileOperation.error} • </>}
|
{fileOperation.error && <>{fileOperation.error} • </>}
|
||||||
{t(`{{userName}} requested`, {
|
{t(`{{userName}} requested`, {
|
||||||
userName:
|
userName:
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export default async function documentCreator({
|
|||||||
collectionId,
|
collectionId,
|
||||||
parentDocumentId,
|
parentDocumentId,
|
||||||
templateDocument,
|
templateDocument,
|
||||||
|
importId,
|
||||||
createdAt,
|
createdAt,
|
||||||
// allows override for import
|
// allows override for import
|
||||||
updatedAt,
|
updatedAt,
|
||||||
@@ -26,6 +27,7 @@ export default async function documentCreator({
|
|||||||
publish?: boolean;
|
publish?: boolean;
|
||||||
collectionId: string;
|
collectionId: string;
|
||||||
parentDocumentId?: string;
|
parentDocumentId?: string;
|
||||||
|
importId?: string;
|
||||||
templateDocument?: Document | null;
|
templateDocument?: Document | null;
|
||||||
publishedAt?: Date;
|
publishedAt?: Date;
|
||||||
template?: boolean;
|
template?: boolean;
|
||||||
@@ -54,6 +56,7 @@ export default async function documentCreator({
|
|||||||
template,
|
template,
|
||||||
templateId,
|
templateId,
|
||||||
publishedAt,
|
publishedAt,
|
||||||
|
importId,
|
||||||
title: templateDocument ? templateDocument.title : title,
|
title: templateDocument ? templateDocument.title : title,
|
||||||
text: templateDocument ? templateDocument.text : text,
|
text: templateDocument ? templateDocument.text : text,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
async up(queryInterface, Sequelize) {
|
||||||
|
await queryInterface.sequelize.transaction(async (transaction) => {
|
||||||
|
await queryInterface.addColumn("documents", "importId", {
|
||||||
|
type: Sequelize.UUID,
|
||||||
|
allowNull: true,
|
||||||
|
references: {
|
||||||
|
model: "file_operations",
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
await queryInterface.addColumn("collections", "importId", {
|
||||||
|
type: Sequelize.UUID,
|
||||||
|
allowNull: true,
|
||||||
|
references: {
|
||||||
|
model: "file_operations",
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
await queryInterface.addIndex("documents", ["importId"], {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
await queryInterface.addIndex("collections", ["importId"], {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
async down(queryInterface) {
|
||||||
|
await queryInterface.sequelize.transaction(async (transaction) => {
|
||||||
|
await queryInterface.removeIndex("collections", ["importId"], {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
await queryInterface.removeIndex("documents", ["importId"], {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
await queryInterface.removeColumn("collections", "importId", {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
await queryInterface.removeColumn("documents", "importId", {
|
||||||
|
transaction
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -30,6 +30,7 @@ import type { NavigationNode, CollectionSort } from "~/types";
|
|||||||
import CollectionGroup from "./CollectionGroup";
|
import CollectionGroup from "./CollectionGroup";
|
||||||
import CollectionUser from "./CollectionUser";
|
import CollectionUser from "./CollectionUser";
|
||||||
import Document from "./Document";
|
import Document from "./Document";
|
||||||
|
import FileOperation from "./FileOperation";
|
||||||
import Group from "./Group";
|
import Group from "./Group";
|
||||||
import GroupUser from "./GroupUser";
|
import GroupUser from "./GroupUser";
|
||||||
import Team from "./Team";
|
import Team from "./Team";
|
||||||
@@ -272,6 +273,13 @@ class Collection extends ParanoidModel {
|
|||||||
|
|
||||||
// associations
|
// associations
|
||||||
|
|
||||||
|
@BelongsTo(() => FileOperation, "importId")
|
||||||
|
import: FileOperation | null;
|
||||||
|
|
||||||
|
@ForeignKey(() => FileOperation)
|
||||||
|
@Column(DataType.UUID)
|
||||||
|
importId: string | null;
|
||||||
|
|
||||||
@HasMany(() => Document, "collectionId")
|
@HasMany(() => Document, "collectionId")
|
||||||
documents: Document[];
|
documents: Document[];
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import { DocumentValidation } from "@shared/validations";
|
|||||||
import slugify from "@server/utils/slugify";
|
import slugify from "@server/utils/slugify";
|
||||||
import Backlink from "./Backlink";
|
import Backlink from "./Backlink";
|
||||||
import Collection from "./Collection";
|
import Collection from "./Collection";
|
||||||
|
import FileOperation from "./FileOperation";
|
||||||
import Revision from "./Revision";
|
import Revision from "./Revision";
|
||||||
import Star from "./Star";
|
import Star from "./Star";
|
||||||
import Team from "./Team";
|
import Team from "./Team";
|
||||||
@@ -342,6 +343,13 @@ class Document extends ParanoidModel {
|
|||||||
|
|
||||||
// associations
|
// associations
|
||||||
|
|
||||||
|
@BelongsTo(() => FileOperation, "importId")
|
||||||
|
import: FileOperation | null;
|
||||||
|
|
||||||
|
@ForeignKey(() => FileOperation)
|
||||||
|
@Column(DataType.UUID)
|
||||||
|
importId: string | null;
|
||||||
|
|
||||||
@BelongsTo(() => Document, "parentDocumentId")
|
@BelongsTo(() => Document, "parentDocumentId")
|
||||||
parentDocument: Document | null;
|
parentDocument: Document | null;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ export default function present(data: FileOperation) {
|
|||||||
return {
|
return {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
type: data.type,
|
type: data.type,
|
||||||
|
format: data.format,
|
||||||
name: data.collection?.name || path.basename(data.key || ""),
|
name: data.collection?.name || path.basename(data.key || ""),
|
||||||
state: data.state,
|
state: data.state,
|
||||||
error: data.error,
|
error: data.error,
|
||||||
|
|||||||
@@ -274,6 +274,7 @@ export default abstract class ImportTask extends BaseTask<Props> {
|
|||||||
}),
|
}),
|
||||||
createdById: fileOperation.userId,
|
createdById: fileOperation.userId,
|
||||||
permission: CollectionPermission.ReadWrite,
|
permission: CollectionPermission.ReadWrite,
|
||||||
|
importId: fileOperation.id,
|
||||||
},
|
},
|
||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
@@ -294,6 +295,7 @@ export default abstract class ImportTask extends BaseTask<Props> {
|
|||||||
createdById: fileOperation.userId,
|
createdById: fileOperation.userId,
|
||||||
name,
|
name,
|
||||||
permission: CollectionPermission.ReadWrite,
|
permission: CollectionPermission.ReadWrite,
|
||||||
|
importId: fileOperation.id,
|
||||||
},
|
},
|
||||||
{ transaction }
|
{ transaction }
|
||||||
);
|
);
|
||||||
@@ -357,6 +359,7 @@ export default abstract class ImportTask extends BaseTask<Props> {
|
|||||||
updatedAt: item.updatedAt ?? item.createdAt,
|
updatedAt: item.updatedAt ?? item.createdAt,
|
||||||
publishedAt: item.updatedAt ?? item.createdAt ?? new Date(),
|
publishedAt: item.updatedAt ?? item.createdAt ?? new Date(),
|
||||||
parentDocumentId: item.parentDocumentId,
|
parentDocumentId: item.parentDocumentId,
|
||||||
|
importId: fileOperation.id,
|
||||||
user,
|
user,
|
||||||
ip,
|
ip,
|
||||||
transaction,
|
transaction,
|
||||||
|
|||||||
@@ -51,13 +51,13 @@ router.post(
|
|||||||
authorize(user, "manage", team);
|
authorize(user, "manage", team);
|
||||||
|
|
||||||
const [exports, total] = await Promise.all([
|
const [exports, total] = await Promise.all([
|
||||||
await FileOperation.findAll({
|
FileOperation.findAll({
|
||||||
where,
|
where,
|
||||||
order: [[sort, direction]],
|
order: [[sort, direction]],
|
||||||
offset: ctx.state.pagination.offset,
|
offset: ctx.state.pagination.offset,
|
||||||
limit: ctx.state.pagination.limit,
|
limit: ctx.state.pagination.limit,
|
||||||
}),
|
}),
|
||||||
await FileOperation.count({
|
FileOperation.count({
|
||||||
where,
|
where,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -586,6 +586,7 @@
|
|||||||
"Please choose a single file to import": "Please choose a single file to import",
|
"Please choose a single file to import": "Please choose a single file to import",
|
||||||
"Your import is being processed, you can safely leave this page": "Your import is being processed, you can safely leave this page",
|
"Your import is being processed, you can safely leave this page": "Your import is being processed, you can safely leave this page",
|
||||||
"File not supported – please upload a valid ZIP file": "File not supported – please upload a valid ZIP file",
|
"File not supported – please upload a valid ZIP file": "File not supported – please upload a valid ZIP file",
|
||||||
|
"Completed": "Completed",
|
||||||
"Processing": "Processing",
|
"Processing": "Processing",
|
||||||
"Expired": "Expired",
|
"Expired": "Expired",
|
||||||
"Failed": "Failed",
|
"Failed": "Failed",
|
||||||
@@ -673,7 +674,7 @@
|
|||||||
"Import data": "Import data",
|
"Import data": "Import data",
|
||||||
"Import pages exported from Notion": "Import pages exported from Notion",
|
"Import pages exported from Notion": "Import pages exported from Notion",
|
||||||
"Import pages from a Confluence instance": "Import pages from a Confluence instance",
|
"Import pages from a Confluence instance": "Import pages from a Confluence instance",
|
||||||
"Coming soon": "Coming soon",
|
"Enterprise": "Enterprise",
|
||||||
"Recent imports": "Recent imports",
|
"Recent imports": "Recent imports",
|
||||||
"Everyone that has signed into Outline appears here. It’s possible that there are other users who have access through {team.signinMethods} but haven’t signed in yet.": "Everyone that has signed into Outline appears here. It’s possible that there are other users who have access through {team.signinMethods} but haven’t signed in yet.",
|
"Everyone that has signed into Outline appears here. It’s possible that there are other users who have access through {team.signinMethods} but haven’t signed in yet.": "Everyone that has signed into Outline appears here. It’s possible that there are other users who have access through {team.signinMethods} but haven’t signed in yet.",
|
||||||
"Filter": "Filter",
|
"Filter": "Filter",
|
||||||
|
|||||||
Reference in New Issue
Block a user