import { upperFirst } from 'lodash';
import * as React from 'react';
import { Link } from 'react-router-dom';
import { Subject, Subscription } from 'rxjs';
import { catchError, distinctUntilChanged, filter, map, startWith, switchMap, tap } from 'rxjs/operators';
import { gql, queryGraphQL } from '../../backend/graphql';
import { FilteredConnection } from '../../components/FilteredConnection';
import { PageTitle } from '../../components/PageTitle';
import { eventLogger } from '../../tracking/eventLogger';
import { userURL } from '../../user';
import { asError, createAggregateError, isErrorLike } from '../../util/errors';
import { removeUserFromOrganization } from '../backend';
import { InviteForm } from '../invite/InviteForm';
class UserNode extends React.PureComponent {
    constructor() {
        super(...arguments);
        this.state = {
            removalOrError: null,
        };
        this.removes = new Subject();
        this.subscriptions = new Subscription();
        this.remove = () => this.removes.next();
    }
    get isSelf() {
        return this.props.authenticatedUser !== null && this.props.node.id === this.props.authenticatedUser.id;
    }
    componentDidMount() {
        this.subscriptions.add(this.removes
            .pipe(filter(() => window.confirm(this.isSelf ? 'Leave the organization?' : `Remove the user ${this.props.node.username}?`)), switchMap(() => removeUserFromOrganization({ user: this.props.node.id, organization: this.props.org.id }).pipe(catchError(error => [asError(error)]), map(c => ({ removalOrError: c || null })), tap(() => {
            if (this.props.onDidUpdate) {
                this.props.onDidUpdate();
            }
        }), startWith({ removalOrError: undefined }))))
            .subscribe(stateUpdate => {
            this.setState(stateUpdate);
        }, error => console.error(error)));
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        const loading = this.state.removalOrError === undefined;
        return (React.createElement("li", { className: "list-group-item py-2" },
            React.createElement("div", { className: "d-flex align-items-center justify-content-between" },
                React.createElement("div", null,
                    React.createElement(Link, { to: userURL(this.props.node.username) },
                        React.createElement("strong", null, this.props.node.username)),
                    this.props.node.displayName && (React.createElement(React.Fragment, null,
                        React.createElement("br", null),
                        React.createElement("span", { className: "text-muted" }, this.props.node.displayName)))),
                React.createElement("div", { className: "site-admin-detail-list__actions" }, this.props.authenticatedUser &&
                    this.props.org.viewerCanAdminister && (React.createElement("button", { className: "btn btn-secondary btn-sm site-admin-detail-list__action", onClick: this.remove, disabled: loading }, this.isSelf ? 'Leave organization' : 'Remove from organization')))),
            isErrorLike(this.state.removalOrError) && (React.createElement("div", { className: "alert alert-danger mt-2" }, upperFirst(this.state.removalOrError.message)))));
    }
}
/**
 * The organizations members page
 */
export class OrgMembersPage extends React.PureComponent {
    constructor(props) {
        super(props);
        this.orgChanges = new Subject();
        this.userUpdates = new Subject();
        this.subscriptions = new Subscription();
        this.onDidUpdateUser = () => this.userUpdates.next();
        this.onDidUpdateOrganizationMembers = () => this.userUpdates.next();
        this.fetchOrgMembers = () => queryGraphQL(gql `
                query OrganizationMembers($id: ID!) {
                    node(id: $id) {
                        ... on Org {
                            viewerCanAdminister
                            members {
                                nodes {
                                    id
                                    username
                                    displayName
                                    avatarURL
                                }
                                totalCount
                            }
                        }
                    }
                }
            `, { id: this.props.org.id }).pipe(map(({ data, errors }) => {
            if (!data || !data.node) {
                this.setState({ viewerCanAdminister: false });
                throw createAggregateError(errors);
            }
            const org = data.node;
            if (!org.members) {
                this.setState({ viewerCanAdminister: false });
                throw createAggregateError(errors);
            }
            this.setState({ viewerCanAdminister: org.viewerCanAdminister });
            return org.members;
        }));
        this.state = { viewerCanAdminister: props.org.viewerCanAdminister };
    }
    componentDidMount() {
        eventLogger.logViewEvent('OrgMembers', { organization: { org_name: this.props.org.name } });
        this.subscriptions.add(this.orgChanges.pipe(distinctUntilChanged((a, b) => a.id === b.id)).subscribe(org => {
            this.setState({ viewerCanAdminister: org.viewerCanAdminister });
            this.userUpdates.next();
        }));
    }
    componentWillReceiveProps(props) {
        if (props.org !== this.props.org) {
            this.orgChanges.next(props.org);
        }
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        const nodeProps = {
            org: Object.assign({}, this.props.org, { viewerCanAdminister: this.state.viewerCanAdminister }),
            authenticatedUser: this.props.authenticatedUser,
            onDidUpdate: this.onDidUpdateUser,
        };
        return (React.createElement("div", { className: "org-settings-members-page" },
            React.createElement(PageTitle, { title: `Members - ${this.props.org.name}` }),
            this.state.viewerCanAdminister && (React.createElement(InviteForm, { orgID: this.props.org.id, authenticatedUser: this.props.authenticatedUser, onOrganizationUpdate: this.props.onOrganizationUpdate, onDidUpdateOrganizationMembers: this.onDidUpdateOrganizationMembers })),
            React.createElement(FilteredConnection, { className: "list-group list-group-flush mt-3", noun: "member", pluralNoun: "members", queryConnection: this.fetchOrgMembers, nodeComponent: UserNode, nodeComponentProps: nodeProps, noShowMore: true, hideSearch: true, updates: this.userUpdates, history: this.props.history, location: this.props.location })));
    }
}
//# sourceMappingURL=OrgMembersPage.js.map