[MM-58108] Posts missing channel_id in handleThreadReadChanged, handleAllThreadsInChannelMarkedRead, getThreadItemsInChannel (#27006)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
f0110e361e
Коммит
7d7b203567
@@ -1632,9 +1632,9 @@ function handleThreadReadChanged(msg) {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else if (msg.broadcast.channel_id) {
|
} else if (msg.broadcast.channel_id) {
|
||||||
handleAllThreadsInChannelMarkedRead(doDispatch, doGetState, msg.broadcast.channel_id, msg.data.timestamp);
|
doDispatch(handleAllThreadsInChannelMarkedRead(msg.broadcast.channel_id, msg.data.timestamp));
|
||||||
} else {
|
} else {
|
||||||
handleAllMarkedRead(doDispatch, msg.broadcast.team_id);
|
doDispatch(handleAllMarkedRead(msg.broadcast.team_id));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {getChannel} from 'mattermost-redux/selectors/entities/channels';
|
|||||||
import {makeGetPostsForThread} from 'mattermost-redux/selectors/entities/posts';
|
import {makeGetPostsForThread} from 'mattermost-redux/selectors/entities/posts';
|
||||||
import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
|
import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
|
||||||
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
import {getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams';
|
||||||
import {getThread as getThreadSelector, getThreadItemsInChannel} from 'mattermost-redux/selectors/entities/threads';
|
import {getThread as getThreadSelector, getThreadsInChannel} from 'mattermost-redux/selectors/entities/threads';
|
||||||
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users';
|
||||||
import type {DispatchFunc, GetStateFunc, ActionFunc, ActionFuncAsync} from 'mattermost-redux/types/actions';
|
import type {DispatchFunc, GetStateFunc, ActionFunc, ActionFuncAsync} from 'mattermost-redux/types/actions';
|
||||||
|
|
||||||
@@ -248,13 +248,13 @@ export function getThread(userId: string, teamId: string, threadId: string, exte
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleAllMarkedRead(dispatch: DispatchFunc, teamId: string) {
|
export function handleAllMarkedRead(teamId: string) {
|
||||||
dispatch({
|
return {
|
||||||
type: ThreadTypes.ALL_TEAM_THREADS_READ,
|
type: ThreadTypes.ALL_TEAM_THREADS_READ,
|
||||||
data: {
|
data: {
|
||||||
team_id: teamId,
|
team_id: teamId,
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function markAllThreadsInTeamRead(userId: string, teamId: string): ActionFuncAsync {
|
export function markAllThreadsInTeamRead(userId: string, teamId: string): ActionFuncAsync {
|
||||||
@@ -267,7 +267,7 @@ export function markAllThreadsInTeamRead(userId: string, teamId: string): Action
|
|||||||
return {error};
|
return {error};
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAllMarkedRead(dispatch, teamId);
|
dispatch(handleAllMarkedRead(teamId));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
@@ -395,32 +395,38 @@ export function setThreadFollow(userId: string, teamId: string, threadId: string
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleAllThreadsInChannelMarkedRead(dispatch: DispatchFunc, getState: GetStateFunc, channelId: string, lastViewedAt: number) {
|
export function handleAllThreadsInChannelMarkedRead(channelId: string, lastViewedAt: number): ActionFunc<boolean> {
|
||||||
const state = getState();
|
return (dispatch, getState) => {
|
||||||
const threadsInChannel = getThreadItemsInChannel(state, channelId);
|
const state = getState();
|
||||||
const channel = getChannel(state, channelId);
|
|
||||||
if (channel == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const teamId = channel.team_id;
|
|
||||||
const actions = [];
|
|
||||||
|
|
||||||
for (const thread of threadsInChannel) {
|
const channel = getChannel(state, channelId);
|
||||||
actions.push({
|
if (channel == null) {
|
||||||
type: ThreadTypes.READ_CHANGED_THREAD,
|
return {data: false};
|
||||||
data: {
|
}
|
||||||
id: thread.id,
|
|
||||||
channelId,
|
|
||||||
teamId,
|
|
||||||
lastViewedAt,
|
|
||||||
newUnreadMentions: 0,
|
|
||||||
newUnreadReplies: 0,
|
|
||||||
isUrgent: thread.is_urgent,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
dispatch(batchActions(actions));
|
const teamId = channel.team_id;
|
||||||
|
const threadsInChannel = getThreadsInChannel(state, channelId);
|
||||||
|
|
||||||
|
const actions = [];
|
||||||
|
for (const thread of threadsInChannel) {
|
||||||
|
actions.push({
|
||||||
|
type: ThreadTypes.READ_CHANGED_THREAD,
|
||||||
|
data: {
|
||||||
|
id: thread.id,
|
||||||
|
channelId,
|
||||||
|
teamId,
|
||||||
|
lastViewedAt,
|
||||||
|
newUnreadMentions: 0,
|
||||||
|
newUnreadReplies: 0,
|
||||||
|
isUrgent: thread.is_urgent,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(batchActions(actions));
|
||||||
|
|
||||||
|
return {data: true};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decrementThreadCounts(post: ExtendedPost): ActionFunc {
|
export function decrementThreadCounts(post: ExtendedPost): ActionFunc {
|
||||||
|
|||||||
@@ -189,6 +189,10 @@ describe('Selectors.Threads.getThreadsInChannel', () => {
|
|||||||
|
|
||||||
it('should return threads in channel', () => {
|
it('should return threads in channel', () => {
|
||||||
const user = TestHelper.fakeUserWithId();
|
const user = TestHelper.fakeUserWithId();
|
||||||
|
const thread1 = TestHelper.fakeThread(user.id, channel1.id);
|
||||||
|
const thread2 = TestHelper.fakeThread(user.id, channel1.id);
|
||||||
|
const thread3 = TestHelper.fakeThread(user.id, channel2.id);
|
||||||
|
const thread4 = TestHelper.fakeThread(user.id, channel3.id);
|
||||||
|
|
||||||
const profiles = {
|
const profiles = {
|
||||||
[user.id]: user,
|
[user.id]: user,
|
||||||
@@ -205,36 +209,20 @@ describe('Selectors.Threads.getThreadsInChannel', () => {
|
|||||||
},
|
},
|
||||||
threads: {
|
threads: {
|
||||||
threads: {
|
threads: {
|
||||||
a: {
|
[thread1.id]: thread1,
|
||||||
post: {
|
[thread2.id]: thread2,
|
||||||
channel_id: channel1.id,
|
[thread3.id]: thread3,
|
||||||
},
|
[thread4.id]: thread4,
|
||||||
},
|
|
||||||
b: {
|
|
||||||
post: {
|
|
||||||
channel_id: channel1.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
c: {
|
|
||||||
post: {
|
|
||||||
channel_id: channel2.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
d: {
|
|
||||||
post: {
|
|
||||||
channel_id: channel3.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
threadsInTeam: {
|
threadsInTeam: {
|
||||||
[team1.id]: ['a', 'b', 'c'],
|
[team1.id]: [thread1.id, thread2.id, thread3.id],
|
||||||
[team2.id]: ['d'],
|
[team2.id]: [thread4.id],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(Selectors.getThreadsInChannel(testState, channel1.id)).toEqual(['a', 'b']);
|
expect(Selectors.getThreadsInChannel(testState, channel1.id)).toEqual([thread1, thread2]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -176,25 +176,20 @@ function sortByLastReply(ids: Array<UserThread['id']>, threads: ReturnType<typeo
|
|||||||
export const getThreadsInChannel: (
|
export const getThreadsInChannel: (
|
||||||
state: GlobalState,
|
state: GlobalState,
|
||||||
channelID: string,
|
channelID: string,
|
||||||
) => Array<UserThread['id']> = createSelector(
|
) => UserThread[] = createSelector(
|
||||||
'getThreadsInChannel',
|
'getThreadsInChannel',
|
||||||
getThreads,
|
getThreads,
|
||||||
(state: GlobalState, channelID: string) => channelID,
|
(_: GlobalState, channelID: string) => channelID,
|
||||||
(allThreads: IDMappedObjects<UserThread>, channelID: string) => {
|
(threads: IDMappedObjects<UserThread>, channelID: Channel['id']) => {
|
||||||
return Object.keys(allThreads).filter((id) => allThreads[id].post.channel_id === channelID);
|
const allThreads = Object.values(threads);
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
export const getThreadItemsInChannel: (
|
const threadsInChannel: UserThread[] = [];
|
||||||
state: GlobalState,
|
for (const thread of allThreads) {
|
||||||
channelID: string,
|
if (thread && thread.post && thread.post.channel_id && thread.post.channel_id === channelID) {
|
||||||
) => UserThread[] = createSelector(
|
threadsInChannel.push(thread);
|
||||||
'getThreadItemsInChannel',
|
}
|
||||||
getThreads,
|
}
|
||||||
(state: GlobalState, channelID: string) => channelID,
|
|
||||||
(allThreads: IDMappedObjects<UserThread>, channelID: Channel['id']) => {
|
return threadsInChannel;
|
||||||
return Object.keys(allThreads).
|
|
||||||
map((id) => allThreads[id]).
|
|
||||||
filter((item) => item.post.channel_id === channelID);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import type {Reaction} from '@mattermost/types/reactions';
|
|||||||
import type {Role} from '@mattermost/types/roles';
|
import type {Role} from '@mattermost/types/roles';
|
||||||
import type {Scheme} from '@mattermost/types/schemes';
|
import type {Scheme} from '@mattermost/types/schemes';
|
||||||
import type {Team, TeamMembership} from '@mattermost/types/teams';
|
import type {Team, TeamMembership} from '@mattermost/types/teams';
|
||||||
|
import type {UserThread} from '@mattermost/types/threads';
|
||||||
import type {UserProfile, UserNotifyProps} from '@mattermost/types/users';
|
import type {UserProfile, UserNotifyProps} from '@mattermost/types/users';
|
||||||
|
|
||||||
export const DEFAULT_SERVER = 'http://localhost:8065';
|
export const DEFAULT_SERVER = 'http://localhost:8065';
|
||||||
@@ -553,6 +554,23 @@ class TestHelper {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fakeThread = (userId: string, channelId: string, override?: Partial<UserThread>): UserThread => {
|
||||||
|
return {
|
||||||
|
id: this.generateId(),
|
||||||
|
reply_count: 0,
|
||||||
|
last_reply_at: 0,
|
||||||
|
last_viewed_at: 0,
|
||||||
|
participants: [],
|
||||||
|
unread_replies: 0,
|
||||||
|
unread_mentions: 0,
|
||||||
|
is_following: true,
|
||||||
|
post: {
|
||||||
|
channel_id: channelId,
|
||||||
|
user_id: userId,
|
||||||
|
},
|
||||||
|
...override,
|
||||||
|
};
|
||||||
|
};
|
||||||
getFileInfoMock = (override: Partial<FileInfo>): FileInfo => {
|
getFileInfoMock = (override: Partial<FileInfo>): FileInfo => {
|
||||||
return {
|
return {
|
||||||
id: '',
|
id: '',
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user