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 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 Обычный файл
Просмотреть файл

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