Update text for activated users in team statistics (#25921)
* Update text for activated users in team statistics * Fix lint * Generalize tooltip and make it show according to the designs * Fix lint * Fix test * Generalize even more overlay trigger * Update snapshot * Update link
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
7833dd2c1c
Коммит
f8dbb2e168
@@ -565,104 +565,26 @@ exports[`admin_console/team_channel_settings/team/TeamProfile__Cloud should matc
|
|||||||
<div
|
<div
|
||||||
className="AdminChannelDetails_archiveContainer"
|
className="AdminChannelDetails_archiveContainer"
|
||||||
>
|
>
|
||||||
<OverlayTrigger
|
<WithTooltip
|
||||||
defaultOverlayShown={false}
|
hint={
|
||||||
delay={400}
|
Object {
|
||||||
disabled={false}
|
"defaultMessage": "You've reached the team limit for your current plan. Consider upgrading to unarchive this team or archive your other teams",
|
||||||
overlay={
|
"id": "workspace_limits.teams_limit_reached.tool_tip",
|
||||||
<Tooltip
|
}
|
||||||
id="sharedTooltip"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="tooltip-title"
|
|
||||||
>
|
|
||||||
<Memo(MemoizedFormattedMessage)
|
|
||||||
defaultMessage="Upgrade to Unarchive"
|
|
||||||
id="workspace_limits.teams_limit_reached.upgrade_to_unarchive"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="tooltip-body"
|
|
||||||
>
|
|
||||||
<Memo(MemoizedFormattedMessage)
|
|
||||||
defaultMessage="You've reached the team limit for your current plan. Consider upgrading to unarchive this team or archive your other teams"
|
|
||||||
id="workspace_limits.teams_limit_reached.tool_tip"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
}
|
||||||
|
id="sharedTooltip"
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
trigger={
|
title={
|
||||||
Array [
|
Object {
|
||||||
"hover",
|
"defaultMessage": "Upgrade to Unarchive",
|
||||||
"focus",
|
"id": "workspace_limits.teams_limit_reached.upgrade_to_unarchive",
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<OverlayTrigger
|
<OverlayTrigger
|
||||||
defaultOverlayShown={false}
|
defaultOverlayShown={false}
|
||||||
delay={400}
|
delay={400}
|
||||||
overlay={
|
overlay={<Unknown />}
|
||||||
<OverlayWrapper
|
|
||||||
id="sharedTooltip"
|
|
||||||
intl={
|
|
||||||
Object {
|
|
||||||
"$t": [Function],
|
|
||||||
"defaultFormats": Object {},
|
|
||||||
"defaultLocale": "en",
|
|
||||||
"defaultRichTextElements": undefined,
|
|
||||||
"fallbackOnEmptyString": true,
|
|
||||||
"formatDate": [Function],
|
|
||||||
"formatDateTimeRange": [Function],
|
|
||||||
"formatDateToParts": [Function],
|
|
||||||
"formatDisplayName": [Function],
|
|
||||||
"formatList": [Function],
|
|
||||||
"formatListToParts": [Function],
|
|
||||||
"formatMessage": [Function],
|
|
||||||
"formatNumber": [Function],
|
|
||||||
"formatNumberToParts": [Function],
|
|
||||||
"formatPlural": [Function],
|
|
||||||
"formatRelativeTime": [Function],
|
|
||||||
"formatTime": [Function],
|
|
||||||
"formatTimeToParts": [Function],
|
|
||||||
"formats": Object {},
|
|
||||||
"formatters": Object {
|
|
||||||
"getDateTimeFormat": [Function],
|
|
||||||
"getDisplayNames": [Function],
|
|
||||||
"getListFormat": [Function],
|
|
||||||
"getMessageFormat": [Function],
|
|
||||||
"getNumberFormat": [Function],
|
|
||||||
"getPluralRules": [Function],
|
|
||||||
"getRelativeTimeFormat": [Function],
|
|
||||||
},
|
|
||||||
"locale": "en",
|
|
||||||
"messages": Object {},
|
|
||||||
"onError": [Function],
|
|
||||||
"onWarn": [Function],
|
|
||||||
"textComponent": "span",
|
|
||||||
"timeZone": "Etc/UTC",
|
|
||||||
"wrapRichTextChunksInFragment": undefined,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="tooltip-title"
|
|
||||||
>
|
|
||||||
<Memo(MemoizedFormattedMessage)
|
|
||||||
defaultMessage="Upgrade to Unarchive"
|
|
||||||
id="workspace_limits.teams_limit_reached.upgrade_to_unarchive"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="tooltip-body"
|
|
||||||
>
|
|
||||||
<Memo(MemoizedFormattedMessage)
|
|
||||||
defaultMessage="You've reached the team limit for your current plan. Consider upgrading to unarchive this team or archive your other teams"
|
|
||||||
id="workspace_limits.teams_limit_reached.tool_tip"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</OverlayWrapper>
|
|
||||||
}
|
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
trigger={
|
trigger={
|
||||||
Array [
|
Array [
|
||||||
@@ -671,40 +593,95 @@ exports[`admin_console/team_channel_settings/team/TeamProfile__Cloud should matc
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div
|
<OverlayTrigger
|
||||||
className="disabled-overlay-wrapper"
|
defaultOverlayShown={false}
|
||||||
onBlur={[Function]}
|
delay={400}
|
||||||
onClick={null}
|
overlay={
|
||||||
onFocus={[Function]}
|
<OverlayWrapper
|
||||||
onMouseOut={[Function]}
|
intl={
|
||||||
onMouseOver={[Function]}
|
Object {
|
||||||
>
|
"$t": [Function],
|
||||||
<button
|
"defaultFormats": Object {},
|
||||||
className="btn btn-danger ArchiveButton ArchiveButton___archived cloud-limits-disabled"
|
"defaultLocale": "en",
|
||||||
disabled={true}
|
"defaultRichTextElements": undefined,
|
||||||
onClick={[Function]}
|
"fallbackOnEmptyString": true,
|
||||||
style={
|
"formatDate": [Function],
|
||||||
Object {
|
"formatDateTimeRange": [Function],
|
||||||
"pointerEvents": "none",
|
"formatDateToParts": [Function],
|
||||||
|
"formatDisplayName": [Function],
|
||||||
|
"formatList": [Function],
|
||||||
|
"formatListToParts": [Function],
|
||||||
|
"formatMessage": [Function],
|
||||||
|
"formatNumber": [Function],
|
||||||
|
"formatNumberToParts": [Function],
|
||||||
|
"formatPlural": [Function],
|
||||||
|
"formatRelativeTime": [Function],
|
||||||
|
"formatTime": [Function],
|
||||||
|
"formatTimeToParts": [Function],
|
||||||
|
"formats": Object {},
|
||||||
|
"formatters": Object {
|
||||||
|
"getDateTimeFormat": [Function],
|
||||||
|
"getDisplayNames": [Function],
|
||||||
|
"getListFormat": [Function],
|
||||||
|
"getMessageFormat": [Function],
|
||||||
|
"getNumberFormat": [Function],
|
||||||
|
"getPluralRules": [Function],
|
||||||
|
"getRelativeTimeFormat": [Function],
|
||||||
|
},
|
||||||
|
"locale": "en",
|
||||||
|
"messages": Object {},
|
||||||
|
"onError": [Function],
|
||||||
|
"onWarn": [Function],
|
||||||
|
"textComponent": "span",
|
||||||
|
"timeZone": "Etc/UTC",
|
||||||
|
"wrapRichTextChunksInFragment": undefined,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
className="icon icon-archive-arrow-up-outline"
|
|
||||||
/>
|
/>
|
||||||
<FormattedMessage
|
}
|
||||||
defaultMessage="Unarchive Team"
|
placement="bottom"
|
||||||
id="admin.team_settings.team_details.unarchiveTeam"
|
trigger={
|
||||||
|
Array [
|
||||||
|
"hover",
|
||||||
|
"focus",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="disabled-overlay-wrapper"
|
||||||
|
onBlur={[Function]}
|
||||||
|
onClick={null}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onMouseOut={[Function]}
|
||||||
|
onMouseOver={[Function]}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
className="btn btn-danger ArchiveButton ArchiveButton___archived cloud-limits-disabled"
|
||||||
|
disabled={true}
|
||||||
|
onClick={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"pointerEvents": "none",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type="button"
|
||||||
>
|
>
|
||||||
<span>
|
<i
|
||||||
Unarchive Team
|
className="icon icon-archive-arrow-up-outline"
|
||||||
</span>
|
/>
|
||||||
</FormattedMessage>
|
<FormattedMessage
|
||||||
</button>
|
defaultMessage="Unarchive Team"
|
||||||
</div>
|
id="admin.team_settings.team_details.unarchiveTeam"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
Unarchive Team
|
||||||
|
</span>
|
||||||
|
</FormattedMessage>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</OverlayTrigger>
|
||||||
</OverlayTrigger>
|
</OverlayTrigger>
|
||||||
</OverlayTrigger>
|
</WithTooltip>
|
||||||
<button
|
<button
|
||||||
className="btn btn-secondary upgrade-options-button"
|
className="btn btn-secondary upgrade-options-button"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
|||||||
@@ -16,13 +16,3 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-title {
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip-body {
|
|
||||||
font-weight: normal;
|
|
||||||
opacity: 56%;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -16,11 +16,10 @@ import {openModal} from 'actions/views/modals';
|
|||||||
import useGetUsage from 'components/common/hooks/useGetUsage';
|
import useGetUsage from 'components/common/hooks/useGetUsage';
|
||||||
import useGetUsageDeltas from 'components/common/hooks/useGetUsageDeltas';
|
import useGetUsageDeltas from 'components/common/hooks/useGetUsageDeltas';
|
||||||
import FormattedMarkdownMessage from 'components/formatted_markdown_message';
|
import FormattedMarkdownMessage from 'components/formatted_markdown_message';
|
||||||
import OverlayTrigger from 'components/overlay_trigger';
|
|
||||||
import PricingModal from 'components/pricing_modal';
|
import PricingModal from 'components/pricing_modal';
|
||||||
import Tooltip from 'components/tooltip';
|
|
||||||
import AdminPanel from 'components/widgets/admin_console/admin_panel';
|
import AdminPanel from 'components/widgets/admin_console/admin_panel';
|
||||||
import TeamIcon from 'components/widgets/team_icon/team_icon';
|
import TeamIcon from 'components/widgets/team_icon/team_icon';
|
||||||
|
import WithTooltip from 'components/with_tooltip';
|
||||||
|
|
||||||
import {ModalIdentifiers} from 'utils/constants';
|
import {ModalIdentifiers} from 'utils/constants';
|
||||||
import {imageURLForTeam} from 'utils/utils';
|
import {imageURLForTeam} from 'utils/utils';
|
||||||
@@ -66,26 +65,11 @@ export function TeamProfile({team, isArchived, onToggleArchive, isDisabled, save
|
|||||||
const button = () => {
|
const button = () => {
|
||||||
if (restoreDisabled) {
|
if (restoreDisabled) {
|
||||||
return (
|
return (
|
||||||
<OverlayTrigger
|
<WithTooltip
|
||||||
delay={400}
|
id='sharedTooltip'
|
||||||
|
title={defineMessage({id: 'workspace_limits.teams_limit_reached.upgrade_to_unarchive', defaultMessage: 'Upgrade to Unarchive'})}
|
||||||
|
hint={defineMessage({id: 'workspace_limits.teams_limit_reached.tool_tip', defaultMessage: 'You\'ve reached the team limit for your current plan. Consider upgrading to unarchive this team or archive your other teams'})}
|
||||||
placement='bottom'
|
placement='bottom'
|
||||||
disabled={!restoreDisabled}
|
|
||||||
overlay={
|
|
||||||
<Tooltip id='sharedTooltip'>
|
|
||||||
<div className={'tooltip-title'}>
|
|
||||||
<FormattedMessage
|
|
||||||
id={'workspace_limits.teams_limit_reached.upgrade_to_unarchive'}
|
|
||||||
defaultMessage={'Upgrade to Unarchive'}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className={'tooltip-body'}>
|
|
||||||
<FormattedMessage
|
|
||||||
id={'workspace_limits.teams_limit_reached.tool_tip'}
|
|
||||||
defaultMessage={'You\'ve reached the team limit for your current plan. Consider upgrading to unarchive this team or archive your other teams'}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{/* OverlayTrigger doesn't play nicely with `disabled` buttons, because the :hover events don't fire. This is a workaround to ensure the popover appears see: https://github.com/react-bootstrap/react-bootstrap/issues/1588*/}
|
{/* OverlayTrigger doesn't play nicely with `disabled` buttons, because the :hover events don't fire. This is a workaround to ensure the popover appears see: https://github.com/react-bootstrap/react-bootstrap/issues/1588*/}
|
||||||
<div
|
<div
|
||||||
@@ -116,8 +100,7 @@ export function TeamProfile({team, isArchived, onToggleArchive, isDisabled, save
|
|||||||
<FormattedMessage {...archiveBtn}/>
|
<FormattedMessage {...archiveBtn}/>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</OverlayTrigger>
|
</WithTooltip>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {FormattedMessage, defineMessages} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
import {AlertOutlineIcon} from '@mattermost/compass-icons/components';
|
import {AlertOutlineIcon} from '@mattermost/compass-icons/components';
|
||||||
|
|
||||||
@@ -11,17 +11,15 @@ import StatisticCount from 'components/analytics/statistic_count';
|
|||||||
|
|
||||||
import {calculateOverageUserActivated} from 'utils/overage_team';
|
import {calculateOverageUserActivated} from 'utils/overage_team';
|
||||||
|
|
||||||
|
import Title from './title';
|
||||||
|
|
||||||
type ActivatedUserCardProps = {
|
type ActivatedUserCardProps = {
|
||||||
seatsPurchased: number;
|
seatsPurchased: number;
|
||||||
activatedUsers: number | undefined;
|
activatedUsers: number | undefined;
|
||||||
isCloud: boolean;
|
isCloud: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const messages = defineMessages({
|
const ActivatedUserCard = ({activatedUsers, seatsPurchased, isCloud}: ActivatedUserCardProps) => {
|
||||||
totalUsers: {id: 'analytics.team.totalUsers', defaultMessage: 'Total Active Users'},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const ActivatedUserCard = ({activatedUsers, seatsPurchased, isCloud}: ActivatedUserCardProps) => {
|
|
||||||
const {isBetween5PercerntAnd10PercentPurchasedSeats, isOver10PercerntPurchasedSeats} = calculateOverageUserActivated({seatsPurchased, activeUsers: activatedUsers || 0});
|
const {isBetween5PercerntAnd10PercentPurchasedSeats, isOver10PercerntPurchasedSeats} = calculateOverageUserActivated({seatsPurchased, activeUsers: activatedUsers || 0});
|
||||||
const showOverageWarning = !isCloud && (isBetween5PercerntAnd10PercentPurchasedSeats || isOver10PercerntPurchasedSeats);
|
const showOverageWarning = !isCloud && (isBetween5PercerntAnd10PercentPurchasedSeats || isOver10PercerntPurchasedSeats);
|
||||||
|
|
||||||
@@ -36,11 +34,7 @@ export const ActivatedUserCard = ({activatedUsers, seatsPurchased, isCloud}: Act
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StatisticCount
|
<StatisticCount
|
||||||
title={
|
title={<Title/>}
|
||||||
<FormattedMessage
|
|
||||||
{...messages.totalUsers}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
icon='fa-users'
|
icon='fa-users'
|
||||||
status={activeUserStatus}
|
status={activeUserStatus}
|
||||||
count={activatedUsers}
|
count={activatedUsers}
|
||||||
@@ -67,3 +61,5 @@ export const ActivatedUserCard = ({activatedUsers, seatsPurchased, isCloud}: Act
|
|||||||
</StatisticCount>
|
</StatisticCount>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default ActivatedUserCard;
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {defineMessage, defineMessages, useIntl} from 'react-intl';
|
||||||
|
|
||||||
|
import {InformationOutlineIcon} from '@mattermost/compass-icons/components';
|
||||||
|
|
||||||
|
import ExternalLink from 'components/external_link';
|
||||||
|
import WithTooltip from 'components/with_tooltip';
|
||||||
|
|
||||||
|
export const messages = defineMessages({
|
||||||
|
totalUsers: {id: 'analytics.team.totalUsers', defaultMessage: 'Total Activated Users'},
|
||||||
|
});
|
||||||
|
|
||||||
|
const Title = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
return (
|
||||||
|
<WithTooltip
|
||||||
|
id='activated_user_title_tooltip'
|
||||||
|
title={defineMessage({id: 'analytics.team.totalUsers.title.tooltip.title', defaultMessage: 'Activated users on this server'})}
|
||||||
|
hint={defineMessage({id: 'analytics.team.totalUsers.title.tooltip.hint', defaultMessage: 'Also called Registered Users'})}
|
||||||
|
placement='top'
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<ExternalLink href='https://mattermost.com/pl/site-statistics-definitions'>
|
||||||
|
{intl.formatMessage(messages.totalUsers)}
|
||||||
|
<InformationOutlineIcon size='16'/>
|
||||||
|
</ExternalLink>
|
||||||
|
</span>
|
||||||
|
</WithTooltip>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Title;
|
||||||
@@ -9,7 +9,7 @@ import type {ClientLicense} from '@mattermost/types/config';
|
|||||||
|
|
||||||
import * as AdminActions from 'actions/admin_actions.jsx';
|
import * as AdminActions from 'actions/admin_actions.jsx';
|
||||||
|
|
||||||
import {ActivatedUserCard} from 'components/analytics/activated_users_card';
|
import ActivatedUserCard from 'components/analytics/activated_users_card';
|
||||||
import TrueUpReview from 'components/analytics/true_up_review';
|
import TrueUpReview from 'components/analytics/true_up_review';
|
||||||
import ExternalLink from 'components/external_link';
|
import ExternalLink from 'components/external_link';
|
||||||
import AdminHeader from 'components/widgets/admin_console/admin_header';
|
import AdminHeader from 'components/widgets/admin_console/admin_header';
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ import {General} from 'mattermost-redux/constants';
|
|||||||
import * as AdminActions from 'actions/admin_actions';
|
import * as AdminActions from 'actions/admin_actions';
|
||||||
|
|
||||||
import Banner from 'components/admin_console/banner';
|
import Banner from 'components/admin_console/banner';
|
||||||
import {ActivatedUserCard, messages as activatedUsersCardsMessages} from 'components/analytics/activated_users_card';
|
import ActivatedUserCard from 'components/analytics/activated_users_card';
|
||||||
|
import {messages as activatedUsersCardsMessages} from 'components/analytics/activated_users_card/title';
|
||||||
import LineChart from 'components/analytics/line_chart';
|
import LineChart from 'components/analytics/line_chart';
|
||||||
import StatisticCount from 'components/analytics/statistic_count';
|
import StatisticCount from 'components/analytics/statistic_count';
|
||||||
import TableChart from 'components/analytics/table_chart';
|
import TableChart from 'components/analytics/table_chart';
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ type Props = OverlayTriggerProps & {
|
|||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use (and expand when extrictly needed) WithTooltip instead
|
||||||
|
*/
|
||||||
const OverlayTrigger = React.forwardRef((props: Props, ref?: React.Ref<OriginalOverlayTrigger>) => {
|
const OverlayTrigger = React.forwardRef((props: Props, ref?: React.Ref<OriginalOverlayTrigger>) => {
|
||||||
const {overlay, disabled, ...otherProps} = props;
|
const {overlay, disabled, ...otherProps} = props;
|
||||||
|
|
||||||
|
|||||||
@@ -42,3 +42,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.console__body {
|
||||||
|
.shortcut-key {
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
&.shortcut-key--tooltip {
|
||||||
|
padding: 2px 5px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.08);
|
||||||
|
color: rgba(255, 255, 255, 0.72);
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ type Props = {
|
|||||||
placement?: string;
|
placement?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use (and expand when extrictly needed) WithTooltip instead
|
||||||
|
*/
|
||||||
export default function Tooltip(props: Props) {
|
export default function Tooltip(props: Props) {
|
||||||
return (
|
return (
|
||||||
<RBTooltip
|
<RBTooltip
|
||||||
|
|||||||
58
webapp/channels/src/components/with_tooltip/create_tooltip.tsx
Обычный файл
58
webapp/channels/src/components/with_tooltip/create_tooltip.tsx
Обычный файл
@@ -0,0 +1,58 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import type {ComponentProps} from 'react';
|
||||||
|
import type {MessageDescriptor} from 'react-intl';
|
||||||
|
|
||||||
|
import RenderEmoji from 'components/emoji/render_emoji';
|
||||||
|
import {ShortcutKey, ShortcutKeyVariant} from 'components/shortcut_key';
|
||||||
|
import Tooltip from 'components/tooltip';
|
||||||
|
|
||||||
|
import {getStringOrDescriptorComponent} from './utils';
|
||||||
|
|
||||||
|
export type CommonTooltipProps = {
|
||||||
|
id: string;
|
||||||
|
title: string | MessageDescriptor;
|
||||||
|
hint?: string | MessageDescriptor;
|
||||||
|
shortcut?: string[];
|
||||||
|
emoji?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTooltip(commonTooltipProps: CommonTooltipProps) {
|
||||||
|
return (props: Omit<ComponentProps<typeof Tooltip>, 'children' | 'id'>) => {
|
||||||
|
const title = getStringOrDescriptorComponent(commonTooltipProps.title);
|
||||||
|
const hint = getStringOrDescriptorComponent(commonTooltipProps.hint);
|
||||||
|
|
||||||
|
const emoji = commonTooltipProps.emoji && (
|
||||||
|
<RenderEmoji
|
||||||
|
emojiName={commonTooltipProps.emoji}
|
||||||
|
size={12}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<Tooltip
|
||||||
|
{...props}
|
||||||
|
id={commonTooltipProps.id}
|
||||||
|
>
|
||||||
|
<div className={'tooltip-title'}>
|
||||||
|
{emoji}
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
{commonTooltipProps.shortcut && (
|
||||||
|
<div className={'tooltip-shortcuts-container'}>
|
||||||
|
{commonTooltipProps.shortcut.map((v) => (
|
||||||
|
<ShortcutKey
|
||||||
|
key={v}
|
||||||
|
variant={ShortcutKeyVariant.Tooltip}
|
||||||
|
>
|
||||||
|
{v}
|
||||||
|
</ShortcutKey>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{commonTooltipProps.hint && (<div className={'tooltip-hint'}>{hint}</div>)}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
48
webapp/channels/src/components/with_tooltip/index.tsx
Обычный файл
48
webapp/channels/src/components/with_tooltip/index.tsx
Обычный файл
@@ -0,0 +1,48 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import React, {useMemo} from 'react';
|
||||||
|
import type {ComponentProps} from 'react';
|
||||||
|
|
||||||
|
import OverlayTrigger from 'components/overlay_trigger';
|
||||||
|
|
||||||
|
import Constants from 'utils/constants';
|
||||||
|
|
||||||
|
import type {CommonTooltipProps} from './create_tooltip';
|
||||||
|
import {createTooltip} from './create_tooltip';
|
||||||
|
|
||||||
|
type OverlayTriggerProps = ComponentProps<typeof OverlayTrigger>;
|
||||||
|
|
||||||
|
type WithTooltipProps = {
|
||||||
|
children: OverlayTriggerProps['children'];
|
||||||
|
placement: OverlayTriggerProps['placement'];
|
||||||
|
} & CommonTooltipProps;
|
||||||
|
const WithTooltip = ({
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
emoji,
|
||||||
|
hint,
|
||||||
|
shortcut,
|
||||||
|
placement,
|
||||||
|
children,
|
||||||
|
}: WithTooltipProps) => {
|
||||||
|
const ThisTooltip = useMemo(() => createTooltip({
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
emoji,
|
||||||
|
hint,
|
||||||
|
shortcut,
|
||||||
|
}), [id, title, emoji, hint, shortcut]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<OverlayTrigger
|
||||||
|
delay={Constants.OVERLAY_TIME_DELAY}
|
||||||
|
overlay={<ThisTooltip/>}
|
||||||
|
placement={placement}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</OverlayTrigger>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WithTooltip;
|
||||||
24
webapp/channels/src/components/with_tooltip/utils.tsx
Обычный файл
24
webapp/channels/src/components/with_tooltip/utils.tsx
Обычный файл
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import type {ComponentProps} from 'react';
|
||||||
|
import type {MessageDescriptor} from 'react-intl';
|
||||||
|
import {FormattedMessage} from 'react-intl';
|
||||||
|
|
||||||
|
export function getStringOrDescriptorComponent(v: string | MessageDescriptor | undefined, values?: ComponentProps<typeof FormattedMessage>['values']) {
|
||||||
|
if (!v) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof v === 'string') {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormattedMessage
|
||||||
|
{...v}
|
||||||
|
values={values}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2713,7 +2713,9 @@
|
|||||||
"analytics.team.recentUsers": "Recent Active Users",
|
"analytics.team.recentUsers": "Recent Active Users",
|
||||||
"analytics.team.title": "Team Statistics for {team}",
|
"analytics.team.title": "Team Statistics for {team}",
|
||||||
"analytics.team.totalPosts": "Total Posts",
|
"analytics.team.totalPosts": "Total Posts",
|
||||||
"analytics.team.totalUsers": "Total Active Users",
|
"analytics.team.totalUsers": "Total Activated Users",
|
||||||
|
"analytics.team.totalUsers.title.tooltip.hint": "Also called Registered Users",
|
||||||
|
"analytics.team.totalUsers.title.tooltip.title": "Activated users on this server",
|
||||||
"announcement_bar.error.email_verification_required": "Check your email inbox to verify the address.",
|
"announcement_bar.error.email_verification_required": "Check your email inbox to verify the address.",
|
||||||
"announcement_bar.error.license_expired": "{licenseSku} license is expired and some features may be disabled.",
|
"announcement_bar.error.license_expired": "{licenseSku} license is expired and some features may be disabled.",
|
||||||
"announcement_bar.error.license_expiring": "{licenseSku} license expires on {date, date, long}.",
|
"announcement_bar.error.license_expiring": "{licenseSku} license expires on {date, date, long}.",
|
||||||
|
|||||||
@@ -49,6 +49,29 @@
|
|||||||
.tooltip-help {
|
.tooltip-help {
|
||||||
color: rgba(255, 255, 255, 0.64);
|
color: rgba(255, 255, 255, 0.64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tooltip-title {
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-hint {
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 16px;
|
||||||
|
opacity: 56%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-shortcuts-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 4px 0;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoticon {
|
||||||
|
margin-right: 6px;
|
||||||
|
vertical-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.floating-ui-tooltip {
|
.floating-ui-tooltip {
|
||||||
|
|||||||
@@ -10,6 +10,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.analytics_tooltip_body {
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
.team_statistics {
|
.team_statistics {
|
||||||
&--warning {
|
&--warning {
|
||||||
// Adding the !important because this class has less preference in some html elements
|
// Adding the !important because this class has less preference in some html elements
|
||||||
@@ -71,6 +75,11 @@
|
|||||||
width: calc(100% - 20px);
|
width: calc(100% - 20px);
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
margin-left: 5px;
|
||||||
|
vertical-align: text-top;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.fa {
|
.fa {
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user