import { Button, Column, Dialog, ModalContext } from '@8base/boost'; import { ApolloClient, ApolloQueryResult } from 'apollo-client'; import debounce from 'lodash/debounce'; import React from 'react'; import { compose, withApollo } from 'react-apollo'; import { ChatContext, IChatContext, withContext } from 'context'; import { DialogForm, UsersBrowser } from 'shared/components'; import { FindOrCreateDmDocument, FindOrCreateDmMutation, FindOrCreateDmMutationVariables, UserContactsPreviewDocument, UserContactsPreviewQuery, UserDmsPreviewDocument, // UsersDmSearchDocument, UsersDmSearchQuery, } from 'shared/graphql/__generated__'; import { makeCancelable } from 'shared/utils'; import { IOption } from 'types'; import { getOperationName } from 'apollo-link'; import cssUtils from '../../../styles/utilities.css'; // -- TYPES interface IOpenDmDialogProps extends Pick< IChatContext, 'user' | 'setChannel' | 'usersFilter' | 'channelMembersFilter' > { client: ApolloClient; } interface IDialogContentProps extends IOpenDmDialogProps {} interface IDialogContentState { data: { users: IOption[]; }; userSearchText: string; usersList: UsersDmSearchQuery['usersList']; loadingOptions: boolean; submitting: boolean; } // -- CONSTANTS export const OPEN_DM_DIALOG_ID = 'OPEN_DM_DIALOG_ID'; const MAX_USERS_AMOUNT = 8; // -- COMPONENTS const cnUsersBrowser = { list: cssUtils['u-dialog-browser-list'], }; class DialogContent extends React.Component { static contextType = ModalContext; private onSearchDebounced: DialogContent['onSearch']; private currentRequest?: ReturnType; constructor(props: IDialogContentProps) { super(props); this.state = { data: { users: [], }, userSearchText: '', usersList: { items: [], }, loadingOptions: false, submitting: false, }; this.onSearchDebounced = debounce(this.onSearch, 200); } componentDidMount() { this.fetchUsers(this.state.userSearchText); } componentWillUnmount() { this.cancelCurrentRequest(); } render() { const { data, userSearchText, usersList, loadingOptions, submitting } = this.state; const disabled = data.users.length === 0; const availableUsers = usersList.items.filter( user => data.users.find(el => el.value === user.id) === undefined, ); return (
You can only invite {MAX_USERS_AMOUNT} users.
el.value), onChange: this.onSelectChange, }} options={data.users} loading={loadingOptions} onInputChange={this.onInputChange} inputValue={userSearchText} users={availableUsers} onItemSelect={this.onItemSelect} />
); } private onSubmit = async (e: any) => { e.preventDefault(); if (!this.props.user || this.state.submitting) { return; } const currentUserId = this.props.user.id; const usersIds = this.state.data.users.map(el => el.value); usersIds.push(currentUserId); this.setState({ submitting: true, }); const { data }: { data: FindOrCreateDmMutation } = await this.props.client.mutate< FindOrCreateDmMutation, FindOrCreateDmMutationVariables >({ mutation: FindOrCreateDmDocument, variables: { usersIds, channelMembersFilter: this.props.channelMembersFilter, }, refetchQueries: [getOperationName(UserDmsPreviewDocument) as string], }); this.setState({ submitting: false, }); if (!data.findOrCreateDM) { return; } const channelIdentity = data.findOrCreateDM.members.items.find( el => el.user.id === currentUserId, ); if (!channelIdentity) { return; } this.props.setChannel({ channelIdentityId: channelIdentity.id, }); this.closeModal(); }; private closeModal = () => { this.context.closeModal(OPEN_DM_DIALOG_ID); }; private onItemSelect = (option: IOption) => { this.setState(s => { if ( s.data.users.length === MAX_USERS_AMOUNT || s.data.users.find(el => el.value === option.value) ) { return null; } return { data: { ...s.data, users: [...s.data.users, option], }, }; }); }; private onSelectChange = (values: string[]) => { this.setState(s => ({ data: { ...s.data, users: Array.isArray(values) ? s.data.users.filter(el => values.includes(el.value)) : [], }, })); }; private onInputChange = (val: string, { action }: { action: string }) => { if (action !== 'input-change') { return; } this.setState({ userSearchText: val, }); this.onSearchDebounced(val); }; private onSearch = (text: string) => { this.cancelCurrentRequest(); this.fetchUsers(text); }; private fetchUsers(text: string) { const idNotIn = this.props.user ? [this.props.user.id] : []; this.setState({ loadingOptions: true, }); this.currentRequest = makeCancelable( this.props.client.query({ query: UserContactsPreviewDocument, variables: { filter: this.props.usersFilter, }, }), ); (this.currentRequest.promise as Promise>) .then(({ data }) => { this.setState({ usersList: data.usersList, loadingOptions: false, }); }) .catch(() => {}); } private cancelCurrentRequest() { if (this.currentRequest) { this.currentRequest.cancel(); } } } // -- MAIN function OpenDmDialog(props: IOpenDmDialogProps) { return ( ); } OpenDmDialog.id = OPEN_DM_DIALOG_ID; export default compose( withApollo, withContext({ context: ChatContext, keys: ['user', 'setChannel', 'usersFilter', 'channelMembersFilter'], }), )(OpenDmDialog);