├── src ├── react-app-env.d.ts ├── types │ └── mapbox-gl-arcgis-featureserver.d.ts ├── sass │ ├── _utilities.scss │ ├── index.scss │ ├── variables.scss │ ├── _typography.scss │ ├── _animations.scss │ └── components │ │ └── shared.scss ├── assets │ └── images │ │ ├── BrokenAb.gif │ │ ├── MedRXIV.jpg │ │ ├── PlosOnePub.png │ │ ├── WHO-EN-C-H.png │ │ ├── WHO-FR-C-H.png │ │ ├── amc-joule.png │ │ ├── innovation.png │ │ ├── PubMedia │ │ ├── mars.jpg │ │ ├── joule.png │ │ ├── logo-1.png │ │ ├── oxford.jpg │ │ ├── download.png │ │ ├── unnamed.jpg │ │ ├── waterloo.png │ │ ├── Forbes-logo.png │ │ ├── marcia news.png │ │ ├── Bloomberg_Logo.jpg │ │ ├── chi_logo_89px.png │ │ ├── mckinsey_logo.png │ │ ├── reuters-logo.png │ │ ├── waterloo1png.png │ │ ├── 3622.1582633003.png │ │ ├── UtQKN6pj_400x400.jpg │ │ ├── CITF-logo-BIL-700.png │ │ ├── covidend-global-logo.png │ │ ├── HIMSSlogo_Hfullcolor_RGB.png │ │ ├── JournalQuebec_Logo2013-.png │ │ ├── New-York-Times-Logo8x6_0.png │ │ ├── 1200px-The_Economist_Logo.svg.png │ │ ├── mars-discovery-district-vector-logo.png │ │ ├── BI_blue_background_vertical.png.crdownload.png │ │ └── mcgill-university-logo-png-transparent-cropped.png │ │ ├── close-round.png │ │ ├── LancetIDArticle.png │ │ ├── Prepublication.png │ │ ├── InsuringTheEconomy.png │ │ ├── YearInReview2020.png │ │ ├── public-health-agency.png │ │ ├── serotracker_map_may7.png │ │ ├── IndustryUpdatePre_2020.png │ │ ├── serotracker_chart_may7.jpg │ │ ├── InventoryEvidenceSynthesis.png │ │ ├── University-Of-Calgary-Logo.png │ │ ├── SeroTrackerBloodBank_July_2020.png │ │ ├── airtable-icon.svg │ │ ├── two-tone-dark.svg │ │ ├── two-tone-light.svg │ │ ├── SerotrackerLogo.svg │ │ └── colored-icon.svg ├── tests │ └── system.test.ts ├── utils │ ├── translate │ │ ├── caseChanger.ts │ │ └── translateService.ts │ ├── usePrevious.ts │ ├── GeoJsonGenerator.tsx │ ├── stateUpdateUtils.tsx │ ├── utils.tsx │ ├── analyticsUtils.tsx │ └── MappingUtil.tsx ├── components │ ├── shared │ │ ├── TableauEmbed │ │ │ ├── TableauEmbed.scss │ │ │ └── TableauEmbed.tsx │ │ ├── PageBody.tsx │ │ ├── MaintenanceModal.tsx │ │ ├── NewsletterPopup.tsx │ │ ├── WhoLogo.tsx │ │ ├── CookieBanner.tsx │ │ ├── Footer │ │ │ ├── Footer.scss │ │ │ └── NewsletterEmailInput.tsx │ │ ├── InformationText.tsx │ │ ├── Settings.tsx │ │ ├── InformationIcon.tsx │ │ └── DownloadButton.tsx │ ├── sidebar │ │ ├── right-sidebar │ │ │ ├── LanguageSelector.css │ │ │ ├── Filters.css │ │ │ ├── datepicker │ │ │ │ ├── Track.tsx │ │ │ │ ├── Tick.tsx │ │ │ │ ├── TooltipRail.tsx │ │ │ │ ├── Handle.tsx │ │ │ │ ├── DateSlider.css │ │ │ │ ├── DateSlider.tsx │ │ │ │ └── Datepicker.tsx │ │ │ ├── SectionHeader.tsx │ │ │ └── LanguageSelector.tsx │ │ ├── sidebar.scss │ │ └── left-sidebar │ │ │ ├── TotalStats.css │ │ │ ├── AnalysisMethods.tsx │ │ │ ├── TotalStats.tsx │ │ │ └── LeftSidebar.tsx │ ├── static │ │ └── Auth │ │ │ ├── AuthController.ts │ │ │ ├── auth.css │ │ │ └── Auth.tsx │ ├── pages │ │ ├── Publications │ │ │ ├── biblioDigestStyles.scss │ │ │ ├── PrivateReportsCard.tsx │ │ │ ├── PublicationsItem.tsx │ │ │ ├── MediaCard.tsx │ │ │ ├── styles.scss │ │ │ └── BiblioDigestCard.tsx │ │ ├── Explore │ │ │ ├── Explore.scss │ │ │ └── ExploreMobile.tsx │ │ ├── PrivacyPolicy.tsx │ │ ├── Partnerships │ │ │ ├── Partnerships.tsx │ │ │ └── CanadaPartnership.tsx │ │ ├── CookiePolicy.tsx │ │ ├── NotFoundPage.tsx │ │ ├── TermsOfUse.tsx │ │ ├── Analyze.tsx │ │ └── static.css │ ├── map │ │ ├── ArbotrackerBanner.tsx │ │ ├── Legend.css │ │ ├── MapboxMap.scss │ │ ├── Legend.tsx │ │ ├── Popups │ │ │ ├── CountryPopup.tsx │ │ │ └── StudyPopup.tsx │ │ ├── MapConfig.ts │ │ └── Layers │ │ │ └── StudyPins.tsx │ └── partnerships │ │ └── PartnershipsMap.tsx ├── setupTests.js ├── PartnershipsConfig.ts ├── index.js ├── constants.ts ├── serviceWorker.js ├── types.ts ├── App.tsx └── context.tsx ├── public ├── robots.txt ├── logo192.png ├── logo512.png ├── two-tone │ ├── favicon.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── apple-touch-icon.png │ ├── android-chrome-192x192.png │ ├── android-chrome-512x512.png │ └── site.webmanifest ├── colored │ ├── favicon-new.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── apple-touch-icon.png │ ├── android-chrome-192x192.png │ └── android-chrome-512x512.png ├── site.webmanifest ├── manifest.json └── index.html ├── .idea ├── misc.xml ├── vcs.xml ├── .gitignore ├── inspectionProfiles │ └── profiles_settings.xml ├── modules.xml └── sero-can-webapp.iml ├── jest.config.js ├── .github └── workflows │ ├── deploy-staging.yml │ ├── deploy-staging-1.yml │ ├── deploy-staging-2.yml │ ├── deploy-staging-3.yml │ ├── ci.yml │ └── deploy-gh-pages.yml ├── .gitignore ├── tsconfig.json ├── LICENSE ├── pull_request_template.md └── package.json /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/types/mapbox-gl-arcgis-featureserver.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'mapbox-gl-arcgis-featureserver'; -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/two-tone/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/two-tone/favicon.ico -------------------------------------------------------------------------------- /src/sass/_utilities.scss: -------------------------------------------------------------------------------- 1 | @for $i from 1 through 5 { 2 | .w-#{$i*20} { 3 | width: 100% !important; 4 | } 5 | } -------------------------------------------------------------------------------- /public/colored/favicon-new.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/colored/favicon-new.ico -------------------------------------------------------------------------------- /src/assets/images/BrokenAb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/BrokenAb.gif -------------------------------------------------------------------------------- /src/assets/images/MedRXIV.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/MedRXIV.jpg -------------------------------------------------------------------------------- /public/colored/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/colored/favicon-16x16.png -------------------------------------------------------------------------------- /public/colored/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/colored/favicon-32x32.png -------------------------------------------------------------------------------- /src/assets/images/PlosOnePub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PlosOnePub.png -------------------------------------------------------------------------------- /src/assets/images/WHO-EN-C-H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/WHO-EN-C-H.png -------------------------------------------------------------------------------- /src/assets/images/WHO-FR-C-H.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/WHO-FR-C-H.png -------------------------------------------------------------------------------- /src/assets/images/amc-joule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/amc-joule.png -------------------------------------------------------------------------------- /src/assets/images/innovation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/innovation.png -------------------------------------------------------------------------------- /public/colored/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/colored/apple-touch-icon.png -------------------------------------------------------------------------------- /public/two-tone/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/two-tone/favicon-16x16.png -------------------------------------------------------------------------------- /public/two-tone/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/two-tone/favicon-32x32.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/mars.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/mars.jpg -------------------------------------------------------------------------------- /src/assets/images/close-round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/close-round.png -------------------------------------------------------------------------------- /public/two-tone/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/two-tone/apple-touch-icon.png -------------------------------------------------------------------------------- /src/assets/images/LancetIDArticle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/LancetIDArticle.png -------------------------------------------------------------------------------- /src/assets/images/Prepublication.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/Prepublication.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/joule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/joule.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/logo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/logo-1.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/oxford.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/oxford.jpg -------------------------------------------------------------------------------- /src/assets/images/InsuringTheEconomy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/InsuringTheEconomy.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/download.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/unnamed.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/unnamed.jpg -------------------------------------------------------------------------------- /src/assets/images/PubMedia/waterloo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/waterloo.png -------------------------------------------------------------------------------- /src/assets/images/YearInReview2020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/YearInReview2020.png -------------------------------------------------------------------------------- /src/tests/system.test.ts: -------------------------------------------------------------------------------- 1 | 2 | // TODO: Make real component tests 3 | test('placeholder test', () => { 4 | expect(true).toBe(true) 5 | }); -------------------------------------------------------------------------------- /public/colored/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/colored/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/colored/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/colored/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/two-tone/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/two-tone/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/two-tone/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/public/two-tone/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/Forbes-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/Forbes-logo.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/marcia news.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/marcia news.png -------------------------------------------------------------------------------- /src/assets/images/public-health-agency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/public-health-agency.png -------------------------------------------------------------------------------- /src/assets/images/serotracker_map_may7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/serotracker_map_may7.png -------------------------------------------------------------------------------- /src/utils/translate/caseChanger.ts: -------------------------------------------------------------------------------- 1 | import _ from "lodash"; 2 | 3 | export const toPascalCase = (str: string) => _.upperFirst(_.camelCase(str)); -------------------------------------------------------------------------------- /src/assets/images/IndustryUpdatePre_2020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/IndustryUpdatePre_2020.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/Bloomberg_Logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/Bloomberg_Logo.jpg -------------------------------------------------------------------------------- /src/assets/images/PubMedia/chi_logo_89px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/chi_logo_89px.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/mckinsey_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/mckinsey_logo.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/reuters-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/reuters-logo.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/waterloo1png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/waterloo1png.png -------------------------------------------------------------------------------- /src/assets/images/serotracker_chart_may7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/serotracker_chart_may7.jpg -------------------------------------------------------------------------------- /src/assets/images/PubMedia/3622.1582633003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/3622.1582633003.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/UtQKN6pj_400x400.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/UtQKN6pj_400x400.jpg -------------------------------------------------------------------------------- /src/assets/images/InventoryEvidenceSynthesis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/InventoryEvidenceSynthesis.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/CITF-logo-BIL-700.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/CITF-logo-BIL-700.png -------------------------------------------------------------------------------- /src/assets/images/University-Of-Calgary-Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/University-Of-Calgary-Logo.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/covidend-global-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/covidend-global-logo.png -------------------------------------------------------------------------------- /src/assets/images/SeroTrackerBloodBank_July_2020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/SeroTrackerBloodBank_July_2020.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/HIMSSlogo_Hfullcolor_RGB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/HIMSSlogo_Hfullcolor_RGB.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/JournalQuebec_Logo2013-.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/JournalQuebec_Logo2013-.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/New-York-Times-Logo8x6_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/New-York-Times-Logo8x6_0.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/1200px-The_Economist_Logo.svg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/1200px-The_Economist_Logo.svg.png -------------------------------------------------------------------------------- /src/components/shared/TableauEmbed/TableauEmbed.scss: -------------------------------------------------------------------------------- 1 | @import '../../../sass/variables.scss'; 2 | 3 | 4 | .tableau-embed { 5 | > div { 6 | width: 100%; 7 | } 8 | } -------------------------------------------------------------------------------- /src/assets/images/PubMedia/mars-discovery-district-vector-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/mars-discovery-district-vector-logo.png -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/images/PubMedia/BI_blue_background_vertical.png.crdownload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/BI_blue_background_vertical.png.crdownload.png -------------------------------------------------------------------------------- /src/assets/images/PubMedia/mcgill-university-logo-png-transparent-cropped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serotracker/sero-can-webapp/HEAD/src/assets/images/PubMedia/mcgill-university-logo-png-transparent-cropped.png -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /src/components/sidebar/right-sidebar/LanguageSelector.css: -------------------------------------------------------------------------------- 1 | .highlighted-language { 2 | color: #455A64; 3 | } 4 | 5 | .regular-language { 6 | font-weight: 300; 7 | } 8 | 9 | .language-selector-container { 10 | border-top: 1px grey 11 | } -------------------------------------------------------------------------------- /src/utils/usePrevious.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from "react"; 2 | 3 | function usePrevious(value: any) { 4 | const ref = useRef(); 5 | useEffect(() => { 6 | ref.current = value; 7 | }); 8 | return ref.current; 9 | } 10 | 11 | export default usePrevious; -------------------------------------------------------------------------------- /public/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /public/two-tone/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/components/sidebar/sidebar.scss: -------------------------------------------------------------------------------- 1 | .sidebar-container { 2 | border: none; 3 | overflow-y: auto; 4 | overflow-x: hidden; 5 | display: block; 6 | padding: 5%; 7 | 8 | &::-webkit-scrollbar { 9 | width: 3px; 10 | } 11 | } 12 | 13 | .left-sidebar { 14 | font-size: 14px; 15 | line-height: 21px; 16 | } -------------------------------------------------------------------------------- /.idea/sero-can-webapp.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "roots": [ 3 | "/src" 4 | ], 5 | "transform": { 6 | "^.+\\.tsx?$": "ts-jest" 7 | }, 8 | "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$", 9 | "moduleFileExtensions": [ 10 | "ts", 11 | "tsx", 12 | "js", 13 | "jsx", 14 | "json", 15 | "node" 16 | ], 17 | } 18 | -------------------------------------------------------------------------------- /src/components/sidebar/right-sidebar/Filters.css: -------------------------------------------------------------------------------- 1 | .checkbox-item { 2 | display: flex; 3 | justify-content: flex-start; 4 | align-items: center; 5 | margin: 0.2em; 6 | } 7 | 8 | .ui.dropdown > .text { 9 | white-space: nowrap; 10 | overflow: hidden; 11 | text-overflow: ellipsis; 12 | } 13 | 14 | .filters-container { 15 | overflow-y: hidden; 16 | overflow-x: hidden; 17 | height: calc(100vh); 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/deploy-staging.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to Staging 2 | on: 3 | push: 4 | branches: 5 | - staging 6 | 7 | 8 | jobs: 9 | deploy-staging: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: akhileshns/heroku-deploy@v3.0.4 14 | with: 15 | heroku_api_key: ${{secrets.HEROKU_API_KEY}} 16 | heroku_app_name: "serotracker-staging" 17 | heroku_email: "abeljohnjoseph@gmail.com" 18 | -------------------------------------------------------------------------------- /.github/workflows/deploy-staging-1.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to Staging-1 2 | on: 3 | push: 4 | branches: 5 | - staging-1 6 | 7 | 8 | jobs: 9 | deploy-staging: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: akhileshns/heroku-deploy@v3.0.4 14 | with: 15 | heroku_api_key: ${{secrets.NEW_HEROKU_API_KEY}} 16 | heroku_app_name: "serotracker-staging-1" 17 | heroku_email: "can.serosurveillance.dev@gmail.com" 18 | -------------------------------------------------------------------------------- /.github/workflows/deploy-staging-2.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to Staging-2 2 | on: 3 | push: 4 | branches: 5 | - staging-2 6 | 7 | 8 | jobs: 9 | deploy-staging: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: akhileshns/heroku-deploy@v3.0.4 14 | with: 15 | heroku_api_key: ${{secrets.NEW_HEROKU_API_KEY}} 16 | heroku_app_name: "serotracker-staging-2" 17 | heroku_email: "can.serosurveillance.dev@gmail.com" 18 | -------------------------------------------------------------------------------- /.github/workflows/deploy-staging-3.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to Staging-3 2 | on: 3 | push: 4 | branches: 5 | - staging-3 6 | 7 | 8 | jobs: 9 | deploy-staging: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: akhileshns/heroku-deploy@v3.0.4 14 | with: 15 | heroku_api_key: ${{secrets.NEW_HEROKU_API_KEY}} 16 | heroku_app_name: "serotracker-staging-3" 17 | heroku_email: "can.serosurveillance.dev@gmail.com" 18 | -------------------------------------------------------------------------------- /src/sass/index.scss: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&display=swap'); 2 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap'); 3 | 4 | body { 5 | margin: 0; 6 | font-family: 'Open Sans', sans-serif; 7 | -webkit-font-smoothing: antialiased; 8 | -moz-osx-font-smoothing: grayscale; 9 | } 10 | 11 | label { 12 | overflow: visible; 13 | } 14 | 15 | html, body { height: 100% } 16 | 17 | #root { 18 | display: flex; 19 | flex: 1; 20 | height: 100%; 21 | } -------------------------------------------------------------------------------- /src/components/static/Auth/AuthController.ts: -------------------------------------------------------------------------------- 1 | import * as crypto from "crypto-js"; 2 | 3 | // Note, this password protection method is intended for deterrence, not a robust security solution 4 | export function checkPassword(password: string) { 5 | const msg = "decrypted string" 6 | const encrypted = "U2FsdGVkX1/8XcUQ6PdvFxmM8rTNnwQeyb+MvIXh2hrwvoER4IWLu1It5+Hv/28K"; 7 | const decryptedMsg = crypto.AES.decrypt(encrypted, password); 8 | const passwordValid = decryptedMsg.toString(crypto.enc.Utf8) === msg; 9 | return passwordValid; 10 | } -------------------------------------------------------------------------------- /src/components/pages/Publications/biblioDigestStyles.scss: -------------------------------------------------------------------------------- 1 | .biblio-digest { 2 | &-card { 3 | height: 350px; 4 | width: 100% !important; 5 | max-width: 350px !important; 6 | 7 | &-text { 8 | font-size: 0.9em; 9 | font-weight: 500; 10 | } 11 | 12 | &-text-bold { 13 | font-size: 0.9em; 14 | font-weight: 1000; 15 | } 16 | 17 | &-title { 18 | margin: 0px !important; 19 | } 20 | 21 | &-row { 22 | flex-direction: row; 23 | justify-content: space-between; 24 | display: flex; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/sass/variables.scss: -------------------------------------------------------------------------------- 1 | /* Primary Colors */ 2 | $sero-blue: #55A6BA; 3 | $sero-dark-blue: #364E60; 4 | $sero-green: #47C2B1; 5 | $white: #FFFFFF; 6 | 7 | .sero-blue { color: $sero-blue} 8 | .sero-dark-blue { color: $sero-dark-blue} 9 | .sero-green { color: $sero-green} 10 | .white { color: $white} 11 | 12 | 13 | /* Secondary Colors */ 14 | /* Greys */ 15 | $light-blue-grey: #C9D6DF; 16 | $light-grey: #EAEAEA; 17 | $grey: #888888; 18 | $dark-grey: #212121; 19 | 20 | /* Highlights */ 21 | $banana: #FFBB49; 22 | $spicy: #E15759; 23 | $aqua: #0275FF; 24 | $stone-cold-steve-austin: #094180; -------------------------------------------------------------------------------- /src/components/sidebar/left-sidebar/TotalStats.css: -------------------------------------------------------------------------------- 1 | .main-statistic-title { 2 | font-weight: 400; 3 | font-size: 1em; 4 | line-height: 1em; 5 | } 6 | 7 | .main-statistic { 8 | font-weight: 400; 9 | font-size: 1em; 10 | line-height: 1em; 11 | } 12 | 13 | .secondary-statistic-title { 14 | font-weight: 400; 15 | font-size: 1em; 16 | line-height: 1em; 17 | } 18 | 19 | .secondary-statistic { 20 | font-weight: 400; 21 | font-size: 1em; 22 | line-height: 1em; 23 | text-align: center; 24 | color: #455A64; 25 | } 26 | 27 | .stats-container { 28 | flex: 0 1 29 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | ./src/react-app-env.d.ts 25 | 26 | # code editor 27 | .vscode/ 28 | .idea/ 29 | 30 | #.env 31 | # DO NOT COMMIT SECRETS 32 | .env 33 | 34 | load-dotenv.sh 35 | 36 | .idea/ 37 | 38 | get_diff.py -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push] 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout 9 | uses: actions/checkout@v1 10 | - name: Setup Node 11 | uses: actions/setup-node@v2 12 | with: 13 | node-version: "12.16.0" 14 | - name: Build 15 | run: | 16 | npm install 17 | npm run build 18 | env: 19 | REACT_APP_MAPBOX_API_KEY: ${{ secrets.MAPBOX_API_KEY }} 20 | REACT_APP_ROUTE: ${{ secrets.ROUTE }} 21 | CI: false 22 | - name: Test 23 | run: | 24 | npm test 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "baseUrl": "src", 11 | "skipLibCheck": true, 12 | "esModuleInterop": true, 13 | "allowSyntheticDefaultImports": true, 14 | "strict": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react", 22 | "noFallthroughCasesInSwitch": true 23 | }, 24 | "include": [ 25 | "src" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /src/sass/_typography.scss: -------------------------------------------------------------------------------- 1 | .text-lead{ 2 | font-size: 16.8px; 3 | line-height: 150%; 4 | } 5 | 6 | .text-default { 7 | font-size: 14px; 8 | line-height: 150%; 9 | } 10 | 11 | .text-small { 12 | font-size: 12px; 13 | line-height: 150%; 14 | } 15 | 16 | h1, h2, h3, h4, h5 { 17 | margin: 0; 18 | line-height: 110%; 19 | } 20 | 21 | h1 { 22 | font-size: 34.8px; 23 | } 24 | 25 | h2 { 26 | font-size: 29px; 27 | } 28 | 29 | h3 { 30 | font-size: 24.2px; 31 | } 32 | 33 | h4 { 34 | font-size: 20.2px; 35 | } 36 | 37 | h5 { 38 | font-family: "Open Sans"; 39 | font-size: 14px; 40 | } 41 | 42 | .subheading { 43 | font-size: 14px; 44 | font-weight: 600; 45 | } 46 | 47 | .extra-bold { 48 | font-weight: 800; 49 | } -------------------------------------------------------------------------------- /src/components/shared/PageBody.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { isMaintenanceMode } from "../../constants"; 3 | import MaintenanceModal from "../shared/MaintenanceModal"; 4 | 5 | interface PageBodyProps { 6 | className?: string, 7 | children?: JSX.Element | JSX.Element[]; 8 | includeMaintenanceModal: boolean, 9 | } 10 | 11 | const PageBody = (props: PageBodyProps) => { 12 | return ( 13 |
14 |
15 |
16 | {props.children} 17 |
18 |
19 | {props.includeMaintenanceModal && } 20 |
21 | ) 22 | } 23 | 24 | export default PageBody -------------------------------------------------------------------------------- /src/components/sidebar/right-sidebar/datepicker/Track.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { SliderItem } from "react-compound-slider"; 3 | 4 | interface TrackProps { 5 | source: SliderItem; 6 | target: SliderItem; 7 | disabled?: Boolean; 8 | getTrackProps: () => object; 9 | } 10 | 11 | export default function Track({ 12 | source, 13 | target, 14 | getTrackProps, 15 | disabled = false 16 | }: TrackProps) { 17 | return ( 18 |
27 | ); 28 | } -------------------------------------------------------------------------------- /src/components/pages/Explore/Explore.scss: -------------------------------------------------------------------------------- 1 | @import '../../../sass/variables.scss'; 2 | 3 | @mixin icon-container { 4 | position: absolute; 5 | z-index: 3000; 6 | background-color: white; 7 | border-radius: 3px; 8 | box-shadow: 0 3px 3px 0 #646464; 9 | height: 30px; 10 | width: 30px; 11 | } 12 | 13 | .explore { 14 | .sidebar { 15 | &__info-btn { 16 | @include icon-container; 17 | top: 45px; 18 | left: 10px; 19 | } 20 | 21 | &__filter-btn { 22 | @include icon-container; 23 | top: 10px; 24 | left: 10px; 25 | } 26 | 27 | &__map-btn { 28 | @include icon-container; 29 | bottom: 10px; 30 | right: 10px; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/components/pages/PrivacyPolicy.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useMediaQuery } from "react-responsive"; 3 | import { mobileDeviceOrTabletWidth } from "../../constants"; 4 | import Translate from "../../utils/translate/translateService"; 5 | import './static.css'; 6 | 7 | export default function PrivacyPolicy() { 8 | const isMobileDeviceOrTablet = useMediaQuery({ maxDeviceWidth: mobileDeviceOrTabletWidth }) 9 | 10 | return ( 11 |
12 | 13 |
14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /src/assets/images/airtable-icon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/PartnershipsConfig.ts: -------------------------------------------------------------------------------- 1 | import { Partnership } from './types'; 2 | import { CANADA_URLS } from "./constants"; 3 | 4 | const PartnershipsConfig: Partnership[] = [ 5 | { 6 | iso3: 'CAN', 7 | routeName: "Canada", 8 | tableauKey: "CanadianTableau", 9 | tableauUrl: CANADA_URLS, 10 | mapboxMapOptions: { 11 | bounds: [ 12 | [-148, 39], // Southwest coordinates 13 | [-50, 75] // Northeast coordinates 14 | ], 15 | /* 16 | maxBounds: [ 17 | [-147, 37], // Southwest coordinates 18 | [-48, 86] // Northeast coordinates 19 | ] 20 | */ 21 | } 22 | } 23 | ] 24 | 25 | export default PartnershipsConfig; -------------------------------------------------------------------------------- /src/sass/_animations.scss: -------------------------------------------------------------------------------- 1 | .pulse { 2 | cursor: pointer; 3 | box-shadow: 0 0 0 #65BEE9; 4 | animation: pulse 1s; 5 | animation-iteration-count: 5; 6 | } 7 | .pulse:hover { 8 | animation: none; 9 | } 10 | 11 | @-webkit-keyframes pulse { 12 | 0% { 13 | -webkit-box-shadow: 0 0 0 0 rgba(101, 190, 233, 0.8); 14 | } 15 | 70% { 16 | -webkit-box-shadow: 0 0 0 14px rgba(101, 190, 233, 0.4); 17 | } 18 | 100% { 19 | -webkit-box-shadow: 0 0 0 0 rgba(101, 190, 233, 0); 20 | } 21 | } 22 | @keyframes pulse { 23 | 0% { 24 | -moz-box-shadow: 0 0 0 0 rgba(101, 190, 233, 0.8); 25 | box-shadow: 0 0 0 0 rgba(101, 190, 233, 0.4); 26 | } 27 | 70% { 28 | -moz-box-shadow: 0 0 0 14px rgba(101, 190, 233, 0.4); 29 | box-shadow: 0 0 0 14px rgba(101, 190, 233, 0); 30 | } 31 | 100% { 32 | -moz-box-shadow: 0 0 0 0 rgba(101, 190, 233, 0); 33 | box-shadow: 0 0 0 0 rgba(101, 190, 233, 0); 34 | } 35 | } -------------------------------------------------------------------------------- /src/assets/images/two-tone-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/images/two-tone-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/components/shared/MaintenanceModal.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Modal } from "semantic-ui-react"; 3 | import 'sass/components/shared.scss'; 4 | import Translate from "../../utils/translate/translateService"; 5 | 6 | interface MaintenanceModalProps { 7 | isOpen: boolean, 8 | headerText: string // specifies if analysis or explore page 9 | } 10 | 11 | export default function MaintenanceModal(props: MaintenanceModalProps) { 12 | 13 | const { isOpen, headerText } = props; 14 | 15 | return ( 16 | 22 | {Translate('TemporaryMaintenance')} 23 | 24 |

{Translate('TemporaryMaintenanceDescription')}

25 |
26 |
27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /src/components/sidebar/right-sidebar/datepicker/Tick.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | import { SliderItem } from "react-compound-slider"; 3 | 4 | interface TickProps { 5 | tick: SliderItem; 6 | count: number; 7 | format: (val: number) => string; 8 | } 9 | 10 | const defaultFormat = (d: number) => `d`; 11 | 12 | export default function Tick({ tick, count, format = defaultFormat }: TickProps) { 13 | return ( 14 |
15 |
21 |
29 | {format(tick.value)} 30 |
31 |
32 | ); 33 | } -------------------------------------------------------------------------------- /.github/workflows/deploy-gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | repository_dispatch: 8 | types: manual-trigger 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v1 16 | - name: Setup Node 17 | uses: actions/setup-node@v2 18 | with: 19 | node-version: "12.16.0" 20 | - name: Build 21 | run: | 22 | npm install 23 | npm run build 24 | env: 25 | REACT_APP_MAPBOX_API_KEY: ${{ secrets.MAPBOX_API_KEY }} 26 | REACT_APP_ROUTE: ${{ secrets.ROUTE }} 27 | REACT_APP_GA_TRACKERID: ${{ secrets.GA_TRACKERID }} 28 | CI: false 29 | - name: Deploy 30 | uses: JamesIves/github-pages-deploy-action@releases/v3 31 | with: 32 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 33 | BRANCH: gh-pages 34 | FOLDER: build 35 | -------------------------------------------------------------------------------- /src/components/static/Auth/auth.css: -------------------------------------------------------------------------------- 1 | .staticrypt-form { 2 | position: relative; 3 | z-index: 1; 4 | background: #FFFFFF; 5 | max-width: 360px; 6 | margin: 0 auto 100px; 7 | padding: 45px; 8 | text-align: center; 9 | box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24); 10 | } 11 | 12 | .staticrypt-form input { 13 | outline: 0; 14 | background: #f2f2f2; 15 | width: 100%; 16 | border: 0; 17 | margin: 0 0 15px; 18 | padding: 15px; 19 | box-sizing: border-box; 20 | font-size: 0.875em; 21 | } 22 | 23 | .staticrypt-form .staticrypt-decrypt-button { 24 | text-transform: uppercase; 25 | outline: 0; 26 | background: #4CAF50; 27 | width: 100%; 28 | border: 0; 29 | padding: 15px; 30 | color: #FFFFFF; 31 | font-size: 0.875em; 32 | cursor: pointer; 33 | } 34 | 35 | .staticrypt-form .staticrypt-decrypt-button:hover, .staticrypt-form .staticrypt-decrypt-button:active, .staticrypt-form .staticrypt-decrypt-button:focus { 36 | background: #43A047; 37 | } -------------------------------------------------------------------------------- /src/components/sidebar/right-sidebar/SectionHeader.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "react-datepicker/dist/react-datepicker.css"; 3 | import InformationIcon from "../../shared/InformationIcon"; 4 | 5 | interface SectionHeaderProps { 6 | header_text: string, 7 | tooltip_text?: string | React.ReactNode, 8 | tooltip_header?: string 9 | } 10 | 11 | export default function SectionHeader({header_text, tooltip_text, tooltip_header}: SectionHeaderProps){ 12 | return ( 13 |
14 |
{header_text}
15 | {tooltip_text && ( 16 |
17 | 25 |
26 | )} 27 |
28 | ) 29 | } -------------------------------------------------------------------------------- /src/components/map/ArbotrackerBanner.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; 3 | import { faTimes} from "@fortawesome/free-solid-svg-icons"; 4 | 5 | export const ArboTrackerBanner = () => { 6 | const [visible, setVisible]= useState(true); 7 | 8 | return ( 9 | 28 | ); 29 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 SeroTracker contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/sidebar/right-sidebar/LanguageSelector.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext, useState } from "react"; 2 | import { CheckboxProps, Radio } from "semantic-ui-react"; 3 | import { AppContext } from "../../../context"; 4 | import { LanguageType } from "../../../types"; 5 | import Translate from "../../../utils/translate/translateService"; 6 | 7 | 8 | export default function LanguageSelector() { 9 | const [state, dispatch] = useContext(AppContext); 10 | const [checked, setChecked] = useState(state.language !== LanguageType.english) 11 | const handleChange = (event: React.SyntheticEvent, data: CheckboxProps) => { 12 | event.preventDefault(); 13 | let newLanguage = data.checked ? LanguageType.french : LanguageType.english 14 | setChecked(data.checked || false); 15 | dispatch({ 16 | type: 'SELECT_LANGUAGE', 17 | payload: newLanguage 18 | }) 19 | } 20 | 21 | return ( 22 |
23 |
{Translate('English')}
24 | < Radio toggle checked={checked} onChange={handleChange} onClick={(e, ea) => { e.preventDefault() }}> 25 |
{Translate('French')}
26 |
27 | ) 28 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import 'sass/index.scss'; 5 | import * as serviceWorker from './serviceWorker'; 6 | import { AppContextProvider } from './context' 7 | import {Router} from 'react-router-dom'; 8 | import GAListener from "./utils/analyticsUtils"; 9 | import {createBrowserHistory} from 'history'; 10 | import ReactGA from 'react-ga'; 11 | 12 | // Initialize ReactGA 13 | const isDev = process.env.NODE_ENV === "development"; 14 | ReactGA.initialize(process.env.REACT_APP_GA_TRACKERID, { 15 | titleCase: false, 16 | debug: isDev, 17 | gaOptions: { 18 | cookieDomain: isDev ? 'none' : 'auto' 19 | } 20 | }); 21 | 22 | const history = createBrowserHistory() 23 | 24 | ReactDOM.render( 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | , 34 | document.getElementById('root') 35 | ); 36 | 37 | // If you want your app to work offline and load faster, you can change 38 | // unregister() to register() below. Note this comes with some pitfalls. 39 | // Learn more about service workers: https://bit.ly/CRA-PWA 40 | serviceWorker.unregister(); 41 | -------------------------------------------------------------------------------- /src/components/pages/Partnerships/Partnerships.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Redirect, useParams } from "react-router-dom"; 3 | import { Partnership } from "types"; 4 | import PartnershipsConfig from "PartnershipsConfig"; 5 | import CanadaPartnership from 'components/pages/Partnerships/CanadaPartnership'; 6 | import PageBody from '../../shared/PageBody' 7 | 8 | type PartnershipProps = { 9 | partnershipConfig: Partnership; 10 | }; 11 | 12 | function RenderSelectedPartnershipComponent({partnershipConfig}: PartnershipProps){ 13 | let partnership = undefined 14 | switch(partnershipConfig.routeName) { 15 | case 'Canada': 16 | partnership = 17 | break; 18 | // Add more cases for new parnership components here. 19 | } 20 | 21 | return partnership 22 | } 23 | 24 | export default function Partnerships() { 25 | const {name} = useParams<{ name: string }>(); 26 | const config = PartnershipsConfig.find(x => x.routeName === name); 27 | 28 | return ( 29 | <> 30 | {config !== undefined ? ( 31 | 32 | {RenderSelectedPartnershipComponent({partnershipConfig: config})} 33 | 34 | ) : ( 35 | 36 | )} 37 | 38 | ); 39 | } 40 | -------------------------------------------------------------------------------- /src/components/pages/CookiePolicy.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from "react"; 2 | import { useMediaQuery } from "react-responsive"; 3 | import { mobileDeviceOrTabletWidth } from "../../constants"; 4 | import Translate from "../../utils/translate/translateService"; 5 | import './static.css'; 6 | 7 | export default function CookiePolicy() { 8 | const isMobileDeviceOrTablet = useMediaQuery({ maxDeviceWidth: mobileDeviceOrTabletWidth }) 9 | 10 | useEffect(() => { 11 | const script = document.createElement('script'); 12 | 13 | script.text = "(function(d, s, id) { var js, tjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = 'https://app.termly.io/embed-policy.min.js'; tjs.parentNode.insertBefore(js, tjs); }(document, 'script', 'termly-jssdk'));" 14 | 15 | document.body.appendChild(script); 16 | 17 | return () => { 18 | document.body.removeChild(script); 19 | } 20 | }, []); 21 | 22 | return ( 23 |
24 | 25 |
26 | ) 27 | } 28 | -------------------------------------------------------------------------------- /src/utils/GeoJsonGenerator.tsx: -------------------------------------------------------------------------------- 1 | import { AirtableRecord } from "../types"; 2 | 3 | // Please refer to GeoJSON spec rfc7946 if adding addiontal members: https://tools.ietf.org/html/rfc7946#section-3.1.1 4 | function recordsToGeoJsonFeatures(records: AirtableRecord[]): GeoJSON.Feature[] { 5 | return records.flatMap((record) => { 6 | if (!record.pin_latitude && !record.pin_longitude){ 7 | return []; 8 | } 9 | return { 10 | type: "Feature", 11 | properties: { // We can add any properties here to modify how we want to render the pin - helpful for WHO data 12 | estimate_grade: record.estimate_grade, 13 | source_id: record.source_id ?? undefined 14 | }, 15 | geometry: { 16 | type: "Point", 17 | coordinates: [record.pin_longitude, record.pin_latitude], 18 | }, 19 | }; 20 | }); 21 | } 22 | 23 | export default function generateSourceFromRecords(records: AirtableRecord[]): mapboxgl.GeoJSONSourceRaw { 24 | const f = recordsToGeoJsonFeatures(records); 25 | const source = { 26 | type: "geojson", 27 | promoteId: 'source_id', 28 | data: { 29 | type: "FeatureCollection", 30 | features: f, 31 | }, 32 | } as mapboxgl.GeoJSONSourceRaw; 33 | 34 | return source; 35 | } -------------------------------------------------------------------------------- /src/components/shared/NewsletterPopup.tsx: -------------------------------------------------------------------------------- 1 | import React, {useEffect, useState} from "react"; 2 | import {Button, Icon} from "semantic-ui-react"; 3 | 4 | export default function NewsletterPopup() { 5 | const [hidden, setHidden] = useState(true) 6 | 7 | useEffect(() => { 8 | if (!localStorage.getItem("SubscribePopupSeen")){ 9 | if(localStorage.getItem("returnUser") === "true") { 10 | setTimeout(function () { 11 | setHidden(false) 12 | localStorage.setItem("SubscribePopupSeen", "true") 13 | }, 30000) // 30 seconds in ms 14 | } 15 | } 16 | }, []) 17 | 18 | const onClickHandle = () => { 19 | setHidden(true) 20 | } 21 | 22 | return ( 23 |