mattermost-redux 11.7.0 → 11.8.0-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/actions/access_control.d.ts +14 -1
- package/lib/actions/access_control.js +30 -0
- package/lib/actions/channel_categories.js +3 -0
- package/lib/actions/channels.d.ts +2 -0
- package/lib/actions/channels.js +35 -0
- package/lib/actions/properties.d.ts +12 -0
- package/lib/actions/properties.js +55 -0
- package/lib/actions/recaps.d.ts +3 -0
- package/lib/actions/recaps.js +14 -0
- package/lib/actions/teams.d.ts +1 -0
- package/lib/actions/teams.js +18 -0
- package/lib/actions/users.d.ts +1 -1
- package/lib/actions/users.js +7 -7
- package/lib/constants/general.d.ts +1 -0
- package/lib/constants/general.js +1 -0
- package/lib/constants/permissions.d.ts +1 -0
- package/lib/constants/permissions.js +1 -0
- package/lib/constants/posts.d.ts +2 -0
- package/lib/constants/posts.js +1 -0
- package/lib/constants/preferences.d.ts +4 -0
- package/lib/constants/preferences.js +4 -0
- package/lib/reducers/entities/properties.js +21 -8
- package/lib/selectors/entities/channel_categories.d.ts +2 -0
- package/lib/selectors/entities/channel_categories.js +16 -0
- package/lib/selectors/entities/general.d.ts +26 -0
- package/lib/selectors/entities/general.js +38 -0
- package/lib/selectors/entities/recaps.d.ts +10 -0
- package/lib/selectors/entities/recaps.js +20 -1
- package/lib/selectors/entities/report_a_problem.d.ts +1 -0
- package/lib/selectors/entities/report_a_problem.js +31 -4
- package/lib/utils/browser_info.d.ts +2 -0
- package/lib/utils/browser_info.js +11 -0
- package/lib/utils/integration_utils.js +7 -5
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AccessControlPoliciesResult, AccessControlPolicy, AccessControlPolicyActiveUpdate, AccessControlTestResult } from '@mattermost/types/access_control';
|
|
1
|
+
import type { AccessControlPoliciesResult, AccessControlPolicy, AccessControlPolicyActiveUpdate, AccessControlTestResult, PolicySimulationResponse, PolicySimulationByUsersParams } 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, teamId?: string): ActionFuncAsync<AccessControlPolicy, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
@@ -12,6 +12,19 @@ export declare function assignChannelsToAccessControlPolicy(policyId: string, ch
|
|
|
12
12
|
export declare function unassignChannelsFromAccessControlPolicy(policyId: string, channelIds: string[], teamId?: string): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
13
13
|
export declare function getAccessControlFields(after: string, limit: number, channelId?: string, teamId?: string): ActionFuncAsync<import("@mattermost/types/properties").UserPropertyField[], import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
14
14
|
export declare function searchUsersForExpression(expression: string, term: string, after: string, limit: number, channelId?: string, teamId?: string): ActionFuncAsync<AccessControlTestResult>;
|
|
15
|
+
/**
|
|
16
|
+
* Run the dual-lane PDP simulation against a draft policy for an explicit
|
|
17
|
+
* set of users (with optional per-user session attribute overrides) and
|
|
18
|
+
* return per-user, per-action ALLOW/DENY decisions with blame attribution.
|
|
19
|
+
* Backs the picker-based "Simulate access" modal in the System Console
|
|
20
|
+
* and Channel Settings so authors can see how a draft interacts with
|
|
21
|
+
* persisted higher-scoped policies before saving.
|
|
22
|
+
*
|
|
23
|
+
* The redux action only forwards profiles into the user store on success;
|
|
24
|
+
* decisions and blame metadata stay on the returned data and are consumed
|
|
25
|
+
* directly by the modal.
|
|
26
|
+
*/
|
|
27
|
+
export declare function simulatePolicyForUsers(params: PolicySimulationByUsersParams): ActionFuncAsync<PolicySimulationResponse>;
|
|
15
28
|
export declare function getVisualAST(expression: string, channelId?: string, teamId?: string): ActionFuncAsync<import("@mattermost/types/access_control").AccessControlVisualAST, import("@mattermost/types/store").GlobalState, import("redux").AnyAction>;
|
|
16
29
|
export declare function validateExpressionAgainstRequester(expression: string, channelId?: string, teamId?: string): ActionFuncAsync<{
|
|
17
30
|
requester_matches: boolean;
|
|
@@ -13,6 +13,7 @@ exports.assignChannelsToAccessControlPolicy = assignChannelsToAccessControlPolic
|
|
|
13
13
|
exports.unassignChannelsFromAccessControlPolicy = unassignChannelsFromAccessControlPolicy;
|
|
14
14
|
exports.getAccessControlFields = getAccessControlFields;
|
|
15
15
|
exports.searchUsersForExpression = searchUsersForExpression;
|
|
16
|
+
exports.simulatePolicyForUsers = simulatePolicyForUsers;
|
|
16
17
|
exports.getVisualAST = getVisualAST;
|
|
17
18
|
exports.validateExpressionAgainstRequester = validateExpressionAgainstRequester;
|
|
18
19
|
exports.createAccessControlSyncJob = createAccessControlSyncJob;
|
|
@@ -147,6 +148,35 @@ function searchUsersForExpression(expression, term, after, limit, channelId, tea
|
|
|
147
148
|
return { data };
|
|
148
149
|
};
|
|
149
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Run the dual-lane PDP simulation against a draft policy for an explicit
|
|
153
|
+
* set of users (with optional per-user session attribute overrides) and
|
|
154
|
+
* return per-user, per-action ALLOW/DENY decisions with blame attribution.
|
|
155
|
+
* Backs the picker-based "Simulate access" modal in the System Console
|
|
156
|
+
* and Channel Settings so authors can see how a draft interacts with
|
|
157
|
+
* persisted higher-scoped policies before saving.
|
|
158
|
+
*
|
|
159
|
+
* The redux action only forwards profiles into the user store on success;
|
|
160
|
+
* decisions and blame metadata stay on the returned data and are consumed
|
|
161
|
+
* directly by the modal.
|
|
162
|
+
*/
|
|
163
|
+
function simulatePolicyForUsers(params) {
|
|
164
|
+
return async (dispatch, getState) => {
|
|
165
|
+
let data;
|
|
166
|
+
try {
|
|
167
|
+
data = await client_1.Client4.simulateAccessControlPolicyForUsers(params);
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
171
|
+
return { error };
|
|
172
|
+
}
|
|
173
|
+
const profiles = data.results?.map((r) => r.user).filter(Boolean) ?? [];
|
|
174
|
+
if (profiles.length > 0) {
|
|
175
|
+
dispatch({ type: action_types_1.UserTypes.RECEIVED_PROFILES, data: profiles });
|
|
176
|
+
}
|
|
177
|
+
return { data };
|
|
178
|
+
};
|
|
179
|
+
}
|
|
150
180
|
function getVisualAST(expression, channelId, teamId) {
|
|
151
181
|
return (0, helpers_1.bindClientFunc)({
|
|
152
182
|
clientFunc: () => client_1.Client4.expressionToVisualFormat(expression, channelId, teamId),
|
|
@@ -175,6 +175,9 @@ function addChannelToInitialCategory(channel, setOnServer = false) {
|
|
|
175
175
|
if ((0, channel_categories_3.areManagedCategoriesEnabled)(state)) {
|
|
176
176
|
dispatch(fetchChannelManagedCategoryMapping(channel));
|
|
177
177
|
}
|
|
178
|
+
if (channel.default_category_name) {
|
|
179
|
+
return { data: false };
|
|
180
|
+
}
|
|
178
181
|
// Add the new channel to the Channels category on the channel's team
|
|
179
182
|
if (categories.some((category) => category.channel_ids.some((channelId) => channelId === channel.id))) {
|
|
180
183
|
return { data: false };
|
|
@@ -39,9 +39,11 @@ export declare function deleteChannel(channelId: string): ActionFuncAsync;
|
|
|
39
39
|
export declare function unarchiveChannel(channelId: string): ActionFuncAsync;
|
|
40
40
|
export declare function updateApproximateViewTime(channelId: string): ActionFuncAsync;
|
|
41
41
|
export declare function unsetActiveChannelOnServer(): ActionFuncAsync;
|
|
42
|
+
export declare function readAllMessages(userId: string): ActionFuncAsync;
|
|
42
43
|
export declare function readMultipleChannels(channelIds: string[]): ActionFuncAsync;
|
|
43
44
|
export declare function getChannels(teamId: string, page?: number, perPage?: number): ActionFuncAsync<Channel[]>;
|
|
44
45
|
export declare function getArchivedChannels(teamId: string, page?: number, perPage?: number): ActionFuncAsync<Channel[]>;
|
|
46
|
+
export declare function getRecommendedChannelsForUser(teamId: string): ActionFuncAsync<Channel[]>;
|
|
45
47
|
export declare function getAllChannelsWithCount(page?: number, perPage?: number, notAssociatedToGroup?: string, excludeDefaultChannels?: boolean, includeDeleted?: boolean, excludePolicyConstrained?: boolean, accessControlPolicyEnforced?: boolean, excludeAccessControlPolicyEnforced?: boolean): ActionFuncAsync<ChannelsWithTotalCount>;
|
|
46
48
|
export declare function getAllChannels(page?: number, perPage?: number, notAssociatedToGroup?: string, excludeDefaultChannels?: boolean, excludePolicyConstrained?: boolean, excludeAccessControlPolicyEnforced?: boolean, accessControlPolicyEnforced?: boolean): ActionFuncAsync<ChannelWithTeamData[]>;
|
|
47
49
|
export declare function autocompleteChannels(teamId: string, term: string): ActionFuncAsync<Channel[]>;
|
package/lib/actions/channels.js
CHANGED
|
@@ -26,9 +26,11 @@ exports.deleteChannel = deleteChannel;
|
|
|
26
26
|
exports.unarchiveChannel = unarchiveChannel;
|
|
27
27
|
exports.updateApproximateViewTime = updateApproximateViewTime;
|
|
28
28
|
exports.unsetActiveChannelOnServer = unsetActiveChannelOnServer;
|
|
29
|
+
exports.readAllMessages = readAllMessages;
|
|
29
30
|
exports.readMultipleChannels = readMultipleChannels;
|
|
30
31
|
exports.getChannels = getChannels;
|
|
31
32
|
exports.getArchivedChannels = getArchivedChannels;
|
|
33
|
+
exports.getRecommendedChannelsForUser = getRecommendedChannelsForUser;
|
|
32
34
|
exports.getAllChannelsWithCount = getAllChannelsWithCount;
|
|
33
35
|
exports.getAllChannels = getAllChannels;
|
|
34
36
|
exports.autocompleteChannels = autocompleteChannels;
|
|
@@ -693,6 +695,21 @@ function unsetActiveChannelOnServer() {
|
|
|
693
695
|
return { data: true };
|
|
694
696
|
};
|
|
695
697
|
}
|
|
698
|
+
function readAllMessages(userId) {
|
|
699
|
+
return async (dispatch, getState) => {
|
|
700
|
+
let response;
|
|
701
|
+
try {
|
|
702
|
+
response = await client_1.Client4.markAllMessagesAsRead(userId);
|
|
703
|
+
}
|
|
704
|
+
catch (error) {
|
|
705
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
706
|
+
dispatch((0, errors_1.logError)(error));
|
|
707
|
+
return { error };
|
|
708
|
+
}
|
|
709
|
+
dispatch(markMultipleChannelsAsRead(response.last_viewed_at_times));
|
|
710
|
+
return { data: true };
|
|
711
|
+
};
|
|
712
|
+
}
|
|
696
713
|
function readMultipleChannels(channelIds) {
|
|
697
714
|
return async (dispatch, getState) => {
|
|
698
715
|
let response;
|
|
@@ -752,6 +769,24 @@ function getArchivedChannels(teamId, page = 0, perPage = constants_1.General.CHA
|
|
|
752
769
|
return { data: channels };
|
|
753
770
|
};
|
|
754
771
|
}
|
|
772
|
+
function getRecommendedChannelsForUser(teamId) {
|
|
773
|
+
return async (dispatch, getState) => {
|
|
774
|
+
let channels;
|
|
775
|
+
try {
|
|
776
|
+
channels = await client_1.Client4.getRecommendedChannelsForUser(teamId);
|
|
777
|
+
}
|
|
778
|
+
catch (error) {
|
|
779
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
780
|
+
return { error };
|
|
781
|
+
}
|
|
782
|
+
dispatch({
|
|
783
|
+
type: action_types_1.ChannelTypes.RECEIVED_CHANNELS,
|
|
784
|
+
teamId,
|
|
785
|
+
data: channels,
|
|
786
|
+
});
|
|
787
|
+
return { data: channels };
|
|
788
|
+
};
|
|
789
|
+
}
|
|
755
790
|
function getAllChannelsWithCount(page = 0, perPage = constants_1.General.CHANNELS_CHUNK_SIZE, notAssociatedToGroup = '', excludeDefaultChannels = false, includeDeleted = false, excludePolicyConstrained = false, accessControlPolicyEnforced = false, excludeAccessControlPolicyEnforced = false) {
|
|
756
791
|
return async (dispatch, getState) => {
|
|
757
792
|
dispatch({ type: action_types_1.ChannelTypes.GET_ALL_CHANNELS_REQUEST, data: null });
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PropertyField, PropertyValue } from '@mattermost/types/properties';
|
|
2
|
+
import type { ActionFuncAsync } from 'mattermost-redux/types/actions';
|
|
3
|
+
/**
|
|
4
|
+
* Fetches property fields for a given group, object type, and target scope,
|
|
5
|
+
* then stores them in the Redux property fields state.
|
|
6
|
+
*/
|
|
7
|
+
export declare function fetchPropertyFields(groupName: string, objectType: string, targetType: string, targetId?: string): ActionFuncAsync<PropertyField[]>;
|
|
8
|
+
/**
|
|
9
|
+
* Fetches all system-scoped property values for a given group via the
|
|
10
|
+
* dedicated `/system/values` endpoint, then stores them in Redux.
|
|
11
|
+
*/
|
|
12
|
+
export declare function fetchSystemPropertyValues<T = unknown>(groupName: string): ActionFuncAsync<Array<PropertyValue<T>>>;
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
exports.fetchPropertyFields = fetchPropertyFields;
|
|
9
|
+
exports.fetchSystemPropertyValues = fetchSystemPropertyValues;
|
|
10
|
+
const client_1 = require("mattermost-redux/client");
|
|
11
|
+
const properties_1 = __importDefault(require("../action_types/properties"));
|
|
12
|
+
/**
|
|
13
|
+
* Fetches property fields for a given group, object type, and target scope,
|
|
14
|
+
* then stores them in the Redux property fields state.
|
|
15
|
+
*/
|
|
16
|
+
function fetchPropertyFields(groupName, objectType, targetType, targetId) {
|
|
17
|
+
return async (dispatch) => {
|
|
18
|
+
let fields = [];
|
|
19
|
+
const maxItems = 500;
|
|
20
|
+
let fetched = 0;
|
|
21
|
+
let cursorId;
|
|
22
|
+
let cursorCreateAt;
|
|
23
|
+
while (fetched < maxItems) {
|
|
24
|
+
// eslint-disable-next-line no-await-in-loop
|
|
25
|
+
const page = await client_1.Client4.getPropertyFields(groupName, objectType, targetType, targetId, { cursorId, cursorCreateAt });
|
|
26
|
+
fields = fields.concat(page);
|
|
27
|
+
if (page.length === 0) {
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
fetched += page.length;
|
|
31
|
+
const last = page[page.length - 1];
|
|
32
|
+
cursorId = last.id;
|
|
33
|
+
cursorCreateAt = last.create_at;
|
|
34
|
+
}
|
|
35
|
+
dispatch({
|
|
36
|
+
type: properties_1.default.RECEIVED_PROPERTY_FIELDS,
|
|
37
|
+
data: { fields },
|
|
38
|
+
});
|
|
39
|
+
return { data: fields };
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Fetches all system-scoped property values for a given group via the
|
|
44
|
+
* dedicated `/system/values` endpoint, then stores them in Redux.
|
|
45
|
+
*/
|
|
46
|
+
function fetchSystemPropertyValues(groupName) {
|
|
47
|
+
return async (dispatch) => {
|
|
48
|
+
const values = (await client_1.Client4.getSystemPropertyValues(groupName)) ?? [];
|
|
49
|
+
dispatch({
|
|
50
|
+
type: properties_1.default.RECEIVED_PROPERTY_VALUES,
|
|
51
|
+
data: { values },
|
|
52
|
+
});
|
|
53
|
+
return { data: values };
|
|
54
|
+
};
|
|
55
|
+
}
|
package/lib/actions/recaps.d.ts
CHANGED
|
@@ -4,5 +4,8 @@ export declare function createRecap(title: string, channelIds: string[], agentId
|
|
|
4
4
|
export declare function getRecaps(page?: number, perPage?: number): ActionFuncAsync<Recap[]>;
|
|
5
5
|
export declare function getRecap(recapId: string): ActionFuncAsync<Recap>;
|
|
6
6
|
export declare function markRecapAsRead(recapId: string): ActionFuncAsync<Recap>;
|
|
7
|
+
export declare function markRecapsAsViewed(): ActionFuncAsync<{
|
|
8
|
+
recap_ids: string[];
|
|
9
|
+
}>;
|
|
7
10
|
export declare function regenerateRecap(recapId: string): ActionFuncAsync<Recap>;
|
|
8
11
|
export declare function deleteRecap(recapId: string): ActionFuncAsync;
|
package/lib/actions/recaps.js
CHANGED
|
@@ -6,6 +6,7 @@ exports.createRecap = createRecap;
|
|
|
6
6
|
exports.getRecaps = getRecaps;
|
|
7
7
|
exports.getRecap = getRecap;
|
|
8
8
|
exports.markRecapAsRead = markRecapAsRead;
|
|
9
|
+
exports.markRecapsAsViewed = markRecapsAsViewed;
|
|
9
10
|
exports.regenerateRecap = regenerateRecap;
|
|
10
11
|
exports.deleteRecap = deleteRecap;
|
|
11
12
|
const action_types_1 = require("mattermost-redux/action_types");
|
|
@@ -44,6 +45,19 @@ function markRecapAsRead(recapId) {
|
|
|
44
45
|
onFailure: action_types_1.RecapTypes.MARK_RECAP_READ_FAILURE,
|
|
45
46
|
});
|
|
46
47
|
}
|
|
48
|
+
function markRecapsAsViewed() {
|
|
49
|
+
return async (dispatch, getState) => {
|
|
50
|
+
try {
|
|
51
|
+
const data = await client_1.Client4.markRecapsAsViewed();
|
|
52
|
+
return { data };
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
dispatch((0, errors_1.logError)(error));
|
|
56
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
57
|
+
return { error };
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
47
61
|
function regenerateRecap(recapId) {
|
|
48
62
|
return (0, helpers_1.bindClientFunc)({
|
|
49
63
|
clientFunc: () => client_1.Client4.regenerateRecap(recapId),
|
package/lib/actions/teams.d.ts
CHANGED
|
@@ -61,3 +61,4 @@ export declare function invalidateAllEmailInvites(): ActionFuncAsync<import("@ma
|
|
|
61
61
|
export declare function membersMinusGroupMembers(teamID: string, groupIDs: string[], page?: number, perPage?: number): ActionFuncAsync<import("@mattermost/types/groups").UsersWithGroupsAndCount, import("@mattermost/types/store").GlobalState, AnyAction>;
|
|
62
62
|
export declare function getInProductNotices(teamId: string, client: string, clientVersion: string): ActionFuncAsync<import("@mattermost/types/product_notices").ProductNotices, import("@mattermost/types/store").GlobalState, AnyAction>;
|
|
63
63
|
export declare function updateNoticesAsViewed(noticeIds: string[]): ActionFuncAsync<import("@mattermost/types/client4").StatusOK, import("@mattermost/types/store").GlobalState, AnyAction>;
|
|
64
|
+
export declare function markAllInTeamAsRead(userId: string, teamId: string): ActionFuncAsync;
|
package/lib/actions/teams.js
CHANGED
|
@@ -44,6 +44,7 @@ exports.invalidateAllEmailInvites = invalidateAllEmailInvites;
|
|
|
44
44
|
exports.membersMinusGroupMembers = membersMinusGroupMembers;
|
|
45
45
|
exports.getInProductNotices = getInProductNotices;
|
|
46
46
|
exports.updateNoticesAsViewed = updateNoticesAsViewed;
|
|
47
|
+
exports.markAllInTeamAsRead = markAllInTeamAsRead;
|
|
47
48
|
const redux_batched_actions_1 = require("redux-batched-actions");
|
|
48
49
|
const action_types_1 = require("mattermost-redux/action_types");
|
|
49
50
|
const channels_1 = require("mattermost-redux/actions/channels");
|
|
@@ -57,6 +58,7 @@ const common_1 = require("mattermost-redux/selectors/entities/common");
|
|
|
57
58
|
const teams_1 = require("mattermost-redux/selectors/entities/teams");
|
|
58
59
|
const users_2 = require("mattermost-redux/selectors/entities/users");
|
|
59
60
|
const event_emitter_1 = __importDefault(require("mattermost-redux/utils/event_emitter"));
|
|
61
|
+
const threads_1 = require("./threads");
|
|
60
62
|
async function getProfilesAndStatusesForMembers(userIds, dispatch, getState) {
|
|
61
63
|
const state = getState();
|
|
62
64
|
const { currentUserId, profiles, statuses, } = state.entities.users;
|
|
@@ -667,3 +669,19 @@ function updateNoticesAsViewed(noticeIds) {
|
|
|
667
669
|
],
|
|
668
670
|
});
|
|
669
671
|
}
|
|
672
|
+
function markAllInTeamAsRead(userId, teamId) {
|
|
673
|
+
return async (dispatch, getState) => {
|
|
674
|
+
let response;
|
|
675
|
+
try {
|
|
676
|
+
response = await client_1.Client4.markAllInTeamAsRead(userId, teamId);
|
|
677
|
+
}
|
|
678
|
+
catch (error) {
|
|
679
|
+
(0, helpers_1.forceLogoutIfNecessary)(error, dispatch, getState);
|
|
680
|
+
dispatch((0, errors_1.logError)(error));
|
|
681
|
+
return { error };
|
|
682
|
+
}
|
|
683
|
+
dispatch((0, channels_1.markMultipleChannelsAsRead)(response.last_viewed_at_times));
|
|
684
|
+
dispatch((0, threads_1.handleAllMarkedRead)(teamId));
|
|
685
|
+
return { data: response };
|
|
686
|
+
};
|
|
687
|
+
}
|
package/lib/actions/users.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export declare enum ProfilesInChannelSortBy {
|
|
|
25
25
|
export declare function getProfilesInChannel(channelId: string, page: number, perPage?: number, sort?: string, options?: {
|
|
26
26
|
active?: boolean;
|
|
27
27
|
}): ActionFuncAsync<UserProfile[]>;
|
|
28
|
-
export declare function
|
|
28
|
+
export declare function batchGetProfilesInGroupChannel(channelId: string): ActionFuncAsync<Array<Channel['id']>>;
|
|
29
29
|
export declare function getProfilesInGroupChannels(channelsIds: string[]): ActionFuncAsync;
|
|
30
30
|
export declare function getProfilesNotInChannel(teamId: string, channelId: string, groupConstrained: boolean, page: number, perPage?: number, cursorId?: string): ActionFuncAsync<UserProfile[]>;
|
|
31
31
|
export declare function getMe(): ActionFuncAsync<UserProfile>;
|
package/lib/actions/users.js
CHANGED
|
@@ -17,7 +17,7 @@ exports.getProfilesByUsernames = getProfilesByUsernames;
|
|
|
17
17
|
exports.getProfilesInTeam = getProfilesInTeam;
|
|
18
18
|
exports.getProfilesNotInTeam = getProfilesNotInTeam;
|
|
19
19
|
exports.getProfilesInChannel = getProfilesInChannel;
|
|
20
|
-
exports.
|
|
20
|
+
exports.batchGetProfilesInGroupChannel = batchGetProfilesInGroupChannel;
|
|
21
21
|
exports.getProfilesInGroupChannels = getProfilesInGroupChannels;
|
|
22
22
|
exports.getProfilesNotInChannel = getProfilesNotInChannel;
|
|
23
23
|
exports.getMe = getMe;
|
|
@@ -365,16 +365,16 @@ function getProfilesInChannel(channelId, page, perPage = constants_1.General.PRO
|
|
|
365
365
|
return { data: profiles };
|
|
366
366
|
};
|
|
367
367
|
}
|
|
368
|
-
function
|
|
368
|
+
function batchGetProfilesInGroupChannel(channelId) {
|
|
369
369
|
return async (dispatch, getState, { loaders }) => {
|
|
370
|
-
if (!loaders.
|
|
371
|
-
loaders.
|
|
372
|
-
fetchBatch: (channelIds) => dispatch(
|
|
373
|
-
maxBatchSize:
|
|
370
|
+
if (!loaders.profilesInGroupChannelLoader) {
|
|
371
|
+
loaders.profilesInGroupChannelLoader = new data_loader_1.DelayedDataLoader({
|
|
372
|
+
fetchBatch: (channelIds) => dispatch(getProfilesInGroupChannels(channelIds)),
|
|
373
|
+
maxBatchSize: constants_1.General.MAX_GROUP_CHANNELS_FOR_PROFILES,
|
|
374
374
|
wait: missingProfilesWait,
|
|
375
375
|
});
|
|
376
376
|
}
|
|
377
|
-
await loaders.
|
|
377
|
+
await loaders.profilesInGroupChannelLoader.queueAndWait([channelId]);
|
|
378
378
|
return {};
|
|
379
379
|
};
|
|
380
380
|
}
|
package/lib/constants/general.js
CHANGED
|
@@ -48,6 +48,7 @@ const values = {
|
|
|
48
48
|
REMOVE_OTHERS_REACTIONS: 'remove_others_reactions',
|
|
49
49
|
PERMANENT_DELETE_USER: 'permanent_delete_user',
|
|
50
50
|
UPLOAD_FILE: 'upload_file',
|
|
51
|
+
EDIT_FILE_ATTACHMENT: 'edit_file_attachment',
|
|
51
52
|
GET_PUBLIC_LINK: 'get_public_link',
|
|
52
53
|
MANAGE_WEBHOOKS: 'manage_webhooks',
|
|
53
54
|
MANAGE_OTHERS_WEBHOOKS: 'manage_others_webhooks',
|
package/lib/constants/posts.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export declare const PostTypes: {
|
|
|
29
29
|
WRANGLER: PostType;
|
|
30
30
|
GM_CONVERTED_TO_CHANNEL: PostType;
|
|
31
31
|
BURN_ON_READ: PostType;
|
|
32
|
+
SHARED_CHANNEL_STATE: PostType;
|
|
32
33
|
};
|
|
33
34
|
declare const _default: {
|
|
34
35
|
POST_CHUNK_SIZE: number;
|
|
@@ -65,6 +66,7 @@ declare const _default: {
|
|
|
65
66
|
WRANGLER: PostType;
|
|
66
67
|
GM_CONVERTED_TO_CHANNEL: PostType;
|
|
67
68
|
BURN_ON_READ: PostType;
|
|
69
|
+
SHARED_CHANNEL_STATE: PostType;
|
|
68
70
|
};
|
|
69
71
|
MESSAGE_TYPES: {
|
|
70
72
|
POST: string;
|
package/lib/constants/posts.js
CHANGED
|
@@ -46,6 +46,10 @@ declare const Preferences: {
|
|
|
46
46
|
ADVANCED_SYNC_DRAFTS: string;
|
|
47
47
|
CATEGORY_WHATS_NEW_MODAL: string;
|
|
48
48
|
HAS_SEEN_SIDEBAR_WHATS_NEW_MODAL: string;
|
|
49
|
+
CATEGORY_SHORTCUT_ACTIONS: string;
|
|
50
|
+
MARK_ALL_READ_WITHOUT_CONFIRM: string;
|
|
51
|
+
CATEGORY_NEW_FEATURES: string;
|
|
52
|
+
HAS_SEEN_MARK_ALL_READ_FEATURE: string;
|
|
49
53
|
CATEGORY_PERFORMANCE_DEBUGGING: string;
|
|
50
54
|
NAME_DISABLE_CLIENT_PLUGINS: string;
|
|
51
55
|
NAME_DISABLE_TYPING_MESSAGES: string;
|
|
@@ -50,6 +50,10 @@ const Preferences = {
|
|
|
50
50
|
ADVANCED_SYNC_DRAFTS: 'sync_drafts',
|
|
51
51
|
CATEGORY_WHATS_NEW_MODAL: 'whats_new_modal',
|
|
52
52
|
HAS_SEEN_SIDEBAR_WHATS_NEW_MODAL: 'has_seen_sidebar_whats_new_modal',
|
|
53
|
+
CATEGORY_SHORTCUT_ACTIONS: 'shortcut_actions',
|
|
54
|
+
MARK_ALL_READ_WITHOUT_CONFIRM: 'mark_all_read_without_confirm',
|
|
55
|
+
CATEGORY_NEW_FEATURES: 'new_features',
|
|
56
|
+
HAS_SEEN_MARK_ALL_READ_FEATURE: 'mark_all_read_seen',
|
|
53
57
|
CATEGORY_PERFORMANCE_DEBUGGING: 'performance_debugging',
|
|
54
58
|
NAME_DISABLE_CLIENT_PLUGINS: 'disable_client_plugins',
|
|
55
59
|
NAME_DISABLE_TYPING_MESSAGES: 'disable_typing_messages',
|
|
@@ -28,7 +28,7 @@ function fieldsReducer(state = initialFieldsState, action) {
|
|
|
28
28
|
const nextByObjectType = { ...state.byObjectType };
|
|
29
29
|
let changed = false;
|
|
30
30
|
for (const field of fields) {
|
|
31
|
-
if ((0, property_utils_1.isPSAv1PropertyField)(field)
|
|
31
|
+
if ((0, property_utils_1.isPSAv1PropertyField)(field)) {
|
|
32
32
|
continue;
|
|
33
33
|
}
|
|
34
34
|
changed = true;
|
|
@@ -38,16 +38,27 @@ function fieldsReducer(state = initialFieldsState, action) {
|
|
|
38
38
|
if (!nextByObjectType[objectType]) {
|
|
39
39
|
nextByObjectType[objectType] = {};
|
|
40
40
|
}
|
|
41
|
-
else if (nextByObjectType[objectType] ===
|
|
42
|
-
|
|
41
|
+
else if (nextByObjectType[objectType] ===
|
|
42
|
+
state.byObjectType[objectType]) {
|
|
43
|
+
nextByObjectType[objectType] = {
|
|
44
|
+
...nextByObjectType[objectType],
|
|
45
|
+
};
|
|
43
46
|
}
|
|
44
47
|
if (!nextByObjectType[objectType][groupId]) {
|
|
45
48
|
nextByObjectType[objectType][groupId] = {};
|
|
46
49
|
}
|
|
47
|
-
else if (nextByObjectType[objectType][groupId] ===
|
|
48
|
-
|
|
50
|
+
else if (nextByObjectType[objectType][groupId] ===
|
|
51
|
+
state.byObjectType[objectType]?.[groupId]) {
|
|
52
|
+
nextByObjectType[objectType][groupId] = {
|
|
53
|
+
...nextByObjectType[objectType][groupId],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (field.delete_at > 0) {
|
|
57
|
+
Reflect.deleteProperty(nextByObjectType[objectType][groupId], field.id);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
nextByObjectType[objectType][groupId][field.id] = field;
|
|
49
61
|
}
|
|
50
|
-
nextByObjectType[objectType][groupId][field.id] = field;
|
|
51
62
|
}
|
|
52
63
|
if (!changed) {
|
|
53
64
|
return state;
|
|
@@ -66,7 +77,9 @@ function fieldsReducer(state = initialFieldsState, action) {
|
|
|
66
77
|
Reflect.deleteProperty(nextById, fieldId);
|
|
67
78
|
const nextByObjectType = { ...state.byObjectType };
|
|
68
79
|
nextByObjectType[objectType] = { ...nextByObjectType[objectType] };
|
|
69
|
-
nextByObjectType[objectType][groupId] = {
|
|
80
|
+
nextByObjectType[objectType][groupId] = {
|
|
81
|
+
...nextByObjectType[objectType][groupId],
|
|
82
|
+
};
|
|
70
83
|
Reflect.deleteProperty(nextByObjectType[objectType][groupId], fieldId);
|
|
71
84
|
// Clean up empty buckets
|
|
72
85
|
if (Object.keys(nextByObjectType[objectType][groupId]).length === 0) {
|
|
@@ -86,7 +99,7 @@ function fieldsReducer(state = initialFieldsState, action) {
|
|
|
86
99
|
function valuesReducer(state = initialValuesState, action) {
|
|
87
100
|
switch (action.type) {
|
|
88
101
|
case action_types_1.PropertyTypes.RECEIVED_PROPERTY_VALUES: {
|
|
89
|
-
const values = action.data.values;
|
|
102
|
+
const values = action.data.values ?? [];
|
|
90
103
|
if (values.length === 0) {
|
|
91
104
|
return state;
|
|
92
105
|
}
|
|
@@ -21,8 +21,10 @@ export declare function makeGetChannelIdsForCategory(): (state: GlobalState, cat
|
|
|
21
21
|
export declare function makeFilterAndSortChannelsForCategory(): (state: GlobalState, originalChannels: Channel[], category: ChannelCategory) => Channel[];
|
|
22
22
|
export declare function makeGetChannelsByCategory(): (state: GlobalState, teamId: string) => RelationOneToOne<ChannelCategory, Channel[]>;
|
|
23
23
|
export declare function areManagedCategoriesEnabled(state: GlobalState): boolean;
|
|
24
|
+
export declare function isChannelCategorySortingEnabled(state: GlobalState): boolean;
|
|
24
25
|
export declare function getManagedCategoryMappings(state: GlobalState, teamId: string): Record<string, string> | undefined;
|
|
25
26
|
export declare function isChannelInManagedCategory(state: GlobalState, channelId: string): boolean;
|
|
26
27
|
export declare function getChannelManagedCategoryName(state: GlobalState, channelId: string): string | undefined;
|
|
27
28
|
export declare function makeGetCategoriesForTeam(): (state: GlobalState, teamId: string) => ChannelCategory[];
|
|
29
|
+
export declare function makeGetSidebarCategoryNamesForTeam(): (state: GlobalState, teamId: string) => string[];
|
|
28
30
|
export declare function makeGetManagedCategoriesForTeam(): (state: GlobalState, teamId: string) => ChannelCategory[];
|
|
@@ -24,10 +24,12 @@ exports.makeGetChannelIdsForCategory = makeGetChannelIdsForCategory;
|
|
|
24
24
|
exports.makeFilterAndSortChannelsForCategory = makeFilterAndSortChannelsForCategory;
|
|
25
25
|
exports.makeGetChannelsByCategory = makeGetChannelsByCategory;
|
|
26
26
|
exports.areManagedCategoriesEnabled = areManagedCategoriesEnabled;
|
|
27
|
+
exports.isChannelCategorySortingEnabled = isChannelCategorySortingEnabled;
|
|
27
28
|
exports.getManagedCategoryMappings = getManagedCategoryMappings;
|
|
28
29
|
exports.isChannelInManagedCategory = isChannelInManagedCategory;
|
|
29
30
|
exports.getChannelManagedCategoryName = getChannelManagedCategoryName;
|
|
30
31
|
exports.makeGetCategoriesForTeam = makeGetCategoriesForTeam;
|
|
32
|
+
exports.makeGetSidebarCategoryNamesForTeam = makeGetSidebarCategoryNamesForTeam;
|
|
31
33
|
exports.makeGetManagedCategoriesForTeam = makeGetManagedCategoriesForTeam;
|
|
32
34
|
const shallow_equals_1 = __importDefault(require("shallow-equals"));
|
|
33
35
|
const channel_categories_1 = require("@mattermost/types/channel_categories");
|
|
@@ -348,6 +350,9 @@ function isUnreadChannel(channelId, messageCounts, members, crtEnabled) {
|
|
|
348
350
|
function areManagedCategoriesEnabled(state) {
|
|
349
351
|
return (0, general_1.getConfig)(state).FeatureFlagManagedChannelCategories === 'true';
|
|
350
352
|
}
|
|
353
|
+
function isChannelCategorySortingEnabled(state) {
|
|
354
|
+
return (0, general_1.getConfig)(state).EnableChannelCategorySorting === 'true';
|
|
355
|
+
}
|
|
351
356
|
function getManagedCategoryMappings(state, teamId) {
|
|
352
357
|
if (!areManagedCategoriesEnabled(state)) {
|
|
353
358
|
return undefined;
|
|
@@ -396,6 +401,17 @@ function makeGetCategoriesForTeam() {
|
|
|
396
401
|
];
|
|
397
402
|
});
|
|
398
403
|
}
|
|
404
|
+
function makeGetSidebarCategoryNamesForTeam() {
|
|
405
|
+
const getCategoriesForTeam = makeGetCategoriesForTeam();
|
|
406
|
+
return (0, create_selector_1.createSelector)('makeGetSidebarCategoryNamesForTeam', (state, teamId) => getCategoriesForTeam(state, teamId), (state) => (0, i18n_1.getCurrentUserLocale)(state), (categories, locale) => {
|
|
407
|
+
const names = categories.
|
|
408
|
+
filter((c) => c.type === channel_categories_2.CategoryTypes.CUSTOM || c.type === channel_categories_2.CategoryTypes.MANAGED).
|
|
409
|
+
map((c) => c.display_name);
|
|
410
|
+
const unique = [...new Set(names)];
|
|
411
|
+
unique.sort((a, b) => a.localeCompare(b, locale, { numeric: true }));
|
|
412
|
+
return unique;
|
|
413
|
+
});
|
|
414
|
+
}
|
|
399
415
|
function makeGetManagedCategoriesForTeam() {
|
|
400
416
|
return (0, create_selector_1.createSelector)('makeGetManagedCategoriesForTeam', (state, teamId) => getManagedCategoryMappings(state, teamId), (state) => (0, users_1.getCurrentUserId)(state), (_, teamId) => teamId, (mappings, currentUserId, teamId) => {
|
|
401
417
|
if (!mappings || Object.keys(mappings).length === 0) {
|
|
@@ -9,6 +9,31 @@ export declare function getConfig(state: GlobalState): Partial<ClientConfig>;
|
|
|
9
9
|
export declare function getFeatureFlagValue(state: GlobalState, key: keyof FeatureFlags): string | undefined;
|
|
10
10
|
export declare function isCustomProfileAttributesEnabled(state: GlobalState): boolean;
|
|
11
11
|
export declare function isPermissionPoliciesEnabled(state: GlobalState): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Whether channel-scope policies may carry permission-rule actions
|
|
14
|
+
* (file upload/download) — i.e. whether the Channel Settings →
|
|
15
|
+
* Permissions Policy tab should be exposed.
|
|
16
|
+
*
|
|
17
|
+
* The sub-flag `ChannelPermissionPolicies` AND the umbrella
|
|
18
|
+
* `PermissionPolicies` must BOTH be on. Mirrors the server-side
|
|
19
|
+
* `FeatureFlags.IsChannelPermissionPoliciesEnabled()` helper so the
|
|
20
|
+
* dependency direction is consistent across the wire. Centralizing
|
|
21
|
+
* the check here means every consumer (settings tab, save buttons,
|
|
22
|
+
* etc.) automatically picks up future changes to the dependency.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isChannelPermissionPoliciesEnabled(state: GlobalState): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Whether the "Simulate access" preview UX should be exposed
|
|
27
|
+
* (System Console policy editor + Channel Settings tab).
|
|
28
|
+
*
|
|
29
|
+
* The sub-flag `PolicySimulation` AND the umbrella
|
|
30
|
+
* `PermissionPolicies` must BOTH be on. Mirrors the server-side
|
|
31
|
+
* `FeatureFlags.IsPolicySimulationEnabled()` helper. The backing
|
|
32
|
+
* `/cel/simulate_users` endpoint returns 501 when this is off, so
|
|
33
|
+
* hiding the entry points here also prevents users from seeing an
|
|
34
|
+
* "Evaluating…" button that can never resolve.
|
|
35
|
+
*/
|
|
36
|
+
export declare function isPolicySimulationEnabled(state: GlobalState): boolean;
|
|
12
37
|
export type PasswordConfig = {
|
|
13
38
|
minimumLength: number;
|
|
14
39
|
requireLowercase: boolean;
|
|
@@ -18,6 +43,7 @@ export type PasswordConfig = {
|
|
|
18
43
|
};
|
|
19
44
|
export declare const getPasswordConfig: (state: GlobalState) => PasswordConfig;
|
|
20
45
|
export declare function getLicense(state: GlobalState): ClientLicense;
|
|
46
|
+
export declare function isFreeEdition(state: GlobalState): boolean;
|
|
21
47
|
export declare const isCloudLicense: (state: GlobalState) => boolean;
|
|
22
48
|
export declare function isCompatibleWithJoinViewTeamPermissions(state: GlobalState): boolean;
|
|
23
49
|
export declare const canUploadFilesOnMobile: (a: GlobalState) => boolean;
|
|
@@ -7,7 +7,10 @@ exports.getConfig = getConfig;
|
|
|
7
7
|
exports.getFeatureFlagValue = getFeatureFlagValue;
|
|
8
8
|
exports.isCustomProfileAttributesEnabled = isCustomProfileAttributesEnabled;
|
|
9
9
|
exports.isPermissionPoliciesEnabled = isPermissionPoliciesEnabled;
|
|
10
|
+
exports.isChannelPermissionPoliciesEnabled = isChannelPermissionPoliciesEnabled;
|
|
11
|
+
exports.isPolicySimulationEnabled = isPolicySimulationEnabled;
|
|
10
12
|
exports.getLicense = getLicense;
|
|
13
|
+
exports.isFreeEdition = isFreeEdition;
|
|
11
14
|
exports.isCompatibleWithJoinViewTeamPermissions = isCompatibleWithJoinViewTeamPermissions;
|
|
12
15
|
exports.getFirstAdminVisitMarketplaceStatus = getFirstAdminVisitMarketplaceStatus;
|
|
13
16
|
exports.getFirstAdminSetupComplete = getFirstAdminSetupComplete;
|
|
@@ -34,6 +37,37 @@ function isCustomProfileAttributesEnabled(state) {
|
|
|
34
37
|
function isPermissionPoliciesEnabled(state) {
|
|
35
38
|
return getConfig(state).FeatureFlagPermissionPolicies === 'true';
|
|
36
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Whether channel-scope policies may carry permission-rule actions
|
|
42
|
+
* (file upload/download) — i.e. whether the Channel Settings →
|
|
43
|
+
* Permissions Policy tab should be exposed.
|
|
44
|
+
*
|
|
45
|
+
* The sub-flag `ChannelPermissionPolicies` AND the umbrella
|
|
46
|
+
* `PermissionPolicies` must BOTH be on. Mirrors the server-side
|
|
47
|
+
* `FeatureFlags.IsChannelPermissionPoliciesEnabled()` helper so the
|
|
48
|
+
* dependency direction is consistent across the wire. Centralizing
|
|
49
|
+
* the check here means every consumer (settings tab, save buttons,
|
|
50
|
+
* etc.) automatically picks up future changes to the dependency.
|
|
51
|
+
*/
|
|
52
|
+
function isChannelPermissionPoliciesEnabled(state) {
|
|
53
|
+
return isPermissionPoliciesEnabled(state) &&
|
|
54
|
+
getConfig(state).FeatureFlagChannelPermissionPolicies === 'true';
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Whether the "Simulate access" preview UX should be exposed
|
|
58
|
+
* (System Console policy editor + Channel Settings tab).
|
|
59
|
+
*
|
|
60
|
+
* The sub-flag `PolicySimulation` AND the umbrella
|
|
61
|
+
* `PermissionPolicies` must BOTH be on. Mirrors the server-side
|
|
62
|
+
* `FeatureFlags.IsPolicySimulationEnabled()` helper. The backing
|
|
63
|
+
* `/cel/simulate_users` endpoint returns 501 when this is off, so
|
|
64
|
+
* hiding the entry points here also prevents users from seeing an
|
|
65
|
+
* "Evaluating…" button that can never resolve.
|
|
66
|
+
*/
|
|
67
|
+
function isPolicySimulationEnabled(state) {
|
|
68
|
+
return isPermissionPoliciesEnabled(state) &&
|
|
69
|
+
getConfig(state).FeatureFlagPolicySimulation === 'true';
|
|
70
|
+
}
|
|
37
71
|
exports.getPasswordConfig = (0, create_selector_1.createSelector)('getPasswordConfig', getConfig, (config) => {
|
|
38
72
|
return {
|
|
39
73
|
minimumLength: parseInt(config.PasswordMinimumLength, 10),
|
|
@@ -46,6 +80,10 @@ exports.getPasswordConfig = (0, create_selector_1.createSelector)('getPasswordCo
|
|
|
46
80
|
function getLicense(state) {
|
|
47
81
|
return state.entities.general.license;
|
|
48
82
|
}
|
|
83
|
+
function isFreeEdition(state) {
|
|
84
|
+
const license = getLicense(state);
|
|
85
|
+
return license.IsLicensed !== 'true' || license.SkuShortName === constants_1.General.SKUEntry;
|
|
86
|
+
}
|
|
49
87
|
exports.isCloudLicense = (0, create_selector_1.createSelector)('isCloudLicense', getLicense, (license) => license?.Cloud === 'true');
|
|
50
88
|
function isCompatibleWithJoinViewTeamPermissions(state) {
|
|
51
89
|
const version = state.entities.general.serverVersion;
|
|
@@ -9,3 +9,13 @@ export declare const getCompletedRecaps: import("mattermost-redux/selectors/crea
|
|
|
9
9
|
export declare const getPendingRecaps: import("mattermost-redux/selectors/create_selector").OutputSelector<GlobalState, Recap[], (res: Recap[]) => Recap[]>;
|
|
10
10
|
export declare const getUnreadRecaps: import("mattermost-redux/selectors/create_selector").OutputSelector<GlobalState, Recap[], (res: Recap[]) => Recap[]>;
|
|
11
11
|
export declare const getReadRecaps: import("mattermost-redux/selectors/create_selector").OutputSelector<GlobalState, Recap[], (res: Recap[]) => Recap[]>;
|
|
12
|
+
export declare const getUnreadFinishedRecapsBadge: import("mattermost-redux/selectors/create_selector").OutputSelector<GlobalState, {
|
|
13
|
+
count: number;
|
|
14
|
+
hasFailed: boolean;
|
|
15
|
+
}, (res: {
|
|
16
|
+
byId: Record<string, Recap>;
|
|
17
|
+
allIds: string[];
|
|
18
|
+
}) => {
|
|
19
|
+
count: number;
|
|
20
|
+
hasFailed: boolean;
|
|
21
|
+
}>;
|
|
@@ -2,7 +2,7 @@
|
|
|
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.getReadRecaps = exports.getUnreadRecaps = exports.getPendingRecaps = exports.getCompletedRecaps = exports.getSortedRecaps = exports.getRecapsByStatus = void 0;
|
|
5
|
+
exports.getUnreadFinishedRecapsBadge = exports.getReadRecaps = exports.getUnreadRecaps = exports.getPendingRecaps = exports.getCompletedRecaps = exports.getSortedRecaps = exports.getRecapsByStatus = void 0;
|
|
6
6
|
exports.getAllRecaps = getAllRecaps;
|
|
7
7
|
exports.getRecap = getRecap;
|
|
8
8
|
const recaps_1 = require("@mattermost/types/recaps");
|
|
@@ -32,3 +32,22 @@ exports.getUnreadRecaps = (0, create_selector_1.createSelector)('getUnreadRecaps
|
|
|
32
32
|
exports.getReadRecaps = (0, create_selector_1.createSelector)('getReadRecaps', getAllRecaps, (recaps) => {
|
|
33
33
|
return recaps.filter((recap) => recap.read_at > 0).sort((a, b) => b.read_at - a.read_at);
|
|
34
34
|
});
|
|
35
|
+
const getRecapsSlice = (state) => state.entities.recaps;
|
|
36
|
+
exports.getUnreadFinishedRecapsBadge = (0, create_selector_1.createSelector)('getUnreadFinishedRecapsBadge', getRecapsSlice, ({ byId, allIds }) => {
|
|
37
|
+
let count = 0;
|
|
38
|
+
let hasFailed = false;
|
|
39
|
+
for (const id of allIds) {
|
|
40
|
+
const recap = byId[id];
|
|
41
|
+
if (!recap || recap.viewed_at !== 0) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (recap.status === recaps_1.RecapStatus.COMPLETED) {
|
|
45
|
+
count++;
|
|
46
|
+
}
|
|
47
|
+
else if (recap.status === recaps_1.RecapStatus.FAILED) {
|
|
48
|
+
count++;
|
|
49
|
+
hasFailed = true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return { count, hasFailed };
|
|
53
|
+
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { GlobalState } from '@mattermost/types/store';
|
|
2
2
|
export declare function getReportAProblemLink(state: GlobalState): string;
|
|
3
|
+
export declare const getDefaultReportAProblemMailtoLink: import("mattermost-redux/selectors/create_selector").OutputSelector<GlobalState, string, (res1: string, res2: string, res3: string | undefined, res4: string | undefined) => string>;
|
|
3
4
|
export declare const getSystemInfoMailtoLink: import("mattermost-redux/selectors/create_selector").OutputParametricSelector<GlobalState, string | undefined, string, (res1: string, res2: string, res3: string | undefined, res4: string | undefined, res5: string | undefined, res6: string | undefined) => string>;
|
|
@@ -2,13 +2,14 @@
|
|
|
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.getSystemInfoMailtoLink = void 0;
|
|
5
|
+
exports.getSystemInfoMailtoLink = exports.getDefaultReportAProblemMailtoLink = void 0;
|
|
6
6
|
exports.getReportAProblemLink = getReportAProblemLink;
|
|
7
7
|
const create_selector_1 = require("mattermost-redux/selectors/create_selector");
|
|
8
8
|
const browser_info_1 = require("mattermost-redux/utils/browser_info");
|
|
9
9
|
const general_1 = require("./general");
|
|
10
10
|
const teams_1 = require("./teams");
|
|
11
11
|
const users_1 = require("./users");
|
|
12
|
+
const MATTERMOST_REPORT_PROBLEM_EMAIL = 'reportaproblem@mattermost.com';
|
|
12
13
|
function getReportAProblemLink(state) {
|
|
13
14
|
const config = (0, general_1.getConfig)(state);
|
|
14
15
|
const type = config.ReportAProblemType;
|
|
@@ -21,15 +22,41 @@ function getReportAProblemLink(state) {
|
|
|
21
22
|
}
|
|
22
23
|
// falls through
|
|
23
24
|
case 'default': {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return 'https://mattermost.com/pl/report_a_problem_licensed';
|
|
25
|
+
if (!(0, general_1.isFreeEdition)(state)) {
|
|
26
|
+
return (0, exports.getDefaultReportAProblemMailtoLink)(state);
|
|
27
27
|
}
|
|
28
28
|
return 'https://mattermost.com/pl/report_a_problem_unlicensed';
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
return '';
|
|
32
32
|
}
|
|
33
|
+
exports.getDefaultReportAProblemMailtoLink = (0, create_selector_1.createSelector)('getDefaultReportAProblemMailtoLink', users_1.getCurrentUserId, teams_1.getCurrentTeamId, (state) => (0, general_1.getConfig)(state).Version, (state) => (0, general_1.getConfig)(state).BuildNumber, (currentUserId, currentTeamId, version, buildNumber) => {
|
|
34
|
+
const { browser, browserVersion } = (0, browser_info_1.getBrowserInfo)();
|
|
35
|
+
const platformName = (0, browser_info_1.getPlatformInfo)();
|
|
36
|
+
let appLine = '';
|
|
37
|
+
let logsInstructions = '';
|
|
38
|
+
if ((0, browser_info_1.isDesktopApp)()) {
|
|
39
|
+
appLine = `Desktop Version: ${(0, browser_info_1.getDesktopVersion)()}`;
|
|
40
|
+
logsInstructions = 'desktop app logs (https://support.mattermost.com/hc/en-us/articles/37269786544916)';
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
appLine = `Browser: ${browser} ${browserVersion}`;
|
|
44
|
+
logsInstructions = 'browser console logs (https://support.mattermost.com/hc/en-us/articles/35971622382484)';
|
|
45
|
+
}
|
|
46
|
+
const subject = 'Problem with Mattermost app';
|
|
47
|
+
const body = `Please share a description of the problem with reproduction steps:
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
You may also attach any relevant screenshots and ${logsInstructions}, if applicable:
|
|
51
|
+
|
|
52
|
+
App metadata:
|
|
53
|
+
- Current User Id: ${currentUserId}
|
|
54
|
+
- Current Team Id: ${currentTeamId}
|
|
55
|
+
- Server Version: ${version} (Build ${buildNumber})
|
|
56
|
+
- App Platform: ${platformName}
|
|
57
|
+
- ${appLine}`.trim();
|
|
58
|
+
return `mailto:${MATTERMOST_REPORT_PROBLEM_EMAIL}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
|
59
|
+
});
|
|
33
60
|
exports.getSystemInfoMailtoLink = (0, create_selector_1.createSelector)('getSystemInfoMailtoLink', users_1.getCurrentUserId, teams_1.getCurrentTeamId, (state) => (0, general_1.getConfig)(state).Version, (state) => (0, general_1.getConfig)(state).BuildNumber, (state) => (0, general_1.getConfig)(state).SiteName, (state, supportEmail) => supportEmail, (currentUserId, currentTeamId, version, buildNumber, siteName, supportEmail) => {
|
|
34
61
|
const { browser, browserVersion } = (0, browser_info_1.getBrowserInfo)();
|
|
35
62
|
const platformName = (0, browser_info_1.getPlatformInfo)();
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
// See LICENSE.txt for license information.
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.getBrowserInfo = getBrowserInfo;
|
|
6
|
+
exports.isDesktopApp = isDesktopApp;
|
|
7
|
+
exports.getDesktopVersion = getDesktopVersion;
|
|
6
8
|
exports.getPlatformInfo = getPlatformInfo;
|
|
7
9
|
function getBrowserInfo() {
|
|
8
10
|
const userAgent = window.navigator.userAgent.toLowerCase();
|
|
@@ -63,6 +65,15 @@ function getBrowserInfo() {
|
|
|
63
65
|
}
|
|
64
66
|
return { browser, browserVersion };
|
|
65
67
|
}
|
|
68
|
+
function isDesktopApp() {
|
|
69
|
+
return window.navigator.userAgent.indexOf('Mattermost') !== -1 && window.navigator.userAgent.indexOf('Electron') !== -1;
|
|
70
|
+
}
|
|
71
|
+
function getDesktopVersion() {
|
|
72
|
+
// use if the value window.desktop.version is not set yet
|
|
73
|
+
const regex = /Mattermost\/(\d+\.\d+\.\d+)/gm;
|
|
74
|
+
const match = regex.exec(window.navigator.appVersion)?.[1] || '';
|
|
75
|
+
return match;
|
|
76
|
+
}
|
|
66
77
|
function getPlatformInfo() {
|
|
67
78
|
// Casting to undefined in case it is deprecated in any browser
|
|
68
79
|
const platform = window.navigator.platform;
|
|
@@ -72,9 +72,11 @@ function validateDateTimeValue(value, elem) {
|
|
|
72
72
|
defaultMessage: 'DateTime field must be in YYYY-MM-DDTHH:mm:ssZ or YYYY-MM-DDTHH:mm:ss+HH:MM format',
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
|
-
// Range validation against min_date / max_date
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
// Range validation against min_date / max_date (datetime_config takes precedence over legacy fields)
|
|
76
|
+
const effectiveMinDate = elem.datetime_config?.min_date ?? elem.min_date;
|
|
77
|
+
const effectiveMaxDate = elem.datetime_config?.max_date ?? elem.max_date;
|
|
78
|
+
if (effectiveMinDate) {
|
|
79
|
+
const minDate = resolveBoundToDate(effectiveMinDate);
|
|
78
80
|
if (minDate && parsedDate < minDate) {
|
|
79
81
|
return (0, react_intl_1.defineMessage)({
|
|
80
82
|
id: 'interactive_dialog.error.before_min_date',
|
|
@@ -82,8 +84,8 @@ function validateDateTimeValue(value, elem) {
|
|
|
82
84
|
});
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
|
-
if (
|
|
86
|
-
const maxDate = resolveBoundToDate(
|
|
87
|
+
if (effectiveMaxDate) {
|
|
88
|
+
const maxDate = resolveBoundToDate(effectiveMaxDate);
|
|
87
89
|
if (maxDate && parsedDate > maxDate) {
|
|
88
90
|
return (0, react_intl_1.defineMessage)({
|
|
89
91
|
id: 'interactive_dialog.error.after_max_date',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mattermost-redux",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.8.0-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.8.0-0",
|
|
43
|
+
"@mattermost/types": "11.8.0-0",
|
|
44
44
|
"@redux-devtools/extension": "3.3.0",
|
|
45
45
|
"lodash": "^4.17.21",
|
|
46
46
|
"moment-timezone": "^0.5.38",
|