2018-10-13 20:14:46 +00:00
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
|
import React from 'react';
|
2019-05-14 17:50:33 +00:00
|
|
|
|
|
2020-04-26 09:40:00 +00:00
|
|
|
|
import Button from '../../../common/Button';
|
2020-05-26 20:17:24 +00:00
|
|
|
|
import { PlusIcon } from '../../../common/icons';
|
2019-05-15 10:11:58 +00:00
|
|
|
|
import CopyableInput from '../../IDE/components/CopyableInput';
|
2019-05-14 17:50:33 +00:00
|
|
|
|
|
2019-05-15 10:11:58 +00:00
|
|
|
|
import APIKeyList from './APIKeyList';
|
2019-05-14 18:12:52 +00:00
|
|
|
|
|
2019-05-15 10:11:58 +00:00
|
|
|
|
export const APIKeyPropType = PropTypes.shape({
|
2020-07-24 21:11:10 +00:00
|
|
|
|
id: PropTypes.object.isRequired, // eslint-disable-line
|
|
|
|
|
token: PropTypes.object, // eslint-disable-line
|
2019-05-15 10:11:58 +00:00
|
|
|
|
label: PropTypes.string.isRequired,
|
2019-05-15 10:28:18 +00:00
|
|
|
|
createdAt: PropTypes.string.isRequired,
|
|
|
|
|
lastUsedAt: PropTypes.string,
|
2019-05-15 10:11:58 +00:00
|
|
|
|
});
|
2018-10-13 20:14:46 +00:00
|
|
|
|
|
|
|
|
|
class APIKeyForm extends React.Component {
|
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = { keyLabel: '' };
|
|
|
|
|
|
|
|
|
|
this.addKey = this.addKey.bind(this);
|
2019-05-14 17:50:33 +00:00
|
|
|
|
this.removeKey = this.removeKey.bind(this);
|
|
|
|
|
this.renderApiKeys = this.renderApiKeys.bind(this);
|
2018-10-13 20:14:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addKey(event) {
|
|
|
|
|
event.preventDefault();
|
2019-05-14 17:50:33 +00:00
|
|
|
|
const { keyLabel } = this.state;
|
|
|
|
|
|
|
|
|
|
this.setState({
|
2020-07-24 21:11:10 +00:00
|
|
|
|
keyLabel: '',
|
2019-05-14 17:50:33 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.props.createApiKey(keyLabel);
|
|
|
|
|
|
2018-10-13 20:14:46 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-14 17:50:33 +00:00
|
|
|
|
removeKey(key) {
|
|
|
|
|
const message = `Are you sure you want to delete "${key.label}"?`;
|
|
|
|
|
|
|
|
|
|
if (window.confirm(message)) {
|
|
|
|
|
this.props.removeApiKey(key.id);
|
|
|
|
|
}
|
2018-10-13 20:14:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-14 17:50:33 +00:00
|
|
|
|
renderApiKeys() {
|
|
|
|
|
const hasApiKeys = this.props.apiKeys && this.props.apiKeys.length > 0;
|
|
|
|
|
|
|
|
|
|
if (hasApiKeys) {
|
|
|
|
|
return (
|
2019-05-15 10:11:58 +00:00
|
|
|
|
<APIKeyList apiKeys={this.props.apiKeys} onRemove={this.removeKey} />
|
2019-05-14 09:25:14 +00:00
|
|
|
|
);
|
2019-05-14 17:50:33 +00:00
|
|
|
|
}
|
2019-05-15 10:11:58 +00:00
|
|
|
|
return <p>You have no exsiting tokens.</p>;
|
2019-05-14 17:50:33 +00:00
|
|
|
|
}
|
2019-05-14 09:25:14 +00:00
|
|
|
|
|
2019-05-14 17:50:33 +00:00
|
|
|
|
render() {
|
2019-05-15 10:11:58 +00:00
|
|
|
|
const keyWithToken = this.props.apiKeys.find(k => !!k.token);
|
|
|
|
|
|
2019-05-14 09:25:14 +00:00
|
|
|
|
return (
|
2019-05-15 10:11:58 +00:00
|
|
|
|
<div className="api-key-form">
|
2019-05-15 14:25:58 +00:00
|
|
|
|
<p className="api-key-form__summary">
|
|
|
|
|
Personal Access Tokens act like your password to allow automated
|
2020-07-24 21:11:10 +00:00
|
|
|
|
scripts to access the Editor API. Create a token for each script that
|
|
|
|
|
needs access.
|
2019-05-15 14:25:58 +00:00
|
|
|
|
</p>
|
2019-05-15 10:11:58 +00:00
|
|
|
|
|
|
|
|
|
<div className="api-key-form__section">
|
|
|
|
|
<h3 className="api-key-form__title">Create new token</h3>
|
|
|
|
|
<form className="form form--inline" onSubmit={this.addKey}>
|
2020-07-24 21:11:10 +00:00
|
|
|
|
<label
|
|
|
|
|
htmlFor="keyLabel"
|
|
|
|
|
className="form__label form__label--hidden "
|
|
|
|
|
>
|
|
|
|
|
What is this token for?
|
|
|
|
|
</label>
|
2019-05-15 10:11:58 +00:00
|
|
|
|
<input
|
|
|
|
|
className="form__input"
|
|
|
|
|
id="keyLabel"
|
2020-07-24 21:11:10 +00:00
|
|
|
|
onChange={(event) => {
|
|
|
|
|
this.setState({ keyLabel: event.target.value });
|
|
|
|
|
}}
|
2019-05-15 10:11:58 +00:00
|
|
|
|
placeholder="What is this token for? e.g. Example import script"
|
|
|
|
|
type="text"
|
|
|
|
|
value={this.state.keyLabel}
|
|
|
|
|
/>
|
2020-04-26 09:40:00 +00:00
|
|
|
|
<Button
|
2019-05-15 10:11:58 +00:00
|
|
|
|
disabled={this.state.keyLabel === ''}
|
2020-05-19 16:31:36 +00:00
|
|
|
|
iconBefore={<PlusIcon />}
|
2020-04-26 09:40:00 +00:00
|
|
|
|
label="Create new key"
|
2020-05-19 16:31:36 +00:00
|
|
|
|
type="submit"
|
2019-05-15 10:11:58 +00:00
|
|
|
|
>
|
2020-05-19 16:31:36 +00:00
|
|
|
|
Create
|
2020-04-26 09:40:00 +00:00
|
|
|
|
</Button>
|
2019-05-15 10:11:58 +00:00
|
|
|
|
</form>
|
|
|
|
|
|
2020-07-24 21:11:10 +00:00
|
|
|
|
{keyWithToken && (
|
|
|
|
|
<div className="api-key-form__new-token">
|
|
|
|
|
<h4 className="api-key-form__new-token__title">
|
|
|
|
|
Your new access token
|
|
|
|
|
</h4>
|
|
|
|
|
<p className="api-key-form__new-token__info">
|
|
|
|
|
Make sure to copy your new personal access token now. You won’t
|
|
|
|
|
be able to see it again!
|
|
|
|
|
</p>
|
|
|
|
|
<CopyableInput
|
|
|
|
|
label={keyWithToken.label}
|
|
|
|
|
value={keyWithToken.token}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2019-05-15 10:11:58 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="api-key-form__section">
|
|
|
|
|
<h3 className="api-key-form__title">Existing tokens</h3>
|
|
|
|
|
{this.renderApiKeys()}
|
|
|
|
|
</div>
|
2018-10-13 20:14:46 +00:00
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
APIKeyForm.propTypes = {
|
2019-05-15 10:11:58 +00:00
|
|
|
|
apiKeys: PropTypes.arrayOf(PropTypes.shape(APIKeyPropType)).isRequired,
|
2019-05-14 09:25:14 +00:00
|
|
|
|
createApiKey: PropTypes.func.isRequired,
|
2018-10-15 22:22:56 +00:00
|
|
|
|
removeApiKey: PropTypes.func.isRequired,
|
2018-10-13 20:14:46 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default APIKeyForm;
|