mirror of
https://github.com/outline/outline.git
synced 2026-04-27 05:04:38 -05:00
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")}
|
||||
actions={
|
||||
<Button type="submit" disabled neutral>
|
||||
{t("Coming soon")}
|
||||
{t("Enterprise")}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -21,6 +21,7 @@ const FileOperationListItem = ({ fileOperation, handleDelete }: Props) => {
|
||||
const user = useCurrentUser();
|
||||
const theme = useTheme();
|
||||
const stateMapping = {
|
||||
complete: t("Completed"),
|
||||
creating: t("Processing"),
|
||||
expired: t("Expired"),
|
||||
uploading: t("Processing"),
|
||||
@@ -46,9 +47,7 @@ const FileOperationListItem = ({ fileOperation, handleDelete }: Props) => {
|
||||
image={iconMapping[fileOperation.state]}
|
||||
subtitle={
|
||||
<>
|
||||
{fileOperation.state !== "complete" && (
|
||||
<>{stateMapping[fileOperation.state]} • </>
|
||||
)}
|
||||
{stateMapping[fileOperation.state]} •
|
||||
{fileOperation.error && <>{fileOperation.error} • </>}
|
||||
{t(`{{userName}} requested`, {
|
||||
userName:
|
||||
|
||||
@@ -9,6 +9,7 @@ export default async function documentCreator({
|
||||
collectionId,
|
||||
parentDocumentId,
|
||||
templateDocument,
|
||||
importId,
|
||||
createdAt,
|
||||
// allows override for import
|
||||
updatedAt,
|
||||
@@ -26,6 +27,7 @@ export default async function documentCreator({
|
||||
publish?: boolean;
|
||||
collectionId: string;
|
||||
parentDocumentId?: string;
|
||||
importId?: string;
|
||||
templateDocument?: Document | null;
|
||||
publishedAt?: Date;
|
||||
template?: boolean;
|
||||
@@ -54,6 +56,7 @@ export default async function documentCreator({
|
||||
template,
|
||||
templateId,
|
||||
publishedAt,
|
||||
importId,
|
||||
title: templateDocument ? templateDocument.title : title,
|
||||
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 CollectionUser from "./CollectionUser";
|
||||
import Document from "./Document";
|
||||
import FileOperation from "./FileOperation";
|
||||
import Group from "./Group";
|
||||
import GroupUser from "./GroupUser";
|
||||
import Team from "./Team";
|
||||
@@ -272,6 +273,13 @@ class Collection extends ParanoidModel {
|
||||
|
||||
// associations
|
||||
|
||||
@BelongsTo(() => FileOperation, "importId")
|
||||
import: FileOperation | null;
|
||||
|
||||
@ForeignKey(() => FileOperation)
|
||||
@Column(DataType.UUID)
|
||||
importId: string | null;
|
||||
|
||||
@HasMany(() => Document, "collectionId")
|
||||
documents: Document[];
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import { DocumentValidation } from "@shared/validations";
|
||||
import slugify from "@server/utils/slugify";
|
||||
import Backlink from "./Backlink";
|
||||
import Collection from "./Collection";
|
||||
import FileOperation from "./FileOperation";
|
||||
import Revision from "./Revision";
|
||||
import Star from "./Star";
|
||||
import Team from "./Team";
|
||||
@@ -342,6 +343,13 @@ class Document extends ParanoidModel {
|
||||
|
||||
// associations
|
||||
|
||||
@BelongsTo(() => FileOperation, "importId")
|
||||
import: FileOperation | null;
|
||||
|
||||
@ForeignKey(() => FileOperation)
|
||||
@Column(DataType.UUID)
|
||||
importId: string | null;
|
||||
|
||||
@BelongsTo(() => Document, "parentDocumentId")
|
||||
parentDocument: Document | null;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ export default function present(data: FileOperation) {
|
||||
return {
|
||||
id: data.id,
|
||||
type: data.type,
|
||||
format: data.format,
|
||||
name: data.collection?.name || path.basename(data.key || ""),
|
||||
state: data.state,
|
||||
error: data.error,
|
||||
|
||||
@@ -274,6 +274,7 @@ export default abstract class ImportTask extends BaseTask<Props> {
|
||||
}),
|
||||
createdById: fileOperation.userId,
|
||||
permission: CollectionPermission.ReadWrite,
|
||||
importId: fileOperation.id,
|
||||
},
|
||||
transaction,
|
||||
});
|
||||
@@ -294,6 +295,7 @@ export default abstract class ImportTask extends BaseTask<Props> {
|
||||
createdById: fileOperation.userId,
|
||||
name,
|
||||
permission: CollectionPermission.ReadWrite,
|
||||
importId: fileOperation.id,
|
||||
},
|
||||
{ transaction }
|
||||
);
|
||||
@@ -357,6 +359,7 @@ export default abstract class ImportTask extends BaseTask<Props> {
|
||||
updatedAt: item.updatedAt ?? item.createdAt,
|
||||
publishedAt: item.updatedAt ?? item.createdAt ?? new Date(),
|
||||
parentDocumentId: item.parentDocumentId,
|
||||
importId: fileOperation.id,
|
||||
user,
|
||||
ip,
|
||||
transaction,
|
||||
|
||||
@@ -51,13 +51,13 @@ router.post(
|
||||
authorize(user, "manage", team);
|
||||
|
||||
const [exports, total] = await Promise.all([
|
||||
await FileOperation.findAll({
|
||||
FileOperation.findAll({
|
||||
where,
|
||||
order: [[sort, direction]],
|
||||
offset: ctx.state.pagination.offset,
|
||||
limit: ctx.state.pagination.limit,
|
||||
}),
|
||||
await FileOperation.count({
|
||||
FileOperation.count({
|
||||
where,
|
||||
}),
|
||||
]);
|
||||
|
||||
@@ -586,6 +586,7 @@
|
||||
"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",
|
||||
"File not supported – please upload a valid ZIP file": "File not supported – please upload a valid ZIP file",
|
||||
"Completed": "Completed",
|
||||
"Processing": "Processing",
|
||||
"Expired": "Expired",
|
||||
"Failed": "Failed",
|
||||
@@ -673,7 +674,7 @@
|
||||
"Import data": "Import data",
|
||||
"Import pages exported from Notion": "Import pages exported from Notion",
|
||||
"Import pages from a Confluence instance": "Import pages from a Confluence instance",
|
||||
"Coming soon": "Coming soon",
|
||||
"Enterprise": "Enterprise",
|
||||
"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.",
|
||||
"Filter": "Filter",
|
||||
|
||||
Reference in New Issue
Block a user