Files
outline/app/scenes/CollectionPermissions/AddGroupsToCollection.tsx
Tom Moor 212985e18f feat: Allow viewers to be upgraded to editors on individual collections (#4023)
* Improve types

* More types, fix default permission for viewers added to collection

* fix change of default role for CollectionGroup

* Restore policy

* test

* tests
2022-08-30 23:12:27 -07:00

153 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { debounce } from "lodash";
import { observable } from "mobx";
import { observer } from "mobx-react";
import * as React from "react";
import { withTranslation, WithTranslation } from "react-i18next";
import styled from "styled-components";
import RootStore from "~/stores/RootStore";
import Collection from "~/models/Collection";
import Group from "~/models/Group";
import GroupNew from "~/scenes/GroupNew";
import Button from "~/components/Button";
import ButtonLink from "~/components/ButtonLink";
import Empty from "~/components/Empty";
import Flex from "~/components/Flex";
import GroupListItem from "~/components/GroupListItem";
import Input from "~/components/Input";
import Modal from "~/components/Modal";
import PaginatedList from "~/components/PaginatedList";
import Text from "~/components/Text";
import withStores from "~/components/withStores";
type Props = WithTranslation &
RootStore & {
collection: Collection;
onSubmit: () => void;
};
@observer
class AddGroupsToCollection extends React.Component<Props> {
@observable
newGroupModalOpen = false;
@observable
query = "";
handleNewGroupModalOpen = () => {
this.newGroupModalOpen = true;
};
handleNewGroupModalClose = () => {
this.newGroupModalOpen = false;
};
handleFilter = (ev: React.ChangeEvent<HTMLInputElement>) => {
this.query = ev.target.value;
this.debouncedFetch();
};
debouncedFetch = debounce(() => {
this.props.groups.fetchPage({
query: this.query,
});
}, 250);
handleAddGroup = (group: Group) => {
const { t } = this.props;
try {
this.props.collectionGroupMemberships.create({
collectionId: this.props.collection.id,
groupId: group.id,
});
this.props.toasts.showToast(
t("{{ groupName }} was added to the collection", {
groupName: group.name,
}),
{
type: "success",
}
);
} catch (err) {
this.props.toasts.showToast(t("Could not add user"), {
type: "error",
});
console.error(err);
}
};
render() {
const { groups, policies, collection, auth, t } = this.props;
const { user, team } = auth;
if (!user || !team) {
return null;
}
const can = policies.abilities(team.id);
return (
<Flex column>
{can.createGroup && (
<Text type="secondary">
{t("Cant find the group youre looking for?")}{" "}
<ButtonLink onClick={this.handleNewGroupModalOpen}>
{t("Create a group")}
</ButtonLink>
.
</Text>
)}
<Input
type="search"
placeholder={`${t("Search by group name")}`}
value={this.query}
onChange={this.handleFilter}
label={t("Search groups")}
labelHidden
flex
/>
<PaginatedList
empty={
this.query ? (
<Empty>{t("No groups matching your search")}</Empty>
) : (
<Empty>{t("No groups left to add")}</Empty>
)
}
items={groups.notInCollection(collection.id, this.query)}
fetch={this.query ? undefined : groups.fetchPage}
renderItem={(item: Group) => (
<GroupListItem
key={item.id}
group={item}
showFacepile
renderActions={() => (
<ButtonWrap>
<Button onClick={() => this.handleAddGroup(item)} neutral>
{t("Add")}
</Button>
</ButtonWrap>
)}
/>
)}
/>
{can.createGroup && (
<Modal
title={t("Create a group")}
onRequestClose={this.handleNewGroupModalClose}
isOpen={this.newGroupModalOpen}
>
<GroupNew onSubmit={this.handleNewGroupModalClose} />
</Modal>
)}
</Flex>
);
}
}
const ButtonWrap = styled.div`
margin-left: 6px;
`;
export default withTranslation()(withStores(AddGroupsToCollection));