Improve consistency on hooks (#28868)
* Improve consistency on useOpenX hooks * Review other hooks * i18n and minor fix * Address feedback
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
48c42fc588
Коммит
8214ffbacd
@@ -48,5 +48,5 @@ export function useControlModal<T>(modalData: ModalData<T>): ControlModal {
|
||||
close: () => {
|
||||
dispatch(closeModal(modalData.modalId));
|
||||
},
|
||||
}), [modalData]);
|
||||
}), [modalData, dispatch]);
|
||||
}
|
||||
|
||||
@@ -18,20 +18,22 @@ type CopyResponse = {
|
||||
|
||||
const DEFAULT_COPY_TIMEOUT = 4000;
|
||||
|
||||
export default function useCopyText(options: CopyOptions): CopyResponse {
|
||||
export default function useCopyText({
|
||||
text,
|
||||
successCopyTimeout: successCopyTimeoutReceived,
|
||||
trackCallback,
|
||||
}: CopyOptions): CopyResponse {
|
||||
const [copiedRecently, setCopiedRecently] = useState(false);
|
||||
const [copyError, setCopyError] = useState(false);
|
||||
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
let successCopyTimeout = DEFAULT_COPY_TIMEOUT;
|
||||
if (options.successCopyTimeout || options.successCopyTimeout === 0) {
|
||||
successCopyTimeout = options.successCopyTimeout;
|
||||
if (successCopyTimeoutReceived || successCopyTimeoutReceived === 0) {
|
||||
successCopyTimeout = successCopyTimeoutReceived;
|
||||
}
|
||||
|
||||
const onClick = useCallback(() => {
|
||||
if (options.trackCallback) {
|
||||
options.trackCallback();
|
||||
}
|
||||
trackCallback?.();
|
||||
|
||||
if (timerRef.current) {
|
||||
clearTimeout(timerRef.current);
|
||||
@@ -39,7 +41,7 @@ export default function useCopyText(options: CopyOptions): CopyResponse {
|
||||
}
|
||||
const clipboard = navigator.clipboard;
|
||||
if (clipboard) {
|
||||
clipboard.writeText(options.text).
|
||||
clipboard.writeText(text).
|
||||
then(() => {
|
||||
setCopiedRecently(true);
|
||||
setCopyError(false);
|
||||
@@ -50,7 +52,7 @@ export default function useCopyText(options: CopyOptions): CopyResponse {
|
||||
});
|
||||
} else {
|
||||
const textField = document.createElement('textarea');
|
||||
textField.innerText = options.text;
|
||||
textField.innerText = text;
|
||||
textField.style.position = 'fixed';
|
||||
textField.style.opacity = '0';
|
||||
|
||||
@@ -72,7 +74,7 @@ export default function useCopyText(options: CopyOptions): CopyResponse {
|
||||
setCopiedRecently(false);
|
||||
setCopyError(false);
|
||||
}, successCopyTimeout);
|
||||
}, [options.text, successCopyTimeout]);
|
||||
}, [successCopyTimeout, text, trackCallback]);
|
||||
|
||||
return {
|
||||
copiedRecently,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {useCallback} from 'react';
|
||||
import {defineMessage} from 'react-intl';
|
||||
import {useSelector} from 'react-redux';
|
||||
|
||||
@@ -12,23 +13,23 @@ type UseExpandOverageUsersCheckArgs = {
|
||||
banner: 'global banner' | 'invite modal';
|
||||
}
|
||||
|
||||
const cta = defineMessage({
|
||||
id: 'licensingPage.overageUsersBanner.cta',
|
||||
defaultMessage: 'Contact Sales',
|
||||
});
|
||||
|
||||
export const useExpandOverageUsersCheck = ({
|
||||
isWarningState,
|
||||
banner,
|
||||
}: UseExpandOverageUsersCheckArgs) => {
|
||||
const expandableLink = useSelector(getExpandSeatsLink);
|
||||
|
||||
const cta = defineMessage({
|
||||
id: 'licensingPage.overageUsersBanner.cta',
|
||||
defaultMessage: 'Contact Sales',
|
||||
});
|
||||
|
||||
const trackEventFn = (cta: 'Contact Sales' | 'Self Serve') => {
|
||||
const trackEventFn = useCallback((cta: 'Contact Sales' | 'Self Serve') => {
|
||||
trackEvent('insights', isWarningState ? 'click_true_up_warning' : 'click_true_up_error', {
|
||||
cta,
|
||||
banner,
|
||||
});
|
||||
};
|
||||
}, [banner, isWarningState]);
|
||||
|
||||
return {
|
||||
cta,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {useState} from 'react';
|
||||
import {useCallback, useState} from 'react';
|
||||
import {defineMessages} from 'react-intl';
|
||||
|
||||
import type {NotifyAdminRequest} from '@mattermost/types/cloud';
|
||||
|
||||
@@ -19,14 +20,6 @@ export const NotifyStatus = {
|
||||
|
||||
export type NotifyStatusValues = ValueOf<typeof NotifyStatus>;
|
||||
|
||||
export const DefaultBtnText = {
|
||||
NotifyAdmin: 'Notify your admin',
|
||||
Notifying: 'Notifying...',
|
||||
Notified: 'Admin notified!',
|
||||
AlreadyNotified: 'Already notified!',
|
||||
Failed: 'Try again later!',
|
||||
} as const;
|
||||
|
||||
type ValueOf<T> = T[keyof T];
|
||||
|
||||
type UseNotifyAdminArgs = {
|
||||
@@ -45,25 +38,40 @@ type NotifyAdminArgs = {
|
||||
};
|
||||
}
|
||||
|
||||
const messages = defineMessages({
|
||||
[NotifyStatus.Started]: {
|
||||
id: 'notify_admin_to_upgrade_cta.notify-admin.notifying',
|
||||
defaultMessage: 'Notifying...',
|
||||
},
|
||||
[NotifyStatus.Success]: {
|
||||
id: 'notify_admin_to_upgrade_cta.notify-admin.notified',
|
||||
defaultMessage: 'Admin notified!',
|
||||
},
|
||||
[NotifyStatus.AlreadyComplete]: {
|
||||
id: 'notify_admin_to_upgrade_cta.notify-admin.already_notified',
|
||||
defaultMessage: 'Already notified!',
|
||||
},
|
||||
[NotifyStatus.Failed]: {
|
||||
id: 'notify_admin_to_upgrade_cta.notify-admin.failed',
|
||||
defaultMessage: 'Try again later!',
|
||||
},
|
||||
[NotifyStatus.NotStarted]: {
|
||||
id: 'notify_admin_to_upgrade_cta.notify-admin.notify',
|
||||
defaultMessage: 'Notify your admin',
|
||||
},
|
||||
});
|
||||
|
||||
export const useGetNotifyAdmin = (args: UseNotifyAdminArgs) => {
|
||||
const [notifyStatus, setStatus] = useState<ValueOf<typeof NotifyStatus>>(NotifyStatus.NotStarted);
|
||||
|
||||
const btnText = (status: ValueOf<typeof NotifyStatus>): {id: string; defaultMessage: string} => {
|
||||
switch (status) {
|
||||
case NotifyStatus.Started:
|
||||
return {id: 'notify_admin_to_upgrade_cta.notify-admin.notifying', defaultMessage: DefaultBtnText.Notifying};
|
||||
case NotifyStatus.Success:
|
||||
return {id: 'notify_admin_to_upgrade_cta.notify-admin.notified', defaultMessage: DefaultBtnText.Notified};
|
||||
case NotifyStatus.AlreadyComplete:
|
||||
return {id: 'notify_admin_to_upgrade_cta.notify-admin.already_notified', defaultMessage: DefaultBtnText.AlreadyNotified};
|
||||
case NotifyStatus.Failed:
|
||||
return {id: 'notify_admin_to_upgrade_cta.notify-admin.failed', defaultMessage: DefaultBtnText.Failed};
|
||||
default:
|
||||
return args.ctaText || {id: 'notify_admin_to_upgrade_cta.notify-admin.notify', defaultMessage: DefaultBtnText.NotifyAdmin};
|
||||
const btnText = useCallback((status: ValueOf<typeof NotifyStatus>): {id: string; defaultMessage: string} => {
|
||||
if (args.ctaText && status === NotifyStatus.NotStarted) {
|
||||
return args.ctaText;
|
||||
}
|
||||
};
|
||||
return messages[status];
|
||||
}, [args.ctaText]);
|
||||
|
||||
const notifyAdmin = async ({requestData, trackingArgs}: NotifyAdminArgs) => {
|
||||
const notifyAdmin = useCallback(async ({requestData, trackingArgs}: NotifyAdminArgs) => {
|
||||
try {
|
||||
setStatus(NotifyStatus.Started);
|
||||
await Client4.notifyAdmin(requestData);
|
||||
@@ -76,7 +84,7 @@ export const useGetNotifyAdmin = (args: UseNotifyAdminArgs) => {
|
||||
setStatus(NotifyStatus.Failed);
|
||||
}
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
return {
|
||||
notifyStatus,
|
||||
|
||||
@@ -10,12 +10,12 @@ const useGetTotalUsersNoBots = (includeInactive = false): number => {
|
||||
const dispatch = useDispatch();
|
||||
const [userCount, setUserCount] = useState<number>(0);
|
||||
|
||||
const getTotalUsers = async () => {
|
||||
const {data} = await dispatch(getFilteredUsersStats({include_bots: false, include_deleted: includeInactive}, false));
|
||||
setUserCount(data?.total_users_count ?? 0);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const getTotalUsers = async () => {
|
||||
const {data} = await dispatch(getFilteredUsersStats({include_bots: false, include_deleted: includeInactive}, false));
|
||||
setUserCount(data?.total_users_count ?? 0);
|
||||
};
|
||||
|
||||
getTotalUsers();
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {useCallback} from 'react';
|
||||
import {useDispatch} from 'react-redux';
|
||||
|
||||
import {trackEvent} from 'actions/telemetry_actions';
|
||||
@@ -17,7 +18,7 @@ type TelemetryProps = Pick<OpenDowngradeModalOptions, 'trackingLocation'>
|
||||
|
||||
export default function useOpenDowngradeModal() {
|
||||
const dispatch = useDispatch();
|
||||
return (telemetryProps: TelemetryProps) => {
|
||||
return useCallback((telemetryProps: TelemetryProps) => {
|
||||
trackEvent(TELEMETRY_CATEGORIES.CLOUD_ADMIN, 'click_open_downgrade_modal', {
|
||||
callerInfo: telemetryProps.trackingLocation,
|
||||
});
|
||||
@@ -25,5 +26,5 @@ export default function useOpenDowngradeModal() {
|
||||
modalId: ModalIdentifiers.DOWNGRADE_MODAL,
|
||||
dialogType: DowngradeModal,
|
||||
}));
|
||||
};
|
||||
}, [dispatch]);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {useCallback} from 'react';
|
||||
import {useDispatch} from 'react-redux';
|
||||
|
||||
import {trackEvent} from 'actions/telemetry_actions';
|
||||
@@ -12,11 +13,11 @@ import {ModalIdentifiers} from 'utils/constants';
|
||||
|
||||
export default function useOpenInvitePeopleModal() {
|
||||
const dispatch = useDispatch();
|
||||
return () => {
|
||||
return useCallback(() => {
|
||||
trackEvent('invite_people', 'click_open_invite_people_modal');
|
||||
dispatch(openModal({
|
||||
modalId: ModalIdentifiers.INVITATION,
|
||||
dialogType: InvitationModal,
|
||||
}));
|
||||
};
|
||||
}, [dispatch]);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {useCallback} from 'react';
|
||||
import {useDispatch, useSelector} from 'react-redux';
|
||||
|
||||
import {isCurrentLicenseCloud} from 'mattermost-redux/selectors/entities/cloud';
|
||||
@@ -19,8 +20,9 @@ export type TelemetryProps = {
|
||||
export default function useOpenPricingModal() {
|
||||
const dispatch = useDispatch();
|
||||
const isCloud = useSelector(isCurrentLicenseCloud);
|
||||
let category;
|
||||
return (telemetryProps?: TelemetryProps) => {
|
||||
const openPricingModal = useCallback((telemetryProps?: TelemetryProps) => {
|
||||
let category;
|
||||
|
||||
if (isCloud) {
|
||||
category = TELEMETRY_CATEGORIES.CLOUD_PRICING;
|
||||
} else {
|
||||
@@ -36,5 +38,7 @@ export default function useOpenPricingModal() {
|
||||
callerCTA: telemetryProps?.trackingLocation,
|
||||
},
|
||||
}));
|
||||
};
|
||||
}, [dispatch, isCloud]);
|
||||
|
||||
return openPricingModal;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {useCallback} from 'react';
|
||||
import {useSelector} from 'react-redux';
|
||||
|
||||
import {getCloudCustomer, isCurrentLicenseCloud} from 'mattermost-redux/selectors/entities/cloud';
|
||||
@@ -9,6 +10,8 @@ import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
|
||||
import {LicenseLinks} from 'utils/constants';
|
||||
import {buildMMURL, goToMattermostContactSalesForm} from 'utils/contact_support_sales';
|
||||
|
||||
const utmSource = 'mattermost';
|
||||
|
||||
export default function useOpenSalesLink(): [() => void, string] {
|
||||
const isCloud = useSelector(isCurrentLicenseCloud);
|
||||
const customer = useSelector(getCloudCustomer);
|
||||
@@ -17,7 +20,6 @@ export default function useOpenSalesLink(): [() => void, string] {
|
||||
let firstName = '';
|
||||
let lastName = '';
|
||||
let companyName = '';
|
||||
const utmSource = 'mattermost';
|
||||
let utmMedium = 'in-product';
|
||||
|
||||
if (isCloud && customer) {
|
||||
@@ -31,8 +33,9 @@ export default function useOpenSalesLink(): [() => void, string] {
|
||||
}
|
||||
|
||||
const contactSalesLink = buildMMURL(LicenseLinks.CONTACT_SALES, firstName, lastName, companyName, customerEmail, utmSource, utmMedium);
|
||||
const goToSalesLinkFunc = () => {
|
||||
const goToSalesLinkFunc = useCallback(() => {
|
||||
goToMattermostContactSalesForm(firstName, lastName, companyName, customerEmail, utmSource, utmMedium);
|
||||
};
|
||||
}, [firstName, lastName, companyName, customerEmail, utmMedium]);
|
||||
|
||||
return [goToSalesLinkFunc, contactSalesLink];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {useCallback} from 'react';
|
||||
import {useDispatch} from 'react-redux';
|
||||
|
||||
import {openModal} from 'actions/views/modals';
|
||||
@@ -13,7 +14,7 @@ import type {TelemetryProps} from './useOpenPricingModal';
|
||||
|
||||
export default function useOpenStartTrialFormModal() {
|
||||
const dispatch = useDispatch();
|
||||
return (telemetryProps?: TelemetryProps, onClose?: () => void) => {
|
||||
return useCallback((telemetryProps?: TelemetryProps, onClose?: () => void) => {
|
||||
dispatch(openModal({
|
||||
modalId: ModalIdentifiers.START_TRIAL_FORM_MODAL,
|
||||
dialogType: StartTrialFormModal,
|
||||
@@ -22,5 +23,5 @@ export default function useOpenStartTrialFormModal() {
|
||||
onClose,
|
||||
},
|
||||
}));
|
||||
};
|
||||
}, [dispatch]);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {useCallback} from 'react';
|
||||
import {useSelector} from 'react-redux';
|
||||
|
||||
import {getCloudCustomer} from 'mattermost-redux/selectors/entities/cloud';
|
||||
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {getCloudSupportLink, getSelfHostedSupportLink, goToCloudSupportForm, goToSelfHostedSupportForm} from 'utils/contact_support_sales';
|
||||
import {getCloudSupportLink, goToCloudSupportForm} from 'utils/contact_support_sales';
|
||||
|
||||
export function useOpenCloudZendeskSupportForm(subject: string, description: string): [() => void, string] {
|
||||
const customer = useSelector(getCloudCustomer);
|
||||
@@ -14,14 +14,9 @@ export function useOpenCloudZendeskSupportForm(subject: string, description: str
|
||||
|
||||
const url = getCloudSupportLink(customerEmail, subject, description, window.location.host);
|
||||
|
||||
return [() => goToCloudSupportForm(customerEmail, subject, description, window.location.host), url];
|
||||
}
|
||||
|
||||
export function useOpenSelfHostedZendeskSupportForm(subject: string): [() => void, string] {
|
||||
const currentUser = useSelector(getCurrentUser);
|
||||
const customerEmail = currentUser.email || '';
|
||||
|
||||
const url = getSelfHostedSupportLink(customerEmail, subject);
|
||||
|
||||
return [() => goToSelfHostedSupportForm(customerEmail, subject), url];
|
||||
const openContactSupport = useCallback(
|
||||
() => goToCloudSupportForm(customerEmail, subject, description, window.location.host),
|
||||
[customerEmail, subject, description],
|
||||
);
|
||||
return [openContactSupport, url];
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function usePreference(category: string, name: string): [string |
|
||||
value,
|
||||
};
|
||||
return dispatch(savePreferences(userId, [preference]));
|
||||
}, [category, name, userId]);
|
||||
}, [category, dispatch, name, userId]);
|
||||
|
||||
return useMemo(() => ([preferenceValue, setPreference]), [preferenceValue, setPreference]);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function useSavePreferences(): (preferences: MinimalPreferenceTyp
|
||||
const preferencesList = ((preferences as MinimalPreferenceType[]).length ? preferences : [preferences]) as MinimalPreferenceType[];
|
||||
const preferencesListWithUserId: PreferenceType[] = preferencesList.map((x) => ({...x, user_id: userId}));
|
||||
dispatch(savePreferences(userId, preferencesListWithUserId));
|
||||
}, [userId]);
|
||||
}, [dispatch, userId]);
|
||||
}
|
||||
|
||||
type MinimalBoolPreferenceType = Omit<MinimalPreferenceType, 'value'> & {value?: boolean}
|
||||
|
||||
@@ -24,8 +24,6 @@ function useTelemetryIdentitySync() {
|
||||
Client4.setUserRoles(userRoles);
|
||||
}
|
||||
}, [userId, userRoles]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default useTelemetryIdentitySync;
|
||||
|
||||
@@ -4444,6 +4444,11 @@
|
||||
"no_results.user_groups.title": "No groups yet",
|
||||
"notification.crt": "Reply in {title}",
|
||||
"notification.dm": "Direct Message",
|
||||
"notify_admin_to_upgrade_cta.notify-admin.already_notified": "Already notified!",
|
||||
"notify_admin_to_upgrade_cta.notify-admin.failed": "Try again later!",
|
||||
"notify_admin_to_upgrade_cta.notify-admin.notified": "Admin notified!",
|
||||
"notify_admin_to_upgrade_cta.notify-admin.notify": "Notify your admin",
|
||||
"notify_admin_to_upgrade_cta.notify-admin.notifying": "Notifying...",
|
||||
"notify_all.confirm": "Confirm",
|
||||
"notify_all.title.confirm": "Confirm Sending Notifications to Entire Channel",
|
||||
"notify_all.title.confirm_groups": "Confirm sending notifications to groups",
|
||||
|
||||
@@ -40,24 +40,6 @@ export const buildZendeskSupportForm = (form: ZendeskSupportForm, formFieldIDs:
|
||||
return formUrl;
|
||||
};
|
||||
|
||||
export const goToSelfHostedSupportForm = (email: string, subject: string) => {
|
||||
const form = ZendeskSupportForm.SELF_HOSTED_SUPPORT_FORM;
|
||||
const url = buildZendeskSupportForm(form, [
|
||||
{id: ZendeskFormFieldIDs.EMAIL, val: email},
|
||||
{id: ZendeskFormFieldIDs.SUBJECT, val: subject},
|
||||
]);
|
||||
window.open(url, '_blank');
|
||||
};
|
||||
|
||||
export const getSelfHostedSupportLink = (email: string, subject: string) => {
|
||||
const form = ZendeskSupportForm.SELF_HOSTED_SUPPORT_FORM;
|
||||
const url = buildZendeskSupportForm(form, [
|
||||
{id: ZendeskFormFieldIDs.EMAIL, val: email},
|
||||
{id: ZendeskFormFieldIDs.SUBJECT, val: subject},
|
||||
]);
|
||||
return url;
|
||||
};
|
||||
|
||||
export const goToCloudSupportForm = (email: string, subject: string, description: string, workspaceURL: string) => {
|
||||
const form = ZendeskSupportForm.CLOUD_SUPPORT_FORM;
|
||||
let url = buildZendeskSupportForm(form, [
|
||||
|
||||
Ссылка в новой задаче
Block a user