mirror of
https://github.com/outline/outline.git
synced 2026-06-13 19:35:02 +03:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e028e9799 |
@@ -114,17 +114,6 @@ function MainSidebar() {
|
||||
exact={false}
|
||||
label={t("Starred")}
|
||||
/>
|
||||
{can.createDocument && (
|
||||
<SidebarLink
|
||||
to="/templates"
|
||||
icon={<ShapesIcon color="currentColor" />}
|
||||
exact={false}
|
||||
label={t("Templates")}
|
||||
active={
|
||||
documents.active ? documents.active.template : undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{can.createDocument && (
|
||||
<SidebarLink
|
||||
to="/drafts"
|
||||
@@ -171,6 +160,17 @@ function MainSidebar() {
|
||||
documents.active ? documents.active.isDeleted : undefined
|
||||
}
|
||||
/>
|
||||
{can.createDocument && (
|
||||
<SidebarLink
|
||||
to="/templates"
|
||||
icon={<ShapesIcon color="currentColor" />}
|
||||
exact={false}
|
||||
label={t("Templates")}
|
||||
active={
|
||||
documents.active ? documents.active.template : undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<SidebarLink
|
||||
to="/settings"
|
||||
icon={<SettingsIcon color="currentColor" />}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
import fractionalIndex from "fractional-index";
|
||||
import { observer } from "mobx-react";
|
||||
import { PlusIcon } from "outline-icons";
|
||||
import { PlusIcon, DocumentIcon } from "outline-icons";
|
||||
import * as React from "react";
|
||||
import { useDrop } from "react-dnd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -10,10 +10,12 @@ import Flex from "components/Flex";
|
||||
import useStores from "../../../hooks/useStores";
|
||||
import CollectionLink from "./CollectionLink";
|
||||
import CollectionsLoading from "./CollectionsLoading";
|
||||
import DocumentLink from "./DocumentLink";
|
||||
import DropCursor from "./DropCursor";
|
||||
import Header from "./Header";
|
||||
import SidebarLink from "./SidebarLink";
|
||||
import useCurrentTeam from "hooks/useCurrentTeam";
|
||||
import { newDocumentUrl } from "utils/routeHelpers";
|
||||
type Props = {
|
||||
onCreateCollection: () => void,
|
||||
};
|
||||
@@ -22,6 +24,7 @@ function Collections({ onCreateCollection }: Props) {
|
||||
const [isFetching, setFetching] = React.useState(false);
|
||||
const [fetchError, setFetchError] = React.useState();
|
||||
const { ui, policies, documents, collections } = useStores();
|
||||
const personalCollection = collections.personal;
|
||||
const isPreloaded: boolean = !!collections.orderedData.length;
|
||||
const { t } = useTranslation();
|
||||
const team = useCurrentTeam();
|
||||
@@ -98,6 +101,32 @@ function Collections({ onCreateCollection }: Props) {
|
||||
exact
|
||||
/>
|
||||
)}
|
||||
|
||||
{personalCollection && (
|
||||
<>
|
||||
<br />
|
||||
<Header>{t("Personal")}</Header>
|
||||
{personalCollection.documents.map((node, index) => (
|
||||
<DocumentLink
|
||||
key={node.id}
|
||||
node={node}
|
||||
collection={personalCollection}
|
||||
activeDocument={documents.active}
|
||||
prefetchDocument={documents.prefetchDocument}
|
||||
icon={node.children.length ? undefined : <DocumentIcon />}
|
||||
depth={node.children.length ? 1.5 : 0}
|
||||
canUpdate
|
||||
index={index}
|
||||
/>
|
||||
))}
|
||||
<SidebarLink
|
||||
to={newDocumentUrl(personalCollection.id)}
|
||||
icon={<PlusIcon color="currentColor" />}
|
||||
label={`${t("New document")}…`}
|
||||
exact
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ type Props = {|
|
||||
prefetchDocument: (documentId: string) => Promise<void>,
|
||||
depth: number,
|
||||
index: number,
|
||||
icon?: React.Node,
|
||||
parentId?: string,
|
||||
|};
|
||||
|
||||
@@ -35,6 +36,7 @@ function DocumentLink({
|
||||
prefetchDocument,
|
||||
depth,
|
||||
index,
|
||||
icon,
|
||||
parentId,
|
||||
}: Props) {
|
||||
const { documents, policies } = useStores();
|
||||
@@ -236,6 +238,7 @@ function DocumentLink({
|
||||
depth={depth}
|
||||
exact={false}
|
||||
showActions={menuOpen}
|
||||
icon={icon}
|
||||
menu={
|
||||
document && !isMoving ? (
|
||||
<Fade>
|
||||
@@ -264,7 +267,7 @@ function DocumentLink({
|
||||
node={childNode}
|
||||
activeDocument={activeDocument}
|
||||
prefetchDocument={prefetchDocument}
|
||||
depth={depth + 1}
|
||||
depth={(depth || 1) + 1}
|
||||
canUpdate={canUpdate}
|
||||
index={index}
|
||||
parentId={node.id}
|
||||
|
||||
@@ -16,6 +16,7 @@ export default class Collection extends BaseModel {
|
||||
icon: string;
|
||||
color: string;
|
||||
permission: "read" | "read_write" | void;
|
||||
isPersonal: boolean;
|
||||
sharing: boolean;
|
||||
index: string;
|
||||
documents: NavigationNode[];
|
||||
|
||||
@@ -27,6 +27,7 @@ function DocumentNew() {
|
||||
|
||||
const document = await documents.create({
|
||||
collectionId: collection.id,
|
||||
publish: collection.isPersonal,
|
||||
parentDocumentId: params.parentDocumentId,
|
||||
templateId: params.templateId,
|
||||
template: params.template,
|
||||
|
||||
@@ -31,12 +31,17 @@ export default class CollectionsStore extends BaseStore<Collection> {
|
||||
: undefined;
|
||||
}
|
||||
|
||||
@computed
|
||||
get personal(): ?Collection {
|
||||
return Array.from(this.data.values()).find((c) => c.isPersonal);
|
||||
}
|
||||
|
||||
@computed
|
||||
get orderedData(): Collection[] {
|
||||
let collections = Array.from(this.data.values());
|
||||
|
||||
collections = collections.filter((collection) =>
|
||||
collection.deletedAt ? false : true
|
||||
collections = collections.filter(
|
||||
(collection) => !collection.deletedAt && !collection.isPersonal
|
||||
);
|
||||
|
||||
return collections.sort((a, b) => {
|
||||
|
||||
@@ -609,6 +609,20 @@ router.post("collections.list", auth(), pagination(), async (ctx) => {
|
||||
limit: ctx.state.pagination.limit,
|
||||
});
|
||||
|
||||
const personalCollection = collections.find((c) => c.isPersonal);
|
||||
if (!personalCollection) {
|
||||
const personalCollection = await Collection.create({
|
||||
name: user.name,
|
||||
teamId: user.teamId,
|
||||
createdById: user.id,
|
||||
isPersonal: true,
|
||||
sort: Collection.DEFAULT_SORT,
|
||||
permission: null,
|
||||
});
|
||||
|
||||
collections.push(personalCollection);
|
||||
}
|
||||
|
||||
const nullIndexCollection = collections.findIndex(
|
||||
(collection) => collection.index === null
|
||||
);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
up: async (queryInterface, Sequelize) => {
|
||||
await queryInterface.addColumn("collections", "isPersonal", {
|
||||
type: Sequelize.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false,
|
||||
});
|
||||
},
|
||||
|
||||
down: async (queryInterface, Sequelize) => {
|
||||
await queryInterface.removeColumn("collections", "isPersonal");
|
||||
}
|
||||
};
|
||||
@@ -25,6 +25,11 @@ const Collection = sequelize.define(
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: null,
|
||||
},
|
||||
isPersonal: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
allowNull: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
permission: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: null,
|
||||
|
||||
@@ -100,7 +100,7 @@ User.prototype.collectionIds = async function (options = {}) {
|
||||
const collectionStubs = await Collection.scope({
|
||||
method: ["withMembership", this.id],
|
||||
}).findAll({
|
||||
attributes: ["id", "permission"],
|
||||
attributes: ["id", "permission", "isPersonal"],
|
||||
where: { teamId: this.teamId },
|
||||
paranoid: true,
|
||||
...options,
|
||||
@@ -111,6 +111,7 @@ User.prototype.collectionIds = async function (options = {}) {
|
||||
(c) =>
|
||||
c.permission === "read" ||
|
||||
c.permission === "read_write" ||
|
||||
(c.isPersonal && c.createdById === this.id) ||
|
||||
c.memberships.length > 0 ||
|
||||
c.collectionGroupMemberships.length > 0
|
||||
)
|
||||
|
||||
@@ -32,6 +32,7 @@ export default function present(collection: Collection) {
|
||||
index: collection.index,
|
||||
color: collection.color || "#4E5C6E",
|
||||
permission: collection.permission,
|
||||
isPersonal: collection.isPersonal,
|
||||
sharing: collection.sharing,
|
||||
createdAt: collection.createdAt,
|
||||
updatedAt: collection.updatedAt,
|
||||
|
||||
Reference in New Issue
Block a user