From 887ba95cc1496b29b164f488c83df810a5907519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Andr=C3=A9s=20V=C3=A9lez=20Vidal?= Date: Mon, 26 Jun 2023 14:13:14 +0200 Subject: [PATCH] MM-53088 - remove autoshow linked board (#23783) Co-authored-by: Mattermost Build --- .../support/server/default_config.ts | 1 - .../visual/channels/intro_channel.spec.ts | 8 +- server/channels/app/team.go | 139 ------------------ server/i18n/en.json | 24 --- server/public/model/feature_flags.go | 4 - server/public/model/preference.go | 3 - .../onboarding_tasklist.tsx | 27 +--- .../components/onboarding_tasks/constants.ts | 3 - webapp/channels/src/i18n/en.json | 2 - .../mattermost-redux/src/actions/boards.ts | 17 --- .../src/constants/preferences.ts | 1 - .../src/selectors/entities/preferences.ts | 4 - .../auto_show_linked_board_tourtip.tsx | 96 ------------ .../src/plugins/rhs_plugin/rhs_plugin.tsx | 5 - webapp/channels/src/selectors/plugins.ts | 13 +- 15 files changed, 6 insertions(+), 341 deletions(-) delete mode 100644 webapp/channels/src/plugins/rhs_plugin/auto_show_linked_board_tourtip.tsx diff --git a/e2e-tests/playwright/support/server/default_config.ts b/e2e-tests/playwright/support/server/default_config.ts index 7ec72cfb7b..6f2252317c 100644 --- a/e2e-tests/playwright/support/server/default_config.ts +++ b/e2e-tests/playwright/support/server/default_config.ts @@ -675,7 +675,6 @@ const defaultServerConfig: AdminConfig = { WysiwygEditor: false, PeopleProduct: false, ReduceOnBoardingTaskList: false, - OnboardingAutoShowLinkedBoard: false, ThreadsEverywhere: false, GlobalDrafts: true, OnboardingTourTips: true, diff --git a/e2e-tests/playwright/tests/visual/channels/intro_channel.spec.ts b/e2e-tests/playwright/tests/visual/channels/intro_channel.spec.ts index 86fd10ef54..86ebf18acc 100644 --- a/e2e-tests/playwright/tests/visual/channels/intro_channel.spec.ts +++ b/e2e-tests/playwright/tests/visual/channels/intro_channel.spec.ts @@ -2,6 +2,7 @@ // See LICENSE.txt for license information. import {expect, test} from '@e2e-support/test_fixture'; +import {duration, wait} from '@e2e-support/util'; test('Intro to channel as regular user', async ({pw, pages, browserName, viewport}, testInfo) => { // Create and sign in a new user @@ -16,10 +17,9 @@ test('Intro to channel as regular user', async ({pw, pages, browserName, viewpor await channelsPage.toBeVisible(); // Wait for Boards' bot image to be loaded - // await pw.shouldHaveFeatureFlag('OnboardingAutoShowLinkedBoard', true); - // const boardsWelcomePost = await channelsPage.getFirstPost(); - // await expect(await boardsWelcomePost.getProfileImage('boards')).toBeVisible(); - // await wait(duration.one_sec); + const boardsWelcomePost = await channelsPage.getFirstPost(); + await expect(await boardsWelcomePost.getProfileImage('boards')).toBeVisible(); + await wait(duration.one_sec); // Wait for Playbooks icon to be loaded in App bar, except in iphone if (!pw.isSmallScreen()) { diff --git a/server/channels/app/team.go b/server/channels/app/team.go index c1940208f1..971b10931a 100644 --- a/server/channels/app/team.go +++ b/server/channels/app/team.go @@ -6,7 +6,6 @@ package app import ( "bytes" "context" - "crypto/md5" "encoding/json" "errors" "fmt" @@ -18,8 +17,6 @@ import ( "sort" "strings" - fb_model "github.com/mattermost/mattermost/server/v8/boards/model" - "github.com/mattermost/mattermost/server/public/model" "github.com/mattermost/mattermost/server/public/plugin" "github.com/mattermost/mattermost/server/public/shared/i18n" @@ -163,128 +160,6 @@ func (a *App) SoftDeleteAllTeamsExcept(teamID string) *model.AppError { return nil } -// MM-48246 A/B test show linked boards -const preferenceName = "linked_board_created" - -func (a *App) shouldCreateOnboardingLinkedBoard(c request.CTX, teamId string) bool { - ffEnabled := a.Config().FeatureFlags.OnboardingAutoShowLinkedBoard - if !ffEnabled { - return false - } - - hasBoard, err := a.HasBoardProduct() - if err != nil { - a.Log().Error("error checking the existence of boards product: ", mlog.Err(err)) - return false - } - - if !hasBoard { - a.Log().Warn("board product not found") - return false - } - - data, sysValErr := a.Srv().Store().System().GetByName(model.PreferenceOnboarding + "_" + preferenceName) - if sysValErr != nil { - var nfErr *store.ErrNotFound - if errors.As(sysValErr, &nfErr) { // if no board has been registered, it can create one for this team - return true - } - a.Log().Error("cannot get the system values", mlog.Err(sysValErr)) - return false - } - - // get the team list and check if the team value has been already stored, if so, no need to create a board in town square in that team - teamsList := strings.Split(data.Value, ",") - for _, team := range teamsList { - if team == teamId { - return false - } - } - - return true -} - -func (a *App) createOnboardingLinkedBoard(c request.CTX, teamId string) (*fb_model.Board, *model.AppError) { - const defaultTemplatesTeam = "0" - - // see https://github.com/mattermost/mattermost/server/v8/boards/blob/main/server/services/store/sqlstore/board.go#L302 - // and https://github.com/mattermost/mattermost-server/pull/22201#discussion_r1099536430 - const defaultTemplateTitle = "Welcome to Boards!" - welcomeToBoardsTemplateId := fmt.Sprintf("%x", md5.Sum([]byte(defaultTemplateTitle))) - userId := c.Session().UserId - - boardServiceItf, ok := a.Srv().services[product.BoardsKey] - if !ok { - return nil, model.NewAppError("CreateBoard", "app.team.create_onboarding_linked_board.product_key_not_found", nil, "", http.StatusBadRequest) - } - - boardService, typeOk := boardServiceItf.(product.BoardsService) - if !typeOk { - // boardServiceItf is NOT of type product.BoardsService - return nil, model.NewAppError("CreateBoard", "app.team.create_onboarding_linked_board.itf_not_of_type", nil, "", http.StatusBadRequest) - } - - templates, err := boardService.GetTemplates(defaultTemplatesTeam, userId) - if err != nil { - return nil, model.NewAppError("CreateBoard", "app.team.create_onboarding_linked_board.error_getting_templates", nil, "", http.StatusBadRequest).Wrap(err) - } - - channel, appErr := a.GetChannelByName(c, model.DefaultChannelName, teamId, false) - if appErr != nil { - return nil, appErr - } - - var template *fb_model.Board - for _, t := range templates { - v := t.Properties["trackingTemplateId"] - if v == welcomeToBoardsTemplateId { - template = t - break - } - } - if template == nil && len(templates) > 0 { - template = templates[0] - } - - // Duplicate board From template - boardsAndBlocks, _, err := boardService.DuplicateBoard(template.ID, userId, teamId, false) - if err != nil { - return nil, model.NewAppError("CreateBoard", "app.team.create_onboarding_linked_board.error_duplicating_board", nil, "", http.StatusBadRequest).Wrap(err) - } - if len(boardsAndBlocks.Boards) != 1 { - return nil, model.NewAppError("CreateBoard", "app.team.create_onboarding_linked_board.error_no_board", nil, "", http.StatusBadRequest).Wrap(err) - } - - // link the board with the channel - patchedBoard, err := boardService.PatchBoard(&fb_model.BoardPatch{ - ChannelID: &channel.Id, - }, boardsAndBlocks.Boards[0].ID, userId) - if err != nil && patchedBoard == nil { - return nil, model.NewAppError("CreateBoard", "app.team.create_onboarding_linked_board.error_patching_board", nil, "", http.StatusBadRequest).Wrap(err) - } - - // Save in the system preferences that the board was already created once per team - data, sysValErr := a.Srv().Store().System().GetByName(model.PreferenceOnboarding + "_" + preferenceName) - if sysValErr != nil { - c.Logger().Error("cannot get the system preferences", mlog.Err(sysValErr)) - } - - teamsList := teamId - // if data is not nil, data.Value contains the list of teams where the A/B test has alredy created a channel for town square - if data != nil { - teamsList = data.Value + "," + teamId - } - - if err := a.Srv().Store().System().SaveOrUpdate(&model.System{ - Name: model.PreferenceOnboarding + "_" + preferenceName, - Value: teamsList, - }); err != nil { - c.Logger().Warn("encountered error saving user preferences", mlog.Err(err)) - } - - return patchedBoard, nil -} - func (a *App) CreateTeam(c request.CTX, team *model.Team) (*model.Team, *model.AppError) { rteam, err := a.ch.srv.teamService.CreateTeam(team) if err != nil { @@ -316,20 +191,6 @@ func (a *App) CreateTeam(c request.CTX, team *model.Team) (*model.Team, *model.A } } - // MM-48246 A/B test show linked boards. Create a welcome to boards linked board per user - if a.shouldCreateOnboardingLinkedBoard(c, team.Id) { - board, aErr := a.createOnboardingLinkedBoard(c, team.Id) - if aErr != nil || board == nil { - a.Log().Warn("Error creating the linked board, only team created", mlog.Err(err)) - return rteam, nil - } - - if board.ID != "" { - logInfo := fmt.Sprintf("Board created with id %s and associated to channel %s in team %s", board.ID, board.ChannelID, team.Id) - a.Log().Info(logInfo, mlog.Err(err)) - } - } - return rteam, nil } diff --git a/server/i18n/en.json b/server/i18n/en.json index a3f89f57de..5419a092a8 100644 --- a/server/i18n/en.json +++ b/server/i18n/en.json @@ -6523,30 +6523,6 @@ "id": "app.team.clear_cache.app_error", "translation": "Error clearing team member cache" }, - { - "id": "app.team.create_onboarding_linked_board.error_duplicating_board", - "translation": "error duplicating board" - }, - { - "id": "app.team.create_onboarding_linked_board.error_getting_templates", - "translation": "error getting boards templates" - }, - { - "id": "app.team.create_onboarding_linked_board.error_no_board", - "translation": "error no board created" - }, - { - "id": "app.team.create_onboarding_linked_board.error_patching_board", - "translation": "error while patching board" - }, - { - "id": "app.team.create_onboarding_linked_board.itf_not_of_type", - "translation": "interface not of expected type" - }, - { - "id": "app.team.create_onboarding_linked_board.product_key_not_found", - "translation": "product key not found" - }, { "id": "app.team.get.find.app_error", "translation": "Unable to find the existing team." diff --git a/server/public/model/feature_flags.go b/server/public/model/feature_flags.go index 992184cadd..7f0861b500 100644 --- a/server/public/model/feature_flags.go +++ b/server/public/model/feature_flags.go @@ -58,9 +58,6 @@ type FeatureFlags struct { // A/B Test on reduced onboarding task list item ReduceOnBoardingTaskList bool - // A/B Test to control when to show onboarding linked board - OnboardingAutoShowLinkedBoard bool - ThreadsEverywhere bool GlobalDrafts bool @@ -94,7 +91,6 @@ func (f *FeatureFlags) SetDefaults() { f.GlobalDrafts = true f.DeprecateCloudFree = false f.WysiwygEditor = false - f.OnboardingAutoShowLinkedBoard = false f.OnboardingTourTips = true f.CloudReverseTrial = false } diff --git a/server/public/model/preference.go b/server/public/model/preference.go index df149179e2..98e0a08c5a 100644 --- a/server/public/model/preference.go +++ b/server/public/model/preference.go @@ -33,9 +33,6 @@ const ( PreferenceRecommendedNextSteps = "recommended_next_steps" PreferenceNameInsights = "insights_tutorial_state" - // initial onboarding preferences - PreferenceOnboarding = "onboarding" - PreferenceCategoryTheme = "theme" // the name for theme props is the team id diff --git a/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist.tsx b/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist.tsx index 9680140c6b..39c5bc083f 100644 --- a/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist.tsx +++ b/webapp/channels/src/components/onboarding_tasklist/onboarding_tasklist.tsx @@ -8,7 +8,6 @@ import styled, {css} from 'styled-components'; import {FormattedMessage} from 'react-intl'; import {getShowTaskListBool} from 'selectors/onboarding'; -import {shouldShowAutoLinkedBoard} from 'selectors/plugins'; import { getBool, @@ -32,11 +31,10 @@ import CompassThemeProvider from 'components/compass_theme_provider/compass_them import {openModal} from 'actions/views/modals'; import {GlobalState} from 'types/store'; -import {showRHSPlugin} from 'actions/views/rhs'; import {trackEvent} from 'actions/telemetry_actions'; import checklistImg from 'images/onboarding-checklist.svg'; -import {Preferences, RecommendedNextStepsLegacy, suitePluginIds} from 'utils/constants'; +import {Preferences, RecommendedNextStepsLegacy} from 'utils/constants'; import {TaskListPopover} from './onboarding_tasklist_popover'; import {Task} from './onboarding_tasklist_task'; @@ -187,24 +185,11 @@ const OnBoardingTaskList = (): JSX.Element | null => { const [showTaskList, firstTimeOnboarding] = useSelector(getShowTaskListBool); const theme = useSelector(getTheme); - // a/b test auto show linked boards - const autoShowLinkedBoard = useSelector((state: GlobalState) => shouldShowAutoLinkedBoard(state)); - const pluginsComponentsList = useSelector((state: GlobalState) => state.plugins.components); - const startTask = (taskName: string) => { toggleTaskList(); handleTaskTrigger(taskName); }; - const findRhsPluginId = (pluginId: string) => { - const rhsPlugins = pluginsComponentsList.RightHandSidebarComponent; - - if (rhsPlugins.length) { - return rhsPlugins.find((plugin) => plugin.pluginId === pluginId)?.id; - } - return null; - }; - const initOnboardingPrefs = async () => { // save to preferences the show/open-task-list to true // also save the recomendedNextSteps-hide to true to avoid asserting to true @@ -288,16 +273,6 @@ const OnBoardingTaskList = (): JSX.Element | null => { }]; dispatch(savePreferences(currentUserId, preferences)); trackEvent(OnboardingTaskCategory, open ? OnboardingTaskList.ONBOARDING_TASK_LIST_CLOSE : OnboardingTaskList.ONBOARDING_TASK_LIST_OPEN); - - // check if the AB test FF is set and also check that the linkedBoard has only been shown once, then open the RHS - if (autoShowLinkedBoard && open) { - const boardsId = findRhsPluginId(suitePluginIds.boards); - if (!boardsId) { - return; - } - - dispatch(showRHSPlugin(boardsId)); - } }, [open, currentUserId]); const openVideoModal = useCallback(() => { diff --git a/webapp/channels/src/components/onboarding_tasks/constants.ts b/webapp/channels/src/components/onboarding_tasks/constants.ts index 2b19b6d98f..c5d1836e56 100644 --- a/webapp/channels/src/components/onboarding_tasks/constants.ts +++ b/webapp/channels/src/components/onboarding_tasks/constants.ts @@ -24,9 +24,6 @@ export const OnboardingTaskList = { ONBOARDING_TASK_LIST_CLOSE: 'onboarding_task_list_close', ONBOARDING_VIDEO_MODAL: 'onboarding_video_modal', DECLINED_ONBOARDING_TASK_LIST: 'declined_onboarding_task_list', - - // auto show channel linked boards A/B test - ONBOARDING_LINKED_BOARD_AUTO_SHOWN: 'linked_board_auto_shown', }; export const GenericTaskSteps = { diff --git a/webapp/channels/src/i18n/en.json b/webapp/channels/src/i18n/en.json index aeb24bd655..3cfcbccf1e 100644 --- a/webapp/channels/src/i18n/en.json +++ b/webapp/channels/src/i18n/en.json @@ -2797,8 +2797,6 @@ "authorize.app": "The app **{appName}** would like the ability to access and modify your basic information.", "authorize.deny": "Deny", "authorize.title": "Authorize **{appName}** to Connect to Your **Mattermost** User Account", - "autoShowLinkedBoard.tutorialTip.description": "Manage tasks, plan sprints, conduct standup with the help of kanban boards and tables.", - "autoShowLinkedBoard.tutorialTip.title": "Link kanban boards to channels", "avatars.overflowUnnamedOnly": "{overflowUnnamedCount, plural, =1 {one other} other {# others}}", "avatars.overflowUsers": "{overflowUnnamedCount, plural, =0 {{names}} =1 {{names} and one other} other {{names} and # others}}", "backstage_list.search": "Search", diff --git a/webapp/channels/src/packages/mattermost-redux/src/actions/boards.ts b/webapp/channels/src/packages/mattermost-redux/src/actions/boards.ts index 99435ff09f..60dd41a415 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/actions/boards.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/actions/boards.ts @@ -8,8 +8,6 @@ import {PreferenceType} from '@mattermost/types/preferences'; import {Preferences} from '../constants'; -import {OnboardingTaskCategory, OnboardingTaskList} from 'components/onboarding_tasks'; - import {savePreferences} from './preferences'; export function setNewChannelWithBoardPreference(initializationState: Record): ActionFunc { @@ -26,18 +24,3 @@ export function setNewChannelWithBoardPreference(initializationState: Record { - const state = getState(); - const currentUserId = getCurrentUserId(state); - const preference: PreferenceType = { - category: OnboardingTaskCategory, - user_id: currentUserId, - name: OnboardingTaskList.ONBOARDING_LINKED_BOARD_AUTO_SHOWN, - value: 'true', - }; - await dispatch(savePreferences(currentUserId, [preference])); - return {data: true}; - }; -} diff --git a/webapp/channels/src/packages/mattermost-redux/src/constants/preferences.ts b/webapp/channels/src/packages/mattermost-redux/src/constants/preferences.ts index 23266483e7..b403b90af2 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/constants/preferences.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/constants/preferences.ts @@ -76,7 +76,6 @@ const Preferences = { NEW_CHANNEL_WITH_BOARD_TOUR_SHOWED: 'channel_with_board_tip_showed', - AUTO_LINKED_BOARD: 'auto_linked_board', CATEGORY_ONBOARDING: 'category_onboarding', CATEGORY_DRAFTS: 'drafts', diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/preferences.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/preferences.ts index 55152b0ce7..015a900d2a 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/preferences.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/preferences.ts @@ -291,10 +291,6 @@ export function getVisibleDmGmLimit(state: GlobalState) { return getInt(state, Preferences.CATEGORY_SIDEBAR_SETTINGS, Preferences.LIMIT_VISIBLE_DMS_GMS, defaultLimit); } -export function autoShowLinkedBoardFFEnabled(state: GlobalState): boolean { - return getFeatureFlagValue(state, 'OnboardingAutoShowLinkedBoard') === 'true'; -} - export function onboardingTourTipsEnabled(state: GlobalState): boolean { return getFeatureFlagValue(state, 'OnboardingTourTips') === 'true'; } diff --git a/webapp/channels/src/plugins/rhs_plugin/auto_show_linked_board_tourtip.tsx b/webapp/channels/src/plugins/rhs_plugin/auto_show_linked_board_tourtip.tsx deleted file mode 100644 index c6852f02a3..0000000000 --- a/webapp/channels/src/plugins/rhs_plugin/auto_show_linked_board_tourtip.tsx +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React, {useCallback} from 'react'; -import {FormattedMessage} from 'react-intl'; -import {useDispatch, useSelector} from 'react-redux'; - -import {Placement} from 'tippy.js'; - -import {setAutoShowLinkedBoardPreference} from 'mattermost-redux/actions/boards'; - -import {TourTip} from '@mattermost/components'; -import {shouldShowAutoLinkedBoard} from 'selectors/plugins'; -import {suitePluginIds} from 'utils/constants'; -import {getPluggableId} from 'selectors/rhs'; -import {PluginComponent} from 'types/store/plugins'; -import {GlobalState} from 'types/store'; - -type Props = { - pulsatingDotPlacement?: Omit; -} - -const AutoShowLinkedBoardTourTip = ({ - pulsatingDotPlacement = 'auto', -}: Props): JSX.Element | null => { - const dispatch = useDispatch(); - - const rhsPlugins: PluginComponent[] = useSelector((state: GlobalState) => state.plugins.components.RightHandSidebarComponent); - const pluggableId = useSelector(getPluggableId); - const pluginComponent = rhsPlugins.find((element: PluginComponent) => element.id === pluggableId); - - const isBoards = pluginComponent && (pluginComponent.pluginId === suitePluginIds.focalboard || pluginComponent.pluginId === suitePluginIds.boards); - const showAutoLinkedBoard = useSelector(shouldShowAutoLinkedBoard); - const showAutoLinkedBoardTourTip = isBoards && showAutoLinkedBoard; - - const title = ( - - ); - - const screen = ( - - ); - - const handleDismiss = useCallback((e: React.MouseEvent) => { - e.stopPropagation(); - dispatch(setAutoShowLinkedBoardPreference()); - }, []); - - const handleOpen = useCallback((e: React.MouseEvent) => { - e.stopPropagation(); - e.preventDefault(); - dispatch(setAutoShowLinkedBoardPreference()); - }, []); - - const nextBtn = ( - - ); - - if (!showAutoLinkedBoardTourTip) { - return null; - } - - return ( - - ); -}; - -export default AutoShowLinkedBoardTourTip; diff --git a/webapp/channels/src/plugins/rhs_plugin/rhs_plugin.tsx b/webapp/channels/src/plugins/rhs_plugin/rhs_plugin.tsx index 850643c6d6..80408e8ec4 100644 --- a/webapp/channels/src/plugins/rhs_plugin/rhs_plugin.tsx +++ b/webapp/channels/src/plugins/rhs_plugin/rhs_plugin.tsx @@ -7,8 +7,6 @@ import SearchResultsHeader from 'components/search_results_header'; import Pluggable from 'plugins/pluggable'; -import AutoShowLinkedBoardTourTip from './auto_show_linked_board_tourtip'; - export type Props = { showPluggable: boolean; pluggableId: string; @@ -17,15 +15,12 @@ export type Props = { export default class RhsPlugin extends React.PureComponent { render() { - const autoLinkedBoardTourTip = (); - return (
- {autoLinkedBoardTourTip} {this.props.title} { diff --git a/webapp/channels/src/selectors/plugins.ts b/webapp/channels/src/selectors/plugins.ts index b4f4ab3781..9693be5b78 100644 --- a/webapp/channels/src/selectors/plugins.ts +++ b/webapp/channels/src/selectors/plugins.ts @@ -5,11 +5,9 @@ import {createSelector} from 'mattermost-redux/selectors/create_selector'; import {appBarEnabled, getAppBarAppBindings} from 'mattermost-redux/selectors/entities/apps'; import {createShallowSelector} from 'mattermost-redux/utils/helpers'; -import {autoShowLinkedBoardFFEnabled, get, getBool} from 'mattermost-redux/selectors/entities/preferences'; +import {get} from 'mattermost-redux/selectors/entities/preferences'; import {Preferences} from 'mattermost-redux/constants'; -import {OnboardingTaskCategory, OnboardingTaskList} from 'components/onboarding_tasks'; - import {GlobalState} from 'types/store'; import {AppBinding} from '@mattermost/types/apps'; @@ -104,12 +102,3 @@ export function showNewChannelWithBoardPulsatingDot(state: GlobalState): boolean const showPulsatingDot = pulsatingDotState !== '' && JSON.parse(pulsatingDotState)[Preferences.NEW_CHANNEL_WITH_BOARD_TOUR_SHOWED] === false; return showPulsatingDot; } - -export const shouldShowAutoLinkedBoard = createSelector( - 'shouldShowAutoLinkedBoard', - (state: GlobalState) => getBool(state, OnboardingTaskCategory, OnboardingTaskList.ONBOARDING_LINKED_BOARD_AUTO_SHOWN), - (state: GlobalState) => autoShowLinkedBoardFFEnabled(state), - (showAutoLinkedBoardPref: boolean, showAutoLinkedBoardFFEnabled: boolean) => { - return !showAutoLinkedBoardPref && showAutoLinkedBoardFFEnabled; - }, -);