import { LoadingSpinner } from '@sourcegraph/react-loading-spinner';
import { upperFirst } from 'lodash';
import AddIcon from 'mdi-react/AddIcon';
import * as React from 'react';
import { Link } from 'react-router-dom';
import { concat, Subject, Subscription } from 'rxjs';
import { catchError, concatMap, map, tap } from 'rxjs/operators';
import { AccessTokenScopes } from '../../auth/accessToken';
import { gql, mutateGraphQL } from '../../backend/graphql';
import { Form } from '../../components/Form';
import { PageTitle } from '../../components/PageTitle';
import { SiteAdminAlert } from '../../site-admin/SiteAdminAlert';
import { eventLogger } from '../../tracking/eventLogger';
import { asError, createAggregateError, isErrorLike } from '../../util/errors';
function createAccessToken(user, scopes, note) {
    return mutateGraphQL(gql `
            mutation CreateAccessToken($user: ID!, $scopes: [String!]!, $note: String!) {
                createAccessToken(user: $user, scopes: $scopes, note: $note) {
                    id
                    token
                }
            }
        `, { user, scopes, note }).pipe(map(({ data, errors }) => {
        if (!data || !data.createAccessToken || (errors && errors.length > 0)) {
            eventLogger.log('CreateAccessTokenFailed');
            throw createAggregateError(errors);
        }
        eventLogger.log('AccessTokenCreated');
        return data.createAccessToken;
    }));
}
/**
 * A page with a form to create an access token for a user.
 */
export class UserAccountCreateAccessTokenPage extends React.PureComponent {
    constructor() {
        super(...arguments);
        this.state = {
            note: '',
            scopes: [AccessTokenScopes.UserAll],
        };
        this.submits = new Subject();
        this.componentUpdates = new Subject();
        this.subscriptions = new Subscription();
        this.onNoteChange = e => this.setState({ note: e.currentTarget.value });
        this.onScopesChange = e => {
            const checked = e.currentTarget.checked;
            const value = e.currentTarget.value;
            this.setState(prevState => ({
                scopes: checked ? [...prevState.scopes, value] : prevState.scopes.filter(s => s !== value),
            }));
        };
        this.onSubmit = e => this.submits.next(e);
    }
    componentDidMount() {
        eventLogger.logViewEvent('NewAccessToken');
        this.subscriptions.add(this.submits
            .pipe(tap(e => e.preventDefault()), concatMap(() => concat([{ creationOrError: 'loading' }], createAccessToken(this.props.user.id, this.state.scopes, this.state.note).pipe(tap(result => {
            // Go back to access tokens list page and display the token secret value.
            this.props.history.push(`${this.props.match.url.replace(/\/new$/, '')}`);
            this.props.onDidCreateAccessToken(result);
        }), map(result => ({ creationOrError: result })), catchError(error => [{ creationOrError: asError(error) }])))))
            .subscribe(stateUpdate => this.setState(stateUpdate), err => console.error(err)));
        this.componentUpdates.next(this.props);
    }
    componentWillReceiveProps(nextProps) {
        this.componentUpdates.next(nextProps);
    }
    componentWillUnmount() {
        this.subscriptions.unsubscribe();
    }
    render() {
        const siteAdminViewingOtherUser = this.props.authenticatedUser && this.props.authenticatedUser.id !== this.props.user.id;
        return (React.createElement("div", { className: "user-settings-create-access-token-page" },
            React.createElement(PageTitle, { title: "Create access token" }),
            React.createElement("h2", null, "New access token"),
            siteAdminViewingOtherUser && (React.createElement(SiteAdminAlert, { className: "sidebar__alert" },
                "Creating access token for other user ",
                React.createElement("strong", null, this.props.user.username))),
            React.createElement(Form, { onSubmit: this.onSubmit },
                React.createElement("div", { className: "form-group" },
                    React.createElement("label", { htmlFor: "user-settings-create-access-token-page__note" }, "Token description"),
                    React.createElement("input", { type: "text", className: "form-control", id: "user-settings-create-access-token-page__note", onChange: this.onNoteChange, required: true, autoFocus: true, placeholder: "Description" }),
                    React.createElement("small", { className: "form-help text-muted" }, "What's this token for?")),
                React.createElement("div", { className: "form-group" },
                    React.createElement("label", { className: "mb-1", htmlFor: "user-settings-create-access-token-page__note" }, "Token scope"),
                    React.createElement("div", null,
                        React.createElement("small", { className: "form-help text-muted" }, "Tokens with limited user scopes are not yet supported.")),
                    React.createElement("div", { className: "form-check" },
                        React.createElement("input", { className: "form-check-input", type: "checkbox", id: "user-settings-create-access-token-page__scope-user:all", checked: true, value: AccessTokenScopes.UserAll, onChange: this.onScopesChange, disabled: true }),
                        React.createElement("label", { className: "form-check-label", htmlFor: "user-settings-create-access-token-page__scope-user:all" },
                            React.createElement("strong", null, AccessTokenScopes.UserAll),
                            " \u2014 Full control of all resources accessible to the user account")),
                    this.props.user.siteAdmin && (React.createElement("div", { className: "form-check" },
                        React.createElement("input", { className: "form-check-input", type: "checkbox", id: "user-settings-create-access-token-page__scope-site-admin:sudo", checked: this.state.scopes.includes(AccessTokenScopes.SiteAdminSudo), value: AccessTokenScopes.SiteAdminSudo, onChange: this.onScopesChange }),
                        React.createElement("label", { className: "form-check-label", htmlFor: "user-settings-create-access-token-page__scope-site-admin:sudo" },
                            React.createElement("strong", null, AccessTokenScopes.SiteAdminSudo),
                            " \u2014 Ability to perform any action as any other user")))),
                React.createElement("button", { type: "submit", disabled: this.state.creationOrError === 'loading', className: "btn btn-success" },
                    this.state.creationOrError === 'loading' ? (React.createElement(LoadingSpinner, { className: "icon-inline" })) : (React.createElement(AddIcon, { className: "icon-inline" })),
                    ' ',
                    "Generate token"),
                React.createElement(Link, { className: "btn btn-secondary ml-1", to: `${this.props.match.url.replace(/\/new$/, '')}}` }, "Cancel")),
            isErrorLike(this.state.creationOrError) && (React.createElement("div", { className: "invite-form__alert alert alert-danger" },
                "Error: ",
                upperFirst(this.state.creationOrError.message)))));
    }
}
//# sourceMappingURL=UserAccountCreateAccessTokenPage.js.map