* MM-61297 - remove unused code

* remove unused code for install plugin in backend

* fix translations
Этот коммит содержится в:
Pablo Vélez
2024-11-26 19:11:21 -05:00
коммит произвёл GitHub
родитель edbcb247c6
Коммит 48c14af280
6 изменённых файлов: 4 добавлений и 636 удалений

Просмотреть файл

@@ -117,7 +117,7 @@ func (a *App) SendNotifyAdminPosts(c request.CTX, workspaceName string, currentS
return nil
}
userBasedPaidFeatureData, userBasedPluginData := a.groupNotifyAdminByUser(data)
userBasedPaidFeatureData := a.groupNotifyAdminByUser(data)
featureBasedData := a.groupNotifyAdminByPaidFeature(data)
pluginBasedData := a.groupNotifyAdminByPlugin(data)
@@ -125,41 +125,12 @@ func (a *App) SendNotifyAdminPosts(c request.CTX, workspaceName string, currentS
if len(userBasedPaidFeatureData) > 0 && len(featureBasedData) > 0 {
a.upgradePlanAdminNotifyPost(c, workspaceName, userBasedPaidFeatureData, featureBasedData, systemBot, admin, trial)
}
if len(userBasedPluginData) > 0 {
a.pluginInstallAdminNotifyPost(c, userBasedPluginData, pluginBasedData, systemBot, admin)
}
}
a.FinishSendAdminNotifyPost(c, trial, now, pluginBasedData)
return nil
}
func (a *App) pluginInstallAdminNotifyPost(c request.CTX, userBasedData map[string][]*model.NotifyAdminData, pluginBasedPluginData map[string][]*model.NotifyAdminData, systemBot *model.Bot, admin *model.User) {
props := make(model.StringInterface)
channel, appErr := a.GetOrCreateDirectChannel(c, systemBot.UserId, admin.Id)
if appErr != nil {
c.Logger().Warn("Error getting direct channel", mlog.Err(appErr))
return
}
post := &model.Post{
UserId: systemBot.UserId,
ChannelId: channel.Id,
Type: fmt.Sprintf("%spl_notification", model.PostCustomTypePrefix), // webapp will have to create renderer for this custom post type
}
props["requested_plugins_by_plugin_ids"] = pluginBasedPluginData
props["requested_plugins_by_user_ids"] = userBasedData
post.SetProps(props)
_, appErr = a.CreatePost(c, post, channel, model.CreatePostFlags{SetOnline: true})
if appErr != nil {
c.Logger().Warn("Error creating post", mlog.Err(appErr))
}
}
func (a *App) upgradePlanAdminNotifyPost(c request.CTX, workspaceName string, userBasedData map[string][]*model.NotifyAdminData, featureBasedData map[model.MattermostFeature][]*model.NotifyAdminData, systemBot *model.Bot, admin *model.User, trial bool) {
props := make(model.StringInterface)
T := i18n.GetUserTranslations(admin.Locale)
@@ -276,17 +247,12 @@ func (a *App) FinishSendAdminNotifyPost(rctx request.CTX, trial bool, now int64,
}
}
func (a *App) groupNotifyAdminByUser(data []*model.NotifyAdminData) (map[string][]*model.NotifyAdminData, map[string][]*model.NotifyAdminData) {
func (a *App) groupNotifyAdminByUser(data []*model.NotifyAdminData) map[string][]*model.NotifyAdminData {
userBasedPaidFeatureData := make(map[string][]*model.NotifyAdminData)
userBasedPluginData := make(map[string][]*model.NotifyAdminData)
for _, d := range data {
if strings.HasPrefix(string(d.RequiredFeature), string(model.PluginFeature)) {
userBasedPluginData[d.UserId] = append(userBasedPluginData[d.UserId], d)
} else {
userBasedPaidFeatureData[d.UserId] = append(userBasedPaidFeatureData[d.UserId], d)
}
userBasedPaidFeatureData[d.UserId] = append(userBasedPaidFeatureData[d.UserId], d)
}
return userBasedPaidFeatureData, userBasedPluginData
return userBasedPaidFeatureData
}
func (a *App) groupNotifyAdminByPaidFeature(data []*model.NotifyAdminData) map[model.MattermostFeature][]*model.NotifyAdminData {

Просмотреть файл

@@ -14,8 +14,6 @@ import (
"github.com/mattermost/mattermost/server/public/model"
)
const PluginIDGithub = "github"
func Test_SendNotifyAdminPosts(t *testing.T) {
t.Run("no error sending non trial upgrade post when no notifications are available", func(t *testing.T) {
th := Setup(t).InitBasic()
@@ -137,119 +135,6 @@ func Test_SendNotifyAdminPosts(t *testing.T) {
require.Equal(t, "1 member of the test workspace has requested starting the Enterprise trial for access to: ", post.Message)
})
t.Run("successfully send install plugin notification", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
// some notifications
_, appErr := th.App.SaveAdminNotifyData(&model.NotifyAdminData{
UserId: th.BasicUser.Id,
RequiredPlan: PluginIDGithub,
RequiredFeature: model.PluginFeature,
Trial: false,
})
require.Nil(t, appErr)
appErr = th.App.SendNotifyAdminPosts(th.Context, "", "", false)
require.Nil(t, appErr)
bot, appErr := th.App.GetSystemBot(th.Context)
require.Nil(t, appErr)
var channel *model.Channel
var err error
var timeout = 5 * time.Second
begin := time.Now()
for {
if time.Since(begin) > timeout {
break
}
channel, err = th.App.Srv().Store().Channel().GetByName("", model.GetDMNameFromIds(bot.UserId, th.SystemAdminUser.Id), false)
if err == nil && channel != nil {
break
}
time.Sleep(100 * time.Millisecond)
}
require.NoError(t, err, "Expected message to have been sent within %d seconds", timeout)
postList, err := th.App.Srv().Store().Post().GetPosts(model.GetPostsOptions{ChannelId: channel.Id, Page: 0, PerPage: 1}, false, map[string]bool{})
require.NoError(t, err)
post := postList.Posts[postList.Order[0]]
require.Equal(t, fmt.Sprintf("%spl_notification", model.PostCustomTypePrefix), post.Type)
require.Equal(t, bot.UserId, post.UserId)
})
t.Run("persist notify admin data after sending the install plugin notification", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
// some notifications
_, appErr := th.App.SaveAdminNotifyData(&model.NotifyAdminData{
UserId: th.BasicUser.Id,
RequiredPlan: PluginIDGithub,
RequiredFeature: model.PluginFeature,
Trial: false,
})
require.Nil(t, appErr)
appErr = th.App.SendNotifyAdminPosts(th.Context, "", "", false)
require.Nil(t, appErr)
bot, appErr := th.App.GetSystemBot(th.Context)
require.Nil(t, appErr)
var channel *model.Channel
var err error
var timeout = 5 * time.Second
begin := time.Now()
for {
if time.Since(begin) > timeout {
break
}
channel, err = th.App.Srv().Store().Channel().GetByName("", model.GetDMNameFromIds(bot.UserId, th.SystemAdminUser.Id), false)
if err == nil && channel != nil {
break
}
time.Sleep(100 * time.Millisecond)
}
require.NoError(t, err, "Expected message to have been sent within %d seconds", timeout)
postList, err := th.App.Srv().Store().Post().GetPosts(model.GetPostsOptions{ChannelId: channel.Id, Page: 0, PerPage: 1}, false, map[string]bool{})
require.NoError(t, err)
post := postList.Posts[postList.Order[0]]
require.Equal(t, fmt.Sprintf("%spl_notification", model.PostCustomTypePrefix), post.Type)
require.Equal(t, bot.UserId, post.UserId)
data, err := th.App.Srv().Store().NotifyAdmin().GetDataByUserIdAndFeature(th.BasicUser.Id, model.PluginFeature)
require.NoError(t, err)
require.Equal(t, len(data), 1)
})
t.Run("error sending more than one notification to the same user and for the same plugin", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
err := th.App.SaveAdminNotification(th.BasicUser.Id, &model.NotifyAdminToUpgradeRequest{
RequiredPlan: PluginIDGithub,
RequiredFeature: model.PluginFeature,
TrialNotification: false,
})
require.Nil(t, err)
err = th.App.SaveAdminNotification(th.BasicUser.Id, &model.NotifyAdminToUpgradeRequest{
RequiredPlan: PluginIDGithub,
RequiredFeature: model.PluginFeature,
TrialNotification: false,
})
require.Equal(t, err.Error(), "app.SaveAdminNotification: Already notified admin")
})
t.Run("error when trying to send upgrade post before end of cool off period", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
@@ -370,67 +255,4 @@ func Test_SendNotifyAdminPosts(t *testing.T) {
require.Equal(t, bot.UserId, post.UserId)
require.Equal(t, "1 member of the test workspace has requested a workspace upgrade for: ", post.Message) // expect only one member's notification even though 2 were added
})
t.Run("correctly send upgrade and install plugin post with the correct user request", func(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
os.Setenv("MM_NOTIFY_ADMIN_COOL_OFF_DAYS", "0")
defer os.Unsetenv("MM_NOTIFY_ADMIN_COOL_OFF_DAYS")
th.App.Srv().SetLicense(model.NewTestLicense("cloud"))
// some notifications
_, appErr := th.App.SaveAdminNotifyData(&model.NotifyAdminData{
UserId: th.BasicUser.Id,
RequiredPlan: model.LicenseShortSkuProfessional,
RequiredFeature: model.PaidFeatureGuestAccounts,
Trial: false,
})
require.Nil(t, appErr)
appErr = th.App.SendNotifyAdminPosts(th.Context, "test", "", false)
require.Nil(t, appErr)
// some notifications
_, appErr = th.App.SaveAdminNotifyData(&model.NotifyAdminData{
UserId: th.BasicUser.Id,
RequiredPlan: PluginIDGithub,
RequiredFeature: model.PluginFeature,
Trial: false,
})
require.Nil(t, appErr)
appErr = th.App.SendNotifyAdminPosts(th.Context, "test", "", false)
require.Nil(t, appErr)
bot, appErr := th.App.GetSystemBot(th.Context)
require.Nil(t, appErr)
var channel *model.Channel
var err error
var timeout = 5 * time.Second
begin := time.Now()
for {
if time.Since(begin) > timeout {
break
}
channel, err = th.App.Srv().Store().Channel().GetByName("", model.GetDMNameFromIds(bot.UserId, th.SystemAdminUser.Id), false)
if err == nil && channel != nil {
break
}
time.Sleep(100 * time.Millisecond)
}
require.NoError(t, err, "Expected message to have been sent within %d seconds", timeout)
postList, err := th.App.Srv().Store().Post().GetPosts(model.GetPostsOptions{ChannelId: channel.Id, Page: 0, PerPage: 2}, false, map[string]bool{})
require.NoError(t, err)
installPluginPost := postList.Posts[postList.Order[0]]
require.Equal(t, fmt.Sprintf("%spl_notification", model.PostCustomTypePrefix), installPluginPost.Type)
require.Equal(t, bot.UserId, installPluginPost.UserId)
upgradePost := postList.Posts[postList.Order[1]]
require.Equal(t, fmt.Sprintf("%sup_notification", model.PostCustomTypePrefix), upgradePost.Type)
require.Equal(t, bot.UserId, upgradePost.UserId)
require.Equal(t, "1 member of the test workspace has requested a workspace upgrade for: ", upgradePost.Message)
})
}

Просмотреть файл

@@ -1,65 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import type {DeepPartial} from '@mattermost/types/utilities';
import {isCustomPostProps, type CustomPostProps} from '.';
describe('isCustomPostProps', () => {
it('no content', () => {
const props: CustomPostProps = {
requested_plugins_by_plugin_ids: {},
requested_plugins_by_user_ids: {},
};
expect(isCustomPostProps(props)).toBe(true);
});
it('content but no elements', () => {
const props: CustomPostProps = {
requested_plugins_by_plugin_ids: {'some id': []},
requested_plugins_by_user_ids: {'some id': []},
};
expect(isCustomPostProps(props)).toBe(true);
});
it('content with elements', () => {
const props: CustomPostProps = {
requested_plugins_by_plugin_ids: {'some id': [{
user_id: '123',
}]},
requested_plugins_by_user_ids: {'some id': [{
user_id: '123',
}]},
};
expect(isCustomPostProps(props)).toBe(true);
});
it('all values are required', () => {
const baseProp: CustomPostProps = {
requested_plugins_by_plugin_ids: {},
requested_plugins_by_user_ids: {},
};
expect(isCustomPostProps(baseProp)).toBe(true);
for (const key of Object.keys(baseProp)) {
const wrongProp: Partial<CustomPostProps> = {...baseProp};
delete wrongProp[key as keyof CustomPostProps];
expect(isCustomPostProps(wrongProp)).toBe(false);
}
const wrongProp: DeepPartial<CustomPostProps> = {
requested_plugins_by_plugin_ids: {'some id': [{}]},
requested_plugins_by_user_ids: {'some id': []},
};
expect(isCustomPostProps(wrongProp)).toBe(false);
});
it('common false cases', () => {
expect(isCustomPostProps('')).toBe(false);
expect(isCustomPostProps(undefined)).toBe(false);
expect(isCustomPostProps(true)).toBe(false);
expect(isCustomPostProps(1)).toBe(false);
expect(isCustomPostProps([])).toBe(false);
});
});

Просмотреть файл

@@ -1,342 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import uniqWith from 'lodash/uniqWith';
import React, {useEffect, useMemo} from 'react';
import {FormattedMessage, useIntl} from 'react-intl';
import {useSelector, useDispatch} from 'react-redux';
import {Link} from 'react-router-dom';
import type {MarketplacePlugin} from '@mattermost/types/marketplace';
import type {Post} from '@mattermost/types/posts';
import {isArrayOf, isRecordOf} from '@mattermost/types/utilities';
import {getMissingProfilesByIds} from 'mattermost-redux/actions/users';
import {getUsers} from 'mattermost-redux/selectors/entities/users';
import {fetchListing, installPlugin} from 'actions/marketplace';
import {getError, getInstalledListing, getInstalling, getPlugins} from 'selectors/views/marketplace';
import Markdown from 'components/markdown';
import MarketplaceModal from 'components/plugin_marketplace/marketplace_modal';
import ToggleModalButton from 'components/toggle_modal_button';
import {ModalIdentifiers} from 'utils/constants';
import type {GlobalState} from 'types/store';
// We only define the props used in this component for
// clarity. If more props are needed in the future,
// feel free to add them.
type PluginRequest = {
user_id: string;
}
function isPluginRequest(v: unknown): v is PluginRequest {
if (typeof v !== 'object' || v === null) {
return false;
}
const request = v as PluginRequest;
if (typeof request.user_id !== 'string') {
return false;
}
return true;
}
type RequestedPlugins = Record<string, PluginRequest[]>
export type CustomPostProps = {
requested_plugins_by_plugin_ids: RequestedPlugins;
requested_plugins_by_user_ids: RequestedPlugins;
}
export function isCustomPostProps(v: unknown): v is CustomPostProps {
if (typeof v !== 'object' || !v) {
return false;
}
const props = v as CustomPostProps;
if (!isRecordOf(props.requested_plugins_by_plugin_ids, (e) => isArrayOf(e, isPluginRequest))) {
return false;
}
if (!isRecordOf(props.requested_plugins_by_user_ids, (e) => isArrayOf(e, isPluginRequest))) {
return false;
}
return true;
}
const usersListStyle = {
margin: '20px 0',
};
const InstallLink = (props: {pluginId: string; pluginName: string}) => {
const dispatch = useDispatch();
return (
<Link
to='#'
onClick={() => dispatch(installPlugin(props.pluginId))}
style={{color: 'var(--denim-button-bg)', fontWeight: '600'}}
>
<FormattedMessage
id='marketplace_modal.list.install.plugin'
defaultMessage={'Install {plugin}'}
values={{
plugin: props.pluginName,
}}
/>
</Link>
);
};
const ConfigureLink = (props: {pluginId: string; pluginName: string}) => {
return (
<>
<FormattedMessage
id='postypes.custom_open_plugin_install_post_rendered.plugins_installed'
defaultMessage={`${props.pluginName} is now installed.`}
values={{
pluginName: props.pluginName,
}}
/>
{' '}
<Link
to={'/admin_console/plugins/plugin_' + props.pluginId}
style={{color: 'var(--denim-button-bg)', fontWeight: '600'}}
>
<FormattedMessage
id='marketplace_modal.list.configure.plugin'
defaultMessage={'Configure {plugin}'}
values={{
plugin: props.pluginName,
}}
/>
</Link>
</>
);
};
const InstallAndConfigureLink = (props: {pluginId: string; pluginName: string}) => {
const installedListing = useSelector(getInstalledListing) as MarketplacePlugin[];
const error = useSelector((state: GlobalState) => getError(state, props.pluginId));
const isInstalled = installedListing.some((plugin) => plugin.manifest.id === props.pluginId);
const installing = useSelector((state: GlobalState) => getInstalling(state, props.pluginId));
if (installing) {
return (
<span style={{fontStyle: 'italic', color: 'var(--online-indicator)', fontWeight: '600'}}>
<FormattedMessage
id='marketplace_modal.installing'
defaultMessage='Installing...'
/>
</span>
);
} else if (!isInstalled && !error) {
return (
<InstallLink
pluginId={props.pluginId}
pluginName={props.pluginName}
/>);
} else if (isInstalled && !error) {
return (
<ConfigureLink
pluginId={props.pluginId}
pluginName={props.pluginName}
/>);
}
return null;
};
export default function OpenPluginInstallPost(props: {post: Post}) {
const customMessageBody = [];
const dispatch = useDispatch();
const {formatMessage, formatList} = useIntl();
const postProps = isCustomPostProps(props.post.props) ? props.post.props : undefined;
const requestedPluginsByPluginIds = postProps?.requested_plugins_by_plugin_ids;
const requestedPluginsByUserIds = postProps?.requested_plugins_by_user_ids;
const userProfiles = useSelector(getUsers);
const marketplacePlugins: MarketplacePlugin[] = useSelector(getPlugins);
const marketplacePluginsNamesById = useMemo(() => {
return marketplacePlugins.reduce<Record<string, string>>((acc, v) => {
acc[v.manifest.id] = v.manifest.name;
return acc;
}, {});
}, [marketplacePlugins]);
const getUserIdsForUsersThatRequestedFeature = (requests: PluginRequest[]): string[] => requests.map((request: PluginRequest) => request.user_id);
useEffect(() => {
if (!marketplacePlugins.length) {
dispatch(fetchListing());
}
}, [dispatch, marketplacePlugins.length]);
useEffect(() => {
// process the plugins once the marketplace plugins are fetched and the plugins are available from the props
if (requestedPluginsByPluginIds && marketplacePlugins.length) {
for (const pluginId of Object.keys(requestedPluginsByPluginIds)) {
dispatch(getMissingProfilesByIds(getUserIdsForUsersThatRequestedFeature(requestedPluginsByPluginIds[pluginId])));
}
}
}, [dispatch, marketplacePlugins, requestedPluginsByPluginIds]);
const createUsernameMessage = (requests: PluginRequest[]) => {
if (requests.length >= 5) {
return formatMessage({
id: 'postypes.custom_open_pricing_modal_post_renderer.members',
defaultMessage: '{members} members',
}, {members: requests.length});
}
let usernameMessage;
const users = getUserNamesForUsersThatRequestedFeature(requests);
if (users.length === 1) {
usernameMessage = users[0];
} else {
const lastUser = users.splice(-1, 1)[0];
users.push(formatMessage({id: 'postypes.custom_open_pricing_modal_post_renderer.and', defaultMessage: 'and'}) + ' ' + lastUser);
usernameMessage = users.join(', ').replace(/,([^,]*)$/, '$1');
}
return usernameMessage;
};
const getUserNamesForUsersThatRequestedFeature = (requests: PluginRequest[]): string[] => {
const userNames = requests.map((req: PluginRequest) => {
return getUserNameForUser(req.user_id);
});
return userNames;
};
const getUserNameForUser = (userId: string) => {
const unknownName = formatMessage({id: 'postypes.custom_open_pricing_modal_post_renderer.unknown', defaultMessage: '@unknown'});
const username = userProfiles[userId]?.username;
return username ? '@' + username : unknownName;
};
const markDownOptions = {
atSumOfMembersMentions: true,
atPlanMentions: true,
markdown: false,
};
const pluginIds = Object.keys(requestedPluginsByPluginIds || {});
if (pluginIds.length && requestedPluginsByUserIds && requestedPluginsByPluginIds) {
let post;
const messageBuilder: string[] = [];
const userIds = Object.keys(requestedPluginsByUserIds);
if (userIds.length === 1 && pluginIds.length === 1) {
const pluginName = marketplacePluginsNamesById[pluginIds[0]];
messageBuilder.push('@' + userProfiles[userIds[0]]?.username);
messageBuilder.push(' ' + formatMessage({id: 'postypes.custom_open_plugin_install_post_rendered.plugin_request', defaultMessage: 'requested installing the {pluginRequests} app.'}, {pluginRequests: pluginName}));
const instructions = (
<FormattedMessage
id='postypes.custom_open_plugin_install_post_rendered.plugin_instructions'
defaultMessage='<pluginApp></pluginApp> or visit <marketplaceLink>Marketplace</marketplaceLink> to view all plugins.'
values={{
marketplaceLink: (text: string) => (
<ToggleModalButton
id='marketplaceModal'
className='color--link'
modalId={ModalIdentifiers.PLUGIN_MARKETPLACE}
dialogType={MarketplaceModal}
>
{text}
</ToggleModalButton>
),
pluginApp: () => (
<InstallAndConfigureLink
pluginId={pluginIds[0]}
pluginName={pluginName}
/>
),
}}
/>);
const message = formatList(messageBuilder, {style: 'narrow', type: 'unit'});
post = (
<>
<Markdown
postId={props.post.id}
message={message}
options={markDownOptions}
userIds={getUserIdsForUsersThatRequestedFeature(requestedPluginsByUserIds[userIds[0]])}
/>
{' '}
{instructions}
</>);
customMessageBody.push(post);
} else {
messageBuilder.push(formatMessage({id: 'postypes.custom_open_plugin_install_post_rendered.app_installation_request_text', defaultMessage: 'Youve received the following app installation requests:'}));
post = (
<ul
style={usersListStyle}
key={pluginIds.join('')}
>
{pluginIds.map((pluginId) => {
const plugins = requestedPluginsByPluginIds[pluginId];
const pluginName = marketplacePluginsNamesById[pluginId];
const uniqueUserRequestsForPlugins = uniqWith(plugins, (one, two) => one.user_id === two.user_id);
const installRequests = [];
installRequests.push(createUsernameMessage(uniqueUserRequestsForPlugins));
installRequests.push(' ' + formatMessage({id: 'postypes.custom_open_plugin_install_post_rendered.plugin_request', defaultMessage: 'requested installing the {pluginRequests} app.'}, {pluginRequests: pluginName}));
return (
<li key={pluginId}>
<Markdown
postId={props.post.id}
message={installRequests.join('')}
options={markDownOptions}
userIds={getUserIdsForUsersThatRequestedFeature(requestedPluginsByUserIds[userIds[0]])}
/>
{' '}
<InstallAndConfigureLink
pluginId={pluginId}
pluginName={pluginName}
/>
</li>
);
})}
</ul>
);
const instructions = (
<FormattedMessage
id='postypes.custom_open_plugin_install_post_rendered.plugins_instructions'
defaultMessage='Install the apps or visit <marketplaceLink>Marketplace</marketplaceLink> to view all plugins.'
values={{
marketplaceLink: (text: string) => (
<ToggleModalButton
id='marketplaceModal'
className='color--link'
modalId={ModalIdentifiers.PLUGIN_MARKETPLACE}
dialogType={MarketplaceModal}
dialogProps={{openedFrom: 'open_plugin_install_post'}}
>
{text}
</ToggleModalButton>
),
}}
/>);
customMessageBody.push(messageBuilder);
customMessageBody.push(post);
customMessageBody.push(instructions);
}
}
return (
<div>
{customMessageBody}
</div>
);
}

Просмотреть файл

@@ -19,7 +19,6 @@ import {measurePageLoadTelemetry, temporarilySetPageLoadContext, trackEvent, tra
import BrowserStore from 'stores/browser_store';
import {makeAsyncComponent} from 'components/async_load';
import OpenPluginInstallPost from 'components/custom_open_plugin_install_post_renderer';
import GlobalHeader from 'components/global_header/global_header';
import {HFRoute} from 'components/header_footer_route/header_footer_route';
import {HFTRoute, LoggedInHFTRoute} from 'components/header_footer_template_route';
@@ -360,9 +359,6 @@ export default class Root extends React.PureComponent<Props, State> {
this.initiateMeRequests();
// See figma design on issue https://mattermost.atlassian.net/browse/MM-43649
this.props.actions.registerCustomPostRenderer('custom_pl_notification', OpenPluginInstallPost, 'plugin_install_post_message_renderer');
measurePageLoadTelemetry();
trackSelectorMetrics();

Просмотреть файл

@@ -4281,9 +4281,7 @@
"marketplace_modal.install_plugins": "Install plugins",
"marketplace_modal.installing": "Installing...",
"marketplace_modal.list.configure": "Configure",
"marketplace_modal.list.configure.plugin": "Configure {plugin}",
"marketplace_modal.list.install": "Install",
"marketplace_modal.list.install.plugin": "Install {plugin}",
"marketplace_modal.list.installed": "Installed",
"marketplace_modal.list.try_again": "Try Again",
"marketplace_modal.list.update": "Update",
@@ -4723,14 +4721,7 @@
"postlist.toast.searchHint": "Tip: Try {searchShortcut} to search this channel",
"posts_view.loadMore": "Load More messages",
"posts_view.newMsg": "New Messages",
"postypes.custom_open_plugin_install_post_rendered.app_installation_request_text": "Youve received the following app installation requests:",
"postypes.custom_open_plugin_install_post_rendered.plugin_instructions": "<pluginApp></pluginApp> or visit <marketplaceLink>Marketplace</marketplaceLink> to view all plugins.",
"postypes.custom_open_plugin_install_post_rendered.plugin_request": "requested installing the {pluginRequests} app.",
"postypes.custom_open_plugin_install_post_rendered.plugins_instructions": "Install the apps or visit <marketplaceLink>Marketplace</marketplaceLink> to view all plugins.",
"postypes.custom_open_pricing_modal_post_renderer.and": "and",
"postypes.custom_open_pricing_modal_post_renderer.members": "{members} members",
"postypes.custom_open_pricing_modal_post_renderer.membersThatRequested": "Members that requested ",
"postypes.custom_open_pricing_modal_post_renderer.unknown": "@unknown",
"pricing_modal.addons.dedicatedDB": "Dedicated database",
"pricing_modal.addons.dedicatedDeployment": "Dedicated virtual secure cloud deployment (Cloud)",
"pricing_modal.addons.dedicatedEncryption": "Dedicated encryption keys",