Conflicts:
	web/react/components/popover_list_members.jsx
	web/react/components/user_profile.jsx
Этот коммит содержится в:
Asaad Mahmood
2015-10-16 23:19:23 +05:00
родитель e840cb612f 3bd0a15341
Коммит 7849a48a85
15 изменённых файлов: 152 добавлений и 102 удалений

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

@@ -60,9 +60,10 @@ func TestGetAllPreferences(t *testing.T) {
Client.LoginByEmail(team.Name, user2.Email, "pwd") Client.LoginByEmail(team.Name, user2.Email, "pwd")
// note that user2 will automatically have a preference set for them to show user1 for direct messages
if result, err := Client.GetAllPreferences(); err != nil { if result, err := Client.GetAllPreferences(); err != nil {
t.Fatal(err) t.Fatal(err)
} else if data := result.Data.(model.Preferences); len(data) != 0 { } else if data := result.Data.(model.Preferences); len(data) != 1 {
t.Fatal("received the wrong number of preferences") t.Fatal("received the wrong number of preferences")
} }
} }

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

@@ -2,6 +2,13 @@
The following install instructions are for single-container installs of Mattermost using Docker for exploring product functionality and upgrading to newer versions. The following install instructions are for single-container installs of Mattermost using Docker for exploring product functionality and upgrading to newer versions.
### One-line Docker Install ###
If you have Docker set up, Mattermost installs in one-line:
`docker run --name mattermost-dev -d --publish 8065:80 mattermost/platform`
Otherwise, see step-by-step available:
### Mac OSX ### ### Mac OSX ###
1. Install Docker Toolbox using instructions at: http://docs.docker.com/installation/mac/ 1. Install Docker Toolbox using instructions at: http://docs.docker.com/installation/mac/

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

@@ -8,6 +8,11 @@ import (
"io" "io"
) )
const (
DEFAULT_WEBHOOK_USERNAME = "webhook"
DEFAULT_WEBHOOK_ICON = "/static/images/webhook_icon.jpg"
)
type IncomingWebhook struct { type IncomingWebhook struct {
Id string `json:"id"` Id string `json:"id"`
CreateAt int64 `json:"create_at"` CreateAt int64 `json:"create_at"`

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

@@ -440,9 +440,11 @@ export default class EmailSettings extends React.Component {
className='table table-bordered' className='table table-bordered'
cellPadding='5' cellPadding='5'
> >
<tr><td className='help-text'>{'None'}</td><td className='help-text'>{'Mattermost will send email over an unsecure connection.'}</td></tr> <tbody>
<tr><td className='help-text'>{'TLS'}</td><td className='help-text'>{'Encrypts the communication between Mattermost and your email server.'}</td></tr> <tr><td className='help-text'>{'None'}</td><td className='help-text'>{'Mattermost will send email over an unsecure connection.'}</td></tr>
<tr><td className='help-text'>{'STARTTLS'}</td><td className='help-text'>{'Takes an existing insecure connection and attempts to upgrade it to a secure connection using TLS.'}</td></tr> <tr><td className='help-text'>{'TLS'}</td><td className='help-text'>{'Encrypts the communication between Mattermost and your email server.'}</td></tr>
<tr><td className='help-text'>{'STARTTLS'}</td><td className='help-text'>{'Takes an existing insecure connection and attempts to upgrade it to a secure connection using TLS.'}</td></tr>
</tbody>
</table> </table>
</div> </div>
<div className='help-text'> <div className='help-text'>

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

@@ -249,22 +249,24 @@ export default class LogSettings extends React.Component {
onChange={this.handleChange} onChange={this.handleChange}
disabled={!this.state.fileEnable} disabled={!this.state.fileEnable}
/> />
<p className='help-text'> <div className='help-text'>
{'Format of log message output. If blank will be set to "[%D %T] [%L] %M", where:'} {'Format of log message output. If blank will be set to "[%D %T] [%L] %M", where:'}
<div className='help-text'> <div className='help-text'>
<table <table
className='table table-bordered' className='table table-bordered'
cellPadding='5' cellPadding='5'
> >
<tr><td className='help-text'>{'%T'}</td><td className='help-text'>{'Time (15:04:05 MST)'}</td></tr> <tbody>
<tr><td className='help-text'>{'%D'}</td><td className='help-text'>{'Date (2006/01/02)'}</td></tr> <tr><td className='help-text'>{'%T'}</td><td className='help-text'>{'Time (15:04:05 MST)'}</td></tr>
<tr><td className='help-text'>{'%d'}</td><td className='help-text'>{'Date (01/02/06)'}</td></tr> <tr><td className='help-text'>{'%D'}</td><td className='help-text'>{'Date (2006/01/02)'}</td></tr>
<tr><td className='help-text'>{'%L'}</td><td className='help-text'>{'Level (DEBG, INFO, EROR)'}</td></tr> <tr><td className='help-text'>{'%d'}</td><td className='help-text'>{'Date (01/02/06)'}</td></tr>
<tr><td className='help-text'>{'%S'}</td><td className='help-text'>{'Source'}</td></tr> <tr><td className='help-text'>{'%L'}</td><td className='help-text'>{'Level (DEBG, INFO, EROR)'}</td></tr>
<tr><td className='help-text'>{'%M'}</td><td className='help-text'>{'Message'}</td></tr> <tr><td className='help-text'>{'%S'}</td><td className='help-text'>{'Source'}</td></tr>
<tr><td className='help-text'>{'%M'}</td><td className='help-text'>{'Message'}</td></tr>
</tbody>
</table> </table>
</div> </div>
</p> </div>
</div> </div>
</div> </div>

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

@@ -70,7 +70,7 @@ export default class EditPostModal extends React.Component {
refocusId: options.refocusId || '' refocusId: options.refocusId || ''
}); });
$(React.findDOMNode(this.refs.modal)).modal('show'); $(ReactDOM.findDOMNode(this.refs.modal)).modal('show');
} }
componentDidMount() { componentDidMount() {
var self = this; var self = this;
@@ -92,7 +92,7 @@ export default class EditPostModal extends React.Component {
$('#edit_textbox').get(0).focus(); $('#edit_textbox').get(0).focus();
}); });
$(React.findDOMNode(this.refs.modal)).on('hide.bs.modal', function onShown() { $(ReactDOM.findDOMNode(this.refs.modal)).on('hide.bs.modal', function onShown() {
if (self.state.refocusId !== '') { if (self.state.refocusId !== '') {
setTimeout(() => { setTimeout(() => {
$(self.state.refocusId).get(0).focus(); $(self.state.refocusId).get(0).focus();

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

@@ -35,13 +35,20 @@ export default class PopoverListMembers extends React.Component {
const teamMembers = UserStore.getProfilesUsernameMap(); const teamMembers = UserStore.getProfilesUsernameMap();
if (members && teamMembers) { if (members && teamMembers) {
members.sort(function compareByLocal(a, b) { members.sort((a, b) => {
return a.username.localeCompare(b.username); return a.username.localeCompare(b.username);
}); });
members.forEach(function addMemberElement(m) { members.forEach((m, i) => {
if (teamMembers[m.username] && teamMembers[m.username].delete_at <= 0) { if (teamMembers[m.username] && teamMembers[m.username].delete_at <= 0) {
popoverHtml.push(<div className='text--nowrap'>{m.username}</div>); popoverHtml.push(
<div
className='text--nowrap'
key={'popover-member-' + i}
>
{m.username}
</div>
);
count++; count++;
} }
}); });
@@ -58,7 +65,14 @@ export default class PopoverListMembers extends React.Component {
trigger='click' trigger='click'
placement='bottom' placement='bottom'
rootClose={true} rootClose={true}
overlay={<Popover title='Members'>{popoverHtml}</Popover>} overlay={
<Popover
title='Members'
id='member-list-popover'
>
{popoverHtml}
</Popover>
}
> >
<div id='member_popover'> <div id='member_popover'>
<div> <div>

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

@@ -29,7 +29,7 @@ export default class RhsComment extends React.Component {
var post = this.props.post; var post = this.props.post;
Client.createPost(post, post.channel_id, Client.createPost(post, post.channel_id,
function success(data) { (data) => {
AsyncClient.getPosts(post.channel_id); AsyncClient.getPosts(post.channel_id);
var channel = ChannelStore.get(post.channel_id); var channel = ChannelStore.get(post.channel_id);
@@ -43,11 +43,11 @@ export default class RhsComment extends React.Component {
post: data post: data
}); });
}, },
function fail() { () => {
post.state = Constants.POST_FAILED; post.state = Constants.POST_FAILED;
PostStore.updatePendingPost(post); PostStore.updatePendingPost(post);
this.forceUpdate(); this.forceUpdate();
}.bind(this) }
); );
post.state = Constants.POST_LOADING; post.state = Constants.POST_LOADING;
@@ -84,7 +84,10 @@ export default class RhsComment extends React.Component {
if (isOwner) { if (isOwner) {
dropdownContents.push( dropdownContents.push(
<li role='presentation'> <li
role='presentation'
key='edit-button'
>
<a <a
href='#' href='#'
role='menuitem' role='menuitem'
@@ -95,7 +98,7 @@ export default class RhsComment extends React.Component {
data-postid={post.id} data-postid={post.id}
data-channelid={post.channel_id} data-channelid={post.channel_id}
> >
Edit {'Edit'}
</a> </a>
</li> </li>
); );
@@ -103,7 +106,10 @@ export default class RhsComment extends React.Component {
if (isOwner || isAdmin) { if (isOwner || isAdmin) {
dropdownContents.push( dropdownContents.push(
<li role='presentation'> <li
role='presentation'
key='delete-button'
>
<a <a
href='#' href='#'
role='menuitem' role='menuitem'
@@ -114,7 +120,7 @@ export default class RhsComment extends React.Component {
data-channelid={post.channel_id} data-channelid={post.channel_id}
data-comments={0} data-comments={0}
> >
Delete {'Delete'}
</a> </a>
</li> </li>
); );
@@ -162,7 +168,7 @@ export default class RhsComment extends React.Component {
href='#' href='#'
onClick={this.retryComment} onClick={this.retryComment}
> >
Retry {'Retry'}
</a> </a>
); );
} else if (post.state === Constants.POST_LOADING) { } else if (post.state === Constants.POST_LOADING) {
@@ -213,14 +219,14 @@ export default class RhsComment extends React.Component {
</li> </li>
</ul> </ul>
<div className='post-body'> <div className='post-body'>
<p className={postClass}> <div className={postClass}>
{loading} {loading}
<div <div
ref='message_holder' ref='message_holder'
onClick={TextFormatting.handleClick} onClick={TextFormatting.handleClick}
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(post.message)}} dangerouslySetInnerHTML={{__html: TextFormatting.formatText(post.message)}}
/> />
</p> </div>
{fileAttachment} {fileAttachment}
</div> </div>
</div> </div>

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

@@ -46,7 +46,7 @@ export default class Sidebar extends React.Component {
const state = this.getStateFromStores(); const state = this.getStateFromStores();
state.newChannelModalType = ''; state.newChannelModalType = '';
state.showMoreDirectChannelsModal = false; state.showDirectChannelsModal = false;
state.loadingDMChannel = -1; state.loadingDMChannel = -1;
this.state = state; this.state = state;
@@ -471,7 +471,9 @@ export default class Sidebar extends React.Component {
} }
let closeButton = null; let closeButton = null;
const removeTooltip = <Tooltip>{'Remove from list'}</Tooltip>; const removeTooltip = (
<Tooltip id='remove-dm-tooltip'>{'Remove from list'}</Tooltip>
);
if (handleClose && !badge) { if (handleClose && !badge) {
closeButton = ( closeButton = (
<OverlayTrigger <OverlayTrigger
@@ -564,8 +566,12 @@ export default class Sidebar extends React.Component {
showChannelModal = true; showChannelModal = true;
} }
const createChannelTootlip = <Tooltip>{'Create new channel'}</Tooltip>; const createChannelTootlip = (
const createGroupTootlip = <Tooltip>{'Create new group'}</Tooltip>; <Tooltip id='new-channel-tooltip' >{'Create new channel'}</Tooltip>
);
const createGroupTootlip = (
<Tooltip id='new-group-tooltip'>{'Create new group'}</Tooltip>
);
return ( return (
<div> <div>

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

@@ -65,19 +65,29 @@ export default class UserProfile extends React.Component {
var dataContent = []; var dataContent = [];
dataContent.push( dataContent.push(
<img className='user-popover__image' <img
className='user-popover__image'
src={'/api/v1/users/' + this.state.profile.id + '/image?time=' + this.state.profile.update_at} src={'/api/v1/users/' + this.state.profile.id + '/image?time=' + this.state.profile.update_at}
height='128' height='128'
width='128' width='128'
key='user-popover-image'
/> />
); );
if (!global.window.config.ShowEmailAddress === 'true') { if (!global.window.config.ShowEmailAddress === 'true') {
dataContent.push(<div className='text-nowrap'>{'Email not shared'}</div>); dataContent.push(
<div
className='text-nowrap'
key='user-popover-no-email'
>
{'Email not shared'}
</div>
);
} else { } else {
dataContent.push( dataContent.push(
<div <div
data-toggle='tooltip' data-toggle='tooltip'
title="' + this.state.profile.email + '" title="' + this.state.profile.email + '"
key='user-popover-email'
> >
<a <a
href="mailto:' + this.state.profile.email + '" href="mailto:' + this.state.profile.email + '"
@@ -94,14 +104,21 @@ export default class UserProfile extends React.Component {
trigger='click' trigger='click'
placement='right' placement='right'
rootClose={true} rootClose={true}
overlay={<Popover title={this.state.profile.username}>{dataContent}</Popover>} overlay={
<Popover
title={this.state.profile.username}
id='user-profile-popover'
>
{dataContent}
</Popover>
}
> >
<div <div
className='user-popover' className='user-popover'
id={'profile_' + this.uniqueId} id={'profile_' + this.uniqueId}
> >
{name} {name}
</div> </div>
</OverlayTrigger> </OverlayTrigger>
); );
} }

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

@@ -152,9 +152,8 @@ export default class UserSettingsAppearance extends React.Component {
<input type='radio' <input type='radio'
checked={!displayCustom} checked={!displayCustom}
onChange={this.updateType.bind(this, 'premade')} onChange={this.updateType.bind(this, 'premade')}
> />
{'Theme Colors'} {'Theme Colors'}
</input>
</label> </label>
<br/> <br/>
</div> </div>
@@ -164,9 +163,8 @@ export default class UserSettingsAppearance extends React.Component {
<input type='radio' <input type='radio'
checked={displayCustom} checked={displayCustom}
onChange={this.updateType.bind(this, 'custom')} onChange={this.updateType.bind(this, 'custom')}
> />
{'Custom Theme'} {'Custom Theme'}
</input>
</label> </label>
<br/> <br/>
</div> </div>

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

@@ -1,7 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information. // See License.txt for license information.
import { savePreferences } from '../../utils/client.jsx'; import {savePreferences} from '../../utils/client.jsx';
import SettingItemMin from '../setting_item_min.jsx'; import SettingItemMin from '../setting_item_min.jsx';
import SettingItemMax from '../setting_item_max.jsx'; import SettingItemMax from '../setting_item_max.jsx';
import Constants from '../../utils/constants.jsx'; import Constants from '../../utils/constants.jsx';
@@ -38,7 +38,7 @@ export default class UserSettingsDisplay extends React.Component {
); );
} }
handleClockRadio(militaryTime) { handleClockRadio(militaryTime) {
this.setState({militaryTime: militaryTime}); this.setState({militaryTime});
} }
updateSection(section) { updateSection(section) {
this.setState(getDisplayStateFromStores()); this.setState(getDisplayStateFromStores());
@@ -57,7 +57,7 @@ export default class UserSettingsDisplay extends React.Component {
const serverError = this.state.serverError || null; const serverError = this.state.serverError || null;
let clockSection; let clockSection;
if (this.props.activeSection === 'clock') { if (this.props.activeSection === 'clock') {
let clockFormat = [false, false]; const clockFormat = [false, false];
if (this.state.militaryTime === 'true') { if (this.state.militaryTime === 'true') {
clockFormat[1] = true; clockFormat[1] = true;
} else { } else {
@@ -77,9 +77,8 @@ export default class UserSettingsDisplay extends React.Component {
type='radio' type='radio'
checked={clockFormat[0]} checked={clockFormat[0]}
onChange={this.handleClockRadio.bind(this, 'false')} onChange={this.handleClockRadio.bind(this, 'false')}
> />
12-hour clock (example: 4:00 PM) {'12-hour clock (example: 4:00 PM)'}
</input>
</label> </label>
<br/> <br/>
</div> </div>
@@ -89,9 +88,8 @@ export default class UserSettingsDisplay extends React.Component {
type='radio' type='radio'
checked={clockFormat[1]} checked={clockFormat[1]}
onChange={this.handleClockRadio.bind(this, 'true')} onChange={this.handleClockRadio.bind(this, 'true')}
> />
24-hour clock (example: 16:00) {'24-hour clock (example: 16:00)'}
</input>
</label> </label>
<br/> <br/>
</div> </div>
@@ -99,7 +97,6 @@ export default class UserSettingsDisplay extends React.Component {
</div> </div>
]; ];
clockSection = ( clockSection = (
<SettingItemMax <SettingItemMax
title='Clock Display' title='Clock Display'
@@ -138,13 +135,13 @@ export default class UserSettingsDisplay extends React.Component {
className='close' className='close'
data-dismiss='modal' data-dismiss='modal'
aria-label='Close' aria-label='Close'
> >
<span aria-hidden='true'>{'×'}</span> <span aria-hidden='true'>{'×'}</span>
</button> </button>
<h4 <h4
className='modal-title' className='modal-title'
ref='title' ref='title'
> >
<i className='modal-back'></i> <i className='modal-back'></i>
{'Display Settings'} {'Display Settings'}
</h4> </h4>

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

@@ -228,9 +228,8 @@ export default class NotificationsTab extends React.Component {
<input type='radio' <input type='radio'
checked={notifyActive[0]} checked={notifyActive[0]}
onChange={this.handleNotifyRadio.bind(this, 'all')} onChange={this.handleNotifyRadio.bind(this, 'all')}
> />
For all activity {'For all activity'}
</input>
</label> </label>
<br/> <br/>
</div> </div>
@@ -240,9 +239,8 @@ export default class NotificationsTab extends React.Component {
type='radio' type='radio'
checked={notifyActive[1]} checked={notifyActive[1]}
onChange={this.handleNotifyRadio.bind(this, 'mention')} onChange={this.handleNotifyRadio.bind(this, 'mention')}
> />
Only for mentions and direct messages {'Only for mentions and direct messages'}
</input>
</label> </label>
<br/> <br/>
</div> </div>
@@ -252,9 +250,8 @@ export default class NotificationsTab extends React.Component {
type='radio' type='radio'
checked={notifyActive[2]} checked={notifyActive[2]}
onChange={this.handleNotifyRadio.bind(this, 'none')} onChange={this.handleNotifyRadio.bind(this, 'none')}
> />
Never {'Never'}
</input>
</label> </label>
</div> </div>
</div> </div>
@@ -320,9 +317,8 @@ export default class NotificationsTab extends React.Component {
type='radio' type='radio'
checked={soundActive[0]} checked={soundActive[0]}
onChange={this.handleSoundRadio.bind(this, 'true')} onChange={this.handleSoundRadio.bind(this, 'true')}
> />
On {'On'}
</input>
</label> </label>
<br/> <br/>
</div> </div>
@@ -332,9 +328,8 @@ export default class NotificationsTab extends React.Component {
type='radio' type='radio'
checked={soundActive[1]} checked={soundActive[1]}
onChange={this.handleSoundRadio.bind(this, 'false')} onChange={this.handleSoundRadio.bind(this, 'false')}
> />
Off {'Off'}
</input>
</label> </label>
<br/> <br/>
</div> </div>
@@ -402,9 +397,8 @@ export default class NotificationsTab extends React.Component {
type='radio' type='radio'
checked={emailActive[0]} checked={emailActive[0]}
onChange={this.handleEmailRadio.bind(this, 'true')} onChange={this.handleEmailRadio.bind(this, 'true')}
> />
On {'On'}
</input>
</label> </label>
<br/> <br/>
</div> </div>
@@ -414,9 +408,8 @@ export default class NotificationsTab extends React.Component {
type='radio' type='radio'
checked={emailActive[1]} checked={emailActive[1]}
onChange={this.handleEmailRadio.bind(this, 'false')} onChange={this.handleEmailRadio.bind(this, 'false')}
> />
Off {'Off'}
</input>
</label> </label>
<br/> <br/>
</div> </div>
@@ -482,9 +475,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox' type='checkbox'
checked={this.state.firstNameKey} checked={this.state.firstNameKey}
onChange={handleUpdateFirstNameKey} onChange={handleUpdateFirstNameKey}
> />
{'Your case sensitive first name "' + user.first_name + '"'} {'Your case sensitive first name "' + user.first_name + '"'}
</input>
</label> </label>
</div> </div>
</div> </div>
@@ -502,9 +494,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox' type='checkbox'
checked={this.state.usernameKey} checked={this.state.usernameKey}
onChange={handleUpdateUsernameKey} onChange={handleUpdateUsernameKey}
> />
{'Your non-case sensitive username "' + user.username + '"'} {'Your non-case sensitive username "' + user.username + '"'}
</input>
</label> </label>
</div> </div>
</div> </div>
@@ -521,9 +512,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox' type='checkbox'
checked={this.state.mentionKey} checked={this.state.mentionKey}
onChange={handleUpdateMentionKey} onChange={handleUpdateMentionKey}
> />
{'Your username mentioned "@' + user.username + '"'} {'Your username mentioned "@' + user.username + '"'}
</input>
</label> </label>
</div> </div>
</div> </div>
@@ -540,9 +530,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox' type='checkbox'
checked={this.state.allKey} checked={this.state.allKey}
onChange={handleUpdateAllKey} onChange={handleUpdateAllKey}
> />
{'Team-wide mentions "@all"'} {'Team-wide mentions "@all"'}
</input>
</label> </label>
</div> </div>
</div> </div>
@@ -559,9 +548,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox' type='checkbox'
checked={this.state.channelKey} checked={this.state.channelKey}
onChange={handleUpdateChannelKey} onChange={handleUpdateChannelKey}
> />
{'Channel-wide mentions "@channel"'} {'Channel-wide mentions "@channel"'}
</input>
</label> </label>
</div> </div>
</div> </div>
@@ -576,9 +564,8 @@ export default class NotificationsTab extends React.Component {
type='checkbox' type='checkbox'
checked={this.state.customKeysChecked} checked={this.state.customKeysChecked}
onChange={this.updateCustomMentionKeys} onChange={this.updateCustomMentionKeys}
> />
{'Other non-case sensitive words, separated by commas:'} {'Other non-case sensitive words, separated by commas:'}
</input>
</label> </label>
</div> </div>
<input <input

Двоичные данные
web/static/images/webhook_icon.jpg Обычный файл

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 67 KiB

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

@@ -971,12 +971,20 @@ func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) {
post := &model.Post{UserId: hook.UserId, ChannelId: channel.Id, Message: text} post := &model.Post{UserId: hook.UserId, ChannelId: channel.Id, Message: text}
post.AddProp("from_webhook", "true") post.AddProp("from_webhook", "true")
if len(overrideUsername) != 0 && utils.Cfg.ServiceSettings.EnablePostUsernameOverride { if utils.Cfg.ServiceSettings.EnablePostUsernameOverride {
post.AddProp("override_username", overrideUsername) if len(overrideUsername) != 0 {
post.AddProp("override_username", overrideUsername)
} else {
post.AddProp("override_username", model.DEFAULT_WEBHOOK_USERNAME)
}
} }
if len(overrideIconUrl) != 0 && utils.Cfg.ServiceSettings.EnablePostIconOverride { if utils.Cfg.ServiceSettings.EnablePostIconOverride {
post.AddProp("override_icon_url", overrideIconUrl) if len(overrideIconUrl) != 0 {
post.AddProp("override_icon_url", overrideIconUrl)
} else {
post.AddProp("override_icon_url", model.DEFAULT_WEBHOOK_ICON)
}
} }
if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN { if !c.HasPermissionsToChannel(pchan, "createIncomingHook") && channel.Type != model.CHANNEL_OPEN {