layout.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /* eslint-disable max-lines-per-function */
  2. /* eslint-disable max-len */
  3. /**
  4. * Layout component that queries for data
  5. * with Gatsby's useStaticQuery component
  6. *
  7. * See: https://www.gatsbyjs.org/docs/use-static-query/
  8. */
  9. import 'normalize.css';
  10. import '../styles/layout.scss';
  11. import 'typeface-inter';
  12. import 'typeface-inconsolata';
  13. import React, { useEffect, useState, useCallback } from 'react';
  14. import PropTypes from 'prop-types';
  15. import { useStaticQuery, graphql } from 'gatsby';
  16. import { IntlProvider } from 'react-intl';
  17. import { LocaleProvider } from '@douyinfe/semi-ui';
  18. import semiZhCN from '@douyinfe/semi-ui/locale/source/zh_CN';
  19. import semiEnUS from '@douyinfe/semi-ui/locale/source/en_US';
  20. import SemiSiteBanner from 'semi-site-banner';
  21. import 'semi-site-banner/dist/index.css';
  22. import appLocaleCN from '../locale/zh-CN';
  23. import appLocaleUS from '../locale/en-US';
  24. import Header from './header';
  25. import SideNav from './side-nav';
  26. import Footer from './Footer';
  27. import { itemsArr } from 'utils/category';
  28. import { getLocale, _t } from 'utils/locale';
  29. const insertScript = scriptText => {
  30. let sdk = document.createElement('script');
  31. sdk.type = 'text/javascript';
  32. sdk.innerHTML = scriptText;
  33. document.head.appendChild(sdk);
  34. };
  35. const AppLayout = ({ type, location, children }) => {
  36. const [showBanner, setShowBanner] = useState(false);
  37. // ----------------START insert static code to document-------------------------
  38. useEffect(() => {
  39. if (window.insertSlardarAndHornbill) {
  40. return;
  41. }
  42. Promise.resolve()
  43. .then(() => {
  44. // eslint-disable-next-line
  45. insertScript(`(function(i,s,o,g,r,a,m){i["SlardarMonitorObject"]=r;(i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)}),(i[r].l=1*new Date());(a=s.createElement(o)),(m=s.getElementsByTagName(o)[0]);a.async=1;a.src=g;a.crossOrigin="anonymous";m.parentNode.insertBefore(a,m);i[r].globalPreCollectError=function(){i[r]("precollect","error",arguments)};if(typeof i.addEventListener==="function"){i.addEventListener("error",i[r].globalPreCollectError,true)}if('PerformanceLongTaskTiming'in i){var g=i[r].lt={e:[]};g.o=new PerformanceObserver(function(l){g.e=g.e.concat(l.getEntries())});g.o.observe({entryTypes:['longtask']})}})(window,document,"script","https://i.snssdk.com/slardar/sdk.js?bid=patrol_445","Slardar");`);
  46. insertScript(`
  47. window.Slardar && window.Slardar("config",{
  48. bid: 'patrol_445',
  49. sampleRate: 1,
  50. ignoreAjax: [/.*/],
  51. ignoreStatic: [/.*/],
  52. ignoreErrors: [/.*/],
  53. enableCatchJSError: false,
  54. enableFPSJankTimesMonitor: false,
  55. enableCrash: false,
  56. performanceAuto: true
  57. });`);
  58. })
  59. .then(() => {
  60. window.insertSlardarAndHornbill = true;
  61. })
  62. .catch(e => {
  63. console.error('Insert Slardar Failed. Error: ', e);
  64. });
  65. }, []);
  66. // -----------------------------------------------------------------------------
  67. const showSideNav =
  68. location.pathname.replace(/(zh\-CN\/?|en\-US\/?)/, '') !== '/' && !/(showcase|resources|customers|contribute|teams)/g.test(location.pathname);
  69. const data = useStaticQuery(graphql`
  70. query {
  71. allMdx(
  72. filter: { fields: { type: { nin: ["principles", "concepts"] } } }
  73. sort: { order: ASC, fields: [fields___typeOrder, fields___slug] }
  74. ) {
  75. edges {
  76. node {
  77. fields {
  78. type
  79. slug
  80. }
  81. frontmatter {
  82. title
  83. subTitle
  84. localeCode
  85. icon
  86. order
  87. }
  88. }
  89. }
  90. }
  91. site {
  92. siteMetadata {
  93. title
  94. }
  95. }
  96. }
  97. `);
  98. const locale = getLocale(location.pathname);
  99. const messages = locale === 'zh-CN' ? appLocaleCN.messages : appLocaleUS.messages;
  100. const semiLocale = {
  101. 'zh-CN': semiZhCN,
  102. 'en-US': semiEnUS,
  103. };
  104. const semiLocaleSource = semiLocale[locale];
  105. const bannerRef = useCallback(node => {
  106. if (node !== null) {
  107. setShowBanner(true);
  108. } else {
  109. setShowBanner(false);
  110. }
  111. }, []);
  112. const headerStyle = {};
  113. const contentAeraStyle = {};
  114. const sideNavStyle = {};
  115. if (!showSideNav) {
  116. contentAeraStyle.paddingLeft = 0;
  117. }
  118. if (showBanner) {
  119. contentAeraStyle.paddingTop = 92;
  120. sideNavStyle.marginTop = 92;
  121. }
  122. // TODO import semi common footer
  123. return (
  124. <>
  125. <IntlProvider locale={locale} messages={messages}>
  126. <LocaleProvider locale={semiLocaleSource}>
  127. <div style={{ position: 'fixed', width: '100%', top: 0, zIndex: 999 }}>
  128. <SemiSiteBanner ref={bannerRef} type="black" style={{ height: 32 }} icon={null} />
  129. {/* ssr, can't use location directly, get location from layout and pass to children */}
  130. <Header style={headerStyle} location={location} localeCode={locale} />
  131. </div>
  132. <div className="content-area" style={contentAeraStyle}>
  133. {children}
  134. {!/showcase|teams/.test(location.pathname) && <Footer />}
  135. </div>
  136. {showSideNav ? (
  137. <>
  138. <SideNav hasBanner={showBanner} type={type} style={sideNavStyle} location={location} edges={data.allMdx.edges} itemsArr={itemsArr} />
  139. {/* {footer} */}
  140. </>
  141. ) : null}
  142. </LocaleProvider>
  143. </IntlProvider>
  144. </>
  145. );
  146. };
  147. AppLayout.propTypes = {
  148. children: PropTypes.node.isRequired,
  149. };
  150. export default AppLayout;