PLT-6965 jira integration (plus plugin scaffolding) (#6918)

* plugin scaffolding / jira integration

* add vendored testify packages

* webhook fix

* don't change i18n ids

* support configuration watching

* add basic jira plugin configuration to admin console

* fix eslint errors

* fix another eslint warning

* polish

* undo unintentional config.json commit >:(

* test fix

* add jira plugin diagnostics, remove dm support, add bot tag, generate web-safe secrets

* rebase, implement requested changes

* requested changes

* remove tests and minimize makefile change

* add missing license headers

* add missing comma

* remove bad line from Makefile
Этот коммит содержится в:
Chris
2017-08-02 01:36:54 -07:00
коммит произвёл GitHub
родитель c6bf235ec2
Коммит 65817e13c7
24 изменённых файлов: 891 добавлений и 33 удалений

Просмотреть файл

@@ -522,6 +522,15 @@ export default class AdminSidebar extends React.Component {
/>
}
/>
<AdminSidebarSection
name='jira'
title={
<FormattedMessage
id='admin.sidebar.jira'
defaultMessage='JIRA (Beta)'
/>
}
/>
{webrtcSettings}
<AdminSidebarSection
name='external'

Просмотреть файл

@@ -20,7 +20,8 @@ export default class GeneratedSetting extends React.Component {
disabled: PropTypes.bool.isRequired,
disabledText: PropTypes.node,
helpText: PropTypes.node.isRequired,
regenerateText: PropTypes.node
regenerateText: PropTypes.node,
regenerateHelpText: PropTypes.node
};
}
@@ -58,6 +59,15 @@ export default class GeneratedSetting extends React.Component {
);
}
let regenerateHelpText = null;
if (this.props.regenerateHelpText) {
regenerateHelpText = (
<div className='help-text'>
{this.props.regenerateHelpText}
</div>
);
}
return (
<div className='form-group'>
<label
@@ -88,6 +98,7 @@ export default class GeneratedSetting extends React.Component {
{this.props.regenerateText}
</button>
</div>
{regenerateHelpText}
</div>
</div>
);

Просмотреть файл

@@ -80,7 +80,12 @@ export default class SuggestionBox extends React.Component {
/**
* Function called when @mention is clicked
*/
popoverMentionKeyClick: PropTypes.bool
popoverMentionKeyClick: PropTypes.bool,
/**
* The number of characters required to show the suggestion list, defaults to 1
*/
requiredCharacters: PropTypes.number
}
static defaultProps = {
@@ -88,13 +93,15 @@ export default class SuggestionBox extends React.Component {
listStyle: 'top',
renderDividers: false,
completeOnTab: true,
isRHS: false
isRHS: false,
requiredCharacters: 1
}
constructor(props) {
super(props);
this.handleBlur = this.handleBlur.bind(this);
this.handleFocus = this.handleFocus.bind(this);
this.handlePopoverMentionKeyClick = this.handlePopoverMentionKeyClick.bind(this);
this.handleCompleteWord = this.handleCompleteWord.bind(this);
@@ -163,11 +170,22 @@ export default class SuggestionBox extends React.Component {
}
}
handleFocus() {
setTimeout(() => {
const textbox = this.getTextbox();
const pretext = textbox.value.substring(0, textbox.selectionEnd);
if (pretext.length >= this.props.requiredCharacters) {
GlobalActions.emitSuggestionPretextChanged(this.suggestionId, pretext);
}
});
}
handleChange(e) {
const textbox = this.getTextbox();
const pretext = textbox.value.substring(0, textbox.selectionEnd);
if (!this.composing && SuggestionStore.getPretext(this.suggestionId) !== pretext) {
if (!this.composing && SuggestionStore.getPretext(this.suggestionId) !== pretext && pretext.length >= this.props.requiredCharacters) {
GlobalActions.emitSuggestionPretextChanged(this.suggestionId, pretext);
}
@@ -228,7 +246,8 @@ export default class SuggestionBox extends React.Component {
const suffix = text.substring(caret);
this.refs.textbox.value = prefix + term + ' ' + suffix;
const newValue = prefix + term + ' ' + suffix;
this.refs.textbox.value = newValue;
if (this.props.onChange) {
// fake an input event to send back to parent components
@@ -242,9 +261,10 @@ export default class SuggestionBox extends React.Component {
if (this.props.onItemSelected) {
const items = SuggestionStore.getItems(this.suggestionId);
for (const i of items) {
if (i.name === term) {
this.props.onItemSelected(i);
const terms = SuggestionStore.getTerms(this.suggestionId);
for (let i = 0; i < terms.length; i++) {
if (terms[i] === term) {
this.props.onItemSelected(items[i]);
break;
}
}
@@ -254,7 +274,9 @@ export default class SuggestionBox extends React.Component {
// set the caret position after the next rendering
window.requestAnimationFrame(() => {
Utils.setCaretPosition(textbox, prefix.length + term.length + 1);
if (textbox.value === newValue) {
Utils.setCaretPosition(textbox, newValue.length);
}
});
for (const provider of this.props.providers) {
@@ -277,7 +299,9 @@ export default class SuggestionBox extends React.Component {
e.preventDefault();
} else if (e.which === KeyCodes.ENTER || (this.props.completeOnTab && e.which === KeyCodes.TAB)) {
this.handleCompleteWord(SuggestionStore.getSelection(this.suggestionId), SuggestionStore.getSelectedMatchedPretext(this.suggestionId));
this.props.onKeyDown(e);
if (this.props.onKeyDown) {
this.props.onKeyDown(e);
}
e.preventDefault();
} else if (e.which === KeyCodes.ESCAPE) {
GlobalActions.emitClearSuggestions(this.suggestionId);
@@ -321,11 +345,14 @@ export default class SuggestionBox extends React.Component {
Reflect.deleteProperty(props, 'completeOnTab');
Reflect.deleteProperty(props, 'isRHS');
Reflect.deleteProperty(props, 'popoverMentionKeyClick');
Reflect.deleteProperty(props, 'requiredCharacters');
const childProps = {
ref: 'textbox',
onBlur: this.handleBlur,
onFocus: this.handleFocus,
onInput: this.handleChange,
onChange() { /* this is only here to suppress warnings about onChange not being implemented for read-write inputs */ },
onCompositionStart: this.handleCompositionStart,
onCompositionUpdate: this.handleCompositionUpdate,
onCompositionEnd: this.handleCompositionEnd,
@@ -337,6 +364,7 @@ export default class SuggestionBox extends React.Component {
textbox = (
<input
type='text'
autoComplete='off'
{...props}
{...childProps}
/>
@@ -345,6 +373,7 @@ export default class SuggestionBox extends React.Component {
textbox = (
<input
type='search'
autoComplete='off'
{...props}
{...childProps}
/>
@@ -364,7 +393,7 @@ export default class SuggestionBox extends React.Component {
return (
<div ref='container'>
{textbox}
{this.props.value &&
{this.props.value.length >= this.props.requiredCharacters &&
<SuggestionListComponent
suggestionId={this.suggestionId}
location={listStyle}