Merge pull request #1219 from asaadmahmoodspin/ui-improvements

Ui improvements
Этот коммит содержится в:
Corey Hulen
2015-10-28 14:42:58 -07:00
родитель ccf9e0cabd 110bc3e7e9
Коммит 9312272234
18 изменённых файлов: 188 добавлений и 155 удалений

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

@@ -270,7 +270,7 @@ export default class FileAttachment extends React.Component {
href={fileUrl} href={fileUrl}
download={filenameString} download={filenameString}
data-toggle='tooltip' data-toggle='tooltip'
title={filenameString} title={'Download ' + filenameString}
className='post-image__name' className='post-image__name'
> >
{trimmedFilename} {trimmedFilename}

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

@@ -98,7 +98,7 @@ export default class GetLinkModal extends React.Component {
<br /><br /> <br /><br />
</p> </p>
<textarea <textarea
className='form-control no-resize' className='form-control no-resize min-height'
readOnly='true' readOnly='true'
ref='textarea' ref='textarea'
value={this.state.value} value={this.state.value}

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

@@ -58,6 +58,7 @@ export default class NavbarDropdown extends React.Component {
TeamStore.addChangeListener(this.onListenerChange); TeamStore.addChangeListener(this.onListenerChange);
$(ReactDOM.findDOMNode(this.refs.dropdown)).on('hide.bs.dropdown', () => { $(ReactDOM.findDOMNode(this.refs.dropdown)).on('hide.bs.dropdown', () => {
$('.sidebar--left .dropdown-menu').scrollTop(0);
this.blockToggle = true; this.blockToggle = true;
setTimeout(() => { setTimeout(() => {
this.blockToggle = false; this.blockToggle = false;

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

@@ -96,75 +96,74 @@ export default class RegisterAppModal extends React.Component {
var body = ''; var body = '';
if (this.state.clientId === '') { if (this.state.clientId === '') {
body = ( body = (
<div className='form-group user-settings'> <div className='settings-modal'>
<h3>{'Register a New Application'}</h3> <div className='form-horizontal user-settings'>
<br/> <h4 className='padding-bottom x3'>{'Register a New Application'}</h4>
<label className='col-sm-4 control-label'>{'Application Name'}</label> <div className='row'>
<div className='col-sm-7'> <label className='col-sm-4 control-label'>{'Application Name'}</label>
<input <div className='col-sm-7'>
ref='name' <input
className='form-control' ref='name'
type='text' className='form-control'
placeholder='Required' type='text'
/> placeholder='Required'
{nameError} />
{nameError}
</div>
</div>
<div className='row padding-top x2'>
<label className='col-sm-4 control-label'>{'Homepage URL'}</label>
<div className='col-sm-7'>
<input
ref='homepage'
className='form-control'
type='text'
placeholder='Required'
/>
{homepageError}
</div>
</div>
<div className='row padding-top x2'>
<label className='col-sm-4 control-label'>{'Description'}</label>
<div className='col-sm-7'>
<input
ref='desc'
className='form-control'
type='text'
placeholder='Optional'
/>
</div>
</div>
<div className='row padding-top padding-bottom x2'>
<label className='col-sm-4 control-label'>{'Callback URL'}</label>
<div className='col-sm-7'>
<textarea
ref='callback'
className='form-control'
type='text'
placeholder='Required'
rows='5'
/>
{callbackError}
</div>
</div>
{serverError}
<hr />
<a
className='btn btn-sm theme pull-right'
href='#'
data-dismiss='modal'
aria-label='Close'
>
{'Cancel'}
</a>
<a
className='btn btn-sm btn-primary pull-right'
onClick={this.register}
>
{'Register'}
</a>
</div> </div>
<br/>
<br/>
<label className='col-sm-4 control-label'>{'Homepage URL'}</label>
<div className='col-sm-7'>
<input
ref='homepage'
className='form-control'
type='text'
placeholder='Required'
/>
{homepageError}
</div>
<br/>
<br/>
<label className='col-sm-4 control-label'>{'Description'}</label>
<div className='col-sm-7'>
<input
ref='desc'
className='form-control'
type='text'
placeholder='Optional'
/>
</div>
<br/>
<br/>
<label className='col-sm-4 control-label'>{'Callback URL'}</label>
<div className='col-sm-7'>
<textarea
ref='callback'
className='form-control'
type='text'
placeholder='Required'
rows='5'
/>
{callbackError}
</div>
<br/>
<br/>
<br/>
<br/>
<br/>
{serverError}
<a
className='btn btn-sm theme pull-right'
href='#'
data-dismiss='modal'
aria-label='Close'
>
{'Cancel'}
</a>
<a
className='btn btn-sm btn-primary pull-right'
onClick={this.register}
>
{'Register'}
</a>
</div> </div>
); );
} else { } else {

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

@@ -10,6 +10,7 @@ const patterns = new Map([
['channels', /\b(?:in|channel):\s*(\S*)$/i], ['channels', /\b(?:in|channel):\s*(\S*)$/i],
['users', /\bfrom:\s*(\S*)$/i] ['users', /\bfrom:\s*(\S*)$/i]
]); ]);
const Popover = ReactBootstrap.Popover;
export default class SearchAutocomplete extends React.Component { export default class SearchAutocomplete extends React.Component {
constructor(props) { constructor(props) {
@@ -36,6 +37,11 @@ export default class SearchAutocomplete extends React.Component {
$(document).on('click', this.handleDocumentClick); $(document).on('click', this.handleDocumentClick);
} }
componentDidUpdate() {
$(ReactDOM.findDOMNode(this.refs.searchPopover)).find('.popover-content').perfectScrollbar();
$(ReactDOM.findDOMNode(this.refs.searchPopover)).find('.popover-content').css('max-height', $(window).height() - 200);
}
componentWillUnmount() { componentWillUnmount() {
$(document).off('click', this.handleDocumentClick); $(document).off('click', this.handleDocumentClick);
} }
@@ -193,7 +199,7 @@ export default class SearchAutocomplete extends React.Component {
if (this.state.mode === 'channels') { if (this.state.mode === 'channels') {
suggestions = this.state.suggestions.map((channel, index) => { suggestions = this.state.suggestions.map((channel, index) => {
let className = 'search-autocomplete__channel'; let className = 'search-autocomplete__item';
if (this.state.selection === index) { if (this.state.selection === index) {
className += ' selected'; className += ' selected';
} }
@@ -211,7 +217,7 @@ export default class SearchAutocomplete extends React.Component {
}); });
} else if (this.state.mode === 'users') { } else if (this.state.mode === 'users') {
suggestions = this.state.suggestions.map((user, index) => { suggestions = this.state.suggestions.map((user, index) => {
let className = 'search-autocomplete__user'; let className = 'search-autocomplete__item';
if (this.state.selection === index) { if (this.state.selection === index) {
className += ' selected'; className += ' selected';
} }
@@ -224,7 +230,7 @@ export default class SearchAutocomplete extends React.Component {
className={className} className={className}
> >
<img <img
className='profile-img' className='profile-img rounded'
src={'/api/v1/users/' + user.id + '/image?time=' + user.update_at} src={'/api/v1/users/' + user.id + '/image?time=' + user.update_at}
/> />
{user.username} {user.username}
@@ -234,12 +240,15 @@ export default class SearchAutocomplete extends React.Component {
} }
return ( return (
<div <Popover
ref='container' ref='searchPopover'
className='search-autocomplete' onShow={this.componentDidMount}
id='search-autocomplete__popover'
className='search-help-popover autocomplete visible'
placement='bottom'
> >
{suggestions} {suggestions}
</div> </Popover>
); );
} }
} }

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

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

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

@@ -42,7 +42,7 @@ export default class SettingPicture extends React.Component {
img = ( img = (
<img <img
ref='image' ref='image'
className='profile-img' className='profile-img rounded'
src='' src=''
/> />
); );
@@ -50,7 +50,7 @@ export default class SettingPicture extends React.Component {
img = ( img = (
<img <img
ref='image' ref='image'
className='profile-img' className='profile-img rounded'
src={this.props.src} src={this.props.src}
/> />
); );

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

@@ -5,6 +5,9 @@ var NavbarDropdown = require('./navbar_dropdown.jsx');
var UserStore = require('../stores/user_store.jsx'); var UserStore = require('../stores/user_store.jsx');
const Utils = require('../utils/utils.jsx'); const Utils = require('../utils/utils.jsx');
const Tooltip = ReactBootstrap.Tooltip;
const OverlayTrigger = ReactBootstrap.OverlayTrigger;
export default class SidebarHeader extends React.Component { export default class SidebarHeader extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -47,7 +50,15 @@ export default class SidebarHeader extends React.Component {
{profilePicture} {profilePicture}
<div className='header__info'> <div className='header__info'>
<div className='user__name'>{'@' + me.username}</div> <div className='user__name'>{'@' + me.username}</div>
<OverlayTrigger
trigger={['hover', 'focus']}
delayShow={1000}
placement='bottom'
overlay={<Tooltip id='team-name__tooltip'>{this.props.teamDisplayName}</Tooltip>}
ref='descriptionOverlay'
>
<div className='team__name'>{this.props.teamDisplayName}</div> <div className='team__name'>{this.props.teamDisplayName}</div>
</OverlayTrigger>
</div> </div>
</a> </a>
<NavbarDropdown <NavbarDropdown

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

@@ -71,7 +71,7 @@ export default class EmailSignUpPage extends React.Component {
className='btn btn-md btn-primary' className='btn btn-md btn-primary'
type='submit' type='submit'
> >
{'Sign up'} {'Create Team'}
</button> </button>
{serverError} {serverError}
</div> </div>

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

@@ -236,6 +236,7 @@ export default class ManageOutgoingHooks extends React.Component {
return ( return (
<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 divider-light'></div>
<div className='padding-top'> <div className='padding-top'>
<div> <div>
<label className='control-label'>{'Channel'}</label> <label className='control-label'>{'Channel'}</label>

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

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

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

@@ -438,6 +438,8 @@ 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); 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);
changeCss('.search-help-popover .search-autocomplete__item:hover', 'background:' + changeOpacity(theme.sidebarTextActiveColor, 0.05), 1);
changeCss('.search-help-popover .search-autocomplete__item.selected', 'background:' + changeOpacity(theme.sidebarTextActiveColor, 0.15), 1);
} }
if (theme.sidebarHeaderBg) { if (theme.sidebarHeaderBg) {

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

@@ -37,6 +37,9 @@ body {
img { img {
max-width: 100%; max-width: 100%;
height: auto; height: auto;
&.rounded {
@include border-radius(100%);
}
} }
.popover { .popover {
@@ -122,6 +125,9 @@ a:focus, a:hover {
&.no-resize { &.no-resize {
resize: none; resize: none;
} }
&.min-height {
min-height: 100px;
}
} }
.form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { .form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control {

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

@@ -113,11 +113,10 @@
text-align: center; text-align: center;
padding: 2em 1em; padding: 2em 1em;
.primary-message { .primary-message {
font-size: 1.2em; font-size: 1.25em;
} }
.secondary-message { .secondary-message {
font-size: 1.25em; @include opacity(0.8);
color: #888;
margin: 1em 0 0; margin: 1em 0 0;
} }
} }

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

@@ -28,6 +28,36 @@
@include single-transition(opacity, 0.3s, ease-in); @include single-transition(opacity, 0.3s, ease-in);
font-size: em(13px); font-size: em(13px);
&.autocomplete {
display: block;
.popover-content {
padding: 10px;
position: relative;
}
}
.search-autocomplete__item {
cursor: pointer;
padding: 6px 8px;
margin: 3px 0;
@include border-radius(2px);
&:hover {
background: rgba(black, 0.1);
}
&.selected {
background: rgba(black, 0.2);
}
.profile-img {
margin-top: -1px;
height: 16px;
margin-right: 6px;
width: 16px;
}
}
&.bottom > .arrow { &.bottom > .arrow {
top: -18px; top: -18px;
border-width: 9px; border-width: 9px;

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

@@ -379,7 +379,9 @@
} }
.btn { .btn {
&.btn-primary { &.btn-primary {
margin: 8px 0 0 -10px; display: block;
margin: 10px 0 6px;
width: 100%;
float: none; float: none;
} }
} }
@@ -401,7 +403,13 @@
&.minimize-settings { &.minimize-settings {
display: block; display: block;
.section-edit { .section-edit {
text-align: left; position: absolute;
top: 7px;
right: 0;
width: 50px;
.fa {
display: inline-block;
}
} }
} }
.no-padding--left { .no-padding--left {

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

@@ -108,44 +108,4 @@
.search-highlight { .search-highlight {
background-color: #FFF2BB; background-color: #FFF2BB;
} }
.search-autocomplete {
background-color: #fff;
border: $border-gray;
line-height: 36px;
overflow-x: hidden;
overflow-y: scroll;
position: absolute;
text-align: left;
width: 100%;
z-index: 100;
@extend %popover-box-shadow;
}
.search-autocomplete__channel {
cursor: pointer;
height: 36px;
padding: 0px 6px;
&.selected {
background-color:rgba(51, 51, 51, 0.15);
}
}
.search-autocomplete__user {
cursor: pointer;
height: 36px;
padding: 0px;
.profile-img {
height: 32px;
margin-right: 6px;
width: 32px;
@include border-radius(16px);
}
&.selected {
background-color:rgba(51, 51, 51, 0.15);
}
}

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

@@ -33,6 +33,33 @@
label { label {
font-weight: 600; font-weight: 600;
} }
.no-padding--left {
padding-left: 0;
}
.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;
&.text-left {
text-align: left;
}
}
}
.settings-table { .settings-table {
display: table; display: table;
table-layout: fixed; table-layout: fixed;
@@ -44,7 +71,7 @@
.nav { .nav {
position: fixed; position: fixed;
top: 57px; top: 57px;
width: 180px; width: 179px;
} }
.security-links { .security-links {
margin-right: 20px; margin-right: 20px;
@@ -66,6 +93,7 @@
padding: 1em 0; padding: 1em 0;
margin-bottom: 0; margin-bottom: 0;
cursor: pointer; cursor: pointer;
position: relative;
@include clearfix; @include clearfix;
&:hover { &:hover {
background: #f9f9f9; background: #f9f9f9;
@@ -170,33 +198,6 @@
.has-error { .has-error {
color: #a94442; color: #a94442;
} }
.no-padding--left {
padding-left: 0;
}
.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;
&.text-left {
text-align: left;
}
}
}
.file-status { .file-status {
font-size: 13px; font-size: 13px;