* Improve consistency on useOpenX hooks

* Review other hooks

* i18n and minor fix

* Address feedback
Этот коммит содержится в:
Daniel Espino García
2024-10-24 10:52:01 +02:00
коммит произвёл GitHub
родитель 48c42fc588
Коммит 8214ffbacd
16 изменённых файлов: 93 добавлений и 92 удалений

Просмотреть файл

@@ -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, [