Commit e784fa6c authored by Stelios Milidonis's avatar Stelios Milidonis

Bump release v5.14.0

parent aec8d53b
......@@ -30,4 +30,4 @@ module.name_mapper='^utils\(.*\)$' -> '<PROJECT_ROOT>/src/utils/\1'
module.name_mapper='^types\(.*\)$' -> '<PROJECT_ROOT>/src/types/\1'
[version]
0.91.0
0.95.1
# Code Contribution Guidelines
Thank you for your interest in contributing! Please see the [Mattermost Contribution Guide](https://developers.mattermost.com/contribute/getting-started/) which describes the process for making code contributions across Mattermost projects and [join our "Contributors" community channel](https://pre-release.mattermost.com/core/channels/tickets) to ask questions from community members and the Mattermost core team.
### Review Process for this Repo
After following the steps in the [Contribution Guide](http://docs.mattermost.com/developer/contribution-guide.html), submitted pull requests go through the review process outlined below. We aim to start reviewing pull requests in this repo the week they are submitted, but the length of time to complete the process will vary depending on the pull request.
The one exception may be around release time, where the review process may take longer as the team focuses on our [release process](https://docs.mattermost.com/process/release-process.html).
#### `Stage 1: PM Review`
A Product Manager will review the pull request to make sure it:
1. Fits with our product roadmap
2. Works as expected
3. Meets UX guidelines
This step is sometimes skipped for bugs or small improvements with a ticket, but always happens for new features or pull requests without a related ticket.
The Product Manager may come back with some bugs or UI improvements to fix before the pull request moves on to the next stage.
#### `Stage 2: Dev Review`
Two developers will review the pull request and either give feedback or `+1` the PR.
Any comments will need to be addressed before the pull request moves on to the last stage.
- PRs that do not follow Style Guides cannot be merged
#### `Stage 3: Ready to Merge`
The review process is complete, and the pull request will be merged.
Thank you for your interest in contributing! Please see the [Mattermost Contribution Guide](https://developers.mattermost.com/contribute/getting-started/) which describes the process for making code contributions across Mattermost projects and [join our "Contributors" community channel](https://community.mattermost.com/core/channels/tickets) to ask questions from community members and the Mattermost core team.
When you submit a pull request, it goes through a [code review process outlined here](https://developers.mattermost.com/contribute/getting-started/code-review/).
......@@ -248,6 +248,40 @@ THE SOFTWARE.
---
## moment-timezone
This product contains 'moment-timezone' by Moment.js.
Timezone support for moment.js
* HOMEPAGE:
* https://github.com/moment/moment-timezone
* LICENSE: MIT
The MIT License (MIT)
Copyright (c) JS Foundation and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
## redux
This product contains 'redux' by Redux.
......
......@@ -14,7 +14,7 @@ When filling in a section please remove the help text and the above text.
- [ ] Ran `make test` to ensure unit tests passed
- [ ] Ran `make flow` to ensure type checking passed
- [ ] Added or updated unit tests (required for all new features)
- [ ] All new/modified APIs include changes to the drivers
- [ ] All new/modified APIs include changes to the [JavaScript driver](https://github.com/mattermost/mattermost-redux/blob/master/src/client/client4.js)
#### Test Information
This PR was tested on: [Device name(s), OS version(s)]
# Mattermost Redux ![CircleCI branch](https://img.shields.io/circleci/project/github/mattermost/mattermost-redux/release-5.11.svg)
# Mattermost Redux ![CircleCI branch](https://img.shields.io/circleci/project/github/mattermost/mattermost-redux/master.svg)
The project purpose is consolidating the storage, web utilities and logic of the webapp and React Native mobile clients into a single driver. We encourage you to use mattermost-redux to power your own Mattermost clients or integrations.
......
......@@ -18,6 +18,7 @@ module.exports = {
plugins: [
'@babel/transform-flow-comments',
'@babel/proposal-class-properties',
'@babel/plugin-proposal-optional-chaining',
['module-resolver', {
root: ['./src', '.'],
}],
......
This diff is collapsed.
{
"name": "mattermost-redux",
"version": "5.11.0",
"version": "5.14.0",
"description": "Common code (API client, Redux stores, logic, utility functions) for building a Mattermost client",
"homepage": "https://github.com/mattermost/mattermost-redux",
"license": "Apache-2.0",
......@@ -10,12 +10,13 @@
},
"dependencies": {
"deep-equal": "1.0.1",
"eslint-plugin-header": "2.0.0",
"eslint-plugin-header": "3.0.0",
"form-data": "2.3.3",
"gfycat-sdk": "1.4.18",
"harmony-reflect": "1.6.1",
"isomorphic-fetch": "2.2.1",
"mime-db": "1.37.0",
"mime-db": "1.40.0",
"moment-timezone": "0.5.25",
"redux": "4.0.1",
"redux-action-buffer": "1.2.0",
"redux-batched-actions": "0.4.1",
......@@ -27,38 +28,40 @@
"shallow-equals": "1.0.0"
},
"devDependencies": {
"@babel/cli": "7.2.0",
"@babel/core": "7.2.0",
"@babel/plugin-proposal-class-properties": "7.2.1",
"@babel/plugin-transform-flow-comments": "7.2.0",
"@babel/cli": "7.4.4",
"@babel/core": "7.4.5",
"@babel/plugin-proposal-class-properties": "7.4.4",
"@babel/plugin-proposal-optional-chaining": "^7.2.0",
"@babel/plugin-transform-flow-comments": "7.4.4",
"@babel/preset-env": "7.2.0",
"@babel/register": "7.0.0",
"@babel/register": "7.4.4",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.0.1",
"babel-jest": "23.6.0",
"babel-loader": "8.0.4",
"babel-plugin-module-resolver": "3.1.1",
"babel-jest": "24.8.0",
"babel-loader": "8.0.6",
"babel-plugin-module-resolver": "3.2.0",
"chai": "4.2.0",
"deep-freeze": "0.0.1",
"eslint": "5.9.0",
"eslint": "5.16.0",
"eslint-config-mattermost": "github:mattermost/eslint-config-mattermost",
"eslint-plugin-flowtype": "3.2.0",
"eslint-plugin-jest": "22.0.0",
"fetch-mock": "7.2.5",
"flow-bin": "0.91.0",
"eslint-plugin-flowtype": "3.7.0",
"eslint-plugin-jest": "22.6.4",
"expect": "24.8.0",
"fetch-mock": "7.3.3",
"flow-bin": "0.95.1",
"flow-typed": "2.5.1",
"jest": "23.6.0",
"jest-cli": "23.6.0",
"jest-junit": "5.2.0",
"jest": "24.8.0",
"jest-cli": "24.8.0",
"jest-junit": "6.4.0",
"mock-socket": "8.0.5",
"nock": "10.0.3",
"react": "16.6.3",
"nock": "10.0.6",
"react": "16.8.6",
"redux-mock-store": "1.5.3",
"redux-persist-node-storage": "2.0.0",
"remote-redux-devtools": "0.5.13",
"remotedev-rn-debugger": "0.8.3",
"uglifyjs-webpack-plugin": "2.0.1",
"webpack": "4.27.0",
"ws": "6.1.2"
"remote-redux-devtools": "0.5.16",
"uglifyjs-webpack-plugin": "2.1.3",
"webpack": "4.32.2",
"ws": "7.0.0"
},
"scripts": {
"build": "babel src --out-dir . --ignore '**/*.test.js'",
......@@ -89,7 +92,9 @@
"default",
"jest-junit"
],
"setupTestFrameworkScriptFile": "<rootDir>/test/setup.js",
"setupFilesAfterEnv": [
"<rootDir>/test/setup.js"
],
"testPathIgnorePatterns": [
"/node_modules/"
]
......
......@@ -137,6 +137,10 @@ export default keyMirror({
UPLOAD_PLUGIN_SUCCESS: null,
UPLOAD_PLUGIN_FAILURE: null,
INSTALL_PLUGIN_FROM_URL_REQUEST: null,
INSTALL_PLUGIN_FROM_URL_SUCCESS: null,
INSTALL_PLUGIN_FROM_URL_FAILURE: null,
GET_PLUGIN_REQUEST: null,
GET_PLUGIN_SUCCESS: null,
GET_PLUGIN_FAILURE: null,
......
......@@ -71,4 +71,8 @@ export default keyMirror({
UPDATED_CHANNEL_SCHEME: null,
UPDATED_CHANNEL_MEMBER_SCHEME_ROLES: null,
RECEIVED_CHANNEL_MEMBERS_MINUS_GROUP_MEMBERS: null,
RECEIVED_TOTAL_CHANNEL_COUNT: null,
});
......@@ -32,4 +32,36 @@ export default keyMirror({
GET_GROUP_SUCCESS: null,
GET_GROUP_FAILURE: null,
RECEIVED_GROUP: null,
RECEIVED_GROUPS: null,
GET_GROUPS_ASSOCIATED_TO_TEAM_REQUEST: null,
GET_GROUPS_ASSOCIATED_TO_TEAM_SUCCESS: null,
GET_GROUPS_ASSOCIATED_TO_TEAM_FAILURE: null,
RECEIVED_GROUPS_ASSOCIATED_TO_TEAM: null,
GET_GROUPS_ASSOCIATED_TO_CHANNEL_REQUEST: null,
GET_GROUPS_ASSOCIATED_TO_CHANNEL_SUCCESS: null,
GET_GROUPS_ASSOCIATED_TO_CHANNEL_FAILURE: null,
RECEIVED_GROUPS_ASSOCIATED_TO_CHANNEL: null,
GET_ALL_GROUPS_ASSOCIATED_TO_TEAM_REQUEST: null,
GET_ALL_GROUPS_ASSOCIATED_TO_TEAM_SUCCESS: null,
GET_ALL_GROUPS_ASSOCIATED_TO_TEAM_FAILURE: null,
RECEIVED_ALL_GROUPS_ASSOCIATED_TO_TEAM: null,
GET_ALL_GROUPS_ASSOCIATED_TO_CHANNEL_REQUEST: null,
GET_ALL_GROUPS_ASSOCIATED_TO_CHANNEL_SUCCESS: null,
GET_ALL_GROUPS_ASSOCIATED_TO_CHANNEL_FAILURE: null,
RECEIVED_ALL_GROUPS_ASSOCIATED_TO_CHANNEL: null,
GET_GROUPS_NOT_ASSOCIATED_TO_TEAM_REQUEST: null,
GET_GROUPS_NOT_ASSOCIATED_TO_TEAM_SUCCESS: null,
GET_GROUPS_NOT_ASSOCIATED_TO_TEAM_FAILURE: null,
RECEIVED_GROUPS_NOT_ASSOCIATED_TO_TEAM: null,
GET_GROUPS_NOT_ASSOCIATED_TO_CHANNEL_REQUEST: null,
GET_GROUPS_NOT_ASSOCIATED_TO_CHANNEL_SUCCESS: null,
GET_GROUPS_NOT_ASSOCIATED_TO_CHANNEL_FAILURE: null,
RECEIVED_GROUPS_NOT_ASSOCIATED_TO_CHANNEL: null,
});
......@@ -77,6 +77,10 @@ export default keyMirror({
GET_OAUTH_APP_SUCCESS: null,
GET_OAUTH_APP_FAILURE: null,
GET_AUTHORIZED_OAUTH_APPS_REQUEST: null,
GET_AUTHORIZED_OAUTH_APPS_SUCCESS: null,
GET_AUTHORIZED_OAUTH_APPS_FAILURE: null,
DELETE_OAUTH_APP_REQUEST: null,
DELETE_OAUTH_APP_SUCCESS: null,
DELETE_OAUTH_APP_FAILURE: null,
......@@ -85,6 +89,10 @@ export default keyMirror({
UPDATE_OAUTH_APP_SUCCESS: null,
UPDATE_OAUTH_APP_FAILURE: null,
DEAUTHORIZE_OAUTH_APP_REQUEST: null,
DEAUTHORIZE_OAUTH_APP_SUCCESS: null,
DEAUTHORIZE_OAUTH_APP_FAILURE: null,
EXECUTE_COMMAND_REQUEST: null,
EXECUTE_COMMAND_SUCCESS: null,
EXECUTE_COMMAND_FAILURE: null,
......
......@@ -10,8 +10,6 @@ export default keyMirror({
CREATE_POST_FAILURE: null,
CREATE_POST_RESET_REQUEST: null,
REMOVE_PENDING_POST: null,
EDIT_POST_REQUEST: null,
EDIT_POST_SUCCESS: null,
EDIT_POST_FAILURE: null,
......@@ -31,12 +29,20 @@ export default keyMirror({
RECEIVED_POST: null,
RECEIVED_NEW_POST: null,
RECEIVED_POSTS: null,
RECEIVED_POSTS_AFTER: null,
RECEIVED_POSTS_BEFORE: null,
RECEIVED_POSTS_IN_CHANNEL: null,
RECEIVED_POSTS_IN_THREAD: null,
RECEIVED_POSTS_SINCE: null,
POST_DELETED: null,
POST_REMOVED: null,
RECEIVED_FOCUSED_POST: null,
RECEIVED_POST_SELECTED: null,
RECEIVED_EDIT_POST: null,
POST_DELETED: null,
REMOVE_POST: null,
RECEIVED_REACTION: null,
RECEIVED_REACTIONS: null,
REACTION_DELETED: null,
......
......@@ -53,4 +53,8 @@ export default keyMirror({
LEAVE_TEAM: null,
UPDATED_TEAM_SCHEME: null,
UPDATED_TEAM_MEMBER_SCHEME_ROLES: null,
RECEIVED_TEAM_MEMBERS_MINUS_GROUP_MEMBERS: null,
RECEIVED_TOTAL_TEAM_COUNT: null,
});
......@@ -18,6 +18,7 @@ export default keyMirror({
LOGOUT_FAILURE: null,
REVOKE_ALL_USER_SESSIONS_SUCCESS: null,
REVOKE_SESSIONS_FOR_ALL_USERS_SUCCESS: null,
CHECK_MFA_REQUEST: null,
CHECK_MFA_SUCCESS: null,
......@@ -41,6 +42,7 @@ export default keyMirror({
RECEIVED_PROFILES_LIST_IN_TEAM: null,
RECEIVED_PROFILE_NOT_IN_TEAM: null,
RECEIVED_PROFILES_LIST_NOT_IN_TEAM: null,
RECEIVED_PROFILES_LIST_NOT_IN_TEAM_AND_REPLACE: null,
RECEIVED_PROFILE_WITHOUT_TEAM: null,
RECEIVED_PROFILES_LIST_WITHOUT_TEAM: null,
RECEIVED_PROFILES_IN_CHANNEL: null,
......@@ -48,6 +50,7 @@ export default keyMirror({
RECEIVED_PROFILE_IN_CHANNEL: null,
RECEIVED_PROFILES_NOT_IN_CHANNEL: null,
RECEIVED_PROFILES_LIST_NOT_IN_CHANNEL: null,
RECEIVED_PROFILES_LIST_NOT_IN_CHANNEL_AND_REPLACE: null,
RECEIVED_PROFILE_NOT_IN_CHANNEL: null,
RECEIVED_SESSIONS: null,
RECEIVED_REVOKED_SESSION: null,
......
......@@ -433,6 +433,10 @@ export function getPostsPerDayAnalytics(teamId: string = ''): ActionFunc {
return getAnalytics('post_counts_day', teamId);
}
export function getBotPostsPerDayAnalytics(teamId: string = ''): ActionFunc {
return getAnalytics('bot_post_counts_day', teamId);
}
export function getUsersPerDayAnalytics(teamId: string = ''): ActionFunc {
return getAnalytics('user_counts_with_posts_day', teamId);
}
......@@ -461,6 +465,28 @@ export function uploadPlugin(fileData: File, force: boolean = false): ActionFunc
};
}
export function installPluginFromUrl(url: string, force: boolean = false): ActionFunc {
return async (dispatch, getState) => {
dispatch({type: AdminTypes.INSTALL_PLUGIN_FROM_URL_REQUEST, data: null});
let data;
try {
data = await Client4.installPluginFromUrl(url, force);
} catch (error) {
forceLogoutIfNecessary(error, dispatch, getState);
dispatch(batchActions([
{type: AdminTypes.INSTALL_PLUGIN_FROM_URL_FAILURE, error},
logError(error),
]));
return {error};
}
dispatch({type: AdminTypes.INSTALL_PLUGIN_FROM_URL_SUCCESS, data: null});
return {data};
};
}
export function getPlugins(): ActionFunc {
return bindClientFunc({
clientFunc: Client4.getPlugins,
......
......@@ -801,6 +801,52 @@ describe('Actions.Admin', () => {
}
});
it('overwriteInstallPlugin', async () => {
const downloadUrl = 'testplugin.tar.gz';
const testPlugin = {id: 'testplugin', webapp: {bundle_path: '/static/somebundle.js'}};
let urlMatch = `/plugins/install_from_url?plugin_download_url=${downloadUrl}&force=false`;
nock(Client4.getBaseRoute()).
post(urlMatch).
reply(200, testPlugin);
await Actions.installPluginFromUrl(downloadUrl, false)(store.dispatch, store.getState);
let state = store.getState();
let request = state.requests.admin.installPluginFromUrl;
if (request.status === RequestStatus.FAILURE) {
throw new Error('uploadPlugin request failed err=' + request.error);
}
urlMatch = `/plugins/install_from_url?plugin_download_url=${downloadUrl}&force=true`;
nock(Client4.getBaseRoute()).
post(urlMatch).
reply(200, testPlugin);
await Actions.installPluginFromUrl(downloadUrl, true)(store.dispatch, store.getState);
state = store.getState();
request = state.requests.admin.installPluginFromUrl;
if (request.status === RequestStatus.FAILURE) {
throw new Error('uploadPlugin request failed err=' + request.error);
}
});
it('installPluginFromUrl', async () => {
const downloadUrl = 'testplugin.tar.gz';
const testPlugin = {id: 'testplugin', webapp: {bundle_path: '/static/somebundle.js'}};
const urlMatch = `/plugins/install_from_url?plugin_download_url=${downloadUrl}&force=false`;
nock(Client4.getBaseRoute()).
post(urlMatch).
reply(200, testPlugin);
await Actions.installPluginFromUrl(downloadUrl, false)(store.dispatch, store.getState);
const state = store.getState();
const request = state.requests.admin.installPluginFromUrl;
if (request.status === RequestStatus.FAILURE) {
throw new Error('uploadPlugin request failed err=' + request.error);
}
});
it('getPlugins', async () => {
const testPlugin = {id: 'testplugin', webapp: {bundle_path: '/static/somebundle.js'}};
const testPlugin2 = {id: 'testplugin2', webapp: {bundle_path: '/static/somebundle.js'}};
......
......@@ -8,8 +8,9 @@ import {Client4} from 'client';
import {General, Preferences} from 'constants';
import {ChannelTypes, PreferenceTypes, UserTypes} from 'action_types';
import {savePreferences, deletePreferences} from 'actions/preferences';
import {getChannelsIdForTeam} from 'utils/channel_utils';
import {getMyChannelMember as getMyChannelMemberSelector} from 'selectors/entities/channels';
import {getChannelsIdForTeam, getChannelByName} from 'utils/channel_utils';
import {getChannelsNameMapInTeam, getMyChannelMember as getMyChannelMemberSelector, getRedirectChannelNameForTeam} from 'selectors/entities/channels';
import {getCurrentTeamId} from 'selectors/entities/teams';
import {logError} from './errors';
import {bindClientFunc, forceLogoutIfNecessary} from './helpers';
......@@ -589,7 +590,7 @@ export function leaveChannel(channelId: string): ActionFunc {
meta: {
offline: {
effect: () => Client4.removeFromChannel(currentUserId, channelId),
commit: {type: ChannelTypes.LEAVE_CHANNEL},
commit: {type: 'do_nothing'}, // redux-offline always needs to dispatch something on commit
rollback: () => {
dispatch(batchActions([
{
......@@ -654,7 +655,7 @@ export function joinChannel(userId: string, teamId: string, channelId: string, c
export function deleteChannel(channelId: string): ActionFunc {
return async (dispatch, getState) => {
const state = getState();
let state = getState();
const viewArchivedChannels = state.entities.general.config.ExperimentalViewArchivedChannels === 'true';
try {
......@@ -665,16 +666,15 @@ export function deleteChannel(channelId: string): ActionFunc {
return {error};
}
const entities = getState().entities;
const {channels, currentChannelId} = entities.channels;
state = getState();
const {currentChannelId} = state.entities.channels;
if (channelId === currentChannelId && !viewArchivedChannels) {
const channel = Object.keys(channels).filter((key) => channels[key].name === General.DEFAULT_CHANNEL);
let defaultChannelId = '';
if (channel.length) {
defaultChannelId = channel[0];
const teamId = getCurrentTeamId(state);
const channelsInTeam = getChannelsNameMapInTeam(state, teamId);
const channel = getChannelByName(channelsInTeam, getRedirectChannelNameForTeam(state, teamId));
if (channel && channel.id) {
dispatch({type: ChannelTypes.SELECT_CHANNEL, data: channel.id}, getState);
}
dispatch({type: ChannelTypes.SELECT_CHANNEL, data: defaultChannelId}, getState);
}
dispatch({type: ChannelTypes.DELETE_CHANNEL_SUCCESS, data: {id: channelId, viewArchivedChannels}}, getState);
......@@ -795,13 +795,47 @@ export function getChannels(teamId: string, page: number = 0, perPage: number =
};
}
export function getAllChannels(page: number = 0, perPage: number = General.CHANNELS_CHUNK_SIZE): ActionFunc {
export function getAllChannelsWithCount(page: number = 0, perPage: number = General.CHANNELS_CHUNK_SIZE, notAssociatedToGroup: string = '', excludeDefaultChannels: boolean = false): ActionFunc {
return async (dispatch, getState) => {
dispatch({type: ChannelTypes.GET_ALL_CHANNELS_REQUEST, data: null}, getState);
let payload;
try {
payload = await Client4.getAllChannels(page, perPage, notAssociatedToGroup, excludeDefaultChannels, true);
} catch (error) {
forceLogoutIfNecessary(error, dispatch, getState);
dispatch(batchActions([
{type: ChannelTypes.GET_ALL_CHANNELS_FAILURE, error},
logError(error),
]), getState);
return {error};
}
dispatch(batchActions([
{
type: ChannelTypes.RECEIVED_ALL_CHANNELS,
data: payload.channels,
},
{
type: ChannelTypes.GET_ALL_CHANNELS_SUCCESS,
},
{
type: ChannelTypes.RECEIVED_TOTAL_CHANNEL_COUNT,
data: payload.total_count,
},
]), getState);
return {data: payload};
};
}
export function getAllChannels(page: number = 0, perPage: number = General.CHANNELS_CHUNK_SIZE, notAssociatedToGroup: string = '', excludeDefaultChannels: boolean = false): ActionFunc {
return async (dispatch, getState) => {
dispatch({type: ChannelTypes.GET_ALL_CHANNELS_REQUEST, data: null}, getState);
let channels;
try {
channels = await Client4.getAllChannels(page, perPage);
channels = await Client4.getAllChannels(page, perPage, notAssociatedToGroup, excludeDefaultChannels);
} catch (error) {
forceLogoutIfNecessary(error, dispatch, getState);
dispatch(batchActions([
......@@ -918,13 +952,13 @@ export function searchChannels(teamId: string, term: string): ActionFunc {
};
}
export function searchAllChannels(term: string): ActionFunc {
export function searchAllChannels(term: string, notAssociatedToGroup: string = '', excludeDefaultChannels: boolean = false): ActionFunc {
return async (dispatch, getState) => {
dispatch({type: ChannelTypes.GET_ALL_CHANNELS_REQUEST, data: null}, getState);
let channels;
try {
channels = await Client4.searchAllChannels(term);
channels = await Client4.searchAllChannels(term, notAssociatedToGroup, excludeDefaultChannels);
} catch (error) {
forceLogoutIfNecessary(error, dispatch, getState);
dispatch(batchActions([
......@@ -948,6 +982,13 @@ export function searchAllChannels(term: string): ActionFunc {
};
}
export function searchGroupChannels(term: string): ActionFunc {
return bindClientFunc({
clientFunc: Client4.searchGroupChannels,
params: [term],
});
}
export function getChannelStats(channelId: string): ActionFunc {
return async (dispatch, getState) => {
let stat;
......@@ -1081,7 +1122,7 @@ export function updateChannelPurpose(channelId: string, purpose: string): Action
};
}
export function markChannelAsRead(channelId: string, prevChannelId: string, updateLastViewedAt: boolean = true): ActionFunc {
export function markChannelAsRead(channelId: string, prevChannelId: ?string, updateLastViewedAt: boolean = true): ActionFunc {
return async (dispatch, getState) => {
// Send channel last viewed at to the server
if (updateLastViewedAt) {
......@@ -1097,11 +1138,11 @@ export function markChannelAsRead(channelId: string, prevChannelId: string, upda
// Update channel member objects to set all mentions and posts as viewed
const channel = channels[channelId];
const prevChannel = channels[prevChannelId]; // May be null since prevChannelId is optional
const prevChannel = prevChannelId ? channels[prevChannelId] : null; // May be null since prevChannelId is optional
// Update team member objects to set mentions and posts in channel as viewed
const channelMember = myMembers[channelId];
const prevChannelMember = myMembers[prevChannelId]; // May also be null
const prevChannelMember = prevChannelId ? myMembers[prevChannelId] : null; // May also be null
const actions = [];
......@@ -1278,6 +1319,19 @@ export function updateChannelMemberSchemeRoles(channelId: string, userId: string
});
}