From 86aad9d0a5f8d880a53d187cd0a3a7bfe3ac0e0a Mon Sep 17 00:00:00 2001 From: Harrison Healey Date: Tue, 4 Feb 2025 17:26:46 -0500 Subject: [PATCH] Add platform/mattermost-redux package for publishing (#30020) * Replace key-mirror with mattermost-redux/utils/key_mirror At some point, we made our own version for mattermost-redux with proper type definitions but we seem to have forgotten to use that everywhere in the web app. * Remove Rudder reference from mattermost-redux * Remove Giphy API from mattermost-redux * Remove mattermost-webapp refernces from Client and Types packages * Create platform/mattermost-redux without moving its source files * Don't build mattermost-redux automatically * Copy changes to package.json from platform/mattermost-redux to other packages The changes to the typesVersions and exports fields are to make it easier for tooling to know to make it so that importing a folder imports the index file inside that folder since that's not standard to all CommonJS packages. The added type field is just a good pracice. * Explicitly type re-exported selectors For some reason, the types generated by the previous version of this didn't work when mattermost-redux was built as a standalone package. Explicitly typing these is a bit more verbose, but it fixes things. * Fix import loop in selectors introduced by last commit * Update package versions to 10.6.0 * Add explicit dependencies to mattermost-redux package * Remove check and run scripts from mattermost-redux package * Revert changes to NOTICE.txt --- webapp/channels/package.json | 3 +- .../components/gif_picker_items.tsx | 4 +- .../src/components/gif_picker/selectors.ts | 22 +++++++ .../src/components/root/root.test.tsx | 2 +- webapp/channels/src/components/root/root.tsx | 2 +- .../src/action_types/scheudled_posts.ts | 2 +- .../src/selectors/create_selector/index.d.ts | 2 - .../src/selectors/entities/channels.ts | 12 ++-- .../src/selectors/entities/general.ts | 15 ----- .../src/selectors/entities/roles.ts | 18 +++--- .../src/selectors/entities/users.ts | 11 ++-- .../src/types/external/key-mirror.d.ts | 8 --- webapp/channels/src/utils/constants.tsx | 2 +- .../src/client => utils}/rudder.ts | 0 webapp/package-lock.json | 47 +++++++++++---- webapp/package.json | 1 + webapp/platform/client/package.json | 3 +- webapp/platform/client/src/client4.ts | 17 ++---- webapp/platform/mattermost-redux/README.md | 11 ++++ webapp/platform/mattermost-redux/package.json | 59 +++++++++++++++++++ .../platform/mattermost-redux/tsconfig.json | 32 ++++++++++ webapp/platform/types/package.json | 6 +- webapp/platform/types/src/posts.ts | 4 +- 23 files changed, 205 insertions(+), 78 deletions(-) create mode 100644 webapp/channels/src/components/gif_picker/selectors.ts delete mode 100644 webapp/channels/src/types/external/key-mirror.d.ts rename webapp/channels/src/{packages/mattermost-redux/src/client => utils}/rudder.ts (100%) create mode 100644 webapp/platform/mattermost-redux/README.md create mode 100644 webapp/platform/mattermost-redux/package.json create mode 100644 webapp/platform/mattermost-redux/tsconfig.json diff --git a/webapp/channels/package.json b/webapp/channels/package.json index dbf705ec82..8426757577 100644 --- a/webapp/channels/package.json +++ b/webapp/channels/package.json @@ -3,7 +3,7 @@ "browser": { "./client/web_client.jsx": "./client/browser_web_client.jsx" }, - "version": "9.3.0", + "version": "10.6.0", "private": true, "dependencies": { "@floating-ui/react": "0.26.28", @@ -46,7 +46,6 @@ "inobounce": "0.2.1", "ipaddr.js": "2.1.0", "katex": "0.16.10", - "key-mirror": "1.0.1", "localforage": "1.10.0", "localforage-observable": "2.1.1", "lodash": "4.17.21", diff --git a/webapp/channels/src/components/gif_picker/components/gif_picker_items.tsx b/webapp/channels/src/components/gif_picker/components/gif_picker_items.tsx index 355b0a2fa0..27abb818fc 100644 --- a/webapp/channels/src/components/gif_picker/components/gif_picker_items.tsx +++ b/webapp/channels/src/components/gif_picker/components/gif_picker_items.tsx @@ -7,11 +7,11 @@ import {Grid} from '@giphy/react-components'; import React, {memo, useCallback} from 'react'; import {useSelector} from 'react-redux'; -import {getGiphyFetchInstance} from 'mattermost-redux/selectors/entities/general'; - import NoResultsIndicator from 'components/no_results_indicator'; import {NoResultsVariant} from 'components/no_results_indicator/types'; +import {getGiphyFetchInstance} from '../selectors'; + const GUTTER_BETWEEN_GIFS = 8; const NUM_OF_GIFS_COLUMNS = 2; diff --git a/webapp/channels/src/components/gif_picker/selectors.ts b/webapp/channels/src/components/gif_picker/selectors.ts new file mode 100644 index 0000000000..63a13891c7 --- /dev/null +++ b/webapp/channels/src/components/gif_picker/selectors.ts @@ -0,0 +1,22 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {GiphyFetch} from '@giphy/js-fetch-api'; + +import {createSelector} from 'mattermost-redux/selectors/create_selector'; +import {getConfig} from 'mattermost-redux/selectors/entities/general'; + +import type {GlobalState} from 'types/store'; + +export const getGiphyFetchInstance: (state: GlobalState) => GiphyFetch | null = createSelector( + 'getGiphyFetchInstance', + (state) => getConfig(state).GiphySdkKey, + (giphySdkKey) => { + if (giphySdkKey) { + const giphyFetch = new GiphyFetch(giphySdkKey); + return giphyFetch; + } + + return null; + }, +); diff --git a/webapp/channels/src/components/root/root.test.tsx b/webapp/channels/src/components/root/root.test.tsx index ddd79cb761..14eef3eaf7 100644 --- a/webapp/channels/src/components/root/root.test.tsx +++ b/webapp/channels/src/components/root/root.test.tsx @@ -21,7 +21,7 @@ import {handleLoginLogoutSignal, redirectToOnboardingOrDefaultTeam} from './acti import type {Props} from './root'; import Root, {doesRouteBelongToTeamControllerRoutes} from './root'; -jest.mock('mattermost-redux/client/rudder', () => ({ +jest.mock('utils/rudder', () => ({ rudderAnalytics: { identify: jest.fn(), load: jest.fn(), diff --git a/webapp/channels/src/components/root/root.tsx b/webapp/channels/src/components/root/root.tsx index fac84e7469..9101560aed 100644 --- a/webapp/channels/src/components/root/root.tsx +++ b/webapp/channels/src/components/root/root.tsx @@ -12,7 +12,6 @@ import {ServiceEnvironment} from '@mattermost/types/config'; import {setSystemEmojis} from 'mattermost-redux/actions/emojis'; import {setUrl} from 'mattermost-redux/actions/general'; import {Client4} from 'mattermost-redux/client'; -import {rudderAnalytics, RudderTelemetryHandler} from 'mattermost-redux/client/rudder'; import {Preferences} from 'mattermost-redux/constants'; import {measurePageLoadTelemetry, temporarilySetPageLoadContext, trackEvent, trackSelectorMetrics} from 'actions/telemetry_actions.jsx'; @@ -36,6 +35,7 @@ import {PageLoadContext, SCHEDULED_POST_URL_SUFFIX} from 'utils/constants'; import DesktopApp from 'utils/desktop_api'; import {EmojiIndicesByAlias} from 'utils/emoji'; import {TEAM_NAME_PATH_PATTERN} from 'utils/path'; +import {rudderAnalytics, RudderTelemetryHandler} from 'utils/rudder'; import {getSiteURL} from 'utils/url'; import {isAndroidWeb, isChromebook, isDesktopApp, isIosWeb} from 'utils/user_agent'; import {applyTheme, isTextDroppableEvent} from 'utils/utils'; diff --git a/webapp/channels/src/packages/mattermost-redux/src/action_types/scheudled_posts.ts b/webapp/channels/src/packages/mattermost-redux/src/action_types/scheudled_posts.ts index 5999b0f316..a54f9cff39 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/action_types/scheudled_posts.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/action_types/scheudled_posts.ts @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import keyMirror from 'key-mirror'; +import keyMirror from 'mattermost-redux/utils/key_mirror'; export default keyMirror({ SCHEDULED_POSTS_RECEIVED: null, diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/create_selector/index.d.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/create_selector/index.d.ts index 495edb28d1..3722165832 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/create_selector/index.d.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/create_selector/index.d.ts @@ -5,8 +5,6 @@ /* eslint-disable @typescript-eslint/ban-types */ /* eslint-disable @typescript-eslint/no-explicit-any */ -export as namespace Reselect; - export type Selector = (state: S) => R; export type OutputSelector = Selector & { diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/channels.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/channels.ts index 551e1e5b61..0cbd74f297 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/channels.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/channels.ts @@ -27,10 +27,10 @@ import {createSelector} from 'mattermost-redux/selectors/create_selector'; import {getDataRetentionCustomPolicy} from 'mattermost-redux/selectors/entities/admin'; import {getCategoryInTeamByType} from 'mattermost-redux/selectors/entities/channel_categories'; import { - getCurrentChannelId, + getCurrentChannelId as getCurrentChannelIdInternal, getCurrentUser, - getMyChannelMemberships, - getMyCurrentChannelMembership, + getMyChannelMemberships as getMyChannelMembershipsInternal, + getMyCurrentChannelMembership as getMyCurrentChannelMembershipInternal, getUsers, } from 'mattermost-redux/selectors/entities/common'; import { @@ -69,7 +69,11 @@ import {createIdsSelector} from 'mattermost-redux/utils/helpers'; import {isPostPriorityEnabled} from './posts'; import {getThreadCounts, getThreadCountsIncludingDirect} from './threads'; -export {getCurrentChannelId, getMyChannelMemberships, getMyCurrentChannelMembership}; +// Re-define these types to ensure that these are typed correctly when mattermost-redux is published +export const getCurrentChannelId: (state: GlobalState) => string = getCurrentChannelIdInternal; +export const getMyChannelMemberships: (state: GlobalState) => RelationOneToOne = getMyChannelMembershipsInternal; +export const getMyCurrentChannelMembership: (state: GlobalState) => ChannelMembership | undefined = getMyCurrentChannelMembershipInternal; + export function getAllChannels(state: GlobalState): IDMappedObjects { return state.entities.channels.channels; } diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/general.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/general.ts index b0ac14593c..fef303dce2 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/general.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/general.ts @@ -1,8 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {GiphyFetch} from '@giphy/js-fetch-api'; - import type {ClientConfig, FeatureFlags, ClientLicense} from '@mattermost/types/config'; import type {UserPropertyField} from '@mattermost/types/properties'; import type {GlobalState} from '@mattermost/types/store'; @@ -134,19 +132,6 @@ export const isMarketplaceEnabled: (state: GlobalState) => boolean = createSelec }, ); -export const getGiphyFetchInstance: (state: GlobalState) => GiphyFetch | null = createSelector( - 'getGiphyFetchInstance', - (state) => getConfig(state).GiphySdkKey, - (giphySdkKey) => { - if (giphySdkKey) { - const giphyFetch = new GiphyFetch(giphySdkKey); - return giphyFetch; - } - - return null; - }, -); - export const getUsersStatusAndProfileFetchingPollInterval: (state: GlobalState) => number | null = createSelector( 'getUsersStatusAndProfileFetchingPollInterval', getConfig, diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/roles.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/roles.ts index 5a0f8c2e95..ab66dd382e 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/roles.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/roles.ts @@ -7,18 +7,22 @@ import type {GlobalState} from '@mattermost/types/store'; import {General, Permissions} from 'mattermost-redux/constants'; import {createSelector} from 'mattermost-redux/selectors/create_selector'; -import {getCurrentChannelId} from 'mattermost-redux/selectors/entities/common'; +import {getCurrentChannelId, getCurrentUserId} from 'mattermost-redux/selectors/entities/common'; +import type {PermissionsOptions} from 'mattermost-redux/selectors/entities/roles_helpers'; import { - getMySystemPermissions, - getMySystemRoles, + getMySystemPermissions as getMySystemPermissionsInternal, + getMySystemRoles as getMySystemRolesInternal, getPermissionsForRoles, - getRoles, - haveISystemPermission, + getRoles as getRolesInternal, + haveISystemPermission as haveISystemPermissionInternal, } from 'mattermost-redux/selectors/entities/roles_helpers'; import {getTeamMemberships, getCurrentTeamId} from 'mattermost-redux/selectors/entities/teams'; -import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; -export {getMySystemPermissions, getMySystemRoles, getRoles, haveISystemPermission}; +// Re-define these types to ensure that these are typed correctly when mattermost-redux is published +export const getMySystemPermissions: (state: GlobalState) => Set = getMySystemPermissionsInternal; +export const getMySystemRoles: (state: GlobalState) => Set = getMySystemRolesInternal; +export const getRoles: (state: GlobalState) => Record = getRolesInternal; +export const haveISystemPermission: (state: GlobalState, options: PermissionsOptions) => boolean = haveISystemPermissionInternal; export const getGroupMemberships: (state: GlobalState) => Record = createSelector( 'getGroupMemberships', diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts index 69de654f67..74f57c6862 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts @@ -17,10 +17,10 @@ import {General} from 'mattermost-redux/constants'; import {createSelector} from 'mattermost-redux/selectors/create_selector'; import { getCurrentChannelId, - getCurrentUser, - getCurrentUserId, + getCurrentUser as getCurrentUserInternal, + getCurrentUserId as getCurrentUserIdInternal, getMyCurrentChannelMembership, - getUsers, + getUsers as getUsersInternal, getMembersInTeam, getMembersInChannel, } from 'mattermost-redux/selectors/entities/common'; @@ -39,7 +39,10 @@ import { applyRolesFilters, } from 'mattermost-redux/utils/user_utils'; -export {getCurrentUser, getCurrentUserId, getUsers}; +// Re-define these types to ensure that these are typed correctly when mattermost-redux is published +export const getCurrentUser: (state: GlobalState) => UserProfile = getCurrentUserInternal; +export const getCurrentUserId: (state: GlobalState) => string = getCurrentUserIdInternal; +export const getUsers: (state: GlobalState) => IDMappedObjects = getUsersInternal; export type Filters = { role?: string; diff --git a/webapp/channels/src/types/external/key-mirror.d.ts b/webapp/channels/src/types/external/key-mirror.d.ts deleted file mode 100644 index e7681067cb..0000000000 --- a/webapp/channels/src/types/external/key-mirror.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -declare module 'key-mirror' { - function keyMirror(obj: T): { [K in keyof T]: K }; - export = keyMirror; -} - diff --git a/webapp/channels/src/utils/constants.tsx b/webapp/channels/src/utils/constants.tsx index c10b006a19..8397c1ef86 100644 --- a/webapp/channels/src/utils/constants.tsx +++ b/webapp/channels/src/utils/constants.tsx @@ -7,13 +7,13 @@ import solarizedDarkCSS from 'highlight.js/styles/base16/solarized-dark.css'; import solarizedLightCSS from 'highlight.js/styles/base16/solarized-light.css'; import githubCSS from 'highlight.js/styles/github.css'; import monokaiCSS from 'highlight.js/styles/monokai.css'; -import keyMirror from 'key-mirror'; import {defineMessage, defineMessages} from 'react-intl'; import {CustomStatusDuration} from '@mattermost/types/users'; import {Preferences as ReduxPreferences} from 'mattermost-redux/constants'; import Permissions from 'mattermost-redux/constants/permissions'; +import keyMirror from 'mattermost-redux/utils/key_mirror'; import * as PostListUtils from 'mattermost-redux/utils/post_list'; import audioIcon from 'images/icons/audio.svg'; diff --git a/webapp/channels/src/packages/mattermost-redux/src/client/rudder.ts b/webapp/channels/src/utils/rudder.ts similarity index 100% rename from webapp/channels/src/packages/mattermost-redux/src/client/rudder.ts rename to webapp/channels/src/utils/rudder.ts diff --git a/webapp/package-lock.json b/webapp/package-lock.json index e2b3253f92..5b15840923 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -11,6 +11,7 @@ "platform/client", "platform/components", "platform/eslint-plugin", + "platform/mattermost-redux", "platform/types" ], "dependencies": { @@ -55,7 +56,7 @@ }, "channels": { "name": "mattermost-webapp", - "version": "9.3.0", + "version": "10.6.0", "dependencies": { "@floating-ui/react": "0.26.28", "@giphy/js-fetch-api": "5.1.0", @@ -97,7 +98,6 @@ "inobounce": "0.2.1", "ipaddr.js": "2.1.0", "katex": "0.16.10", - "key-mirror": "1.0.1", "localforage": "1.10.0", "localforage-observable": "2.1.1", "lodash": "4.17.21", @@ -6006,7 +6006,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.2.3.tgz", "integrity": "sha512-y90IIqdQF6kIkP4KfBCfiFrnu9KMrEPUmcnb5A3v12tjfwRJUXecX8vCEbFqqJLjOomvVmis0Aal7QdFjk6CRQ==", - "dev": true, "dependencies": { "@babel/runtime": "^7.18.3", "immutable": "^4.0.0" @@ -15594,8 +15593,7 @@ "node_modules/immutable": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", - "dev": true + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -20284,11 +20282,6 @@ "node": ">= 12" } }, - "node_modules/key-mirror": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/key-mirror/-/key-mirror-1.0.1.tgz", - "integrity": "sha512-qRqYvj2S1VGEr+KnxwSX74xKCfnhZsLHUwvsGYC1OP0vaV/eYzS8jpEO/lFGPAJPmzwCm/JQmxabpoVMdOK76g==" - }, "node_modules/keycode": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz", @@ -20688,6 +20681,10 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/mattermost-redux": { + "resolved": "platform/mattermost-redux", + "link": true + }, "node_modules/mattermost-webapp": { "resolved": "channels", "link": true @@ -28180,7 +28177,7 @@ }, "platform/client": { "name": "@mattermost/client", - "version": "9.3.0", + "version": "10.6.0", "license": "MIT", "devDependencies": { "@types/jest": "28.1.8", @@ -28188,7 +28185,6 @@ "typescript": "^5.0.0" }, "peerDependencies": { - "@mattermost/types": "^9.3.0 || ^10.0.0", "typescript": "^4.3.0 || ^5.0.0" }, "peerDependenciesMeta": { @@ -29642,9 +29638,34 @@ } } }, + "platform/mattermost-redux": { + "version": "10.6.0", + "license": "MIT", + "dependencies": { + "@mattermost/client": "10.6.0", + "@mattermost/types": "10.6.0", + "@redux-devtools/extension": "^3.2.3", + "lodash": "^4.17.21", + "moment-timezone": "^0.5.38", + "redux": "^4.2.0", + "redux-batched-actions": "^0.5.0", + "redux-thunk": "^2.4.2", + "serialize-error": "^11.0.3", + "shallow-equals": "^1.0.0", + "timezones.json": "^1.7.1" + }, + "peerDependencies": { + "typescript": "^4.3.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "platform/types": { "name": "@mattermost/types", - "version": "9.3.0", + "version": "10.6.0", "license": "MIT", "devDependencies": { "typescript": "^5.0.0" diff --git a/webapp/package.json b/webapp/package.json index a69570bc57..646853059b 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -108,6 +108,7 @@ "platform/client", "platform/components", "platform/eslint-plugin", + "platform/mattermost-redux", "platform/types" ] } diff --git a/webapp/platform/client/package.json b/webapp/platform/client/package.json index 4eb307c2a6..72eee7e10c 100644 --- a/webapp/platform/client/package.json +++ b/webapp/platform/client/package.json @@ -1,12 +1,13 @@ { "name": "@mattermost/client", - "version": "9.3.0", + "version": "10.6.0", "description": "JavaScript/TypeScript client for Mattermost", "keywords": [ "mattermost" ], "homepage": "https://github.com/mattermost/mattermost/tree/master/webapp/platform/client#readme", "license": "MIT", + "type": "commonjs", "files": [ "lib" ], diff --git a/webapp/platform/client/src/client4.ts b/webapp/platform/client/src/client4.ts index 7d5b75f775..6cd0458118 100644 --- a/webapp/platform/client/src/client4.ts +++ b/webapp/platform/client/src/client4.ts @@ -3,11 +3,6 @@ /* eslint-disable max-lines */ -import { - TrackPropertyUser, - TrackPropertyUserAgent, TrackScheduledPostsFeature, -} from 'mattermost-webapp/src/packages/mattermost-redux/src/constants/telemetry'; - import type {ClusterInfo, AnalyticsRow, SchemaMigration, LogFilterQuery} from '@mattermost/types/admin'; import type {AppBinding, AppCallRequest, AppCallResponse} from '@mattermost/types/apps'; import type {Audit} from '@mattermost/types/audits'; @@ -2125,7 +2120,7 @@ export default class Client4 { `${this.getPostsRoute()}`, {method: 'post', body: JSON.stringify(post)}, ); - const analyticsData = {channel_id: result.channel_id, post_id: result.id, [TrackPropertyUser]: result.user_id, root_id: result.root_id} as PostAnalytics; + const analyticsData = {channel_id: result.channel_id, post_id: result.id, user_actual_id: result.user_id, root_id: result.root_id} as PostAnalytics; if (post.metadata?.priority) { analyticsData.priority = post.metadata.priority.priority; analyticsData.requested_ack = post.metadata.priority.requested_ack; @@ -3760,7 +3755,7 @@ export default class Client4 { context: { ...call.context, track_as_submit: trackAsSubmit, - [TrackPropertyUserAgent]: 'webapp', + user_agent: 'webapp', }, }; return this.doFetch( @@ -3773,7 +3768,7 @@ export default class Client4 { const params = { channel_id: channelID, team_id: teamID, - [TrackPropertyUserAgent]: 'webapp', + user_agent: 'webapp', }; return this.doFetch( @@ -4296,7 +4291,7 @@ export default class Client4 { // Schedule Post methods createScheduledPost = (schedulePost: PartialExcept, connectionId: string) => { - this.trackFeatureEvent(TrackScheduledPostsFeature, 'create_scheduled_post', {[TrackPropertyUser]: schedulePost.user_id, [TrackPropertyUserAgent]: 'desktop'}); + this.trackFeatureEvent('scheduled_posts', 'create_scheduled_post', {actual_user_id: schedulePost.user_id, user_agent: 'desktop'}); return this.doFetchWithResponse( `${this.getPostsRoute()}/schedule`, @@ -4313,7 +4308,7 @@ export default class Client4 { }; updateScheduledPost = (schedulePost: ScheduledPost, connectionId: string) => { - this.trackFeatureEvent(TrackScheduledPostsFeature, 'update_scheduled_post', {[TrackPropertyUser]: schedulePost.user_id, [TrackPropertyUserAgent]: 'desktop'}); + this.trackFeatureEvent('scheduled_posts', 'update_scheduled_post', {actual_user_id: schedulePost.user_id, user_agent: 'desktop'}); return this.doFetchWithResponse( `${this.getPostsRoute()}/schedule/${schedulePost.id}`, @@ -4322,7 +4317,7 @@ export default class Client4 { }; deleteScheduledPost = (userId: string, schedulePostId: string, connectionId: string) => { - this.trackFeatureEvent(TrackScheduledPostsFeature, 'delete_scheduled_post', {[TrackPropertyUser]: userId, [TrackPropertyUserAgent]: 'desktop'}); + this.trackFeatureEvent('scheduled_posts', 'delete_scheduled_post', {actual_user_id: userId, user_agent: 'desktop'}); return this.doFetchWithResponse( `${this.getPostsRoute()}/schedule/${schedulePostId}`, diff --git a/webapp/platform/mattermost-redux/README.md b/webapp/platform/mattermost-redux/README.md new file mode 100644 index 0000000000..1b41b227b9 --- /dev/null +++ b/webapp/platform/mattermost-redux/README.md @@ -0,0 +1,11 @@ +# mattermost-redux + +This package contains a large part of the [Redux](http://redux.js.org) code and some utilities used by [the Mattermost web app](https://github.com/mattermost/mattermost/tree/master/webapp/channels) for usage in Mattermost plugins and other related projects. + +This code doesn't strictly follow semantic versioning as it is mostly internal code to Mattermost, and it will feature breaking changes outside of major releases, but it can be considered stable for the most part. + +## Installation + +```sh +$ npm install mattermost-redux @mattermost/types @mattermost/client +``` diff --git a/webapp/platform/mattermost-redux/package.json b/webapp/platform/mattermost-redux/package.json new file mode 100644 index 0000000000..879ca0f535 --- /dev/null +++ b/webapp/platform/mattermost-redux/package.json @@ -0,0 +1,59 @@ +{ + "name": "mattermost-redux", + "version": "10.6.0", + "description": "Common code (API client, Redux stores, logic, utility functions) for building a Mattermost client", + "keywords": [ + "mattermost" + ], + "homepage": "https://github.com/mattermost/mattermost/tree/master/webapp/platform/mattermost-redux#readme", + "license": "MIT", + "type": "commonjs", + "files": [ + "lib" + ], + "exports": { + "./*": [ + "./lib/*/index.js", + "./lib/*.js" + ] + }, + "typesVersions": { + ">=3.1": { + "*": [ + "./lib/*.d.ts", + "./lib/*/index.d.ts" + ] + } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/mattermost/mattermost.git", + "directory": "webapp/platform/mattermost-redux" + }, + "dependencies": { + "@mattermost/client": "10.6.0", + "@mattermost/types": "10.6.0", + "@redux-devtools/extension": "^3.2.3", + "lodash": "^4.17.21", + "moment-timezone": "^0.5.38", + "redux": "^4.2.0", + "redux-batched-actions": "^0.5.0", + "redux-thunk": "^2.4.2", + "serialize-error": "^11.0.3", + "shallow-equals": "^1.0.0", + "timezones.json": "^1.7.1" + }, + "peerDependencies": { + "typescript": "^4.3.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + }, + "scripts": { + "build": "tsc --build --verbose", + "postbuild": "cp ../../channels/src/packages/mattermost-redux/src/selectors/create_selector/index.d.ts lib/selectors/create_selector/index.d.ts", + "clean": "rm -rf lib node_modules *.tsbuildinfo" + } +} diff --git a/webapp/platform/mattermost-redux/tsconfig.json b/webapp/platform/mattermost-redux/tsconfig.json new file mode 100644 index 0000000000..24f7b82d78 --- /dev/null +++ b/webapp/platform/mattermost-redux/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "allowJs": true, + "module": "commonjs", + "moduleResolution": "node", + "target": "ES2022", + "lib": [ + "ES2022" + ], + "declaration": true, + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "jsx": "react", + "outDir": "./lib", + "rootDir": "../../channels/src/packages/mattermost-redux/src", + "composite": true, + "useUnknownInCatchVariables": false, + "tsBuildInfoFile": "tsconfig.tsbuildinfo", + "paths": { + "mattermost-redux/*": ["../../channels/src/packages/mattermost-redux/src/*"] + } + }, + "include": [ + "../../channels/src/packages/mattermost-redux/src/**/*" + ], + "exclude": [ + "../../**/*.test.*" + ] +} diff --git a/webapp/platform/types/package.json b/webapp/platform/types/package.json index 1770c0b581..3b1a7010df 100644 --- a/webapp/platform/types/package.json +++ b/webapp/platform/types/package.json @@ -1,12 +1,13 @@ { "name": "@mattermost/types", - "version": "9.3.0", + "version": "10.6.0", "description": "Shared type definitions used by the Mattermost web app", "keywords": [ "mattermost" ], "homepage": "https://github.com/mattermost/mattermost/tree/master/webapp/platform/types#readme", "license": "MIT", + "type": "commonjs", "files": [ "lib" ], @@ -16,7 +17,8 @@ "typesVersions": { ">=3.1": { "*": [ - "./lib/*.d.ts" + "./lib/*.d.ts", + "./lib/*/index.d.ts" ] } }, diff --git a/webapp/platform/types/src/posts.ts b/webapp/platform/types/src/posts.ts index 87e01b137a..fac94690d5 100644 --- a/webapp/platform/types/src/posts.ts +++ b/webapp/platform/types/src/posts.ts @@ -1,8 +1,6 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import type {TrackPropertyUser} from 'mattermost-webapp/src/packages/mattermost-redux/src/constants/telemetry'; - import type {Channel, ChannelType} from './channels'; import type {CustomEmoji} from './emojis'; import type {FileInfo} from './files'; @@ -201,7 +199,7 @@ export declare type TeamsUsageResponse = { export type PostAnalytics = { channel_id: string; post_id: string; - [TrackPropertyUser]: string; + user_actual_id: string; root_id: string; priority?: PostPriority|''; requested_ack?: boolean;