MM-47849 - show worktemplate tourtip only once (#22703)

Этот коммит содержится в:
Pablo Andrés Vélez Vidal
2023-03-29 13:39:55 +02:00
коммит произвёл GitHub
родитель b892fe0555
Коммит 5a76d20a1a
7 изменённых файлов: 25 добавлений и 26 удалений

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

@@ -4,6 +4,8 @@
import React from 'react'; import React from 'react';
import {FormattedMessage, useIntl} from 'react-intl'; import {FormattedMessage, useIntl} from 'react-intl';
import {useMeasurePunchouts} from '@mattermost/components';
import OnboardingWorkTemplateTourTip from './worktemplate_explore_tour_tip'; import OnboardingWorkTemplateTourTip from './worktemplate_explore_tour_tip';
import {useShowTourTip} from './useShowTourTip'; import {useShowTourTip} from './useShowTourTip';
@@ -11,6 +13,7 @@ export const BoardsTourTip = (): JSX.Element | null => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const {playbooksCount, boardsCount, showBoardsTour} = useShowTourTip(); const {playbooksCount, boardsCount, showBoardsTour} = useShowTourTip();
const overlayPunchOut = useMeasurePunchouts(['sidebar-right'], []);
if (!showBoardsTour) { if (!showBoardsTour) {
return null; return null;
@@ -50,11 +53,11 @@ export const BoardsTourTip = (): JSX.Element | null => {
return ( return (
<OnboardingWorkTemplateTourTip <OnboardingWorkTemplateTourTip
pulsatingDotPlacement={'left'} pulsatingDotPlacement={'left'}
pulsatingDotTranslate={{x: 10, y: -140}} pulsatingDotTranslate={{x: 10, y: -350}}
title={title} title={title}
screen={screen} screen={screen}
overlayPunchOut={overlayPunchOut}
singleTip={playbooksCount === 0} singleTip={playbooksCount === 0}
overlayPunchOut={null}
placement='left-start' placement='left-start'
showOptOut={false} showOptOut={false}
/> />

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

@@ -4,12 +4,15 @@
import React from 'react'; import React from 'react';
import {FormattedMessage, useIntl} from 'react-intl'; import {FormattedMessage, useIntl} from 'react-intl';
import {useMeasurePunchouts} from '@mattermost/components';
import {useShowTourTip} from './useShowTourTip'; import {useShowTourTip} from './useShowTourTip';
import OnboardingWorkTemplateTourTip from './worktemplate_explore_tour_tip'; import OnboardingWorkTemplateTourTip from './worktemplate_explore_tour_tip';
export const PlaybooksTourTip = (): JSX.Element | null => { export const PlaybooksTourTip = (): JSX.Element | null => {
const {formatMessage} = useIntl(); const {formatMessage} = useIntl();
const {playbooksCount, boardsCount, showPlaybooksTour} = useShowTourTip(); const {playbooksCount, boardsCount, showPlaybooksTour} = useShowTourTip();
const overlayPunchOut = useMeasurePunchouts(['sidebar-right'], []);
if (!showPlaybooksTour) { if (!showPlaybooksTour) {
return null; return null;
@@ -53,7 +56,7 @@ export const PlaybooksTourTip = (): JSX.Element | null => {
title={title} title={title}
screen={screen} screen={screen}
singleTip={boardsCount === 0} singleTip={boardsCount === 0}
overlayPunchOut={null} overlayPunchOut={overlayPunchOut}
placement='left-start' placement='left-start'
showOptOut={false} showOptOut={false}
/> />

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

@@ -3,7 +3,7 @@
import {useSelector} from 'react-redux'; import {useSelector} from 'react-redux';
import {getCurrentUserId} from 'mattermost-redux/selectors/entities/common'; import {getCurrentChannelId, getCurrentUserId} from 'mattermost-redux/selectors/entities/common';
import {getConfig, getWorkTemplatesLinkedProducts} from 'mattermost-redux/selectors/entities/general'; import {getConfig, getWorkTemplatesLinkedProducts} from 'mattermost-redux/selectors/entities/general';
import {getInt} from 'mattermost-redux/selectors/entities/preferences'; import {getInt} from 'mattermost-redux/selectors/entities/preferences';
@@ -17,18 +17,22 @@ export const useShowTourTip = () => {
const activeRhsComponent = useSelector(getActiveRhsComponent); const activeRhsComponent = useSelector(getActiveRhsComponent);
const pluginId = activeRhsComponent?.pluginId || ''; const pluginId = activeRhsComponent?.pluginId || '';
const currentChannelId = useSelector(getCurrentChannelId);
const currentUserId = useSelector(getCurrentUserId); const currentUserId = useSelector(getCurrentUserId);
const enableTutorial = useSelector(getConfig).EnableTutorial === 'true'; const enableTutorial = useSelector(getConfig).EnableTutorial === 'true';
const tutorialStep = useSelector((state: GlobalState) => getInt(state, TutorialTourName.WORK_TEMPLATE_TUTORIAL, currentUserId, 0)); const tutorialStep = useSelector((state: GlobalState) => getInt(state, TutorialTourName.WORK_TEMPLATE_TUTORIAL, currentUserId, 0));
const workTemplateTourTipShown = tutorialStep === WorkTemplateTourSteps.FINISHED; const workTemplateTourTipShown = tutorialStep === WorkTemplateTourSteps.FINISHED;
const showProductTour = !workTemplateTourTipShown && enableTutorial;
const channelLinkedItems = useSelector(getWorkTemplatesLinkedProducts); const channelLinkedItems = useSelector(getWorkTemplatesLinkedProducts);
const boardsCount = channelLinkedItems?.boards || 0; const boardsCount = channelLinkedItems?.boards || 0;
const playbooksCount = channelLinkedItems?.playbooks || 0; const playbooksCount = channelLinkedItems?.playbooks || 0;
const channelId = channelLinkedItems?.channelId || null;
const showProductTour = channelId && channelId === currentChannelId && !workTemplateTourTipShown && enableTutorial;
const showBoardsTour = showProductTour && pluginId === suitePluginIds.boards && boardsCount > 0; const showBoardsTour = showProductTour && pluginId === suitePluginIds.boards && boardsCount > 0;
const showPlaybooksTour = showProductTour && pluginId === suitePluginIds.playbooks && playbooksCount > 0; const showPlaybooksTour = showProductTour && pluginId === suitePluginIds.playbooks && playbooksCount > 0;
@@ -38,5 +42,6 @@ export const useShowTourTip = () => {
showPlaybooksTour, showPlaybooksTour,
boardsCount, boardsCount,
playbooksCount, playbooksCount,
showProductTour,
}; };
}; };

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

@@ -8,7 +8,7 @@ import {useDispatch, useSelector} from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import LocalizedIcon from 'components/localized_icon'; import LocalizedIcon from 'components/localized_icon';
import {TTNameMapToATStatusKey, TutorialTourName, WorkTemplateTourSteps} from 'components/tours/constant'; import {TTNameMapToATStatusKey, TutorialTourName} from 'components/tours/constant';
import {closeModal as closeModalAction} from 'actions/views/modals'; import {closeModal as closeModalAction} from 'actions/views/modals';
import {trackEvent} from 'actions/telemetry_actions'; import {trackEvent} from 'actions/telemetry_actions';
@@ -195,18 +195,15 @@ const WorkTemplateModal = () => {
* Creates the necessary data in the global store as long storing in DB preferences the tourtip information * Creates the necessary data in the global store as long storing in DB preferences the tourtip information
* @param template current used worktempplate * @param template current used worktempplate
*/ */
const tourTipActions = async (template: WorkTemplate) => { const tourTipActions = async (template: WorkTemplate, firstChannelId: string) => {
const linkedProductsCount = getContentCount(template, playbookTemplates); const linkedProductsCount = getContentCount(template, playbookTemplates, firstChannelId);
// stepValue and pluginId are used for showing the tourtip for the used template // stepValue and pluginId are used for showing the tourtip for the used template
let stepValue = 0;
let pluginId; let pluginId;
if (linkedProductsCount.playbooks) { if (linkedProductsCount.playbooks) {
pluginId = rhsPluggableIds.get(suitePluginIds.playbooks); pluginId = rhsPluggableIds.get(suitePluginIds.playbooks);
stepValue = WorkTemplateTourSteps.PLAYBOOKS_TOUR_TIP;
} else { } else {
pluginId = rhsPluggableIds.get(suitePluginIds.boards); pluginId = rhsPluggableIds.get(suitePluginIds.boards);
stepValue = WorkTemplateTourSteps.BOARDS_TOUR_TIP;
} }
if (!pluginId) { if (!pluginId) {
@@ -219,17 +216,8 @@ const WorkTemplateModal = () => {
// store the required preferences for the tourtip // store the required preferences for the tourtip
const tourCategory = TutorialTourName.WORK_TEMPLATE_TUTORIAL; const tourCategory = TutorialTourName.WORK_TEMPLATE_TUTORIAL;
const preferences = [ const preferences = [
// here reset the step value to be able to show the tour again (if we dedide to show the tour only once, this must be removed)
{
user_id: currentUserId,
category: tourCategory,
name: currentUserId,
value: stepValue.toString(),
},
// this one is for defining the auto tour start for the tour tip
{ {
user_id: currentUserId, user_id: currentUserId,
category: tourCategory, category: tourCategory,
@@ -237,7 +225,6 @@ const WorkTemplateModal = () => {
value: String(AutoTourStatus.ENABLED), value: String(AutoTourStatus.ENABLED),
}, },
]; ];
await dispatch(savePreferences(currentUserId, preferences)); await dispatch(savePreferences(currentUserId, preferences));
dispatch(showRHSPlugin(pluginId)); dispatch(showRHSPlugin(pluginId));
@@ -285,7 +272,7 @@ const WorkTemplateModal = () => {
dispatch(loadIfNecessaryAndSwitchToChannelById(firstChannelId)); dispatch(loadIfNecessaryAndSwitchToChannelById(firstChannelId));
} }
await tourTipActions(template); await tourTipActions(template, firstChannelId);
setIsCreating(false); setIsCreating(false);
closeModal(); closeModal();

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

@@ -31,10 +31,11 @@ export function getTemplateDefaultIllustration(template: WorkTemplate): string {
return ''; return '';
} }
export const getContentCount = (template: WorkTemplate, playbookTemplates: PlaybookTemplateType[]) => { export const getContentCount = (template: WorkTemplate, playbookTemplates: PlaybookTemplateType[], channelId: string) => {
const res = { const res = {
playbooks: 0, playbooks: 0,
boards: 0, boards: 0,
channelId,
}; };
for (const item of template.content) { for (const item of template.content) {
if (item.playbook) { if (item.playbook) {

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

@@ -47,7 +47,7 @@ export function clearWorkTemplates(): ActionFunc {
} }
// stores the linked product information in the state so it can be used to show the tourtip // stores the linked product information in the state so it can be used to show the tourtip
export function onExecuteSuccess(data: Record<string, number>): ActionFunc { export function onExecuteSuccess(data: Record<string, string | number>): ActionFunc {
return async (dispatch) => { return async (dispatch) => {
dispatch({type: WorkTemplatesType.EXECUTE_SUCCESS, data}); dispatch({type: WorkTemplatesType.EXECUTE_SUCCESS, data});
return []; return [];

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

@@ -7,7 +7,7 @@ export type WorkTemplatesState = {
categories: Category[]; categories: Category[];
templatesInCategory: Record<string, WorkTemplate[]>; templatesInCategory: Record<string, WorkTemplate[]>;
playbookTemplates: PlaybookTemplateType[]; playbookTemplates: PlaybookTemplateType[];
linkedProducts: Record<string, number>; linkedProducts: Record<string, string | number>;
} }
export interface PlaybookTemplateType { export interface PlaybookTemplateType {