summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--api/channel.go8
-rw-r--r--api/channel_test.go3
-rw-r--r--api/post.go8
-rw-r--r--config/config.json4
-rw-r--r--doc/integrations/webhooks/Outgoing-Webhooks.md4
-rw-r--r--docker/1.2/Dockerfile2
-rw-r--r--docker/1.2/config_docker.json4
-rw-r--r--docker/dev/config_docker.json4
-rw-r--r--docker/local/config_docker.json4
-rw-r--r--model/version.go1
-rw-r--r--utils/textgeneration.go15
-rw-r--r--web/react/components/channel_header.jsx41
-rw-r--r--web/react/components/navbar.jsx56
-rw-r--r--web/react/components/post_body.jsx38
-rw-r--r--web/react/components/rename_channel_modal.jsx51
-rw-r--r--web/sass-files/sass/partials/_forms.scss4
-rw-r--r--web/sass-files/sass/partials/_responsive.scss2
-rw-r--r--web/sass-files/sass/partials/_videos.scss2
-rw-r--r--web/web.go2
20 files changed, 149 insertions, 106 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 74c5b5208..3e423557d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -98,7 +98,7 @@ Multiple settings were added to [`config.json`](./config/config.json). These opt
- Added: `"RestrictTeamNames": true` to control whether team names can contain reserved words like www, admin, support, test, etc.
- Added: `"EnableTeamListing": false` to control whether teams can be listed on the root page of the site
- Under `ServiceSettings` in `config.json`
- - Added: `EnableOutgoingWebhooks": true` to turn on outgoing webhooks
+ - Added: `EnableOutgoingWebhooks": false` to control whether outgoing webhooks are enabled
#### Database Changes from v1.1 to v1.2
diff --git a/api/channel.go b/api/channel.go
index 75ca9680d..99640e71a 100644
--- a/api/channel.go
+++ b/api/channel.go
@@ -205,9 +205,11 @@ func updateChannel(c *Context, w http.ResponseWriter, r *http.Request) {
}
if oldChannel.Name == model.DEFAULT_CHANNEL {
- c.Err = model.NewAppError("updateChannel", "Cannot update the default channel "+model.DEFAULT_CHANNEL, "")
- c.Err.StatusCode = http.StatusForbidden
- return
+ if (len(channel.Name) > 0 && channel.Name != oldChannel.Name) || (len(channel.Type) > 0 && channel.Type != oldChannel.Type) {
+ c.Err = model.NewAppError("updateChannel", "Tried to perform an invalid update of the default channel "+model.DEFAULT_CHANNEL, "")
+ c.Err.StatusCode = http.StatusForbidden
+ return
+ }
}
oldChannel.Header = channel.Header
diff --git a/api/channel_test.go b/api/channel_test.go
index faed387dd..e7e1f4eb0 100644
--- a/api/channel_test.go
+++ b/api/channel_test.go
@@ -215,8 +215,9 @@ func TestUpdateChannel(t *testing.T) {
for _, c := range data.Channels {
if c.Name == model.DEFAULT_CHANNEL {
c.Header = "new header"
+ c.Name = "pseudo-square"
if _, err := Client.UpdateChannel(c); err == nil {
- t.Fatal("should have errored on updating default channel")
+ t.Fatal("should have errored on updating default channel name")
}
break
}
diff --git a/api/post.go b/api/post.go
index 3892d4ee8..ef70e1336 100644
--- a/api/post.go
+++ b/api/post.go
@@ -229,6 +229,14 @@ func handlePostEventsAndForget(c *Context, post *model.Post, triggerWebhooks boo
func handleWebhookEventsAndForget(c *Context, post *model.Post, team *model.Team, channel *model.Channel, user *model.User) {
go func() {
+ if !utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
+ return
+ }
+
+ if channel.Type != model.CHANNEL_OPEN {
+ return
+ }
+
hchan := Srv.Store.Webhook().GetOutgoingByTeam(c.Session.TeamId)
hooks := []*model.OutgoingWebhook{}
diff --git a/config/config.json b/config/config.json
index a927620b5..932bed8a2 100644
--- a/config/config.json
+++ b/config/config.json
@@ -5,8 +5,8 @@
"SegmentDeveloperKey": "",
"GoogleDeveloperKey": "",
"EnableOAuthServiceProvider": false,
- "EnableIncomingWebhooks": true,
- "EnableOutgoingWebhooks": true,
+ "EnableIncomingWebhooks": false,
+ "EnableOutgoingWebhooks": false,
"EnablePostUsernameOverride": false,
"EnablePostIconOverride": false,
"EnableTesting": false,
diff --git a/doc/integrations/webhooks/Outgoing-Webhooks.md b/doc/integrations/webhooks/Outgoing-Webhooks.md
index 008245715..5fbbb9d87 100644
--- a/doc/integrations/webhooks/Outgoing-Webhooks.md
+++ b/doc/integrations/webhooks/Outgoing-Webhooks.md
@@ -1,7 +1,5 @@
# Outgoing Webhooks
-#### [To be released in Mattermost v1.2, available now on master]
-
Outgoing webhooks allow external applications, written in the programming language of your choice--to receive HTTP POST requests whenever a user posts to a certain channel, with a trigger word at the beginning of the message, or a combination of both. If the external application responds appropriately to the HTTP request, as response post can be made in the channel where the original post occurred.
A couple key points:
@@ -36,7 +34,7 @@ Which would render in a Mattermost message as follows:
---
### Enabling Outgoing Webhooks
-Outgoing webhooks should be enabled on your Mattermost instance by default, but if they are not you'll need to get your system administrator to enable them. If you are the system administrator you can enable them by doing the following:
+Outgoing webhooks are off by default, and can be enabled by the system administrator. If you are the system administrator you can enable them by doing the following:
1. Login to your Mattermost team account that has the system administrator role.
1. Enable outgoing webhooks from **System Console -> Service Settings**.
diff --git a/docker/1.2/Dockerfile b/docker/1.2/Dockerfile
index cb2b58f53..e00c4e5ca 100644
--- a/docker/1.2/Dockerfile
+++ b/docker/1.2/Dockerfile
@@ -34,7 +34,7 @@ VOLUME /var/lib/mysql
WORKDIR /mattermost
# Copy over files
-ADD https://github.com/mattermost/platform/releases/download/v1.2.0/mattermost.tar.gz /
+ADD https://github.com/mattermost/platform/releases/download/v1.2.1/mattermost.tar.gz /
RUN tar -zxvf /mattermost.tar.gz --strip-components=1 && rm /mattermost.tar.gz
ADD config_docker.json /
ADD docker-entry.sh /
diff --git a/docker/1.2/config_docker.json b/docker/1.2/config_docker.json
index 80e6ab14e..c23a72cd1 100644
--- a/docker/1.2/config_docker.json
+++ b/docker/1.2/config_docker.json
@@ -5,8 +5,8 @@
"SegmentDeveloperKey": "",
"GoogleDeveloperKey": "",
"EnableOAuthServiceProvider": false,
- "EnableIncomingWebhooks": true,
- "EnableOutgoingWebhooks": true,
+ "EnableIncomingWebhooks": false,
+ "EnableOutgoingWebhooks": false,
"EnablePostUsernameOverride": false,
"EnablePostIconOverride": false,
"EnableTesting": false,
diff --git a/docker/dev/config_docker.json b/docker/dev/config_docker.json
index 80e6ab14e..c23a72cd1 100644
--- a/docker/dev/config_docker.json
+++ b/docker/dev/config_docker.json
@@ -5,8 +5,8 @@
"SegmentDeveloperKey": "",
"GoogleDeveloperKey": "",
"EnableOAuthServiceProvider": false,
- "EnableIncomingWebhooks": true,
- "EnableOutgoingWebhooks": true,
+ "EnableIncomingWebhooks": false,
+ "EnableOutgoingWebhooks": false,
"EnablePostUsernameOverride": false,
"EnablePostIconOverride": false,
"EnableTesting": false,
diff --git a/docker/local/config_docker.json b/docker/local/config_docker.json
index 80e6ab14e..c23a72cd1 100644
--- a/docker/local/config_docker.json
+++ b/docker/local/config_docker.json
@@ -5,8 +5,8 @@
"SegmentDeveloperKey": "",
"GoogleDeveloperKey": "",
"EnableOAuthServiceProvider": false,
- "EnableIncomingWebhooks": true,
- "EnableOutgoingWebhooks": true,
+ "EnableIncomingWebhooks": false,
+ "EnableOutgoingWebhooks": false,
"EnablePostUsernameOverride": false,
"EnablePostIconOverride": false,
"EnableTesting": false,
diff --git a/model/version.go b/model/version.go
index 6eae436bc..af99717cd 100644
--- a/model/version.go
+++ b/model/version.go
@@ -12,6 +12,7 @@ import (
// It should be maitained in chronological order with most current
// release at the front of the list.
var versions = []string{
+ "1.2.1",
"1.2.0",
"1.1.0",
"1.0.0",
diff --git a/utils/textgeneration.go b/utils/textgeneration.go
index affd65bc1..31b6517b8 100644
--- a/utils/textgeneration.go
+++ b/utils/textgeneration.go
@@ -126,6 +126,13 @@ http://en.wikipedia.org/wiki/Foo
https://vine.co/v/eDeVgbFrt9L
`,
+ `**[7] [Image Test]**
+
+## this *should* display an image
+
+http://37.media.tumblr.com/tumblr_mavsumGGAd1qboaw8o1_500.jpg
+`,
+
/* `**[2] [Username Linking Test]**
I saw @alice--and I said "Hi @alice!" then "What's up @alice?" and then @alice, was totally @alice; she just "@alice"'d me and walked on by. That's @alice...
@alice‽‽
@@ -134,7 +141,7 @@ https://vine.co/v/eDeVgbFrt9L
`**[3] [Mention Highlighting Test]**
`,*/
- `**[4] [Emoji Display Test 1]**
+ `**[8] [Emoji Display Test 1]**
:+1: :-1: :100: :1234: :8ball: :a: :ab: :abc: :abcd: :accept:
:aerial_tramway: :airplane: :alarm_clock: :ambulance: :anchor: :angel: :anger: :angry: :anguished: :ant:
:apple: :aquarius: :aries: :arrow_backward: :arrow_double_down: :arrow_double_up: :arrow_down: :arrow_down_small: :arrow_forward: :arrow_heading_down:
@@ -169,7 +176,7 @@ https://vine.co/v/eDeVgbFrt9L
:fork_and_knife: :fountain: :four: :four_leaf_clover: :fr: :free: :fried_shrimp: :fries: :frog: :frowning:
:fu: :fuelpump: :full_moon: :full_moon_with_face: :game_die: :gb: :gem: :gemini: :ghost: :gift:`,
- `**[5] [Emoji Display Test 2]**
+ `**[9] [Emoji Display Test 2]**
:gift_heart: :girl: :globe_with_meridians: :goat: :goberserk: :godmode: :golf: :grapes: :green_apple: :green_book:
:green_heart: :grey_exclamation: :grey_question: :grimacing: :grin: :grinning: :guardsman: :guitar: :gun: :haircut:
:hamburger: :hammer: :hamster: :hand: :handbag: :hankey: :hash: :hatched_chick: :hatching_chick: :headphones:
@@ -198,7 +205,7 @@ https://vine.co/v/eDeVgbFrt9L
:person_with_blond_hair: :person_with_pouting_face: :phone: :pig: :pig2: :pig_nose: :pill: :pineapple: :pisces: :pizza:
`,
- `**[6] [Emoji Display Test 3]**
+ `**[10] [Emoji Display Test 3]**
:plus1: :point_down: :point_left: :point_right: :point_up: :point_up_2: :police_car: :poodle: :poop: :post_office:
:postal_horn: :postbox: :potable_water: :pouch: :poultry_leg: :pound: :pouting_cat: :pray: :princess: :punch:
:purple_heart: :purse: :pushpin: :put_litter_in_its_place: :question: :rabbit: :rabbit2: :racehorse: :radio: :radio_button:
@@ -231,7 +238,7 @@ https://vine.co/v/eDeVgbFrt9L
Unnamed: :u5272: :u5408: :u55b6: :u6307: :u6708: :u6709: :u6e80: :u7121: :u7533: :u7981: :u7a7a:
`,
- `**[7] [Auto Linking]**
+ `**[11] [Auto Linking]**
#### should be turned into links:
http://example.com
https://example.com
diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx
index a8d4ec100..79c7f90a9 100644
--- a/web/react/components/channel_header.jsx
+++ b/web/react/components/channel_header.jsx
@@ -276,26 +276,27 @@ export default class ChannelHeader extends React.Component {
</li>
);
- if (!ChannelStore.isDefault(channel)) {
- if (isAdmin) {
- dropdownContents.push(
- <li
- key='rename_channel'
- role='presentation'
+ if (isAdmin) {
+ dropdownContents.push(
+ <li
+ key='rename_channel'
+ role='presentation'
+ >
+ <a
+ role='menuitem'
+ href='#'
+ data-toggle='modal'
+ data-target='#rename_channel'
+ data-display={channel.display_name}
+ data-name={channel.name}
+ data-channelid={channel.id}
>
- <a
- role='menuitem'
- href='#'
- data-toggle='modal'
- data-target='#rename_channel'
- data-display={channel.display_name}
- data-name={channel.name}
- data-channelid={channel.id}
- >
- {'Rename '}{channelTerm}{'...'}
- </a>
- </li>
- );
+ {'Rename '}{channelTerm}{'...'}
+ </a>
+ </li>
+ );
+
+ if (!ChannelStore.isDefault(channel)) {
dropdownContents.push(
<li
key='delete_channel'
@@ -314,7 +315,9 @@ export default class ChannelHeader extends React.Component {
</li>
);
}
+ }
+ if (!ChannelStore.isDefault(channel)) {
dropdownContents.push(
<li
key='leave_channel'
diff --git a/web/react/components/navbar.jsx b/web/react/components/navbar.jsx
index af29f219e..7ad1f9305 100644
--- a/web/react/components/navbar.jsx
+++ b/web/react/components/navbar.jsx
@@ -178,18 +178,35 @@ export default class Navbar extends React.Component {
var manageMembersOption;
var renameChannelOption;
var deleteChannelOption;
- if (!isDirect && isAdmin && !ChannelStore.isDefault(channel)) {
- manageMembersOption = (
- <li role='presentation'>
- <a
- role='menuitem'
- href='#'
- onClick={() => this.setState({showMembersModal: true})}
- >
- {'Manage Members'}
- </a>
- </li>
- );
+ if (!isDirect && isAdmin) {
+ if (!ChannelStore.isDefault(channel)) {
+ manageMembersOption = (
+ <li role='presentation'>
+ <a
+ role='menuitem'
+ href='#'
+ onClick={() => this.setState({showMembersModal: true})}
+ >
+ {'Manage Members'}
+ </a>
+ </li>
+ );
+
+ deleteChannelOption = (
+ <li role='presentation'>
+ <a
+ role='menuitem'
+ href='#'
+ data-toggle='modal'
+ data-target='#delete_channel'
+ data-title={channel.display_name}
+ data-channelid={channel.id}
+ >
+ {'Delete Channel...'}
+ </a>
+ </li>
+ );
+ }
renameChannelOption = (
<li role='presentation'>
@@ -206,21 +223,6 @@ export default class Navbar extends React.Component {
</a>
</li>
);
-
- deleteChannelOption = (
- <li role='presentation'>
- <a
- role='menuitem'
- href='#'
- data-toggle='modal'
- data-target='#delete_channel'
- data-title={channel.display_name}
- data-channelid={channel.id}
- >
- {'Delete Channel...'}
- </a>
- </li>
- );
}
var notificationPreferenceOption;
diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx
index 617b4b36c..975ac64dc 100644
--- a/web/react/components/post_body.jsx
+++ b/web/react/components/post_body.jsx
@@ -16,13 +16,13 @@ export default class PostBody extends React.Component {
super(props);
this.receivedYoutubeData = false;
- this.isGifLoading = false;
+ this.isImgLoading = false;
this.handleUserChange = this.handleUserChange.bind(this);
this.parseEmojis = this.parseEmojis.bind(this);
this.createEmbed = this.createEmbed.bind(this);
- this.createGifEmbed = this.createGifEmbed.bind(this);
- this.loadGif = this.loadGif.bind(this);
+ this.createImageEmbed = this.createImageEmbed.bind(this);
+ this.loadImg = this.loadImg.bind(this);
this.createYoutubeEmbed = this.createYoutubeEmbed.bind(this);
const linkData = Utils.extractLinks(this.props.post.message);
@@ -117,8 +117,12 @@ export default class PostBody extends React.Component {
return embed;
}
- if (link.substring(link.length - 4) === '.gif') {
- return this.createGifEmbed(link, this.state.gifLoaded);
+ for (let i = 0; i < Constants.IMAGE_TYPES.length; i++) {
+ const imageType = Constants.IMAGE_TYPES[i];
+ const suffix = link.substring(link.length - (imageType.length + 1));
+ if (suffix === '.' + imageType || suffix === '=' + imageType) {
+ return this.createImageEmbed(link, this.state.imgLoaded);
+ }
}
return null;
@@ -135,29 +139,29 @@ export default class PostBody extends React.Component {
return false;
}
- loadGif(src) {
- if (this.isGifLoading) {
+ loadImg(src) {
+ if (this.isImgLoading) {
return;
}
- this.isGifLoading = true;
+ this.isImgLoading = true;
- const gif = new Image();
- gif.onload = (
+ const img = new Image();
+ img.onload = (
() => {
- this.embed = this.createGifEmbed(src, true);
- this.setState({gifLoaded: true});
+ this.embed = this.createImageEmbed(src, true);
+ this.setState({imgLoaded: true});
}
);
- gif.src = src;
+ img.src = src;
}
- createGifEmbed(link, isLoaded) {
+ createImageEmbed(link, isLoaded) {
if (!isLoaded) {
- this.loadGif(link);
+ this.loadImg(link);
return (
<img
- className='gif-div placeholder'
+ className='img-div placeholder'
height='500px'
/>
);
@@ -165,7 +169,7 @@ export default class PostBody extends React.Component {
return (
<img
- className='gif-div'
+ className='img-div'
src={link}
/>
);
diff --git a/web/react/components/rename_channel_modal.jsx b/web/react/components/rename_channel_modal.jsx
index 9fb3af035..f47009cce 100644
--- a/web/react/components/rename_channel_modal.jsx
+++ b/web/react/components/rename_channel_modal.jsx
@@ -5,6 +5,7 @@ const Utils = require('../utils/utils.jsx');
const Client = require('../utils/client.jsx');
const AsyncClient = require('../utils/async_client.jsx');
const ChannelStore = require('../stores/channel_store.jsx');
+const Constants = require('../utils/constants.jsx');
export default class RenameChannelModal extends React.Component {
constructor(props) {
@@ -36,10 +37,10 @@ export default class RenameChannelModal extends React.Component {
return;
}
- let channel = ChannelStore.get(this.state.channelId);
+ const channel = ChannelStore.get(this.state.channelId);
const oldName = channel.name;
const oldDisplayName = channel.displayName;
- let state = {serverError: ''};
+ const state = {serverError: ''};
channel.display_name = this.state.displayName.trim();
if (!channel.display_name) {
@@ -60,7 +61,7 @@ export default class RenameChannelModal extends React.Component {
state.nameError = 'This field must be less than 22 characters';
state.invalid = true;
} else {
- let cleanedName = Utils.cleanUpUrlable(channel.name);
+ const cleanedName = Utils.cleanUpUrlable(channel.name);
if (cleanedName === channel.name) {
state.nameError = '';
} else {
@@ -76,7 +77,7 @@ export default class RenameChannelModal extends React.Component {
}
Client.updateChannel(channel,
- function handleUpdateSuccess() {
+ () => {
$(ReactDOM.findDOMNode(this.refs.modal)).modal('hide');
AsyncClient.getChannel(channel.id);
@@ -84,12 +85,12 @@ export default class RenameChannelModal extends React.Component {
ReactDOM.findDOMNode(this.refs.displayName).value = '';
ReactDOM.findDOMNode(this.refs.channelName).value = '';
- }.bind(this),
- function handleUpdateError(err) {
+ },
+ (err) => {
state.serverError = err.message;
state.invalid = true;
this.setState(state);
- }.bind(this)
+ }
);
}
onNameChange() {
@@ -99,10 +100,12 @@ export default class RenameChannelModal extends React.Component {
this.setState({displayName: ReactDOM.findDOMNode(this.refs.displayName).value});
}
displayNameKeyUp() {
- const displayName = ReactDOM.findDOMNode(this.refs.displayName).value.trim();
- const channelName = Utils.cleanUpUrlable(displayName);
- ReactDOM.findDOMNode(this.refs.channelName).value = channelName;
- this.setState({channelName: channelName});
+ if (this.state.channelName !== Constants.DEFAULT_CHANNEL) {
+ const displayName = ReactDOM.findDOMNode(this.refs.displayName).value.trim();
+ const channelName = Utils.cleanUpUrlable(displayName);
+ ReactDOM.findDOMNode(this.refs.channelName).value = channelName;
+ this.setState({channelName: channelName});
+ }
}
handleClose() {
this.setState({
@@ -150,6 +153,15 @@ export default class RenameChannelModal extends React.Component {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
}
+ let handleInputLabel = 'Handle';
+ let handleInputClass = 'form-control';
+ let readOnlyHandleInput = false;
+ if (this.state.channelName === Constants.DEFAULT_CHANNEL) {
+ handleInputLabel += ' - Cannot be changed for the default channel';
+ handleInputClass += ' disabled-input';
+ readOnlyHandleInput = true;
+ }
+
return (
<div
className='modal fade'
@@ -167,15 +179,15 @@ export default class RenameChannelModal extends React.Component {
className='close'
data-dismiss='modal'
>
- <span aria-hidden='true'>&times;</span>
- <span className='sr-only'>Close</span>
+ <span aria-hidden='true'>{'×'}</span>
+ <span className='sr-only'>{'Close'}</span>
</button>
- <h4 className='modal-title'>Rename Channel</h4>
+ <h4 className='modal-title'>{'Rename Channel'}</h4>
</div>
<form role='form'>
<div className='modal-body'>
<div className={displayNameClass}>
- <label className='control-label'>Display Name</label>
+ <label className='control-label'>{'Display Name'}</label>
<input
onKeyUp={this.displayNameKeyUp}
onChange={this.onDisplayNameChange}
@@ -190,15 +202,16 @@ export default class RenameChannelModal extends React.Component {
{displayNameError}
</div>
<div className={nameClass}>
- <label className='control-label'>Handle</label>
+ <label className='control-label'>{handleInputLabel}</label>
<input
onChange={this.onNameChange}
type='text'
- className='form-control'
+ className={handleInputClass}
ref='channelName'
placeholder='lowercase alphanumeric&#39;s only'
value={this.state.channelName}
maxLength='64'
+ readOnly={readOnlyHandleInput}
/>
{nameError}
</div>
@@ -210,14 +223,14 @@ export default class RenameChannelModal extends React.Component {
className='btn btn-default'
data-dismiss='modal'
>
- Cancel
+ {'Cancel'}
</button>
<button
onClick={this.handleSubmit}
type='submit'
className='btn btn-primary'
>
- Save
+ {'Save'}
</button>
</div>
</form>
diff --git a/web/sass-files/sass/partials/_forms.scss b/web/sass-files/sass/partials/_forms.scss
index 2d7b6cd26..685677ad0 100644
--- a/web/sass-files/sass/partials/_forms.scss
+++ b/web/sass-files/sass/partials/_forms.scss
@@ -43,3 +43,7 @@
margin: 10px 0 0;
color: #999;
}
+
+.disabled-input {
+ background-color: #dddddd !important;
+}
diff --git a/web/sass-files/sass/partials/_responsive.scss b/web/sass-files/sass/partials/_responsive.scss
index 966ae5cd1..a4bdc3e92 100644
--- a/web/sass-files/sass/partials/_responsive.scss
+++ b/web/sass-files/sass/partials/_responsive.scss
@@ -285,7 +285,7 @@
min-height: 100px;
}
}
- .gif-div {
+ .img-div {
max-width: 100%;
}
.tip-div {
diff --git a/web/sass-files/sass/partials/_videos.scss b/web/sass-files/sass/partials/_videos.scss
index bb36b6223..3f15f8f1e 100644
--- a/web/sass-files/sass/partials/_videos.scss
+++ b/web/sass-files/sass/partials/_videos.scss
@@ -51,7 +51,7 @@
border-left:60px solid rgba(255,255,255,0.4);
}
-.gif-div {
+.img-div {
-moz-force-broken-image-icon: 1;
position:relative;
max-width: 450px;
diff --git a/web/web.go b/web/web.go
index ffc791cb7..02ceb69ba 100644
--- a/web/web.go
+++ b/web/web.go
@@ -989,7 +989,7 @@ func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) {
}
text := parsedRequest.Text
- if len(text) == 0 {
+ if len(text) == 0 && parsedRequest.Attachments == nil {
c.Err = model.NewAppError("incomingWebhook", "No text specified", "")
return
}