github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/webapp/javascript/components/Footer.tsx (about)

     1  import React from 'react';
     2  
     3  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
     4  import { faDownload } from '@fortawesome/free-solid-svg-icons/faDownload';
     5  import { Maybe } from 'true-myth';
     6  import { BuildInfo, buildInfo, latestVersionInfo } from '../util/buildInfo';
     7  
     8  const START_YEAR = '2020';
     9  
    10  function copyrightYears(start: string, end: string) {
    11    return start === end ? start : `${start} – ${end}`;
    12  }
    13  
    14  function buildInfoStr(buildInfo: BuildInfo) {
    15    return `
    16      BUILD INFO:
    17      js_version: ${buildInfo.jsVersion}
    18      goos: ${buildInfo?.goos}
    19      goarch: ${buildInfo?.goarch}
    20      go_version: ${buildInfo?.goVersion}
    21      version: ${buildInfo?.version}
    22      time: ${buildInfo?.time}
    23      gitSHA: ${buildInfo?.gitSHA}
    24      gitDirty: ${buildInfo?.gitDirty}
    25      embeddedAssets: ${buildInfo?.useEmbeddedAssets}
    26  `.replace(/^\s+/gm, '');
    27  }
    28  
    29  function NewerVersionCheck() {
    30    const { version } = buildInfo();
    31    const maybeLatestVersionInfo = latestVersionInfo();
    32  
    33    if (maybeLatestVersionInfo.isNothing) {
    34      return null;
    35    }
    36  
    37    const latestVersion = maybeLatestVersionInfo.value.latest_version;
    38  
    39    interface Version {
    40      major: number;
    41      minor: number;
    42      patch: number;
    43    }
    44  
    45    const splitVersion = function (s: string): Maybe<Version> {
    46      // Since we control the format, there's no need for a complex parser
    47      const split = s.split('.');
    48      if (split.length !== 3) {
    49        return Maybe.nothing();
    50      }
    51  
    52      return Maybe.of({
    53        // handle cases like v1.0.0
    54        major: parseInt(split[0].replace('v', ''), 10),
    55        minor: parseInt(split[1], 10),
    56        patch: parseInt(split[2], 10),
    57      });
    58    };
    59  
    60    const isUpdateAvailable = function (v1: Maybe<Version>, v2: Maybe<Version>) {
    61      // we can't infer anything
    62      if (v1.isNothing || v2.isNothing) {
    63        return false;
    64      }
    65  
    66      const v1Value = v1.value;
    67      const v2Value = v2.value;
    68  
    69      // Compare major
    70      if (v2Value.major > v1Value.major) {
    71        return true;
    72      }
    73      if (v2Value.major < v1Value.major) {
    74        return false;
    75      }
    76      // major value is equal
    77  
    78      // compare minor
    79      if (v2Value.minor > v1Value.minor) {
    80        return true;
    81      }
    82      if (v2Value.minor < v1Value.minor) {
    83        return false;
    84      }
    85  
    86      // minor is the same
    87      // compare patch
    88      if (v2Value.patch > v1Value.patch) {
    89        return true;
    90      }
    91      if (v2Value.patch < v1Value.patch) {
    92        return false;
    93      }
    94  
    95      return false;
    96    };
    97  
    98    const currVersionObj = splitVersion(version);
    99    const latestVersionObj = splitVersion(latestVersion);
   100  
   101    if (!isUpdateAvailable(currVersionObj, latestVersionObj)) {
   102      return null;
   103    }
   104  
   105    return (
   106      <span>
   107        &nbsp;&nbsp;|&nbsp;&nbsp;
   108        <a
   109          href="https://pyroscope.io/downloads?utm_source=pyroscope_footer"
   110          rel="noreferrer"
   111          target="_blank"
   112        >
   113          <FontAwesomeIcon icon={faDownload} />
   114          &nbsp;
   115          <span>{`Newer Version Available (${latestVersion})`}</span>
   116        </a>
   117      </span>
   118    );
   119  }
   120  
   121  function Footer() {
   122    const info = buildInfo();
   123  
   124    return (
   125      <footer className="footer" title={buildInfoStr(info)}>
   126        <span>
   127          {`© Pyroscope ${copyrightYears(
   128            START_YEAR,
   129            new Date().getFullYear().toFixed()
   130          )}`}
   131        </span>
   132        &nbsp;&nbsp;|&nbsp;&nbsp;
   133        <span>{info.version}</span>
   134        <NewerVersionCheck />
   135      </footer>
   136    );
   137  }
   138  
   139  export default Footer;