CloudLibrary
1 year ago
Settings
1 year ago
StarterSites
3 years ago
App.js
2 years ago
Card.js
3 years ago
CategoriesTabs.js
3 years ago
CategorySelector.js
2 years ago
CustomTooltip.js
3 years ago
DocNotice.js
2 years ago
EditorSelector.js
2 years ago
EditorTabs.js
4 years ago
Header.js
2 years ago
Icon.js
2 years ago
ImportModal.js
1 year ago
ImportModalError.js
2 years ago
ImportModalMock.js
4 years ago
ImportModalNote.js
4 years ago
ImportStepper.js
1 year ago
InstallModal.js
1 year ago
License.js
2 years ago
LicensePanelContext.js
3 years ago
Loading.js
4 years ago
Main.js
1 year ago
Migration.js
4 years ago
NewTCNotice.js
1 year ago
Notification.js
4 years ago
OnboardingContent.js
4 years ago
PreviewFrame.js
3 years ago
Search.js
2 years ago
StarterSiteCard.js
3 years ago
Header.js
217 lines
| 1 | /* global tiobDash, localStorage */ |
| 2 | import { withSelect, withDispatch } from '@wordpress/data'; |
| 3 | import { useEffect, useState, useContext } from '@wordpress/element'; |
| 4 | import { Button, Icon } from '@wordpress/components'; |
| 5 | import { compose } from '@wordpress/compose'; |
| 6 | import { update, cloud, close } from '@wordpress/icons'; |
| 7 | import { __ } from '@wordpress/i18n'; |
| 8 | |
| 9 | import Logo, { NeveIcon } from './Icon'; |
| 10 | import classnames from 'classnames'; |
| 11 | import { v4 as uuidv4 } from 'uuid'; |
| 12 | import { addUrlHash, getTabHash } from '../utils/common'; |
| 13 | import License from './License'; |
| 14 | import { LicensePanelContext } from './LicensePanelContext'; |
| 15 | |
| 16 | const TabNavigation = ( { |
| 17 | setCurrentTab, |
| 18 | currentTab, |
| 19 | isFetching, |
| 20 | license, |
| 21 | } ) => { |
| 22 | const buttons = {}; |
| 23 | |
| 24 | if ( ! tiobDash.hideStarterSites ) { |
| 25 | buttons.starterSites = __( 'Starter Sites', 'templates-patterns-collection' ); |
| 26 | buttons.pageTemplates = __( 'Page Templates', 'templates-patterns-collection' ); |
| 27 | } |
| 28 | |
| 29 | if ( ! tiobDash.hideMyLibrary ) { |
| 30 | buttons.library = __( 'My Library', 'templates-patterns-collection' ); |
| 31 | } |
| 32 | buttons.settings = __( 'Settings', 'templates-patterns-collection' ); |
| 33 | |
| 34 | const [ isSyncing, setSyncing ] = useState( false ); |
| 35 | const { isLicenseOpen, setLicenseOpen } = useContext( LicensePanelContext ); |
| 36 | const isValid = 'valid' === license?.valid || 'valid' === license?.license; |
| 37 | |
| 38 | const sync = () => { |
| 39 | setSyncing( true ); |
| 40 | localStorage.setItem( 'tpcCacheBuster', uuidv4() ); |
| 41 | const nextTab = currentTab; |
| 42 | setCurrentTab( null ); |
| 43 | setTimeout( () => { |
| 44 | setCurrentTab( nextTab ); |
| 45 | setSyncing( false ); |
| 46 | }, 100 ); |
| 47 | }; |
| 48 | |
| 49 | const onHashChanged = () => { |
| 50 | const hash = getTabHash( buttons ); |
| 51 | if ( null === hash ) { |
| 52 | return; |
| 53 | } |
| 54 | |
| 55 | let menu = document.getElementById( 'toplevel_page_neve-welcome' ); |
| 56 | if ( ! menu ) { |
| 57 | menu = document.getElementById( 'menu-appearance' ); |
| 58 | } |
| 59 | const tiobMenu = document.getElementById( 'toplevel_page_tiob-plugin' ); |
| 60 | |
| 61 | const lookupHashList = [ '#pageTemplates', '#settings' ]; |
| 62 | const itemHashList = lookupHashList.map( ( itemHash ) => { |
| 63 | return { |
| 64 | hash: itemHash, |
| 65 | item: menu.querySelector( `a[href="themes.php?page=tiob-starter-sites${ itemHash }"]` ) |
| 66 | || menu.querySelector( `a[href="admin.php?page=tiob-starter-sites${ itemHash }"]` ) |
| 67 | || tiobMenu.querySelector( `a[href="admin.php?page=tiob-plugin${ itemHash }"]` ), |
| 68 | } |
| 69 | } ); |
| 70 | |
| 71 | const hasAllItemsDefined = itemHashList.reduce( ( acc, link ) => { return ( link?.item ) ? ++acc : acc }, 0 ) === itemHashList.length; |
| 72 | |
| 73 | // The logic here is to ensure the sidebar menu items appear as active when the user navigates to a page via the URL hash (through react). |
| 74 | if ( hasAllItemsDefined ) { |
| 75 | for ( let i in itemHashList ) { |
| 76 | const link = itemHashList[ i ]; |
| 77 | if ( link.hash.replace('#', '') === hash ) { |
| 78 | let siblings = link.item.parentElement.parentElement.children; |
| 79 | for ( let child of siblings ) { |
| 80 | child.classList.remove( 'current' ); |
| 81 | } |
| 82 | link.item.parentElement.classList.add( 'current' ); |
| 83 | } |
| 84 | } |
| 85 | } |
| 86 | setCurrentTab( hash ); |
| 87 | }; |
| 88 | |
| 89 | useEffect( () => { |
| 90 | onHashChanged(); |
| 91 | window.addEventListener( 'hashchange', onHashChanged ); |
| 92 | }, [] ); |
| 93 | |
| 94 | return ( |
| 95 | <div className="header-nav"> |
| 96 | { currentTab !== 'starterSites' && currentTab !== 'settings' && ! tiobDash.hideMyLibrary && ( |
| 97 | <Button |
| 98 | icon={ update } |
| 99 | onClick={ sync } |
| 100 | label={ __( |
| 101 | 'Re-sync Library', |
| 102 | 'templates-patterns-collection' |
| 103 | ) } |
| 104 | className={ classnames( 'is-icon-btn', { |
| 105 | 'is-loading': isSyncing, |
| 106 | } ) } |
| 107 | disabled={ isFetching || isSyncing } |
| 108 | data-content={ __( |
| 109 | 'Sync', |
| 110 | 'templates-patterns-collection' |
| 111 | ) } |
| 112 | /> |
| 113 | ) } |
| 114 | </div> |
| 115 | ); |
| 116 | }; |
| 117 | |
| 118 | const BrandTitle = ( currentTab ) => { |
| 119 | |
| 120 | let showNeveIcon = false; |
| 121 | if ( [ 'starterSites', 'pageTemplates' ].includes( currentTab.currentTab ) && ! tiobDash.brandedTheme ) { |
| 122 | showNeveIcon = true; |
| 123 | } |
| 124 | |
| 125 | let title = __( 'Templates Cloud', 'templates-patterns-collection' ); |
| 126 | switch ( currentTab.currentTab ) { |
| 127 | case 'starterSites': |
| 128 | title = __( 'Starter Sites', 'templates-patterns-collection' ); |
| 129 | break; |
| 130 | case 'pageTemplates': |
| 131 | title = __( 'Page Templates', 'templates-patterns-collection' ); |
| 132 | break; |
| 133 | case 'library': |
| 134 | title = __( 'My Library', 'templates-patterns-collection' ); |
| 135 | break; |
| 136 | case 'settings': |
| 137 | title = __( 'Settings', 'templates-patterns-collection' ); |
| 138 | break; |
| 139 | } |
| 140 | |
| 141 | return ( |
| 142 | <h2> |
| 143 | { showNeveIcon && ( |
| 144 | <Icon icon={ NeveIcon } /> |
| 145 | ) } |
| 146 | { ! showNeveIcon && ( |
| 147 | <Icon icon={ Logo } /> |
| 148 | ) } |
| 149 | <span> |
| 150 | { title } |
| 151 | </span> |
| 152 | </h2> |
| 153 | ); |
| 154 | }; |
| 155 | |
| 156 | const Header = ( { |
| 157 | isOnboarding, |
| 158 | cancelOnboarding, |
| 159 | setCurrentTab, |
| 160 | currentTab, |
| 161 | license, |
| 162 | } ) => { |
| 163 | return ( |
| 164 | <div className="ob-head"> |
| 165 | { ! isOnboarding && ( |
| 166 | <> |
| 167 | <div className="header-container"> |
| 168 | <BrandTitle currentTab={ currentTab } /> |
| 169 | <TabNavigation |
| 170 | setCurrentTab={ setCurrentTab } |
| 171 | currentTab={ currentTab } |
| 172 | license={ license } |
| 173 | /> |
| 174 | </div> |
| 175 | </> |
| 176 | ) } |
| 177 | { isOnboarding && ( |
| 178 | <Button |
| 179 | className="close-onboarding" |
| 180 | isLink |
| 181 | icon="no-alt" |
| 182 | onClick={ cancelOnboarding } |
| 183 | /> |
| 184 | ) } |
| 185 | </div> |
| 186 | ); |
| 187 | }; |
| 188 | |
| 189 | export default compose( |
| 190 | withDispatch( ( dispatch ) => { |
| 191 | const { setOnboardingState, setCurrentTab, setFetching } = dispatch( |
| 192 | 'neve-onboarding' |
| 193 | ); |
| 194 | return { |
| 195 | cancelOnboarding: () => { |
| 196 | setOnboardingState( false ); |
| 197 | }, |
| 198 | setCurrentTab, |
| 199 | setFetching, |
| 200 | }; |
| 201 | } ), |
| 202 | withSelect( ( select ) => { |
| 203 | const { |
| 204 | getOnboardingStatus, |
| 205 | getCurrentTab, |
| 206 | getFetching, |
| 207 | getLicense, |
| 208 | } = select( 'neve-onboarding' ); |
| 209 | return { |
| 210 | isOnboarding: getOnboardingStatus(), |
| 211 | currentTab: getCurrentTab(), |
| 212 | isFetching: getFetching(), |
| 213 | license: getLicense(), |
| 214 | }; |
| 215 | } ) |
| 216 | )( Header ); |
| 217 |