Commit e3002ec0 authored by Harrison Healey's avatar Harrison Healey

Merge branch 'master' into mark-as-unread

parents edaa6ebc 66314024
......@@ -10,13 +10,10 @@ PULL_REQUEST_TEMPLATE.md
.npmignore
.npminstall
.tmp
src
.circleci
jest.config.js
babel.config.js
rollup.config.js
tsconfig.json
.editorconfig
.eslintignore
mattermost-redux.iml
.eslintrc.json
\ No newline at end of file
.eslintrc.json
......@@ -5,9 +5,11 @@ import {Client4} from 'client';
import {BotTypes} from 'action_types';
import {bindClientFunc} from './helpers';
import {ActionFunc} from 'types/actions';
const BOTS_PER_PAGE_DEFAULT = 20;
export function createBot(bot) {
export function createBot(bot): ActionFunc {
return bindClientFunc({
clientFunc: Client4.createBot,
onSuccess: BotTypes.RECEIVED_BOT_ACCOUNT,
......@@ -17,7 +19,7 @@ export function createBot(bot) {
});
}
export function patchBot(botUserId, botPatch) {
export function patchBot(botUserId, botPatch): ActionFunc {
return bindClientFunc({
clientFunc: Client4.patchBot,
onSuccess: BotTypes.RECEIVED_BOT_ACCOUNT,
......@@ -28,7 +30,7 @@ export function patchBot(botUserId, botPatch) {
});
}
export function loadBot(botUserId) {
export function loadBot(botUserId): ActionFunc {
return bindClientFunc({
clientFunc: Client4.getBot,
onSuccess: BotTypes.RECEIVED_BOT_ACCOUNT,
......@@ -38,7 +40,7 @@ export function loadBot(botUserId) {
});
}
export function loadBots(page = 0, perPage = BOTS_PER_PAGE_DEFAULT) {
export function loadBots(page = 0, perPage = BOTS_PER_PAGE_DEFAULT): ActionFunc {
return bindClientFunc({
clientFunc: Client4.getBotsIncludeDeleted,
onSuccess: BotTypes.RECEIVED_BOT_ACCOUNTS,
......@@ -49,7 +51,7 @@ export function loadBots(page = 0, perPage = BOTS_PER_PAGE_DEFAULT) {
});
}
export function disableBot(botUserId) {
export function disableBot(botUserId): ActionFunc {
return bindClientFunc({
clientFunc: Client4.disableBot,
onSuccess: BotTypes.RECEIVED_BOT_ACCOUNT,
......@@ -59,7 +61,7 @@ export function disableBot(botUserId) {
});
}
export function enableBot(botUserId) {
export function enableBot(botUserId): ActionFunc {
return bindClientFunc({
clientFunc: Client4.enableBot,
onSuccess: BotTypes.RECEIVED_BOT_ACCOUNT,
......@@ -69,7 +71,7 @@ export function enableBot(botUserId) {
});
}
export function assignBot(botUserId, newOwnerId) {
export function assignBot(botUserId, newOwnerId): ActionFunc {
return bindClientFunc({
clientFunc: Client4.assignBot,
onSuccess: BotTypes.RECEIVED_BOT_ACCOUNT,
......
......@@ -3,12 +3,12 @@
import {Client4} from 'client';
import {FileTypes} from 'action_types';
import {Action, batchActions, DispatchFunc, GetStateFunc} from 'types/actions';
import {Action, batchActions, DispatchFunc, GetStateFunc, ActionFunc} from 'types/actions';
import {logError} from './errors';
import {bindClientFunc, forceLogoutIfNecessary} from './helpers';
export function getFilesForPost(postId: string) {
export function getFilesForPost(postId: string): ActionFunc {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
let files;
......@@ -30,7 +30,7 @@ export function getFilesForPost(postId: string) {
};
}
export function uploadFile(channelId: string, rootId: string, clientIds: Array<string>, fileFormData: File, formBoundary: string) {
export function uploadFile(channelId: string, rootId: string, clientIds: Array<string>, fileFormData: File, formBoundary: string): ActionFunc {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
dispatch({type: FileTypes.UPLOAD_FILES_REQUEST, data: {}}, getState);
......@@ -75,7 +75,7 @@ export function uploadFile(channelId: string, rootId: string, clientIds: Array<s
};
}
export function getFilePublicLink(fileId: string) {
export function getFilePublicLink(fileId: string): ActionFunc {
return bindClientFunc({
clientFunc: Client4.getFilePublicLink,
onSuccess: FileTypes.RECEIVED_FILE_PUBLIC_LINK,
......
This diff is collapsed.
......@@ -6,7 +6,9 @@ import {bindClientFunc} from './helpers';
import {PluginTypes} from 'action_types';
export function getMarketplacePlugins(filter) {
import {ActionFunc} from 'types/actions';
export function getMarketplacePlugins(filter): ActionFunc {
return bindClientFunc({
clientFunc: Client4.getMarketplacePlugins,
onSuccess: PluginTypes.RECEIVED_MARKETPLACE_PLUGINS,
......
......@@ -16,7 +16,7 @@ import {fromAutoResponder} from 'utils/post_utils';
import EventEmitter from 'utils/event_emitter';
import {getMyPreferences} from './preferences';
import {ActionFunc, DispatchFunc, GetStateFunc, PlatformType} from '../types/actions';
import {ActionFunc, DispatchFunc, GetStateFunc, PlatformType} from 'types/actions';
import {getTeam, getMyTeamUnreads, getMyTeams, getMyTeamMembers} from './teams';
import {getPost, getPosts, getProfilesAndStatusesForPosts, getCustomEmojiForReaction, getUnreadPostData, handleNewPost, postDeleted, receivedPost} from './posts';
......
......@@ -3,10 +3,9 @@
import {combineReducers} from 'redux';
import {EmojiTypes, PostTypes, UserTypes} from 'action_types';
import {EmojisState, CustomEmoji} from 'types/emojis';
import {Post} from 'types/posts';
import {GenericAction} from 'types/actions';
import {IDMappedObjects} from 'types/utilities';
export function customEmoji(state: IDMappedObjects<CustomEmoji> = {}, action: GenericAction): IDMappedObjects<CustomEmoji> {
import * as types from 'types';
export function customEmoji(state: types.utilities.IDMappedObjects<CustomEmoji> = {}, action: types.actions.GenericAction): types.utilities.IDMappedObjects<CustomEmoji> {
switch (action.type) {
case EmojiTypes.RECEIVED_CUSTOM_EMOJI: {
const nextState = {...state};
......@@ -31,7 +30,7 @@ export function customEmoji(state: IDMappedObjects<CustomEmoji> = {}, action: Ge
case PostTypes.RECEIVED_NEW_POST:
case PostTypes.RECEIVED_POST: {
const post: Post = action.data;
const post: types.posts.Post = action.data;
return storeEmojisForPost(state, post);
}
......@@ -45,7 +44,7 @@ export function customEmoji(state: IDMappedObjects<CustomEmoji> = {}, action: Ge
}
}
function storeEmojisForPost(state: IDMappedObjects<CustomEmoji>, post: Post): IDMappedObjects<CustomEmoji> {
function storeEmojisForPost(state: types.utilities.IDMappedObjects<CustomEmoji>, post: types.posts.Post): types.utilities.IDMappedObjects<CustomEmoji> {
if (!post.metadata || !post.metadata.emojis) {
return state;
}
......@@ -63,7 +62,7 @@ function storeEmojisForPost(state: IDMappedObjects<CustomEmoji>, post: Post): ID
}, state);
}
function nonExistentEmoji(state: Set<string> = new Set(), action: GenericAction): Set<string> {
function nonExistentEmoji(state: Set<string> = new Set(), action: types.actions.GenericAction): Set<string> {
switch (action.type) {
case EmojiTypes.CUSTOM_EMOJI_DOES_NOT_EXIST: {
if (!state.has(action.data)) {
......@@ -110,4 +109,4 @@ export default (combineReducers({
// set containing custom emoji names that do not exist
nonExistentEmoji,
}) as (b: EmojisState, a: GenericAction) => EmojisState);
}) as (b: EmojisState, a: types.actions.GenericAction) => EmojisState);
......@@ -3,8 +3,8 @@
import {combineReducers} from 'redux';
import {GroupTypes} from 'action_types';
import {GenericAction} from '../../types/actions';
import {RequestStatusType, GroupsRequestsStatuses} from '../../types/requests';
import {GenericAction} from 'types/actions';
import {RequestStatusType, GroupsRequestsStatuses} from 'types/requests';
import {handleRequest, initialRequestState} from './helpers';
......
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {createSelector} from 'reselect';
import * as reselect from 'reselect';
import {getCurrentUserLocale} from 'selectors/entities/i18n';
import {sortFileInfos} from 'utils/file_utils';
function getAllFiles(state) {
import * as types from 'types';
function getAllFiles(state: types.store.GlobalState) {
return state.entities.files.files;
}
function getFilesIdsForPost(state, postId) {
function getFilesIdsForPost(state: types.store.GlobalState, postId: string) {
if (postId) {
return state.entities.files.fileIdsByPostId[postId] || [];
}
......@@ -24,7 +26,7 @@ export function getFilePublicLink(state) {
}
export function makeGetFilesForPost() {
return createSelector(
return reselect.createSelector(
[getAllFiles, getFilesIdsForPost, getCurrentUserLocale],
(allFiles, fileIdsForPost, locale) => {
const fileInfos = fileIdsForPost.map((id) => allFiles[id]).filter((id) => Boolean(id));
......
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {createSelector} from 'reselect';
import * as reselect from 'reselect';
import {GlobalState} from 'types/store';
const emptyList = [];
const emptySyncables = {
......@@ -49,17 +49,17 @@ const teamGroupIDs = (state: GlobalState, teamID) => (state.entities.teams.group
const channelGroupIDs = (state: GlobalState, channelID) => (state.entities.channels.groupsAssociatedToChannel[channelID] == null ? undefined : state.entities.channels.groupsAssociatedToChannel[channelID].ids == null ? undefined : state.entities.channels.groupsAssociatedToChannel[channelID].ids) || [];
const getTeamGroupIDSet = createSelector(
const getTeamGroupIDSet = reselect.createSelector(
teamGroupIDs,
(teamIDs) => new Set(teamIDs),
);
const getChannelGroupIDSet = createSelector(
const getChannelGroupIDSet = reselect.createSelector(
channelGroupIDs,
(channelIDs) => new Set(channelIDs),
);
export const getGroupsNotAssociatedToTeam = createSelector(
export const getGroupsNotAssociatedToTeam = reselect.createSelector(
getAllGroups,
(state, teamID) => getTeamGroupIDSet(state, teamID),
(allGroups, teamGroupIDSet) => {
......@@ -67,7 +67,7 @@ export const getGroupsNotAssociatedToTeam = createSelector(
}
);
export const getGroupsAssociatedToTeam = createSelector(
export const getGroupsAssociatedToTeam = reselect.createSelector(
getAllGroups,
(state, teamID) => getTeamGroupIDSet(state, teamID),
(allGroups, teamGroupIDSet) => {
......@@ -75,7 +75,7 @@ export const getGroupsAssociatedToTeam = createSelector(
}
);
export const getGroupsNotAssociatedToChannel = createSelector(
export const getGroupsNotAssociatedToChannel = reselect.createSelector(
getAllGroups,
(state, channelID) => getChannelGroupIDSet(state, channelID),
(allGroups, channelGroupIDSet) => {
......@@ -83,7 +83,7 @@ export const getGroupsNotAssociatedToChannel = createSelector(
}
);
export const getGroupsAssociatedToChannel = createSelector(
export const getGroupsAssociatedToChannel = reselect.createSelector(
getAllGroups,
(state, channelID) => getChannelGroupIDSet(state, channelID),
(allGroups, channelGroupIDSet) => {
......
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {createSelector} from 'reselect';
import * as reselect from 'reselect';
import {getCurrentTeamId} from 'selectors/entities/teams';
import {GlobalState} from 'types/store';
import * as types from 'types';
export function getIncomingHooks(state: GlobalState) {
export function getIncomingHooks(state: types.store.GlobalState) {
return state.entities.integrations.incomingHooks;
}
export function getOutgoingHooks(state: GlobalState) {
export function getOutgoingHooks(state: types.store.GlobalState) {
return state.entities.integrations.outgoingHooks;
}
export function getCommands(state: GlobalState) {
export function getCommands(state: types.store.GlobalState) {
return state.entities.integrations.commands;
}
export function getOAuthApps(state: GlobalState) {
export function getOAuthApps(state: types.store.GlobalState) {
return state.entities.integrations.oauthApps;
}
export function getSystemCommands(state: GlobalState) {
export function getSystemCommands(state: types.store.GlobalState) {
return state.entities.integrations.systemCommands;
}
/**
* get outgoing hooks in current team
*/
export const getOutgoingHooksInCurrentTeam = createSelector(
export const getOutgoingHooksInCurrentTeam = reselect.createSelector(
getCurrentTeamId,
getOutgoingHooks,
(teamId, hooks) => {
......@@ -37,7 +37,7 @@ export const getOutgoingHooksInCurrentTeam = createSelector(
}
);
export const getAllCommands = createSelector(
export const getAllCommands = reselect.createSelector(
getCommands,
getSystemCommands,
(commands, systemCommands) => {
......@@ -48,7 +48,7 @@ export const getAllCommands = createSelector(
}
);
export const getAutocompleteCommandsList = createSelector(
export const getAutocompleteCommandsList = reselect.createSelector(
getAllCommands,
getCurrentTeamId,
(commands, currentTeamId) => {
......
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {createSelector} from 'reselect';
import * as reselect from 'reselect';
export function getMarketplacePlugins(state) {
return state.entities.plugins.marketplacePlugins;
}
export const getMarketplaceInstalledPlugins = createSelector(
export const getMarketplaceInstalledPlugins = reselect.createSelector(
getMarketplacePlugins,
(plugins) => {
return Object.values(plugins).filter((p: any) => p.installed_version !== '');
......
......@@ -12,7 +12,7 @@ import {Post, PostWithFormatData} from 'types/posts';
import {Reaction} from 'types/reactions';
import {UserProfile} from 'types/users';
import {Channel} from 'types/channels';
import {$ID, IDMappedObjects, RelationOneToOne, RelationOneToMany} from '../../types/utilities';
import {$ID, IDMappedObjects, RelationOneToOne, RelationOneToMany} from 'types/utilities';
export function getAllPosts(state: GlobalState) {
return state.entities.posts.posts;
}
......
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {createSelector} from 'reselect';
import * as reselect from 'reselect';
import {General, Preferences} from '../../constants';
import {getConfig} from 'selectors/entities/general';
import {getCurrentTeamId} from 'selectors/entities/teams';
......@@ -34,7 +34,7 @@ export function getInt(state, category, name, defaultValue = 0) {
}
export function makeGetCategory() {
return createSelector(
return reselect.createSelector(
getMyPreferences,
(state, category) => category,
(preferences, category) => {
......@@ -71,21 +71,21 @@ export function getFavoritesPreferences(state) {
return favorites.filter((f) => f.value === 'true').map((f) => f.name);
}
export const getVisibleTeammate = createSelector(
export const getVisibleTeammate = reselect.createSelector(
getDirectShowPreferences,
(direct) => {
return direct.filter((dm) => dm.value === 'true' && dm.name).map((dm) => dm.name);
}
);
export const getVisibleGroupIds = createSelector(
export const getVisibleGroupIds = reselect.createSelector(
getGroupShowPreferences,
(groups) => {
return groups.filter((dm) => dm.value === 'true' && dm.name).map((dm) => dm.name);
}
);
export const getTeammateNameDisplaySetting = createSelector(
export const getTeammateNameDisplaySetting = reselect.createSelector(
getConfig,
getMyPreferences,
(config, preferences) => {
......@@ -99,7 +99,7 @@ export const getTeammateNameDisplaySetting = createSelector(
}
);
const getThemePreference = createSelector(
const getThemePreference = reselect.createSelector(
getMyPreferences,
getCurrentTeamId,
(myPreferences, currentTeamId) => {
......@@ -118,7 +118,7 @@ const getThemePreference = createSelector(
}
);
const getDefaultTheme = createSelector(getConfig, (config) => {
const getDefaultTheme = reselect.createSelector(getConfig, (config) => {
if (config.DefaultTheme) {
const theme = Preferences.THEMES[config.DefaultTheme];
if (theme) {
......@@ -177,7 +177,7 @@ export const getTheme = createShallowSelector(
);
export function makeGetStyleFromTheme() {
return createSelector(
return reselect.createSelector(
getTheme,
(state, getStyleFromTheme) => getStyleFromTheme,
(theme, getStyleFromTheme) => {
......@@ -193,7 +193,7 @@ const defaultSidebarPrefs = {
sorting: 'alpha',
};
export const getSidebarPreferences = createSelector(
export const getSidebarPreferences = reselect.createSelector(
(state: GlobalState) => {
const config = getConfig(state);
return config.ExperimentalGroupUnreadChannels !== General.DISABLED && getBool(
......
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {createSelector} from 'reselect';
import * as reselect from 'reselect';
import {getCurrentUser, getCurrentChannelId} from 'selectors/entities/common';
import {getTeamMemberships, getCurrentTeamId} from './teams';
import {GlobalState} from 'types/store';
import * as types from 'types';
import {getMySystemPermissions, getMySystemRoles, getRoles} from 'selectors/entities/roles_helpers';
export {getMySystemPermissions, getMySystemRoles, getRoles};
export const getMyTeamRoles = createSelector(
export const getMyTeamRoles = reselect.createSelector(
getTeamMemberships,
(teamsMemberships) => {
const roles = {};
......@@ -23,8 +23,8 @@ export const getMyTeamRoles = createSelector(
}
);
export const getMyChannelRoles = createSelector(
(state: GlobalState) => state.entities.channels.myMembers,
export const getMyChannelRoles = reselect.createSelector(
(state: types.store.GlobalState) => state.entities.channels.myMembers,
(channelsMemberships) => {
const roles = {};
if (channelsMemberships) {
......@@ -38,7 +38,7 @@ export const getMyChannelRoles = createSelector(
}
);
export const getMyRoles = createSelector(
export const getMyRoles = reselect.createSelector(
getMySystemRoles,
getMyTeamRoles,
getMyChannelRoles,
......@@ -51,7 +51,7 @@ export const getMyRoles = createSelector(
}
);
export const getRolesById = createSelector(
export const getRolesById = reselect.createSelector(
getRoles,
(rolesByName) => {
const rolesById = {};
......@@ -62,7 +62,7 @@ export const getRolesById = createSelector(
}
);
export const getMyCurrentTeamPermissions = createSelector(
export const getMyCurrentTeamPermissions = reselect.createSelector(
getMyTeamRoles,
getRoles,
getMySystemPermissions,
......@@ -85,7 +85,7 @@ export const getMyCurrentTeamPermissions = createSelector(
}
);
export const getMyCurrentChannelPermissions = createSelector(
export const getMyCurrentChannelPermissions = reselect.createSelector(
getMyChannelRoles,
getRoles,
getMyCurrentTeamPermissions,
......@@ -108,7 +108,7 @@ export const getMyCurrentChannelPermissions = createSelector(
}
);
export const getMyTeamPermissions = createSelector(
export const getMyTeamPermissions = reselect.createSelector(
getMyTeamRoles,
getRoles,
getMySystemPermissions,
......@@ -131,7 +131,7 @@ export const getMyTeamPermissions = createSelector(
}
);
export const getMyChannelPermissions = createSelector(
export const getMyChannelPermissions = reselect.createSelector(
getMyChannelRoles,
getRoles,
getMyTeamPermissions,
......@@ -154,7 +154,7 @@ export const getMyChannelPermissions = createSelector(
}
);
export const haveISystemPermission = createSelector(
export const haveISystemPermission = reselect.createSelector(
getMySystemPermissions,
(state, options) => options.permission,
(permissions, permission) => {
......@@ -162,7 +162,7 @@ export const haveISystemPermission = createSelector(
}
);
export const haveITeamPermission = createSelector(
export const haveITeamPermission = reselect.createSelector(
getMyTeamPermissions,
(state, options) => options.permission,
(permissions, permission) => {
......@@ -170,7 +170,7 @@ export const haveITeamPermission = createSelector(
}
);
export const haveIChannelPermission = createSelector(
export const haveIChannelPermission = reselect.createSelector(
getMyChannelPermissions,
(state, options) => options.permission,
(permissions, permission) => {
......@@ -178,7 +178,7 @@ export const haveIChannelPermission = createSelector(
}
);
export const haveICurrentTeamPermission = createSelector(
export const haveICurrentTeamPermission = reselect.createSelector(
getMyCurrentTeamPermissions,
(state, options) => options.permission,
(permissions, permission) => {
......@@ -186,7 +186,7 @@ export const haveICurrentTeamPermission = createSelector(
}
);
export const haveICurrentChannelPermission = createSelector(
export const haveICurrentChannelPermission = reselect.createSelector(
getMyCurrentChannelPermissions,
(state, options) => options.permission,
(permissions, permission) => {
......
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {createSelector} from 'reselect';
import * as reselect from 'reselect';
import {GlobalState} from 'types/store';
import {getCurrentUser} from 'selectors/entities/common';
import {UserProfile} from 'types/users';
import * as types from 'types';
export function getRoles(state: GlobalState) {
return state.entities.roles.roles;
}
export const getMySystemRoles = createSelector(getCurrentUser, (user: UserProfile) => {
export const getMySystemRoles = reselect.createSelector(getCurrentUser, (user: types.users.UserProfile) => {
if (user) {
return new Set<string>(user.roles.split(' '));
}
......@@ -17,7 +17,7 @@ export const getMySystemRoles = createSelector(getCurrentUser, (user: UserProfil
return new Set<string>();
});
export const getMySystemPermissions = createSelector(getMySystemRoles, getRoles, (mySystemRoles: Set<string>, roles) => {
export const getMySystemPermissions = reselect.createSelector(getMySystemRoles, getRoles, (mySystemRoles: Set<string>, roles) => {
const permissions = new Set<string>();
for (const roleName of mySystemRoles) {
......@@ -31,6 +31,6 @@ export const getMySystemPermissions = createSelector(getMySystemRoles, getRoles,
return permissions;
});
export const haveISystemPermission = createSelector(getMySystemPermissions, (state, options) => options.permission, (permissions, permission) => {
export const haveISystemPermission = reselect.createSelector(getMySystemPermissions, (state, options) => options.permission, (permissions, permission) => {
return permissions.has(permission);
});
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {createSelector} from 'reselect';
import * as reselect from 'reselect';
import {getCurrentTeamId} from 'selectors/entities/teams';
export const getCurrentSearchForCurrentTeam = createSelector(
(state) => state.entities.search.current,
import * as types from 'types';
export const getCurrentSearchForCurrentTeam = reselect.createSelector(
(state: types.store.GlobalState) => state.entities.search.current,
getCurrentTeamId,
(current, teamId) => {
return current[teamId];
}
);
\ No newline at end of file
);
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {createSelector} from 'reselect';
import * as reselect from 'reselect';
import {Permissions} from '../../constants';
import {getConfig, getCurrentUrl, isCompatibleWithJoinViewTeamPermissions} from 'selectors/entities/general';
import {haveISystemPermission} from 'selectors/entities/roles_helpers';
......@@ -14,7 +14,7 @@ export function getCurrentTeamId(state: GlobalState) {
return state.entities.teams.currentTeamId;
}
export const getTeamByName = createSelector(getTeams, (state, name) => name, (teams, name) => {