PLT-2553 Additional backstage UI Improvements (#2673)

* Renamed Commands to Slash Commands in backstage UI

* Updated displayed info for listed commands and outgoing webhooks

* Disallowed empty outgoing webhook trigger words and improved client-side validation for them
Этот коммит содержится в:
Harrison Healey
2016-04-11 09:04:56 -04:00
коммит произвёл Christopher Speller
родитель 81e7e85369
Коммит 29e1a85360
8 изменённых файлов: 73 добавлений и 29 удалений

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

@@ -2351,6 +2351,10 @@
"id": "model.outgoing_hook.is_valid.token.app_error", "id": "model.outgoing_hook.is_valid.token.app_error",
"translation": "Invalid token" "translation": "Invalid token"
}, },
{
"id": "model.outgoing_hook.is_valid.trigger_words.app_error",
"translation": "Invalid trigger words"
},
{ {
"id": "model.outgoing_hook.is_valid.update_at.app_error", "id": "model.outgoing_hook.is_valid.update_at.app_error",
"translation": "Update at must be a valid time" "translation": "Update at must be a valid time"

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

@@ -98,6 +98,14 @@ func (o *OutgoingWebhook) IsValid() *AppError {
return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.words.app_error", nil, "") return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.words.app_error", nil, "")
} }
if len(o.TriggerWords) != 0 {
for _, triggerWord := range o.TriggerWords {
if len(triggerWord) == 0 {
return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.trigger_words.app_error", nil, "")
}
}
}
if len(o.CallbackURLs) == 0 || len(fmt.Sprintf("%s", o.CallbackURLs)) > 1024 { if len(o.CallbackURLs) == 0 || len(fmt.Sprintf("%s", o.CallbackURLs)) > 1024 {
return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.callback.app_error", nil, "") return NewLocAppError("OutgoingWebhook.IsValid", "model.outgoing_hook.is_valid.callback.app_error", nil, "")
} }

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

@@ -50,7 +50,18 @@ export default class AddOutgoingWebhook extends React.Component {
clientError: '' clientError: ''
}); });
if (!this.state.channelId && !this.state.triggerWords) { const triggerWords = [];
if (this.state.triggerWords) {
for (let triggerWord of this.state.triggerWords.split('\n')) {
triggerWord = triggerWord.trim();
if (triggerWord.length > 0) {
triggerWords.push(triggerWord);
}
}
}
if (!this.state.channelId && triggerWords.length === 0) {
this.setState({ this.setState({
saving: false, saving: false,
clientError: ( clientError: (
@@ -64,7 +75,16 @@ export default class AddOutgoingWebhook extends React.Component {
return; return;
} }
if (!this.state.callbackUrls) { const callbackUrls = [];
for (let callbackUrl of this.state.callbackUrls.split('\n')) {
callbackUrl = callbackUrl.trim();
if (callbackUrl.length > 0) {
callbackUrls.push(callbackUrl);
}
}
if (callbackUrls.length === 0) {
this.setState({ this.setState({
saving: false, saving: false,
clientError: ( clientError: (
@@ -80,8 +100,8 @@ export default class AddOutgoingWebhook extends React.Component {
const hook = { const hook = {
channel_id: this.state.channelId, channel_id: this.state.channelId,
trigger_words: this.state.triggerWords.split('\n').map((word) => word.trim()), trigger_words: triggerWords,
callback_urls: this.state.callbackUrls.split('\n').map((url) => url.trim()), callback_urls: callbackUrls,
display_name: this.state.displayName, display_name: this.state.displayName,
description: this.state.description description: this.state.description
}; };

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

@@ -78,6 +78,11 @@ export default class InstalledCommand extends React.Component {
); );
} }
let trigger = '- /' + command.trigger;
if (command.auto_complete && command.auto_complete_hint) {
trigger += ' ' + command.auto_complete_hint;
}
return ( return (
<div className='backstage-list__item'> <div className='backstage-list__item'>
<div className='item-details'> <div className='item-details'>
@@ -86,7 +91,7 @@ export default class InstalledCommand extends React.Component {
{name} {name}
</span> </span>
<span className='item-details__trigger'> <span className='item-details__trigger'>
{'- /' + command.trigger} {trigger}
</span> </span>
</div> </div>
{description} {description}

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

@@ -74,14 +74,14 @@ export default class InstalledCommands extends React.Component {
<InstalledIntegrations <InstalledIntegrations
header={ header={
<FormattedMessage <FormattedMessage
id='installed_integrations.commands' id='installed_commands.header'
defaultMessage='Installed Commands' defaultMessage='Installed Slash Commands'
/> />
} }
addText={ addText={
<FormattedMessage <FormattedMessage
id='installed_integrations.add_command' id='installed_commands.add'
defaultMessage='Add Command' defaultMessage='Add Slash Command'
/> />
} }
addLink='/settings/integrations/commands/add' addLink='/settings/integrations/commands/add'

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

@@ -95,6 +95,23 @@ export default class InstalledOutgoingWebhook extends React.Component {
); );
} }
let triggerWords = null;
if (outgoingWebhook.trigger_words && outgoingWebhook.trigger_words.length > 0) {
triggerWords = (
<div className='item-details__row'>
<span className='item-details__trigger-words'>
<FormattedMessage
id='installed_integrations.triggerWords'
defaultMessage='Trigger Words: {triggerWords}'
values={{
triggerWords: outgoingWebhook.trigger_words.join(', ')
}}
/>
</span>
</div>
);
}
return ( return (
<div className='backstage-list__item'> <div className='backstage-list__item'>
<div className='item-details'> <div className='item-details'>
@@ -104,6 +121,7 @@ export default class InstalledOutgoingWebhook extends React.Component {
</span> </span>
</div> </div>
{description} {description}
{triggerWords}
<div className='item-details__row'> <div className='item-details__row'>
<span className='item-details__token'> <span className='item-details__token'>
<FormattedMessage <FormattedMessage
@@ -128,7 +146,7 @@ export default class InstalledOutgoingWebhook extends React.Component {
</span> </span>
</div> </div>
</div> </div>
<div className='actions'> <div className='item-actions'>
<a <a
href='#' href='#'
onClick={this.handleRegenToken} onClick={this.handleRegenToken}
@@ -152,21 +170,4 @@ export default class InstalledOutgoingWebhook extends React.Component {
</div> </div>
); );
} }
static matches(outgoingWebhook, filter) {
if (outgoingWebhook.display_name.toLowerCase().indexOf(filter) !== -1 ||
outgoingWebhook.description.toLowerCase().indexOf(filter) !== -1) {
return true;
}
if (outgoingWebhook.channel_id) {
const channel = ChannelStore.get(outgoingWebhook.channel_id);
if (channel && channel.name.toLowerCase().indexOf(filter) !== -1) {
return true;
}
}
return false;
}
} }

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

@@ -619,7 +619,7 @@
"backstage_sidebar.integrations": "Integrations", "backstage_sidebar.integrations": "Integrations",
"backstage_sidebar.integrations.incoming_webhooks": "Incoming Webhooks", "backstage_sidebar.integrations.incoming_webhooks": "Incoming Webhooks",
"backstage_sidebar.integrations.outgoing_webhooks": "Outgoing Webhooks", "backstage_sidebar.integrations.outgoing_webhooks": "Outgoing Webhooks",
"backstage_sidebar.integrations.commands": "Commands", "backstage_sidebar.integrations.commands": "Slash Commands",
"center_panel.recent": "Click here to jump to recent messages. ", "center_panel.recent": "Click here to jump to recent messages. ",
"chanel_header.addMembers": "Add Members", "chanel_header.addMembers": "Add Members",
"change_url.close": "Close", "change_url.close": "Close",

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

@@ -192,6 +192,7 @@ body {
} }
.item-details { .item-details {
color: $dark-gray;
flex-grow: 1; flex-grow: 1;
flex-shrink: 1; flex-shrink: 1;
overflow: hidden; overflow: hidden;
@@ -204,6 +205,7 @@ body {
} }
.item-details__name { .item-details__name {
color: black;
font-weight: 600; font-weight: 600;
} }
@@ -213,8 +215,8 @@ body {
.item-details__description, .item-details__description,
.item-details__token, .item-details__token,
.item-details__trigger-words,
.item-details__creation { .item-details__creation {
color: $dark-gray;
display: inline-block; display: inline-block;
margin-top: 10px; margin-top: 10px;
vertical-align: top; vertical-align: top;
@@ -224,6 +226,10 @@ body {
} }
} }
.item-details__trigger-words {
white-space: nowrap;
}
.item-actions { .item-actions {
flex-grow: 0; flex-grow: 0;
flex-shrink: 0; flex-shrink: 0;