feat: Memberships (#1032)
* WIP * feat: Add collection.memberships endpoint * feat: Add ability to filter collection.memberships with query * WIP * Merge stashed work * feat: Add ability to filter memberships by permission * continued refactoring * paginated list component * Collection member management * fix: Incorrect policy data sent down after collection.update * Reduce duplication, add empty state * cleanup * fix: Modal close should be a real button * fix: Allow opening edit from modal * fix: remove unused methods * test: fix * Passing test suite * Refactor * fix: Flow UI errors * test: Add collections.update tests * lint * test: moar tests * fix: Missing scopes, more missing tests * fix: Handle collection privacy change over socket * fix: More membership scopes * fix: view endpoint permissions * fix: respond to privacy change on socket event * policy driven menus * fix: share endpoint policies * chore: Use policies to drive documents UI * alignment * fix: Header height * fix: Correct behavior when collection becomes private * fix: Header height for read-only collection * send id's over socket instead of serialized objects * fix: Remote policy change * fix: reduce collection fetching * More websocket efficiencies * fix: Document collection pinning * fix: Restored ability to edit drafts fix: Removed ability to star drafts * fix: Require write permissions to pin doc to collection * fix: Header title overlaying document actions at small screen sizes * fix: Jank on load caused by previous commit * fix: Double collection fetch post-publish * fix: Hide publish button if draft is in no longer accessible collection * fix: Always allow deleting drafts fix: Improved handling of deleted documents * feat: Show collections in drafts view feat: Show more obvious 'draft' badge on documents * fix: incorrect policies after publish to private collection * fix: Duplicating a draft publishes it
This commit is contained in:
@@ -3,12 +3,12 @@ import * as React from 'react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { observable } from 'mobx';
|
||||
import { inject, observer } from 'mobx-react';
|
||||
import { MoreIcon } from 'outline-icons';
|
||||
|
||||
import Document from 'models/Document';
|
||||
import UiStore from 'stores/UiStore';
|
||||
import AuthStore from 'stores/AuthStore';
|
||||
import CollectionStore from 'stores/CollectionsStore';
|
||||
import PoliciesStore from 'stores/PoliciesStore';
|
||||
import {
|
||||
documentMoveUrl,
|
||||
documentEditUrl,
|
||||
@@ -16,7 +16,6 @@ import {
|
||||
newDocumentUrl,
|
||||
} from 'utils/routeHelpers';
|
||||
import { DropdownMenu, DropdownMenuItem } from 'components/DropdownMenu';
|
||||
import NudeButton from 'components/NudeButton';
|
||||
|
||||
type Props = {
|
||||
ui: UiStore,
|
||||
@@ -24,6 +23,7 @@ type Props = {
|
||||
position?: 'left' | 'right' | 'center',
|
||||
document: Document,
|
||||
collections: CollectionStore,
|
||||
policies: PoliciesStore,
|
||||
className: string,
|
||||
showPrint?: boolean,
|
||||
showToggleEmbeds?: boolean,
|
||||
@@ -111,6 +111,7 @@ class DocumentMenu extends React.Component<Props> {
|
||||
if (this.redirectTo) return <Redirect to={this.redirectTo} push />;
|
||||
|
||||
const {
|
||||
policies,
|
||||
document,
|
||||
position,
|
||||
className,
|
||||
@@ -120,110 +121,94 @@ class DocumentMenu extends React.Component<Props> {
|
||||
onOpen,
|
||||
onClose,
|
||||
} = this.props;
|
||||
const canShareDocuments = auth.team && auth.team.sharing;
|
||||
|
||||
if (document.isArchived) {
|
||||
return (
|
||||
<DropdownMenu
|
||||
label={
|
||||
<NudeButton>
|
||||
<MoreIcon />
|
||||
</NudeButton>
|
||||
}
|
||||
className={className}
|
||||
>
|
||||
<DropdownMenuItem onClick={this.handleRestore}>
|
||||
Restore
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={this.handleDelete}>
|
||||
Delete…
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
const can = policies.abilities(document.id);
|
||||
const canShareDocuments = can.share && auth.team && auth.team.sharing;
|
||||
|
||||
return (
|
||||
<DropdownMenu
|
||||
label={
|
||||
<NudeButton>
|
||||
<MoreIcon />
|
||||
</NudeButton>
|
||||
}
|
||||
className={className}
|
||||
position={position}
|
||||
onOpen={onOpen}
|
||||
onClose={onClose}
|
||||
>
|
||||
{!document.isDraft ? (
|
||||
<React.Fragment>
|
||||
{showPin &&
|
||||
(document.pinned ? (
|
||||
{can.unarchive && (
|
||||
<DropdownMenuItem onClick={this.handleRestore}>
|
||||
Restore
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{showPin &&
|
||||
(document.pinned
|
||||
? can.unpin && (
|
||||
<DropdownMenuItem onClick={this.handleUnpin}>
|
||||
Unpin
|
||||
</DropdownMenuItem>
|
||||
) : (
|
||||
)
|
||||
: can.pin && (
|
||||
<DropdownMenuItem onClick={this.handlePin}>
|
||||
Pin to collection
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
{document.isStarred ? (
|
||||
{document.isStarred
|
||||
? can.unstar && (
|
||||
<DropdownMenuItem onClick={this.handleUnstar}>
|
||||
Unstar
|
||||
</DropdownMenuItem>
|
||||
) : (
|
||||
)
|
||||
: can.star && (
|
||||
<DropdownMenuItem onClick={this.handleStar}>
|
||||
Star
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{canShareDocuments && (
|
||||
<DropdownMenuItem
|
||||
onClick={this.handleShareLink}
|
||||
title="Create a public share link"
|
||||
>
|
||||
Share link…
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<hr />
|
||||
<DropdownMenuItem onClick={this.handleDocumentHistory}>
|
||||
Document history
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={this.handleNewChild}
|
||||
title="Create a new child document for the current document"
|
||||
>
|
||||
New child document
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={this.handleEdit}>Edit</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={this.handleDuplicate}>
|
||||
Duplicate
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={this.handleArchive}>
|
||||
Archive
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={this.handleDelete}>
|
||||
Delete…
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={this.handleMove}>Move…</DropdownMenuItem>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<React.Fragment>
|
||||
{canShareDocuments && (
|
||||
<DropdownMenuItem
|
||||
onClick={this.handleShareLink}
|
||||
title="Create a public share link"
|
||||
>
|
||||
Share link…
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuItem onClick={this.handleDelete}>
|
||||
Delete…
|
||||
</DropdownMenuItem>
|
||||
</React.Fragment>
|
||||
{canShareDocuments && (
|
||||
<DropdownMenuItem
|
||||
onClick={this.handleShareLink}
|
||||
title="Create a public share link"
|
||||
>
|
||||
Share link…
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
<hr />
|
||||
<DropdownMenuItem onClick={this.handleExport}>
|
||||
Download
|
||||
</DropdownMenuItem>
|
||||
{can.read && (
|
||||
<DropdownMenuItem onClick={this.handleDocumentHistory}>
|
||||
Document history
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{can.update && (
|
||||
<DropdownMenuItem
|
||||
onClick={this.handleNewChild}
|
||||
title="Create a new child document for the current document"
|
||||
>
|
||||
New child document
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{can.update && (
|
||||
<DropdownMenuItem onClick={this.handleEdit}>Edit</DropdownMenuItem>
|
||||
)}
|
||||
{can.update && (
|
||||
<DropdownMenuItem onClick={this.handleDuplicate}>
|
||||
Duplicate
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{can.archive && (
|
||||
<DropdownMenuItem onClick={this.handleArchive}>
|
||||
Archive
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{can.delete && (
|
||||
<DropdownMenuItem onClick={this.handleDelete}>
|
||||
Delete…
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{can.move && (
|
||||
<DropdownMenuItem onClick={this.handleMove}>Move…</DropdownMenuItem>
|
||||
)}
|
||||
<hr />
|
||||
{can.download && (
|
||||
<DropdownMenuItem onClick={this.handleExport}>
|
||||
Download
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
{showPrint && (
|
||||
<DropdownMenuItem onClick={window.print}>Print</DropdownMenuItem>
|
||||
)}
|
||||
@@ -232,4 +217,4 @@ class DocumentMenu extends React.Component<Props> {
|
||||
}
|
||||
}
|
||||
|
||||
export default inject('ui', 'auth', 'collections')(DocumentMenu);
|
||||
export default inject('ui', 'auth', 'collections', 'policies')(DocumentMenu);
|
||||
|
||||
Reference in New Issue
Block a user