summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/admin.go1
-rw-r--r--api/channel.go2
-rw-r--r--api/context.go4
-rw-r--r--api/post.go1
-rw-r--r--api/team.go1
-rw-r--r--api/user.go1
-rw-r--r--docker/2.0/Dockerfile2
-rw-r--r--web/react/components/team_signup_email_item.jsx2
-rw-r--r--web/react/components/team_signup_send_invites_page.jsx4
-rw-r--r--web/react/components/user_settings/manage_outgoing_hooks.jsx9
-rw-r--r--web/react/components/user_settings/user_settings_modal.jsx14
-rw-r--r--web/react/components/user_settings/user_settings_security.jsx8
-rw-r--r--web/react/stores/post_store.jsx17
-rw-r--r--web/react/stores/socket_store.jsx14
-rw-r--r--web/react/utils/async_client.jsx13
-rw-r--r--web/react/utils/utils.jsx4
-rw-r--r--web/templates/head.html1
17 files changed, 60 insertions, 38 deletions
diff --git a/api/admin.go b/api/admin.go
index e8cb8b3c7..d04991353 100644
--- a/api/admin.go
+++ b/api/admin.go
@@ -120,6 +120,7 @@ func getConfig(c *Context, w http.ResponseWriter, r *http.Request) {
cfg := model.ConfigFromJson(strings.NewReader(json))
json = cfg.ToJson()
+ w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Write([]byte(json))
}
diff --git a/api/channel.go b/api/channel.go
index ff5b0f8da..e97e08fc0 100644
--- a/api/channel.go
+++ b/api/channel.go
@@ -729,7 +729,6 @@ func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
return
} else {
w.Header().Set(model.HEADER_ETAG_SERVER, data.Etag())
- w.Header().Set("Expires", "-1")
w.Write([]byte(data.ToJson()))
}
}
@@ -798,7 +797,6 @@ func getChannelExtraInfo(c *Context, w http.ResponseWriter, r *http.Request) {
data := model.ChannelExtra{Id: channel.Id, Members: extraMembers, MemberCount: memberCount}
w.Header().Set(model.HEADER_ETAG_SERVER, extraEtag)
- w.Header().Set("Expires", "-1")
w.Write([]byte(data.ToJson()))
}
}
diff --git a/api/context.go b/api/context.go
index b91981ecd..d0b4f85d2 100644
--- a/api/context.go
+++ b/api/context.go
@@ -165,6 +165,10 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} else {
// All api response bodies will be JSON formatted by default
w.Header().Set("Content-Type", "application/json")
+
+ if r.Method == "GET" {
+ w.Header().Set("Expires", "0")
+ }
}
if len(token) != 0 {
diff --git a/api/post.go b/api/post.go
index fadabd66e..9d3ba5ab1 100644
--- a/api/post.go
+++ b/api/post.go
@@ -1197,6 +1197,5 @@ func searchPosts(c *Context, w http.ResponseWriter, r *http.Request) {
}
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
- w.Header().Set("Expires", "0")
w.Write([]byte(posts.ToJson()))
}
diff --git a/api/team.go b/api/team.go
index 6d59e94e9..052d6e698 100644
--- a/api/team.go
+++ b/api/team.go
@@ -647,7 +647,6 @@ func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
} else {
w.Header().Set(model.HEADER_ETAG_SERVER, result.Data.(*model.Team).Etag())
- w.Header().Set("Expires", "-1")
w.Write([]byte(result.Data.(*model.Team).ToJson()))
return
}
diff --git a/api/user.go b/api/user.go
index db8de5f6a..7919da168 100644
--- a/api/user.go
+++ b/api/user.go
@@ -897,7 +897,6 @@ func getMe(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
result.Data.(*model.User).Sanitize(map[string]bool{})
w.Header().Set(model.HEADER_ETAG_SERVER, result.Data.(*model.User).Etag())
- w.Header().Set("Expires", "-1")
w.Write([]byte(result.Data.(*model.User).ToJson()))
return
}
diff --git a/docker/2.0/Dockerfile b/docker/2.0/Dockerfile
index 5cf3c6653..0f7a13e45 100644
--- a/docker/2.0/Dockerfile
+++ b/docker/2.0/Dockerfile
@@ -34,7 +34,7 @@ VOLUME /var/lib/mysql
WORKDIR /mattermost
# Copy over files
-ADD https://github.com/mattermost/platform/releases/download/v2.0.0-rc1/mattermost.tar.gz /
+ADD https://github.com/mattermost/platform/releases/download/v2.0.0-rc2/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/web/react/components/team_signup_email_item.jsx b/web/react/components/team_signup_email_item.jsx
index feb70dc71..790ec2e5d 100644
--- a/web/react/components/team_signup_email_item.jsx
+++ b/web/react/components/team_signup_email_item.jsx
@@ -83,4 +83,4 @@ TeamSignupEmailItem.propTypes = {
email: React.PropTypes.string
};
-export default injectIntl(TeamSignupEmailItem); \ No newline at end of file
+export default injectIntl(TeamSignupEmailItem, {withRef: true});
diff --git a/web/react/components/team_signup_send_invites_page.jsx b/web/react/components/team_signup_send_invites_page.jsx
index 46a6bc68e..343db13e8 100644
--- a/web/react/components/team_signup_send_invites_page.jsx
+++ b/web/react/components/team_signup_send_invites_page.jsx
@@ -33,8 +33,8 @@ export default class TeamSignupSendInvitesPage extends React.Component {
var emails = [];
for (var i = 0; i < this.props.state.invites.length; i++) {
- if (this.refs['email_' + i].validate(this.props.state.team.email)) {
- emails.push(this.refs['email_' + i].getValue());
+ if (this.refs['email_' + i].getWrappedInstance().validate(this.props.state.team.email)) {
+ emails.push(this.refs['email_' + i].getWrappedInstance().getValue());
} else {
valid = false;
}
diff --git a/web/react/components/user_settings/manage_outgoing_hooks.jsx b/web/react/components/user_settings/manage_outgoing_hooks.jsx
index 3f88e9f41..44aab486e 100644
--- a/web/react/components/user_settings/manage_outgoing_hooks.jsx
+++ b/web/react/components/user_settings/manage_outgoing_hooks.jsx
@@ -18,6 +18,10 @@ const holders = defineMessages({
callbackHolder: {
id: 'user.settings.hooks_out.callbackHolder',
defaultMessage: 'Each URL must start with http:// or https://'
+ },
+ select: {
+ id: 'user.settings.hooks_out.select',
+ defaultMessage: '--- Select a channel ---'
}
});
@@ -153,10 +157,7 @@ class ManageOutgoingHooks extends React.Component {
key='select-channel'
value=''
>
- <FormattedMessage
- id='user.settings.hooks_out.select'
- defaultMessage='--- Select a channel ---'
- />
+ {this.props.intl.formatMessage(holders.select)}
</option>
);
diff --git a/web/react/components/user_settings/user_settings_modal.jsx b/web/react/components/user_settings/user_settings_modal.jsx
index 7e911f09a..5442f7ac4 100644
--- a/web/react/components/user_settings/user_settings_modal.jsx
+++ b/web/react/components/user_settings/user_settings_modal.jsx
@@ -234,7 +234,10 @@ class UserSettingsModal extends React.Component {
render() {
const {formatMessage} = this.props.intl;
+ var currentUser = UserStore.getCurrentUser();
+ var isAdmin = Utils.isAdmin(currentUser.roles);
var tabs = [];
+
tabs.push({name: 'general', uiName: formatMessage(holders.general), icon: 'glyphicon glyphicon-cog'});
tabs.push({name: 'security', uiName: formatMessage(holders.security), icon: 'glyphicon glyphicon-lock'});
tabs.push({name: 'notifications', uiName: formatMessage(holders.notifications), icon: 'glyphicon glyphicon-exclamation-sign'});
@@ -243,8 +246,17 @@ class UserSettingsModal extends React.Component {
}
if (global.window.mm_config.EnableIncomingWebhooks === 'true' || global.window.mm_config.EnableOutgoingWebhooks === 'true' || global.window.mm_config.EnableCommands === 'true') {
- tabs.push({name: 'integrations', uiName: formatMessage(holders.integrations), icon: 'glyphicon glyphicon-transfer'});
+ var show = global.window.mm_config.EnableOnlyAdminIntegrations !== 'true';
+
+ if (global.window.mm_config.EnableOnlyAdminIntegrations === 'true' && isAdmin) {
+ show = true;
+ }
+
+ if (show) {
+ tabs.push({name: 'integrations', uiName: formatMessage(holders.integrations), icon: 'glyphicon glyphicon-transfer'});
+ }
}
+
tabs.push({name: 'display', uiName: formatMessage(holders.display), icon: 'glyphicon glyphicon-eye-open'});
tabs.push({name: 'advanced', uiName: formatMessage(holders.advanced), icon: 'glyphicon glyphicon-list-alt'});
diff --git a/web/react/components/user_settings/user_settings_security.jsx b/web/react/components/user_settings/user_settings_security.jsx
index 5693047c2..53d79906f 100644
--- a/web/react/components/user_settings/user_settings_security.jsx
+++ b/web/react/components/user_settings/user_settings_security.jsx
@@ -11,6 +11,7 @@ import TeamStore from '../../stores/team_store.jsx';
import * as Client from '../../utils/client.jsx';
import * as AsyncClient from '../../utils/async_client.jsx';
+import * as Utils from '../../utils/utils.jsx';
import Constants from '../../utils/constants.jsx';
import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl';
@@ -216,15 +217,12 @@ class SecurityTab extends React.Component {
var describe;
var d = new Date(this.props.user.last_password_update);
- var timeOfDay = ' am';
- if (d.getHours() >= 12) {
- timeOfDay = ' pm';
- }
const locale = global.window.mm_locale;
+ const hours12 = !Utils.isMilitaryTime();
describe = formatMessage(holders.lastUpdated, {
date: d.toLocaleDateString(locale, {month: 'short', day: '2-digit', year: 'numeric'}),
- time: d.toLocaleTimeString(locale, {hours12: true, hour: '2-digit', minute: '2-digit'}) + timeOfDay
+ time: d.toLocaleTimeString(locale, {hour12: hours12, hour: '2-digit', minute: '2-digit'})
});
updateSectionStatus = function updateSection() {
diff --git a/web/react/stores/post_store.jsx b/web/react/stores/post_store.jsx
index b5bb93576..f5c342163 100644
--- a/web/react/stores/post_store.jsx
+++ b/web/react/stores/post_store.jsx
@@ -83,8 +83,6 @@ class PostStoreClass extends EventEmitter {
this.getCommentDraft = this.getCommentDraft.bind(this);
this.clearDraftUploads = this.clearDraftUploads.bind(this);
this.clearCommentDraftUploads = this.clearCommentDraftUploads.bind(this);
- this.storeLatestUpdate = this.storeLatestUpdate.bind(this);
- this.getLatestUpdate = this.getLatestUpdate.bind(this);
this.getCurrentUsersLatestPost = this.getCurrentUsersLatestPost.bind(this);
this.getCommentCount = this.getCommentCount.bind(this);
@@ -258,7 +256,7 @@ class PostStoreClass extends EventEmitter {
const np = newPosts.posts[pid];
if (np.delete_at === 0) {
combinedPosts.posts[pid] = np;
- if (combinedPosts.order.indexOf(pid) === -1) {
+ if (combinedPosts.order.indexOf(pid) === -1 && newPosts.order.indexOf(pid) !== -1) {
combinedPosts.order.push(pid);
}
}
@@ -507,19 +505,6 @@ class PostStoreClass extends EventEmitter {
}
});
}
- storeLatestUpdate(channelId, time) {
- if (!this.postsInfo.hasOwnProperty(channelId)) {
- this.postsInfo[channelId] = {};
- }
- this.postsInfo[channelId].latestPost = time;
- }
- getLatestUpdate(channelId) {
- if (this.postsInfo.hasOwnProperty(channelId) && this.postsInfo[channelId].hasOwnProperty('latestPost')) {
- return this.postsInfo[channelId].latestPost;
- }
-
- return 0;
- }
getCommentCount(post) {
const posts = this.getAllPosts(post.channel_id).posts;
diff --git a/web/react/stores/socket_store.jsx b/web/react/stores/socket_store.jsx
index e1b65fe14..424c7fe57 100644
--- a/web/react/stores/socket_store.jsx
+++ b/web/react/stores/socket_store.jsx
@@ -32,6 +32,8 @@ class SocketStoreClass extends EventEmitter {
this.failCount = 0;
+ this.translations = this.getDefaultTranslations();
+
this.initialize();
}
@@ -174,6 +176,18 @@ class SocketStoreClass extends EventEmitter {
this.translations = messages;
}
+ getDefaultTranslations() {
+ return ({
+ socketError: 'Please check connection, Mattermost unreachable. If issue persists, ask administrator to check WebSocket port.',
+ someone: 'Someone',
+ posted: 'Posted',
+ uploadedImage: ' uploaded an image',
+ uploadedFile: ' uploaded a file',
+ something: ' did something new',
+ wrote: ' wrote: '
+ });
+ }
+
close() {
if (conn && conn.readyState === WebSocket.OPEN) {
conn.close();
diff --git a/web/react/utils/async_client.jsx b/web/react/utils/async_client.jsx
index c8676f45d..45cdf699f 100644
--- a/web/react/utils/async_client.jsx
+++ b/web/react/utils/async_client.jsx
@@ -521,18 +521,25 @@ export function getPosts(id) {
return;
}
- if (PostStore.getAllPosts(channelId) == null) {
+ const postList = PostStore.getAllPosts(channelId);
+
+ if ($.isEmptyObject(postList) || postList.order.length < Constants.POST_CHUNK_SIZE) {
getPostsPage(channelId, Constants.POST_CHUNK_SIZE);
return;
}
- const latestUpdate = PostStore.getLatestUpdate(channelId);
+ const latestPost = PostStore.getLatestPost(channelId);
+ let latestPostTime = 0;
+
+ if (latestPost != null && latestPost.update_at != null) {
+ latestPostTime = latestPost.create_at;
+ }
callTracker['getPosts_' + channelId] = utils.getTimestamp();
client.getPosts(
channelId,
- latestUpdate,
+ latestPostTime,
(data, textStatus, xhr) => {
if (xhr.status === 304 || !data) {
return;
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index e2a5b9620..7f124149d 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -260,6 +260,10 @@ export function displayTimeFormatted(ticks) {
);
}
+export function isMilitaryTime() {
+ return PreferenceStore.getBool(Constants.Preferences.CATEGORY_DISPLAY_SETTINGS, 'use_military_time');
+}
+
export function displayDateTime(ticks) {
var seconds = Math.floor((Date.now() - ticks) / 1000);
diff --git a/web/templates/head.html b/web/templates/head.html
index da65e1779..94a86e3dd 100644
--- a/web/templates/head.html
+++ b/web/templates/head.html
@@ -79,6 +79,7 @@
$(function() {
if (window.mm_preferences != null) {
PreferenceStore.setPreferences(window.mm_preferences);
+ PreferenceStore.emitChange();
}
});