From 5b42689529e156d5c70c3be51d14a3ef26759dbb Mon Sep 17 00:00:00 2001 From: Conor Macpherson Date: Mon, 17 Apr 2023 14:24:58 -0400 Subject: [PATCH] Address code review comments (styling, clean-up css, re-org imports, math errors, etc). --- .../src/components/outlined_input/index.tsx | 26 ++++++++ .../error_page.tsx | 2 +- .../expansion_card.scss | 10 --- .../expansion_card.tsx | 63 +++++++++---------- .../self_hosted_expansion_modal/index.tsx | 62 +++++++++--------- .../self_hosted_expansion_modal.scss | 3 - .../submitting.tsx | 3 +- .../success_page.scss | 1 - .../success_page.tsx | 8 +-- webapp/channels/src/i18n/en.json | 1 - 10 files changed, 90 insertions(+), 89 deletions(-) create mode 100644 webapp/channels/src/components/outlined_input/index.tsx diff --git a/webapp/channels/src/components/outlined_input/index.tsx b/webapp/channels/src/components/outlined_input/index.tsx new file mode 100644 index 0000000000..5644bf958c --- /dev/null +++ b/webapp/channels/src/components/outlined_input/index.tsx @@ -0,0 +1,26 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; +import {OutlinedInput as MUIOutlineInput, OutlinedInputProps} from '@mui/material'; + +/** + * A horizontal separator for use in menus. + * @example + * span:first-child { - font-family: 'Open Sans'; font-size: 14px; } .costPerUser > span:last-child { color: rgba(var(--sys-denim-center-channel-text-rgb), 0.72); - font-family: 'Open Sans'; font-size: 12px; } @@ -94,14 +88,12 @@ .totalCostWarning > span:first-child { color: var(--sys-denim-center-channel-text); - font-family: 'Open Sans'; font-size: 14px; font-weight: 700; } .totalCostWarning > span:last-child { color: rgba(var(--sys-denim-center-channel-text-rgb), 0.72); - font-family: 'Open Sans'; font-size: 12px; } @@ -119,7 +111,6 @@ height: 35px; margin-bottom: 15px; color: var(--dnd-indicator); - font-family: 'Open Sans'; font-size: 12px; font-weight: 600; text-align: right; @@ -134,7 +125,6 @@ &__ChargedTodayDisclaimer { color: rgba(var(--sys-denim-center-channel-text-rgb), 0.72); - font-family: 'Open Sans'; font-size: 12px; font-weight: 400; } diff --git a/webapp/channels/src/components/self_hosted_purchases/self_hosted_expansion_modal/expansion_card.tsx b/webapp/channels/src/components/self_hosted_purchases/self_hosted_expansion_modal/expansion_card.tsx index 3cf1243e17..aa9a5edfb8 100644 --- a/webapp/channels/src/components/self_hosted_purchases/self_hosted_expansion_modal/expansion_card.tsx +++ b/webapp/channels/src/components/self_hosted_purchases/self_hosted_expansion_modal/expansion_card.tsx @@ -1,21 +1,22 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {OutlinedInput} from '@mui/material'; - -import moment from 'moment-timezone'; -import React, {Fragment, useState} from 'react'; -import {FormattedMessage} from 'react-intl'; +import React, {useState} from 'react'; +import {FormattedMessage, useIntl} from 'react-intl'; import {useSelector} from 'react-redux'; +import moment from 'moment-timezone'; import {getLicense} from 'mattermost-redux/selectors/entities/general'; -import {DocLinks} from 'utils/constants'; + import WarningIcon from 'components/widgets/icons/fa_warning_icon'; +import useGetSelfHostedProducts from 'components/common/hooks/useGetSelfHostedProducts'; +import ExternalLink from 'components/external_link'; +import {OutlinedInput} from 'components/outlined_input'; + +import {DocLinks} from 'utils/constants'; +import {findSelfHostedProductBySku} from 'utils/hosted_customer'; import './expansion_card.scss'; -import useGetSelfHostedProducts from 'components/common/hooks/useGetSelfHostedProducts'; -import {findSelfHostedProductBySku} from 'utils/hosted_customer'; -import ExternalLink from 'components/external_link'; const MONTHS_IN_YEAR = 12; const MAX_TRANSACTION_VALUE = 1_000_000 - 1; @@ -29,6 +30,7 @@ interface Props { } export default function SelfHostedExpansionCard(props: Props) { + const intl = useIntl(); const license = useSelector(getLicense); const startsAt = moment(parseInt(license.StartsAt, 10)).format('MMM. D, YYYY'); const endsAt = moment(parseInt(license.ExpiresAt, 10)).format('MMM. D, YYYY'); @@ -46,14 +48,11 @@ export default function SelfHostedExpansionCard(props: Props) { }; const getCostPerUser = () => { - if (isNaN(additionalSeats)) { - return 0; - } const monthsUntilExpiry = getMonthsUntilExpiry(); return costPerMonth * monthsUntilExpiry; }; - const getTotal = () => { + const getPaymentTotal = () => { if (isNaN(additionalSeats)) { return 0; } @@ -63,25 +62,29 @@ export default function SelfHostedExpansionCard(props: Props) { // Finds the maximum number of additional seats that is possible, taking into account // the stripe transaction limit. The maximum number of seats will follow the formula: - // (StripeTransaction Limit - (Current_Seats * Price Per Seat)) / price_per_seat + // (StripeTransaction Limit - (current_seats * yearly_price_per_seat)) / yearly_price_per_seat const getMaximumAdditionalSeats = () => { if (currentProduct === null) { return 0; } - const currentPaymentPrice = costPerMonth * props.licensedSeats; + const currentPaymentPrice = costPerMonth * props.licensedSeats * 12; const remainingTransactionLimit = MAX_TRANSACTION_VALUE - currentPaymentPrice; - const remainingSeats = Math.floor(remainingTransactionLimit / costPerMonth); + const remainingSeats = Math.floor(remainingTransactionLimit / (costPerMonth * 12)); return Math.max(0, remainingSeats); }; - const maxAdditionalSeats = getMaximumAdditionalSeats(); const handleNewSeatsInputChange = (e: React.ChangeEvent) => { - setOverMaxSeats(false); - const requestedSeats = parseInt(e.target.value, 10); + if (requestedSeats <= 0) { + e.preventDefault(); + return; + } + + setOverMaxSeats(false); + const overMaxAdditionalSeats = requestedSeats > maxAdditionalSeats; setOverMaxSeats(overMaxAdditionalSeats); @@ -91,6 +94,10 @@ export default function SelfHostedExpansionCard(props: Props) { props.updateSeats(finalSeatCount); }; + const formatCurrency = (value: number) => { + return intl.formatNumber(value, {style: 'currency', currency: 'USD'}); + }; + return (
@@ -158,16 +165,6 @@ export default function SelfHostedExpansionCard(props: Props) { }} /> } - {maxAdditionalSeats === 0 && - , - warningIcon: , - }} - /> - }
@@ -179,15 +176,15 @@ export default function SelfHostedExpansionCard(props: Props) {
- {'$' + getCostPerUser().toFixed(2)} + {formatCurrency(getCostPerUser())}
- {'$' + getTotal().toFixed(2)} + {formatCurrency(getPaymentTotal()) }