// @flow import * as React from 'react'; import { Link, withRouter, type RouterHistory } from 'react-router-dom'; import { observable, action } from 'mobx'; import { inject, observer } from 'mobx-react'; import { CloseIcon } from 'outline-icons'; import styled from 'styled-components'; import Flex from 'shared/components/Flex'; import Button from 'components/Button'; import Input from 'components/Input'; import CopyToClipboard from 'components/CopyToClipboard'; import Checkbox from 'components/Checkbox'; import HelpText from 'components/HelpText'; import Tooltip from 'components/Tooltip'; import NudeButton from 'components/NudeButton'; import UiStore from 'stores/UiStore'; import AuthStore from 'stores/AuthStore'; import UsersStore from 'stores/UsersStore'; import PoliciesStore from 'stores/PoliciesStore'; const MAX_INVITES = 20; type Props = { auth: AuthStore, users: UsersStore, history: RouterHistory, policies: PoliciesStore, ui: UiStore, onSubmit: () => void, }; type InviteRequest = { email: string, name: string, guest: boolean, }; @observer class Invite extends React.Component { @observable isSaving: boolean; @observable linkCopied: boolean = false; @observable invites: InviteRequest[] = [ { email: '', name: '', guest: false }, { email: '', name: '', guest: false }, { email: '', name: '', guest: false }, ]; handleSubmit = async (ev: SyntheticEvent<>) => { ev.preventDefault(); this.isSaving = true; try { await this.props.users.invite(this.invites); this.props.onSubmit(); this.props.ui.showToast('We sent out your invites!'); } catch (err) { this.props.ui.showToast(err.message); } finally { this.isSaving = false; } }; @action handleChange = (ev, index) => { this.invites[index][ev.target.name] = ev.target.value; }; @action handleGuestChange = (ev, index) => { this.invites[index][ev.target.name] = ev.target.checked; }; @action handleAdd = () => { if (this.invites.length >= MAX_INVITES) { this.props.ui.showToast( `Sorry, you can only send ${MAX_INVITES} invites at a time` ); } this.invites.push({ email: '', name: '', guest: false }); }; @action handleRemove = (ev: SyntheticEvent<>, index: number) => { ev.preventDefault(); this.invites.splice(index, 1); }; handleCopy = () => { this.linkCopied = true; this.props.ui.showToast('A link was copied to your clipboard'); }; render() { const { team, user } = this.props.auth; if (!team || !user) return null; const predictedDomain = user.email.split('@')[1]; const can = this.props.policies.abilities(team.id); return (
{team.guestSignin ? ( Invite team members or guests to join your knowledge base. Team members can sign in with {team.signinMethods} and guests can use their email address. ) : ( Invite team members to join your knowledge base. They will need to sign in with {team.signinMethods}.{' '} {can.update && ( As an admin you can also{' '} enable guest invites. )} )} {team.subdomain && ( Want a link to share directly with your team?    )} {this.invites.map((invite, index) => ( this.handleChange(ev, index)} placeholder={`example@${predictedDomain}`} value={invite.email} required={index === 0} autoFocus={index === 0} flex />    this.handleChange(ev, index)} value={invite.name} required={!!invite.email} flex /> {team.guestSignin && (    Guests can sign in with email and
do not require{' '} {team.signinMethods} accounts } placement="top" > this.handleGuestChange(ev, index)} checked={invite.guest} />
)} {index !== 0 && ( this.handleRemove(ev, index)}> )}
))} {this.invites.length <= MAX_INVITES ? ( ) : ( )}
); } } const CopyBlock = styled('div')` font-size: 14px; background: ${props => props.theme.secondaryBackground}; padding: 8px 16px 4px; border-radius: 8px; margin-bottom: 24px; input { background: ${props => props.theme.background}; border-radius: 4px; } `; const Guest = styled('div')` padding-top: 4px; margin: 0 4px 16px; align-self: flex-end; `; const Remove = styled('div')` margin-top: 6px; position: absolute; right: -32px; `; export default inject('auth', 'users', 'policies', 'ui')(withRouter(Invite));