[MM-53702] Remove Downgrade Team Selection modal and all accompanying logic (#24059)
* Remove Downgrade Team Selection modal and all accompanying logic * fix linter * Fix i18n * Final pipeline fixes
Этот коммит содержится в:
@@ -42,7 +42,6 @@ func (api *API) InitTeam() {
|
|||||||
api.BaseRoutes.Team.Handle("", api.APISessionRequired(getTeam)).Methods("GET")
|
api.BaseRoutes.Team.Handle("", api.APISessionRequired(getTeam)).Methods("GET")
|
||||||
api.BaseRoutes.Team.Handle("", api.APISessionRequired(updateTeam)).Methods("PUT")
|
api.BaseRoutes.Team.Handle("", api.APISessionRequired(updateTeam)).Methods("PUT")
|
||||||
api.BaseRoutes.Team.Handle("", api.APISessionRequired(deleteTeam)).Methods("DELETE")
|
api.BaseRoutes.Team.Handle("", api.APISessionRequired(deleteTeam)).Methods("DELETE")
|
||||||
api.BaseRoutes.Team.Handle("/except", api.APISessionRequired(softDeleteTeamsExcept)).Methods("DELETE")
|
|
||||||
api.BaseRoutes.Team.Handle("/patch", api.APISessionRequired(patchTeam)).Methods("PUT")
|
api.BaseRoutes.Team.Handle("/patch", api.APISessionRequired(patchTeam)).Methods("PUT")
|
||||||
api.BaseRoutes.Team.Handle("/restore", api.APISessionRequired(restoreTeam)).Methods("POST")
|
api.BaseRoutes.Team.Handle("/restore", api.APISessionRequired(restoreTeam)).Methods("POST")
|
||||||
api.BaseRoutes.Team.Handle("/privacy", api.APISessionRequired(updateTeamPrivacy)).Methods("PUT")
|
api.BaseRoutes.Team.Handle("/privacy", api.APISessionRequired(updateTeamPrivacy)).Methods("PUT")
|
||||||
@@ -464,25 +463,6 @@ func deleteTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
ReturnStatusOK(w)
|
ReturnStatusOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
func softDeleteTeamsExcept(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
||||||
c.RequireTeamId()
|
|
||||||
if c.Err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), c.Params.TeamId, model.PermissionManageTeam) {
|
|
||||||
c.SetPermissionError(model.PermissionManageTeam)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err := c.App.SoftDeleteAllTeamsExcept(c.Params.TeamId)
|
|
||||||
if err != nil {
|
|
||||||
c.Err = err
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnStatusOK(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTeamsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
func getTeamsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireUserId()
|
c.RequireUserId()
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
|
|||||||
@@ -1096,7 +1096,6 @@ type AppIface interface {
|
|||||||
SetTeamIconFromFile(team *model.Team, file io.Reader) *model.AppError
|
SetTeamIconFromFile(team *model.Team, file io.Reader) *model.AppError
|
||||||
SetTeamIconFromMultiPartFile(teamID string, file multipart.File) *model.AppError
|
SetTeamIconFromMultiPartFile(teamID string, file multipart.File) *model.AppError
|
||||||
SlackImport(c *request.Context, fileData multipart.File, fileSize int64, teamID string) (*model.AppError, *bytes.Buffer)
|
SlackImport(c *request.Context, fileData multipart.File, fileSize int64, teamID string) (*model.AppError, *bytes.Buffer)
|
||||||
SoftDeleteAllTeamsExcept(teamID string) *model.AppError
|
|
||||||
SoftDeleteTeam(teamID string) *model.AppError
|
SoftDeleteTeam(teamID string) *model.AppError
|
||||||
Srv() *Server
|
Srv() *Server
|
||||||
SubmitInteractiveDialog(c *request.Context, request model.SubmitDialogRequest) (*model.SubmitDialogResponse, *model.AppError)
|
SubmitInteractiveDialog(c *request.Context, request model.SubmitDialogRequest) (*model.SubmitDialogResponse, *model.AppError)
|
||||||
|
|||||||
@@ -16652,28 +16652,6 @@ func (a *OpenTracingAppLayer) SlackImport(c *request.Context, fileData multipart
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) SoftDeleteAllTeamsExcept(teamID string) *model.AppError {
|
|
||||||
origCtx := a.ctx
|
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SoftDeleteAllTeamsExcept")
|
|
||||||
|
|
||||||
a.ctx = newCtx
|
|
||||||
a.app.Srv().Store().SetContext(newCtx)
|
|
||||||
defer func() {
|
|
||||||
a.app.Srv().Store().SetContext(origCtx)
|
|
||||||
a.ctx = origCtx
|
|
||||||
}()
|
|
||||||
|
|
||||||
defer span.Finish()
|
|
||||||
resultVar0 := a.app.SoftDeleteAllTeamsExcept(teamID)
|
|
||||||
|
|
||||||
if resultVar0 != nil {
|
|
||||||
span.LogFields(spanlog.Error(resultVar0))
|
|
||||||
ext.Error.Set(span, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return resultVar0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) SoftDeleteTeam(teamID string) *model.AppError {
|
func (a *OpenTracingAppLayer) SoftDeleteTeam(teamID string) *model.AppError {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SoftDeleteTeam")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SoftDeleteTeam")
|
||||||
|
|||||||
@@ -133,33 +133,6 @@ func (a *App) AdjustTeamsFromProductLimits(teamLimits *model.TeamsLimits) *model
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) SoftDeleteAllTeamsExcept(teamID string) *model.AppError {
|
|
||||||
teams, appErr := a.GetAllTeams()
|
|
||||||
if appErr != nil {
|
|
||||||
return appErr
|
|
||||||
}
|
|
||||||
|
|
||||||
if teams == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
cloudLimitsArchived := true
|
|
||||||
patch := &model.TeamPatch{CloudLimitsArchived: &cloudLimitsArchived}
|
|
||||||
for _, team := range teams {
|
|
||||||
if team.Id != teamID {
|
|
||||||
_, err := a.PatchTeam(team.Id, patch)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = a.SoftDeleteTeam(team.Id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) CreateTeam(c request.CTX, team *model.Team) (*model.Team, *model.AppError) {
|
func (a *App) CreateTeam(c request.CTX, team *model.Team) (*model.Team, *model.AppError) {
|
||||||
rteam, err := a.ch.srv.teamService.CreateTeam(team)
|
rteam, err := a.ch.srv.teamService.CreateTeam(team)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -469,41 +469,6 @@ func TestAddUserToTeamByTeamId(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSoftDeleteAllTeamsExcept(t *testing.T) {
|
|
||||||
th := Setup(t).InitBasic()
|
|
||||||
defer th.TearDown()
|
|
||||||
|
|
||||||
teams := []*model.Team{
|
|
||||||
{
|
|
||||||
DisplayName: "team-1",
|
|
||||||
Name: "team-1",
|
|
||||||
Email: "foo@foo.com",
|
|
||||||
Type: model.TeamOpen,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
teamId := ""
|
|
||||||
for _, create := range teams {
|
|
||||||
team, err := th.App.CreateTeam(th.Context, create)
|
|
||||||
require.Nil(t, err)
|
|
||||||
teamId = team.Id
|
|
||||||
}
|
|
||||||
|
|
||||||
err := th.App.SoftDeleteAllTeamsExcept(teamId)
|
|
||||||
assert.Nil(t, err)
|
|
||||||
allTeams, err := th.App.GetAllTeams()
|
|
||||||
require.Nil(t, err)
|
|
||||||
for _, team := range allTeams {
|
|
||||||
if team.Id == teamId {
|
|
||||||
require.Equal(t, int64(0), team.DeleteAt)
|
|
||||||
require.Equal(t, false, team.CloudLimitsArchived)
|
|
||||||
} else {
|
|
||||||
require.NotEqual(t, int64(0), team.DeleteAt)
|
|
||||||
require.Equal(t, true, team.CloudLimitsArchived)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAdjustTeamsFromProductLimits(t *testing.T) {
|
func TestAdjustTeamsFromProductLimits(t *testing.T) {
|
||||||
th := Setup(t).InitBasic()
|
th := Setup(t).InitBasic()
|
||||||
defer th.TearDown()
|
defer th.TearDown()
|
||||||
|
|||||||
@@ -20,9 +20,6 @@ import PaymentSuccessStandardSvg from 'components/common/svg_images_components/p
|
|||||||
import PaymentFailedSvg from 'components/common/svg_images_components/payment_failed_svg';
|
import PaymentFailedSvg from 'components/common/svg_images_components/payment_failed_svg';
|
||||||
import IconMessage from 'components/purchase_modal/icon_message';
|
import IconMessage from 'components/purchase_modal/icon_message';
|
||||||
import ProgressBar, {ProcessState} from 'components/icon_message_with_progress_bar';
|
import ProgressBar, {ProcessState} from 'components/icon_message_with_progress_bar';
|
||||||
import {
|
|
||||||
archiveAllTeamsExcept,
|
|
||||||
} from 'mattermost-redux/actions/teams';
|
|
||||||
import {DispatchFunc} from 'mattermost-redux/types/actions';
|
import {DispatchFunc} from 'mattermost-redux/types/actions';
|
||||||
|
|
||||||
type Props = RouteComponentProps & {
|
type Props = RouteComponentProps & {
|
||||||
@@ -55,10 +52,6 @@ function CloudSubscribeWithLoad(props: Props) {
|
|||||||
|
|
||||||
const handleSubscribe = async () => {
|
const handleSubscribe = async () => {
|
||||||
const start = new Date();
|
const start = new Date();
|
||||||
if (props.teamToKeep) {
|
|
||||||
await dispatch(archiveAllTeamsExcept(props.teamToKeep.id));
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await dispatch(subscribeCloudSubscription(
|
const result = await dispatch(subscribeCloudSubscription(
|
||||||
props.selectedProduct?.id as string, undefined, 0, props.downgradeFeedback,
|
props.selectedProduct?.id as string, undefined, 0, props.downgradeFeedback,
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import {DispatchFunc} from 'mattermost-redux/types/actions';
|
|||||||
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
|
import {deprecateCloudFree} from 'mattermost-redux/selectors/entities/preferences';
|
||||||
|
|
||||||
import {Feedback} from '@mattermost/types/cloud';
|
import {Feedback} from '@mattermost/types/cloud';
|
||||||
import useGetUsage from 'components/common/hooks/useGetUsage';
|
|
||||||
import useGetLimits from 'components/common/hooks/useGetLimits';
|
import useGetLimits from 'components/common/hooks/useGetLimits';
|
||||||
import SuccessModal from 'components/cloud_subscribe_result_modal/success';
|
import SuccessModal from 'components/cloud_subscribe_result_modal/success';
|
||||||
import ErrorModal from 'components/cloud_subscribe_result_modal/error';
|
import ErrorModal from 'components/cloud_subscribe_result_modal/error';
|
||||||
@@ -41,7 +40,6 @@ import useOpenSalesLink from 'components/common/hooks/useOpenSalesLink';
|
|||||||
import {useOpenCloudZendeskSupportForm} from 'components/common/hooks/useOpenZendeskForm';
|
import {useOpenCloudZendeskSupportForm} from 'components/common/hooks/useOpenZendeskForm';
|
||||||
import ExternalLink from 'components/external_link';
|
import ExternalLink from 'components/external_link';
|
||||||
|
|
||||||
import DowngradeTeamRemovalModal from './downgrade_team_removal_modal';
|
|
||||||
import ContactSalesCTA from './contact_sales_cta';
|
import ContactSalesCTA from './contact_sales_cta';
|
||||||
import StarterDisclaimerCTA from './starter_disclaimer_cta';
|
import StarterDisclaimerCTA from './starter_disclaimer_cta';
|
||||||
import StartTrialCaution from './start_trial_caution';
|
import StartTrialCaution from './start_trial_caution';
|
||||||
@@ -60,7 +58,6 @@ type ContentProps = {
|
|||||||
function Content(props: ContentProps) {
|
function Content(props: ContentProps) {
|
||||||
const {formatMessage, formatNumber} = useIntl();
|
const {formatMessage, formatNumber} = useIntl();
|
||||||
const dispatch = useDispatch<DispatchFunc>();
|
const dispatch = useDispatch<DispatchFunc>();
|
||||||
const usage = useGetUsage();
|
|
||||||
const [limits] = useGetLimits();
|
const [limits] = useGetLimits();
|
||||||
const openPricingModalBackAction = useOpenPricingModal();
|
const openPricingModalBackAction = useOpenPricingModal();
|
||||||
|
|
||||||
@@ -379,29 +376,15 @@ function Content(props: ContentProps) {
|
|||||||
if (!starterProduct) {
|
if (!starterProduct) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
dispatch(
|
||||||
if (usage.teams.active > 1) {
|
openModal({
|
||||||
dispatch(
|
modalId: ModalIdentifiers.FEEDBACK,
|
||||||
openModal({
|
dialogType: DowngradeFeedbackModal,
|
||||||
modalId: ModalIdentifiers.CLOUD_DOWNGRADE_CHOOSE_TEAM,
|
dialogProps: {
|
||||||
dialogType: DowngradeTeamRemovalModal,
|
onSubmit: handleClickDowngrade,
|
||||||
dialogProps: {
|
},
|
||||||
product_id: starterProduct?.id,
|
}),
|
||||||
starterProduct,
|
);
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
dispatch(
|
|
||||||
openModal({
|
|
||||||
modalId: ModalIdentifiers.FEEDBACK,
|
|
||||||
dialogType: DowngradeFeedbackModal,
|
|
||||||
dialogProps: {
|
|
||||||
onSubmit: handleClickDowngrade,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
text: freeTierText,
|
text: freeTierText,
|
||||||
disabled: isStarter || isEnterprise || !isAdmin,
|
disabled: isStarter || isEnterprise || !isAdmin,
|
||||||
|
|||||||
@@ -1,165 +0,0 @@
|
|||||||
|
|
||||||
@import 'utils/variables';
|
|
||||||
|
|
||||||
.modal-backdrop.downgrade-modal-backdrop {
|
|
||||||
z-index: 1050;
|
|
||||||
}
|
|
||||||
|
|
||||||
.DowngradeTeamRemovalModal {
|
|
||||||
z-index: 1051;
|
|
||||||
|
|
||||||
.modal {
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-dialog {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
width: 600px;
|
|
||||||
height: 404px;
|
|
||||||
border: none;
|
|
||||||
margin: auto;
|
|
||||||
transform: translate(-50%, -50%) !important;
|
|
||||||
|
|
||||||
.modal-content {
|
|
||||||
border: none;
|
|
||||||
background-color: var(--center-channel-bg);
|
|
||||||
border-radius: 12px;
|
|
||||||
box-shadow: $elevation-6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-header {
|
|
||||||
height: 77px;
|
|
||||||
min-height: 77px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.DowngradeTeamRemovalModal__header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 22px 32px;
|
|
||||||
border: none;
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: 600;
|
|
||||||
|
|
||||||
&::before,
|
|
||||||
&::after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// beat regular modal-header in specificity
|
|
||||||
&.modal-header {
|
|
||||||
background-color: var(--center-channel-bg);
|
|
||||||
color: var(--center-channel-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-close {
|
|
||||||
padding: 0;
|
|
||||||
border: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
background: none;
|
|
||||||
color: rgb(var(--center-channel-color-rgb), 0.56);
|
|
||||||
cursor: pointer;
|
|
||||||
font: inherit;
|
|
||||||
outline: inherit;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:active,
|
|
||||||
&:focus {
|
|
||||||
color: rgb(var(--center-channel-color-rgb), 0.56);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-body {
|
|
||||||
padding: 26px 32px;
|
|
||||||
padding-top: 0;
|
|
||||||
border: none;
|
|
||||||
overflow-y: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.DowngradeTeamRemovalModal__body {
|
|
||||||
.DowngradeTeamRemovalModal__selectionSection {
|
|
||||||
.radio {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.DropDown__menu {
|
|
||||||
max-height: 124px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.DropDown__menu-list {
|
|
||||||
max-height: 124px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.DropDown__value-container {
|
|
||||||
padding-left: 0;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cta {
|
|
||||||
margin-top: 24px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.warning {
|
|
||||||
display: flex;
|
|
||||||
height: 16px;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 19px;
|
|
||||||
margin-bottom: 35px;
|
|
||||||
color: var(--sys-error-text);
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: 16px;
|
|
||||||
|
|
||||||
.icon.icon-alert-outline {
|
|
||||||
height: 16px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.warning-text {
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon.icon-alert-outline::before {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.DowngradeTeamRemovalModal__buttons {
|
|
||||||
border: none;
|
|
||||||
float: right;
|
|
||||||
|
|
||||||
.btn.btn-light {
|
|
||||||
padding: 12px 20px;
|
|
||||||
background: rgba(var(--denim-button-bg-rgb), 0.08);
|
|
||||||
border-radius: 4px;
|
|
||||||
color: var(--sys-denim-button-bg);
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn.btn-primary {
|
|
||||||
padding: 12px 20px;
|
|
||||||
margin-left: 8px;
|
|
||||||
background: var(--sys-denim-button-bg);
|
|
||||||
border-radius: 4px;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
line-height: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,365 +0,0 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See LICENSE.txt for license information.
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import * as redux from 'react-redux';
|
|
||||||
|
|
||||||
import {renderWithIntl, screen} from 'tests/react_testing_utils';
|
|
||||||
import mockStore from 'tests/test_store';
|
|
||||||
|
|
||||||
import {CloudProducts} from 'utils/constants';
|
|
||||||
import {FileSizes} from 'utils/file_utils';
|
|
||||||
|
|
||||||
import DowngradeTeamRemovalModal from './';
|
|
||||||
|
|
||||||
describe('components/pricing_modal/downgrade_team_removal_modal', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.spyOn(redux, 'useDispatch').mockImplementation(
|
|
||||||
jest.fn(() => jest.fn()),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const state = {
|
|
||||||
entities: {
|
|
||||||
users: {
|
|
||||||
currentUserId: 'user1',
|
|
||||||
profiles: {
|
|
||||||
user1: {
|
|
||||||
id: 'user1',
|
|
||||||
roles: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
usage: {
|
|
||||||
files: {
|
|
||||||
totalStorage: 0,
|
|
||||||
totalStorageLoaded: true,
|
|
||||||
},
|
|
||||||
messages: {
|
|
||||||
history: 0,
|
|
||||||
historyLoaded: true,
|
|
||||||
},
|
|
||||||
boards: {
|
|
||||||
cards: 0,
|
|
||||||
cardsLoaded: true,
|
|
||||||
},
|
|
||||||
integrations: {
|
|
||||||
enabled: 3,
|
|
||||||
enabledLoaded: true,
|
|
||||||
},
|
|
||||||
teams: {
|
|
||||||
active: 4,
|
|
||||||
cloudArchived: 0,
|
|
||||||
teamsLoaded: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
teams: {
|
|
||||||
currentTeamId: 'frggfw9objyz5e6ma7ibpx6jda',
|
|
||||||
teams: {
|
|
||||||
frggfw9objyz5e6ma7ibpx6jda: {
|
|
||||||
id: 'frggfw9objyz5e6ma7ibpx6jda',
|
|
||||||
create_at: 1654097827977,
|
|
||||||
update_at: 1654783962398,
|
|
||||||
delete_at: 0,
|
|
||||||
display_name: 'Team 4',
|
|
||||||
name: 'team-4',
|
|
||||||
description: '',
|
|
||||||
email: 'test@example.com',
|
|
||||||
type: 'O',
|
|
||||||
company_name: '',
|
|
||||||
allowed_domains: '',
|
|
||||||
invite_id: 'jagqnrb5ubb78grwebzckmpxxa',
|
|
||||||
allow_open_invite: false,
|
|
||||||
scheme_id: null,
|
|
||||||
group_constrained: null,
|
|
||||||
policy_id: null,
|
|
||||||
cloud_limits_archived: false,
|
|
||||||
},
|
|
||||||
ypbsfrr583yc9futzyghpmhc6r: {
|
|
||||||
id: 'ypbsfrr583yc9futzyghpmhc6r',
|
|
||||||
create_at: 1652892296690,
|
|
||||||
update_at: 1654784021789,
|
|
||||||
delete_at: 0,
|
|
||||||
display_name: 'team 3',
|
|
||||||
name: 'team-3',
|
|
||||||
description: '',
|
|
||||||
email: 'test@example.com',
|
|
||||||
type: 'O',
|
|
||||||
company_name: '',
|
|
||||||
allowed_domains: '',
|
|
||||||
invite_id: 'cfqgw4utbpfjucjqjaddg6mxmo',
|
|
||||||
allow_open_invite: false,
|
|
||||||
scheme_id: null,
|
|
||||||
group_constrained: false,
|
|
||||||
policy_id: null,
|
|
||||||
cloud_limits_archived: false,
|
|
||||||
},
|
|
||||||
p6kpct39xigtpxfk739dwu9eny: {
|
|
||||||
id: 'p6kpct39xigtpxfk739dwu9eny',
|
|
||||||
create_at: 1652891664653,
|
|
||||||
update_at: 1654784021776,
|
|
||||||
delete_at: 0,
|
|
||||||
display_name: 'second team',
|
|
||||||
name: 'second-team',
|
|
||||||
description: '',
|
|
||||||
email: 'test@example.com',
|
|
||||||
type: 'O',
|
|
||||||
company_name: '',
|
|
||||||
allowed_domains: '',
|
|
||||||
invite_id: 'yefar6zmoiya8dsw59oiw9xwac',
|
|
||||||
allow_open_invite: false,
|
|
||||||
scheme_id: null,
|
|
||||||
group_constrained: false,
|
|
||||||
policy_id: null,
|
|
||||||
cloud_limits_archived: false,
|
|
||||||
},
|
|
||||||
qet86xzhwpbim841jwyfh3fgwe: {
|
|
||||||
id: 'qet86xzhwpbim841jwyfh3fgwe',
|
|
||||||
create_at: 1652891651309,
|
|
||||||
update_at: 1654784021766,
|
|
||||||
delete_at: 0,
|
|
||||||
display_name: 'first team',
|
|
||||||
name: 'first-team',
|
|
||||||
description: '',
|
|
||||||
email: 'test@example.com',
|
|
||||||
type: 'O',
|
|
||||||
company_name: '',
|
|
||||||
allowed_domains: '',
|
|
||||||
invite_id: '3qm66p1ub3n17rbi7f315wqsdy',
|
|
||||||
allow_open_invite: false,
|
|
||||||
scheme_id: null,
|
|
||||||
group_constrained: false,
|
|
||||||
policy_id: null,
|
|
||||||
cloud_limits_archived: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
myMembers: {
|
|
||||||
frggfw9objyz5e6ma7ibpx6jda: {
|
|
||||||
mention_count: 0,
|
|
||||||
msg_count: 0,
|
|
||||||
mention_count_root: 0,
|
|
||||||
msg_count_root: 0,
|
|
||||||
team_id: 'frggfw9objyz5e6ma7ibpx6jda',
|
|
||||||
user_id: 'jp1dthppbfri5d46impk1ndk8a',
|
|
||||||
roles: 'team_user team_admin',
|
|
||||||
delete_at: 0,
|
|
||||||
scheme_guest: false,
|
|
||||||
scheme_user: true,
|
|
||||||
scheme_admin: true,
|
|
||||||
explicit_roles: '',
|
|
||||||
},
|
|
||||||
ypbsfrr583yc9futzyghpmhc6r: {
|
|
||||||
mention_count: 0,
|
|
||||||
msg_count: 0,
|
|
||||||
mention_count_root: 0,
|
|
||||||
msg_count_root: 0,
|
|
||||||
team_id: 'ypbsfrr583yc9futzyghpmhc6r',
|
|
||||||
user_id: 'jp1dthppbfri5d46impk1ndk8a',
|
|
||||||
roles: 'team_user team_admin',
|
|
||||||
delete_at: 0,
|
|
||||||
scheme_guest: false,
|
|
||||||
scheme_user: true,
|
|
||||||
scheme_admin: true,
|
|
||||||
explicit_roles: '',
|
|
||||||
},
|
|
||||||
p6kpct39xigtpxfk739dwu9eny: {
|
|
||||||
mention_count: 0,
|
|
||||||
msg_count: 0,
|
|
||||||
mention_count_root: 0,
|
|
||||||
msg_count_root: 0,
|
|
||||||
team_id: 'p6kpct39xigtpxfk739dwu9eny',
|
|
||||||
user_id: 'jp1dthppbfri5d46impk1ndk8a',
|
|
||||||
roles: 'team_user team_admin',
|
|
||||||
delete_at: 0,
|
|
||||||
scheme_guest: false,
|
|
||||||
scheme_user: true,
|
|
||||||
scheme_admin: true,
|
|
||||||
explicit_roles: '',
|
|
||||||
},
|
|
||||||
qet86xzhwpbim841jwyfh3fgwe: {
|
|
||||||
mention_count: 0,
|
|
||||||
msg_count: 0,
|
|
||||||
mention_count_root: 0,
|
|
||||||
msg_count_root: 0,
|
|
||||||
team_id: 'qet86xzhwpbim841jwyfh3fgwe',
|
|
||||||
user_id: 'jp1dthppbfri5d46impk1ndk8a',
|
|
||||||
roles: 'team_user team_admin',
|
|
||||||
delete_at: 0,
|
|
||||||
scheme_guest: false,
|
|
||||||
scheme_user: true,
|
|
||||||
scheme_admin: true,
|
|
||||||
explicit_roles: '',
|
|
||||||
},
|
|
||||||
isw1dyt5ijnozg8frzjb1uongr: {
|
|
||||||
mention_count: 0,
|
|
||||||
msg_count: 0,
|
|
||||||
mention_count_root: 0,
|
|
||||||
msg_count_root: 0,
|
|
||||||
team_id: 'isw1dyt5ijnozg8frzjb1uongr',
|
|
||||||
user_id: 'jp1dthppbfri5d46impk1ndk8a',
|
|
||||||
roles: 'team_user team_admin',
|
|
||||||
delete_at: 0,
|
|
||||||
scheme_guest: false,
|
|
||||||
scheme_user: true,
|
|
||||||
scheme_admin: true,
|
|
||||||
explicit_roles: '',
|
|
||||||
},
|
|
||||||
m1niyeo5n3fc9kb41dthno6xgy: {
|
|
||||||
mention_count: 0,
|
|
||||||
msg_count: 0,
|
|
||||||
mention_count_root: 0,
|
|
||||||
msg_count_root: 0,
|
|
||||||
team_id: 'm1niyeo5n3fc9kb41dthno6xgy',
|
|
||||||
user_id: 'jp1dthppbfri5d46impk1ndk8a',
|
|
||||||
roles: 'team_user team_admin',
|
|
||||||
delete_at: 0,
|
|
||||||
scheme_guest: false,
|
|
||||||
scheme_user: true,
|
|
||||||
scheme_admin: true,
|
|
||||||
explicit_roles: '',
|
|
||||||
},
|
|
||||||
'51ifbyhn6b8s7es7nbu5faezhc': {
|
|
||||||
mention_count: 0,
|
|
||||||
msg_count: 0,
|
|
||||||
mention_count_root: 0,
|
|
||||||
msg_count_root: 0,
|
|
||||||
team_id: '51ifbyhn6b8s7es7nbu5faezhc',
|
|
||||||
user_id: 'jp1dthppbfri5d46impk1ndk8a',
|
|
||||||
roles: 'team_user team_admin',
|
|
||||||
delete_at: 0,
|
|
||||||
scheme_guest: false,
|
|
||||||
scheme_user: true,
|
|
||||||
scheme_admin: true,
|
|
||||||
explicit_roles: '',
|
|
||||||
},
|
|
||||||
n8h6tsdfipn79eho3k1dj69jba: {
|
|
||||||
mention_count: 0,
|
|
||||||
msg_count: 0,
|
|
||||||
mention_count_root: 0,
|
|
||||||
msg_count_root: 0,
|
|
||||||
team_id: 'n8h6tsdfipn79eho3k1dj69jba',
|
|
||||||
user_id: 'jp1dthppbfri5d46impk1ndk8a',
|
|
||||||
roles: 'team_user team_admin',
|
|
||||||
delete_at: 0,
|
|
||||||
scheme_guest: false,
|
|
||||||
scheme_user: true,
|
|
||||||
scheme_admin: true,
|
|
||||||
explicit_roles: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
membersInTeam: {},
|
|
||||||
stats: {},
|
|
||||||
groupsAssociatedToTeam: {},
|
|
||||||
totalCount: 0,
|
|
||||||
},
|
|
||||||
admin: {},
|
|
||||||
general: {
|
|
||||||
license: {
|
|
||||||
IsLicensed: 'true',
|
|
||||||
Cloud: 'true',
|
|
||||||
},
|
|
||||||
credentials: {
|
|
||||||
url: 'http://example.com',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
cloud: {
|
|
||||||
subscription: {
|
|
||||||
is_free_trial: 'false',
|
|
||||||
trial_end_at: 0,
|
|
||||||
product_id: 'prod_free',
|
|
||||||
},
|
|
||||||
limits: {
|
|
||||||
limitsLoaded: true,
|
|
||||||
limits: {
|
|
||||||
integrations: {
|
|
||||||
enabled: 5,
|
|
||||||
},
|
|
||||||
messages: {
|
|
||||||
history: 10000,
|
|
||||||
},
|
|
||||||
files: {
|
|
||||||
total_storage: FileSizes.Gigabyte,
|
|
||||||
},
|
|
||||||
teams: {
|
|
||||||
active: 1,
|
|
||||||
},
|
|
||||||
boards: {
|
|
||||||
cards: 500,
|
|
||||||
views: 5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
products: {
|
|
||||||
prod_free: {
|
|
||||||
id: 'prod_free',
|
|
||||||
name: 'Cloud Free',
|
|
||||||
sku: CloudProducts.STARTER,
|
|
||||||
price_per_seat: 0,
|
|
||||||
product_family: 'cloud',
|
|
||||||
description: '',
|
|
||||||
add_ons: [],
|
|
||||||
billing_scheme: 'flat_fee',
|
|
||||||
recurring_interval: 'month',
|
|
||||||
cross_sells_to: '',
|
|
||||||
},
|
|
||||||
prod_enterprise: {
|
|
||||||
id: 'prod_enterprise',
|
|
||||||
name: 'Cloud Enterprise',
|
|
||||||
sku: CloudProducts.ENTERPRISE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
views: {
|
|
||||||
modals: {
|
|
||||||
modalState: {
|
|
||||||
cloud_downgrade_choose_team: {
|
|
||||||
open: 'true',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
test('renders modal', () => {
|
|
||||||
const store = mockStore(state);
|
|
||||||
renderWithIntl(
|
|
||||||
<redux.Provider store={store}>
|
|
||||||
<DowngradeTeamRemovalModal
|
|
||||||
product_id={'prod_free'}
|
|
||||||
starterProduct={state.entities.cloud.products.prod_free}
|
|
||||||
/>
|
|
||||||
</redux.Provider>,
|
|
||||||
);
|
|
||||||
expect(screen.getByText('Confirm Plan Downgrade')).toBeInTheDocument();
|
|
||||||
expect(screen.getByText('Which team would you like to continue using?')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('renders dropdown with 4+ teams', () => {
|
|
||||||
const store = mockStore(state);
|
|
||||||
renderWithIntl(
|
|
||||||
<redux.Provider store={store}>
|
|
||||||
<DowngradeTeamRemovalModal
|
|
||||||
product_id={'prod_free'}
|
|
||||||
starterProduct={state.entities.cloud.products.prod_free}
|
|
||||||
/>
|
|
||||||
</redux.Provider>,
|
|
||||||
);
|
|
||||||
expect(screen.getByTestId('deleteTeamDropdownInput')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
test('renders radio buttons with fewer than 4 teams', () => {
|
|
||||||
const newState = {...state};
|
|
||||||
newState.entities.usage.teams.active = 2;
|
|
||||||
const store = mockStore(state);
|
|
||||||
renderWithIntl(
|
|
||||||
<redux.Provider store={store}>
|
|
||||||
<DowngradeTeamRemovalModal
|
|
||||||
product_id={'prod_free'}
|
|
||||||
starterProduct={state.entities.cloud.products.prod_free}
|
|
||||||
/>
|
|
||||||
</redux.Provider>,
|
|
||||||
);
|
|
||||||
expect(screen.getByTestId('deleteTeamRadioGroup')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,262 +0,0 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
||||||
// See LICENSE.txt for license information.
|
|
||||||
|
|
||||||
import React, {useEffect, useState} from 'react';
|
|
||||||
import {FormattedMessage, useIntl} from 'react-intl';
|
|
||||||
import {isEmpty} from 'lodash';
|
|
||||||
import {Modal} from 'react-bootstrap';
|
|
||||||
|
|
||||||
import {useDispatch, useSelector} from 'react-redux';
|
|
||||||
|
|
||||||
import {Team} from '@mattermost/types/teams';
|
|
||||||
import {Feedback, Product} from '@mattermost/types/cloud';
|
|
||||||
import {t} from 'utils/i18n';
|
|
||||||
import RadioButtonGroup from 'components/common/radio_group';
|
|
||||||
import DropdownInput, {ValueType} from 'components/dropdown_input';
|
|
||||||
import CloudSubscribeWithLoadingModal from 'components/cloud_subscribe_with_loading_modal';
|
|
||||||
import useGetUsage from 'components/common/hooks/useGetUsage';
|
|
||||||
import DowngradeFeedback from 'components/feedback_modal/downgrade_feedback';
|
|
||||||
import {getTeams} from 'mattermost-redux/actions/teams';
|
|
||||||
import {getActiveTeamsList} from 'mattermost-redux/selectors/entities/teams';
|
|
||||||
import {closeModal, openModal} from 'actions/views/modals';
|
|
||||||
import {ModalIdentifiers} from 'utils/constants';
|
|
||||||
import {isModalOpen} from 'selectors/views/modals';
|
|
||||||
import {GlobalState} from 'types/store';
|
|
||||||
|
|
||||||
import {fallbackStarterLimits, asGBString} from 'utils/limits';
|
|
||||||
|
|
||||||
import './downgrade_team_removal_modal.scss';
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
product_id: string;
|
|
||||||
starterProduct: Product | null | undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
function DowngradeTeamRemovalModal(props: Props) {
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
const [radioValue, setRadioValue] = useState('');
|
|
||||||
const [dropdownValue, setDropdownValue] = useState<ValueType | undefined>();
|
|
||||||
|
|
||||||
const intl = useIntl();
|
|
||||||
const isCloudDowngradeChooseTeamModalOpen = useSelector(
|
|
||||||
(state: GlobalState) =>
|
|
||||||
isModalOpen(state, ModalIdentifiers.CLOUD_DOWNGRADE_CHOOSE_TEAM),
|
|
||||||
);
|
|
||||||
|
|
||||||
const teams = useSelector(getActiveTeamsList);
|
|
||||||
useEffect(() => {
|
|
||||||
if (!teams) {
|
|
||||||
dispatch(getTeams(0, 10000));
|
|
||||||
}
|
|
||||||
}, [teams]);
|
|
||||||
const usage = useGetUsage();
|
|
||||||
|
|
||||||
const onHide = () => {
|
|
||||||
dispatch(closeModal(ModalIdentifiers.CLOUD_DOWNGRADE_CHOOSE_TEAM));
|
|
||||||
};
|
|
||||||
|
|
||||||
const onConfirmDowngrade = async () => {
|
|
||||||
dispatch(closeModal(ModalIdentifiers.CLOUD_DOWNGRADE_CHOOSE_TEAM));
|
|
||||||
dispatch(closeModal(ModalIdentifiers.PRICING_MODAL));
|
|
||||||
dispatch(openModal({
|
|
||||||
modalId: ModalIdentifiers.FEEDBACK,
|
|
||||||
dialogType: DowngradeFeedback,
|
|
||||||
dialogProps: {
|
|
||||||
onSubmit: downgrade,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const downgrade = (downgradeFeedback: Feedback) => {
|
|
||||||
const teamToKeep = getSelectedTeam();
|
|
||||||
dispatch(openModal({
|
|
||||||
modalId: ModalIdentifiers.CLOUD_SUBSCRIBE_WITH_LOADING_MODAL,
|
|
||||||
dialogType: CloudSubscribeWithLoadingModal,
|
|
||||||
dialogProps: {
|
|
||||||
onBack: () => {
|
|
||||||
dispatch(
|
|
||||||
closeModal(
|
|
||||||
ModalIdentifiers.CLOUD_SUBSCRIBE_WITH_LOADING_MODAL,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
dispatch(
|
|
||||||
openModal({
|
|
||||||
modalId:
|
|
||||||
ModalIdentifiers.CLOUD_DOWNGRADE_CHOOSE_TEAM,
|
|
||||||
dialogType: DowngradeTeamRemovalModal,
|
|
||||||
dialogProps: {
|
|
||||||
product_id: props.starterProduct?.id || '',
|
|
||||||
starterProduct: props.starterProduct,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
teamToKeep,
|
|
||||||
selectedProduct: props.starterProduct,
|
|
||||||
downgradeFeedback,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSelectedTeam = () => {
|
|
||||||
let teamIdToKeep = '';
|
|
||||||
if (radioValue && !dropdownValue) {
|
|
||||||
teamIdToKeep = radioValue;
|
|
||||||
} else {
|
|
||||||
teamIdToKeep = dropdownValue?.value || '';
|
|
||||||
}
|
|
||||||
return teams.find((team: Team) => team.id === teamIdToKeep);
|
|
||||||
};
|
|
||||||
|
|
||||||
const selectionSection = (teamsList: Team[]) => {
|
|
||||||
if (usage.teams.active < 4) {
|
|
||||||
return (
|
|
||||||
<RadioButtonGroup
|
|
||||||
id='deleteTeamRadioGroup'
|
|
||||||
testId='deleteTeamRadioGroup'
|
|
||||||
values={teamsList.map((team) => {
|
|
||||||
return {
|
|
||||||
value: team.id,
|
|
||||||
key: team.display_name,
|
|
||||||
testId: team.id,
|
|
||||||
};
|
|
||||||
})}
|
|
||||||
value={radioValue}
|
|
||||||
onChange={(e) => setRadioValue(e.target.value)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DropdownInput
|
|
||||||
testId='deleteTeamDropdownInput'
|
|
||||||
onChange={setDropdownValue}
|
|
||||||
legend={intl.formatMessage({
|
|
||||||
id: t('admin.channel_settings.channel_list.teamHeader'),
|
|
||||||
defaultMessage: 'Team',
|
|
||||||
})}
|
|
||||||
placeholder={intl.formatMessage({
|
|
||||||
id: t('downgrade_plan_modal.selectTeam'),
|
|
||||||
defaultMessage: 'Select team',
|
|
||||||
})}
|
|
||||||
value={dropdownValue}
|
|
||||||
options={teamsList.map((team) => {
|
|
||||||
return {
|
|
||||||
label: team.display_name,
|
|
||||||
value: team.id,
|
|
||||||
};
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
className='DowngradeTeamRemovalModal'
|
|
||||||
show={isCloudDowngradeChooseTeamModalOpen}
|
|
||||||
backdropClassName={'downgrade-modal-backdrop'}
|
|
||||||
id='downgradeTeamRemovalModal'
|
|
||||||
onExited={onHide}
|
|
||||||
data-testid='downgradeTeamRemovalModal'
|
|
||||||
dialogClassName='a11y__modal'
|
|
||||||
onHide={onHide}
|
|
||||||
role='dialog'
|
|
||||||
aria-modal='true'
|
|
||||||
aria-labelledby='downgradeTeamRemovalModalTitle'
|
|
||||||
>
|
|
||||||
<>
|
|
||||||
<Modal.Header className='DowngradeTeamRemovalModal__header'>
|
|
||||||
<FormattedMessage
|
|
||||||
id='downgrade_plan_modal.title'
|
|
||||||
defaultMessage='Confirm Plan Downgrade'
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
id='closeIcon'
|
|
||||||
className='icon icon-close'
|
|
||||||
aria-label='Close'
|
|
||||||
title='Close'
|
|
||||||
onClick={onHide}
|
|
||||||
/>
|
|
||||||
</Modal.Header>
|
|
||||||
<Modal.Body>
|
|
||||||
<div className='DowngradeTeamRemovalModal__body'>
|
|
||||||
<div>
|
|
||||||
<FormattedMessage
|
|
||||||
id='downgrade_plan_modal.subtitle'
|
|
||||||
defaultMessage='{planName} is restricted to {teams} team, {messages} messages, and {storage} file storage. <strong>If you downgrade, some data will be archived</strong>. Archived data can be accessible when you upgrade back'
|
|
||||||
values={{
|
|
||||||
strong: (msg: React.ReactNode) => (
|
|
||||||
<strong>{msg}</strong>
|
|
||||||
),
|
|
||||||
planName: props.starterProduct?.name,
|
|
||||||
messages: intl.formatNumber(
|
|
||||||
fallbackStarterLimits.messages.
|
|
||||||
history,
|
|
||||||
),
|
|
||||||
storage: asGBString(
|
|
||||||
fallbackStarterLimits.files.
|
|
||||||
totalStorage,
|
|
||||||
intl.formatNumber,
|
|
||||||
),
|
|
||||||
teams: fallbackStarterLimits.teams.
|
|
||||||
active,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='cta'>
|
|
||||||
<FormattedMessage
|
|
||||||
id='downgrade_plan_modal.whichTeamToUse'
|
|
||||||
defaultMessage='Which team would you like to continue using?'
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='DowngradeTeamRemovalModal__selectionSection'>
|
|
||||||
{selectionSection(teams)}
|
|
||||||
</div>
|
|
||||||
<div className='warning'>
|
|
||||||
<i className='icon icon-alert-outline'/>
|
|
||||||
<span className='warning-text'>
|
|
||||||
<FormattedMessage
|
|
||||||
id='downgrade_plan_modal.alert'
|
|
||||||
defaultMessage='The unselected teams will be automatically archived in the system console, but not deleted'
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='DowngradeTeamRemovalModal__buttons'>
|
|
||||||
<button
|
|
||||||
onClick={() =>
|
|
||||||
dispatch(
|
|
||||||
closeModal(
|
|
||||||
ModalIdentifiers.CLOUD_DOWNGRADE_CHOOSE_TEAM,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
className='btn btn-light'
|
|
||||||
>
|
|
||||||
<FormattedMessage
|
|
||||||
id='admin.team_channel_settings.cancel'
|
|
||||||
defaultMessage='Cancel'
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
disabled={
|
|
||||||
isEmpty(radioValue) &&
|
|
||||||
isEmpty(dropdownValue)
|
|
||||||
}
|
|
||||||
onClick={onConfirmDowngrade}
|
|
||||||
className='btn btn-primary'
|
|
||||||
>
|
|
||||||
<FormattedMessage
|
|
||||||
id='downgrade_plan_modal.confirmDowngrade'
|
|
||||||
defaultMessage='Confirm Downgrade'
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</Modal.Body>
|
|
||||||
</>
|
|
||||||
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DowngradeTeamRemovalModal;
|
|
||||||
@@ -3299,12 +3299,6 @@
|
|||||||
"dnd_custom_time_picker_modal.defaultMsg": "Disable notifications until",
|
"dnd_custom_time_picker_modal.defaultMsg": "Disable notifications until",
|
||||||
"dnd_custom_time_picker_modal.submitButton": "Disable Notifications",
|
"dnd_custom_time_picker_modal.submitButton": "Disable Notifications",
|
||||||
"dnd_custom_time_picker_modal.time": "Time",
|
"dnd_custom_time_picker_modal.time": "Time",
|
||||||
"downgrade_plan_modal.alert": "The unselected teams will be automatically archived in the system console, but not deleted",
|
|
||||||
"downgrade_plan_modal.confirmDowngrade": "Confirm Downgrade",
|
|
||||||
"downgrade_plan_modal.selectTeam": "Select team",
|
|
||||||
"downgrade_plan_modal.subtitle": "{planName} is restricted to {teams} team, {messages} messages, and {storage} file storage. <strong>If you downgrade, some data will be archived</strong>. Archived data can be accessible when you upgrade back.",
|
|
||||||
"downgrade_plan_modal.title": "Confirm Plan Downgrade",
|
|
||||||
"downgrade_plan_modal.whichTeamToUse": "Which team would you like to continue using?",
|
|
||||||
"drafts.actions.delete": "Delete draft",
|
"drafts.actions.delete": "Delete draft",
|
||||||
"drafts.actions.edit": "Edit draft",
|
"drafts.actions.edit": "Edit draft",
|
||||||
"drafts.actions.send": "Send draft",
|
"drafts.actions.send": "Send draft",
|
||||||
|
|||||||
@@ -297,18 +297,6 @@ export function unarchiveTeam(teamId: string): ActionFunc {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function archiveAllTeamsExcept(teamId: string) {
|
|
||||||
return async () => {
|
|
||||||
try {
|
|
||||||
await Client4.archiveAllTeamsExcept(teamId);
|
|
||||||
} catch (error) {
|
|
||||||
return {error};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {data: true};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateTeam(team: Team): ActionFunc {
|
export function updateTeam(team: Team): ActionFunc {
|
||||||
return bindClientFunc({
|
return bindClientFunc({
|
||||||
clientFunc: Client4.updateTeam,
|
clientFunc: Client4.updateTeam,
|
||||||
|
|||||||
@@ -1172,13 +1172,6 @@ export default class Client4 {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
archiveAllTeamsExcept = (teamId: string) => {
|
|
||||||
return this.doFetch<StatusOK>(
|
|
||||||
`${this.getTeamRoute(teamId)}/except`,
|
|
||||||
{method: 'delete'},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateTeam = (team: Team) => {
|
updateTeam = (team: Team) => {
|
||||||
this.trackEvent('api', 'api_teams_update_name', {team_id: team.id});
|
this.trackEvent('api', 'api_teams_update_name', {team_id: team.id});
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user