mattermost-redux
Version:
Common code (API client, Redux stores, logic, utility functions) for building a Mattermost client
148 lines (121 loc) • 3.84 kB
text/typescript
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {combineReducers} from 'redux';
import {FileTypes, PostTypes, UserTypes} from 'action_types';
import {GenericAction} from 'types/actions';
import {Post} from 'types/posts';
import {FileInfo} from 'types/files';
import {Dictionary} from 'types/utilities';
export function files(state: Dictionary<FileInfo> = {}, action: GenericAction) {
switch (action.type) {
case FileTypes.RECEIVED_UPLOAD_FILES:
case FileTypes.RECEIVED_FILES_FOR_POST: {
const filesById = action.data.reduce((filesMap: any, file: any) => {
return {...filesMap,
[file.id]: file,
};
}, {} as any);
return {...state,
...filesById,
};
}
case PostTypes.RECEIVED_NEW_POST:
case PostTypes.RECEIVED_POST: {
const post = action.data;
return storeFilesForPost(state, post);
}
case PostTypes.RECEIVED_POSTS: {
const posts = Object.values(action.data.posts);
return posts.reduce(storeFilesForPost, state);
}
case PostTypes.POST_DELETED:
case PostTypes.POST_REMOVED: {
if (action.data && action.data.file_ids && action.data.file_ids.length) {
const nextState = {...state};
const fileIds = action.data.file_ids as string[];
fileIds.forEach((id) => {
Reflect.deleteProperty(nextState, id);
});
return nextState;
}
return state;
}
case UserTypes.LOGOUT_SUCCESS:
return {};
default:
return state;
}
}
function storeFilesForPost(state: Dictionary<FileInfo>, post: Post) {
if (!post.metadata || !post.metadata.files) {
return state;
}
return post.metadata.files.reduce((nextState, file) => {
if (nextState[file.id]) {
// File is already in the store
return nextState;
}
return {
...nextState,
[file.id]: file,
};
}, state);
}
export function fileIdsByPostId(state: Dictionary<string[]> = {}, action: GenericAction) {
switch (action.type) {
case FileTypes.RECEIVED_FILES_FOR_POST: {
const {data, postId} = action;
const filesIdsForPost = data.map((file: FileInfo) => file.id);
return {...state,
[postId as string]: filesIdsForPost,
};
}
case PostTypes.RECEIVED_NEW_POST:
case PostTypes.RECEIVED_POST: {
const post = action.data;
return storeFilesIdsForPost(state, post);
}
case PostTypes.RECEIVED_POSTS: {
const posts = Object.values(action.data.posts);
return posts.reduce(storeFilesIdsForPost, state);
}
case PostTypes.POST_DELETED:
case PostTypes.POST_REMOVED: {
if (action.data) {
const nextState = {...state};
Reflect.deleteProperty(nextState, action.data.id);
return nextState;
}
return state;
}
case UserTypes.LOGOUT_SUCCESS:
return {};
default:
return state;
}
}
function storeFilesIdsForPost(state: Dictionary<string[]>, post: Post) {
if (!post.metadata || !post.metadata.files) {
return state;
}
return {
...state,
[post.id]: post.metadata.files ? post.metadata.files.map((file) => file.id) : [],
};
}
function filePublicLink(state: {link: string} = {link: ''}, action: GenericAction) {
switch (action.type) {
case FileTypes.RECEIVED_FILE_PUBLIC_LINK: {
return action.data;
}
case UserTypes.LOGOUT_SUCCESS:
return {link: ''};
default:
return state;
}
}
export default combineReducers({
files,
fileIdsByPostId,
filePublicLink,
});