Merge pull request #1162 from asaadmahmoodspin/ui-improvements

UI improvements
Этот коммит содержится в:
Corey Hulen
2015-10-23 14:57:31 -07:00
родитель a7852a4810 9ac29075e1
Коммит 127a689e3e
13 изменённых файлов: 191 добавлений и 98 удалений

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

@@ -260,6 +260,12 @@ export default class InviteMemberModal extends React.Component {
var content = null; var content = null;
var sendButton = null; var sendButton = null;
var sendButtonLabel = 'Send Invitation';
if (this.state.inviteIds.length > 1) {
sendButtonLabel = 'Send Invitations';
}
if (this.state.emailEnabled) { if (this.state.emailEnabled) {
content = ( content = (
<div> <div>
@@ -281,7 +287,7 @@ export default class InviteMemberModal extends React.Component {
onClick={this.handleSubmit} onClick={this.handleSubmit}
type='button' type='button'
className='btn btn-primary' className='btn btn-primary'
>Send Invitations</button> >{sendButtonLabel}</button>
); );
} else { } else {
var teamInviteLink = null; var teamInviteLink = null;

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

@@ -36,7 +36,7 @@ export default class SettingItemMax extends React.Component {
if (this.props.width === 'full') { if (this.props.width === 'full') {
widthClass = 'col-sm-12'; widthClass = 'col-sm-12';
} else { } else {
widthClass = 'col-sm-9 col-sm-offset-3'; widthClass = 'col-sm-10 col-sm-offset-2';
} }
return ( return (

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

@@ -2,6 +2,10 @@
// See License.txt for license information. // See License.txt for license information.
export default class SettingsSidebar extends React.Component { export default class SettingsSidebar extends React.Component {
componentDidUpdate() {
$('.settings-modal').find('.modal-body').scrollTop(0);
$('.settings-modal').find('.modal-body').perfectScrollbar('update');
}
constructor(props) { constructor(props) {
super(props); super(props);

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

@@ -19,6 +19,7 @@ export default class TeamSettingsModal extends React.Component {
componentDidMount() { componentDidMount() {
$('body').on('click', '.modal-back', function handleBackClick() { $('body').on('click', '.modal-back', function handleBackClick() {
$(this).closest('.modal-dialog').removeClass('display--content'); $(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', () => { $('body').on('click', '.modal-header .close', () => {
setTimeout(() => { setTimeout(() => {

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

@@ -119,24 +119,23 @@ export default class ManageIncomingHooks extends React.Component {
hooks.push( hooks.push(
<div <div
key={hook.id} key={hook.id}
className='font--small' className='webhook__item'
> >
<div className='padding-top x2 divider-light'></div> <div className='padding-top x2 webhook__url'>
<div className='padding-top x2'> <strong>{'URL: '}</strong>
<strong>{'URL: '}</strong><span className='word-break--all'>{Utils.getWindowLocationOrigin() + '/hooks/' + hook.id}</span> <span className='word-break--all'>{Utils.getWindowLocationOrigin() + '/hooks/' + hook.id}</span>
</div> </div>
<div className='padding-top'> <div className='padding-top'>
<strong>{'Channel: '}</strong>{c.display_name} <strong>{'Channel: '}</strong>{c.display_name}
</div> </div>
<div className='padding-top'> <a
<a className={'webhook__remove'}
className={'text-danger'} href='#'
href='#' onClick={this.removeHook.bind(this, hook.id)}
onClick={this.removeHook.bind(this, hook.id)} >
> <span aria-hidden='true'>{'×'}</span>
{'Remove'} </a>
</a> <div className='padding-top x2 divider-light'></div>
</div>
</div> </div>
); );
} }
@@ -148,35 +147,38 @@ export default class ManageIncomingHooks extends React.Component {
} else if (hooks.length > 0) { } else if (hooks.length > 0) {
displayHooks = hooks; displayHooks = hooks;
} else { } else {
displayHooks = <label>{': None'}</label>; displayHooks = <div className='padding-top x2'>{'None'}</div>;
} }
const existingHooks = ( const existingHooks = (
<div className='padding-top x2'> <div className='webhooks__container'>
<label className='control-label padding-top x2'>{'Existing incoming webhooks'}</label> <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> </div>
); );
return ( return (
<div key='addIncomingHook'> <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.'} {'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/> <label className='control-label padding-top x2'>{'Add a new incoming webhook'}</label>
<br/> <div className='row padding-top'>
<label className='control-label'>{'Add a new incoming webhook'}</label> <div className='col-sm-10 padding-bottom'>
<div className='padding-top'> <select
<select ref='channelName'
ref='channelName' className='form-control'
className='form-control' value={this.state.channelId}
value={this.state.channelId} onChange={this.updateChannelId}
onChange={this.updateChannelId} >
> {options}
{options} </select>
</select> {serverError}
{serverError} </div>
<div className='padding-top'> <div className='col-sm-2 col-xs-4 no-padding--left padding-bottom'>
<a <a
className={'btn btn-sm btn-primary' + disableButton} className={'btn form-control no-padding btn-sm btn-primary' + disableButton}
href='#' href='#'
onClick={this.addNewHook} onClick={this.addNewHook}
> >

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

@@ -6,6 +6,7 @@ var Constants = require('../../utils/constants.jsx');
var ChannelStore = require('../../stores/channel_store.jsx'); var ChannelStore = require('../../stores/channel_store.jsx');
var LoadingScreen = require('../loading_screen.jsx'); var LoadingScreen = require('../loading_screen.jsx');
export default class ManageOutgoingHooks extends React.Component { export default class ManageOutgoingHooks extends React.Component {
constructor() { constructor() {
super(); super();
@@ -180,9 +181,8 @@ export default class ManageOutgoingHooks extends React.Component {
hooks.push( hooks.push(
<div <div
key={hook.id} key={hook.id}
className='font--small' className='webhook__item'
> >
<div className='padding-top x2 divider-light'></div>
<div className='padding-top x2'> <div className='padding-top x2'>
<strong>{'URLs: '}</strong><span className='word-break--all'>{hook.callback_urls.join(', ')}</span> <strong>{'URLs: '}</strong><span className='word-break--all'>{hook.callback_urls.join(', ')}</span>
</div> </div>
@@ -199,15 +199,15 @@ export default class ManageOutgoingHooks extends React.Component {
> >
{'Regen Token'} {'Regen Token'}
</a> </a>
<span>{' - '}</span>
<a <a
className='text-danger' className='webhook__remove'
href='#' href='#'
onClick={this.removeHook.bind(this, hook.id)} onClick={this.removeHook.bind(this, hook.id)}
> >
{'Remove'} <span aria-hidden='true'>{'×'}</span>
</a> </a>
</div> </div>
<div className='padding-top x2 divider-light'></div>
</div> </div>
); );
}); });
@@ -218,13 +218,16 @@ export default class ManageOutgoingHooks extends React.Component {
} else if (hooks.length > 0) { } else if (hooks.length > 0) {
displayHooks = hooks; displayHooks = hooks;
} else { } else {
displayHooks = <label>{': None'}</label>; displayHooks = <div className='padding-top x2'>{'None'}</div>;
} }
const existingHooks = ( const existingHooks = (
<div className='padding-top x2'> <div className='webhooks__container'>
<label className='control-label padding-top x2'>{'Existing outgoing webhooks'}</label> <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> </div>
); );
@@ -234,41 +237,49 @@ export default class ManageOutgoingHooks extends React.Component {
<div key='addOutgoingHook'> <div key='addOutgoingHook'>
<label className='control-label'>{'Add a new outgoing webhook'}</label> <label className='control-label'>{'Add a new outgoing webhook'}</label>
<div className='padding-top'> <div className='padding-top'>
<strong>{'Channel:'}</strong> <div>
<select <label className='control-label'>{'Channel'}</label>
ref='channelName' <div className='padding-top'>
className='form-control' <select
value={this.state.channelId} ref='channelName'
onChange={this.updateChannelId} className='form-control'
> value={this.state.channelId}
{options} onChange={this.updateChannelId}
</select> >
<span>{'Only public channels can be used'}</span> {options}
<br/> </select>
<br/> </div>
<strong>{'Trigger Words:'}</strong> <div className='padding-top'>{'Only public channels can be used'}</div>
<input </div>
ref='triggerWords' <div className='padding-top x2'>
className='form-control' <label className='control-label'>{'Trigger Words:'}</label>
value={this.state.triggerWords} <div className='padding-top'>
onChange={this.updateTriggerWords} <input
placeholder='Optional if channel selected' ref='triggerWords'
/> className='form-control'
<span>{'Comma separated words to trigger on'}</span> value={this.state.triggerWords}
<br/> onChange={this.updateTriggerWords}
<br/> placeholder='Optional if channel selected'
<strong>{'Callback URLs:'}</strong> />
<textarea </div>
ref='callbackURLs' <div className='padding-top'>{'Comma separated words to trigger on'}</div>
className='form-control no-resize' </div>
value={this.state.callbackURLs} <div className='padding-top x2'>
resize={false} <label className='control-label'>{'Callback URLs:'}</label>
rows={3} <div className='padding-top'>
onChange={this.updateCallbackURLs} <textarea
/> ref='callbackURLs'
<span>{'New line separated URLs that will receive the HTTP POST event'}</span> className='form-control no-resize'
{serverError} value={this.state.callbackURLs}
<div className='padding-top'> 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 <a
className={'btn btn-sm btn-primary'} className={'btn btn-sm btn-primary'}
href='#' href='#'

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

@@ -43,7 +43,6 @@ export default class UserSettingsIntegrationsTab extends React.Component {
incomingHooksSection = ( incomingHooksSection = (
<SettingItemMax <SettingItemMax
title='Incoming Webhooks' title='Incoming Webhooks'
width = 'full'
inputs={inputs} inputs={inputs}
updateSection={(e) => { updateSection={(e) => {
this.updateSection(''); this.updateSection('');
@@ -55,7 +54,6 @@ export default class UserSettingsIntegrationsTab extends React.Component {
incomingHooksSection = ( incomingHooksSection = (
<SettingItemMin <SettingItemMin
title='Incoming Webhooks' title='Incoming Webhooks'
width = 'full'
describe='Manage your incoming webhooks (Developer feature)' describe='Manage your incoming webhooks (Developer feature)'
updateSection={() => { updateSection={() => {
this.updateSection('incoming-hooks'); this.updateSection('incoming-hooks');

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

@@ -431,6 +431,7 @@ export function applyTheme(theme) {
if (theme.sidebarTextActiveColor) { 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-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) { 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('.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__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('.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.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.right>.arrow', 'border-right-color:' + changeOpacity(theme.centerChannelColor, 0.25), 1);
changeCss('.popover.left>.arrow', 'border-left-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('@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('.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('.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__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('.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); 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('@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('.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('.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('code', 'background:' + changeOpacity(theme.centerChannelColor, 0.1), 1);
changeCss('.post.current--user:hover .post-body ', 'background: none;', 1); changeCss('.post.current--user:hover .post-body ', 'background: none;', 1);
changeCss('.sidebar--right', 'color:' + theme.centerChannelColor, 2); changeCss('.sidebar--right', 'color:' + theme.centerChannelColor, 2);

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

@@ -94,8 +94,11 @@ a:focus, a:hover {
margin: 0; margin: 0;
} }
.text-danger { .text-danger, a.text-danger {
color: #E05F5D; color: #E05F5D;
&:hover, &:focus {
color: #E05F5D;
}
} }
.btn { .btn {
@@ -112,6 +115,10 @@ a:focus, a:hover {
&:focus { &:focus {
@include box-shadow(none); @include box-shadow(none);
} }
&.no-padding {
line-height: 32px;
padding: 0;
}
&.no-resize { &.no-resize {
resize: none; resize: none;
} }

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

@@ -569,9 +569,10 @@ body.ios {
} }
.bot-indicator { .bot-indicator {
background-color: lightgrey; font-family: inherit;
border-radius:2px; font-size: 11px;
padding-left:2px; padding: 2px 4px;
padding-right:2px; border-radius: 2px;
font-family:"Courier New" font-weight: 600;
margin: 0 0 0 -4px;
} }

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

@@ -284,6 +284,9 @@
height: auto; height: auto;
} }
} }
.search-help-popover.visible {
visibility: hidden;
}
.modal-direct-channels { .modal-direct-channels {
.member-count { .member-count {
float: none; float: none;
@@ -401,6 +404,9 @@
text-align: left; text-align: left;
} }
} }
.no-padding--left {
padding-left: 15px;
}
} }
.settings-links { .settings-links {
display: none; display: none;
@@ -425,6 +431,11 @@
} }
} }
.settings-table { .settings-table {
.nav {
position: relative;
top: auto;
width: 100%;
}
.settings-content { .settings-content {
&.minimize-settings { &.minimize-settings {
padding: 0; padding: 0;

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

@@ -1,5 +1,6 @@
@import "access-history"; @import "access-history";
@import "activity-log"; @import "activity-log";
@import "webhooks";
.user-settings { .user-settings {
min-height:300px; min-height:300px;
@@ -29,6 +30,9 @@
li { li {
list-style: none; list-style: none;
} }
label {
font-weight: 600;
}
.settings-table { .settings-table {
display: table; display: table;
table-layout: fixed; table-layout: fixed;
@@ -37,6 +41,11 @@
display: table-cell; display: table-cell;
vertical-align: top; vertical-align: top;
} }
.nav {
position: fixed;
top: 57px;
width: 180px;
}
.security-links { .security-links {
margin-right: 20px; margin-right: 20px;
.fa { .fa {
@@ -129,10 +138,6 @@
} }
} }
.font--small {
font-size: 13px;
}
.section-describe { .section-describe {
@include opacity(0.7); @include opacity(0.7);
white-space:pre; white-space:pre;
@@ -161,14 +166,29 @@
.setting-list-item { .setting-list-item {
margin-top:7px; 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 { &.x3 {
padding-top: 7px; padding-top: 21px;
&.x2 { }
padding-top: 14px; }
} .padding-bottom {
padding-bottom: 7px;
&.x2 {
padding-bottom: 14px;
}
&.x3 {
padding-bottom: 21px;
} }
.control-label { .control-label {
font-weight: 600; font-weight: 600;

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;
}
}