mattermost-redux 10.11.0 → 11.0.4
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/content_flagging.d.ts +4 -0
- package/lib/action_types/content_flagging.js +11 -0
- package/lib/action_types/index.d.ts +2 -1
- package/lib/action_types/index.js +3 -1
- package/lib/action_types/limits.d.ts +1 -1
- package/lib/action_types/limits.js +1 -1
- package/lib/action_types/search.d.ts +1 -0
- package/lib/action_types/search.js +1 -0
- package/lib/action_types/teams.d.ts +1 -0
- package/lib/action_types/teams.js +1 -0
- package/lib/action_types/users.d.ts +1 -1
- package/lib/action_types/users.js +1 -1
- package/lib/actions/access_control.d.ts +10 -4
- package/lib/actions/access_control.js +36 -6
- package/lib/actions/channels.d.ts +1 -1
- package/lib/actions/channels.js +4 -33
- package/lib/actions/content_flagging.d.ts +6 -0
- package/lib/actions/content_flagging.js +49 -0
- package/lib/actions/general.js +1 -1
- package/lib/actions/integrations.d.ts +6 -0
- package/lib/actions/integrations.js +19 -0
- package/lib/actions/jobs.d.ts +3 -1
- package/lib/actions/limits.js +6 -13
- package/lib/actions/posts.js +0 -2
- package/lib/actions/search.js +31 -0
- package/lib/actions/users.js +0 -3
- package/lib/constants/apps.js +1 -0
- package/lib/constants/permissions.d.ts +1 -0
- package/lib/constants/permissions.js +1 -0
- package/lib/constants/preferences.d.ts +1 -1
- package/lib/constants/preferences.js +1 -1
- package/lib/reducers/entities/content_flagging.d.ts +4 -0
- package/lib/reducers/entities/content_flagging.js +21 -0
- package/lib/reducers/entities/index.d.ts +8 -0
- package/lib/reducers/entities/index.js +2 -0
- package/lib/reducers/entities/limits.js +1 -1
- package/lib/reducers/entities/posts.js +10 -25
- package/lib/reducers/entities/search.d.ts +4 -0
- package/lib/reducers/entities/search.js +27 -0
- package/lib/reducers/entities/teams.d.ts +1 -0
- package/lib/reducers/entities/teams.js +13 -0
- package/lib/reducers/entities/threads/index.js +2 -5
- package/lib/reducers/index.d.ts +8 -0
- package/lib/selectors/entities/access_control.d.ts +1 -0
- package/lib/selectors/entities/access_control.js +18 -1
- package/lib/selectors/entities/channels.js +4 -1
- package/lib/selectors/entities/content_flagging.d.ts +3 -0
- package/lib/selectors/entities/content_flagging.js +14 -0
- package/lib/selectors/entities/interactive_dialog.d.ts +3 -0
- package/lib/selectors/entities/interactive_dialog.js +10 -0
- package/lib/selectors/entities/limits.d.ts +3 -0
- package/lib/selectors/entities/limits.js +15 -0
- package/lib/selectors/entities/posts.js +2 -1
- package/lib/selectors/entities/preferences.d.ts +1 -0
- package/lib/selectors/entities/preferences.js +2 -1
- package/lib/selectors/entities/search.d.ts +5 -0
- package/lib/selectors/entities/search.js +10 -1
- package/lib/selectors/entities/teams.d.ts +1 -0
- package/lib/selectors/entities/teams.js +9 -0
- package/lib/store/initial_state.js +2 -0
- package/lib/utils/integration_utils.js +12 -1
- package/lib/utils/post_list.d.ts +3 -1
- package/lib/utils/post_list.js +34 -15
- package/lib/utils/theme_utils.js +1 -1
- package/lib/utils/user_utils.d.ts +1 -1
- package/lib/utils/user_utils.js +14 -5
- package/package.json +3 -3
- package/lib/constants/telemetry.d.ts +0 -21
- package/lib/constants/telemetry.js +0 -36
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
RECEIVED_CONTENT_FLAGGING_CONFIG: null,
|
|
11
|
+
});
|
|
@@ -6,6 +6,7 @@ import ChannelBookmarkTypes from './channel_bookmarks';
|
|
|
6
6
|
import ChannelCategoryTypes from './channel_categories';
|
|
7
7
|
import ChannelTypes from './channels';
|
|
8
8
|
import CloudTypes from './cloud';
|
|
9
|
+
import ContentFlaggingTypes from './content_flagging';
|
|
9
10
|
import DraftTypes from './drafts';
|
|
10
11
|
import EmojiTypes from './emojis';
|
|
11
12
|
import ErrorTypes from './errors';
|
|
@@ -28,7 +29,7 @@ import SharedChannelTypes from './shared_channels';
|
|
|
28
29
|
import TeamTypes from './teams';
|
|
29
30
|
import ThreadTypes from './threads';
|
|
30
31
|
import UserTypes from './users';
|
|
31
|
-
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, };
|
|
32
|
+
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, };
|
|
32
33
|
/**
|
|
33
34
|
* An MMReduxAction is any non-Thunk Redux action accepted by mattermost-redux.
|
|
34
35
|
*/
|
|
@@ -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.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.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;
|
|
9
9
|
const admin_1 = __importDefault(require("./admin"));
|
|
10
10
|
exports.AdminTypes = admin_1.default;
|
|
11
11
|
const apps_1 = __importDefault(require("./apps"));
|
|
@@ -20,6 +20,8 @@ const channels_1 = __importDefault(require("./channels"));
|
|
|
20
20
|
exports.ChannelTypes = channels_1.default;
|
|
21
21
|
const cloud_1 = __importDefault(require("./cloud"));
|
|
22
22
|
exports.CloudTypes = cloud_1.default;
|
|
23
|
+
const content_flagging_1 = __importDefault(require("./content_flagging"));
|
|
24
|
+
exports.ContentFlaggingTypes = content_flagging_1.default;
|
|
23
25
|
const drafts_1 = __importDefault(require("./drafts"));
|
|
24
26
|
exports.DraftTypes = drafts_1.default;
|
|
25
27
|
const emojis_1 = __importDefault(require("./emojis"));
|
|
@@ -7,5 +7,5 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
const key_mirror_1 = __importDefault(require("mattermost-redux/utils/key_mirror"));
|
|
9
9
|
exports.default = (0, key_mirror_1.default)({
|
|
10
|
-
|
|
10
|
+
RECEIVED_APP_LIMITS: null,
|
|
11
11
|
});
|
|
@@ -14,6 +14,7 @@ declare const _default: {
|
|
|
14
14
|
RECEIVED_SEARCH_FLAGGED_POSTS: "RECEIVED_SEARCH_FLAGGED_POSTS";
|
|
15
15
|
RECEIVED_SEARCH_PINNED_POSTS: "RECEIVED_SEARCH_PINNED_POSTS";
|
|
16
16
|
RECEIVED_SEARCH_TERM: "RECEIVED_SEARCH_TERM";
|
|
17
|
+
RECEIVED_SEARCH_TRUNCATION_INFO: "RECEIVED_SEARCH_TRUNCATION_INFO";
|
|
17
18
|
REMOVE_SEARCH_POSTS: "REMOVE_SEARCH_POSTS";
|
|
18
19
|
REMOVE_SEARCH_FILES: "REMOVE_SEARCH_FILES";
|
|
19
20
|
};
|
|
@@ -22,6 +22,7 @@ exports.default = (0, key_mirror_1.default)({
|
|
|
22
22
|
RECEIVED_SEARCH_FLAGGED_POSTS: null,
|
|
23
23
|
RECEIVED_SEARCH_PINNED_POSTS: null,
|
|
24
24
|
RECEIVED_SEARCH_TERM: null,
|
|
25
|
+
RECEIVED_SEARCH_TRUNCATION_INFO: null,
|
|
25
26
|
REMOVE_SEARCH_POSTS: null,
|
|
26
27
|
REMOVE_SEARCH_FILES: null,
|
|
27
28
|
});
|
|
@@ -37,5 +37,6 @@ declare const _default: {
|
|
|
37
37
|
UPDATED_TEAM_MEMBER_SCHEME_ROLES: "UPDATED_TEAM_MEMBER_SCHEME_ROLES";
|
|
38
38
|
RECEIVED_TEAM_MEMBERS_MINUS_GROUP_MEMBERS: "RECEIVED_TEAM_MEMBERS_MINUS_GROUP_MEMBERS";
|
|
39
39
|
RECEIVED_TOTAL_TEAM_COUNT: "RECEIVED_TOTAL_TEAM_COUNT";
|
|
40
|
+
RECEIVED_CONTENT_FLAGGING_STATUS: "RECEIVED_CONTENT_FLAGGING_STATUS";
|
|
40
41
|
};
|
|
41
42
|
export default _default;
|
|
@@ -57,7 +57,7 @@ declare const _default: {
|
|
|
57
57
|
DISABLED_USER_ACCESS_TOKEN: "DISABLED_USER_ACCESS_TOKEN";
|
|
58
58
|
ENABLED_USER_ACCESS_TOKEN: "ENABLED_USER_ACCESS_TOKEN";
|
|
59
59
|
RECEIVED_USER_STATS: "RECEIVED_USER_STATS";
|
|
60
|
-
|
|
60
|
+
RECEIVED_APP_LIMITS: "RECEIVED_APP_LIMITS";
|
|
61
61
|
RECEIVED_FILTERED_USER_STATS: "RECEIVED_FILTERED_USER_STATS";
|
|
62
62
|
PROFILE_NO_LONGER_VISIBLE: "PROFILE_NO_LONGER_VISIBLE";
|
|
63
63
|
LOGIN: "LOGIN";
|
|
@@ -65,7 +65,7 @@ exports.default = (0, key_mirror_1.default)({
|
|
|
65
65
|
DISABLED_USER_ACCESS_TOKEN: null,
|
|
66
66
|
ENABLED_USER_ACCESS_TOKEN: null,
|
|
67
67
|
RECEIVED_USER_STATS: null,
|
|
68
|
-
|
|
68
|
+
RECEIVED_APP_LIMITS: null,
|
|
69
69
|
RECEIVED_FILTERED_USER_STATS: null,
|
|
70
70
|
PROFILE_NO_LONGER_VISIBLE: null,
|
|
71
71
|
LOGIN: null,
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import type { AccessControlPoliciesResult, AccessControlPolicy, 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
|
-
export declare function getAccessControlPolicy(id: string): ActionFuncAsync<AccessControlPolicy, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
4
|
+
export declare function getAccessControlPolicy(id: string, channelId?: string): ActionFuncAsync<AccessControlPolicy, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
5
5
|
export declare function createAccessControlPolicy(policy: AccessControlPolicy): ActionFuncAsync<AccessControlPolicy>;
|
|
6
6
|
export declare function deleteAccessControlPolicy(id: string): ActionFuncAsync<AccessControlPolicy, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
7
7
|
export declare function searchAccessControlPolicies(term: string, type: string, after: string, limit: number): ActionFuncAsync<AccessControlPoliciesResult>;
|
|
8
8
|
export declare function searchAccessControlPolicyChannels(id: string, term: string, opts: ChannelSearchOpts): ActionFuncAsync<ChannelsWithTotalCount>;
|
|
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
|
-
export declare function getAccessControlFields(after: string, limit: number): ActionFuncAsync<import("@mattermost/types/properties").UserPropertyField[], import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
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
12
|
export declare function updateAccessControlPolicyActive(policyId: string, active: boolean): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
13
|
-
export declare function searchUsersForExpression(expression: string, term: string, after: string, limit: number): ActionFuncAsync<AccessControlTestResult>;
|
|
14
|
-
export declare function getVisualAST(expression: string): ActionFuncAsync<import("@mattermost/types/access_control").AccessControlVisualAST, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
13
|
+
export declare function searchUsersForExpression(expression: string, term: string, after: string, limit: number, channelId?: string): ActionFuncAsync<AccessControlTestResult>;
|
|
14
|
+
export declare function getVisualAST(expression: string, channelId?: string): ActionFuncAsync<import("@mattermost/types/access_control").AccessControlVisualAST, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
15
|
+
export declare function validateExpressionAgainstRequester(expression: string, channelId?: string): ActionFuncAsync<{
|
|
16
|
+
requester_matches: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
export declare function createAccessControlSyncJob(jobData: {
|
|
19
|
+
policy_id: string;
|
|
20
|
+
}): ActionFuncAsync<any>;
|
|
@@ -13,16 +13,19 @@ exports.getAccessControlFields = getAccessControlFields;
|
|
|
13
13
|
exports.updateAccessControlPolicyActive = updateAccessControlPolicyActive;
|
|
14
14
|
exports.searchUsersForExpression = searchUsersForExpression;
|
|
15
15
|
exports.getVisualAST = getVisualAST;
|
|
16
|
+
exports.validateExpressionAgainstRequester = validateExpressionAgainstRequester;
|
|
17
|
+
exports.createAccessControlSyncJob = createAccessControlSyncJob;
|
|
16
18
|
const redux_batched_actions_1 = require("redux-batched-actions");
|
|
17
19
|
const action_types_1 = require("mattermost-redux/action_types");
|
|
18
20
|
const client_1 = require("mattermost-redux/client");
|
|
19
21
|
const helpers_1 = require("./helpers");
|
|
20
|
-
function getAccessControlPolicy(id) {
|
|
22
|
+
function getAccessControlPolicy(id, channelId) {
|
|
21
23
|
return (0, helpers_1.bindClientFunc)({
|
|
22
24
|
clientFunc: client_1.Client4.getAccessControlPolicy,
|
|
23
25
|
onSuccess: [action_types_1.AdminTypes.RECEIVED_ACCESS_CONTROL_POLICY],
|
|
24
26
|
params: [
|
|
25
27
|
id,
|
|
28
|
+
channelId,
|
|
26
29
|
],
|
|
27
30
|
});
|
|
28
31
|
}
|
|
@@ -102,12 +105,13 @@ function unassignChannelsFromAccessControlPolicy(policyId, channelIds) {
|
|
|
102
105
|
],
|
|
103
106
|
});
|
|
104
107
|
}
|
|
105
|
-
function getAccessControlFields(after, limit) {
|
|
108
|
+
function getAccessControlFields(after, limit, channelId) {
|
|
106
109
|
return (0, helpers_1.bindClientFunc)({
|
|
107
110
|
clientFunc: client_1.Client4.getAccessControlFields,
|
|
108
111
|
params: [
|
|
109
112
|
after,
|
|
110
113
|
limit,
|
|
114
|
+
channelId,
|
|
111
115
|
],
|
|
112
116
|
});
|
|
113
117
|
}
|
|
@@ -120,11 +124,11 @@ function updateAccessControlPolicyActive(policyId, active) {
|
|
|
120
124
|
],
|
|
121
125
|
});
|
|
122
126
|
}
|
|
123
|
-
function searchUsersForExpression(expression, term, after, limit) {
|
|
127
|
+
function searchUsersForExpression(expression, term, after, limit, channelId) {
|
|
124
128
|
return async (dispatch, getState) => {
|
|
125
129
|
let data;
|
|
126
130
|
try {
|
|
127
|
-
data = await client_1.Client4.testAccessControlExpression(expression, term, after, limit);
|
|
131
|
+
data = await client_1.Client4.testAccessControlExpression(expression, term, after, limit, channelId);
|
|
128
132
|
}
|
|
129
133
|
catch (error) {
|
|
130
134
|
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
@@ -134,9 +138,35 @@ function searchUsersForExpression(expression, term, after, limit) {
|
|
|
134
138
|
return { data };
|
|
135
139
|
};
|
|
136
140
|
}
|
|
137
|
-
function getVisualAST(expression) {
|
|
141
|
+
function getVisualAST(expression, channelId) {
|
|
138
142
|
return (0, helpers_1.bindClientFunc)({
|
|
139
143
|
clientFunc: client_1.Client4.expressionToVisualFormat,
|
|
140
|
-
params: [expression],
|
|
144
|
+
params: [expression, channelId],
|
|
141
145
|
});
|
|
142
146
|
}
|
|
147
|
+
function validateExpressionAgainstRequester(expression, channelId) {
|
|
148
|
+
return async (dispatch, getState) => {
|
|
149
|
+
let data;
|
|
150
|
+
try {
|
|
151
|
+
data = await client_1.Client4.validateExpressionAgainstRequester(expression, channelId);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
155
|
+
return { error };
|
|
156
|
+
}
|
|
157
|
+
return { data };
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function createAccessControlSyncJob(jobData) {
|
|
161
|
+
return async (dispatch, getState) => {
|
|
162
|
+
let data;
|
|
163
|
+
try {
|
|
164
|
+
data = await client_1.Client4.createAccessControlSyncJob(jobData);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
168
|
+
return { error };
|
|
169
|
+
}
|
|
170
|
+
return { data };
|
|
171
|
+
};
|
|
172
|
+
}
|
|
@@ -45,7 +45,7 @@ export declare function getAllChannelsWithCount(page?: number, perPage?: number,
|
|
|
45
45
|
export declare function getAllChannels(page?: number, perPage?: number, notAssociatedToGroup?: string, excludeDefaultChannels?: boolean, excludePolicyConstrained?: boolean, excludeAccessControlPolicyEnforced?: boolean, accessControlPolicyEnforced?: boolean): ActionFuncAsync<ChannelWithTeamData[]>;
|
|
46
46
|
export declare function autocompleteChannels(teamId: string, term: string): ActionFuncAsync<Channel[]>;
|
|
47
47
|
export declare function autocompleteChannelsForSearch(teamId: string, term: string): ActionFuncAsync<Channel[]>;
|
|
48
|
-
export declare function searchChannels(teamId: string, term: string
|
|
48
|
+
export declare function searchChannels(teamId: string, term: string): ActionFuncAsync<Channel[]>;
|
|
49
49
|
export declare function searchAllChannels(term: string, opts: {
|
|
50
50
|
page: number;
|
|
51
51
|
per_page: number;
|
package/lib/actions/channels.js
CHANGED
|
@@ -66,9 +66,7 @@ const channel_categories_1 = require("mattermost-redux/constants/channel_categor
|
|
|
66
66
|
const channels_1 = require("mattermost-redux/constants/channels");
|
|
67
67
|
const channel_categories_2 = require("mattermost-redux/selectors/entities/channel_categories");
|
|
68
68
|
const channels_2 = require("mattermost-redux/selectors/entities/channels");
|
|
69
|
-
const general_1 = require("mattermost-redux/selectors/entities/general");
|
|
70
69
|
const teams_1 = require("mattermost-redux/selectors/entities/teams");
|
|
71
|
-
const channel_utils_1 = require("mattermost-redux/utils/channel_utils");
|
|
72
70
|
const data_loader_1 = require("mattermost-redux/utils/data_loader");
|
|
73
71
|
const channel_categories_3 = require("./channel_categories");
|
|
74
72
|
const errors_1 = require("./errors");
|
|
@@ -526,7 +524,6 @@ function leaveChannel(channelId) {
|
|
|
526
524
|
const { channels, myMembers } = state.entities.channels;
|
|
527
525
|
const channel = channels[channelId];
|
|
528
526
|
const member = myMembers[channelId];
|
|
529
|
-
client_1.Client4.trackEvent('action', 'action_channels_leave', { channel_id: channelId });
|
|
530
527
|
dispatch({
|
|
531
528
|
type: action_types_1.ChannelTypes.LEAVE_CHANNEL,
|
|
532
529
|
data: {
|
|
@@ -587,7 +584,6 @@ function joinChannel(userId, teamId, channelId, channelName) {
|
|
|
587
584
|
dispatch((0, errors_1.logError)(error));
|
|
588
585
|
return { error };
|
|
589
586
|
}
|
|
590
|
-
client_1.Client4.trackEvent('action', 'action_channels_join', { channel_id: channelId });
|
|
591
587
|
dispatch((0, redux_batched_actions_1.batchActions)([
|
|
592
588
|
{
|
|
593
589
|
type: action_types_1.ChannelTypes.RECEIVED_CHANNEL,
|
|
@@ -607,8 +603,6 @@ function joinChannel(userId, teamId, channelId, channelName) {
|
|
|
607
603
|
}
|
|
608
604
|
function deleteChannel(channelId) {
|
|
609
605
|
return async (dispatch, getState) => {
|
|
610
|
-
let state = getState();
|
|
611
|
-
const viewArchivedChannels = state.entities.general.config.ExperimentalViewArchivedChannels === 'true';
|
|
612
606
|
try {
|
|
613
607
|
await client_1.Client4.deleteChannel(channelId);
|
|
614
608
|
}
|
|
@@ -617,17 +611,7 @@ function deleteChannel(channelId) {
|
|
|
617
611
|
dispatch((0, errors_1.logError)(error));
|
|
618
612
|
return { error };
|
|
619
613
|
}
|
|
620
|
-
|
|
621
|
-
const { currentChannelId } = state.entities.channels;
|
|
622
|
-
if (channelId === currentChannelId && !viewArchivedChannels) {
|
|
623
|
-
const teamId = (0, teams_1.getCurrentTeamId)(state);
|
|
624
|
-
const channelsInTeam = (0, channels_2.getChannelsNameMapInTeam)(state, teamId);
|
|
625
|
-
const channel = (0, channel_utils_1.getChannelByName)(channelsInTeam, (0, channels_2.getRedirectChannelNameForTeam)(state, teamId));
|
|
626
|
-
if (channel && channel.id) {
|
|
627
|
-
dispatch({ type: action_types_1.ChannelTypes.SELECT_CHANNEL, data: channel.id });
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
dispatch({ type: action_types_1.ChannelTypes.DELETE_CHANNEL_SUCCESS, data: { id: channelId, viewArchivedChannels } });
|
|
614
|
+
dispatch({ type: action_types_1.ChannelTypes.DELETE_CHANNEL_SUCCESS, data: { id: channelId } });
|
|
631
615
|
return { data: true };
|
|
632
616
|
};
|
|
633
617
|
}
|
|
@@ -641,10 +625,7 @@ function unarchiveChannel(channelId) {
|
|
|
641
625
|
dispatch((0, errors_1.logError)(error));
|
|
642
626
|
return { error };
|
|
643
627
|
}
|
|
644
|
-
|
|
645
|
-
const config = (0, general_1.getConfig)(state);
|
|
646
|
-
const viewArchivedChannels = config.ExperimentalViewArchivedChannels === 'true';
|
|
647
|
-
dispatch({ type: action_types_1.ChannelTypes.UNARCHIVED_CHANNEL_SUCCESS, data: { id: channelId, viewArchivedChannels } });
|
|
628
|
+
dispatch({ type: action_types_1.ChannelTypes.UNARCHIVED_CHANNEL_SUCCESS, data: { id: channelId } });
|
|
648
629
|
return { data: true };
|
|
649
630
|
};
|
|
650
631
|
}
|
|
@@ -842,17 +823,12 @@ function autocompleteChannelsForSearch(teamId, term) {
|
|
|
842
823
|
return { data: channels };
|
|
843
824
|
};
|
|
844
825
|
}
|
|
845
|
-
function searchChannels(teamId, term
|
|
826
|
+
function searchChannels(teamId, term) {
|
|
846
827
|
return async (dispatch, getState) => {
|
|
847
828
|
dispatch({ type: action_types_1.ChannelTypes.GET_CHANNELS_REQUEST, data: null });
|
|
848
829
|
let channels;
|
|
849
830
|
try {
|
|
850
|
-
|
|
851
|
-
channels = await client_1.Client4.searchArchivedChannels(teamId, term);
|
|
852
|
-
}
|
|
853
|
-
else {
|
|
854
|
-
channels = await client_1.Client4.searchChannels(teamId, term);
|
|
855
|
-
}
|
|
831
|
+
channels = await client_1.Client4.searchChannels(teamId, term);
|
|
856
832
|
}
|
|
857
833
|
catch (error) {
|
|
858
834
|
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
@@ -955,7 +931,6 @@ function addChannelMember(channelId, userId, postRootId = '') {
|
|
|
955
931
|
dispatch((0, errors_1.logError)(error));
|
|
956
932
|
return { error };
|
|
957
933
|
}
|
|
958
|
-
client_1.Client4.trackEvent('action', 'action_channels_add_member', { channel_id: channelId });
|
|
959
934
|
const membersInChannel = getState().entities.channels.membersInChannel[channelId];
|
|
960
935
|
if (!(membersInChannel && userId in membersInChannel)) {
|
|
961
936
|
dispatch((0, redux_batched_actions_1.batchActions)([
|
|
@@ -992,7 +967,6 @@ function addChannelMembers(channelId, userIds, postRootId = '') {
|
|
|
992
967
|
dispatch((0, errors_1.logError)(error));
|
|
993
968
|
return { error };
|
|
994
969
|
}
|
|
995
|
-
client_1.Client4.trackEvent('action', 'action_channels_add_member', { channel_id: channelId });
|
|
996
970
|
const ids = channelMembers.map((member) => ({ id: member.user_id }));
|
|
997
971
|
dispatch((0, redux_batched_actions_1.batchActions)([
|
|
998
972
|
{
|
|
@@ -1023,7 +997,6 @@ function removeChannelMember(channelId, userId) {
|
|
|
1023
997
|
dispatch((0, errors_1.logError)(error));
|
|
1024
998
|
return { error };
|
|
1025
999
|
}
|
|
1026
|
-
client_1.Client4.trackEvent('action', 'action_channels_remove_member', { channel_id: channelId });
|
|
1027
1000
|
dispatch((0, redux_batched_actions_1.batchActions)([
|
|
1028
1001
|
{
|
|
1029
1002
|
type: action_types_1.UserTypes.RECEIVED_PROFILE_NOT_IN_CHANNEL,
|
|
@@ -1216,7 +1189,6 @@ function favoriteChannel(channelId) {
|
|
|
1216
1189
|
const state = getState();
|
|
1217
1190
|
const channel = (0, channels_2.getChannel)(state, channelId);
|
|
1218
1191
|
const category = (0, channel_categories_2.getCategoryInTeamByType)(state, channel?.team_id || (0, teams_1.getCurrentTeamId)(state), channel_categories_1.CategoryTypes.FAVORITES);
|
|
1219
|
-
client_1.Client4.trackEvent('action', 'action_channels_favorite');
|
|
1220
1192
|
if (!category) {
|
|
1221
1193
|
return { data: false };
|
|
1222
1194
|
}
|
|
@@ -1232,7 +1204,6 @@ function unfavoriteChannel(channelId) {
|
|
|
1232
1204
|
return { data: false };
|
|
1233
1205
|
}
|
|
1234
1206
|
const category = (0, channel_categories_2.getCategoryInTeamByType)(state, channel.team_id || (0, teams_1.getCurrentTeamId)(state), channel.type === constants_1.General.DM_CHANNEL || channel.type === constants_1.General.GM_CHANNEL ? channel_categories_1.CategoryTypes.DIRECT_MESSAGES : channel_categories_1.CategoryTypes.CHANNELS);
|
|
1235
|
-
client_1.Client4.trackEvent('action', 'action_channels_unfavorite');
|
|
1236
1207
|
if (!category) {
|
|
1237
1208
|
return { data: false };
|
|
1238
1209
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ContentFlaggingConfig } from '@mattermost/types/content_flagging';
|
|
2
|
+
import type { ActionFuncAsync } from 'mattermost-redux/types/actions';
|
|
3
|
+
export declare function getTeamContentFlaggingStatus(teamId: string): ActionFuncAsync<{
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function getContentFlaggingConfig(): ActionFuncAsync<ContentFlaggingConfig>;
|
|
@@ -0,0 +1,49 @@
|
|
|
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.getTeamContentFlaggingStatus = getTeamContentFlaggingStatus;
|
|
6
|
+
exports.getContentFlaggingConfig = getContentFlaggingConfig;
|
|
7
|
+
const action_types_1 = require("mattermost-redux/action_types");
|
|
8
|
+
const errors_1 = require("mattermost-redux/actions/errors");
|
|
9
|
+
const helpers_1 = require("mattermost-redux/actions/helpers");
|
|
10
|
+
const client_1 = require("mattermost-redux/client");
|
|
11
|
+
function getTeamContentFlaggingStatus(teamId) {
|
|
12
|
+
return async (dispatch, getState) => {
|
|
13
|
+
let response;
|
|
14
|
+
try {
|
|
15
|
+
response = await client_1.Client4.getTeamContentFlaggingStatus(teamId);
|
|
16
|
+
dispatch({
|
|
17
|
+
type: action_types_1.TeamTypes.RECEIVED_CONTENT_FLAGGING_STATUS,
|
|
18
|
+
data: {
|
|
19
|
+
teamId,
|
|
20
|
+
status: response.enabled,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
26
|
+
dispatch((0, errors_1.logError)(error));
|
|
27
|
+
return { error };
|
|
28
|
+
}
|
|
29
|
+
return { data: response };
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function getContentFlaggingConfig() {
|
|
33
|
+
return async (dispatch, getState) => {
|
|
34
|
+
let response;
|
|
35
|
+
try {
|
|
36
|
+
response = await client_1.Client4.getContentFlaggingConfig();
|
|
37
|
+
dispatch({
|
|
38
|
+
type: action_types_1.ContentFlaggingTypes.RECEIVED_CONTENT_FLAGGING_CONFIG,
|
|
39
|
+
data: response,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
44
|
+
dispatch((0, errors_1.logError)(error));
|
|
45
|
+
return { error };
|
|
46
|
+
}
|
|
47
|
+
return { data: response };
|
|
48
|
+
};
|
|
49
|
+
}
|
package/lib/actions/general.js
CHANGED
|
@@ -22,7 +22,7 @@ function getClientConfig() {
|
|
|
22
22
|
return async (dispatch, getState) => {
|
|
23
23
|
let data;
|
|
24
24
|
try {
|
|
25
|
-
data = await client_1.Client4.
|
|
25
|
+
data = await client_1.Client4.getClientConfig();
|
|
26
26
|
}
|
|
27
27
|
catch (error) {
|
|
28
28
|
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
@@ -39,3 +39,9 @@ export declare function deleteOAuthApp(id: string): ActionFuncAsync;
|
|
|
39
39
|
export declare function regenOAuthAppSecret(appId: string): ActionFuncAsync<OAuthApp, import("@mattermost/types/store").GlobalState, AnyAction>;
|
|
40
40
|
export declare function deleteOutgoingOAuthConnection(id: string): ActionFuncAsync<boolean>;
|
|
41
41
|
export declare function submitInteractiveDialog(submission: DialogSubmission): ActionFuncAsync<SubmitDialogResponse>;
|
|
42
|
+
export declare function lookupInteractiveDialog(submission: DialogSubmission): ActionFuncAsync<{
|
|
43
|
+
items: Array<{
|
|
44
|
+
text: string;
|
|
45
|
+
value: string;
|
|
46
|
+
}>;
|
|
47
|
+
}>;
|
|
@@ -40,6 +40,7 @@ exports.deleteOAuthApp = deleteOAuthApp;
|
|
|
40
40
|
exports.regenOAuthAppSecret = regenOAuthAppSecret;
|
|
41
41
|
exports.deleteOutgoingOAuthConnection = deleteOutgoingOAuthConnection;
|
|
42
42
|
exports.submitInteractiveDialog = submitInteractiveDialog;
|
|
43
|
+
exports.lookupInteractiveDialog = lookupInteractiveDialog;
|
|
43
44
|
const redux_batched_actions_1 = require("redux-batched-actions");
|
|
44
45
|
const action_types_1 = require("mattermost-redux/action_types");
|
|
45
46
|
const client_1 = require("mattermost-redux/client");
|
|
@@ -488,3 +489,21 @@ function submitInteractiveDialog(submission) {
|
|
|
488
489
|
return { data };
|
|
489
490
|
};
|
|
490
491
|
}
|
|
492
|
+
function lookupInteractiveDialog(submission) {
|
|
493
|
+
return async (dispatch, getState) => {
|
|
494
|
+
const state = getState();
|
|
495
|
+
submission.channel_id = (0, channels_1.getCurrentChannelId)(state);
|
|
496
|
+
submission.team_id = (0, teams_1.getCurrentTeamId)(state);
|
|
497
|
+
submission.user_id = (0, users_1.getCurrentUserId)(state);
|
|
498
|
+
let data;
|
|
499
|
+
try {
|
|
500
|
+
data = await client_1.Client4.lookupInteractiveDialog(submission);
|
|
501
|
+
}
|
|
502
|
+
catch (error) {
|
|
503
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
504
|
+
dispatch((0, errors_1.logError)(error));
|
|
505
|
+
return { error };
|
|
506
|
+
}
|
|
507
|
+
return { data };
|
|
508
|
+
};
|
|
509
|
+
}
|
package/lib/actions/jobs.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { JobType, JobTypeBase } from '@mattermost/types/jobs';
|
|
2
|
-
export declare function createJob(job: JobTypeBase
|
|
2
|
+
export declare function createJob(job: JobTypeBase & {
|
|
3
|
+
data?: any;
|
|
4
|
+
}): import("../types/actions").ActionFuncAsync<JobTypeBase & {
|
|
3
5
|
id: string;
|
|
4
6
|
priority: number;
|
|
5
7
|
create_at: number;
|
package/lib/actions/limits.js
CHANGED
|
@@ -7,20 +7,9 @@ const action_types_1 = require("mattermost-redux/action_types");
|
|
|
7
7
|
const errors_1 = require("mattermost-redux/actions/errors");
|
|
8
8
|
const helpers_1 = require("mattermost-redux/actions/helpers");
|
|
9
9
|
const client_1 = require("mattermost-redux/client");
|
|
10
|
-
const users_1 = require("mattermost-redux/selectors/entities/users");
|
|
11
|
-
const user_utils_1 = require("mattermost-redux/utils/user_utils");
|
|
12
10
|
function getServerLimits() {
|
|
13
11
|
return async (dispatch, getState) => {
|
|
14
|
-
|
|
15
|
-
const amIAdmin = (0, user_utils_1.isAdmin)(roles);
|
|
16
|
-
if (!amIAdmin) {
|
|
17
|
-
return {
|
|
18
|
-
data: {
|
|
19
|
-
activeUserCount: 0,
|
|
20
|
-
maxUsersLimit: 0,
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
}
|
|
12
|
+
// All users can fetch server limits - server handles permission filtering
|
|
24
13
|
let response;
|
|
25
14
|
try {
|
|
26
15
|
response = await client_1.Client4.getServerLimits();
|
|
@@ -33,8 +22,12 @@ function getServerLimits() {
|
|
|
33
22
|
const data = {
|
|
34
23
|
activeUserCount: response?.data?.activeUserCount ?? 0,
|
|
35
24
|
maxUsersLimit: response?.data?.maxUsersLimit ?? 0,
|
|
25
|
+
maxUsersHardLimit: response?.data?.maxUsersHardLimit ?? 0,
|
|
26
|
+
// Post history limit fields from server response
|
|
27
|
+
lastAccessiblePostTime: response?.data?.lastAccessiblePostTime ?? 0,
|
|
28
|
+
postHistoryLimit: response?.data?.postHistoryLimit ?? 0,
|
|
36
29
|
};
|
|
37
|
-
dispatch({ type: action_types_1.LimitsTypes.
|
|
30
|
+
dispatch({ type: action_types_1.LimitsTypes.RECEIVED_APP_LIMITS, data });
|
|
38
31
|
return { data };
|
|
39
32
|
};
|
|
40
33
|
}
|
package/lib/actions/posts.js
CHANGED
|
@@ -564,7 +564,6 @@ function flagPost(postId) {
|
|
|
564
564
|
name: postId,
|
|
565
565
|
value: 'true',
|
|
566
566
|
};
|
|
567
|
-
client_1.Client4.trackEvent('action', 'action_posts_flag');
|
|
568
567
|
return dispatch((0, preferences_1.savePreferences)(currentUserId, [preference]));
|
|
569
568
|
};
|
|
570
569
|
}
|
|
@@ -1087,7 +1086,6 @@ function unflagPost(postId) {
|
|
|
1087
1086
|
name: postId,
|
|
1088
1087
|
value: 'true',
|
|
1089
1088
|
};
|
|
1090
|
-
client_1.Client4.trackEvent('action', 'action_posts_unflag');
|
|
1091
1089
|
return dispatch((0, preferences_1.deletePreferences)(currentUserId, [preference]));
|
|
1092
1090
|
};
|
|
1093
1091
|
}
|
package/lib/actions/search.js
CHANGED
|
@@ -62,6 +62,16 @@ function searchPostsWithParams(teamId, params) {
|
|
|
62
62
|
type: action_types_1.SearchTypes.SEARCH_POSTS_REQUEST,
|
|
63
63
|
isGettingMore,
|
|
64
64
|
});
|
|
65
|
+
// Reset truncation info for new searches (not pagination)
|
|
66
|
+
if (!isGettingMore) {
|
|
67
|
+
dispatch({
|
|
68
|
+
type: action_types_1.SearchTypes.RECEIVED_SEARCH_TRUNCATION_INFO,
|
|
69
|
+
data: {
|
|
70
|
+
firstInaccessiblePostTime: 0,
|
|
71
|
+
searchType: 'posts',
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
}
|
|
65
75
|
let posts;
|
|
66
76
|
try {
|
|
67
77
|
posts = await client_1.Client4.searchPostsWithParams(teamId, params);
|
|
@@ -94,6 +104,17 @@ function searchPostsWithParams(teamId, params) {
|
|
|
94
104
|
type: action_types_1.SearchTypes.SEARCH_POSTS_SUCCESS,
|
|
95
105
|
},
|
|
96
106
|
], 'SEARCH_POST_BATCH'));
|
|
107
|
+
// Dispatch truncation info separately to avoid typing conflicts
|
|
108
|
+
const firstInaccessiblePostTime = posts.first_inaccessible_post_time || 0;
|
|
109
|
+
if (firstInaccessiblePostTime > 0) {
|
|
110
|
+
dispatch({
|
|
111
|
+
type: action_types_1.SearchTypes.RECEIVED_SEARCH_TRUNCATION_INFO,
|
|
112
|
+
data: {
|
|
113
|
+
firstInaccessiblePostTime,
|
|
114
|
+
searchType: 'posts',
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
}
|
|
97
118
|
return { data: posts };
|
|
98
119
|
};
|
|
99
120
|
}
|
|
@@ -125,6 +146,16 @@ function searchFilesWithParams(teamId, params) {
|
|
|
125
146
|
type: action_types_1.SearchTypes.SEARCH_FILES_REQUEST,
|
|
126
147
|
isGettingMore,
|
|
127
148
|
});
|
|
149
|
+
// Reset truncation info for new searches (not pagination)
|
|
150
|
+
if (!isGettingMore) {
|
|
151
|
+
dispatch({
|
|
152
|
+
type: action_types_1.SearchTypes.RECEIVED_SEARCH_TRUNCATION_INFO,
|
|
153
|
+
data: {
|
|
154
|
+
firstInaccessiblePostTime: 0,
|
|
155
|
+
searchType: 'files',
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
}
|
|
128
159
|
let files;
|
|
129
160
|
try {
|
|
130
161
|
files = await client_1.Client4.searchFilesWithParams(teamId, params);
|
package/lib/actions/users.js
CHANGED
|
@@ -134,9 +134,6 @@ function loadMe() {
|
|
|
134
134
|
dispatch((0, teams_1.getMyTeams)()),
|
|
135
135
|
dispatch((0, teams_1.getMyTeamMembers)()),
|
|
136
136
|
]);
|
|
137
|
-
if ((0, general_2.getFeatureFlagValue)(getState(), 'CustomProfileAttributes') === 'true') {
|
|
138
|
-
dispatch((0, general_1.getCustomProfileAttributeFields)());
|
|
139
|
-
}
|
|
140
137
|
const isCollapsedThreads = (0, preferences_2.isCollapsedThreadsEnabled)(getState());
|
|
141
138
|
await dispatch((0, teams_1.getMyTeamUnreads)(isCollapsedThreads));
|
|
142
139
|
await dispatch((0, limits_1.getServerLimits)());
|
package/lib/constants/apps.js
CHANGED
|
@@ -29,6 +29,7 @@ declare const values: {
|
|
|
29
29
|
CONVERT_PRIVATE_CHANNEL_TO_PUBLIC: string;
|
|
30
30
|
MANAGE_PUBLIC_CHANNEL_BANNER: string;
|
|
31
31
|
MANAGE_PRIVATE_CHANNEL_BANNER: string;
|
|
32
|
+
MANAGE_CHANNEL_ACCESS_RULES: string;
|
|
32
33
|
DELETE_PRIVATE_CHANNEL: string;
|
|
33
34
|
EDIT_OTHER_USERS: string;
|
|
34
35
|
READ_CHANNEL: string;
|
|
@@ -33,6 +33,7 @@ const values = {
|
|
|
33
33
|
CONVERT_PRIVATE_CHANNEL_TO_PUBLIC: 'convert_private_channel_to_public',
|
|
34
34
|
MANAGE_PUBLIC_CHANNEL_BANNER: 'manage_public_channel_banner',
|
|
35
35
|
MANAGE_PRIVATE_CHANNEL_BANNER: 'manage_private_channel_banner',
|
|
36
|
+
MANAGE_CHANNEL_ACCESS_RULES: 'manage_channel_access_rules',
|
|
36
37
|
DELETE_PRIVATE_CHANNEL: 'delete_private_channel',
|
|
37
38
|
EDIT_OTHER_USERS: 'edit_other_users',
|
|
38
39
|
READ_CHANNEL: 'read_channel',
|