Merge pull request #1162 from asaadmahmoodspin/ui-improvements
UI improvements
Этот коммит содержится в:
@@ -260,6 +260,12 @@ export default class InviteMemberModal extends React.Component {
|
||||
|
||||
var content = null;
|
||||
var sendButton = null;
|
||||
|
||||
var sendButtonLabel = 'Send Invitation';
|
||||
if (this.state.inviteIds.length > 1) {
|
||||
sendButtonLabel = 'Send Invitations';
|
||||
}
|
||||
|
||||
if (this.state.emailEnabled) {
|
||||
content = (
|
||||
<div>
|
||||
@@ -281,7 +287,7 @@ export default class InviteMemberModal extends React.Component {
|
||||
onClick={this.handleSubmit}
|
||||
type='button'
|
||||
className='btn btn-primary'
|
||||
>Send Invitations</button>
|
||||
>{sendButtonLabel}</button>
|
||||
);
|
||||
} else {
|
||||
var teamInviteLink = null;
|
||||
|
||||
@@ -36,7 +36,7 @@ export default class SettingItemMax extends React.Component {
|
||||
if (this.props.width === 'full') {
|
||||
widthClass = 'col-sm-12';
|
||||
} else {
|
||||
widthClass = 'col-sm-9 col-sm-offset-3';
|
||||
widthClass = 'col-sm-10 col-sm-offset-2';
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
// See License.txt for license information.
|
||||
|
||||
export default class SettingsSidebar extends React.Component {
|
||||
componentDidUpdate() {
|
||||
$('.settings-modal').find('.modal-body').scrollTop(0);
|
||||
$('.settings-modal').find('.modal-body').perfectScrollbar('update');
|
||||
}
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ export default class TeamSettingsModal extends React.Component {
|
||||
componentDidMount() {
|
||||
$('body').on('click', '.modal-back', function handleBackClick() {
|
||||
$(this).closest('.modal-dialog').removeClass('display--content');
|
||||
$(this).closest('.modal-dialog').find('.settings-table .nav li.active').removeClass('active');
|
||||
});
|
||||
$('body').on('click', '.modal-header .close', () => {
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -119,24 +119,23 @@ export default class ManageIncomingHooks extends React.Component {
|
||||
hooks.push(
|
||||
<div
|
||||
key={hook.id}
|
||||
className='font--small'
|
||||
className='webhook__item'
|
||||
>
|
||||
<div className='padding-top x2 divider-light'></div>
|
||||
<div className='padding-top x2'>
|
||||
<strong>{'URL: '}</strong><span className='word-break--all'>{Utils.getWindowLocationOrigin() + '/hooks/' + hook.id}</span>
|
||||
<div className='padding-top x2 webhook__url'>
|
||||
<strong>{'URL: '}</strong>
|
||||
<span className='word-break--all'>{Utils.getWindowLocationOrigin() + '/hooks/' + hook.id}</span>
|
||||
</div>
|
||||
<div className='padding-top'>
|
||||
<strong>{'Channel: '}</strong>{c.display_name}
|
||||
</div>
|
||||
<div className='padding-top'>
|
||||
<a
|
||||
className={'text-danger'}
|
||||
href='#'
|
||||
onClick={this.removeHook.bind(this, hook.id)}
|
||||
>
|
||||
{'Remove'}
|
||||
</a>
|
||||
</div>
|
||||
<a
|
||||
className={'webhook__remove'}
|
||||
href='#'
|
||||
onClick={this.removeHook.bind(this, hook.id)}
|
||||
>
|
||||
<span aria-hidden='true'>{'×'}</span>
|
||||
</a>
|
||||
<div className='padding-top x2 divider-light'></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -148,35 +147,38 @@ export default class ManageIncomingHooks extends React.Component {
|
||||
} else if (hooks.length > 0) {
|
||||
displayHooks = hooks;
|
||||
} else {
|
||||
displayHooks = <label>{': None'}</label>;
|
||||
displayHooks = <div className='padding-top x2'>{'None'}</div>;
|
||||
}
|
||||
|
||||
const existingHooks = (
|
||||
<div className='padding-top x2'>
|
||||
<div className='webhooks__container'>
|
||||
<label className='control-label padding-top x2'>{'Existing incoming webhooks'}</label>
|
||||
{displayHooks}
|
||||
<div className='padding-top divider-light'></div>
|
||||
<div className='webhooks__list'>
|
||||
{displayHooks}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div key='addIncomingHook'>
|
||||
{'Create webhook URLs for use in external integrations. Please see '}<a href='http://mattermost.org/webhooks'>{'http://mattermost.org/webhooks'}</a> {' to learn more.'}
|
||||
<br/>
|
||||
<br/>
|
||||
<label className='control-label'>{'Add a new incoming webhook'}</label>
|
||||
<div className='padding-top'>
|
||||
<select
|
||||
ref='channelName'
|
||||
className='form-control'
|
||||
value={this.state.channelId}
|
||||
onChange={this.updateChannelId}
|
||||
>
|
||||
{options}
|
||||
</select>
|
||||
{serverError}
|
||||
<div className='padding-top'>
|
||||
<label className='control-label padding-top x2'>{'Add a new incoming webhook'}</label>
|
||||
<div className='row padding-top'>
|
||||
<div className='col-sm-10 padding-bottom'>
|
||||
<select
|
||||
ref='channelName'
|
||||
className='form-control'
|
||||
value={this.state.channelId}
|
||||
onChange={this.updateChannelId}
|
||||
>
|
||||
{options}
|
||||
</select>
|
||||
{serverError}
|
||||
</div>
|
||||
<div className='col-sm-2 col-xs-4 no-padding--left padding-bottom'>
|
||||
<a
|
||||
className={'btn btn-sm btn-primary' + disableButton}
|
||||
className={'btn form-control no-padding btn-sm btn-primary' + disableButton}
|
||||
href='#'
|
||||
onClick={this.addNewHook}
|
||||
>
|
||||
|
||||
@@ -6,6 +6,7 @@ var Constants = require('../../utils/constants.jsx');
|
||||
var ChannelStore = require('../../stores/channel_store.jsx');
|
||||
var LoadingScreen = require('../loading_screen.jsx');
|
||||
|
||||
|
||||
export default class ManageOutgoingHooks extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
@@ -180,9 +181,8 @@ export default class ManageOutgoingHooks extends React.Component {
|
||||
hooks.push(
|
||||
<div
|
||||
key={hook.id}
|
||||
className='font--small'
|
||||
className='webhook__item'
|
||||
>
|
||||
<div className='padding-top x2 divider-light'></div>
|
||||
<div className='padding-top x2'>
|
||||
<strong>{'URLs: '}</strong><span className='word-break--all'>{hook.callback_urls.join(', ')}</span>
|
||||
</div>
|
||||
@@ -199,15 +199,15 @@ export default class ManageOutgoingHooks extends React.Component {
|
||||
>
|
||||
{'Regen Token'}
|
||||
</a>
|
||||
<span>{' - '}</span>
|
||||
<a
|
||||
className='text-danger'
|
||||
className='webhook__remove'
|
||||
href='#'
|
||||
onClick={this.removeHook.bind(this, hook.id)}
|
||||
>
|
||||
{'Remove'}
|
||||
<span aria-hidden='true'>{'×'}</span>
|
||||
</a>
|
||||
</div>
|
||||
<div className='padding-top x2 divider-light'></div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
@@ -218,13 +218,16 @@ export default class ManageOutgoingHooks extends React.Component {
|
||||
} else if (hooks.length > 0) {
|
||||
displayHooks = hooks;
|
||||
} else {
|
||||
displayHooks = <label>{': None'}</label>;
|
||||
displayHooks = <div className='padding-top x2'>{'None'}</div>;
|
||||
}
|
||||
|
||||
const existingHooks = (
|
||||
<div className='padding-top x2'>
|
||||
<div className='webhooks__container'>
|
||||
<label className='control-label padding-top x2'>{'Existing outgoing webhooks'}</label>
|
||||
{displayHooks}
|
||||
<div className='padding-top divider-light'></div>
|
||||
<div className='webhooks__list'>
|
||||
{displayHooks}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -234,41 +237,49 @@ export default class ManageOutgoingHooks extends React.Component {
|
||||
<div key='addOutgoingHook'>
|
||||
<label className='control-label'>{'Add a new outgoing webhook'}</label>
|
||||
<div className='padding-top'>
|
||||
<strong>{'Channel:'}</strong>
|
||||
<select
|
||||
ref='channelName'
|
||||
className='form-control'
|
||||
value={this.state.channelId}
|
||||
onChange={this.updateChannelId}
|
||||
>
|
||||
{options}
|
||||
</select>
|
||||
<span>{'Only public channels can be used'}</span>
|
||||
<br/>
|
||||
<br/>
|
||||
<strong>{'Trigger Words:'}</strong>
|
||||
<input
|
||||
ref='triggerWords'
|
||||
className='form-control'
|
||||
value={this.state.triggerWords}
|
||||
onChange={this.updateTriggerWords}
|
||||
placeholder='Optional if channel selected'
|
||||
/>
|
||||
<span>{'Comma separated words to trigger on'}</span>
|
||||
<br/>
|
||||
<br/>
|
||||
<strong>{'Callback URLs:'}</strong>
|
||||
<textarea
|
||||
ref='callbackURLs'
|
||||
className='form-control no-resize'
|
||||
value={this.state.callbackURLs}
|
||||
resize={false}
|
||||
rows={3}
|
||||
onChange={this.updateCallbackURLs}
|
||||
/>
|
||||
<span>{'New line separated URLs that will receive the HTTP POST event'}</span>
|
||||
{serverError}
|
||||
<div className='padding-top'>
|
||||
<div>
|
||||
<label className='control-label'>{'Channel'}</label>
|
||||
<div className='padding-top'>
|
||||
<select
|
||||
ref='channelName'
|
||||
className='form-control'
|
||||
value={this.state.channelId}
|
||||
onChange={this.updateChannelId}
|
||||
>
|
||||
{options}
|
||||
</select>
|
||||
</div>
|
||||
<div className='padding-top'>{'Only public channels can be used'}</div>
|
||||
</div>
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>{'Trigger Words:'}</label>
|
||||
<div className='padding-top'>
|
||||
<input
|
||||
ref='triggerWords'
|
||||
className='form-control'
|
||||
value={this.state.triggerWords}
|
||||
onChange={this.updateTriggerWords}
|
||||
placeholder='Optional if channel selected'
|
||||
/>
|
||||
</div>
|
||||
<div className='padding-top'>{'Comma separated words to trigger on'}</div>
|
||||
</div>
|
||||
<div className='padding-top x2'>
|
||||
<label className='control-label'>{'Callback URLs:'}</label>
|
||||
<div className='padding-top'>
|
||||
<textarea
|
||||
ref='callbackURLs'
|
||||
className='form-control no-resize'
|
||||
value={this.state.callbackURLs}
|
||||
resize={false}
|
||||
rows={3}
|
||||
onChange={this.updateCallbackURLs}
|
||||
/>
|
||||
</div>
|
||||
<div className='padding-top'>{'New line separated URLs that will receive the HTTP POST event'}</div>
|
||||
{serverError}
|
||||
</div>
|
||||
<div className='padding-top padding-bottom'>
|
||||
<a
|
||||
className={'btn btn-sm btn-primary'}
|
||||
href='#'
|
||||
|
||||
@@ -43,7 +43,6 @@ export default class UserSettingsIntegrationsTab extends React.Component {
|
||||
incomingHooksSection = (
|
||||
<SettingItemMax
|
||||
title='Incoming Webhooks'
|
||||
width = 'full'
|
||||
inputs={inputs}
|
||||
updateSection={(e) => {
|
||||
this.updateSection('');
|
||||
@@ -55,7 +54,6 @@ export default class UserSettingsIntegrationsTab extends React.Component {
|
||||
incomingHooksSection = (
|
||||
<SettingItemMin
|
||||
title='Incoming Webhooks'
|
||||
width = 'full'
|
||||
describe='Manage your incoming webhooks (Developer feature)'
|
||||
updateSection={() => {
|
||||
this.updateSection('incoming-hooks');
|
||||
|
||||
@@ -431,6 +431,7 @@ export function applyTheme(theme) {
|
||||
|
||||
if (theme.sidebarTextActiveColor) {
|
||||
changeCss('.sidebar--left .nav-pills__container li.active a, .sidebar--left .nav-pills__container li.active a:hover, .sidebar--left .nav-pills__container li.active a:focus, .settings-modal .nav-pills>li.active a, .settings-modal .nav-pills>li.active a:hover, .settings-modal .nav-pills>li.active a:active', 'color:' + theme.sidebarTextActiveColor, 2);
|
||||
changeCss('.sidebar--left .nav li.active a, .sidebar--left .nav li.active a:hover, .sidebar--left .nav li.active a:focus', 'background:' + changeOpacity(theme.sidebarTextActiveColor, 0.1), 1);
|
||||
}
|
||||
|
||||
if (theme.sidebarHeaderBg) {
|
||||
@@ -494,7 +495,7 @@ export function applyTheme(theme) {
|
||||
changeCss('.markdown__table tbody tr:nth-child(2n)', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1);
|
||||
changeCss('.channel-header__info>div.dropdown .header-dropdown__icon', 'color:' + changeOpacity(theme.centerChannelColor, 0.8), 1);
|
||||
changeCss('.channel-header #member_popover', 'color:' + changeOpacity(theme.centerChannelColor, 0.8), 1);
|
||||
changeCss('.custom-textarea, .custom-textarea:focus, .preview-container .preview-div, .post-image__column .post-image__details, .sidebar--right .sidebar-right__body, .markdown__table th, .markdown__table td, .command-box, .modal .modal-content, .settings-modal .settings-table .settings-content .divider-light, .dropdown-menu, .modal .modal-header, .popover, .mentions--top .mentions-box', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1);
|
||||
changeCss('.custom-textarea, .custom-textarea:focus, .preview-container .preview-div, .post-image__column .post-image__details, .sidebar--right .sidebar-right__body, .markdown__table th, .markdown__table td, .command-box, .modal .modal-content, .settings-modal .settings-table .settings-content .divider-light, .webhooks__container, .dropdown-menu, .modal .modal-header, .popover, .mentions--top .mentions-box', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1);
|
||||
changeCss('.popover.bottom>.arrow', 'border-bottom-color:' + changeOpacity(theme.centerChannelColor, 0.25), 1);
|
||||
changeCss('.popover.right>.arrow', 'border-right-color:' + changeOpacity(theme.centerChannelColor, 0.25), 1);
|
||||
changeCss('.popover.left>.arrow', 'border-left-color:' + changeOpacity(theme.centerChannelColor, 0.25), 1);
|
||||
@@ -509,7 +510,7 @@ export function applyTheme(theme) {
|
||||
changeCss('@media(max-width: 768px){.search-bar__container .search__form .search-bar', 'background:' + changeOpacity(theme.centerChannelColor, 0.2) + '; color: inherit;', 1);
|
||||
changeCss('.input-group-addon, .search-bar__container .search__form, .form-control', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1);
|
||||
changeCss('.form-control:focus', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.3), 1);
|
||||
changeCss('.channel-intro .channel-intro__content', 'background:' + changeOpacity(theme.centerChannelColor, 0.05), 1);
|
||||
changeCss('.channel-intro .channel-intro__content, .webhooks__container', 'background:' + changeOpacity(theme.centerChannelColor, 0.05), 1);
|
||||
changeCss('.date-separator .separator__text', 'color:' + theme.centerChannelColor, 2);
|
||||
changeCss('.date-separator .separator__hr, .modal-footer, .modal .custom-textarea, .post-right__container .post.post--root hr, .search-item-container', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1);
|
||||
changeCss('.modal .custom-textarea:focus', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.3), 1);
|
||||
@@ -521,7 +522,7 @@ export function applyTheme(theme) {
|
||||
changeCss('@media(max-width: 1800px){.inner__wrap.move--left .post.post--comment.same--root', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.07), 2);
|
||||
changeCss('.post:hover, .modal .more-table tbody>tr:hover td, .sidebar--right .sidebar--right__header, .settings-modal .settings-table .settings-content .section-min:hover', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1);
|
||||
changeCss('.date-separator.hovered--before:after, .date-separator.hovered--after:before, .new-separator.hovered--after:before, .new-separator.hovered--before:after', 'background:' + changeOpacity(theme.centerChannelColor, 0.07), 1);
|
||||
changeCss('.command-name:hover, .mentions-name:hover, .mentions-focus, .dropdown-menu>li>a:focus, .dropdown-menu>li>a:hover', 'background:' + changeOpacity(theme.centerChannelColor, 0.15), 1);
|
||||
changeCss('.command-name:hover, .mentions-name:hover, .mentions-focus, .dropdown-menu>li>a:focus, .dropdown-menu>li>a:hover, .bot-indicator', 'background:' + changeOpacity(theme.centerChannelColor, 0.15), 1);
|
||||
changeCss('code', 'background:' + changeOpacity(theme.centerChannelColor, 0.1), 1);
|
||||
changeCss('.post.current--user:hover .post-body ', 'background: none;', 1);
|
||||
changeCss('.sidebar--right', 'color:' + theme.centerChannelColor, 2);
|
||||
|
||||
@@ -94,8 +94,11 @@ a:focus, a:hover {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
.text-danger, a.text-danger {
|
||||
color: #E05F5D;
|
||||
&:hover, &:focus {
|
||||
color: #E05F5D;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
@@ -112,6 +115,10 @@ a:focus, a:hover {
|
||||
&:focus {
|
||||
@include box-shadow(none);
|
||||
}
|
||||
&.no-padding {
|
||||
line-height: 32px;
|
||||
padding: 0;
|
||||
}
|
||||
&.no-resize {
|
||||
resize: none;
|
||||
}
|
||||
|
||||
@@ -569,9 +569,10 @@ body.ios {
|
||||
}
|
||||
|
||||
.bot-indicator {
|
||||
background-color: lightgrey;
|
||||
border-radius:2px;
|
||||
padding-left:2px;
|
||||
padding-right:2px;
|
||||
font-family:"Courier New"
|
||||
font-family: inherit;
|
||||
font-size: 11px;
|
||||
padding: 2px 4px;
|
||||
border-radius: 2px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 0 -4px;
|
||||
}
|
||||
|
||||
@@ -284,6 +284,9 @@
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.search-help-popover.visible {
|
||||
visibility: hidden;
|
||||
}
|
||||
.modal-direct-channels {
|
||||
.member-count {
|
||||
float: none;
|
||||
@@ -401,6 +404,9 @@
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
.no-padding--left {
|
||||
padding-left: 15px;
|
||||
}
|
||||
}
|
||||
.settings-links {
|
||||
display: none;
|
||||
@@ -425,6 +431,11 @@
|
||||
}
|
||||
}
|
||||
.settings-table {
|
||||
.nav {
|
||||
position: relative;
|
||||
top: auto;
|
||||
width: 100%;
|
||||
}
|
||||
.settings-content {
|
||||
&.minimize-settings {
|
||||
padding: 0;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
@import "access-history";
|
||||
@import "activity-log";
|
||||
@import "webhooks";
|
||||
|
||||
.user-settings {
|
||||
min-height:300px;
|
||||
@@ -29,6 +30,9 @@
|
||||
li {
|
||||
list-style: none;
|
||||
}
|
||||
label {
|
||||
font-weight: 600;
|
||||
}
|
||||
.settings-table {
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
@@ -37,6 +41,11 @@
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
}
|
||||
.nav {
|
||||
position: fixed;
|
||||
top: 57px;
|
||||
width: 180px;
|
||||
}
|
||||
.security-links {
|
||||
margin-right: 20px;
|
||||
.fa {
|
||||
@@ -129,10 +138,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.font--small {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.section-describe {
|
||||
@include opacity(0.7);
|
||||
white-space:pre;
|
||||
@@ -161,14 +166,29 @@
|
||||
|
||||
.setting-list-item {
|
||||
margin-top:7px;
|
||||
.has-error {
|
||||
color: #a94442;
|
||||
}
|
||||
.has-error {
|
||||
color: #a94442;
|
||||
}
|
||||
.no-padding--left {
|
||||
padding-left: 0;
|
||||
}
|
||||
.padding-top {
|
||||
padding-top: 7px;
|
||||
&.x2 {
|
||||
padding-top: 14px;
|
||||
}
|
||||
.padding-top {
|
||||
padding-top: 7px;
|
||||
&.x2 {
|
||||
padding-top: 14px;
|
||||
}
|
||||
&.x3 {
|
||||
padding-top: 21px;
|
||||
}
|
||||
}
|
||||
.padding-bottom {
|
||||
padding-bottom: 7px;
|
||||
&.x2 {
|
||||
padding-bottom: 14px;
|
||||
}
|
||||
&.x3 {
|
||||
padding-bottom: 21px;
|
||||
}
|
||||
.control-label {
|
||||
font-weight: 600;
|
||||
|
||||
31
web/sass-files/sass/partials/_webhooks.scss
Обычный файл
31
web/sass-files/sass/partials/_webhooks.scss
Обычный файл
@@ -0,0 +1,31 @@
|
||||
.webhooks__container {
|
||||
background: rgba(black, 0.1);
|
||||
border: 1px solid;
|
||||
@include border-radius(3px);
|
||||
padding: 0 13px 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.webhook__item {
|
||||
font-size: 13px;
|
||||
position: relative;
|
||||
&:last-child {
|
||||
.divider-light:last-child {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.webhook__remove {
|
||||
position: absolute;
|
||||
right: -7px;
|
||||
top: 8px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: #E05F5D;
|
||||
}
|
||||
.webhook__url {
|
||||
padding-right: 20px;
|
||||
}
|
||||
}
|
||||
Ссылка в новой задаче
Block a user