From dd2e325c24d43b1843356809adba0d1365df99cd Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Tue, 11 Apr 2023 12:52:54 -0400 Subject: [PATCH 01/10] Ensure admins can send true up telemetry, even if telemetry is disabled. --- server/channels/api4/license.go | 13 ++++++++----- server/channels/einterfaces/cloud.go | 3 +++ .../src/components/analytics/true_up_review.tsx | 4 ---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/server/channels/api4/license.go b/server/channels/api4/license.go index 9911c241e1..02420a824d 100644 --- a/server/channels/api4/license.go +++ b/server/channels/api4/license.go @@ -354,15 +354,18 @@ func requestTrueUpReview(c *Context, w http.ResponseWriter, r *http.Request) { // Do not send true-up review data if the user has already requested one for the quarter. // And only send a true-up review via as a one-time telemetry request if telemetry is disabled. telemetryEnabled := c.App.Config().LogSettings.EnableDiagnostics - if telemetryEnabled != nil && !*telemetryEnabled { + if telemetryEnabled != nil && *telemetryEnabled { // Send telemetry data c.App.Srv().GetTelemetryService().SendTelemetry(model.TrueUpReviewTelemetryName, profileMap) - - // Update the review status to reflect the completion. - status.Completed = true - c.App.Srv().Store().TrueUpReview().Update(status) + } else { + // Telemetry is disabled, submit true up review profile via CWS. + c.App.Cloud().SubmitTrueUpReview(profileMap) } + // Update the review status to reflect the completion. + status.Completed = true + c.App.Srv().Store().TrueUpReview().Update(status) + // Encode to string rather than byte[] otherwise json.Marshal will encode it further. encodedData := b64.StdEncoding.EncodeToString(profileMapJson) responseContent := struct { diff --git a/server/channels/einterfaces/cloud.go b/server/channels/einterfaces/cloud.go index 70cdc4676a..1dd2ea65ac 100644 --- a/server/channels/einterfaces/cloud.go +++ b/server/channels/einterfaces/cloud.go @@ -48,4 +48,7 @@ type CloudInterface interface { SelfServeDeleteWorkspace(userID string, deletionRequest *model.WorkspaceDeletionRequest) error SubscribeToNewsletter(userID string, req *model.SubscribeNewsletterRequest) error + + // Used only for when a customer has telemetry disabled. In this scenario, true up review telemetry will be submitted via CWS. + SubmitTrueUpReview(trueUpReviewProfile map[string]any) error } diff --git a/webapp/channels/src/components/analytics/true_up_review.tsx b/webapp/channels/src/components/analytics/true_up_review.tsx index 5098999d63..c5ce7b38b2 100644 --- a/webapp/channels/src/components/analytics/true_up_review.tsx +++ b/webapp/channels/src/components/analytics/true_up_review.tsx @@ -223,10 +223,6 @@ const TrueUpReview: React.FC = () => { return null; } - if (telemetryEnabled) { - return null; - } - pageVisited(TELEMETRY_CATEGORIES.TRUE_UP_REVIEW, 'pageview_true_up_review'); return ( From 33d3c906543aa8513c4b9643844cfc44d5588120 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Tue, 11 Apr 2023 14:15:56 -0400 Subject: [PATCH 02/10] Add mocks/layers. --- plugin/api_timer_layer_generated.go | 2 +- plugin/hooks_timer_layer_generated.go | 2 +- server/channels/api4/license.go | 6 +++++- server/channels/einterfaces/cloud.go | 2 +- .../channels/einterfaces/mocks/CloudInterface.go | 14 ++++++++++++++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/plugin/api_timer_layer_generated.go b/plugin/api_timer_layer_generated.go index a084188c62..c54c6ac7bb 100644 --- a/plugin/api_timer_layer_generated.go +++ b/plugin/api_timer_layer_generated.go @@ -11,8 +11,8 @@ import ( "net/http" timePkg "time" - "github.com/mattermost/mattermost-server/v6/server/channels/einterfaces" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/server/channels/einterfaces" ) type apiTimerLayer struct { diff --git a/plugin/hooks_timer_layer_generated.go b/plugin/hooks_timer_layer_generated.go index 6093048d54..87e79ca7e6 100644 --- a/plugin/hooks_timer_layer_generated.go +++ b/plugin/hooks_timer_layer_generated.go @@ -11,8 +11,8 @@ import ( "net/http" timePkg "time" - "github.com/mattermost/mattermost-server/v6/server/channels/einterfaces" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/server/channels/einterfaces" ) type hooksTimerLayer struct { diff --git a/server/channels/api4/license.go b/server/channels/api4/license.go index 02420a824d..985bada409 100644 --- a/server/channels/api4/license.go +++ b/server/channels/api4/license.go @@ -359,7 +359,11 @@ func requestTrueUpReview(c *Context, w http.ResponseWriter, r *http.Request) { c.App.Srv().GetTelemetryService().SendTelemetry(model.TrueUpReviewTelemetryName, profileMap) } else { // Telemetry is disabled, submit true up review profile via CWS. - c.App.Cloud().SubmitTrueUpReview(profileMap) + err := c.App.Cloud().SubmitTrueUpReview(c.AppContext.Session().UserId, profileMap) + if err != nil { + c.SetJSONEncodingError(err) + return + } } // Update the review status to reflect the completion. diff --git a/server/channels/einterfaces/cloud.go b/server/channels/einterfaces/cloud.go index 1dd2ea65ac..fc5446cd34 100644 --- a/server/channels/einterfaces/cloud.go +++ b/server/channels/einterfaces/cloud.go @@ -50,5 +50,5 @@ type CloudInterface interface { SubscribeToNewsletter(userID string, req *model.SubscribeNewsletterRequest) error // Used only for when a customer has telemetry disabled. In this scenario, true up review telemetry will be submitted via CWS. - SubmitTrueUpReview(trueUpReviewProfile map[string]any) error + SubmitTrueUpReview(userID string, trueUpReviewProfile map[string]any) error } diff --git a/server/channels/einterfaces/mocks/CloudInterface.go b/server/channels/einterfaces/mocks/CloudInterface.go index f84300dbec..5800844da0 100644 --- a/server/channels/einterfaces/mocks/CloudInterface.go +++ b/server/channels/einterfaces/mocks/CloudInterface.go @@ -594,6 +594,20 @@ func (_m *CloudInterface) SelfServeDeleteWorkspace(userID string, deletionReques return r0 } +// SubmitTrueUpReview provides a mock function with given fields: userID, trueUpReviewProfile +func (_m *CloudInterface) SubmitTrueUpReview(userID string, trueUpReviewProfile map[string]interface{}) error { + ret := _m.Called(userID, trueUpReviewProfile) + + var r0 error + if rf, ok := ret.Get(0).(func(string, map[string]interface{}) error); ok { + r0 = rf(userID, trueUpReviewProfile) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // SubscribeToNewsletter provides a mock function with given fields: userID, req func (_m *CloudInterface) SubscribeToNewsletter(userID string, req *model.SubscribeNewsletterRequest) error { ret := _m.Called(userID, req) From 382894b41cff910a7c1babf643e8cd2d0ba46640 Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Wed, 12 Apr 2023 09:56:46 -0400 Subject: [PATCH 03/10] revert change to show true up review when telemetry is enabled, always send true up data to CWS for telemetry capture. --- server/channels/api4/license.go | 19 ++++++------------- .../components/analytics/true_up_review.tsx | 4 ++++ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/server/channels/api4/license.go b/server/channels/api4/license.go index 985bada409..358960272f 100644 --- a/server/channels/api4/license.go +++ b/server/channels/api4/license.go @@ -351,19 +351,12 @@ func requestTrueUpReview(c *Context, w http.ResponseWriter, r *http.Request) { return } - // Do not send true-up review data if the user has already requested one for the quarter. - // And only send a true-up review via as a one-time telemetry request if telemetry is disabled. - telemetryEnabled := c.App.Config().LogSettings.EnableDiagnostics - if telemetryEnabled != nil && *telemetryEnabled { - // Send telemetry data - c.App.Srv().GetTelemetryService().SendTelemetry(model.TrueUpReviewTelemetryName, profileMap) - } else { - // Telemetry is disabled, submit true up review profile via CWS. - err := c.App.Cloud().SubmitTrueUpReview(c.AppContext.Session().UserId, profileMap) - if err != nil { - c.SetJSONEncodingError(err) - return - } + // True-up is only enabled when telemetry is disabled. When telemetry is enabled, we already have all the data necessary + // for true-up reviews to be completed. + err = c.App.Cloud().SubmitTrueUpReview(c.AppContext.Session().UserId, profileMap) + if err != nil { + c.SetJSONEncodingError(err) + return } // Update the review status to reflect the completion. diff --git a/webapp/channels/src/components/analytics/true_up_review.tsx b/webapp/channels/src/components/analytics/true_up_review.tsx index c5ce7b38b2..5098999d63 100644 --- a/webapp/channels/src/components/analytics/true_up_review.tsx +++ b/webapp/channels/src/components/analytics/true_up_review.tsx @@ -223,6 +223,10 @@ const TrueUpReview: React.FC = () => { return null; } + if (telemetryEnabled) { + return null; + } + pageVisited(TELEMETRY_CATEGORIES.TRUE_UP_REVIEW, 'pageview_true_up_review'); return ( From 77e1fbfbc832a96eae76a45ed586b7cf3e31075d Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Wed, 12 Apr 2023 10:12:33 -0400 Subject: [PATCH 04/10] Change error upon failure of true up review submission to CWS. --- server/channels/api4/license.go | 2 +- server/i18n/en.json | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/server/channels/api4/license.go b/server/channels/api4/license.go index 358960272f..abbdf8bcfb 100644 --- a/server/channels/api4/license.go +++ b/server/channels/api4/license.go @@ -355,7 +355,7 @@ func requestTrueUpReview(c *Context, w http.ResponseWriter, r *http.Request) { // for true-up reviews to be completed. err = c.App.Cloud().SubmitTrueUpReview(c.AppContext.Session().UserId, profileMap) if err != nil { - c.SetJSONEncodingError(err) + c.Err = model.NewAppError("requestTrueUpReview", "api.license.true_up_review.failed_to_submit", nil, err.Error(), http.StatusInternalServerError) return } diff --git a/server/i18n/en.json b/server/i18n/en.json index e91fbf2656..d16e605ef0 100644 --- a/server/i18n/en.json +++ b/server/i18n/en.json @@ -2089,6 +2089,10 @@ "id": "api.license.true_up_review.create_error", "translation": "Could not create true up status record" }, + { + "id": "api.license.true_up_review.failed_to_submit", + "translation": "Failed to submit true up review profile to CWS." + }, { "id": "api.license.true_up_review.get_status_error", "translation": "Could not get true up status records" From eebd57ead11a89a2327ec747b0a09d41afe4a86a Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Wed, 12 Apr 2023 15:06:55 -0400 Subject: [PATCH 05/10] Add ok response code to hopefully fix tests. --- server/channels/api4/license.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/channels/api4/license.go b/server/channels/api4/license.go index abbdf8bcfb..a1b7806dbf 100644 --- a/server/channels/api4/license.go +++ b/server/channels/api4/license.go @@ -370,6 +370,7 @@ func requestTrueUpReview(c *Context, w http.ResponseWriter, r *http.Request) { }{Content: encodedData} response, _ := json.Marshal(responseContent) + w.WriteHeader(http.StatusOK) w.Write(response) } From 0b731f4330eea1bc643ac8f73d9c8eedc65068bd Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Wed, 12 Apr 2023 16:22:10 -0400 Subject: [PATCH 06/10] fix tests. --- server/channels/api4/license_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/server/channels/api4/license_test.go b/server/channels/api4/license_test.go index 08a9e57305..8769fae1fc 100644 --- a/server/channels/api4/license_test.go +++ b/server/channels/api4/license_test.go @@ -521,6 +521,14 @@ func TestTrueUpReviewStatus(t *testing.T) { th.App.Srv().SetLicense(model.NewTestLicense()) t.Run("returns 200 when status retrieved", func(t *testing.T) { + cloud := mocks.CloudInterface{} + + cloudImpl := th.App.Srv().Cloud + defer func() { + th.App.Srv().Cloud = cloudImpl + }() + th.App.Srv().Cloud = &cloud + resp, err := th.SystemAdminClient.DoAPIGet("/license/review/status", "") require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) From 7cc866ed89d1e3859470d5f97aac87f97c00331a Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Thu, 13 Apr 2023 09:34:48 -0400 Subject: [PATCH 07/10] actually fix tests through mocks. --- model/client4.go | 14 ++++++++++++++ server/channels/api4/license_test.go | 22 +++++++++++++--------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/model/client4.go b/model/client4.go index d6cc62ba0f..74b65948b0 100644 --- a/model/client4.go +++ b/model/client4.go @@ -8803,3 +8803,17 @@ func (c *Client4) GetWorkTemplatesByCategory(category string) ([]*WorkTemplate, err = json.NewDecoder(r.Body).Decode(&templates) return templates, BuildResponse(r), err } + +func (c *Client4) SubmitTrueUpReview(req map[string]any) (*Response, error) { + reqBytes, err := json.Marshal(req) + if err != nil { + return nil, NewAppError("SubmitTrueUpReview", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) + } + r, err := c.DoAPIPostBytes(c.licenseRoute()+"/review", reqBytes) + if err != nil { + return BuildResponse(r), nil + } + defer closeBody(r) + + return BuildResponse(r), nil +} diff --git a/server/channels/api4/license_test.go b/server/channels/api4/license_test.go index 8769fae1fc..1a4b4a7803 100644 --- a/server/channels/api4/license_test.go +++ b/server/channels/api4/license_test.go @@ -484,7 +484,19 @@ func TestRequestTrueUpReview(t *testing.T) { th.App.Srv().SetLicense(model.NewTestLicense()) t.Run("returns status 200 when telemetry data sent", func(t *testing.T) { - resp, err := th.SystemAdminClient.DoAPIPost("/license/review", "") + th.Client.Login(th.SystemAdminUser.Email, th.SystemAdminUser.Password) + + cloud := mocks.CloudInterface{} + cloud.Mock.On("SubmitTrueUpReview", mock.Anything, mock.Anything).Return(nil) + + cloudImpl := th.App.Srv().Cloud + defer func() { + th.App.Srv().Cloud = cloudImpl + }() + th.App.Srv().Cloud = &cloud + + var reviewProfile map[string]any + resp, err := th.Client.SubmitTrueUpReview(reviewProfile) require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) }) @@ -521,14 +533,6 @@ func TestTrueUpReviewStatus(t *testing.T) { th.App.Srv().SetLicense(model.NewTestLicense()) t.Run("returns 200 when status retrieved", func(t *testing.T) { - cloud := mocks.CloudInterface{} - - cloudImpl := th.App.Srv().Cloud - defer func() { - th.App.Srv().Cloud = cloudImpl - }() - th.App.Srv().Cloud = &cloud - resp, err := th.SystemAdminClient.DoAPIGet("/license/review/status", "") require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) From 27d959485e7c0e1b94d6c8054cbafcf898bcb02a Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Thu, 13 Apr 2023 09:54:58 -0400 Subject: [PATCH 08/10] move setup/teardown into each test. --- server/channels/api4/license_test.go | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/server/channels/api4/license_test.go b/server/channels/api4/license_test.go index 1a4b4a7803..d673e13543 100644 --- a/server/channels/api4/license_test.go +++ b/server/channels/api4/license_test.go @@ -478,12 +478,11 @@ func TestRequestRenewalLink(t *testing.T) { } func TestRequestTrueUpReview(t *testing.T) { - th := Setup(t) - defer th.TearDown() - - th.App.Srv().SetLicense(model.NewTestLicense()) - t.Run("returns status 200 when telemetry data sent", func(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + th.App.Srv().SetLicense(model.NewTestLicense()) + th.Client.Login(th.SystemAdminUser.Email, th.SystemAdminUser.Password) cloud := mocks.CloudInterface{} @@ -502,6 +501,10 @@ func TestRequestTrueUpReview(t *testing.T) { }) t.Run("returns 501 when ran by cloud user", func(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + th.App.Srv().SetLicense(model.NewTestLicense()) + th.App.Srv().SetLicense(model.NewTestLicense("cloud")) resp, err := th.SystemAdminClient.DoAPIPost("/license/review", "") @@ -512,12 +515,19 @@ func TestRequestTrueUpReview(t *testing.T) { }) t.Run("returns 403 when user does not have permissions", func(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + th.App.Srv().SetLicense(model.NewTestLicense()) + resp, err := th.Client.DoAPIPost("/license/review", "") require.Error(t, err) require.Equal(t, http.StatusForbidden, resp.StatusCode) }) t.Run("returns 400 when license is nil", func(t *testing.T) { + th := Setup(t).InitBasic() + defer th.TearDown() + th.App.Srv().SetLicense(nil) resp, err := th.SystemAdminClient.DoAPIPost("/license/review", "") From aa7939264fccaf044fb4085ea66f9b69a87cf82b Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Mon, 17 Apr 2023 15:09:54 -0400 Subject: [PATCH 09/10] Check if telemetry is disable, and only submit the true up profile if it is disabled. --- server/channels/api4/license.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/server/channels/api4/license.go b/server/channels/api4/license.go index a1b7806dbf..ff63704774 100644 --- a/server/channels/api4/license.go +++ b/server/channels/api4/license.go @@ -351,12 +351,15 @@ func requestTrueUpReview(c *Context, w http.ResponseWriter, r *http.Request) { return } - // True-up is only enabled when telemetry is disabled. When telemetry is enabled, we already have all the data necessary - // for true-up reviews to be completed. - err = c.App.Cloud().SubmitTrueUpReview(c.AppContext.Session().UserId, profileMap) - if err != nil { - c.Err = model.NewAppError("requestTrueUpReview", "api.license.true_up_review.failed_to_submit", nil, err.Error(), http.StatusInternalServerError) - return + // True-up is only enabled when telemetry is disabled. + // When telemetry is enabled, we already have all the data necessary for true-up reviews to be completed. + telemetryEnabled := c.App.Config().LogSettings.EnableDiagnostics + if telemetryEnabled != nil && !*telemetryEnabled { + err = c.App.Cloud().SubmitTrueUpReview(c.AppContext.Session().UserId, profileMap) + if err != nil { + c.Err = model.NewAppError("requestTrueUpReview", "api.license.true_up_review.failed_to_submit", nil, err.Error(), http.StatusInternalServerError) + return + } } // Update the review status to reflect the completion. From adff327b9c16acab7daea0391dd4fc7b357cf5a0 Mon Sep 17 00:00:00 2001 From: M-ZubairAhmed Date: Tue, 18 Apr 2023 01:04:45 +0530 Subject: [PATCH 10/10] MM-51977 : Remove inconsistencies of the duplicate IDs with different defaultMessages (#22965) * eslint format lib to root * eslint fixes * no id rule removed * same rectintl * try 1 * eslint format lib to root * eslint fixes * no id rule removed * same rectintl * react intl in root * type fix * add back version to components * missing translations added * remove type casting * a * type fix formatjs * snaps updated * Update package-lock.json * Update package-lock.json * rem * snapshot updates --------- Co-authored-by: Mattermost Build --- webapp/channels/src/actions/command.ts | 4 +- .../setting_picture.test.tsx.snap | 16 +- .../top_channels_line_chart.test.tsx.snap | 4 +- .../top_channels_line_chart.tsx | 2 +- .../trial_banner/trial_banner.tsx | 21 +- .../request_button.test.tsx.snap | 36 +- .../request_button/request_button.test.tsx | 28 +- .../admin_console/server_logs/log_list.tsx | 2 +- .../cloud_trial_announcement_bar.tsx | 2 +- .../apps_form/apps_form_component.tsx | 6 +- .../apps_form/apps_form_container.tsx | 6 +- .../channel_groups_manage_modal.tsx | 2 +- .../cloud_start_trial_btn.tsx | 24 +- .../src/components/dot_menu/dot_menu.tsx | 4 +- .../__snapshots__/panel_body.test.tsx.snap | 4 +- .../components/emoji_picker_preview.tsx | 2 +- .../src/components/error_page/error_page.tsx | 4 +- .../file_preview_modal_main_nav.test.tsx.snap | 2 +- .../file_preview_modal_main_nav.tsx | 2 +- .../header_footer_template.test.tsx.snap | 8 + .../header_footer_template.tsx | 20 +- .../abstract_incoming_hook.test.tsx.snap | 12 +- .../abstract_outgoing_webhook.test.jsx.snap | 2 +- .../installed_outgoing_webhook.test.jsx.snap | 2 +- .../abstract_incoming_webhook.tsx | 2 +- .../abstract_outgoing_webhook.jsx | 2 +- .../__snapshots__/add_bot.test.tsx.snap | 362 ++++++++++++++++++ .../bots/add_bot/add_bot.test.tsx | 8 +- .../integrations/bots/add_bot/add_bot.tsx | 6 +- .../confirm_integration.test.tsx.snap | 8 +- .../confirm_integration.tsx | 8 +- .../installed_oauth_apps.test.tsx.snap | 2 +- .../installed_oauth_apps.tsx | 2 +- .../installed_outgoing_webhook.tsx | 2 +- .../post_priority/post_priority_label.tsx | 4 +- .../profile_popover.test.tsx.snap | 20 +- .../profile_popover/profile_popover.tsx | 2 +- .../success_page.tsx | 2 +- .../src/components/setting_picture.test.tsx | 2 +- .../add_channels_cta_button.test.tsx.snap | 4 +- .../sidebar/add_channels_cta_button.tsx | 2 +- .../app_command_parser/app_command_parser.ts | 12 +- .../team_groups_manage_modal.tsx | 2 +- .../general/user_settings_general.tsx | 2 +- .../email_notification_setting.test.tsx.snap | 4 +- .../email_notification_setting.tsx | 2 +- .../view_user_group_modal_header.tsx | 2 +- webapp/channels/src/i18n/en.json | 25 +- .../src/plugins/call_button/call_button.tsx | 2 +- 49 files changed, 565 insertions(+), 139 deletions(-) create mode 100644 webapp/channels/src/components/integrations/bots/add_bot/__snapshots__/add_bot.test.tsx.snap diff --git a/webapp/channels/src/actions/command.ts b/webapp/channels/src/actions/command.ts index 62195ac6dc..8b86ec2f43 100644 --- a/webapp/channels/src/actions/command.ts +++ b/webapp/channels/src/actions/command.ts @@ -175,7 +175,7 @@ export function executeCommand(message: string, args: CommandArgs): ActionFunc { const errorResponse = res.error; return createErrorMessage(errorResponse.text || intlShim.formatMessage({ id: 'apps.error.unknown', - defaultMessage: 'Unknown error.', + defaultMessage: 'Unknown error occurred.', })); } @@ -201,7 +201,7 @@ export function executeCommand(message: string, args: CommandArgs): ActionFunc { )); } } catch (err: any) { - return createErrorMessage(err.message || localizeMessage('apps.error.unknown', 'Unknown error.')); + return createErrorMessage(err.message || localizeMessage('apps.error.unknown', 'Unknown error occurred.')); } } } diff --git a/webapp/channels/src/components/__snapshots__/setting_picture.test.tsx.snap b/webapp/channels/src/components/__snapshots__/setting_picture.test.tsx.snap index 0b9111bc4c..df524dcda4 100644 --- a/webapp/channels/src/components/__snapshots__/setting_picture.test.tsx.snap +++ b/webapp/channels/src/components/__snapshots__/setting_picture.test.tsx.snap @@ -34,7 +34,7 @@ exports[`components/SettingItemMin should match snapshot with active Save button > } > @@ -237,7 +237,7 @@ exports[`components/activity_and_insights/insights/top_channels should match sna > Top Channels diff --git a/webapp/channels/src/components/activity_and_insights/insights/top_channels/top_channels_line_chart/top_channels_line_chart.tsx b/webapp/channels/src/components/activity_and_insights/insights/top_channels/top_channels_line_chart/top_channels_line_chart.tsx index 8acab322b3..aa2d3d5bb4 100644 --- a/webapp/channels/src/components/activity_and_insights/insights/top_channels/top_channels_line_chart/top_channels_line_chart.tsx +++ b/webapp/channels/src/components/activity_and_insights/insights/top_channels/top_channels_line_chart/top_channels_line_chart.tsx @@ -115,7 +115,7 @@ const TopChannelsLineChart = ({topChannels, timeFrame, channelLineChartData, tim } diff --git a/webapp/channels/src/components/admin_console/license_settings/trial_banner/trial_banner.tsx b/webapp/channels/src/components/admin_console/license_settings/trial_banner/trial_banner.tsx index ba97c6a2f0..17f13e3861 100644 --- a/webapp/channels/src/components/admin_console/license_settings/trial_banner/trial_banner.tsx +++ b/webapp/channels/src/components/admin_console/license_settings/trial_banner/trial_banner.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useEffect, useState} from 'react'; +import React, {useEffect, useState, ReactNode} from 'react'; import {FormattedMessage, useIntl} from 'react-intl'; import {useDispatch, useSelector} from 'react-redux'; @@ -106,7 +106,7 @@ const TrialBanner = ({ const dispatch = useDispatch(); - const btnText = (status: TrialLoadStatus): string => { + const btnText = (status: TrialLoadStatus) => { switch (status) { case TrialLoadStatus.Started: return formatMessage({id: 'start_trial.modal.gettingTrial', defaultMessage: 'Getting Trial...'}); @@ -115,7 +115,22 @@ const TrialBanner = ({ case TrialLoadStatus.Failed: return formatMessage({id: 'start_trial.modal.failed', defaultMessage: 'Failed'}); case TrialLoadStatus.Embargoed: - return formatMessage({id: 'admin.license.trial-request.embargoed'}); + return formatMessage( + { + id: 'admin.license.trial-request.embargoed', + defaultMessage: 'We were unable to process the request due to limitations for embargoed countries. Learn more in our documentation, or reach out to legal@mattermost.com for questions around export limitations.', + }, + { + link: (text: string) => ( + + {text} + + ), + }, + ); default: return formatMessage({id: 'admin.license.trial-request.startTrial', defaultMessage: 'Start trial'}); } diff --git a/webapp/channels/src/components/admin_console/request_button/__snapshots__/request_button.test.tsx.snap b/webapp/channels/src/components/admin_console/request_button/__snapshots__/request_button.test.tsx.snap index a13c3bb7ec..142bbd54a4 100644 --- a/webapp/channels/src/components/admin_console/request_button/__snapshots__/request_button.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/request_button/__snapshots__/request_button.test.tsx.snap @@ -20,7 +20,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match > @@ -30,7 +30,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match > @@ -42,7 +42,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match buttonText={ } disabled={false} @@ -55,7 +55,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match helpText={ } includeDetailedError={true} @@ -103,7 +103,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match > Button Text @@ -154,7 +154,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match > Help Text @@ -171,7 +171,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match buttonText={ } disabled={false} @@ -184,7 +184,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match helpText={ } includeDetailedError={false} @@ -240,7 +240,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match > Button Text @@ -291,7 +291,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match > Help Text @@ -308,7 +308,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match buttonText={ } disabled={false} @@ -321,7 +321,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match helpText={ } includeDetailedError={false} @@ -369,7 +369,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match > Button Text @@ -413,7 +413,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match > Help Text @@ -430,7 +430,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match buttonText={ } disabled={false} @@ -443,7 +443,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match helpText={ } includeDetailedError={false} @@ -499,7 +499,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match > Button Text @@ -513,7 +513,7 @@ exports[`components/admin_console/request_button/request_button.jsx should match > Help Text diff --git a/webapp/channels/src/components/admin_console/request_button/request_button.test.tsx b/webapp/channels/src/components/admin_console/request_button/request_button.test.tsx index f4ec173212..176669253f 100644 --- a/webapp/channels/src/components/admin_console/request_button/request_button.test.tsx +++ b/webapp/channels/src/components/admin_console/request_button/request_button.test.tsx @@ -18,13 +18,13 @@ describe('components/admin_console/request_button/request_button.jsx', () => { requestAction={emptyFunction} helpText={ } buttonText={ } @@ -42,13 +42,13 @@ describe('components/admin_console/request_button/request_button.jsx', () => { requestAction={requestActionSuccess} helpText={ } buttonText={ } @@ -72,13 +72,13 @@ describe('components/admin_console/request_button/request_button.jsx', () => { requestAction={requestActionSuccess} helpText={ } buttonText={ } @@ -102,13 +102,13 @@ describe('components/admin_console/request_button/request_button.jsx', () => { requestAction={requestActionSuccess} helpText={ } buttonText={ } @@ -129,13 +129,13 @@ describe('components/admin_console/request_button/request_button.jsx', () => { requestAction={requestActionSuccess} helpText={ } buttonText={ } @@ -164,13 +164,13 @@ describe('components/admin_console/request_button/request_button.jsx', () => { requestAction={requestActionFailure} helpText={ } buttonText={ } @@ -191,13 +191,13 @@ describe('components/admin_console/request_button/request_button.jsx', () => { requestAction={requestActionFailure} helpText={ } buttonText={ } diff --git a/webapp/channels/src/components/admin_console/server_logs/log_list.tsx b/webapp/channels/src/components/admin_console/server_logs/log_list.tsx index d73d3d4b4e..ce8fa09e16 100644 --- a/webapp/channels/src/components/admin_console/server_logs/log_list.tsx +++ b/webapp/channels/src/components/admin_console/server_logs/log_list.tsx @@ -95,7 +95,7 @@ export default class LogList extends React.PureComponent { ); const level: JSX.Element = ( ); diff --git a/webapp/channels/src/components/announcement_bar/cloud_trial_announcement_bar/cloud_trial_announcement_bar.tsx b/webapp/channels/src/components/announcement_bar/cloud_trial_announcement_bar/cloud_trial_announcement_bar.tsx index 8224463d43..f03effb517 100644 --- a/webapp/channels/src/components/announcement_bar/cloud_trial_announcement_bar/cloud_trial_announcement_bar.tsx +++ b/webapp/channels/src/components/announcement_bar/cloud_trial_announcement_bar/cloud_trial_announcement_bar.tsx @@ -137,7 +137,7 @@ class CloudTrialAnnouncementBar extends React.PureComponent { let trialMoreThan7DaysMsg = ( diff --git a/webapp/channels/src/components/apps_form/apps_form_component.tsx b/webapp/channels/src/components/apps_form/apps_form_component.tsx index a83eb11274..f682058ece 100644 --- a/webapp/channels/src/components/apps_form/apps_form_component.tsx +++ b/webapp/channels/src/components/apps_form/apps_form_component.tsx @@ -234,7 +234,7 @@ export class AppsForm extends React.PureComponent { const errorResponse = res.error; const errMsg = errorResponse.text || intl.formatMessage({ id: 'apps.error.unknown', - defaultMessage: 'Unknown error.', + defaultMessage: 'Unknown error occurred.', }); this.setState({ fieldErrors: { @@ -256,7 +256,7 @@ export class AppsForm extends React.PureComponent { case AppCallResponseTypes.NAVIGATE: { const errMsg = intl.formatMessage({ id: 'apps.error.responses.unexpected_type', - defaultMessage: 'App response type was not expected. Response type: {type}.', + defaultMessage: 'App response type was not expected. Response type: {type}', }, { type: callResp.type, }, @@ -338,7 +338,7 @@ export class AppsForm extends React.PureComponent { case AppCallResponseTypes.NAVIGATE: this.updateErrors([], undefined, this.props.intl.formatMessage({ id: 'apps.error.responses.unexpected_type', - defaultMessage: 'App response type was not expected. Response type: {type}.', + defaultMessage: 'App response type was not expected. Response type: {type}', }, { type: callResponse.type, })); diff --git a/webapp/channels/src/components/apps_form/apps_form_container.tsx b/webapp/channels/src/components/apps_form/apps_form_container.tsx index 2a816bb5d8..3e018f2e81 100644 --- a/webapp/channels/src/components/apps_form/apps_form_container.tsx +++ b/webapp/channels/src/components/apps_form/apps_form_container.tsx @@ -48,7 +48,7 @@ class AppsFormContainer extends React.PureComponent { }; const {form} = this.state; if (!form) { - const errMsg = this.props.intl.formatMessage({id: 'apps.error.form.no_form', defaultMessage: '`form` is not defined'}); + const errMsg = this.props.intl.formatMessage({id: 'apps.error.form.no_form', defaultMessage: '`form` is not defined.'}); return {error: makeCallErrorResponse(makeErrorMsg(errMsg))}; } if (!form.submit) { @@ -97,7 +97,7 @@ class AppsFormContainer extends React.PureComponent { refreshOnSelect = async (field: AppField, values: AppFormValues): Promise> => { const makeErrMsg = (message: string) => this.props.intl.formatMessage( { - id: 'apps.error.form.refresh', + id: 'apps.error.form.update', defaultMessage: 'There has been an error updating the modal. Contact the app developer. Details: {details}', }, {details: message}, @@ -144,7 +144,7 @@ class AppsFormContainer extends React.PureComponent { case AppCallResponseTypes.NAVIGATE: return {error: makeCallErrorResponse(makeErrMsg(this.props.intl.formatMessage({ id: 'apps.error.responses.unexpected_type', - defaultMessage: 'App response type was not expected. Response type: {type}.', + defaultMessage: 'App response type was not expected. Response type: {type}', }, { type: callResp.type, }, diff --git a/webapp/channels/src/components/channel_groups_manage_modal/channel_groups_manage_modal.tsx b/webapp/channels/src/components/channel_groups_manage_modal/channel_groups_manage_modal.tsx index 9bcf5d106e..5bcec33c60 100644 --- a/webapp/channels/src/components/channel_groups_manage_modal/channel_groups_manage_modal.tsx +++ b/webapp/channels/src/components/channel_groups_manage_modal/channel_groups_manage_modal.tsx @@ -145,7 +145,7 @@ class ChannelGroupsManageModal extends React.PureComponent { const {formatMessage} = this.props.intl; return ( { + const btnText = (status: TrialLoadStatus) => { switch (status) { case TrialLoadStatus.Started: return formatMessage({id: 'start_cloud_trial.modal.gettingTrial', defaultMessage: 'Getting Trial...'}); @@ -138,7 +139,22 @@ const CloudStartTrialButton = ({ case TrialLoadStatus.Failed: return formatMessage({id: 'start_cloud_trial.modal.failed', defaultMessage: 'Failed'}); case TrialLoadStatus.Embargoed: - return formatMessage({id: 'admin.license.trial-request.embargoed'}); + return formatMessage( + { + id: 'admin.license.trial-request.embargoed', + defaultMessage: 'We were unable to process the request due to limitations for embargoed countries. Learn more in our documentation, or reach out to legal@mattermost.com for questions around export limitations.', + }, + { + link: (text: string) => ( + + {text} + + ), + }, + ); default: return message; } diff --git a/webapp/channels/src/components/dot_menu/dot_menu.tsx b/webapp/channels/src/components/dot_menu/dot_menu.tsx index 89068ae450..be3d6afa13 100644 --- a/webapp/channels/src/components/dot_menu/dot_menu.tsx +++ b/webapp/channels/src/components/dot_menu/dot_menu.tsx @@ -497,7 +497,7 @@ export class DotMenuClass extends React.PureComponent { class: classNames('post-menu__item', { 'post-menu__item--active': this.props.isMenuOpen, }), - 'aria-label': formatMessage({id: 'post_info.dot_menu.tooltip.more_actions', defaultMessage: 'Actions'}), + 'aria-label': formatMessage({id: 'post_info.dot_menu.tooltip.actions', defaultMessage: 'Actions'}), children: , }} menu={{ @@ -510,7 +510,7 @@ export class DotMenuClass extends React.PureComponent { }} menuButtonTooltip={{ id: `PostDotMenu-ButtonTooltip-${this.props.post.id}`, - text: formatMessage({id: 'post_info.dot_menu.tooltip.more_actions', defaultMessage: 'More'}), + text: formatMessage({id: 'post_info.dot_menu.tooltip.more', defaultMessage: 'More'}), class: 'hidden-xs', }} > diff --git a/webapp/channels/src/components/drafts/panel/__snapshots__/panel_body.test.tsx.snap b/webapp/channels/src/components/drafts/panel/__snapshots__/panel_body.test.tsx.snap index b173fc6031..45e0bcc69f 100644 --- a/webapp/channels/src/components/drafts/panel/__snapshots__/panel_body.test.tsx.snap +++ b/webapp/channels/src/components/drafts/panel/__snapshots__/panel_body.test.tsx.snap @@ -786,7 +786,7 @@ exports[`components/drafts/panel/panel_body should match snapshot for priority 1 @@ -818,7 +818,7 @@ exports[`components/drafts/panel/panel_body should match snapshot for priority 1 - IMPORTANT + Important diff --git a/webapp/channels/src/components/emoji_picker/components/emoji_picker_preview.tsx b/webapp/channels/src/components/emoji_picker/components/emoji_picker_preview.tsx index 12e0905332..b52a3a8ace 100644 --- a/webapp/channels/src/components/emoji_picker/components/emoji_picker_preview.tsx +++ b/webapp/channels/src/components/emoji_picker/components/emoji_picker_preview.tsx @@ -18,7 +18,7 @@ function EmojiPickerPreview({emoji}: Props) { return (
diff --git a/webapp/channels/src/components/error_page/error_page.tsx b/webapp/channels/src/components/error_page/error_page.tsx index 349f978d7c..d180549721 100644 --- a/webapp/channels/src/components/error_page/error_page.tsx +++ b/webapp/channels/src/components/error_page/error_page.tsx @@ -79,7 +79,7 @@ export default class ErrorPage extends React.PureComponent { backButton = ( { backButton = ( } diff --git a/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/file_preview_modal_main_nav.tsx b/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/file_preview_modal_main_nav.tsx index 4f97c4e7a8..ebb6cf5d59 100644 --- a/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/file_preview_modal_main_nav.tsx +++ b/webapp/channels/src/components/file_preview_modal/file_preview_modal_main_nav/file_preview_modal_main_nav.tsx @@ -26,7 +26,7 @@ const FilePreviewModalMainNav: React.FC = (props: Props) => { overlay={ diff --git a/webapp/channels/src/components/header_footer_template/__snapshots__/header_footer_template.test.tsx.snap b/webapp/channels/src/components/header_footer_template/__snapshots__/header_footer_template.test.tsx.snap index bb4dd6479b..1b51b5dbbd 100644 --- a/webapp/channels/src/components/header_footer_template/__snapshots__/header_footer_template.test.tsx.snap +++ b/webapp/channels/src/components/header_footer_template/__snapshots__/header_footer_template.test.tsx.snap @@ -44,6 +44,7 @@ exports[`components/HeaderFooterTemplate should match snapshot with about link 1 location="header_footer_template" > @@ -98,6 +99,7 @@ exports[`components/HeaderFooterTemplate should match snapshot with all links 1` location="header_footer_template" > @@ -109,6 +111,7 @@ exports[`components/HeaderFooterTemplate should match snapshot with all links 1` location="header_footer_template" > @@ -120,6 +123,7 @@ exports[`components/HeaderFooterTemplate should match snapshot with all links 1` location="header_footer_template" > @@ -131,6 +135,7 @@ exports[`components/HeaderFooterTemplate should match snapshot with all links 1` location="header_footer_template" > @@ -231,6 +236,7 @@ exports[`components/HeaderFooterTemplate should match snapshot with help link 1` location="header_footer_template" > @@ -285,6 +291,7 @@ exports[`components/HeaderFooterTemplate should match snapshot with privacy poli location="header_footer_template" > @@ -339,6 +346,7 @@ exports[`components/HeaderFooterTemplate should match snapshot with term of serv location="header_footer_template" > diff --git a/webapp/channels/src/components/header_footer_template/header_footer_template.tsx b/webapp/channels/src/components/header_footer_template/header_footer_template.tsx index 66dc865749..e5be8d3d19 100644 --- a/webapp/channels/src/components/header_footer_template/header_footer_template.tsx +++ b/webapp/channels/src/components/header_footer_template/header_footer_template.tsx @@ -57,7 +57,10 @@ export default class NotLoggedIn extends React.PureComponent { location='header_footer_template' href={this.props.config.AboutLink} > - + , ); } @@ -71,7 +74,10 @@ export default class NotLoggedIn extends React.PureComponent { location='header_footer_template' href={this.props.config.PrivacyPolicyLink} > - + , ); } @@ -85,7 +91,10 @@ export default class NotLoggedIn extends React.PureComponent { location='header_footer_template' href={this.props.config.TermsOfServiceLink} > - + , ); } @@ -99,7 +108,10 @@ export default class NotLoggedIn extends React.PureComponent { location='header_footer_template' href={this.props.config.HelpLink} > - + , ); } diff --git a/webapp/channels/src/components/integrations/__snapshots__/abstract_incoming_hook.test.tsx.snap b/webapp/channels/src/components/integrations/__snapshots__/abstract_incoming_hook.test.tsx.snap index b8fb192a10..45678e2f48 100644 --- a/webapp/channels/src/components/integrations/__snapshots__/abstract_incoming_hook.test.tsx.snap +++ b/webapp/channels/src/components/integrations/__snapshots__/abstract_incoming_hook.test.tsx.snap @@ -10,7 +10,7 @@ exports[`components/integrations/AbstractIncomingWebhook should call action func > diff --git a/webapp/channels/src/components/integrations/abstract_incoming_webhook.tsx b/webapp/channels/src/components/integrations/abstract_incoming_webhook.tsx index c3079b1f7f..cfeb445fff 100644 --- a/webapp/channels/src/components/integrations/abstract_incoming_webhook.tsx +++ b/webapp/channels/src/components/integrations/abstract_incoming_webhook.tsx @@ -184,7 +184,7 @@ export default class AbstractIncomingWebhook extends PureComponent diff --git a/webapp/channels/src/components/integrations/abstract_outgoing_webhook.jsx b/webapp/channels/src/components/integrations/abstract_outgoing_webhook.jsx index dff8215612..ff25337f81 100644 --- a/webapp/channels/src/components/integrations/abstract_outgoing_webhook.jsx +++ b/webapp/channels/src/components/integrations/abstract_outgoing_webhook.jsx @@ -249,7 +249,7 @@ export default class AbstractOutgoingWebhook extends React.PureComponent { diff --git a/webapp/channels/src/components/integrations/bots/add_bot/__snapshots__/add_bot.test.tsx.snap b/webapp/channels/src/components/integrations/bots/add_bot/__snapshots__/add_bot.test.tsx.snap new file mode 100644 index 0000000000..f5cf10dd4e --- /dev/null +++ b/webapp/channels/src/components/integrations/bots/add_bot/__snapshots__/add_bot.test.tsx.snap @@ -0,0 +1,362 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`components/integrations/bots/AddBot blank 1`] = ` +
+ + + + + + +
+
+
+ +
+ +
+ +
+
+
+
+ +
+
+ bot image +
+
+ + +
+
+
+
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+ +
+ +
+ +
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ + + + + + } + type="submit" + > + + +
+
+
+
+`; diff --git a/webapp/channels/src/components/integrations/bots/add_bot/add_bot.test.tsx b/webapp/channels/src/components/integrations/bots/add_bot/add_bot.test.tsx index 5b3b646558..6ad0083e04 100644 --- a/webapp/channels/src/components/integrations/bots/add_bot/add_bot.test.tsx +++ b/webapp/channels/src/components/integrations/bots/add_bot/add_bot.test.tsx @@ -3,9 +3,7 @@ import React from 'react'; import {shallow} from 'enzyme'; -import {FormattedMessage} from 'react-intl'; -// import TestHelper from 'mattermost-redux/test/test_helper'; import {TestHelper} from 'utils/test_helper'; import AddBot from './add_bot'; @@ -49,11 +47,7 @@ describe('components/integrations/bots/AddBot', () => { value={''} />, )).toEqual(true); - expect(wrapper.containsMatchingElement( - , - )).toEqual(true); + expect(wrapper).toMatchSnapshot(); }); it('edit bot', () => { diff --git a/webapp/channels/src/components/integrations/bots/add_bot/add_bot.tsx b/webapp/channels/src/components/integrations/bots/add_bot/add_bot.tsx index 00c31afd06..3aade0e6ec 100644 --- a/webapp/channels/src/components/integrations/bots/add_bot/add_bot.tsx +++ b/webapp/channels/src/components/integrations/bots/add_bot/add_bot.tsx @@ -322,7 +322,7 @@ export default class AddBot extends React.PureComponent { error: ( ), }; @@ -383,7 +383,7 @@ export default class AddBot extends React.PureComponent { render() { let subtitle = ( ); @@ -630,7 +630,7 @@ export default class AddBot extends React.PureComponent {
( diff --git a/webapp/channels/src/components/integrations/confirm_integration/__snapshots__/confirm_integration.test.tsx.snap b/webapp/channels/src/components/integrations/confirm_integration/__snapshots__/confirm_integration.test.tsx.snap index 1c3a97c154..551911427b 100644 --- a/webapp/channels/src/components/integrations/confirm_integration/__snapshots__/confirm_integration.test.tsx.snap +++ b/webapp/channels/src/components/integrations/confirm_integration/__snapshots__/confirm_integration.test.tsx.snap @@ -12,7 +12,7 @@ exports[`components/integrations/ConfirmIntegration should match snapshot, comma > ); @@ -100,7 +100,7 @@ const ConfirmIntegration = ({team, location, commands, oauthApps, incomingHooks, headerText = ( ); @@ -137,7 +137,7 @@ const ConfirmIntegration = ({team, location, commands, oauthApps, incomingHooks, headerText = ( ); @@ -175,7 +175,7 @@ const ConfirmIntegration = ({team, location, commands, oauthApps, incomingHooks, headerText = ( ); diff --git a/webapp/channels/src/components/integrations/installed_oauth_apps/__snapshots__/installed_oauth_apps.test.tsx.snap b/webapp/channels/src/components/integrations/installed_oauth_apps/__snapshots__/installed_oauth_apps.test.tsx.snap index fa20d79ce1..38c7aef4c9 100644 --- a/webapp/channels/src/components/integrations/installed_oauth_apps/__snapshots__/installed_oauth_apps.test.tsx.snap +++ b/webapp/channels/src/components/integrations/installed_oauth_apps/__snapshots__/installed_oauth_apps.test.tsx.snap @@ -20,7 +20,7 @@ exports[`components/integrations/InstalledOAuthApps should match snapshot 1`] = header={ } helpText={ diff --git a/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx b/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx index 1a068e8366..2abeaef631 100644 --- a/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx +++ b/webapp/channels/src/components/integrations/installed_oauth_apps/installed_oauth_apps.tsx @@ -134,7 +134,7 @@ export default class InstalledOAuthApps extends React.PureComponent } diff --git a/webapp/channels/src/components/integrations/installed_outgoing_webhook.tsx b/webapp/channels/src/components/integrations/installed_outgoing_webhook.tsx index 0c01d69962..a07e3e63e5 100644 --- a/webapp/channels/src/components/integrations/installed_outgoing_webhook.tsx +++ b/webapp/channels/src/components/integrations/installed_outgoing_webhook.tsx @@ -167,7 +167,7 @@ export default class InstalledOutgoingWebhook extends React.PureComponent > {' - '} diff --git a/webapp/channels/src/components/post_priority/post_priority_label.tsx b/webapp/channels/src/components/post_priority/post_priority_label.tsx index 770c857cc7..a11c0deda3 100644 --- a/webapp/channels/src/components/post_priority/post_priority_label.tsx +++ b/webapp/channels/src/components/post_priority/post_priority_label.tsx @@ -26,7 +26,7 @@ export default function PriorityLabel({ {...rest} variant='danger' icon={'alert-outline'} - text={formatMessage({id: 'post_priority.priority.urgent', defaultMessage: 'URGENT'})} + text={formatMessage({id: 'post_priority.priority.urgent', defaultMessage: 'Urgent'})} uppercase={true} /> ); @@ -38,7 +38,7 @@ export default function PriorityLabel({ {...rest} variant='info' icon={'alert-circle-outline'} - text={formatMessage({id: 'post_priority.priority.important', defaultMessage: 'IMPORTANT'})} + text={formatMessage({id: 'post_priority.priority.important', defaultMessage: 'Important'})} uppercase={true} /> ); diff --git a/webapp/channels/src/components/profile_popover/__snapshots__/profile_popover.test.tsx.snap b/webapp/channels/src/components/profile_popover/__snapshots__/profile_popover.test.tsx.snap index aba8e516d7..3f98bb1301 100644 --- a/webapp/channels/src/components/profile_popover/__snapshots__/profile_popover.test.tsx.snap +++ b/webapp/channels/src/components/profile_popover/__snapshots__/profile_popover.test.tsx.snap @@ -79,7 +79,7 @@ exports[`components/ProfilePopover should disable start call button when user is > diff --git a/webapp/channels/src/components/setting_picture.test.tsx b/webapp/channels/src/components/setting_picture.test.tsx index 828ff3c024..ab7d85d9de 100644 --- a/webapp/channels/src/components/setting_picture.test.tsx +++ b/webapp/channels/src/components/setting_picture.test.tsx @@ -10,7 +10,7 @@ import SettingPicture from 'components/setting_picture'; const helpText: ReactNode = ( diff --git a/webapp/channels/src/components/sidebar/__snapshots__/add_channels_cta_button.test.tsx.snap b/webapp/channels/src/components/sidebar/__snapshots__/add_channels_cta_button.test.tsx.snap index 893aaa0ffe..f89d1c3fb8 100644 --- a/webapp/channels/src/components/sidebar/__snapshots__/add_channels_cta_button.test.tsx.snap +++ b/webapp/channels/src/components/sidebar/__snapshots__/add_channels_cta_button.test.tsx.snap @@ -8,7 +8,7 @@ exports[`components/new_channel_modal should match snapshot 1`] = ` open={false} > ); diff --git a/webapp/channels/src/i18n/en.json b/webapp/channels/src/i18n/en.json index 238b42172d..792ca8cf0d 100644 --- a/webapp/channels/src/i18n/en.json +++ b/webapp/channels/src/i18n/en.json @@ -184,6 +184,7 @@ "add_outgoing_webhook.displayName": "Title", "add_outgoing_webhook.displayName.help": "Specify a title for the webhook settings page. The title can contain up to 64 characters.", "add_outgoing_webhook.doneHelp": "Your outgoing webhook is set up. The following token will be sent in the outgoing payload. Please use it to verify the request came from your Mattermost team (details at Outgoing Webhooks).", + "add_outgoing_webhook.header": "Outgoing Webhooks", "add_outgoing_webhook.icon_url": "Profile Picture", "add_outgoing_webhook.icon_url.help": "Enter the URL of a .png or .jpg file for this integration to use as the profile picture when posting. The file should be at least 128 pixels by 128 pixels. If left blank, the profile picture specified by the webhook creator is used.", "add_outgoing_webhook.save": "Save", @@ -307,6 +308,7 @@ "admin.billing.subscription.cloudReverseTrial.daysLeftOnTrial": "{daysLeftOnTrial} days left on your trial. Purchase a plan or contact sales to keep your workspace.", "admin.billing.subscription.cloudReverseTrial.lastDay": "This is the last day of your trial. Purchase a plan before {userEndTrialHour} or contact sales", "admin.billing.subscription.cloudReverseTrial.subscribeButton": "Review your options", + "admin.billing.subscription.cloudTrial.daysLeft": "Your trial has started! There are {daysLeftOnTrial} days left", "admin.billing.subscription.cloudTrial.daysLeftOnTrial": "There are {daysLeftOnTrial} days left on your free trial", "admin.billing.subscription.cloudTrial.lastDay": "This is the last day of your free trial. Your access will expire on {userEndTrialDate} at {userEndTrialHour}.", "admin.billing.subscription.cloudTrial.moreThan3Days": "Your trial has started! There are {daysLeftOnTrial} days left", @@ -400,6 +402,7 @@ "admin.billing.subscription.providePaymentDetails": "Provide your payment details", "admin.billing.subscription.returnToTeam": "Return to {team}", "admin.billing.subscription.stateprovince": "State/Province", + "admin.billing.subscription.subscribedSuccess": "You're now subscribed to {productName}", "admin.billing.subscription.switchedToAnnual.title": "You're now switched to {selectedProductName} annual", "admin.billing.subscription.title": "Subscription", "admin.billing.subscription.updatePaymentInfo": "Update Payment Information", @@ -1384,6 +1387,7 @@ "admin.log.fileLevelTitle": "File Log Level:", "admin.log.fileTitle": "Output logs to file: ", "admin.log.jsonDescription": "When true, logged events are written in a machine readable JSON format. Otherwise they are printed as plain text. Changing this setting requires a server restart before taking effect.", + "admin.log.Level": "Level", "admin.log.levelDescription": "This setting determines the level of detail at which log events are written to the console. ERROR: Outputs only error messages. INFO: Outputs error messages and information around startup and initialization. DEBUG: Prints high detail for developers working on debugging issues.", "admin.log.levelTitle": "Console Log Level:", "admin.log.locationDescription": "The location of the log files. If blank, they are stored in the ./logs directory. The path that you set must exist and Mattermost must have write permissions in it. Changing this setting requires a server restart before taking effect.", @@ -1405,6 +1409,7 @@ "admin.manage_roles.additionalRoles": "Select additional permissions for the account. Read more about roles and permissions.", "admin.manage_roles.allowUserAccessTokens": "Allow this account to generate personal access tokens.", "admin.manage_roles.allowUserAccessTokensDesc": "Removing this permission doesn't delete existing tokens. To delete them, go to the user's Manage Tokens menu.", + "admin.manage_roles.botAdditionalRoles": "Select additional permissions for the account. Read more about roles and permissions.", "admin.manage_roles.cancel": "Cancel", "admin.manage_roles.manageRolesTitle": "Manage Roles", "admin.manage_roles.postAllPublicRole": "Access to post to all Mattermost public channels.", @@ -2588,6 +2593,7 @@ "analytics.system.skippedIntensiveQueries": "To maximize performance, some statistics are disabled. You can re-enable them in config.json.", "analytics.system.textPosts": "Posts with Text-only", "analytics.system.title": "System Statistics", + "analytics.system.topChannels": "Top Channels", "analytics.system.totalBotPosts": "Total Posts from Bots", "analytics.system.totalChannels": "Total Channels", "analytics.system.totalCommands": "Total Commands", @@ -2673,6 +2679,7 @@ "apps.error.form.refresh_no_refresh": "Called refresh on no refresh field.", "apps.error.form.required_fields_empty": "Please fix all field errors", "apps.error.form.submit.pretext": "There has been an error submitting the modal. Contact the app developer. Details: {details}", + "apps.error.form.update": "There has been an error updating the modal. Contact the app developer. Details: {details}", "apps.error.lookup.error_preparing_request": "Error preparing lookup request: {errorMessage}", "apps.error.malformed_binding": "This binding is not properly formed. Contact the App developer.", "apps.error.parser": "Parsing error: {error}", @@ -2817,6 +2824,7 @@ "bots.disabled": "Disabled", "bots.image.upload": "Upload Image", "bots.manage.add": "Add Bot Account", + "bots.manage.add.add": "Add", "bots.manage.add.cancel": "Cancel", "bots.manage.add.create": "Create Bot Account", "bots.manage.add.creating": "Creating...", @@ -2853,6 +2861,7 @@ "change_url.shorter": "URLs must have maximum 64 characters.", "change_url.startAndEndWithLetter": "URLs must start and end with a lowercase letter or number.", "change_url.startWithLetter": "URLs must start with a lowercase letter or number.", + "channel_groups": "{channel} Groups", "channel_header.addChannelHeader": "Add a channel header", "channel_header.channelFiles": "Channel files", "channel_header.channelHasGuests": "This channel has guests", @@ -2865,6 +2874,7 @@ "channel_header.flagged": "Saved posts", "channel_header.groupMessageHasGuests": "This group message has guests", "channel_header.lastActive": "Last online {timestamp}", + "channel_header.lastOnline": "Last online {timestamp}", "channel_header.leave": "Leave Channel", "channel_header.manageMembers": "Manage Members", "channel_header.menuAriaLabel": "Channel Menu", @@ -3345,6 +3355,7 @@ "emoji_picker.custom": "Custom", "emoji_picker.custom_emoji": "Custom Emoji", "emoji_picker.emojiPicker": "Select an Emoji", + "emoji_picker.emojiPicker.previewPlaceholder": "Select an Emoji", "emoji_picker.flags": "Flags", "emoji_picker.food-drink": "Food & Drink", "emoji_picker.header": "Emoji Picker", @@ -3377,6 +3388,7 @@ "error.generic.link": "Back to {siteName}", "error.generic.link_login": "Back to Login Page", "error.generic.message": "An error has occurred.", + "error.generic.siteLink": "Back to {siteName}", "error.generic.title": "Error", "error.local_storage.help1": "Enable cookies", "error.local_storage.help2": "Turn off private browsing", @@ -3564,6 +3576,7 @@ "generic_icons.warning": "Warning Icon", "generic_modal.cancel": "Cancel", "generic_modal.confirm": "Confirm", + "generic.close": "Close", "generic.done": "Done", "generic.next": "Next", "generic.previous": "Previous", @@ -3607,7 +3620,6 @@ "group_member_list.searchError": "There was a problem getting results. Clear your search term and try again.", "group_member_list.sendMessageButton": "Send message to {user}", "group_member_list.sendMessageTooltip": "Send message", - "groups": "{team} Groups", "help.attaching.downloading.description": "Download an attached file by selecting the Download icon next to the file thumbnail, or by opening the file previewer and selecting **Download**.", "help.attaching.downloading.title": "Download Files", "help.attaching.dragdrop.description": "Upload a file, or a selection of files, by dragging the files from your computer into the right-hand sidebar or center pane. Dragging and dropping attaches the files to the message input box, then you can optionally type a message and press **ENTER** to post the message.", @@ -3737,6 +3749,7 @@ "help.messaging.reply": "**Reply to Messages:** Select the **Reply Arrow** icon next to the text input box.", "help.messaging.title": "Messaging Basics", "help.messaging.write": "**Write Messages:** Use the text input box at the bottom of the Mattermost interface to write a message. Press **ENTER** to send the message. Use **SHIFT+ENTER** to create a new line without sending a message.", + "incoming_webhooks.header": "Incoming Webhooks", "inProduct_notices.adminOnlyMessage": "Visible to Admins only", "input.clear": "Clear", "insights.accessModal.cloudFreeTrial": "During your trial you are able to view Team Insights.", @@ -3884,6 +3897,7 @@ "installed_oauth_apps.trusted": "Is Trusted", "installed_oauth_apps.trusted.no": "No", "installed_oauth_apps.trusted.yes": "Yes", + "installed_oauth2_apps.header": "OAuth 2.0 Applications", "installed_outgoing_webhooks.add": "Add Outgoing Webhook", "installed_outgoing_webhooks.delete.confirm": "This action permanently deletes the outgoing webhook and breaks any integrations using it. Are you sure you want to delete it?", "installed_outgoing_webhooks.empty": "No outgoing webhooks found", @@ -4448,7 +4462,8 @@ "post_info.comment_icon.tooltip.reply": "Reply", "post_info.copy": "Copy Text", "post_info.del": "Delete", - "post_info.dot_menu.tooltip.more_actions": "More", + "post_info.dot_menu.tooltip.actions": "Actions", + "post_info.dot_menu.tooltip.more": "More", "post_info.edit": "Edit", "post_info.edit.aria_label": "Select to restore an old message.", "post_info.edit.current_version": "Current Version", @@ -4767,6 +4782,7 @@ "setting_item_min.edit": "Edit", "setting_picture.cancel": "Cancel", "setting_picture.help.profile": "Upload a picture in BMP, JPG, JPEG, or PNG format. Maximum file size: {max}", + "setting_picture.help.profile.example": "Upload a picture in BMP, JPG or PNG format. Maximum file size: {max}", "setting_picture.help.team": "Upload a team icon in BMP, JPG or PNG format.\nSquare images with a solid background color are recommended.", "setting_picture.remove": "Remove This Icon", "setting_picture.remove_profile_picture": "Remove Profile Picture", @@ -4996,6 +5012,7 @@ "single_image_view.copied_link_tooltip": "Copied", "single_image_view.copy_link_tooltip": "Copy link", "single_image_view.download_tooltip": "Download", + "slash_commands.header": "Slash Commands", "someting.string": "defaultString", "start_cloud_trial.modal.enter_trial_email.description": "Start a trial and enter a business email to get started. ", "start_cloud_trial.modal.enter_trial_email.input.label": "Enter business email", @@ -5090,6 +5107,7 @@ "tag.default.guest": "GUEST", "tag.default.new": "NEW", "team_channel_settings.group.group_user_row.numberOfGroups": "{amount, number} {amount, plural, one {Group} other {Groups}}", + "team_groups": "{team} Groups", "team_member_modal.invitePeople": "Invite People", "team_member_modal.members": "{team} Members", "team_members_dropdown.confirmDemoteDescription": "If you demote yourself from the System Admin role and there is not another user with System Admin privileges, you'll need to re-assign a System Admin by accessing the Mattermost server through a terminal and running the following command.", @@ -5125,7 +5143,8 @@ "terms_of_service.agreeButton": "I Agree", "terms_of_service.api_error": "Unable to complete the request. If this issue persists, contact your System Administrator.", "terms_of_service.disagreeButton": "I Disagree", - "test": "Button Text", + "test1": "Help Text", + "test2": "Button Text", "textbox.bold": "**bold**", "textbox.edit": "Edit message", "textbox.help": "Help", diff --git a/webapp/channels/src/plugins/call_button/call_button.tsx b/webapp/channels/src/plugins/call_button/call_button.tsx index 0baf551f08..2336ef3c45 100644 --- a/webapp/channels/src/plugins/call_button/call_button.tsx +++ b/webapp/channels/src/plugins/call_button/call_button.tsx @@ -96,7 +96,7 @@ export default function CallButton({pluginCallComponents, currentChannel, channe {'Call'}