/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ import React, { useState, useCallback, useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs"; // eslint-disable-next-line no-shadow import { CSSTransition } from "react-transition-group"; function SectionsMgmtPanel({ exitEventFired }) { const [showPanel, setShowPanel] = useState(false); // State management with useState const { sectionPersonalization } = useSelector( state => state.DiscoveryStream ); const layoutComponents = useSelector( state => state.DiscoveryStream.layout[0].components ); const sections = useSelector(state => state.DiscoveryStream.feeds.data); const dispatch = useDispatch(); // TODO: Wrap sectionsFeedName -> sectionsList logic in try...catch? let sectionsFeedName; const cardGridEntry = layoutComponents.find(item => item.type === "CardGrid"); if (cardGridEntry) { sectionsFeedName = cardGridEntry.feed.url; } let sectionsList; if (sectionsFeedName) { sectionsList = sections[sectionsFeedName].data.sections; } const [sectionsState, setSectionState] = useState(sectionPersonalization); // State management with useState let followedSectionsData = sectionsList.filter( item => sectionsState[item.sectionKey]?.isFollowed ); let blockedSectionsData = sectionsList.filter( item => sectionsState[item.sectionKey]?.isBlocked ); function updateCachedData() { // Reset cached followed/blocked list data while panel is open setSectionState(sectionPersonalization); followedSectionsData = sectionsList.filter( item => sectionsState[item.sectionKey]?.isFollowed ); blockedSectionsData = sectionsList.filter( item => sectionsState[item.sectionKey]?.isBlocked ); } const onFollowClick = useCallback( (sectionKey, receivedRank) => { dispatch( ac.AlsoToMain({ type: at.SECTION_PERSONALIZATION_SET, data: { ...sectionPersonalization, [sectionKey]: { isFollowed: true, isBlocked: false, followedAt: new Date().toISOString(), }, }, }) ); // Telemetry Event Dispatch dispatch( ac.OnlyToMain({ type: "FOLLOW_SECTION", data: { section: sectionKey, section_position: receivedRank, event_source: "CUSTOMIZE_PANEL", }, }) ); }, [dispatch, sectionPersonalization] ); const onBlockClick = useCallback( (sectionKey, receivedRank) => { dispatch( ac.AlsoToMain({ type: at.SECTION_PERSONALIZATION_SET, data: { ...sectionPersonalization, [sectionKey]: { isFollowed: false, isBlocked: true, }, }, }) ); // Telemetry Event Dispatch dispatch( ac.OnlyToMain({ type: "BLOCK_SECTION", data: { section: sectionKey, section_position: receivedRank, event_source: "CUSTOMIZE_PANEL", }, }) ); }, [dispatch, sectionPersonalization] ); const onUnblockClick = useCallback( (sectionKey, receivedRank) => { const updatedSectionData = { ...sectionPersonalization }; delete updatedSectionData[sectionKey]; dispatch( ac.AlsoToMain({ type: at.SECTION_PERSONALIZATION_SET, data: updatedSectionData, }) ); // Telemetry Event Dispatch dispatch( ac.OnlyToMain({ type: "UNBLOCK_SECTION", data: { section: sectionKey, section_position: receivedRank, event_source: "CUSTOMIZE_PANEL", }, }) ); }, [dispatch, sectionPersonalization] ); const onUnfollowClick = useCallback( (sectionKey, receivedRank) => { const updatedSectionData = { ...sectionPersonalization }; delete updatedSectionData[sectionKey]; dispatch( ac.AlsoToMain({ type: at.SECTION_PERSONALIZATION_SET, data: updatedSectionData, }) ); // Telemetry Event Dispatch dispatch( ac.OnlyToMain({ type: "UNFOLLOW_SECTION", data: { section: sectionKey, section_position: receivedRank, event_source: "CUSTOMIZE_PANEL", }, }) ); }, [dispatch, sectionPersonalization] ); // Close followed/blocked topic subpanel when parent menu is closed useEffect(() => { if (exitEventFired) { setShowPanel(false); } }, [exitEventFired]); const togglePanel = () => { setShowPanel(prevShowPanel => !prevShowPanel); // Fire when the panel is open if (!showPanel) { updateCachedData(); } }; const followedSectionsList = followedSectionsData.map( ({ sectionKey, title, receivedRank }) => { const following = sectionPersonalization[sectionKey]?.isFollowed; return (
  • following ? onUnfollowClick(sectionKey, receivedRank) : onFollowClick(sectionKey, receivedRank) } type={"default"} index={receivedRank} section={sectionKey} id={`follow-topic-${sectionKey}`} >
  • ); } ); const blockedSectionsList = blockedSectionsData.map( ({ sectionKey, title, receivedRank }) => { const blocked = sectionPersonalization[sectionKey]?.isBlocked; return (
  • blocked ? onUnblockClick(sectionKey, receivedRank) : onBlockClick(sectionKey, receivedRank) } type="default" index={receivedRank} section={sectionKey} id={`blocked-topic-${sectionKey}`} >
  • ); } ); return (

    {followedSectionsData.length ? (
      {followedSectionsList}
    ) : ( )}

    {blockedSectionsData.length ? (
      {blockedSectionsList}
    ) : ( )}
    ); } export { SectionsMgmtPanel };