mattermost-redux 11.2.0 → 11.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/action_types/index.d.ts +2 -1
- package/lib/action_types/index.js +3 -1
- package/lib/action_types/posts.d.ts +3 -0
- package/lib/action_types/posts.js +3 -0
- package/lib/action_types/recaps.d.ts +23 -0
- package/lib/action_types/recaps.js +30 -0
- package/lib/actions/access_control.d.ts +2 -2
- package/lib/actions/access_control.js +7 -10
- package/lib/actions/recaps.d.ts +8 -0
- package/lib/actions/recaps.js +76 -0
- package/lib/actions/teams.d.ts +1 -1
- package/lib/actions/teams.js +2 -1
- package/lib/constants/posts.d.ts +19 -0
- package/lib/constants/posts.js +18 -0
- package/lib/constants/preferences.d.ts +2 -0
- package/lib/constants/preferences.js +2 -0
- package/lib/constants/websocket.d.ts +3 -0
- package/lib/constants/websocket.js +3 -0
- package/lib/reducers/entities/index.d.ts +2 -0
- package/lib/reducers/entities/index.js +2 -0
- package/lib/reducers/entities/posts.js +130 -16
- package/lib/reducers/entities/recaps.d.ts +7 -0
- package/lib/reducers/entities/recaps.js +52 -0
- package/lib/reducers/index.d.ts +2 -0
- package/lib/selectors/entities/channel_banner.d.ts +0 -1
- package/lib/selectors/entities/channel_banner.js +1 -11
- package/lib/selectors/entities/posts.js +9 -2
- package/lib/selectors/entities/recaps.d.ts +11 -0
- package/lib/selectors/entities/recaps.js +34 -0
- package/lib/store/initial_state.js +4 -0
- package/lib/utils/integration_utils.js +2 -1
- package/lib/utils/post_list.js +10 -0
- package/lib/utils/post_utils.js +3 -0
- package/package.json +3 -3
|
@@ -22,6 +22,7 @@ import PlaybookType from './playbooks';
|
|
|
22
22
|
import PluginTypes from './plugins';
|
|
23
23
|
import PostTypes from './posts';
|
|
24
24
|
import PreferenceTypes from './preferences';
|
|
25
|
+
import RecapTypes from './recaps';
|
|
25
26
|
import RoleTypes from './roles';
|
|
26
27
|
import SchemeTypes from './schemes';
|
|
27
28
|
import ScheduledPostTypes from './scheudled_posts';
|
|
@@ -30,7 +31,7 @@ import SharedChannelTypes from './shared_channels';
|
|
|
30
31
|
import TeamTypes from './teams';
|
|
31
32
|
import ThreadTypes from './threads';
|
|
32
33
|
import UserTypes from './users';
|
|
33
|
-
export { ErrorTypes, GeneralTypes, UserTypes, TeamTypes, ChannelTypes, PostTypes, FileTypes, PreferenceTypes, IntegrationTypes, EmojiTypes, AdminTypes, JobTypes, LimitsTypes, SearchTypes, RoleTypes, SchemeTypes, GroupTypes, BotTypes, PluginTypes, ChannelCategoryTypes, CloudTypes, AppsTypes, ThreadTypes, HostedCustomerTypes, DraftTypes, PlaybookType, ChannelBookmarkTypes, ScheduledPostTypes, SharedChannelTypes, ContentFlaggingTypes, AgentTypes, };
|
|
34
|
+
export { ErrorTypes, GeneralTypes, UserTypes, TeamTypes, ChannelTypes, PostTypes, FileTypes, PreferenceTypes, RecapTypes, IntegrationTypes, EmojiTypes, AdminTypes, JobTypes, LimitsTypes, SearchTypes, RoleTypes, SchemeTypes, GroupTypes, BotTypes, PluginTypes, ChannelCategoryTypes, CloudTypes, AppsTypes, ThreadTypes, HostedCustomerTypes, DraftTypes, PlaybookType, ChannelBookmarkTypes, ScheduledPostTypes, SharedChannelTypes, ContentFlaggingTypes, AgentTypes, };
|
|
34
35
|
/**
|
|
35
36
|
* An MMReduxAction is any non-Thunk Redux action accepted by mattermost-redux.
|
|
36
37
|
*/
|
|
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
6
|
};
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.AgentTypes = exports.ContentFlaggingTypes = exports.SharedChannelTypes = exports.ScheduledPostTypes = exports.ChannelBookmarkTypes = exports.PlaybookType = exports.DraftTypes = exports.HostedCustomerTypes = exports.ThreadTypes = exports.AppsTypes = exports.CloudTypes = exports.ChannelCategoryTypes = exports.PluginTypes = exports.BotTypes = exports.GroupTypes = exports.SchemeTypes = exports.RoleTypes = exports.SearchTypes = exports.LimitsTypes = exports.JobTypes = exports.AdminTypes = exports.EmojiTypes = exports.IntegrationTypes = exports.PreferenceTypes = exports.FileTypes = exports.PostTypes = exports.ChannelTypes = exports.TeamTypes = exports.UserTypes = exports.GeneralTypes = exports.ErrorTypes = void 0;
|
|
8
|
+
exports.AgentTypes = exports.ContentFlaggingTypes = exports.SharedChannelTypes = exports.ScheduledPostTypes = exports.ChannelBookmarkTypes = exports.PlaybookType = exports.DraftTypes = exports.HostedCustomerTypes = exports.ThreadTypes = exports.AppsTypes = exports.CloudTypes = exports.ChannelCategoryTypes = exports.PluginTypes = exports.BotTypes = exports.GroupTypes = exports.SchemeTypes = exports.RoleTypes = exports.SearchTypes = exports.LimitsTypes = exports.JobTypes = exports.AdminTypes = exports.EmojiTypes = exports.IntegrationTypes = exports.RecapTypes = exports.PreferenceTypes = exports.FileTypes = exports.PostTypes = exports.ChannelTypes = exports.TeamTypes = exports.UserTypes = exports.GeneralTypes = exports.ErrorTypes = void 0;
|
|
9
9
|
const admin_1 = __importDefault(require("./admin"));
|
|
10
10
|
exports.AdminTypes = admin_1.default;
|
|
11
11
|
const agents_1 = __importDefault(require("./agents"));
|
|
@@ -52,6 +52,8 @@ const posts_1 = __importDefault(require("./posts"));
|
|
|
52
52
|
exports.PostTypes = posts_1.default;
|
|
53
53
|
const preferences_1 = __importDefault(require("./preferences"));
|
|
54
54
|
exports.PreferenceTypes = preferences_1.default;
|
|
55
|
+
const recaps_1 = __importDefault(require("./recaps"));
|
|
56
|
+
exports.RecapTypes = recaps_1.default;
|
|
55
57
|
const roles_1 = __importDefault(require("./roles"));
|
|
56
58
|
exports.RoleTypes = roles_1.default;
|
|
57
59
|
const schemes_1 = __importDefault(require("./schemes"));
|
|
@@ -41,5 +41,8 @@ declare const _default: {
|
|
|
41
41
|
DELETE_ACK_POST_SUCCESS: "DELETE_ACK_POST_SUCCESS";
|
|
42
42
|
MOVE_POST_SUCCESS: "MOVE_POST_SUCCESS";
|
|
43
43
|
MOVE_POST_FAILURE: "MOVE_POST_FAILURE";
|
|
44
|
+
REVEAL_BURN_ON_READ_SUCCESS: "REVEAL_BURN_ON_READ_SUCCESS";
|
|
45
|
+
POST_RECIPIENTS_UPDATED: "POST_RECIPIENTS_UPDATED";
|
|
46
|
+
BURN_ON_READ_ALL_REVEALED: "BURN_ON_READ_ALL_REVEALED";
|
|
44
47
|
};
|
|
45
48
|
export default _default;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
CREATE_RECAP_REQUEST: "CREATE_RECAP_REQUEST";
|
|
3
|
+
CREATE_RECAP_SUCCESS: "CREATE_RECAP_SUCCESS";
|
|
4
|
+
CREATE_RECAP_FAILURE: "CREATE_RECAP_FAILURE";
|
|
5
|
+
RECEIVED_RECAP: "RECEIVED_RECAP";
|
|
6
|
+
RECEIVED_RECAPS: "RECEIVED_RECAPS";
|
|
7
|
+
GET_RECAP_REQUEST: "GET_RECAP_REQUEST";
|
|
8
|
+
GET_RECAP_SUCCESS: "GET_RECAP_SUCCESS";
|
|
9
|
+
GET_RECAP_FAILURE: "GET_RECAP_FAILURE";
|
|
10
|
+
GET_RECAPS_REQUEST: "GET_RECAPS_REQUEST";
|
|
11
|
+
GET_RECAPS_SUCCESS: "GET_RECAPS_SUCCESS";
|
|
12
|
+
GET_RECAPS_FAILURE: "GET_RECAPS_FAILURE";
|
|
13
|
+
MARK_RECAP_READ_REQUEST: "MARK_RECAP_READ_REQUEST";
|
|
14
|
+
MARK_RECAP_READ_SUCCESS: "MARK_RECAP_READ_SUCCESS";
|
|
15
|
+
MARK_RECAP_READ_FAILURE: "MARK_RECAP_READ_FAILURE";
|
|
16
|
+
DELETE_RECAP_REQUEST: "DELETE_RECAP_REQUEST";
|
|
17
|
+
DELETE_RECAP_SUCCESS: "DELETE_RECAP_SUCCESS";
|
|
18
|
+
DELETE_RECAP_FAILURE: "DELETE_RECAP_FAILURE";
|
|
19
|
+
REGENERATE_RECAP_REQUEST: "REGENERATE_RECAP_REQUEST";
|
|
20
|
+
REGENERATE_RECAP_SUCCESS: "REGENERATE_RECAP_SUCCESS";
|
|
21
|
+
REGENERATE_RECAP_FAILURE: "REGENERATE_RECAP_FAILURE";
|
|
22
|
+
};
|
|
23
|
+
export default _default;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const key_mirror_1 = __importDefault(require("mattermost-redux/utils/key_mirror"));
|
|
9
|
+
exports.default = (0, key_mirror_1.default)({
|
|
10
|
+
CREATE_RECAP_REQUEST: null,
|
|
11
|
+
CREATE_RECAP_SUCCESS: null,
|
|
12
|
+
CREATE_RECAP_FAILURE: null,
|
|
13
|
+
RECEIVED_RECAP: null,
|
|
14
|
+
RECEIVED_RECAPS: null,
|
|
15
|
+
GET_RECAP_REQUEST: null,
|
|
16
|
+
GET_RECAP_SUCCESS: null,
|
|
17
|
+
GET_RECAP_FAILURE: null,
|
|
18
|
+
GET_RECAPS_REQUEST: null,
|
|
19
|
+
GET_RECAPS_SUCCESS: null,
|
|
20
|
+
GET_RECAPS_FAILURE: null,
|
|
21
|
+
MARK_RECAP_READ_REQUEST: null,
|
|
22
|
+
MARK_RECAP_READ_SUCCESS: null,
|
|
23
|
+
MARK_RECAP_READ_FAILURE: null,
|
|
24
|
+
DELETE_RECAP_REQUEST: null,
|
|
25
|
+
DELETE_RECAP_SUCCESS: null,
|
|
26
|
+
DELETE_RECAP_FAILURE: null,
|
|
27
|
+
REGENERATE_RECAP_REQUEST: null,
|
|
28
|
+
REGENERATE_RECAP_SUCCESS: null,
|
|
29
|
+
REGENERATE_RECAP_FAILURE: null,
|
|
30
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AccessControlPoliciesResult, AccessControlPolicy, AccessControlTestResult } from '@mattermost/types/access_control';
|
|
1
|
+
import type { AccessControlPoliciesResult, AccessControlPolicy, AccessControlPolicyActiveUpdate, AccessControlTestResult } from '@mattermost/types/access_control';
|
|
2
2
|
import type { ChannelSearchOpts, ChannelsWithTotalCount } from '@mattermost/types/channels';
|
|
3
3
|
import type { ActionFuncAsync } from 'mattermost-redux/types/actions';
|
|
4
4
|
export declare function getAccessControlPolicy(id: string, channelId?: string): ActionFuncAsync<AccessControlPolicy, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
@@ -9,7 +9,6 @@ export declare function searchAccessControlPolicyChannels(id: string, term: stri
|
|
|
9
9
|
export declare function assignChannelsToAccessControlPolicy(policyId: string, channelIds: string[]): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
10
10
|
export declare function unassignChannelsFromAccessControlPolicy(policyId: string, channelIds: string[]): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
11
11
|
export declare function getAccessControlFields(after: string, limit: number, channelId?: string): ActionFuncAsync<import("@mattermost/types/properties").UserPropertyField[], import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
12
|
-
export declare function updateAccessControlPolicyActive(policyId: string, active: boolean): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
13
12
|
export declare function searchUsersForExpression(expression: string, term: string, after: string, limit: number, channelId?: string): ActionFuncAsync<AccessControlTestResult>;
|
|
14
13
|
export declare function getVisualAST(expression: string, channelId?: string): ActionFuncAsync<import("@mattermost/types/access_control").AccessControlVisualAST, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
15
14
|
export declare function validateExpressionAgainstRequester(expression: string, channelId?: string): ActionFuncAsync<{
|
|
@@ -18,3 +17,4 @@ export declare function validateExpressionAgainstRequester(expression: string, c
|
|
|
18
17
|
export declare function createAccessControlSyncJob(jobData: {
|
|
19
18
|
policy_id: string;
|
|
20
19
|
}): ActionFuncAsync<any>;
|
|
20
|
+
export declare function updateAccessControlPoliciesActive(states: AccessControlPolicyActiveUpdate[]): ActionFuncAsync<AccessControlPolicy[], import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
@@ -10,11 +10,11 @@ exports.searchAccessControlPolicyChannels = searchAccessControlPolicyChannels;
|
|
|
10
10
|
exports.assignChannelsToAccessControlPolicy = assignChannelsToAccessControlPolicy;
|
|
11
11
|
exports.unassignChannelsFromAccessControlPolicy = unassignChannelsFromAccessControlPolicy;
|
|
12
12
|
exports.getAccessControlFields = getAccessControlFields;
|
|
13
|
-
exports.updateAccessControlPolicyActive = updateAccessControlPolicyActive;
|
|
14
13
|
exports.searchUsersForExpression = searchUsersForExpression;
|
|
15
14
|
exports.getVisualAST = getVisualAST;
|
|
16
15
|
exports.validateExpressionAgainstRequester = validateExpressionAgainstRequester;
|
|
17
16
|
exports.createAccessControlSyncJob = createAccessControlSyncJob;
|
|
17
|
+
exports.updateAccessControlPoliciesActive = updateAccessControlPoliciesActive;
|
|
18
18
|
const redux_batched_actions_1 = require("redux-batched-actions");
|
|
19
19
|
const action_types_1 = require("mattermost-redux/action_types");
|
|
20
20
|
const client_1 = require("mattermost-redux/client");
|
|
@@ -115,15 +115,6 @@ function getAccessControlFields(after, limit, channelId) {
|
|
|
115
115
|
],
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
|
-
function updateAccessControlPolicyActive(policyId, active) {
|
|
119
|
-
return (0, helpers_1.bindClientFunc)({
|
|
120
|
-
clientFunc: client_1.Client4.updateAccessControlPolicyActive,
|
|
121
|
-
params: [
|
|
122
|
-
policyId,
|
|
123
|
-
active,
|
|
124
|
-
],
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
118
|
function searchUsersForExpression(expression, term, after, limit, channelId) {
|
|
128
119
|
return async (dispatch, getState) => {
|
|
129
120
|
let data;
|
|
@@ -170,3 +161,9 @@ function createAccessControlSyncJob(jobData) {
|
|
|
170
161
|
return { data };
|
|
171
162
|
};
|
|
172
163
|
}
|
|
164
|
+
function updateAccessControlPoliciesActive(states) {
|
|
165
|
+
return (0, helpers_1.bindClientFunc)({
|
|
166
|
+
clientFunc: client_1.Client4.updateAccessControlPoliciesActive,
|
|
167
|
+
params: [states],
|
|
168
|
+
});
|
|
169
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Recap } from '@mattermost/types/recaps';
|
|
2
|
+
import type { ActionFuncAsync } from 'mattermost-redux/types/actions';
|
|
3
|
+
export declare function createRecap(title: string, channelIds: string[], agentId: string): ActionFuncAsync<Recap>;
|
|
4
|
+
export declare function getRecaps(page?: number, perPage?: number): ActionFuncAsync<Recap[]>;
|
|
5
|
+
export declare function getRecap(recapId: string): ActionFuncAsync<Recap>;
|
|
6
|
+
export declare function markRecapAsRead(recapId: string): ActionFuncAsync<Recap>;
|
|
7
|
+
export declare function regenerateRecap(recapId: string): ActionFuncAsync<Recap>;
|
|
8
|
+
export declare function deleteRecap(recapId: string): ActionFuncAsync;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.createRecap = createRecap;
|
|
6
|
+
exports.getRecaps = getRecaps;
|
|
7
|
+
exports.getRecap = getRecap;
|
|
8
|
+
exports.markRecapAsRead = markRecapAsRead;
|
|
9
|
+
exports.regenerateRecap = regenerateRecap;
|
|
10
|
+
exports.deleteRecap = deleteRecap;
|
|
11
|
+
const action_types_1 = require("mattermost-redux/action_types");
|
|
12
|
+
const errors_1 = require("mattermost-redux/actions/errors");
|
|
13
|
+
const client_1 = require("mattermost-redux/client");
|
|
14
|
+
const helpers_1 = require("./helpers");
|
|
15
|
+
function createRecap(title, channelIds, agentId) {
|
|
16
|
+
return (0, helpers_1.bindClientFunc)({
|
|
17
|
+
clientFunc: () => client_1.Client4.createRecap({ title, channel_ids: channelIds, agent_id: agentId }),
|
|
18
|
+
onRequest: action_types_1.RecapTypes.CREATE_RECAP_REQUEST,
|
|
19
|
+
onSuccess: [action_types_1.RecapTypes.CREATE_RECAP_SUCCESS, action_types_1.RecapTypes.RECEIVED_RECAP],
|
|
20
|
+
onFailure: action_types_1.RecapTypes.CREATE_RECAP_FAILURE,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function getRecaps(page = 0, perPage = 60) {
|
|
24
|
+
return (0, helpers_1.bindClientFunc)({
|
|
25
|
+
clientFunc: () => client_1.Client4.getRecaps(page, perPage),
|
|
26
|
+
onRequest: action_types_1.RecapTypes.GET_RECAPS_REQUEST,
|
|
27
|
+
onSuccess: [action_types_1.RecapTypes.GET_RECAPS_SUCCESS, action_types_1.RecapTypes.RECEIVED_RECAPS],
|
|
28
|
+
onFailure: action_types_1.RecapTypes.GET_RECAPS_FAILURE,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function getRecap(recapId) {
|
|
32
|
+
return (0, helpers_1.bindClientFunc)({
|
|
33
|
+
clientFunc: () => client_1.Client4.getRecap(recapId),
|
|
34
|
+
onRequest: action_types_1.RecapTypes.GET_RECAP_REQUEST,
|
|
35
|
+
onSuccess: [action_types_1.RecapTypes.GET_RECAP_SUCCESS, action_types_1.RecapTypes.RECEIVED_RECAP],
|
|
36
|
+
onFailure: action_types_1.RecapTypes.GET_RECAP_FAILURE,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function markRecapAsRead(recapId) {
|
|
40
|
+
return (0, helpers_1.bindClientFunc)({
|
|
41
|
+
clientFunc: () => client_1.Client4.markRecapAsRead(recapId),
|
|
42
|
+
onRequest: action_types_1.RecapTypes.MARK_RECAP_READ_REQUEST,
|
|
43
|
+
onSuccess: [action_types_1.RecapTypes.MARK_RECAP_READ_SUCCESS, action_types_1.RecapTypes.RECEIVED_RECAP],
|
|
44
|
+
onFailure: action_types_1.RecapTypes.MARK_RECAP_READ_FAILURE,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function regenerateRecap(recapId) {
|
|
48
|
+
return (0, helpers_1.bindClientFunc)({
|
|
49
|
+
clientFunc: () => client_1.Client4.regenerateRecap(recapId),
|
|
50
|
+
onRequest: action_types_1.RecapTypes.REGENERATE_RECAP_REQUEST,
|
|
51
|
+
onSuccess: [action_types_1.RecapTypes.REGENERATE_RECAP_SUCCESS, action_types_1.RecapTypes.RECEIVED_RECAP],
|
|
52
|
+
onFailure: action_types_1.RecapTypes.REGENERATE_RECAP_FAILURE,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function deleteRecap(recapId) {
|
|
56
|
+
return async (dispatch, getState) => {
|
|
57
|
+
dispatch({ type: action_types_1.RecapTypes.DELETE_RECAP_REQUEST, data: recapId });
|
|
58
|
+
try {
|
|
59
|
+
await client_1.Client4.deleteRecap(recapId);
|
|
60
|
+
dispatch({
|
|
61
|
+
type: action_types_1.RecapTypes.DELETE_RECAP_SUCCESS,
|
|
62
|
+
data: { recapId },
|
|
63
|
+
});
|
|
64
|
+
return { data: true };
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
dispatch((0, errors_1.logError)(error));
|
|
68
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
69
|
+
dispatch({
|
|
70
|
+
type: action_types_1.RecapTypes.DELETE_RECAP_FAILURE,
|
|
71
|
+
error,
|
|
72
|
+
});
|
|
73
|
+
return { error };
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
package/lib/actions/teams.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export declare function removeUserFromTeam(teamId: string, userId: string): Acti
|
|
|
41
41
|
export declare function sendEmailInvitesToTeam(teamId: string, emails: string[]): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, AnyAction>;
|
|
42
42
|
export declare function sendEmailGuestInvitesToChannels(teamId: string, channelIds: string[], emails: string[], message: string): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, AnyAction>;
|
|
43
43
|
export declare function sendEmailInvitesToTeamGracefully(teamId: string, emails: string[]): ActionFuncAsync<import("@mattermost/types/teams").TeamInviteWithError[], import("@mattermost/types/store").GlobalState, AnyAction>;
|
|
44
|
-
export declare function sendEmailGuestInvitesToChannelsGracefully(teamId: string, channelIds: string[], emails: string[], message: string): ActionFuncAsync<import("@mattermost/types/teams").TeamInviteWithError[], import("@mattermost/types/store").GlobalState, AnyAction>;
|
|
44
|
+
export declare function sendEmailGuestInvitesToChannelsGracefully(teamId: string, channelIds: string[], emails: string[], message: string, guestMagicLink?: boolean): ActionFuncAsync<import("@mattermost/types/teams").TeamInviteWithError[], import("@mattermost/types/store").GlobalState, AnyAction>;
|
|
45
45
|
export declare function sendEmailInvitesToTeamAndChannelsGracefully(teamId: string, channelIds: string[], emails: string[], message: string): ActionFuncAsync<import("@mattermost/types/teams").TeamInviteWithError[], import("@mattermost/types/store").GlobalState, AnyAction>;
|
|
46
46
|
export declare function getTeamInviteInfo(inviteId: string): ActionFuncAsync<{
|
|
47
47
|
display_name: string;
|
package/lib/actions/teams.js
CHANGED
|
@@ -544,7 +544,7 @@ function sendEmailInvitesToTeamGracefully(teamId, emails) {
|
|
|
544
544
|
],
|
|
545
545
|
});
|
|
546
546
|
}
|
|
547
|
-
function sendEmailGuestInvitesToChannelsGracefully(teamId, channelIds, emails, message) {
|
|
547
|
+
function sendEmailGuestInvitesToChannelsGracefully(teamId, channelIds, emails, message, guestMagicLink = false) {
|
|
548
548
|
return (0, helpers_1.bindClientFunc)({
|
|
549
549
|
clientFunc: client_1.Client4.sendEmailGuestInvitesToChannelsGracefully,
|
|
550
550
|
params: [
|
|
@@ -552,6 +552,7 @@ function sendEmailGuestInvitesToChannelsGracefully(teamId, channelIds, emails, m
|
|
|
552
552
|
channelIds,
|
|
553
553
|
emails,
|
|
554
554
|
message,
|
|
555
|
+
guestMagicLink,
|
|
555
556
|
],
|
|
556
557
|
});
|
|
557
558
|
}
|
package/lib/constants/posts.d.ts
CHANGED
|
@@ -27,6 +27,7 @@ export declare const PostTypes: {
|
|
|
27
27
|
REMINDER: PostType;
|
|
28
28
|
WRANGLER: PostType;
|
|
29
29
|
GM_CONVERTED_TO_CHANNEL: PostType;
|
|
30
|
+
BURN_ON_READ: PostType;
|
|
30
31
|
};
|
|
31
32
|
declare const _default: {
|
|
32
33
|
POST_CHUNK_SIZE: number;
|
|
@@ -61,6 +62,7 @@ declare const _default: {
|
|
|
61
62
|
REMINDER: PostType;
|
|
62
63
|
WRANGLER: PostType;
|
|
63
64
|
GM_CONVERTED_TO_CHANNEL: PostType;
|
|
65
|
+
BURN_ON_READ: PostType;
|
|
64
66
|
};
|
|
65
67
|
MESSAGE_TYPES: {
|
|
66
68
|
POST: string;
|
|
@@ -70,5 +72,22 @@ declare const _default: {
|
|
|
70
72
|
POST_COLLAPSE_TIMEOUT: number;
|
|
71
73
|
IGNORE_POST_TYPES: PostType[];
|
|
72
74
|
USER_ACTIVITY_POST_TYPES: PostType[];
|
|
75
|
+
BURN_ON_READ: {
|
|
76
|
+
DURATION_1_MINUTE: number;
|
|
77
|
+
DURATION_5_MINUTES: number;
|
|
78
|
+
DURATION_10_MINUTES: number;
|
|
79
|
+
DURATION_30_MINUTES: number;
|
|
80
|
+
DURATION_1_HOUR: number;
|
|
81
|
+
DURATION_8_HOURS: number;
|
|
82
|
+
DURATION_DEFAULT: number;
|
|
83
|
+
MAX_TTL_2_MINUTES: number;
|
|
84
|
+
MAX_TTL_5_MINUTES: number;
|
|
85
|
+
MAX_TTL_1_DAY: number;
|
|
86
|
+
MAX_TTL_3_DAYS: number;
|
|
87
|
+
MAX_TTL_7_DAYS: number;
|
|
88
|
+
MAX_TTL_14_DAYS: number;
|
|
89
|
+
MAX_TTL_30_DAYS: number;
|
|
90
|
+
MAX_TTL_DEFAULT: number;
|
|
91
|
+
};
|
|
73
92
|
};
|
|
74
93
|
export default _default;
|
package/lib/constants/posts.js
CHANGED
|
@@ -31,6 +31,7 @@ exports.PostTypes = {
|
|
|
31
31
|
REMINDER: 'reminder',
|
|
32
32
|
WRANGLER: 'system_wrangler',
|
|
33
33
|
GM_CONVERTED_TO_CHANNEL: 'system_gm_to_channel',
|
|
34
|
+
BURN_ON_READ: 'burn_on_read',
|
|
34
35
|
};
|
|
35
36
|
exports.default = {
|
|
36
37
|
POST_CHUNK_SIZE: 60,
|
|
@@ -68,4 +69,21 @@ exports.default = {
|
|
|
68
69
|
exports.PostTypes.LEAVE_TEAM,
|
|
69
70
|
exports.PostTypes.REMOVE_FROM_TEAM,
|
|
70
71
|
],
|
|
72
|
+
BURN_ON_READ: {
|
|
73
|
+
DURATION_1_MINUTE: 60,
|
|
74
|
+
DURATION_5_MINUTES: 300,
|
|
75
|
+
DURATION_10_MINUTES: 600,
|
|
76
|
+
DURATION_30_MINUTES: 1800,
|
|
77
|
+
DURATION_1_HOUR: 3600,
|
|
78
|
+
DURATION_8_HOURS: 28800,
|
|
79
|
+
DURATION_DEFAULT: 600,
|
|
80
|
+
MAX_TTL_2_MINUTES: 120,
|
|
81
|
+
MAX_TTL_5_MINUTES: 300,
|
|
82
|
+
MAX_TTL_1_DAY: 86400,
|
|
83
|
+
MAX_TTL_3_DAYS: 259200,
|
|
84
|
+
MAX_TTL_7_DAYS: 604800,
|
|
85
|
+
MAX_TTL_14_DAYS: 1209600,
|
|
86
|
+
MAX_TTL_30_DAYS: 2592000,
|
|
87
|
+
MAX_TTL_DEFAULT: 604800,
|
|
88
|
+
},
|
|
71
89
|
};
|
|
@@ -62,6 +62,8 @@ declare const Preferences: {
|
|
|
62
62
|
HIDE_MYSQL_STATS_NOTIFICATION: string;
|
|
63
63
|
CATEGORY_OVERAGE_USERS_BANNER: string;
|
|
64
64
|
CATEGORY_POST_HISTORY_LIMIT_BANNER: string;
|
|
65
|
+
CATEGORY_BURN_ON_READ: string;
|
|
66
|
+
BURN_ON_READ_SKIP_CONFIRMATION: string;
|
|
65
67
|
CATEGORY_THEME: string;
|
|
66
68
|
THEMES: Record<ThemeKey, Theme>;
|
|
67
69
|
RECENT_EMOJIS: string;
|
|
@@ -66,6 +66,8 @@ const Preferences = {
|
|
|
66
66
|
HIDE_MYSQL_STATS_NOTIFICATION: 'hide_mysql_stats_notifcation',
|
|
67
67
|
CATEGORY_OVERAGE_USERS_BANNER: 'overage_users_banner',
|
|
68
68
|
CATEGORY_POST_HISTORY_LIMIT_BANNER: 'post_history_limit_banner',
|
|
69
|
+
CATEGORY_BURN_ON_READ: 'burn_on_read',
|
|
70
|
+
BURN_ON_READ_SKIP_CONFIRMATION: 'skip_delete_confirmation',
|
|
69
71
|
CATEGORY_THEME: 'theme',
|
|
70
72
|
THEMES: {
|
|
71
73
|
denim: {
|
|
@@ -49,5 +49,8 @@ declare const WebsocketEvents: {
|
|
|
49
49
|
THREAD_READ_CHANGED: string;
|
|
50
50
|
FIRST_ADMIN_VISIT_MARKETPLACE_STATUS_RECEIVED: string;
|
|
51
51
|
GROUP_MEMBER_DELETED: string;
|
|
52
|
+
BURN_ON_READ_POST_REVEALED: string;
|
|
53
|
+
BURN_ON_READ_POST_BURNED: string;
|
|
54
|
+
BURN_ON_READ_ALL_REVEALED: string;
|
|
52
55
|
};
|
|
53
56
|
export default WebsocketEvents;
|
|
@@ -53,5 +53,8 @@ const WebsocketEvents = {
|
|
|
53
53
|
THREAD_READ_CHANGED: 'thread_read_changed',
|
|
54
54
|
FIRST_ADMIN_VISIT_MARKETPLACE_STATUS_RECEIVED: 'first_admin_visit_marketplace_status_received',
|
|
55
55
|
GROUP_MEMBER_DELETED: 'group_member_deleted',
|
|
56
|
+
BURN_ON_READ_POST_REVEALED: 'post_revealed',
|
|
57
|
+
BURN_ON_READ_POST_BURNED: 'post_burned',
|
|
58
|
+
BURN_ON_READ_ALL_REVEALED: 'burn_on_read_all_revealed',
|
|
56
59
|
};
|
|
57
60
|
exports.default = WebsocketEvents;
|
|
@@ -98,6 +98,7 @@ declare const _default: import("redux").Reducer<{
|
|
|
98
98
|
[key: string]: import("@mattermost/types/preferences").PreferencesType;
|
|
99
99
|
};
|
|
100
100
|
};
|
|
101
|
+
recaps: import("./recaps").RecapsState;
|
|
101
102
|
typing: import("@mattermost/types/typing").Typing;
|
|
102
103
|
integrations: {
|
|
103
104
|
incomingHooks: import("@mattermost/types/utilities").IDMappedObjects<import("@mattermost/types/integrations").IncomingWebhook>;
|
|
@@ -470,6 +471,7 @@ declare const _default: import("redux").Reducer<{
|
|
|
470
471
|
myPreferences: Record<string, import("@mattermost/types/preferences").PreferenceType> | undefined;
|
|
471
472
|
userPreferences: Record<string, import("@mattermost/types/preferences").PreferencesType> | undefined;
|
|
472
473
|
}> | undefined;
|
|
474
|
+
recaps: import("./recaps").RecapsState | undefined;
|
|
473
475
|
typing: import("@mattermost/types/typing").Typing | undefined;
|
|
474
476
|
integrations: {
|
|
475
477
|
incomingHooks: import("@mattermost/types/utilities").IDMappedObjects<import("@mattermost/types/integrations").IncomingWebhook>;
|
|
@@ -25,6 +25,7 @@ const jobs_1 = __importDefault(require("./jobs"));
|
|
|
25
25
|
const limits_1 = __importDefault(require("./limits"));
|
|
26
26
|
const posts_1 = __importDefault(require("./posts"));
|
|
27
27
|
const preferences_1 = __importDefault(require("./preferences"));
|
|
28
|
+
const recaps_1 = __importDefault(require("./recaps"));
|
|
28
29
|
const roles_1 = __importDefault(require("./roles"));
|
|
29
30
|
const scheduled_posts_1 = __importDefault(require("./scheduled_posts"));
|
|
30
31
|
const schemes_1 = __importDefault(require("./schemes"));
|
|
@@ -45,6 +46,7 @@ exports.default = (0, redux_1.combineReducers)({
|
|
|
45
46
|
posts: posts_1.default,
|
|
46
47
|
files: files_1.default,
|
|
47
48
|
preferences: preferences_1.default,
|
|
49
|
+
recaps: recaps_1.default,
|
|
48
50
|
typing: typing_1.default,
|
|
49
51
|
integrations: integrations_1.default,
|
|
50
52
|
emojis: emojis_1.default,
|
|
@@ -20,6 +20,7 @@ exports.limitedViews = limitedViews;
|
|
|
20
20
|
exports.default = reducer;
|
|
21
21
|
const action_types_1 = require("mattermost-redux/action_types");
|
|
22
22
|
const constants_1 = require("mattermost-redux/constants");
|
|
23
|
+
const posts_1 = require("mattermost-redux/constants/posts");
|
|
23
24
|
const post_utils_1 = require("mattermost-redux/utils/post_utils");
|
|
24
25
|
function removeUnneededMetadata(post) {
|
|
25
26
|
if (!post.metadata) {
|
|
@@ -129,6 +130,46 @@ function nextPostsReplies(state = {}, action) {
|
|
|
129
130
|
return state;
|
|
130
131
|
}
|
|
131
132
|
}
|
|
133
|
+
// Helper function to remove posts and permalink embeds for a set of channel IDs.
|
|
134
|
+
function removePostsAndEmbedsForChannels(state, channelIds) {
|
|
135
|
+
let postModified = false;
|
|
136
|
+
const nextState = { ...state };
|
|
137
|
+
for (const post of Object.values(state)) {
|
|
138
|
+
// Remove posts from the channels
|
|
139
|
+
if (channelIds.has(post.channel_id)) {
|
|
140
|
+
Reflect.deleteProperty(nextState, post.id);
|
|
141
|
+
postModified = true;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
// Remove permalink embeds referencing those channels (matches server behavior)
|
|
145
|
+
if (post.metadata?.embeds?.length) {
|
|
146
|
+
const newEmbeds = [];
|
|
147
|
+
let embedRemoved = false;
|
|
148
|
+
for (const embed of post.metadata.embeds) {
|
|
149
|
+
if (embed.type === 'permalink' && embed.data && channelIds.has(embed.data.channel_id)) {
|
|
150
|
+
embedRemoved = true;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
newEmbeds.push(embed);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (embedRemoved) {
|
|
157
|
+
nextState[post.id] = {
|
|
158
|
+
...nextState[post.id],
|
|
159
|
+
metadata: {
|
|
160
|
+
...nextState[post.id].metadata,
|
|
161
|
+
embeds: newEmbeds,
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
postModified = true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (!postModified) {
|
|
169
|
+
return state;
|
|
170
|
+
}
|
|
171
|
+
return nextState;
|
|
172
|
+
}
|
|
132
173
|
function handlePosts(state = {}, action) {
|
|
133
174
|
switch (action.type) {
|
|
134
175
|
case action_types_1.PostTypes.RECEIVED_POST:
|
|
@@ -151,6 +192,11 @@ function handlePosts(state = {}, action) {
|
|
|
151
192
|
if (!state[post.id]) {
|
|
152
193
|
return state;
|
|
153
194
|
}
|
|
195
|
+
if (state[post.id].type === posts_1.PostTypes.BURN_ON_READ) {
|
|
196
|
+
const nextState = { ...state };
|
|
197
|
+
Reflect.deleteProperty(nextState, post.id);
|
|
198
|
+
return nextState;
|
|
199
|
+
}
|
|
154
200
|
// Mark the post as deleted
|
|
155
201
|
const nextState = {
|
|
156
202
|
...state,
|
|
@@ -229,22 +275,78 @@ function handlePosts(state = {}, action) {
|
|
|
229
275
|
},
|
|
230
276
|
};
|
|
231
277
|
}
|
|
278
|
+
case action_types_1.PostTypes.REVEAL_BURN_ON_READ_SUCCESS: {
|
|
279
|
+
const { post, expireAt } = action.data;
|
|
280
|
+
if (!state[post.id]) {
|
|
281
|
+
return state;
|
|
282
|
+
}
|
|
283
|
+
const currentPost = state[post.id];
|
|
284
|
+
const currentMetadata = currentPost.metadata || {};
|
|
285
|
+
const newMetadata = post.metadata || {};
|
|
286
|
+
return {
|
|
287
|
+
...state,
|
|
288
|
+
[post.id]: {
|
|
289
|
+
...currentPost,
|
|
290
|
+
...post,
|
|
291
|
+
metadata: {
|
|
292
|
+
...currentMetadata,
|
|
293
|
+
...newMetadata,
|
|
294
|
+
expire_at: expireAt,
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
case action_types_1.PostTypes.POST_RECIPIENTS_UPDATED: {
|
|
300
|
+
const { postId, recipients } = action.data;
|
|
301
|
+
if (!state[postId]) {
|
|
302
|
+
return state;
|
|
303
|
+
}
|
|
304
|
+
const currentPost = state[postId];
|
|
305
|
+
const currentMetadata = currentPost.metadata || {};
|
|
306
|
+
const currentRecipients = currentMetadata.recipients || [];
|
|
307
|
+
// Merge new recipients with existing ones (don't replace).
|
|
308
|
+
// Server sends incremental updates (only the revealing user), so we must merge.
|
|
309
|
+
const mergedRecipients = [...new Set([...currentRecipients, ...recipients])];
|
|
310
|
+
return {
|
|
311
|
+
...state,
|
|
312
|
+
[postId]: {
|
|
313
|
+
...currentPost,
|
|
314
|
+
metadata: {
|
|
315
|
+
...currentMetadata,
|
|
316
|
+
recipients: mergedRecipients,
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
case action_types_1.PostTypes.BURN_ON_READ_ALL_REVEALED: {
|
|
322
|
+
const { postId, senderExpireAt } = action.data;
|
|
323
|
+
if (!state[postId]) {
|
|
324
|
+
return state;
|
|
325
|
+
}
|
|
326
|
+
const currentPost = state[postId];
|
|
327
|
+
const currentMetadata = currentPost.metadata || {};
|
|
328
|
+
// Set sender's expiration time to trigger timer display
|
|
329
|
+
return {
|
|
330
|
+
...state,
|
|
331
|
+
[postId]: {
|
|
332
|
+
...currentPost,
|
|
333
|
+
metadata: {
|
|
334
|
+
...currentMetadata,
|
|
335
|
+
expire_at: senderExpireAt,
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
}
|
|
232
340
|
case action_types_1.ChannelTypes.LEAVE_CHANNEL: {
|
|
233
341
|
const channelId = action.data.id;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
Reflect.deleteProperty(nextState, post.id);
|
|
240
|
-
postDeleted = true;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
if (!postDeleted) {
|
|
244
|
-
// Nothing changed
|
|
342
|
+
return removePostsAndEmbedsForChannels(state, new Set([channelId]));
|
|
343
|
+
}
|
|
344
|
+
case action_types_1.TeamTypes.LEAVE_TEAM: {
|
|
345
|
+
const channelIds = action.data.channelIds || [];
|
|
346
|
+
if (channelIds.length === 0) {
|
|
245
347
|
return state;
|
|
246
348
|
}
|
|
247
|
-
return
|
|
349
|
+
return removePostsAndEmbedsForChannels(state, new Set(channelIds));
|
|
248
350
|
}
|
|
249
351
|
case action_types_1.ThreadTypes.FOLLOW_CHANGED_THREAD: {
|
|
250
352
|
const { id, following } = action.data;
|
|
@@ -605,17 +707,24 @@ function postsInChannel(state = {}, action, prevPosts, nextPosts) {
|
|
|
605
707
|
}
|
|
606
708
|
case action_types_1.PostTypes.POST_DELETED: {
|
|
607
709
|
const post = action.data;
|
|
608
|
-
// Deleting a post removes its comments from the order, but does not remove the post itself
|
|
609
710
|
const postsForChannel = state[post.channel_id] || [];
|
|
610
711
|
if (postsForChannel.length === 0) {
|
|
611
712
|
return state;
|
|
612
713
|
}
|
|
613
714
|
let changed = false;
|
|
614
715
|
let nextPostsForChannel = [...postsForChannel];
|
|
716
|
+
const isBoRPost = prevPosts[post.id]?.type === posts_1.PostTypes.BURN_ON_READ;
|
|
717
|
+
const shouldRemovePost = (postId) => {
|
|
718
|
+
const isTheDeletedPost = postId === post.id;
|
|
719
|
+
const isReplyToDeletedPost = prevPosts[postId]?.root_id === post.id;
|
|
720
|
+
if (isBoRPost) {
|
|
721
|
+
return isTheDeletedPost;
|
|
722
|
+
}
|
|
723
|
+
return isReplyToDeletedPost;
|
|
724
|
+
};
|
|
615
725
|
for (let i = 0; i < nextPostsForChannel.length; i++) {
|
|
616
726
|
const block = nextPostsForChannel[i];
|
|
617
|
-
|
|
618
|
-
const nextOrder = block.order.filter((postId) => prevPosts[postId].root_id !== post.id);
|
|
727
|
+
const nextOrder = block.order.filter((postId) => !shouldRemovePost(postId));
|
|
619
728
|
if (nextOrder.length !== block.order.length) {
|
|
620
729
|
nextPostsForChannel[i] = {
|
|
621
730
|
...block,
|
|
@@ -642,11 +751,16 @@ function postsInChannel(state = {}, action, prevPosts, nextPosts) {
|
|
|
642
751
|
return state;
|
|
643
752
|
}
|
|
644
753
|
let changed = false;
|
|
754
|
+
const isBoRPost = prevPosts[post.id]?.type === posts_1.PostTypes.BURN_ON_READ;
|
|
645
755
|
// Remove the post and its comments from the channel
|
|
646
756
|
let nextPostsForChannel = [...postsForChannel];
|
|
647
757
|
for (let i = 0; i < nextPostsForChannel.length; i++) {
|
|
648
758
|
const block = nextPostsForChannel[i];
|
|
649
|
-
|
|
759
|
+
// For BoR posts: only remove the post itself (BoR doesn't support threads)
|
|
760
|
+
// For regular posts: remove the post and its thread replies
|
|
761
|
+
const nextOrder = isBoRPost ?
|
|
762
|
+
block.order.filter((postId) => postId !== post.id) :
|
|
763
|
+
block.order.filter((postId) => postId !== post.id && prevPosts[postId]?.root_id !== post.id);
|
|
650
764
|
if (nextOrder.length !== block.order.length) {
|
|
651
765
|
nextPostsForChannel[i] = {
|
|
652
766
|
...block,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Recap } from '@mattermost/types/recaps';
|
|
2
|
+
import type { MMReduxAction } from 'mattermost-redux/action_types';
|
|
3
|
+
export type RecapsState = {
|
|
4
|
+
byId: Record<string, Recap>;
|
|
5
|
+
allIds: string[];
|
|
6
|
+
};
|
|
7
|
+
export default function recapsReducer(state: RecapsState | undefined, action: MMReduxAction): RecapsState;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.default = recapsReducer;
|
|
6
|
+
const action_types_1 = require("mattermost-redux/action_types");
|
|
7
|
+
const initialState = {
|
|
8
|
+
byId: {},
|
|
9
|
+
allIds: [],
|
|
10
|
+
};
|
|
11
|
+
function recapsReducer(state = initialState, action) {
|
|
12
|
+
switch (action.type) {
|
|
13
|
+
case action_types_1.RecapTypes.RECEIVED_RECAP: {
|
|
14
|
+
const recap = action.data;
|
|
15
|
+
const nextState = { ...state };
|
|
16
|
+
nextState.byId = {
|
|
17
|
+
...state.byId,
|
|
18
|
+
[recap.id]: recap,
|
|
19
|
+
};
|
|
20
|
+
if (!state.allIds.includes(recap.id)) {
|
|
21
|
+
nextState.allIds = [...state.allIds, recap.id];
|
|
22
|
+
}
|
|
23
|
+
return nextState;
|
|
24
|
+
}
|
|
25
|
+
case action_types_1.RecapTypes.RECEIVED_RECAPS: {
|
|
26
|
+
const recaps = action.data;
|
|
27
|
+
const nextState = { ...state };
|
|
28
|
+
const newById = { ...state.byId };
|
|
29
|
+
const newAllIds = new Set(state.allIds);
|
|
30
|
+
recaps.forEach((recap) => {
|
|
31
|
+
newById[recap.id] = recap;
|
|
32
|
+
newAllIds.add(recap.id);
|
|
33
|
+
});
|
|
34
|
+
nextState.byId = newById;
|
|
35
|
+
nextState.allIds = Array.from(newAllIds);
|
|
36
|
+
return nextState;
|
|
37
|
+
}
|
|
38
|
+
case action_types_1.RecapTypes.DELETE_RECAP_SUCCESS: {
|
|
39
|
+
const { recapId } = action.data;
|
|
40
|
+
const nextState = { ...state };
|
|
41
|
+
const newById = { ...state.byId };
|
|
42
|
+
delete newById[recapId];
|
|
43
|
+
nextState.byId = newById;
|
|
44
|
+
nextState.allIds = state.allIds.filter((id) => id !== recapId);
|
|
45
|
+
return nextState;
|
|
46
|
+
}
|
|
47
|
+
case action_types_1.UserTypes.LOGOUT_SUCCESS:
|
|
48
|
+
return initialState;
|
|
49
|
+
default:
|
|
50
|
+
return state;
|
|
51
|
+
}
|
|
52
|
+
}
|
package/lib/reducers/index.d.ts
CHANGED
|
@@ -100,6 +100,7 @@ declare const _default: {
|
|
|
100
100
|
[key: string]: import("@mattermost/types/preferences").PreferencesType;
|
|
101
101
|
};
|
|
102
102
|
};
|
|
103
|
+
recaps: import("./entities/recaps").RecapsState;
|
|
103
104
|
typing: import("@mattermost/types/typing").Typing;
|
|
104
105
|
integrations: {
|
|
105
106
|
incomingHooks: import("@mattermost/types/utilities").IDMappedObjects<import("@mattermost/types/integrations").IncomingWebhook>;
|
|
@@ -472,6 +473,7 @@ declare const _default: {
|
|
|
472
473
|
myPreferences: Record<string, import("@mattermost/types/preferences").PreferenceType> | undefined;
|
|
473
474
|
userPreferences: Record<string, import("@mattermost/types/preferences").PreferencesType> | undefined;
|
|
474
475
|
}> | undefined;
|
|
476
|
+
recaps: import("./entities/recaps").RecapsState | undefined;
|
|
475
477
|
typing: import("@mattermost/types/typing").Typing | undefined;
|
|
476
478
|
integrations: {
|
|
477
479
|
incomingHooks: import("@mattermost/types/utilities").IDMappedObjects<import("@mattermost/types/integrations").IncomingWebhook>;
|
|
@@ -2,21 +2,11 @@
|
|
|
2
2
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
3
|
// See LICENSE.txt for license information.
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.selectShowChannelBanner =
|
|
5
|
+
exports.selectShowChannelBanner = void 0;
|
|
6
6
|
const channels_1 = require("@mattermost/types/channels");
|
|
7
7
|
const constants_1 = require("mattermost-redux/constants");
|
|
8
8
|
const channels_2 = require("mattermost-redux/selectors/entities/channels");
|
|
9
|
-
const general_1 = require("mattermost-redux/selectors/entities/general");
|
|
10
|
-
const selectChannelBannerEnabled = (state) => {
|
|
11
|
-
const license = (0, general_1.getLicense)(state);
|
|
12
|
-
return license?.SkuShortName === constants_1.General.SKUEnterpriseAdvanced;
|
|
13
|
-
};
|
|
14
|
-
exports.selectChannelBannerEnabled = selectChannelBannerEnabled;
|
|
15
9
|
const selectShowChannelBanner = (state, channelId) => {
|
|
16
|
-
const enabled = (0, exports.selectChannelBannerEnabled)(state);
|
|
17
|
-
if (!enabled) {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
10
|
const channelBannerInfo = (0, channels_2.getChannelBanner)(state, channelId);
|
|
21
11
|
const channel = (0, channels_2.getChannel)(state, channelId);
|
|
22
12
|
const isValidChannelType = Boolean(channel && (channel.type === constants_1.General.OPEN_CHANNEL || channel.type === constants_1.General.PRIVATE_CHANNEL));
|
|
@@ -132,7 +132,8 @@ function isPostInteractable(post) {
|
|
|
132
132
|
!(0, post_utils_1.isPostEphemeral)(post) &&
|
|
133
133
|
!(0, post_utils_1.isSystemMessage)(post) &&
|
|
134
134
|
!(0, post_utils_1.isPostPendingOrFailed)(post) &&
|
|
135
|
-
post.state !== constants_1.Posts.POST_DELETED
|
|
135
|
+
post.state !== constants_1.Posts.POST_DELETED &&
|
|
136
|
+
post.type !== constants_1.Posts.POST_TYPES.BURN_ON_READ;
|
|
136
137
|
}
|
|
137
138
|
function getLatestInteractablePostId(state, channelId, rootId = '') {
|
|
138
139
|
const postsIds = rootId ? getPostsInThreadOrdered(state, rootId) : getPostIdsInChannel(state, channelId);
|
|
@@ -398,7 +399,13 @@ function getUnreadPostsChunk(state, channelId, timeStamp) {
|
|
|
398
399
|
return oldestPostsChunk;
|
|
399
400
|
}
|
|
400
401
|
}
|
|
401
|
-
|
|
402
|
+
// Try to find a chunk where lastViewedAt falls within the post range
|
|
403
|
+
const chunkAroundTime = getPostsChunkInChannelAroundTime(state, channelId, timeStamp);
|
|
404
|
+
if (chunkAroundTime) {
|
|
405
|
+
return chunkAroundTime;
|
|
406
|
+
}
|
|
407
|
+
// All fetched posts are newer than lastViewedAt. Return the recent chunk.
|
|
408
|
+
return recentChunk;
|
|
402
409
|
}
|
|
403
410
|
const isPostsChunkIncludingUnreadsPosts = (state, chunk, timeStamp) => {
|
|
404
411
|
const postsEntity = state.entities.posts;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Recap } from '@mattermost/types/recaps';
|
|
2
|
+
import { RecapStatus } from '@mattermost/types/recaps';
|
|
3
|
+
import type { GlobalState } from '@mattermost/types/store';
|
|
4
|
+
export declare function getAllRecaps(state: GlobalState): Recap[];
|
|
5
|
+
export declare function getRecap(state: GlobalState, recapId: string): Recap | undefined;
|
|
6
|
+
export declare const getRecapsByStatus: import("mattermost-redux/selectors/create_selector").OutputParametricSelector<GlobalState, RecapStatus, Recap[], (res1: Recap[], res2: RecapStatus) => Recap[]>;
|
|
7
|
+
export declare const getSortedRecaps: import("mattermost-redux/selectors/create_selector").OutputSelector<GlobalState, Recap[], (res: Recap[]) => Recap[]>;
|
|
8
|
+
export declare const getCompletedRecaps: import("mattermost-redux/selectors/create_selector").OutputSelector<GlobalState, Recap[], (res: Recap[]) => Recap[]>;
|
|
9
|
+
export declare const getPendingRecaps: import("mattermost-redux/selectors/create_selector").OutputSelector<GlobalState, Recap[], (res: Recap[]) => Recap[]>;
|
|
10
|
+
export declare const getUnreadRecaps: import("mattermost-redux/selectors/create_selector").OutputSelector<GlobalState, Recap[], (res: Recap[]) => Recap[]>;
|
|
11
|
+
export declare const getReadRecaps: import("mattermost-redux/selectors/create_selector").OutputSelector<GlobalState, Recap[], (res: Recap[]) => Recap[]>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
3
|
+
// See LICENSE.txt for license information.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.getReadRecaps = exports.getUnreadRecaps = exports.getPendingRecaps = exports.getCompletedRecaps = exports.getSortedRecaps = exports.getRecapsByStatus = void 0;
|
|
6
|
+
exports.getAllRecaps = getAllRecaps;
|
|
7
|
+
exports.getRecap = getRecap;
|
|
8
|
+
const recaps_1 = require("@mattermost/types/recaps");
|
|
9
|
+
const create_selector_1 = require("mattermost-redux/selectors/create_selector");
|
|
10
|
+
function getAllRecaps(state) {
|
|
11
|
+
const { byId, allIds } = state.entities.recaps;
|
|
12
|
+
return allIds.map((id) => byId[id]);
|
|
13
|
+
}
|
|
14
|
+
function getRecap(state, recapId) {
|
|
15
|
+
return state.entities.recaps.byId[recapId] || undefined;
|
|
16
|
+
}
|
|
17
|
+
exports.getRecapsByStatus = (0, create_selector_1.createSelector)('getRecapsByStatus', getAllRecaps, (_state, status) => status, (recaps, status) => {
|
|
18
|
+
return recaps.filter((recap) => recap.status === status);
|
|
19
|
+
});
|
|
20
|
+
exports.getSortedRecaps = (0, create_selector_1.createSelector)('getSortedRecaps', getAllRecaps, (recaps) => {
|
|
21
|
+
return [...recaps].sort((a, b) => b.create_at - a.create_at);
|
|
22
|
+
});
|
|
23
|
+
exports.getCompletedRecaps = (0, create_selector_1.createSelector)('getCompletedRecaps', getAllRecaps, (recaps) => {
|
|
24
|
+
return recaps.filter((recap) => recap.status === recaps_1.RecapStatus.COMPLETED).sort((a, b) => b.create_at - a.create_at);
|
|
25
|
+
});
|
|
26
|
+
exports.getPendingRecaps = (0, create_selector_1.createSelector)('getPendingRecaps', getAllRecaps, (recaps) => {
|
|
27
|
+
return recaps.filter((recap) => recap.status === recaps_1.RecapStatus.PENDING || recap.status === recaps_1.RecapStatus.PROCESSING);
|
|
28
|
+
});
|
|
29
|
+
exports.getUnreadRecaps = (0, create_selector_1.createSelector)('getUnreadRecaps', getAllRecaps, (recaps) => {
|
|
30
|
+
return recaps.filter((recap) => recap.read_at === 0).sort((a, b) => b.create_at - a.create_at);
|
|
31
|
+
});
|
|
32
|
+
exports.getReadRecaps = (0, create_selector_1.createSelector)('getReadRecaps', getAllRecaps, (recaps) => {
|
|
33
|
+
return recaps.filter((recap) => recap.read_at > 0).sort((a, b) => b.read_at - a.read_at);
|
|
34
|
+
});
|
|
@@ -60,8 +60,9 @@ function checkDialogElementForError(elem, value) {
|
|
|
60
60
|
if (value && value.length < elem.min_length) {
|
|
61
61
|
return (0, react_intl_1.defineMessage)({
|
|
62
62
|
id: 'interactive_dialog.error.too_short',
|
|
63
|
+
// minLength provided by InteractiveDialog
|
|
64
|
+
// eslint-disable-next-line formatjs/enforce-placeholders
|
|
63
65
|
defaultMessage: 'Minimum input length is {minLength}.',
|
|
64
|
-
values: { minLength: elem.min_length },
|
|
65
66
|
});
|
|
66
67
|
}
|
|
67
68
|
if (elem.subtype === 'email') {
|
package/lib/utils/post_list.js
CHANGED
|
@@ -73,6 +73,16 @@ function makeFilterPostsAndAddSeparators() {
|
|
|
73
73
|
if ((0, post_utils_1.shouldFilterJoinLeavePost)(post, showJoinLeave, currentUser.username)) {
|
|
74
74
|
continue;
|
|
75
75
|
}
|
|
76
|
+
// Filter out expired burn-on-read posts
|
|
77
|
+
// Note: BoR posts should display regardless of feature flag being enabled/disabled
|
|
78
|
+
// The feature flag only controls creation of NEW BoR messages, not display of existing ones
|
|
79
|
+
if (post.type === constants_1.Posts.POST_TYPES.BURN_ON_READ) {
|
|
80
|
+
// Skip if already expired and deleted
|
|
81
|
+
const expireAt = post.metadata?.expire_at;
|
|
82
|
+
if (expireAt && typeof expireAt === 'number' && expireAt <= Date.now()) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
76
86
|
lastDate = pushPostDateIfNeeded(post, currentUser, out, lastDate);
|
|
77
87
|
if (lastViewedAt &&
|
|
78
88
|
post.create_at > lastViewedAt &&
|
package/lib/utils/post_utils.js
CHANGED
|
@@ -62,6 +62,9 @@ function canEditPost(state, config, license, teamId, channelId, userId, post) {
|
|
|
62
62
|
if (!post || isSystemMessage(post)) {
|
|
63
63
|
return false;
|
|
64
64
|
}
|
|
65
|
+
if (post.type === constants_1.Posts.POST_TYPES.BURN_ON_READ) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
65
68
|
const isOwner = isPostOwner(userId, post);
|
|
66
69
|
let canEdit = true;
|
|
67
70
|
const permission = isOwner ? constants_1.Permissions.EDIT_POST : constants_1.Permissions.EDIT_OTHERS_POSTS;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mattermost-redux",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.4.0",
|
|
4
4
|
"description": "Common code (API client, Redux stores, logic, utility functions) for building a Mattermost client",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mattermost"
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"directory": "webapp/platform/mattermost-redux"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@mattermost/client": "11.
|
|
43
|
-
"@mattermost/types": "11.
|
|
42
|
+
"@mattermost/client": "11.4.0",
|
|
43
|
+
"@mattermost/types": "11.4.0",
|
|
44
44
|
"@redux-devtools/extension": "3.3.0",
|
|
45
45
|
"lodash": "^4.17.21",
|
|
46
46
|
"moment-timezone": "^0.5.38",
|