├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── prototypes ├── babelInBrowser │ ├── babel.config.json │ ├── bundle.js │ ├── index.html │ ├── index.js │ ├── package-lock.json │ ├── package.json │ └── rollup.config.js ├── computeReferences │ ├── src │ │ ├── computeReferences.ts │ │ └── index.ts │ └── test │ │ └── test.ts ├── gist-fetching │ ├── .prettierignore │ ├── package-lock.json │ ├── package.json │ ├── public │ │ └── favicon.ico │ └── src │ │ ├── build.js │ │ └── server.js ├── idealExport │ ├── .prettierignore │ ├── README.md │ ├── babel.config.json │ ├── index.html │ ├── loader.js │ ├── package-lock.json │ ├── package.json │ └── rollup.config.js ├── open-core-first-attempt │ ├── .gitignore │ ├── .prettierignore │ ├── LICENSE │ ├── README.md │ ├── package.json │ └── packages │ │ ├── vizhub-ce │ │ ├── package.json │ │ ├── public │ │ │ ├── favicon.ico │ │ │ ├── images │ │ │ │ └── touch │ │ │ │ │ └── logoBlackSquare.png │ │ │ └── manifest.json │ │ └── src │ │ │ ├── build.js │ │ │ ├── client.js │ │ │ ├── server.js │ │ │ ├── styles.scss │ │ │ └── test.js │ │ ├── vizhub-core │ │ ├── VizHubError.js │ │ ├── build.js │ │ ├── client.js │ │ ├── coreTests.js │ │ ├── index.js │ │ ├── package.json │ │ ├── server.js │ │ ├── src │ │ │ ├── client │ │ │ │ └── index.js │ │ │ ├── coreTests.js │ │ │ ├── entities │ │ │ │ ├── User.js │ │ │ │ ├── VizContent.js │ │ │ │ ├── VizContentTest.js │ │ │ │ ├── VizInfo.js │ │ │ │ ├── VizInfoTest.js │ │ │ │ ├── createInstance.js │ │ │ │ └── index.js │ │ │ ├── isomorphic │ │ │ │ ├── App.js │ │ │ │ ├── URLStateContext.js │ │ │ │ ├── classed.js │ │ │ │ ├── getPages.js │ │ │ │ ├── index.js │ │ │ │ ├── indexHTML.js │ │ │ │ ├── isClient.js │ │ │ │ ├── jsDelivrCombine.js │ │ │ │ ├── stringifyPageData.js │ │ │ │ └── stringifyPageDataTest.js │ │ │ ├── plugins │ │ │ │ └── homePagePlugin │ │ │ │ │ ├── Body.js │ │ │ │ │ ├── HomePage.js │ │ │ │ │ ├── client.js │ │ │ │ │ └── server.js │ │ │ ├── server │ │ │ │ ├── gateways.js │ │ │ │ ├── getShareDBSnapshot.js │ │ │ │ ├── identifyAgent.js │ │ │ │ └── index.js │ │ │ ├── styles │ │ │ │ ├── base.scss │ │ │ │ ├── index.scss │ │ │ │ ├── link.scss │ │ │ │ └── variables.scss │ │ │ └── svg │ │ │ │ ├── ArrowSVG.js │ │ │ │ ├── CloseSVG.js │ │ │ │ ├── DirectoryArrowSVG.js │ │ │ │ ├── ExportSVG.js │ │ │ │ ├── ForkSVG.js │ │ │ │ ├── FullExitSVG.js │ │ │ │ ├── FullSVG.js │ │ │ │ ├── LockOpenSVG.js │ │ │ │ ├── LockSVG.js │ │ │ │ ├── LogoSVG.js │ │ │ │ ├── MicroSVG.js │ │ │ │ ├── MiniSVG.js │ │ │ │ ├── NewSVG.js │ │ │ │ ├── PeopleSVG.js │ │ │ │ ├── PlanExcludedSVG.js │ │ │ │ ├── PlanIncludedSVG.js │ │ │ │ ├── PlayPauseSVG.js │ │ │ │ ├── PrettierSVG.js │ │ │ │ ├── PullSVG.js │ │ │ │ ├── RadioButtonSVG.js │ │ │ │ ├── SearchSVG.js │ │ │ │ ├── SettingsSVG.js │ │ │ │ ├── ShareSVG.js │ │ │ │ ├── SharedWithMeSVG.js │ │ │ │ ├── SpinnerSVG.js │ │ │ │ ├── SplitSVG.js │ │ │ │ ├── TrashSVG.js │ │ │ │ ├── VimSVG.js │ │ │ │ ├── VoteSVG.js │ │ │ │ ├── index.js │ │ │ │ └── svgGallery.js │ │ └── worker.js │ │ ├── vizhub-plugin-access-control │ │ ├── package.json │ │ ├── server.js │ │ └── src │ │ │ ├── accessControlServerPlugin.js │ │ │ ├── getVizInfoForRequest.js │ │ │ ├── vizRead.js │ │ │ └── vizWrite.js │ │ └── vizhub-plugin-viz-page │ │ ├── build.js │ │ ├── client.js │ │ ├── package.json │ │ ├── server.js │ │ └── src │ │ ├── Editor │ │ ├── EditorSidebar.js │ │ ├── EditorToggleButton.js │ │ ├── ToggleButton.js │ │ ├── index.js │ │ └── styles.scss │ │ ├── SecondaryModulesContextDraft.js │ │ ├── VizPage │ │ ├── Body.js │ │ ├── Head.js │ │ ├── Navigation.js │ │ ├── Readme │ │ │ ├── index.js │ │ │ ├── markdown-body.scss │ │ │ ├── markdownRenderingWorker.js │ │ │ ├── renderREADME.js │ │ │ └── useReadmeHTML.js │ │ ├── VizContext.js │ │ └── index.js │ │ ├── styles.scss │ │ ├── vizPageBuildPlugin.js │ │ ├── vizPageClientPlugin.js │ │ └── vizPageServerPlugin.js ├── vizhub-v2-false-start │ ├── .gitignore │ ├── README.md │ ├── deploy.sh │ ├── lerna.json │ ├── package.json │ └── packages │ │ ├── backend │ │ ├── .gitignore │ │ ├── package.json │ │ └── src │ │ │ ├── index.js │ │ │ ├── initializeSampleStudioData.js │ │ │ ├── serveFrontend.js │ │ │ ├── serveShareDB.js │ │ │ ├── serveStudioData.js │ │ │ └── snapshot.js │ │ ├── common │ │ ├── entities.dia │ │ ├── package.json │ │ ├── src │ │ │ ├── VizHubError.js │ │ │ ├── computeDiffOps.js │ │ │ ├── fork.js │ │ │ ├── index.js │ │ │ └── sampleStudioData │ │ │ │ ├── index.js │ │ │ │ ├── sampleCode.js │ │ │ │ ├── userData.js │ │ │ │ └── vizData.js │ │ └── test │ │ │ ├── computeDiffOps.js │ │ │ └── fork.js │ │ ├── forks-graph │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.html │ │ ├── index.js │ │ ├── metadata.json │ │ ├── package.json │ │ ├── rollup.config.js │ │ └── styles.css │ │ └── frontend │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── public │ │ ├── favicon.ico │ │ ├── fonts │ │ │ ├── DejaVuSansMonoArrowized.woff │ │ │ ├── DejaVuSansMonoLigaturized.woff │ │ │ ├── FiraCode.woff │ │ │ ├── FiraCodeArrowized.woff │ │ │ ├── Inconsolata-gArrowized.woff │ │ │ ├── Inconsolata-gLigaturized.woff │ │ │ ├── README.md │ │ │ ├── SourceCodeProArrowized.woff │ │ │ ├── SourceCodeProLigaturized.woff │ │ │ ├── UbuntuMonoArrowized.woff │ │ │ └── UbuntuMonoLigaturized.woff │ │ ├── index.html │ │ └── manifest.json │ │ ├── src │ │ ├── App.js │ │ ├── App.test.js │ │ ├── Home.js │ │ ├── LoadingScreen │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── Studio │ │ │ ├── Configurator │ │ │ │ ├── Foldable │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── Menu.js │ │ │ │ ├── RadioMenu.js │ │ │ │ ├── Section.js │ │ │ │ ├── index.js │ │ │ │ ├── sections │ │ │ │ │ ├── FilesSection │ │ │ │ │ │ ├── FileTree.js │ │ │ │ │ │ ├── getFileTree.js │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── PreferencesSection.js │ │ │ │ │ ├── SettingsSection.js │ │ │ │ │ ├── StateSection.js │ │ │ │ │ └── index.js │ │ │ │ ├── styles.js │ │ │ │ └── usePreloadFont.js │ │ │ ├── Editor │ │ │ │ ├── CodeMirror.js │ │ │ │ ├── EditorViewPool.js │ │ │ │ ├── PresenceDisplay │ │ │ │ │ ├── getFileId.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── css.js │ │ │ │ ├── extension.js │ │ │ │ ├── extension.test.js │ │ │ │ ├── index.js │ │ │ │ ├── presence.js │ │ │ │ ├── styles.js │ │ │ │ ├── useCodeMirror.js │ │ │ │ ├── useEditorView.js │ │ │ │ ├── useEditorView.test.js │ │ │ │ ├── useEditorViewPool.js │ │ │ │ ├── useEditorViewPool.test.js │ │ │ │ └── useMode.js │ │ │ ├── ErrorPage.js │ │ │ ├── StudioBody.js │ │ │ ├── Viewer │ │ │ │ ├── Actions │ │ │ │ │ ├── Action.js │ │ │ │ │ ├── Download.js │ │ │ │ │ ├── Edit.js │ │ │ │ │ ├── Fork.js │ │ │ │ │ ├── FullScreen.js │ │ │ │ │ ├── Share.js │ │ │ │ │ ├── UpvoteDownvote.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── Comments │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── ForkedFrom │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── Header │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── OwnerInfo │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── Runner │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── avatarUrl.js │ │ │ │ ├── formatViewCount.js │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── index.js │ │ │ ├── styles.js │ │ │ └── useEditorTheme.js │ │ ├── contexts │ │ │ ├── error │ │ │ │ └── index.js │ │ │ ├── index.js │ │ │ ├── preferences │ │ │ │ ├── index.js │ │ │ │ ├── options.js │ │ │ │ ├── preferencesMemoryGateway.js │ │ │ │ └── usePreference.js │ │ │ ├── studioData │ │ │ │ ├── actions.js │ │ │ │ ├── fetchStudioData.js │ │ │ │ ├── index.js │ │ │ │ ├── reducer.js │ │ │ │ ├── useStudioData.js │ │ │ │ └── wait.js │ │ │ ├── urlState │ │ │ │ ├── accessors.js │ │ │ │ ├── index.js │ │ │ │ └── withURLState.js │ │ │ └── viz │ │ │ │ ├── Viz.js │ │ │ │ ├── getConnection.js │ │ │ │ ├── index.js │ │ │ │ ├── useVizShareDB.js │ │ │ │ └── useVizStub.js │ │ ├── environment.js │ │ ├── index.js │ │ ├── styles.js │ │ ├── svg │ │ │ ├── ArrowBackSVG.js │ │ │ ├── CheckBoxSVG.js │ │ │ ├── CloseSVG.js │ │ │ ├── DownloadSVG.js │ │ │ ├── DownvoteSVG.js │ │ │ ├── EditSVG.js │ │ │ ├── FoldableArrowsSVG.js │ │ │ ├── ForkSVG.js │ │ │ ├── FullScreenSVG.js │ │ │ ├── LogoSVG.js │ │ │ ├── LogoSquareSVG.js │ │ │ ├── RadioButtonSVG.js │ │ │ ├── SVG.js │ │ │ ├── ShareSVG.js │ │ │ ├── UpvoteSVG.js │ │ │ └── index.js │ │ ├── testUtils │ │ │ └── codemirrorGlobalShim.js │ │ └── themes │ │ │ ├── dracula.js │ │ │ ├── index.js │ │ │ ├── light.js │ │ │ ├── material.js │ │ │ ├── monokai.js │ │ │ ├── oneDark.js │ │ │ └── ubuntu.js │ │ └── transferred.csv └── vizhub-v3-false-start │ ├── .gitignore │ ├── .prettierignore │ ├── README.md │ ├── buildCSS.js │ ├── deploy.sh │ ├── ecosystem.config.js │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── images │ │ └── touch │ │ │ └── logoBlackSquare.png │ └── manifest.json │ ├── rollup.config.js │ └── src │ ├── App │ ├── Navigation.js │ ├── VizPreview.js │ ├── classed.js │ ├── index.js │ ├── isClient.js │ └── pages │ │ ├── HomePage.js │ │ ├── SanityCheckPage.js │ │ ├── TestPage.js │ │ ├── VizNotFoundPage.js │ │ ├── VizPage.js │ │ └── index.js │ ├── client │ ├── RequireContext.js │ ├── client2.js │ ├── index.js │ ├── serviceWorker.js │ └── useModule.js │ ├── entities │ ├── User.js │ ├── VizInfo.js │ ├── createInstance.js │ └── vizInfoTest.js │ ├── globals.js │ ├── interactors │ ├── getHomePageData.js │ ├── getHomePageDataTest.js │ └── getVizPageData.js │ ├── pageData.js │ ├── pageDataTest.js │ ├── presenters │ ├── homePagePresenter.js │ ├── homePagePresenterTest.js │ ├── vizPagePresenter.js │ └── vizPagePresenterTest.js │ ├── server │ ├── database │ │ ├── databaseTest.js │ │ ├── generateId.js │ │ ├── index.js │ │ └── mongoMethods.js │ ├── index.js │ └── renderPage │ │ ├── index.js │ │ ├── indexHTML.js │ │ ├── renderPageTest.js │ │ └── renderPageTestExpected.html │ ├── styles │ ├── base.scss │ ├── home-page.scss │ ├── index.scss │ ├── link.scss │ ├── markdown-body.scss │ ├── navigation.scss │ ├── variables.scss │ ├── viz-page.scss │ └── viz-preview.scss │ ├── svg │ └── LogoSVG.js │ └── test.js ├── vizhub-v2 ├── .eslintignore ├── .gitignore ├── LICENSE ├── README.md ├── buildFrontend.sh ├── deploy.sh ├── deployFirstTime.sh ├── docs │ ├── blog.css │ ├── forum.css │ └── nginx.conf.sample ├── ecosystem.config.js ├── lerna.json ├── logo │ ├── favicon.ico │ ├── logo-XL.png │ ├── logo.svg │ ├── logoBlackSmall.png │ ├── logoBlackSquare.png │ ├── logoSquare.svg │ ├── logoSquare_large.png │ ├── logoWhiteSmall.png │ ├── logoWhiteSquare.png │ ├── mugDesign.png │ └── square Main Files-03.svg ├── package-lock.json ├── package.json └── packages │ ├── .gitignore │ ├── controllers │ ├── .eslintrc.js │ ├── package-lock.json │ ├── package.json │ └── src │ │ ├── Error │ │ ├── ErrorResponse.js │ │ ├── index.js │ │ ├── toErrorResponse.js │ │ └── toVizHubAPIError.js │ │ ├── apiController │ │ ├── datasetAPIController │ │ │ ├── createDatasetController.js │ │ │ ├── getDatasetController.js │ │ │ └── index.js │ │ ├── eventRecordsAPIController │ │ │ ├── getEventRecords.js │ │ │ ├── index.js │ │ │ └── sendEvent.js │ │ ├── index.js │ │ ├── paymentsAPIController │ │ │ ├── README.md │ │ │ └── index.js │ │ ├── userAPIController │ │ │ ├── getProfileDataController.js │ │ │ ├── getUserSearchResultsData.js │ │ │ ├── getUsers.js │ │ │ └── index.js │ │ └── visualizationAPIController │ │ │ ├── createVisualizationController.js │ │ │ ├── deleteVisualizationController.js │ │ │ ├── exportVisualizationController.js │ │ │ ├── forkVisualizationController.js │ │ │ ├── getAllVisualizationInfosController.js │ │ │ ├── getForksController.js │ │ │ ├── getHomePageDataController.js │ │ │ ├── getPreviewController.js │ │ │ ├── getPrivateVisualizationsController.js │ │ │ ├── getPublicVisualizationsController.js │ │ │ ├── getSearchResultsPageData.js │ │ │ ├── getSharedVisualizationsController.js │ │ │ ├── getTemplatesDataController.js │ │ │ ├── getThumbnailController.js │ │ │ ├── getVisualizationController.js │ │ │ ├── index.js │ │ │ └── saveVisualizationController.js │ │ ├── index.js │ │ ├── jwtAuth │ │ ├── getAccessToken.js │ │ ├── getFBAccessToken.js │ │ ├── getFBUser.js │ │ ├── getGitHubUser.js │ │ ├── getGoogleUser.js │ │ ├── getUserAvatar.js │ │ ├── index.js │ │ ├── jwt.js │ │ └── routes │ │ │ ├── authCI.js │ │ │ ├── authFB.js │ │ │ ├── authGitHub.js │ │ │ ├── authGoogle.js │ │ │ ├── authMe.js │ │ │ ├── authSignOut.js │ │ │ ├── createAuthController.js │ │ │ └── index.js │ │ ├── oembedController.js │ │ ├── plainText.js │ │ ├── sanitize.js │ │ ├── serveHomePage.js │ │ ├── servePage.js │ │ ├── serveVizPage.js │ │ ├── userController.js │ │ └── userIdFromReq.js │ ├── database │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── collectionName.js │ │ ├── constants.js │ │ ├── createUser.js │ │ ├── createVisualization.js │ │ ├── deleteVisualization.js │ │ ├── eventRecords.js │ │ ├── fetchShareDBDoc.js │ │ ├── fetchShareDBQuery.js │ │ ├── forksCount.js │ │ ├── getAllVisualizationInfos.js │ │ ├── getDataset.js │ │ ├── getDatasetInfosByUserId.js │ │ ├── getForks.js │ │ ├── getHomePageVisualizationInfos.js │ │ ├── getPreview.js │ │ ├── getThumbnail.js │ │ ├── getUser.js │ │ ├── getUserByEmail.js │ │ ├── getUserByEmailOrId.js │ │ ├── getUserByUserName.js │ │ ├── getUsers.js │ │ ├── getVisualization.js │ │ ├── getVisualizationInfo.js │ │ ├── getVisualizationInfos.js │ │ ├── getVisualizationInfosByUserId.js │ │ ├── index.js │ │ ├── save.js │ │ ├── saveUser.js │ │ ├── saveVisualization.js │ │ ├── searchUsers.js │ │ ├── searchVisualizationInfos.js │ │ ├── setImagesUpdatedTimestamp.js │ │ ├── updateImages.js │ │ └── updateScores.js │ └── test │ │ └── test.js │ ├── entities │ ├── .eslintrc.js │ ├── .gitignore │ ├── classDiagram.dia │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── VizHubAPIError.js │ │ ├── ciUser.js │ │ ├── commit.js │ │ ├── dataset.js │ │ ├── datasetContent.js │ │ ├── datasetInfo.js │ │ ├── documentContent.js │ │ ├── documentInfo.js │ │ ├── documentPart.js │ │ ├── documentTypes.js │ │ ├── edge.js │ │ ├── file.js │ │ ├── index.js │ │ ├── testData.js │ │ ├── timestamp.js │ │ ├── user.js │ │ ├── visualization.js │ │ ├── visualizationContent.js │ │ └── visualizationInfo.js │ └── test │ │ ├── revisionHistory.js │ │ └── test.js │ ├── gateways │ ├── .eslintrc.js │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── databaseDatasetGateway.js │ │ ├── databaseEventRecordsGateway.js │ │ ├── databaseImageStorageGateway.js │ │ ├── databaseUserGateway.js │ │ ├── databaseVisualizationGateway.js │ │ └── index.js │ └── test │ │ └── test.js │ ├── i18n │ ├── index.js │ └── package.json │ ├── imageGenerationService │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── computeImageDimensions.js │ │ ├── dimensions.js │ │ ├── generateImages.js │ │ ├── generateScreenshot.js │ │ ├── index.js │ │ ├── resize.js │ │ └── service.js │ └── test │ │ ├── expectedImages.js │ │ └── test.js │ ├── json0-with-presence │ ├── index.js │ ├── package-lock.json │ └── package.json │ ├── neoBackend │ ├── .eslintrc.js │ ├── .gitignore │ ├── README.md │ ├── package.json │ └── src │ │ ├── index.js │ │ ├── serveFrontend.js │ │ └── serveShareDB │ │ ├── index.js │ │ └── shareDBMiddleware │ │ ├── accessControl │ │ ├── getVizInfo.js │ │ ├── index.js │ │ ├── vizRead.js │ │ └── vizWrite.js │ │ ├── identifyAgent.js │ │ └── index.js │ ├── neoCI │ ├── .eslintrc.js │ ├── .gitignore │ ├── package-lock.json │ ├── package.json │ └── test │ │ ├── authentication │ │ ├── index.js │ │ ├── navigateToAuthPage.js │ │ ├── signIn.js │ │ └── signOut.js │ │ ├── editorStates │ │ ├── closeMobilePage.js │ │ ├── codeEditorIndependence.js │ │ ├── getPage.js │ │ ├── index.js │ │ ├── openMobilePage.js │ │ ├── restoreEditorSection.js │ │ ├── toggleCodeEditor.js │ │ ├── toggleEditor.js │ │ ├── toggleFullEditor.js │ │ ├── toggleFullScreen.js │ │ ├── toggleMini.js │ │ └── verifyHomeState.js │ │ ├── navClick.js │ │ ├── openPage.js │ │ ├── privacy │ │ ├── excludePrivateFromHomePage.js │ │ ├── excludePrivateFromPage.js │ │ ├── excludePrivateFromProfilePage.js │ │ ├── forkToPrivate.js │ │ ├── getVizIdList.js │ │ ├── goToHomeState.js │ │ ├── includePrivateOnProfilePage.js │ │ ├── index.js │ │ ├── setupPrivateViz.js │ │ ├── shareDBBlockReads.js │ │ ├── switchPrivacy.js │ │ ├── vizFound.js │ │ └── vizNotFound.js │ │ ├── realtime │ │ ├── index.js │ │ ├── saveAndRestoreChanges.js │ │ └── setupRealtimeViz.js │ │ ├── retry.js │ │ ├── test.js │ │ ├── toPort.js │ │ └── vizCreation │ │ ├── createVizFromScratch.js │ │ ├── fork.js │ │ ├── index.js │ │ └── navigateToCreateVizPage.js │ ├── neoFrontend │ ├── .eslintrc.json │ ├── .gitignore │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── images │ │ │ ├── GitHub-Mark-120px-plus.png │ │ │ ├── mountains.png │ │ │ └── unfurl-logo.png │ │ ├── index.html │ │ ├── manifest.json │ │ └── terms.md │ ├── scripts │ │ └── server.js │ └── src │ │ ├── AlertDialogContext │ │ └── index.js │ │ ├── App.js │ │ ├── Author │ │ ├── index.js │ │ └── styles.js │ │ ├── Avatar │ │ ├── index.js │ │ └── styles.js │ │ ├── Button │ │ └── index.js │ │ ├── ConnectionContext │ │ ├── createWebSocket.js │ │ ├── index.js │ │ └── useConnection.js │ │ ├── ErrorContext │ │ └── index.js │ │ ├── ExitableWrapper.js │ │ ├── ForksLink │ │ ├── index.js │ │ └── styles.js │ │ ├── Input │ │ ├── Autocomplete.js │ │ ├── Input.js │ │ ├── PreviewList.js │ │ ├── index.js │ │ ├── styles.js │ │ └── usePreviewController.js │ │ ├── LoadingScreen │ │ ├── animationDelay.js │ │ ├── index.js │ │ ├── styles.js │ │ └── waitForSpinner.js │ │ ├── Modal │ │ ├── index.js │ │ └── styles.js │ │ ├── NavBar │ │ ├── NeoNavBar │ │ │ ├── DesktopLayout │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── MobileLayout │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── Search │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── UserActionsMenu │ │ │ │ ├── arrowDown.svg │ │ │ │ ├── index.js │ │ │ │ ├── styles.js │ │ │ │ └── useCloseOnGlobalClick.js │ │ │ ├── index.js │ │ │ └── styles.js │ │ └── index.js │ │ ├── PrivacyNotice │ │ ├── index.js │ │ └── styles.js │ │ ├── RealtimeModulesContext │ │ ├── index.js │ │ ├── realtimeModules.js │ │ └── useRealtimeModules.js │ │ ├── SavingIndicator │ │ ├── index.js │ │ └── styles.js │ │ ├── UserPreviewList │ │ ├── UserPreviewList.js │ │ ├── fetchUserSearchResults.js │ │ ├── index.js │ │ ├── styles.js │ │ ├── useUserPreviewController.js │ │ └── useUsers.js │ │ ├── VizPreview │ │ ├── LiveVizPreview.js │ │ ├── VizPreview.js │ │ ├── index.js │ │ └── styles.js │ │ ├── VizzesGrid │ │ ├── Vizzes │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── VizzesSortForm │ │ │ ├── VizzesSortForm.js │ │ │ ├── index.js │ │ │ ├── selectArrow.svg │ │ │ ├── styles.js │ │ │ └── useVizzesSort.js │ │ └── usePaginatedVizzes.js │ │ ├── Voter │ │ ├── index.js │ │ └── styles.js │ │ ├── WarningContext │ │ └── index.js │ │ ├── authentication │ │ ├── AuthContext │ │ │ ├── fetchMe.js │ │ │ └── index.js │ │ ├── constants.js │ │ ├── getJWT.js │ │ ├── getJWTForGoogle.js │ │ ├── index.js │ │ ├── postMessageToOpener.js │ │ ├── signInFlow │ │ │ ├── index.js │ │ │ ├── listenForMe.js │ │ │ └── openPopup.js │ │ └── signOutFlow │ │ │ ├── fetchSignOut.js │ │ │ └── index.js │ │ ├── constants.js │ │ ├── featureFlags.js │ │ ├── index.js │ │ ├── mobileMods.js │ │ ├── pages │ │ ├── AccountPage │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── AuthPage │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── AuthPopupPage │ │ │ ├── index.js │ │ │ ├── useOpener.js │ │ │ └── useTokenGetter.js │ │ ├── ContactPage │ │ │ └── index.js │ │ ├── CreateVizPage │ │ │ ├── CuratedVizzes.js │ │ │ ├── FromScratchSection.js │ │ │ ├── index.js │ │ │ ├── styles.js │ │ │ ├── useTemplates.js │ │ │ └── vizLists.js │ │ ├── CreatingVizFromScratchPage │ │ │ ├── createVizFromScratch.js │ │ │ ├── fetchCreateVizFromScratch.js │ │ │ └── index.js │ │ ├── Datavis2020Page │ │ │ ├── data.js │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── ErrorPage │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── ForksPage │ │ │ ├── fetchPageData.js │ │ │ ├── index.js │ │ │ ├── styles.js │ │ │ └── usePageData.js │ │ ├── HomePage │ │ │ ├── Banner │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── EventBanner │ │ │ │ └── index.js │ │ │ ├── HomePageDataContext.js │ │ │ ├── Sort │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── Vizzes.js │ │ │ ├── fetchHomePageData.js │ │ │ ├── index.js │ │ │ ├── styles.js │ │ │ └── useHomePageData.js │ │ ├── NotFoundPage │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── PricingPage │ │ │ ├── featuresAndPlans.js │ │ │ ├── index.js │ │ │ ├── stripe.js │ │ │ └── styles.js │ │ ├── ProfilePage │ │ │ ├── Body │ │ │ │ ├── createVizzFetcherHook.js │ │ │ │ ├── index.js │ │ │ │ ├── styles.js │ │ │ │ ├── usePrivateVizFetcher.js │ │ │ │ ├── useProfileVizzes.js │ │ │ │ ├── usePublicVizFetcher.js │ │ │ │ └── useSharedVizFetcher.js │ │ │ ├── LinkWithIcon │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── ProfilePageDataContext │ │ │ │ ├── fetchProfilePageData.js │ │ │ │ ├── index.js │ │ │ │ └── useProfilePageData.js │ │ │ ├── ProfilePane │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── index.js │ │ │ ├── profilepage.test.js │ │ │ └── styles.js │ │ ├── SearchResultsPage │ │ │ ├── PageDataContext.js │ │ │ ├── Vizzes.js │ │ │ ├── fetchPageData.js │ │ │ ├── index.js │ │ │ └── usePageData.js │ │ ├── TermsPage │ │ │ └── index.js │ │ ├── UpgradeCanceledPage │ │ │ └── index.js │ │ ├── UpgradeSuccessPage │ │ │ ├── index.js │ │ │ ├── styles.js │ │ │ └── useCheckoutSession.js │ │ ├── VizHubStatsPage │ │ │ ├── RecordViz │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── VizPage │ │ │ ├── Body │ │ │ │ ├── Editor │ │ │ │ │ ├── BottomButtons │ │ │ │ │ │ ├── DeleteTop.js │ │ │ │ │ │ ├── ExportTop.js │ │ │ │ │ │ ├── NewTop.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── styles.js │ │ │ │ │ ├── CodeEditor │ │ │ │ │ │ ├── CodeArea │ │ │ │ │ │ │ ├── CodeAreaCodeMirror5 │ │ │ │ │ │ │ │ ├── CodeMirrorCSS.js │ │ │ │ │ │ │ │ ├── CodeMirrorDialogCSS.js │ │ │ │ │ │ │ │ ├── CodeMirrorGlobalStyle.js │ │ │ │ │ │ │ │ ├── CodeMirrorHintCSS.js │ │ │ │ │ │ │ │ ├── CodeMirrorLintCSS.js │ │ │ │ │ │ │ │ ├── CodeMirrorReactBinding.js │ │ │ │ │ │ │ │ ├── PresenceWidget │ │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ │ └── styles.js │ │ │ │ │ │ │ │ ├── changeObjToOp.js │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ ├── overlays │ │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ │ └── linkOverlay.js │ │ │ │ │ │ │ │ ├── styles.js │ │ │ │ │ │ │ │ └── useStateLocalStorage.js │ │ │ │ │ │ │ ├── CodeAreaPre │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ └── styles.js │ │ │ │ │ │ │ ├── CodeAreaTextarea │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ └── styles.js │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── CodeEditorHeader │ │ │ │ │ │ │ ├── Header.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── styles.js │ │ │ │ │ │ ├── CodeSnippet.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── styles.js │ │ │ │ │ │ ├── useFileIndex.js │ │ │ │ │ │ ├── usePath.js │ │ │ │ │ │ └── useUpdateURLOnRename.js │ │ │ │ │ ├── FilesSection │ │ │ │ │ │ ├── EditableFileEntry │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ └── styles.js │ │ │ │ │ │ ├── FileTree │ │ │ │ │ │ │ ├── Directory │ │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ │ └── styles.js │ │ │ │ │ │ │ ├── File.js │ │ │ │ │ │ │ ├── addPath.js │ │ │ │ │ │ │ ├── getFileTree.js │ │ │ │ │ │ │ ├── getFileTree.test.js │ │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ │ ├── sortFileTree.js │ │ │ │ │ │ │ └── styles.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── initialOpenDirectories.js │ │ │ │ │ │ ├── styles.js │ │ │ │ │ │ ├── useCreateNewFile.js │ │ │ │ │ │ ├── useOpenDirectories.js │ │ │ │ │ │ └── useRenameActiveFile.js │ │ │ │ │ ├── Section │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── styles.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── styles.js │ │ │ │ │ ├── themes │ │ │ │ │ │ ├── dracula.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── light.js │ │ │ │ │ │ ├── material.js │ │ │ │ │ │ ├── monokai.js │ │ │ │ │ │ ├── oneDark.js │ │ │ │ │ │ ├── ubuntu.js │ │ │ │ │ │ └── vizHub.js │ │ │ │ │ └── useEditorTheme.js │ │ │ │ ├── EditorModePresenter.js │ │ │ │ ├── EmbedModePresenter.js │ │ │ │ ├── FullScreen │ │ │ │ │ ├── EmbedFooter │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── styles.js │ │ │ │ │ ├── FullScreen.js │ │ │ │ │ ├── FullScreenFooter.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── FullScreenModePresenter.js │ │ │ │ ├── Head │ │ │ │ │ ├── EditorToggler │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── styles.js │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── MicroConsole │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── Mini │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── PlayPauseControl │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── RecoveryModeBanner │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── SnippetModePresenter.js │ │ │ │ ├── TrashIcon.js │ │ │ │ ├── Viewer │ │ │ │ │ ├── DescriptionSection │ │ │ │ │ │ ├── Forks.js │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── renderMarkdown.js │ │ │ │ │ │ ├── responsiveYouTube.js │ │ │ │ │ │ └── styles.js │ │ │ │ │ ├── GlobalScrollbarStyle.js │ │ │ │ │ ├── Resizer │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── styles.js │ │ │ │ │ ├── TitleBar │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── styles.js │ │ │ │ │ ├── VizFrame │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ └── styles.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── styles.js │ │ │ │ │ └── useLicenseToHtmlRenderer.js │ │ │ │ ├── index.js │ │ │ │ ├── styles.js │ │ │ │ ├── useDimensions │ │ │ │ │ ├── index.js │ │ │ │ │ └── useDimensionsDetector.js │ │ │ │ └── useListener.js │ │ │ ├── CheckBox │ │ │ │ └── index.js │ │ │ ├── DeleteVizContext │ │ │ │ ├── fetchDeleteViz.js │ │ │ │ ├── index.js │ │ │ │ └── useDeleteViz.js │ │ │ ├── EditorModulesContext │ │ │ │ ├── codemirrorAddons │ │ │ │ │ ├── highlightLinesDocExtentions.js │ │ │ │ │ └── lint │ │ │ │ │ │ ├── eslintrc.js │ │ │ │ │ │ └── jsxLint.js │ │ │ │ ├── editorModules.js │ │ │ │ ├── index.js │ │ │ │ └── useEditorModules.js │ │ │ ├── ForkingContext │ │ │ │ ├── fetchFork.js │ │ │ │ ├── index.js │ │ │ │ └── useForking.js │ │ │ ├── PrettierContext │ │ │ │ ├── index.js │ │ │ │ ├── prettierModules.js │ │ │ │ └── usePrettier.js │ │ │ ├── RadioButton │ │ │ │ ├── index.js │ │ │ │ └── styles.js │ │ │ ├── RunContext │ │ │ │ ├── createChangesChecker.js │ │ │ │ ├── generateRunId.js │ │ │ │ ├── index.js │ │ │ │ ├── onlyBundleJSChanged.js │ │ │ │ ├── updateBundleIfNeeded.js │ │ │ │ ├── updateDescriptionIfNeeded.js │ │ │ │ ├── updateLastUpdatedTimestamp.js │ │ │ │ ├── updateTitleIfNeeded.js │ │ │ │ ├── useRun.js │ │ │ │ └── useVizContentDoc.js │ │ │ ├── SettingsContext │ │ │ │ ├── SetHeight │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── index.js │ │ │ │ ├── styles.js │ │ │ │ └── useSettings.js │ │ │ ├── ShareContext │ │ │ │ ├── CollaboratorsBody │ │ │ │ │ ├── AnyoneCanEdit.js │ │ │ │ │ ├── Collaborator │ │ │ │ │ │ ├── index.js │ │ │ │ │ │ ├── styles.js │ │ │ │ │ │ └── useCache.js │ │ │ │ │ ├── CollaboratorList.js │ │ │ │ │ ├── fetchUser.js │ │ │ │ │ ├── fetchUsers.js │ │ │ │ │ ├── index.js │ │ │ │ │ ├── styles.js │ │ │ │ │ └── useCollaborators.js │ │ │ │ ├── EmbedBody │ │ │ │ │ └── index.js │ │ │ │ ├── LinkBody │ │ │ │ │ └── index.js │ │ │ │ ├── SnippetBody │ │ │ │ │ └── index.js │ │ │ │ ├── Tabs │ │ │ │ │ ├── index.js │ │ │ │ │ └── styles.js │ │ │ │ ├── TextCopier.js │ │ │ │ ├── index.js │ │ │ │ ├── styles.js │ │ │ │ └── useShare.js │ │ │ ├── SplitPaneResizeContext │ │ │ │ └── index.js │ │ │ ├── URLStateContext │ │ │ │ ├── index.js │ │ │ │ ├── modes.js │ │ │ │ ├── reducer.js │ │ │ │ ├── useURLState.js │ │ │ │ └── useURLStateReducer.js │ │ │ ├── VimModeContext │ │ │ │ ├── index.js │ │ │ │ └── useVimMode.js │ │ │ ├── VizContext │ │ │ │ └── index.js │ │ │ ├── VizPageDataContext │ │ │ │ ├── fetchVizPageData.js │ │ │ │ ├── index.js │ │ │ │ └── useVizPageData.js │ │ │ ├── VizRunnerContext │ │ │ │ ├── generateErrorMessageSrcDoc.js │ │ │ │ ├── generateRunErrorMessage.js │ │ │ │ ├── index.js │ │ │ │ └── setVizRunnerMode.js │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── fakeDataLoaded.js │ │ ├── index.js │ │ └── styles.js │ │ ├── sendEvent.js │ │ ├── styles.js │ │ ├── svg │ │ ├── ArrowSVG.js │ │ ├── CloseSVG.js │ │ ├── DirectoryArrowSVG.js │ │ ├── ExportSVG.js │ │ ├── ForkSVG.js │ │ ├── FullExitSVG.js │ │ ├── FullSVG.js │ │ ├── LockOpenSVG.js │ │ ├── LockSVG.js │ │ ├── LogoSVG.js │ │ ├── MicroSVG.js │ │ ├── MiniSVG.js │ │ ├── NewSVG.js │ │ ├── PeopleSVG.js │ │ ├── PlanExcludedSVG.js │ │ ├── PlanIncludedSVG.js │ │ ├── PlayPauseSVG.js │ │ ├── PrettierSVG.js │ │ ├── PullSVG.js │ │ ├── RadioButtonSVG.js │ │ ├── SearchSVG.js │ │ ├── SettingsSVG.js │ │ ├── ShareSVG.js │ │ ├── SharedWithMeSVG.js │ │ ├── SpinnerSVG.js │ │ ├── SplitSVG.js │ │ ├── TrashSVG.js │ │ ├── VimSVG.js │ │ ├── VoteSVG.js │ │ ├── index.js │ │ └── svgGallery.js │ │ ├── theme │ │ ├── defaultTheme.js │ │ ├── index.js │ │ ├── neoTheme.js │ │ └── text.js │ │ ├── useSearchQuery.js │ │ ├── useValue.js │ │ ├── utils │ │ ├── array.js │ │ ├── css │ │ │ └── index.js │ │ ├── number.js │ │ ├── object.js │ │ └── viz.js │ │ └── vizRealTimeHooks │ │ ├── index.js │ │ ├── useOpSourceTracker.js │ │ ├── useOpStream.js │ │ ├── usePending.js │ │ ├── usePresence.js │ │ ├── usePresenceStream.js │ │ ├── useShareDBDoc.js │ │ ├── useSubmitOp.js │ │ ├── useSubmitPresence.js │ │ ├── useViz.js │ │ └── useVizInfo.js │ ├── presenters │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── accessors.js │ │ ├── bubleJSXOnly.js │ │ ├── bundle.js │ │ ├── computeSrcDoc.js │ │ ├── datasetViewModel.js │ │ ├── featureFlags.js │ │ ├── getComputedIndexHtml.js │ │ ├── getLibraries.js │ │ ├── hypothetical.js │ │ ├── index.js │ │ ├── magicSandbox.js │ │ ├── packageJson.js │ │ ├── rollup.browser.js │ │ ├── svelte.js │ │ └── visualizationViewModel.js │ └── test │ │ └── test.js │ ├── scoringService │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── index.js │ │ └── service.js │ └── test │ │ └── test.js │ ├── serverGateways │ ├── .gitignore │ ├── package-lock.json │ ├── package.json │ └── src │ │ ├── constants.js │ │ ├── index.js │ │ ├── mongodb.js │ │ └── shareDB.js │ └── useCases │ ├── .eslintrc.js │ ├── createVisualization.md │ ├── docs │ ├── useCaseTemplate.md │ └── useCasesDiagram.dia │ ├── package-lock.json │ ├── package.json │ ├── saveVisualization.md │ ├── src │ ├── accessControl │ │ ├── allowRead.js │ │ ├── allowWrite.js │ │ ├── index.js │ │ ├── isCollaborator.js │ │ └── isOwner.js │ ├── index.js │ ├── interactors │ │ ├── createCommit.js │ │ ├── createDataset │ │ │ ├── datasetDefaults.js │ │ │ └── index.js │ │ ├── createEdge.js │ │ ├── createUser.js │ │ ├── createVisualization │ │ │ ├── index.js │ │ │ └── visualizationDefaults.js │ │ ├── deleteVisualization.js │ │ ├── exportVisualization │ │ │ ├── index.js │ │ │ └── zipFiles.js │ │ ├── forkVisualization.js │ │ ├── getAllVisualizationInfos.js │ │ ├── getDataset.js │ │ ├── getEventRecords.js │ │ ├── getForks.js │ │ ├── getForksPageData.js │ │ ├── getHomePageData.js │ │ ├── getOrCreateUser.js │ │ ├── getPreview.js │ │ ├── getSearchResultsPageData.js │ │ ├── getThumbnail.js │ │ ├── getUser.js │ │ ├── getUserByEmail.js │ │ ├── getUserByEmailOrId.js │ │ ├── getUserProfileData.js │ │ ├── getUserSearchResultsData.js │ │ ├── getUsers.js │ │ ├── getVisualization.js │ │ ├── getVisualizationInfo.js │ │ ├── getVisualizationInfos.js │ │ ├── getVisualizationsOwners.js │ │ ├── getVizAtCommit.js │ │ ├── index.js │ │ ├── saveVisualization.js │ │ ├── sendEvent.js │ │ ├── updateImages.js │ │ ├── updateScores.js │ │ ├── updateUser.js │ │ └── upgradeUser.js │ └── utils │ │ ├── generateId.js │ │ └── removeExtension.js │ └── test │ ├── eventRecords.js │ ├── revisionHistory.js │ └── test.js └── vizhub-v3 ├── Dockerfile ├── README.md ├── package-lock.json ├── package.json ├── vizhub-app ├── .dockerignore ├── .gitignore ├── .prettierignore ├── babel.config.json ├── deploy.sh ├── package.json ├── public │ └── favicon.ico ├── rollup.config.mjs ├── scss │ ├── _home-page.scss │ ├── _profile-page.scss │ ├── _spinner.scss │ ├── _variables.scss │ ├── _viz-page.scss │ ├── _viz-preview.scss │ ├── _vizhub-banner.scss │ └── vizhub-app.scss └── src │ ├── App.js │ ├── client.js │ ├── environment.js │ ├── featureFlags.js │ ├── jsDelivrCombine.js │ ├── presenters │ ├── HomePagePresenter │ │ ├── index.js │ │ └── useVizInfos.js │ ├── LogInWidgetPresenter.js │ ├── LoginPagePresenter │ │ └── index.js │ ├── VizPagePresenter │ │ ├── CodeEditor.js │ │ ├── index.js │ │ ├── useEditorModules.js │ │ └── useViz.js │ ├── index.js │ ├── logShareDBError.js │ └── useShareDBConnection.js │ ├── queries.js │ ├── server │ ├── authentication.js │ ├── html.js │ ├── index.js │ ├── pages.js │ └── vizBot.js │ └── ui │ ├── AuthenticatedUserDropdown.js │ ├── Bootstrap.js │ ├── DemoApp │ ├── MarkdownExample.js │ └── index.js │ ├── ForkModal.js │ ├── HomePage.js │ ├── Layout.js │ ├── Navigation.js │ ├── ProfilePage.js │ ├── README.md │ ├── ShareModal.js │ ├── Spinner.js │ ├── VizPage.js │ ├── VizPreview.js │ └── index.js ├── vizhub-build ├── .prettierignore ├── index.js └── package.json ├── vizhub-codemirror ├── .gitignore ├── .prettierignore ├── README.md ├── index.html ├── package.json ├── rollup.config.mjs └── src │ ├── index.js │ ├── server.js │ └── vizhubHighlightStyle.js ├── vizhub-entities ├── .prettierignore ├── package.json └── src │ ├── entities.ts │ └── index.ts ├── vizhub-interactors ├── .eslintignore ├── .eslintrc.cjs ├── .prettierignore ├── babel.config.json ├── constants.js ├── package.json ├── rollup.config.js ├── src │ ├── DatabaseGateways.ts │ ├── DatabaseGatewaysConstants.ts │ ├── DeleteViz.ts │ ├── FindOrCreateUser.ts │ ├── ForkViz.ts │ ├── Gateways.ts │ ├── GetVizSnapshot.ts │ ├── MemoryGateways.ts │ ├── SaveViz.ts │ ├── errorCodes.ts │ ├── errors.ts │ ├── generateRandomId.js │ ├── index.ts │ └── ot.ts └── test │ ├── DeleteVizTest.ts │ ├── FindOrCreateUserTest.ts │ ├── ForkVizTest.ts │ ├── GatewaysTest.ts │ ├── fixtures.ts │ ├── initGateways.ts │ └── test.ts ├── vizhub-runtime ├── .prettierignore ├── README.md ├── package-lock.json ├── package.json ├── rollup.config.mjs ├── src │ ├── Runner.js │ ├── build.js │ ├── cdn.js │ ├── constants.js │ ├── generateSrcdoc.js │ ├── getGlobals.js │ ├── index.js │ └── virtual.js └── test │ ├── expectedValues │ ├── index.js │ ├── modules.js │ ├── singleFileUMD.js │ ├── srcdocCodeAndConfig.js │ ├── srcdocCodeAndDependencies.js │ └── srcdocCodeOnly.js │ ├── index.js │ └── updateExpectedSrcdocValue.js └── vizhub-ui ├── .gitignore ├── .prettierignore ├── README.md ├── babel.config.json ├── deployment.md ├── icons ├── Arrow.svg ├── README.md ├── chevron.svg ├── close.svg ├── download.svg ├── exit-fullscreen.svg ├── fork.svg ├── fullscreen.svg ├── gear.svg ├── mini-mode.svg ├── new.svg ├── pause.svg ├── play.svg ├── side-by-side-mode.svg ├── trash.svg ├── upload.svg └── upvote.svg ├── index.html ├── package.json └── scss ├── _buttons.scss ├── _forms.scss ├── _icons.scss ├── _markdown-body.scss ├── _modal.scss ├── _nav.scss ├── _navbar.scss ├── _overrides.scss ├── _root.scss ├── _util.scss ├── _variables.scss └── vizhub-ui.scss /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | *.swp 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vizhub-v3/codemirror-ot"] 2 | path = vizhub-v3/codemirror-ot 3 | url = git@github.com:vizhub-core/codemirror-ot.git 4 | -------------------------------------------------------------------------------- /prototypes/babelInBrowser/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [], 3 | "plugins": ["@babel/plugin-syntax-jsx", "@babel/plugin-transform-react-jsx"] 4 | } 5 | -------------------------------------------------------------------------------- /prototypes/babelInBrowser/index.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /prototypes/babelInBrowser/index.js: -------------------------------------------------------------------------------- 1 | import * as babel from "@babel/core"; 2 | 3 | console.log(babel); 4 | 5 | -------------------------------------------------------------------------------- /prototypes/gist-fetching/.prettierignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .prettierignore 3 | build 4 | package-lock.json 5 | *.swp 6 | *.map 7 | *.svg 8 | *.ico 9 | -------------------------------------------------------------------------------- /prototypes/gist-fetching/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/gist-fetching/public/favicon.ico -------------------------------------------------------------------------------- /prototypes/idealExport/.prettierignore: -------------------------------------------------------------------------------- 1 | .prettierignore 2 | *.swp 3 | *.csv 4 | -------------------------------------------------------------------------------- /prototypes/idealExport/README.md: -------------------------------------------------------------------------------- 1 | An implementation of the [Keeling Curve](https://en.wikipedia.org/wiki/Keeling_Curve). 2 | 3 | Data: [NOAA Mauna Loa CO2 records](https://gml.noaa.gov/ccgg/trends/data.html). 4 | -------------------------------------------------------------------------------- /prototypes/idealExport/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [], 3 | "plugins": ["@babel/plugin-syntax-jsx", "@babel/plugin-transform-react-jsx"] 4 | } 5 | -------------------------------------------------------------------------------- /prototypes/idealExport/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Keeling Curve 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /prototypes/idealExport/rollup.config.js: -------------------------------------------------------------------------------- 1 | import { babel } from '@rollup/plugin-babel'; 2 | 3 | export default { 4 | input: 'index.js', 5 | external: ['d3', 'react', 'react-dom', 'three'], 6 | output: { 7 | file: 'bundle.js', 8 | format: 'iife', 9 | sourcemap: true, 10 | globals: { 11 | d3: 'd3', 12 | react: 'React', 13 | 'react-dom': 'ReactDOM', 14 | three: 'THREE', 15 | }, 16 | }, 17 | plugins: [babel({ babelHelpers: 'bundled' })], 18 | }; 19 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | *.swp 4 | *.rdb 5 | /packages/vizhub-ce/build 6 | /packages/vizhub-ce/build 7 | /packages/vizhub-ce/public/build 8 | /packages/vizhub-ee/ 9 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/.prettierignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.png 3 | *.ico 4 | *.map 5 | *.rdb 6 | .* 7 | packages/vizhub-*/build 8 | packages/vizhub-*/public/build 9 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-ce/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/open-core-first-attempt/packages/vizhub-ce/public/favicon.ico -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-ce/public/images/touch/logoBlackSquare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/open-core-first-attempt/packages/vizhub-ce/public/images/touch/logoBlackSquare.png -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-ce/src/client.js: -------------------------------------------------------------------------------- 1 | import { client, homePageClientPlugin } from 'vizhub-core/client'; 2 | 3 | import { vizPageClientPlugin } from 'vizhub-plugin-viz-page/client'; 4 | 5 | const plugins = [homePageClientPlugin(), vizPageClientPlugin()]; 6 | 7 | client(plugins); 8 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-ce/src/server.js: -------------------------------------------------------------------------------- 1 | import { server, homePageServerPlugin } from 'vizhub-core/server'; 2 | import { vizPageServerPlugin } from 'vizhub-plugin-viz-page/server'; 3 | import { accessControlServerPlugin } from 'vizhub-plugin-access-control/server'; 4 | 5 | const plugins = [ 6 | homePageServerPlugin(), 7 | vizPageServerPlugin(), 8 | accessControlServerPlugin(), 9 | ]; 10 | 11 | server(plugins); 12 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-ce/src/styles.scss: -------------------------------------------------------------------------------- 1 | @use '../vizhub-core/src/styles/index'; 2 | @use '../vizhub-plugin-viz-page/src/styles'; 3 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-ce/src/test.js: -------------------------------------------------------------------------------- 1 | import { coreTests } from 'vizhub-core/coreTests'; 2 | 3 | coreTests(); 4 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/client.js: -------------------------------------------------------------------------------- 1 | // This file is here as a package entry point, to support 2 | // tree shaking for independent builds. For example: 3 | // import { ... } from 'vizhub-core/client'; 4 | export { client } from './src/client'; 5 | export { homePageClientPlugin } from './src/plugins/homePagePlugin/client'; 6 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/coreTests.js: -------------------------------------------------------------------------------- 1 | // This file is here as a package entry point, to support 2 | // tree shaking for independent builds. For example: 3 | // import { ... } from 'vizhub-core/coreTests'; 4 | export { coreTests } from './src/coreTests'; 5 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/index.js: -------------------------------------------------------------------------------- 1 | export { 2 | jsDelivrCombine, 3 | App, 4 | indexHTML, 5 | isClient, 6 | classed, 7 | URLStateContext, 8 | } from './src/isomorphic'; 9 | 10 | export { VizInfo, getHeight, VizContent, getFileText } from './src/entities'; 11 | 12 | // TODO move this out of core. Maybe separate package for icon assets? 13 | export { ArrowSVG } from './src/svg'; 14 | 15 | export { VizHubError } from './VizHubError'; 16 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vizhub-core", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "src/index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Tests run inside the vizhub-ce package.\" && exit 1" 9 | }, 10 | "author": "Curran Kelleher", 11 | "license": "MIT", 12 | "dependencies": { 13 | "sharedb": "^1.9.1" 14 | }, 15 | "devDependencies": { 16 | "rollup": "^2.53.3" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/server.js: -------------------------------------------------------------------------------- 1 | // This file is here as a package entry point, to support 2 | // tree shaking for independent builds. For example: 3 | // import { ... } from 'vizhub-core/server'; 4 | export { server } from './src/server'; 5 | export { getShareDBSnapshot } from './src/server/getShareDBSnapshot'; 6 | export { homePageServerPlugin } from './src/plugins/homePagePlugin/server'; 7 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/src/client/index.js: -------------------------------------------------------------------------------- 1 | import { App } from '../isomorphic/App'; 2 | import { getPages } from '../isomorphic/getPages'; 3 | 4 | export const client = (clientPlugins) => { 5 | ReactDOM.hydrate( 6 | , 7 | document.getElementById('root') 8 | ); 9 | }; 10 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/src/entities/index.js: -------------------------------------------------------------------------------- 1 | export { VizInfo, getHeight } from './VizInfo'; 2 | export { VizContent, getFileText } from './VizContent'; 3 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/src/isomorphic/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { URLStateContextProvider } from './URLStateContext'; 3 | 4 | export const App = ({ pageData, pages, ssrQuery }) => { 5 | const { pageName, pageProps } = pageData; 6 | const PageComponent = pages.get(pageName); 7 | 8 | return ( 9 | 10 | 11 | 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/src/isomorphic/classed.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | // Generates a component that's a div (or specified tagName) with a class. 4 | export const classed = 5 | (className, type = 'div') => 6 | (props) => 7 | React.createElement(type, { className, ...props }, props.children); 8 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/src/isomorphic/getPages.js: -------------------------------------------------------------------------------- 1 | export const getPages = (plugins) => 2 | new Map( 3 | plugins 4 | .filter(({ pageComponent }) => pageComponent) 5 | .map(({ pageComponent }) => [pageComponent.name, pageComponent]) 6 | ); 7 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/src/isomorphic/index.js: -------------------------------------------------------------------------------- 1 | export { jsDelivrCombine } from './jsDelivrCombine'; 2 | export { App } from './App'; 3 | export { indexHTML } from './indexHTML'; 4 | export { isClient } from './isClient'; 5 | export { classed } from './classed'; 6 | export { URLStateContext } from './URLStateContext'; 7 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/src/isomorphic/isClient.js: -------------------------------------------------------------------------------- 1 | // True if the app is running in the client. 2 | // False if the app is running in the server (server side rendering). 3 | export const isClient = typeof window !== 'undefined'; 4 | -------------------------------------------------------------------------------- /prototypes/open-core-first-attempt/packages/vizhub-core/src/isomorphic/jsDelivrCombine.js: -------------------------------------------------------------------------------- 1 | // Constructs the src attribute of a 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/forks-graph/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "rollup -c" 4 | }, 5 | "devDependencies": { 6 | "rollup": "latest" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/forks-graph/rollup.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | input: 'index.js', 3 | external: ['d3'], 4 | output: { 5 | file: 'bundle.js', 6 | format: 'iife', 7 | sourcemap: true, 8 | globals: { d3: 'd3' } 9 | } 10 | }; -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/forks-graph/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | position: fixed; 3 | left: 0; 4 | right: 0; 5 | top: 0; 6 | bottom: 0; 7 | margin: 0; 8 | overflow: hidden; 9 | } 10 | 11 | line { 12 | fill: none; 13 | stroke: #349277; 14 | } 15 | 16 | text { 17 | text-shadow: 18 | -1px -1px 3px white, 19 | -1px 1px 3px white, 20 | 1px -1px 3px white, 21 | 1px 1px 3px white; 22 | pointer-events: none; 23 | font-family: 'Playfair Display', serif; 24 | } -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /build 3 | /coverage 4 | *.swp 5 | yarn.lock 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/README.md: -------------------------------------------------------------------------------- 1 | # VizHub 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v2-false-start/packages/frontend/public/favicon.ico -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/DejaVuSansMonoArrowized.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/DejaVuSansMonoArrowized.woff -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/DejaVuSansMonoLigaturized.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/DejaVuSansMonoLigaturized.woff -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/FiraCode.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/FiraCode.woff -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/FiraCodeArrowized.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/FiraCodeArrowized.woff -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/Inconsolata-gArrowized.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/Inconsolata-gArrowized.woff -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/Inconsolata-gLigaturized.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/Inconsolata-gLigaturized.woff -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/SourceCodeProArrowized.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/SourceCodeProArrowized.woff -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/SourceCodeProLigaturized.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/SourceCodeProLigaturized.woff -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/UbuntuMonoArrowized.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/UbuntuMonoArrowized.woff -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/UbuntuMonoLigaturized.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v2-false-start/packages/frontend/public/fonts/UbuntuMonoLigaturized.woff -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "VizHub", 3 | "name": "VizHub", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter as Router, Route } from 'react-router-dom'; 3 | import { Studio } from './Studio'; 4 | import { Home } from './Home'; 5 | import { Wrapper } from './styles'; 6 | 7 | export const App = () => ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { App } from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/LoadingScreen/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { LogoSVG } from '../svg'; 3 | import { LoadingScreenWrapper, SpinningLogo } from './styles'; 4 | 5 | export const LoadingScreen = () => ( 6 | 7 | 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Configurator/Menu.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { Foldable } from './Foldable'; 3 | 4 | export const Menu = ({ title, children, mono }) => { 5 | const [isActive, setIsActive] = useState(false); 6 | const toggle = () => setIsActive(!isActive); 7 | 8 | return ( 9 | 10 | {children} 11 | 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Configurator/sections/SettingsSection.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Section } from '../Section'; 3 | import { Item } from '../styles'; 4 | 5 | export const SettingsSection = () => ( 6 |
7 | Auto-resize 8 | Height 9 | Background color 10 | Privacy 11 | Collaborators 12 |
13 | ); 14 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Configurator/sections/index.js: -------------------------------------------------------------------------------- 1 | export { StateSection } from './StateSection'; 2 | export { FilesSection } from './FilesSection'; 3 | export { SettingsSection } from './SettingsSection'; 4 | export { PreferencesSection } from './PreferencesSection'; 5 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Editor/CodeMirror.js: -------------------------------------------------------------------------------- 1 | export { 2 | EditorState, 3 | EditorView, 4 | keymap, 5 | history, 6 | redo, 7 | redoSelection, 8 | undo, 9 | undoSelection, 10 | lineNumbers, 11 | baseKeymap, 12 | indentSelection, 13 | legacyMode, 14 | legacyModes, 15 | matchBrackets, 16 | specialChars, 17 | multipleSelections 18 | } from '@datavis-tech/codemirror-6-prerelease'; 19 | export { ot } from 'codemirror-ot'; 20 | export { presence } from './presence'; 21 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Editor/PresenceDisplay/getFileId.js: -------------------------------------------------------------------------------- 1 | // Gets the file ID in the presence path. 2 | // This is the file that the presence is "in". 3 | // The presence should be hidden if the current user 4 | // is not also "in" the same file. 5 | export const getFileId = presence => presence.p[presence.p.length - 2]; 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Editor/PresenceDisplay/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Wrapper = styled.div` 4 | position: fixed; 5 | left: ${props => props.x}px; 6 | top: ${props => props.y}px; 7 | width: 2px; 8 | height: ${props => props.height}px; 9 | background: aqua; 10 | pointer-events: none; 11 | `; 12 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Editor/css.js: -------------------------------------------------------------------------------- 1 | // https://stackoverflow.com/questions/47836390/how-to-convert-a-camel-case-string-to-dashes-in-javascript 2 | const dashed = camel => camel.replace(/[A-Z]/g, m => '-' + m.toLowerCase()); 3 | 4 | const objectToCSS = object => 5 | object 6 | ? Object.entries(object) 7 | .map(([key, value]) => `${dashed(key)}:${value};`) 8 | .join('') 9 | : ''; 10 | 11 | export const css = key => props => objectToCSS(props.theme[key]); 12 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Editor/extension.js: -------------------------------------------------------------------------------- 1 | // TODO move to central place for accessors. 2 | // 3 | // Computes the file extension from the given file path. 4 | export const extension = path => { 5 | const i = path.lastIndexOf('.'); 6 | 7 | // If no extension, return null. 8 | if (i === -1) { 9 | return null; 10 | } 11 | 12 | return path.substr(i + 1); 13 | }; 14 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Editor/useCodeMirror.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | export const useCodeMirror = () => { 4 | const [CodeMirror, setCodeMirror] = useState(); 5 | useEffect(() => { 6 | import('./CodeMirror').then(setCodeMirror); 7 | }, []); 8 | return CodeMirror; 9 | }; 10 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Editor/useEditorViewPool.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | import { EditorViewPool } from './EditorViewPool'; 3 | 4 | export const useEditorViewPool = vizId => { 5 | const [editorViewPool, setEditorViewPool] = useState(); 6 | 7 | useEffect(() => { 8 | const newEditorViewPool = new EditorViewPool(vizId); 9 | setEditorViewPool(newEditorViewPool); 10 | return () => newEditorViewPool.destroy(); 11 | }, [vizId]); 12 | 13 | return editorViewPool; 14 | }; 15 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/ErrorPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const ErrorPage = ({ error }) => { 4 | const { statusCode, title, message } = error; 5 | return ( 6 | <> 7 |

{statusCode}

8 |

{title}

9 |
{message}
10 | 11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/Actions/Action.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Wrapper, Icon } from './styles'; 3 | 4 | export const Action = ({ svg: SVG, onClick, children, desktopOnly }) => ( 5 | 6 | 7 | 8 | 9 | {children} 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/Actions/Download.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { DownloadSVG } from '../../../svg'; 3 | import { Action } from './Action'; 4 | 5 | export const Download = () => ( 6 | 7 | Download 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/Actions/Edit.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { URLStateContext } from '../../../contexts'; 3 | import { EditSVG } from '../../../svg'; 4 | import { Action } from './Action'; 5 | 6 | export const Edit = ({ onClick }) => { 7 | const { toggleConfigurator } = useContext(URLStateContext); 8 | return ( 9 | 10 | Edit 11 | 12 | ); 13 | }; 14 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/Actions/Fork.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ForkSVG } from '../../../svg'; 3 | import { Action } from './Action'; 4 | 5 | export const Fork = () => Fork; 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/Actions/FullScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FullScreenSVG } from '../../../svg'; 3 | import { Action } from './Action'; 4 | 5 | export const FullScreen = () => Fullscreen; 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/Actions/Share.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ShareSVG } from '../../../svg'; 3 | import { Action } from './Action'; 4 | 5 | export const Share = () => Share; 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/Actions/UpvoteDownvote.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { format } from 'd3-format'; 3 | import { UpvoteSVG, DownvoteSVG } from '../../../svg'; 4 | import { Action } from './Action'; 5 | 6 | export const formatVotes = format(','); 7 | 8 | export const Upvote = ({ upvotes }) => ( 9 | {formatVotes(upvotes)} 10 | ); 11 | 12 | export const Downvote = ({ downvotes }) => ( 13 | {formatVotes(downvotes)} 14 | ); 15 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/Actions/index.js: -------------------------------------------------------------------------------- 1 | export { Action } from './Action'; 2 | export { Download } from './Download'; 3 | export { Edit } from './Edit'; 4 | export { Fork } from './Fork'; 5 | export { FullScreen } from './FullScreen'; 6 | export { index } from './index'; 7 | export { Share } from './Share'; 8 | export { Upvote, Downvote } from './UpvoteDownvote'; 9 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/ForkedFrom/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Flex } from '../../../styles'; 3 | 4 | export const Wrapper = styled(Flex)` 5 | flex-direction: column; 6 | `; 7 | 8 | export const ForkedFromViz = styled.div` 9 | width: 120px; 10 | height: 50px; 11 | background-color: #ddd; 12 | `; 13 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/Header/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { LogoSVG } from '../../../svg'; 3 | import { Padded } from '../styles'; 4 | import { avatarUrl } from '../avatarUrl'; 5 | import { Wrapper, Logo, HeaderAvatar } from './styles'; 6 | 7 | export const Header = ({ authenticatedUserData, height }) => ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/Runner/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const IFrame = styled.iframe` 4 | background-color: white; 5 | border: 1px solid rgba(0, 0, 0, 0.1); 6 | `; 7 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/avatarUrl.js: -------------------------------------------------------------------------------- 1 | // TODO make this an accessor for user entity 2 | export const avatarUrl = ({ gitHubId }, height) => 3 | `https://avatars0.githubusercontent.com/u/${gitHubId}?s=${height * 2}&v=4`; 4 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/Studio/Viewer/formatViewCount.js: -------------------------------------------------------------------------------- 1 | import { format } from 'd3-format'; 2 | export const formatViewCount = format(','); 3 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/contexts/index.js: -------------------------------------------------------------------------------- 1 | export { PreferencesContext, PreferencesProvider } from './preferences'; 2 | export { StudioDataContext, StudioDataProvider } from './studioData'; 3 | export { VizContext, VizProvider } from './viz'; 4 | export { URLStateContext, URLStateProvider } from './urlState'; 5 | export { ErrorContext, ErrorProvider } from './error'; 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/contexts/preferences/preferencesMemoryGateway.js: -------------------------------------------------------------------------------- 1 | import EventEmitter from 'events'; 2 | 3 | export const preferencesMemoryGateway = () => { 4 | const data = { 5 | colorTheme: 'ubuntu', 6 | font: 'Ubuntu Mono', 7 | ligatures: 'arrows' 8 | }; 9 | const gateway = new EventEmitter(); 10 | gateway.get = key => data[key]; 11 | gateway.set = key => value => { 12 | data[key] = value; 13 | gateway.emit('change', key); 14 | }; 15 | return gateway; 16 | }; 17 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/contexts/studioData/actions.js: -------------------------------------------------------------------------------- 1 | export const request = vizId => ({ 2 | type: 'request', 3 | vizId 4 | }); 5 | 6 | export const receive = (vizId, studioData) => ({ 7 | type: 'receive', 8 | vizId, 9 | studioData 10 | }); 11 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/contexts/studioData/reducer.js: -------------------------------------------------------------------------------- 1 | export const reducer = (state, action) => { 2 | switch (action.type) { 3 | case 'request': 4 | return Object.assign({}, state, { 5 | [action.vizId]: { 6 | isFetching: true 7 | } 8 | }); 9 | case 'receive': 10 | return Object.assign({}, state, { 11 | [action.vizId]: { 12 | isFetching: false, 13 | studioData: action.studioData 14 | } 15 | }); 16 | default: 17 | throw new Error(); 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/contexts/studioData/wait.js: -------------------------------------------------------------------------------- 1 | // Let the loading animation play. 2 | export const wait = ms => 3 | new Promise(resolve => { 4 | setTimeout(resolve, ms); 5 | }); 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/contexts/urlState/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { createContext } from 'react'; 3 | import { withURLState } from './withURLState'; 4 | 5 | export const URLStateContext = createContext(); 6 | 7 | export const URLStateProvider = withURLState(({ children, urlState }) => ( 8 | 9 | {children} 10 | 11 | )); 12 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/environment.js: -------------------------------------------------------------------------------- 1 | export const avoidBackend = false; 2 | export const avoidShareDB = avoidBackend; 3 | // You can put the following in your .env file: 4 | // REACT_APP_WEBSOCKET_URL="ws://vizhub.myDomain.com" 5 | export const webSocketURL = 6 | process.env.REACT_APP_WEBSOCKET_URL || 'ws://localhost:4000'; 7 | export const enablePresence = true; //false; 8 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { App } from './App'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Flex = styled.div` 4 | display: flex; 5 | `; 6 | 7 | export const Wrapper = styled.div` 8 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 9 | 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | `; 13 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/svg/ArrowBackSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SVG } from './SVG'; 3 | 4 | // Derived from Material Design arrow-back icon. 5 | export const ArrowBackSVG = props => ( 6 | 7 | 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/svg/CloseSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SVG } from './SVG'; 3 | 4 | // Derived from Material Design close icon. 5 | export const CloseSVG = () => ( 6 | 7 | 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/svg/DownloadSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SVG } from './SVG'; 3 | 4 | // Derived from Material Design download-button icon. 5 | export const DownloadSVG = () => ( 6 | 7 | 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/svg/EditSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SVG } from './SVG'; 3 | 4 | // Derived from Octicons pencil icon. 5 | // Original viewBox="0 0 14 16" 6 | // viewBox modified to achieve consistent aspect ratio across icons. 7 | export const EditSVG = () => ( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/svg/FullScreenSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SVG } from './SVG'; 3 | 4 | // Derived from Material Design fullscreen icon. 5 | export const FullScreenSVG = () => ( 6 | 7 | 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/svg/SVG.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const SVG = styled.svg` 4 | fill: ${props => props.fill || props.theme.textLight}; 5 | `; 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/svg/ShareSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SVG } from './SVG'; 3 | 4 | // Derived from Material Design forward-arrow icon. 5 | export const ShareSVG = () => ( 6 | 7 | 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/themes/index.js: -------------------------------------------------------------------------------- 1 | export { light } from './light'; 2 | export { ubuntu } from './ubuntu'; 3 | export { oneDark } from './oneDark'; 4 | export { material } from './material'; 5 | export { dracula } from './dracula'; 6 | export { monokai } from './monokai'; 7 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/src/themes/light.js: -------------------------------------------------------------------------------- 1 | export const light = { 2 | headerHeight: 32, 3 | infoAvatarHeight: 64, 4 | infoAvatarPadding: 12, 5 | commentAvatarHeight: 32, 6 | foreground: 'black', 7 | background: 'white', 8 | textMain: '#121212', 9 | textLight: '#636363' 10 | }; 11 | -------------------------------------------------------------------------------- /prototypes/vizhub-v2-false-start/packages/frontend/transferred.csv: -------------------------------------------------------------------------------- 1 | date,viewer,configurator,editor 2 | 3/16/2019,93.3,337, 3 | 3/23/2019,97.5,253, 4 | 4/4/2019,101,263, 5 | 4/15/2019,170,276, 6 | 4/18/2019,163,269,374 7 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.swp 3 | *.map 4 | /build 5 | /public/build 6 | /public/serviceWorkerBuild.js 7 | package-lock.json 8 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/.prettierignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.png 3 | *.ico 4 | *.map 5 | .* 6 | /build 7 | /public/build 8 | /public/serviceWorkerBuild.js 9 | deploy.sh 10 | renderPageTestExpected.html 11 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/buildCSS.js: -------------------------------------------------------------------------------- 1 | const { renderSync } = require('sass'); 2 | const { writeFileSync } = require('fs'); 3 | 4 | // TODO minify for production build. 5 | console.log('Building CSS...'); 6 | writeFileSync( 7 | './public/build/styles.css', 8 | renderSync({ file: 'src/styles/index.scss' }).css.toString() 9 | ); 10 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/deploy.sh: -------------------------------------------------------------------------------- 1 | git pull 2 | npm install 3 | npm run buildProduction 4 | pm2 start ecosystem.config.js 5 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/ecosystem.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | apps: [ 3 | { 4 | name: 'VizHub v3 Beta', 5 | script: 'npm run startProduction', 6 | }, 7 | ], 8 | }; 9 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v3-false-start/public/favicon.ico -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/public/images/touch/logoBlackSquare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/prototypes/vizhub-v3-false-start/public/images/touch/logoBlackSquare.png -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "VizHub", 3 | "name": "VizHub", 4 | "short_name": "VizHub", 5 | "start_url": "./", 6 | "icons": [ 7 | { 8 | "src": "favicon.ico", 9 | "sizes": "64x64 32x32 24x24 16x16", 10 | "type": "image/x-icon" 11 | }, 12 | { 13 | "src": "images/touch/logoBlackSquare.png", 14 | "sizes": "512x512", 15 | "type": "image/png" 16 | } 17 | ], 18 | "display": "fullscreen", 19 | "theme_color": "#f6eee3", 20 | "background_color": "#fffbf6" 21 | } 22 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/App/classed.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | // Generates a component that's a div (or specified tagName) with a class. 4 | export const classed = 5 | (className, type = 'div') => 6 | (props) => 7 | React.createElement(type, { className, ...props }, props.children); 8 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/App/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as pages from './pages'; 3 | 4 | export const App = ({ page, pageProps }) => { 5 | const PageComponent = pages[page]; 6 | return ; 7 | }; 8 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/App/isClient.js: -------------------------------------------------------------------------------- 1 | // True if the app is running in the client. 2 | // False if the app is running in the server (server side rendering). 3 | export let isClient = false; 4 | 5 | export const setIsClient = () => { 6 | isClient = true; 7 | }; 8 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/App/pages/TestPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | // Used only in unit tests - see testRenderPage.js 4 | export const TestPage = ({ message }) =>
Test: {message}
; 5 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/App/pages/VizNotFoundPage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const VizNotFoundPage = () => { 4 | return

Viz not found

; 5 | }; 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/App/pages/index.js: -------------------------------------------------------------------------------- 1 | export { TestPage } from './TestPage'; 2 | export { HomePage } from './HomePage'; 3 | export { VizPage } from './VizPage'; 4 | export { VizNotFoundPage } from './VizNotFoundPage'; 5 | export { SanityCheckPage } from './SanityCheckPage'; 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/client/RequireContext.js: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | 3 | export const RequireContext = createContext(); 4 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/client/client2.js: -------------------------------------------------------------------------------- 1 | // An example of lazy loading a module. 2 | import React from 'react'; 3 | export const Client2 = () =>
Hello there
; 4 | 5 | // TODO think on how to require Marked 6 | // 7 | // Possible to dynamically fetch this from CDN using d3-require? 8 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/client/useModule.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useContext } from 'react'; 2 | import { RequireContext } from './RequireContext'; 3 | 4 | // A hook for dynamically requiring (lazy loading) modules. 5 | export const useModule = (path) => { 6 | const [module, setModule] = useState({}); 7 | const require = useContext(RequireContext); 8 | useEffect(() => { 9 | if (require) require(path).then(setModule); 10 | }, [require]); 11 | return module; 12 | }; 13 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/entities/createInstance.js: -------------------------------------------------------------------------------- 1 | export const createInstance = (constructor, keys, data) => { 2 | if (!data) return null; 3 | const instance = new constructor(); 4 | for (const key of keys) { 5 | instance[key] = data[key]; 6 | } 7 | return instance; 8 | }; 9 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/globals.js: -------------------------------------------------------------------------------- 1 | // This file configures how package names are resolved to browser globals. 2 | // It is required to support the strategy of sourcing large dependencies from a CDN, 3 | // rather than including them in our bundle(s). 4 | 5 | // Used by Rollup config. 6 | export const globals = { 7 | react: 'React', 8 | 'react-dom': 'ReactDOM', 9 | 'd3-require': 'd3', 10 | // TODO marked, sanitize 11 | }; 12 | 13 | // Used by d3-require. 14 | export const aliases = () => ({ 15 | react: React, 16 | 'react-dom': ReactDOM, 17 | }); 18 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/interactors/getVizPageData.js: -------------------------------------------------------------------------------- 1 | export const getVizPageData = async ({ getVizInfo }, vizId) => { 2 | const vizInfo = await getVizInfo(vizId); 3 | if (!vizInfo) { 4 | return null; 5 | } 6 | return { vizInfo }; 7 | }; 8 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/pageData.js: -------------------------------------------------------------------------------- 1 | // These functions are responsible for safely transporting page data 2 | // from the server, via a string in HTML to the client rendered app. 3 | 4 | export const encodePageData = (pageData) => 5 | btoa(encodeURIComponent(JSON.stringify(pageData))); 6 | 7 | export const decodePageData = (encodedPageData) => 8 | JSON.parse(decodeURIComponent(atob(encodedPageData))); 9 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/pageDataTest.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { encodePageData, decodePageData } from './pageData'; 3 | 4 | export const pageDataTest = () => { 5 | describe('pageData', () => { 6 | it('Should encoded and decode data with Unicode characters', () => { 7 | const pageData = { foo: { bar: 'It’s a beautiful day!' } }; 8 | assert.deepEqual(decodePageData(encodePageData(pageData)), pageData); 9 | }); 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/presenters/homePagePresenter.js: -------------------------------------------------------------------------------- 1 | export const homePagePresenter = ({ vizInfos, ownerUsers }) => ({ 2 | title: 'Home', 3 | page: 'HomePage', 4 | pageProps: { 5 | vizInfos, 6 | ownerUsersById: ownerUsers.reduce((accumulator, user) => { 7 | accumulator[user.id] = user; 8 | return accumulator; 9 | }, {}), 10 | }, 11 | // TODO add meta tag info 12 | }); 13 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/server/database/generateId.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuidV4 } from 'uuid'; 2 | 3 | // Generates a unique id for vizzes. 4 | // Uses uuid v4, removes dashes. 5 | export const generateId = () => uuidV4().replace(/-/g, ''); 6 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/server/renderPage/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { renderToString } from 'react-dom/server'; 3 | import { App } from '../../App'; 4 | import { indexHTML } from './indexHTML'; 5 | 6 | export const renderPage = ({ title, page, pageProps }) => { 7 | const rootHTML = renderToString(); 8 | return indexHTML({ title, page, pageProps, rootHTML }); 9 | }; 10 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/styles/base.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: var(--background-color); 3 | color: var(--foreground-color); 4 | font-family: var(--font-family-default); 5 | font-size: var(--font-size-default); 6 | margin: 0; 7 | } 8 | 9 | * { 10 | box-sizing: border-box; 11 | } 12 | 13 | @font-face { 14 | font-family: 'Ubuntu Mono Arrowized'; 15 | src: url('https://cdn.jsdelivr.net/npm/ubuntu-mono-ligaturized@3.0.0/arrowized/UbuntuMonoLigaturized-Regular.woff2') 16 | format('woff2'); 17 | } 18 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/styles/index.scss: -------------------------------------------------------------------------------- 1 | // Inspired by 2 | // * https://github.com/milligram/milligram/blob/master/src/milligram.sass 3 | // * https://codyhouse.co/blog/post/css-custom-properties-vs-sass-variables 4 | 5 | @use 'variables'; 6 | @use 'base'; 7 | @use 'link'; 8 | @use 'navigation'; 9 | @use 'home-page'; 10 | @use 'viz-page'; 11 | @use 'viz-preview'; 12 | @use 'markdown-body'; 13 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/styles/link.scss: -------------------------------------------------------------------------------- 1 | a { 2 | color: var(--link-color); 3 | text-decoration: none; 4 | display: inline-block; 5 | } 6 | 7 | /* 8 | a:visited { 9 | color: var(--link-color-visited); 10 | } 11 | */ 12 | 13 | a:hover { 14 | transform: translateY(-1px); 15 | } 16 | 17 | a:active { 18 | transform: translateY(1px); 19 | } 20 | -------------------------------------------------------------------------------- /prototypes/vizhub-v3-false-start/src/styles/navigation.scss: -------------------------------------------------------------------------------- 1 | .navigation { 2 | position: sticky; 3 | top: 0; 4 | left: 0; 5 | right: 0; 6 | display: flex; 7 | align-items: center; 8 | padding: 0 4px; 9 | height: var(--navigation-height); 10 | background-color: var(--background-color); 11 | color: var(--foreground-color); 12 | z-index: var(--z-index-above); 13 | 14 | .logo-link { 15 | line-height: 0; 16 | color: currentcolor; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vizhub-v2/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /vizhub-v2/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | yarn.lock 4 | yarn-error.log 5 | lerna-debug.log 6 | npm-debug.log 7 | .next 8 | *.swp 9 | *.autosave 10 | .env 11 | .vscode 12 | .eslintcache 13 | -------------------------------------------------------------------------------- /vizhub-v2/buildFrontend.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd packages/neoFrontend/ 3 | npm run build 4 | rm -rf ../neoBackend/build/ 5 | cp -r build ../neoBackend/build 6 | cd ../../ 7 | -------------------------------------------------------------------------------- /vizhub-v2/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | git pull 3 | npm install 4 | npm run lerna 5 | sh ./buildFrontend.sh 6 | 7 | # Flush logs so they don't accumulate and cause disk usage crashes. 8 | pm2 flush 9 | 10 | pm2 restart all --update-env 11 | -------------------------------------------------------------------------------- /vizhub-v2/deployFirstTime.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Note: Do this for the first deploy on a new server: 3 | cd packages/neoBackend/ 4 | pm2 start --name VizHubAppServer npm -- start 5 | -------------------------------------------------------------------------------- /vizhub-v2/lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "2.11.0", 3 | "packages": [ 4 | "packages/*" 5 | ], 6 | "version": "0.0.0" 7 | } 8 | -------------------------------------------------------------------------------- /vizhub-v2/logo/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/logo/favicon.ico -------------------------------------------------------------------------------- /vizhub-v2/logo/logo-XL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/logo/logo-XL.png -------------------------------------------------------------------------------- /vizhub-v2/logo/logoBlackSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/logo/logoBlackSmall.png -------------------------------------------------------------------------------- /vizhub-v2/logo/logoBlackSquare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/logo/logoBlackSquare.png -------------------------------------------------------------------------------- /vizhub-v2/logo/logoSquare_large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/logo/logoSquare_large.png -------------------------------------------------------------------------------- /vizhub-v2/logo/logoWhiteSmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/logo/logoWhiteSmall.png -------------------------------------------------------------------------------- /vizhub-v2/logo/logoWhiteSquare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/logo/logoWhiteSquare.png -------------------------------------------------------------------------------- /vizhub-v2/logo/mugDesign.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/logo/mugDesign.png -------------------------------------------------------------------------------- /vizhub-v2/packages/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/Error/index.js: -------------------------------------------------------------------------------- 1 | export { ErrorResponse } from './ErrorResponse'; 2 | export { toErrorResponse } from './toErrorResponse'; 3 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/Error/toErrorResponse.js: -------------------------------------------------------------------------------- 1 | import { toVizHubAPIError } from './toVizHubAPIError'; 2 | import { ErrorResponse } from './ErrorResponse'; 3 | export const toErrorResponse = (error) => 4 | ErrorResponse(toVizHubAPIError(error)); 5 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/apiController/datasetAPIController/index.js: -------------------------------------------------------------------------------- 1 | import { createDatasetController } from './createDatasetController'; 2 | import { getDatasetController } from './getDatasetController'; 3 | // import { saveDatasetController } from './saveDatasetController'; 4 | 5 | export const datasetAPIController = (expressApp, gateways) => { 6 | createDatasetController(expressApp, gateways); 7 | getDatasetController(expressApp, gateways); 8 | // saveDatasetController(expressApp, datasetGateway); 9 | }; 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/apiController/eventRecordsAPIController/index.js: -------------------------------------------------------------------------------- 1 | import { sendEventController } from './sendEvent'; 2 | import { getEventRecordsController } from './getEventRecords'; 3 | 4 | export const eventRecordsAPIController = (expressApp, gateways) => { 5 | sendEventController(expressApp, gateways); 6 | getEventRecordsController(expressApp, gateways); 7 | }; 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/apiController/userAPIController/getUsers.js: -------------------------------------------------------------------------------- 1 | import { GetUsers } from 'vizhub-use-cases'; 2 | 3 | export const getUsersController = (expressApp, gateways) => { 4 | const getUsers = new GetUsers(gateways); 5 | expressApp.get('/api/user/get', async (req, res) => { 6 | try { 7 | const ids = req.query.ids.split(','); 8 | const data = await getUsers.execute({ ids }); 9 | res.json(data); 10 | } catch (error) { 11 | console.log(error); 12 | res.json({ error }); 13 | } 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/apiController/userAPIController/index.js: -------------------------------------------------------------------------------- 1 | import { getProfileDataController } from './getProfileDataController'; 2 | import { getUserSearchResultsDataController } from './getUserSearchResultsData'; 3 | import { getUsersController } from './getUsers'; 4 | 5 | export const userAPIController = (expressApp, userGateway) => { 6 | getProfileDataController(expressApp, userGateway); 7 | getUserSearchResultsDataController(expressApp, userGateway); 8 | getUsersController(expressApp, userGateway); 9 | }; 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/index.js: -------------------------------------------------------------------------------- 1 | export { apiController } from './apiController'; 2 | export { userController } from './userController'; 3 | export { jwtAuth, getUserIDFromJWT } from './jwtAuth'; 4 | export { serveVizPage } from './serveVizPage'; 5 | export { serveHomePage } from './serveHomePage'; 6 | export { oembedController } from './oembedController'; 7 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/jwtAuth/routes/authSignOut.js: -------------------------------------------------------------------------------- 1 | export const authSignOut = (req, res) => { 2 | res.clearCookie('vizHubJWT'); 3 | res.send({}); 4 | }; 5 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/jwtAuth/routes/index.js: -------------------------------------------------------------------------------- 1 | export { authGitHub } from './authGitHub'; 2 | export { authGoogle } from './authGoogle'; 3 | export { authFB } from './authFB'; 4 | export { authMe } from './authMe'; 5 | export { authCI } from './authCI'; 6 | export { authSignOut } from './authSignOut'; 7 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/sanitize.js: -------------------------------------------------------------------------------- 1 | import { stripHtml } from 'string-strip-html'; 2 | import sanitizeHTML from 'sanitize-html'; 3 | 4 | export const sanitize = (str) => sanitizeHTML(stripHtml(str).result); 5 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/serveHomePage.js: -------------------------------------------------------------------------------- 1 | import { servePage } from './servePage'; 2 | 3 | const meta = { 4 | title: 'VizHub - data visualization platform', 5 | description: 6 | 'Learn to code interactive graphics & data visualization with Web technologies!', 7 | image: '/images/unfurl-logo.png', 8 | url: '/', 9 | }; 10 | 11 | export const serveHomePage = (gateways, indexHTML) => { 12 | const servePageMiddleware = servePage(indexHTML, meta); 13 | return async (req, res) => { 14 | return servePageMiddleware(req, res); 15 | }; 16 | }; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/controllers/src/userIdFromReq.js: -------------------------------------------------------------------------------- 1 | import { getUserIDFromJWT } from './jwtAuth'; 2 | export const userIdFromReq = (req) => { 3 | // Handle VizHub 1.0 sessions. 4 | if (req.user) { 5 | return req.user.id; 6 | } 7 | 8 | // Handle VizHub 2.0 sessions. 9 | const { vizHubJWT } = req.cookies; 10 | if (vizHubJWT) { 11 | return getUserIDFromJWT(vizHubJWT); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/collectionName.js: -------------------------------------------------------------------------------- 1 | export const DOCUMENT_INFO = 'documentInfo'; 2 | export const DOCUMENT_CONTENT = 'documentContent'; 3 | export const USER = 'user'; 4 | export const THUMBNAIL_IMAGES = 'thumbnailImages'; 5 | export const PREVIEW_IMAGES = 'previewImages'; 6 | export const EVENT_RECORDS = 'eventRecords'; 7 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/constants.js: -------------------------------------------------------------------------------- 1 | // The number of vizzes shown in a page of content. 2 | // Infinite scroll pagination fetches the next page. 3 | export const pageSize = 100; 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/createUser.js: -------------------------------------------------------------------------------- 1 | import { USER } from './collectionName'; 2 | 3 | export const createUser = (connection) => (user) => { 4 | return new Promise((resolve) => { 5 | connection.get(USER, user.id).create(user); 6 | resolve(user); 7 | }); 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/createVisualization.js: -------------------------------------------------------------------------------- 1 | import { DOCUMENT_INFO, DOCUMENT_CONTENT } from './collectionName'; 2 | import { saveVisualization } from './saveVisualization'; 3 | 4 | export const createVisualization = (connection) => (visualization) => 5 | saveVisualization(connection)({ visualization }).then(() => ({ 6 | id: visualization.id, 7 | })); 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/fetchShareDBDoc.js: -------------------------------------------------------------------------------- 1 | export const fetchShareDBDoc = (collection, id, connection) => 2 | new Promise((resolve, reject) => { 3 | const shareDBDoc = connection.get(collection, id); 4 | shareDBDoc.fetch((error) => { 5 | error ? reject(error) : resolve(shareDBDoc); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/fetchShareDBQuery.js: -------------------------------------------------------------------------------- 1 | export const fetchShareDBQuery = (collection, mongoQuery, connection) => 2 | new Promise((resolve, reject) => { 3 | connection.createFetchQuery( 4 | collection, 5 | mongoQuery, 6 | {}, 7 | (error, results) => { 8 | error ? reject(error) : resolve(results); 9 | //query.destroy(); 10 | } 11 | ); 12 | }); 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/getHomePageVisualizationInfos.js: -------------------------------------------------------------------------------- 1 | import { searchVisualizationInfos } from './searchVisualizationInfos'; 2 | 3 | export const getHomePageVisualizationInfos = (connection) => async (args) => { 4 | return searchVisualizationInfos(connection)(args); 5 | }; 6 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/getUser.js: -------------------------------------------------------------------------------- 1 | import { User } from 'vizhub-entities'; 2 | import { USER } from './collectionName'; 3 | import { fetchShareDBDoc } from './fetchShareDBDoc'; 4 | 5 | export const getUser = (connection) => async (id) => { 6 | try { 7 | const userDoc = await fetchShareDBDoc(USER, id, connection); 8 | return new User(userDoc.data); 9 | } catch (error) { 10 | return null; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/getUserByEmail.js: -------------------------------------------------------------------------------- 1 | import { i18n } from 'vizhub-i18n'; 2 | import { USER } from './collectionName'; 3 | import { fetchShareDBQuery } from './fetchShareDBQuery'; 4 | 5 | export const getUserByEmail = (connection) => async (email) => { 6 | try { 7 | const mongoQuery = { email }; 8 | const results = await fetchShareDBQuery(USER, mongoQuery, connection); 9 | const userDoc = results[0]; 10 | 11 | return userDoc.data; 12 | } catch (error) { 13 | return null; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/getUsers.js: -------------------------------------------------------------------------------- 1 | import { User } from 'vizhub-entities'; 2 | import { USER } from './collectionName'; 3 | import { fetchShareDBQuery } from './fetchShareDBQuery'; 4 | 5 | export const getUsers = (connection) => async (ids) => { 6 | try { 7 | const mongoQuery = { 8 | id: { $in: ids }, 9 | }; 10 | const userDocs = await fetchShareDBQuery(USER, mongoQuery, connection); 11 | return userDocs.map((userDoc) => new User(userDoc.data)); 12 | } catch (error) { 13 | console.log(error); 14 | return null; 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/getVisualizationInfo.js: -------------------------------------------------------------------------------- 1 | import { VisualizationInfo } from 'vizhub-entities'; 2 | import { DOCUMENT_INFO } from './collectionName'; 3 | import { fetchShareDBDoc } from './fetchShareDBDoc'; 4 | 5 | export const getVisualizationInfo = (connection) => ({ id }) => 6 | fetchShareDBDoc(DOCUMENT_INFO, id, connection).then((visualization) => { 7 | if (visualization.data) { 8 | return new VisualizationInfo(visualization.data); 9 | } else { 10 | return { error: `No data for ${id}` }; 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/getVisualizationInfos.js: -------------------------------------------------------------------------------- 1 | import { searchVisualizationInfos } from './searchVisualizationInfos'; 2 | 3 | export const getVisualizationInfos = (connection) => async (args) => { 4 | const { offset, ids } = args; 5 | 6 | return searchVisualizationInfos(connection)({ 7 | offset, 8 | extraQueryParams: { 9 | id: { $in: ids }, 10 | }, 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/getVisualizationInfosByUserId.js: -------------------------------------------------------------------------------- 1 | import { searchVisualizationInfos } from './searchVisualizationInfos'; 2 | 3 | export const getVisualizationInfosByUserId = (connection) => async ({ 4 | owner, 5 | ...restArgs 6 | }) => { 7 | return searchVisualizationInfos(connection)({ 8 | ...restArgs, 9 | extraQueryParams: { owner }, 10 | }); 11 | }; 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/save.js: -------------------------------------------------------------------------------- 1 | import jsonDiff from 'json0-ot-diff'; 2 | import diffMatchPatch from 'diff-match-patch'; 3 | 4 | export const save = (doc, data) => 5 | new Promise((resolve, reject) => { 6 | const callback = (error) => 7 | error ? reject(error) : resolve({ status: 'success' }); 8 | 9 | if (!doc.type) { 10 | doc.create(data, callback); 11 | } else { 12 | doc.submitOp(jsonDiff(doc.data, data, diffMatchPatch), callback); 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/saveUser.js: -------------------------------------------------------------------------------- 1 | import { USER } from './collectionName'; 2 | import { fetchShareDBDoc } from './fetchShareDBDoc'; 3 | import { save } from './save'; 4 | 5 | export const saveUser = (connection) => async (user) => { 6 | const userDoc = await fetchShareDBDoc(USER, user.id, connection); 7 | return await save(userDoc, user); 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/database/src/updateScores.js: -------------------------------------------------------------------------------- 1 | import { DOCUMENT_INFO } from './collectionName'; 2 | import { fetchShareDBDoc } from './fetchShareDBDoc'; 3 | import { save } from './save'; 4 | 5 | export const updateScores = (connection) => async ({ id, scores }) => { 6 | const info = await fetchShareDBDoc(DOCUMENT_INFO, id, connection); 7 | return await save(info, { ...info.data, ...scores }); 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/packages/entities/.gitignore -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/classDiagram.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/packages/entities/classDiagram.dia -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/src/ciUser.js: -------------------------------------------------------------------------------- 1 | export const ciUser = { 2 | id: '47895473289547832938754', 3 | fullName: 'CI', 4 | email: 'ci@testing.com', 5 | userName: 'ci', 6 | avatarUrl: 'https://avatars0.githubusercontent.com/u/639823?v=4', 7 | }; 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/src/commit.js: -------------------------------------------------------------------------------- 1 | // A Commit represents a specific revision of a viz. 2 | export class Commit { 3 | constructor(data) { 4 | // Every commit has a unique ID. 5 | this.id = data.id; 6 | 7 | // Every commit belongs to exactly one viz. 8 | // This field is the ID of the viz that this commit belongs to. 9 | this.viz = data.viz; 10 | 11 | // Unix timestamp at which this Commit was created. 12 | this.timestamp = data.timestamp; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/src/dataset.js: -------------------------------------------------------------------------------- 1 | export class Dataset { 2 | constructor(data) { 3 | // The unique ID of this dataset. 4 | this.id = data.datasetInfo.id; 5 | // The info part of this dataset. 6 | this.info = data.datasetInfo; 7 | // The content part of this dataset. 8 | this.content = data.datasetContent; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/src/datasetContent.js: -------------------------------------------------------------------------------- 1 | import { DocumentContent } from './documentContent'; 2 | import { DATASET_TYPE } from './documentTypes'; 3 | 4 | export class DatasetContent extends DocumentContent { 5 | constructor(data) { 6 | super({ 7 | id: data.id, 8 | documentType: DATASET_TYPE, 9 | }); 10 | 11 | // The text content of this dataset. 12 | this.text = data.text; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/src/documentContent.js: -------------------------------------------------------------------------------- 1 | import { DocumentPart } from './documentPart'; 2 | 3 | export class DocumentContent extends DocumentPart { 4 | constructor(data) { 5 | super({ 6 | id: data.id, 7 | documentType: data.documentType, 8 | }); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/src/documentPart.js: -------------------------------------------------------------------------------- 1 | export class DocumentPart { 2 | constructor(data) { 3 | // The unique ID of the document 4 | // that this document part is a part of. 5 | this.id = data.id; 6 | 7 | // The type of this document. 8 | // Either documentTypes.VISUALIZATION_TYPE or documentTypes.DATASET_TYPE 9 | this.documentType = data.documentType; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/src/documentTypes.js: -------------------------------------------------------------------------------- 1 | export const VISUALIZATION_TYPE = 'visualization'; 2 | export const DATASET_TYPE = 'dataset'; 3 | -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/src/file.js: -------------------------------------------------------------------------------- 1 | export class File { 2 | constructor(data) { 3 | // The name of the file. 4 | // For example "index.html", "index.js", "foo.js", "styles.css" 5 | this.name = data.name; 6 | 7 | // The text file content. 8 | this.text = data.text; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/src/timestamp.js: -------------------------------------------------------------------------------- 1 | // Returns the Unix timestamp for the present. 2 | export const timestamp = () => Math.floor(new Date().getTime() / 1000); 3 | export const toDate = (timestamp) => new Date(timestamp * 1000); 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/entities/src/visualization.js: -------------------------------------------------------------------------------- 1 | export class Visualization { 2 | constructor(data) { 3 | // The unique ID of this visualization. 4 | this.id = data.visualizationInfo.id; 5 | 6 | // The info part of this visualization. 7 | this.info = data.visualizationInfo; 8 | 9 | // The content part of this visualization. 10 | this.content = data.visualizationContent; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/gateways/src/databaseEventRecordsGateway.js: -------------------------------------------------------------------------------- 1 | export class DatabaseEventRecordsGateway { 2 | constructor(database) { 3 | this.database = database; 4 | } 5 | 6 | async getEventRecords(eventIDs) { 7 | return await this.database.getEventRecords(eventIDs); 8 | } 9 | 10 | async setEventRecords(newEventRecords) { 11 | return await this.database.setEventRecords(newEventRecords); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /vizhub-v2/packages/gateways/src/databaseImageStorageGateway.js: -------------------------------------------------------------------------------- 1 | export class DatabaseImageStorageGateway { 2 | constructor(database) { 3 | this.database = database; 4 | } 5 | 6 | async updateImages(options) { 7 | return await this.database.updateImages(options); 8 | } 9 | 10 | async getThumbnail(options) { 11 | return await this.database.getThumbnail(options); 12 | } 13 | 14 | async getPreview(options) { 15 | return await this.database.getPreview(options); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /vizhub-v2/packages/gateways/src/index.js: -------------------------------------------------------------------------------- 1 | export { DatabaseVisualizationGateway } from './databaseVisualizationGateway'; 2 | export { DatabaseDatasetGateway } from './databaseDatasetGateway'; 3 | export { DatabaseUserGateway } from './databaseUserGateway'; 4 | export { DatabaseImageStorageGateway } from './databaseImageStorageGateway'; 5 | export { DatabaseEventRecordsGateway } from './databaseEventRecordsGateway'; 6 | -------------------------------------------------------------------------------- /vizhub-v2/packages/i18n/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vizhub-i18n", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "", 6 | "main": "index.js", 7 | "scripts": { 8 | "updateDeps": "ncu -u" 9 | }, 10 | "author": "Curran Kelleher", 11 | "license": "UNLICENSED" 12 | } 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/imageGenerationService/src/computeImageDimensions.js: -------------------------------------------------------------------------------- 1 | export const computeImageDimensions = ({ actual, desired }) => 2 | actual.width / actual.height < desired.width / desired.height 3 | ? 4 | { 5 | width: desired.width, 6 | height: Math.round(actual.height / actual.width * desired.width) 7 | } 8 | : 9 | { 10 | width: Math.round(actual.width / actual.height * desired.height), 11 | height: desired.height 12 | }; 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/imageGenerationService/src/dimensions.js: -------------------------------------------------------------------------------- 1 | const defaultWidth = 960; 2 | const defaultHeight = 500; 3 | const aspectRatio = defaultWidth / defaultHeight; 4 | 5 | const dimensions = width => ({ 6 | width, 7 | height: Math.round(width / aspectRatio) 8 | }); 9 | 10 | export const thumbnailDimensions = dimensions(230); 11 | export const previewDimensions = dimensions(960); 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/imageGenerationService/src/index.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | import { startService } from './service'; 3 | startService({}); 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/imageGenerationService/src/resize.js: -------------------------------------------------------------------------------- 1 | import sharp from 'sharp'; 2 | import { computeImageDimensions } from './computeImageDimensions'; 3 | 4 | export const resize = async options => { 5 | const { 6 | actualDimensions: actual, 7 | desiredDimensions: desired, 8 | screenshotBuffer 9 | } = options; 10 | 11 | const { width, height } = computeImageDimensions({ actual, desired }); 12 | 13 | return await sharp(screenshotBuffer) 14 | .resize(width, height) 15 | .toBuffer(); 16 | }; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/json0-with-presence/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "json0-with-presence", 3 | "version": "1.0.0", 4 | "main": "src/index.js", 5 | "private": true, 6 | "scripts": { 7 | "prettier": "prettier --single-quote --write '*.js'", 8 | "updateDeps": "ncu -u" 9 | }, 10 | "author": "Curran Kelleher", 11 | "license": "UNLICENSED", 12 | "dependencies": { 13 | "ot-json0": "^1.1.0" 14 | }, 15 | "devDependencies": { 16 | "esm": "^3.2.25", 17 | "mocha": "^8.2.1", 18 | "prettier": "^2.2.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoBackend/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | node_modules 3 | package-lock.json 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoBackend/src/serveShareDB/shareDBMiddleware/accessControl/index.js: -------------------------------------------------------------------------------- 1 | export { vizWrite } from './vizWrite'; 2 | export { vizRead } from './vizRead'; 3 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoBackend/src/serveShareDB/shareDBMiddleware/index.js: -------------------------------------------------------------------------------- 1 | import { identifyAgent } from './identifyAgent'; 2 | import { vizRead, vizWrite } from './accessControl'; 3 | 4 | export const shareDBMiddleware = (shareDB) => { 5 | shareDB.use('connect', identifyAgent); 6 | shareDB.use('apply', vizWrite); 7 | shareDB.use('readSnapshots', vizRead); 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/authentication/index.js: -------------------------------------------------------------------------------- 1 | import { signIn } from './signIn'; 2 | import { signOut } from './signOut'; 3 | 4 | export { signIn, signOut }; 5 | 6 | export const authentication = (my) => () => { 7 | it('should sign in', signIn(my)); 8 | it('should sign out', signOut(my)); 9 | it('should sign in again', signIn(my)); 10 | }; 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/authentication/signIn.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { navigateToAuthPage } from './navigateToAuthPage'; 3 | 4 | export const signIn = (my) => async () => { 5 | await navigateToAuthPage(my)(); 6 | 7 | const { popup, page } = my; 8 | await (await popup.waitFor('.test-sign-in-as-ci')).click(); 9 | await page.waitFor('.test-avatar-me'); 10 | const alt = await page.evaluate( 11 | () => document.querySelector('.test-avatar-me').alt 12 | ); 13 | assert.equal(alt, 'ci'); 14 | }; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/authentication/signOut.js: -------------------------------------------------------------------------------- 1 | export const signOut = (my) => async () => { 2 | const { page } = my; 3 | 4 | // Pop open the menu, so the sign out button appears. 5 | await (await page.waitFor('.test-avatar-me')).click(); 6 | 7 | // Trigger sign out. 8 | await (await page.waitFor('.test-sign-out')).click(); 9 | 10 | // If this appears, then the test passes. No assertions needed! 11 | await page.waitFor('.test-sign-in'); 12 | }; 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/editorStates/closeMobilePage.js: -------------------------------------------------------------------------------- 1 | export const closeMobilePage = (my) => async () => { 2 | await my.mobilePage.close(); 3 | }; 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/editorStates/getPage.js: -------------------------------------------------------------------------------- 1 | export const getPage = (my, isMobile) => (isMobile ? my.mobilePage : my.page); 2 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/editorStates/openMobilePage.js: -------------------------------------------------------------------------------- 1 | import { devicesMap } from 'puppeteer/DeviceDescriptors'; 2 | 3 | export const openMobilePage = (my) => async () => { 4 | const mobilePage = await my.browser.newPage(); 5 | await mobilePage.emulate(devicesMap['Galaxy S5']); 6 | await mobilePage.goto(my.forkedVizURL); 7 | my.mobilePage = mobilePage; 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/editorStates/toggleFullScreen.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { getPage } from './getPage'; 3 | import { navClick } from '../navClick'; 4 | 5 | export const toggleFullScreen = (my, isMobile) => async () => { 6 | const page = getPage(my, isMobile); 7 | await navClick(page, '.test-enter-fullscreen-from-viewer'); 8 | await page.waitFor('.test-fullscreen'); 9 | await navClick(page, '.exit-fullscreen-from-fullscreen'); 10 | assert.equal(await page.$('.test-fullscreen'), null); 11 | }; 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/navClick.js: -------------------------------------------------------------------------------- 1 | export const navClick = async (page, selector) => 2 | await Promise.all([ 3 | page.waitForNavigation(), 4 | await (await page.waitFor(selector)).click(), 5 | ]); 6 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/privacy/excludePrivateFromHomePage.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { getVizIdList } from './getVizIdList'; 3 | import { excludePrivateFromPage } from './excludePrivateFromPage'; 4 | 5 | export const excludePrivateFromHomePage = (my) => 6 | excludePrivateFromPage(my, { 7 | url: 'http://localhost:3000/', 8 | parentSelector: '.test-home-page-viz-previews', 9 | }); 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/privacy/excludePrivateFromProfilePage.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { excludePrivateFromPage } from './excludePrivateFromPage'; 3 | 4 | export const excludePrivateFromProfilePage = (my) => 5 | excludePrivateFromPage(my, { 6 | url: 'http://localhost:3000/ci', 7 | parentSelector: '.test-profile-page-viz-previews', 8 | }); 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/privacy/getVizIdList.js: -------------------------------------------------------------------------------- 1 | export const getVizIdList = async (page, parentHandle) => 2 | await page.evaluate( 3 | (parentNode) => 4 | Array.from(parentNode.querySelectorAll('.test-viz-preview'), (el) => 5 | el.getAttribute('data-test-viz-id') 6 | ), 7 | parentHandle 8 | ); 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/privacy/includePrivateOnProfilePage.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { excludePrivateFromPage } from './excludePrivateFromPage'; 3 | 4 | export const includePrivateOnProfilePage = (my) => 5 | excludePrivateFromPage(my, { 6 | url: 'http://localhost:3000/ci', 7 | parentSelector: '.test-profile-page-viz-previews', 8 | expectPrivate: true, 9 | }); 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/privacy/vizFound.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | 3 | export const vizFound = (my) => async () => { 4 | await my.page.goto(my.privateVizURL); 5 | await my.page.waitFor('.test-viewer'); 6 | }; 7 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/privacy/vizNotFound.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | 3 | export const vizNotFound = (my) => async () => { 4 | await my.page.reload(); 5 | await my.page.waitFor('.test-viz-not-found'); 6 | }; 7 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/realtime/index.js: -------------------------------------------------------------------------------- 1 | import { setupRealtimeViz } from './setupRealtimeViz'; 2 | import { saveAndRestoreChanges } from './saveAndRestoreChanges'; 3 | 4 | export const realtime = (my) => () => { 5 | before(setupRealtimeViz(my)); 6 | it('should save and restore changes', saveAndRestoreChanges(my)); 7 | }; 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/realtime/saveAndRestoreChanges.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | //import { convenience } from './convenience'; 3 | 4 | export const saveAndRestoreChanges = (my) => async () => { 5 | //const page = my 6 | //// Open editor to index.html. 7 | //await navClick('.test-toggle-editor'); 8 | //await page.waitFor('.test-editor'); 9 | //await navClick('.test-editor-files-section'); 10 | //await navClick('.test-editor-file-entry-index-html'); 11 | }; 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/retry.js: -------------------------------------------------------------------------------- 1 | export const retry = (fn, ms) => 2 | new Promise((resolve) => { 3 | fn() 4 | .then(resolve) 5 | .catch(() => { 6 | setTimeout(() => { 7 | console.log('retrying...'); 8 | retry(fn, ms).then(resolve); 9 | }, ms); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoCI/test/vizCreation/navigateToCreateVizPage.js: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | import { navClick } from '../navClick'; 3 | 4 | export const navigateToCreateVizPage = (my) => async () => { 5 | const { page } = my; 6 | 7 | // Pop open the menu, so the "create visualization" button appears. 8 | await (await page.waitFor('.test-avatar-me')).click(); 9 | 10 | await navClick(page, '.test-create-viz'); 11 | 12 | assert.equal(page.url(), 'http://localhost:3000/create-viz'); 13 | }; 14 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "react-app" 3 | } 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | *.swp 4 | package-lock.json 5 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/packages/neoFrontend/public/favicon.ico -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/public/images/GitHub-Mark-120px-plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/packages/neoFrontend/public/images/GitHub-Mark-120px-plus.png -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/public/images/mountains.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/packages/neoFrontend/public/images/mountains.png -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/public/images/unfurl-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/packages/neoFrontend/public/images/unfurl-logo.png -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "VizHub", 3 | "name": "VizHub", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#f6eee3", 14 | "background_color": "#fffbf6" 15 | } 16 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/ConnectionContext/index.js: -------------------------------------------------------------------------------- 1 | import React, { createContext } from 'react'; 2 | import { useConnection } from './useConnection'; 3 | 4 | export const ConnectionContext = createContext(); 5 | 6 | export const ConnectionProvider = ({ children }) => ( 7 | 8 | {children} 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/ErrorContext/index.js: -------------------------------------------------------------------------------- 1 | import React, { createContext, useState } from 'react'; 2 | 3 | export const ErrorContext = createContext(); 4 | 5 | export const ErrorProvider = ({ children, fallback }) => { 6 | const [error, setError] = useState(); 7 | const contextValue = { setError }; 8 | 9 | return error ? ( 10 | fallback(error) 11 | ) : ( 12 | 13 | {children} 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/ForksLink/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Link } from 'react-router-dom'; 3 | 4 | export const Wrapper = styled.div` 5 | ${(props) => (props.isSmall ? 'font-size: 10px;' : '')} 6 | `; 7 | 8 | export const VizLink = styled(Link)` 9 | font-style: italic; 10 | `; 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/Input/index.js: -------------------------------------------------------------------------------- 1 | export { Input } from './Input'; 2 | export { Autocomplete } from './Autocomplete'; 3 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/Input/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Wrapper = styled.input` 4 | height: 100%; 5 | ${(props) => (props.size === 'grow' ? 'flex: 1;' : '')} 6 | ${(props) => (props.size === 'large' ? 'width: 87px;' : '')} 7 | font-size: 16px; 8 | border: 1px solid ${(props) => props.theme.lightBorder}; 9 | border-radius: 4px; 10 | padding-left: 14px; 11 | `; 12 | 13 | export const FocusableFragment = styled.div` 14 | height: 100%; 15 | display: flex; 16 | flex: 1; 17 | `; 18 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/LoadingScreen/animationDelay.js: -------------------------------------------------------------------------------- 1 | // The time in ms before kicking off the loading screen. 2 | // If the data request finishes before this time, 3 | // the loading screen will never appear. 4 | export const blankScreenDelay = 200; 5 | 6 | // The minimum time in ms to keep the loading screen visible, 7 | // in the case that loading the data takes longer than 8 | // blankScreenDelay. 9 | export const animationDelay = 1000; 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/NavBar/NeoNavBar/UserActionsMenu/arrowDown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/NavBar/NeoNavBar/UserActionsMenu/useCloseOnGlobalClick.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | // Close the menu if the user clicks anywhere on the page. 4 | export const useCloseOnGlobalClick = (isOpen, close) => { 5 | useEffect(() => { 6 | if (isOpen) { 7 | document.addEventListener('click', close); 8 | return () => { 9 | document.removeEventListener('click', close); 10 | }; 11 | } 12 | }, [isOpen, close]); 13 | }; 14 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/NavBar/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { NeoNavBar } from './NeoNavBar'; 3 | 4 | export const NavBar = (props) => ( 5 | 11 | ); 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/RealtimeModulesContext/index.js: -------------------------------------------------------------------------------- 1 | import React, { createContext } from 'react'; 2 | import { useRealtimeModules } from './useRealtimeModules'; 3 | 4 | export const RealtimeModulesContext = createContext(); 5 | 6 | // Lazy load realtime-related modules. 7 | export const RealtimeModulesProvider = ({ children }) => ( 8 | 9 | {children} 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/RealtimeModulesContext/useRealtimeModules.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | export const useRealtimeModules = () => { 4 | const [realtimeModules, setRealtimeModules] = useState(); 5 | useEffect(() => { 6 | import('./realtimeModules').then(setRealtimeModules); 7 | }, []); 8 | return realtimeModules; 9 | }; 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/SavingIndicator/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Flex } from '../styles'; 3 | import { Indicator, Text } from './styles'; 4 | 5 | export const SavingIndicator = ({ saving }) => ( 6 | 7 | {saving ? 'Saving...' : 'Saved'} 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/SavingIndicator/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Text = styled.span` 4 | font-style: normal; 5 | font-weight: normal; 6 | font-size: ${(props) => props.theme.text.tiny}; 7 | line-height: 20px; 8 | color: #797979; 9 | margin-right: 8px; 10 | `; 11 | 12 | export const Indicator = styled.div` 13 | width: 10px; 14 | height: 10px; 15 | 16 | background: ${(props) => (props.saving ? '#FFB951' : '#73D129')}; 17 | border-radius: 100px; 18 | `; 19 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/UserPreviewList/fetchUserSearchResults.js: -------------------------------------------------------------------------------- 1 | export const fetchUserSearchResults = async (query, offset = 0) => { 2 | const url = `/api/user/search?query=${query}&offset=${offset}`; 3 | const response = await fetch(url, { 4 | method: 'GET', 5 | credentials: 'same-origin', 6 | }); 7 | return await response.json(); 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/UserPreviewList/index.js: -------------------------------------------------------------------------------- 1 | export { UserPreviewList } from './UserPreviewList'; 2 | export { useUsers } from './useUsers'; 3 | export { useUserPreviewController } from './useUserPreviewController'; 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/VizPreview/index.js: -------------------------------------------------------------------------------- 1 | export { VizPreviews } from './styles'; 2 | export { VizPreview } from './VizPreview'; 3 | export { LiveVizPreview } from './LiveVizPreview'; 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/VizzesGrid/Vizzes/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Wrapper = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | margin-bottom: 10px; 7 | `; 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/VizzesGrid/VizzesSortForm/index.js: -------------------------------------------------------------------------------- 1 | export { VizzesSortForm } from './VizzesSortForm'; 2 | export { useVizzesSort } from './useVizzesSort'; 3 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/Voter/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Container = styled.div` 4 | display: flex; 5 | align-items: center; 6 | font-size: 10px; 7 | user-select: none; 8 | justify-content: flex-end; 9 | `; 10 | 11 | export const VoteIcon = styled.div` 12 | margin-left: ${(props) => (props.leftmost ? '5px' : '13px')}; 13 | margin-right: 4px; 14 | cursor: ${(props) => (props.canVote ? 'pointer' : 'not-allowed')}; 15 | display: flex; 16 | `; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/authentication/AuthContext/fetchMe.js: -------------------------------------------------------------------------------- 1 | export const fetchMe = async () => { 2 | const response = await fetch('/api/auth/me', { 3 | method: 'GET', 4 | credentials: 'same-origin', 5 | }); 6 | const data = await response.json(); 7 | return data.me; 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/authentication/getJWTForGoogle.js: -------------------------------------------------------------------------------- 1 | export const getJWTForGoogle = async (code) => { 2 | const response = await fetch('/api/auth/google', { 3 | method: 'POST', 4 | headers: { 5 | Accept: 'application/json', 6 | 'Content-Type': 'application/json', 7 | }, 8 | body: JSON.stringify({ code }), 9 | }); 10 | return await response.json(); 11 | }; 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/authentication/index.js: -------------------------------------------------------------------------------- 1 | export { AuthContext, AuthProvider } from './AuthContext'; 2 | export { 3 | AUTH_PENDING, 4 | GITHUB_OAUTH_URL, 5 | CI_AUTH_PATH, 6 | CI_USER_CODE, 7 | GOOGLE_OAUTH_URL, 8 | FACEBOOK_OAUTH_URL, 9 | } from './constants'; 10 | export { getJWT } from './getJWT'; 11 | export { getJWTForGoogle } from './getJWTForGoogle'; 12 | export { postMessageToOpener } from './postMessageToOpener'; 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/authentication/postMessageToOpener.js: -------------------------------------------------------------------------------- 1 | export const postMessageToOpener = (vizHubAuthenticatedUser) => { 2 | window.opener.postMessage( 3 | { vizHubAuthenticatedUser }, 4 | window.opener.location 5 | ); 6 | }; 7 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/authentication/signInFlow/index.js: -------------------------------------------------------------------------------- 1 | import { openPopup } from './openPopup'; 2 | import { listenForMe } from './listenForMe'; 3 | import { AUTH_PENDING } from '../constants'; 4 | 5 | // Implements a popup-based OAuth sign in flow. 6 | export const signInFlow = (setMe) => () => { 7 | setMe(AUTH_PENDING); 8 | const popup = openPopup(); 9 | // TODO make this a Promise 10 | listenForMe((me) => { 11 | popup.close(); 12 | setMe(me); 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/authentication/signInFlow/listenForMe.js: -------------------------------------------------------------------------------- 1 | export const listenForMe = (onMeReceived) => { 2 | window.addEventListener('message', ({ data }) => { 3 | if (data.vizHubAuthenticatedUser) { 4 | onMeReceived(data.vizHubAuthenticatedUser); 5 | } 6 | }); 7 | }; 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/authentication/signInFlow/openPopup.js: -------------------------------------------------------------------------------- 1 | // Opens a popup window that uses OAuth to authenticate. 2 | // The popup ends up at the route /authenticated (see Authenticated.js). 3 | export const openPopup = () => { 4 | return window.open('/auth', 'vithub-auth'); 5 | }; 6 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/authentication/signOutFlow/fetchSignOut.js: -------------------------------------------------------------------------------- 1 | // Hitting this endpoint clears the httpOnly cookie that contains the auth JWT. 2 | export const fetchSignOut = () => fetch('/api/auth/signOut', { method: 'GET' }); 3 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/authentication/signOutFlow/index.js: -------------------------------------------------------------------------------- 1 | import { AUTH_PENDING } from '../constants'; 2 | import { fetchSignOut } from './fetchSignOut'; 3 | 4 | export const signOutFlow = (setMe) => () => { 5 | setMe(AUTH_PENDING); 6 | fetchSignOut().then(({ ok }) => { 7 | if (ok) { 8 | setMe(null); 9 | } else { 10 | throw new Error( 11 | 'Something went wrong with signing out. Server is down perhaps?' 12 | ); 13 | } 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { App } from './App'; 4 | 5 | // A place to put feature previews and easter eggs. 6 | window.vizhub = {}; 7 | 8 | // Wait for prefetched fonts. 9 | window.onload = () => { 10 | ReactDOM.render(, document.getElementById('root')); 11 | }; 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/CreatingVizFromScratchPage/createVizFromScratch.js: -------------------------------------------------------------------------------- 1 | import { AUTH_PENDING } from '../../authentication'; 2 | import { fetchCreateVizFromScratch } from './fetchCreateVizFromScratch'; 3 | 4 | export const createVizFromScratch = async (me, history) => { 5 | if (me === AUTH_PENDING) { 6 | return; 7 | } 8 | const { error, id } = await fetchCreateVizFromScratch(); 9 | if (error) { 10 | console.log(error); 11 | } else { 12 | history.push({ 13 | pathname: `/${me.userName}/${id}`, 14 | }); 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/CreatingVizFromScratchPage/fetchCreateVizFromScratch.js: -------------------------------------------------------------------------------- 1 | export const fetchCreateVizFromScratch = async () => { 2 | const response = await fetch('/api/visualization/create', { 3 | credentials: 'include', 4 | }); 5 | return await response.json(); 6 | }; 7 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/ErrorPage/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Message } from './styles'; 3 | 4 | export const ErrorPage = ({ error }) => ( 5 | {error.message} 6 | ); 7 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/ErrorPage/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Message = styled.div` 4 | height: 100vh; 5 | display: flex; 6 | align-items: center; 7 | justify-content: center; 8 | font-size: 20px; 9 | font-weight: bold; 10 | color: ${(props) => props.theme.attentionGrabber}; 11 | padding: 10px; 12 | box-sizing: border-box; 13 | text-align: center; 14 | `; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/ForksPage/fetchPageData.js: -------------------------------------------------------------------------------- 1 | export const fetchPageData = async (vizId, offset) => { 2 | const url = `/api/visualization/get/${vizId}/forks?offset=${offset}`; 3 | const response = await fetch(url, { 4 | method: 'GET', 5 | credentials: 'same-origin', 6 | }); 7 | return await response.json(); 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/ForksPage/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Text = styled.div` 4 | max-width: 960px; 5 | padding: 10px; 6 | `; 7 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/HomePage/HomePageDataContext.js: -------------------------------------------------------------------------------- 1 | import React, { createContext } from 'react'; 2 | import { useHomePageData } from './useHomePageData'; 3 | 4 | export const HomePageDataContext = createContext(); 5 | 6 | export const HomePageDataProvider = ({ sort, fallback, children }) => { 7 | const homePageData = useHomePageData({ sort }); 8 | 9 | return homePageData ? ( 10 | 11 | {children} 12 | 13 | ) : ( 14 | fallback 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/HomePage/Sort/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { VizzesSortForm } from '../../../VizzesGrid/VizzesSortForm'; 3 | import { Container } from './styles'; 4 | 5 | export const Sort = (props) => ( 6 | 7 | {' '} 8 | {' '} 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/HomePage/Sort/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Container = styled.div` 4 | display: flex; 5 | justify-content: space-between; 6 | align-items: center; 7 | margin: 10px 0px 12px 0px; 8 | flex-wrap: wrap; 9 | `; 10 | 11 | export const Header = styled.div` 12 | font-weight: 600; 13 | font-size: 28px; 14 | color: #353433; 15 | `; 16 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/HomePage/Vizzes.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { Vizzes as VizzesPresentation } from '../../VizzesGrid/Vizzes'; 3 | import { HomePageDataContext } from './HomePageDataContext'; 4 | 5 | export const Vizzes = () => ( 6 | 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/HomePage/fetchHomePageData.js: -------------------------------------------------------------------------------- 1 | export const fetchHomePageData = async ({ offset, sort }) => { 2 | const url = `/api/visualization/home?offset=${offset}&sort=${sort}`; 3 | const response = await fetch(url, { 4 | method: 'GET', 5 | credentials: 'same-origin', 6 | }); 7 | return await response.json(); 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/HomePage/styles.js: -------------------------------------------------------------------------------- 1 | import styled, { createGlobalStyle } from 'styled-components'; 2 | 3 | export const HtmlStylesOverride = createGlobalStyle` 4 | html { 5 | overflow-y: scroll; 6 | } 7 | `; 8 | 9 | export const HorizontalSplit = styled.div` 10 | display: flex; 11 | justify-content: space-between; 12 | align-items: center; 13 | flex-wrap: wrap; 14 | margin-bottom: 20px; 15 | `; 16 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/HomePage/useHomePageData.js: -------------------------------------------------------------------------------- 1 | import { useCallback } from 'react'; 2 | import { usePaginatedVizzes } from '../../VizzesGrid/usePaginatedVizzes'; 3 | import { fetchHomePageData } from './fetchHomePageData'; 4 | 5 | export const useHomePageData = ({ sort }) => { 6 | const fetchData = useCallback( 7 | (offset) => { 8 | return fetchHomePageData({ offset, sort }); 9 | }, 10 | [sort] 11 | ); 12 | 13 | return usePaginatedVizzes(fetchData); 14 | }; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/NotFoundPage/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Message } from './styles'; 3 | 4 | export const NotFoundPage = () => Page Not Found; 5 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/NotFoundPage/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Message = styled.div` 4 | height: 100vh; 5 | display: flex; 6 | align-items: center; 7 | justify-content: center; 8 | font-size: 20px; 9 | font-weight: bold; 10 | color: ${(props) => props.theme.attentionGrabber}; 11 | padding: 10px; 12 | box-sizing: border-box; 13 | text-align: center; 14 | `; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/ProfilePage/Body/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { isMobile } from '../../../mobileMods'; 3 | import { Centering } from '../../styles'; 4 | 5 | export const ProfileMenuBar = styled(Centering)` 6 | flex-direction: ${isMobile ? 'column' : 'row'}; 7 | align-items: ${isMobile ? 'center' : 'unset'}; 8 | `; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/SearchResultsPage/PageDataContext.js: -------------------------------------------------------------------------------- 1 | import React, { createContext } from 'react'; 2 | import { usePageData } from './usePageData'; 3 | 4 | export const PageDataContext = createContext(); 5 | 6 | export const PageDataProvider = ({ fallback, children }) => { 7 | const pageData = usePageData(); 8 | 9 | return pageData ? ( 10 | 11 | {children} 12 | 13 | ) : ( 14 | fallback 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/SearchResultsPage/Vizzes.js: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { Vizzes as VizzesPresentation } from '../../VizzesGrid/Vizzes'; 3 | import { PageDataContext } from './PageDataContext'; 4 | 5 | export const Vizzes = () => ( 6 | 7 | ); 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/SearchResultsPage/fetchPageData.js: -------------------------------------------------------------------------------- 1 | export const fetchPageData = async (query, offset) => { 2 | const url = `/api/visualization/search?query=${query}&offset=${offset}`; 3 | const response = await fetch(url, { 4 | method: 'GET', 5 | credentials: 'same-origin', 6 | }); 7 | return await response.json(); 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/UpgradeCanceledPage/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { NavBar } from '../../NavBar'; 3 | import { Wrapper, Content } from '../styles'; 4 | 5 | export const UpgradeCanceledPage = () => { 6 | return ( 7 | <> 8 | 9 | 10 | Upgrade canceled. 11 | 12 | 13 | ); 14 | }; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/UpgradeSuccessPage/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Wrapper = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | `; 8 | 9 | export const Large = styled.div` 10 | font-size: ${(props) => props.theme.text.large}; 11 | margin-top: 150px; 12 | margin-bottom: 30px; 13 | `; 14 | 15 | export const Blurb = styled.div` 16 | margin-bottom: 30px; 17 | `; 18 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizHubStatsPage/RecordViz/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Wrapper = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | margin-top: 20px; 7 | `; 8 | 9 | export const SVG = styled.svg` 10 | border: 1px solid gray; 11 | `; 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizHubStatsPage/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Stats = styled.div``; 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/BottomButtons/NewTop.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TopList, TopListItem } from './styles'; 3 | 4 | export const NewTop = ({ onNewFileListItemClick }) => ( 5 | 6 | new file 7 | 8 | ); 9 | // new directory 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/CodeEditor/CodeArea/CodeAreaCodeMirror5/changeObjToOp.js: -------------------------------------------------------------------------------- 1 | export const changeObjToOp = ({ from, removed, text }, path, doc) => { 2 | const op = []; 3 | const i = doc.indexFromPos(from); 4 | const sd = removed.join('\n'); 5 | const si = text.join('\n'); 6 | const p = path.concat(i); 7 | if (sd) { 8 | op.push({ sd, p }); 9 | } 10 | if (si) { 11 | op.push({ si, p }); 12 | } 13 | return op; 14 | }; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/CodeEditor/CodeArea/CodeAreaCodeMirror5/overlays/index.js: -------------------------------------------------------------------------------- 1 | export { linkOverlay } from './linkOverlay'; 2 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/CodeEditor/CodeArea/CodeAreaCodeMirror5/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Z_NEW_STACKING_CONTEXT } from '../../../../../../../styles'; 3 | 4 | export const Wrapper = styled.div` 5 | flex: 1; 6 | font-family: ${(props) => props.theme.defaultCodingFontFamily}; 7 | position: relative; 8 | min-height: 0px; 9 | z-index: ${Z_NEW_STACKING_CONTEXT}; 10 | `; 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/CodeEditor/CodeArea/CodeAreaPre/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Wrapper = styled.pre` 4 | flex: 1; 5 | padding: 10px; 6 | margin: 0; 7 | font-family: ${(props) => props.theme.defaultCodingFontFamily}; 8 | line-height: 1.93; 9 | `; 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/CodeEditor/CodeArea/CodeAreaTextarea/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Wrapper = styled.textarea` 4 | flex: 1; 5 | padding: 10px; 6 | margin: 0; 7 | font-family: ${(props) => props.theme.defaultCodingFontFamily}; 8 | line-height: 1.93; 9 | background-color: transparent; 10 | color: #ffffff; 11 | border: none; 12 | resize: none; 13 | outline: none; 14 | `; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/CodeEditor/CodeArea/index.js: -------------------------------------------------------------------------------- 1 | //import { CodeAreaPre } from './CodeAreaPre'; 2 | //import { CodeAreaTextarea } from './CodeAreaTextarea'; 3 | import { CodeAreaCodeMirror5 } from './CodeAreaCodeMirror5'; 4 | 5 | //export const CodeArea = CodeAreaPre; 6 | //export const CodeArea = CodeAreaTextarea; 7 | export const CodeArea = CodeAreaCodeMirror5; 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/CodeEditor/CodeEditorHeader/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Wrapper = styled.div` 4 | display: flex; 5 | justify-content: space-between; 6 | align-items: center; 7 | padding-left: 10px; 8 | background-color: ${(props) => props.theme.editor.headerBackgroundColor}; 9 | `; 10 | 11 | export const Icons = styled.div` 12 | display: flex; 13 | `; 14 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/CodeEditor/useFileIndex.js: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react'; 2 | import { getVizFileIndex } from 'vizhub-presenters'; 3 | import { useValue } from '../../../../../useValue'; 4 | 5 | export const useFileIndex = (viz$, activeFile) => 6 | useValue( 7 | viz$, 8 | useMemo(() => getVizFileIndex(activeFile), [activeFile]) 9 | ); 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/CodeEditor/usePath.js: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react'; 2 | 3 | export const getPath = (fileIndex, field) => ['files', fileIndex, field]; 4 | 5 | export const usePath = (fileIndex, field = 'text') => 6 | useMemo(() => getPath(fileIndex, field), [fileIndex, field]); 7 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/FilesSection/FileTree/Directory/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | const arrowXOffset = 2; 4 | export const ArrowWrapper = styled.div` 5 | position: absolute; 6 | left: ${(props) => 7 | props.theme.editorEntryHorizontalPadding + 8 | props.theme.editorEntryIndentation * (props.indent - 1) - 9 | arrowXOffset}px; 10 | transition: transform 150ms; 11 | transform: rotate(${(props) => props.rotate}deg); 12 | `; 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/FilesSection/FileTree/addPath.js: -------------------------------------------------------------------------------- 1 | export const addPath = (newName, fileName) => { 2 | const path = fileName.split('/'); 3 | path[path.length - 1] = newName; 4 | return path.join('/'); 5 | }; 6 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/FilesSection/FileTree/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Clickable } from '../../../../../../styles'; 3 | import { FileStyle } from '../styles'; 4 | 5 | export const FileEntry = styled(Clickable)` 6 | ${FileStyle} 7 | text-decoration: ${(props) => (props.isActive ? 'underline' : 'none')}; 8 | `; 9 | 10 | export const DirectoryEntry = styled(Clickable)` 11 | ${FileStyle} 12 | position: relative; 13 | `; 14 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/FilesSection/initialOpenDirectories.js: -------------------------------------------------------------------------------- 1 | // When a page is opened with an active file, 2 | // make sure all the directories leading to that file 3 | // are opened automatically. 4 | export const initialOpenDirectories = (activeFile) => { 5 | const openDirectories = {}; 6 | if (activeFile) { 7 | const path = activeFile.split('/'); 8 | for (let i = 1; i < path.length; i++) { 9 | openDirectories[path.slice(0, i).join('/')] = true; 10 | } 11 | } 12 | return openDirectories; 13 | }; 14 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/FilesSection/styles.js: -------------------------------------------------------------------------------- 1 | export const FileStyle = (props) => ` 2 | display: flex; 3 | align-items: center; 4 | height: ${props.theme.editorEntryHeight}px; 5 | padding-left: ${ 6 | props.theme.editorEntryHorizontalPadding + 7 | props.theme.editorEntryIndentation * props.indent 8 | }px; 9 | border-left: ${props.theme.editorEntryLeftBorderSize}px solid 10 | ${props.isActive ? props.theme.editorFileActiveColor : 'transparent'}; 11 | `; 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/themes/index.js: -------------------------------------------------------------------------------- 1 | export { light } from './light'; 2 | export { ubuntu } from './ubuntu'; 3 | export { oneDark } from './oneDark'; 4 | export { material } from './material'; 5 | export { dracula } from './dracula'; 6 | export { monokai } from './monokai'; 7 | export { vizHub } from './vizHub'; 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Editor/themes/light.js: -------------------------------------------------------------------------------- 1 | export const light = { 2 | headerHeight: 32, 3 | infoAvatarHeight: 64, 4 | infoAvatarPadding: 12, 5 | commentAvatarHeight: 32, 6 | foreground: 'black', 7 | background: 'white', 8 | textMain: '#121212', 9 | textLight: '#636363', 10 | }; 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/EmbedModePresenter.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FullScreen, EmbedFooter } from './FullScreen'; 3 | 4 | export const EmbedModePresenter = () => ( 5 | 6 | 7 | 8 | ); 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/FullScreen/index.js: -------------------------------------------------------------------------------- 1 | export { FullScreen } from './FullScreen'; 2 | export { FullScreenFooter } from './FullScreenFooter'; 3 | export { EmbedFooter } from './EmbedFooter'; 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/FullScreenModePresenter.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { FullScreen, FullScreenFooter } from './FullScreen'; 3 | 4 | export const FullScreenModePresenter = () => { 5 | return ( 6 | 7 | 8 | 9 | ); 10 | }; 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Head/EditorToggler/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Clickable } from '../../../../../styles'; 3 | 4 | export const Wrapper = styled(Clickable)` 5 | width: 125px; 6 | height: ${(props) => props.theme.headHeight}px; 7 | display: flex; 8 | align-items: center; 9 | justify-content: center; 10 | `; 11 | 12 | export const Text = styled.div` 13 | font-weight: 600; 14 | margin-left: 10px; 15 | user-select: none; 16 | `; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Mini/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { Z_ABOVE } from '../../../../styles'; 3 | 4 | export const Wrapper = styled.div` 5 | position: fixed; 6 | right: 25px; 7 | bottom: 10px; 8 | width: ${(props) => props.theme.miniWidth}px; 9 | 10 | display: flex; 11 | flex-direction: column; 12 | z-index: ${Z_ABOVE}; 13 | `; 14 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/PlayPauseControl/styles.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/PlayPauseControl/styles.js -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/RecoveryModeBanner/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Wrapper, Side, Message } from './styles'; 3 | import { Button } from '../../../../Button'; 4 | 5 | export const RecoveryModeBanner = ({ exitRecoveryMode }) => ( 6 | 7 | 8 | You are in recovery mode. 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/RecoveryModeBanner/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Wrapper = styled.div` 4 | display: flex; 5 | justify-content: space-between; 6 | height: 80px; 7 | background: #ff8126; 8 | `; 9 | 10 | export const Side = styled.div` 11 | flex: 1; 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | `; 16 | 17 | export const Message = styled.div` 18 | font-weight: bold; 19 | `; 20 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Viewer/DescriptionSection/responsiveYouTube.js: -------------------------------------------------------------------------------- 1 | // Wraps YouTube embeds in a styled wrapper, 2 | // so that the embed resizes nicely, 3 | // preserving aspect ratio. 4 | export const responsiveYouTube = (html) => 5 | html.replace( 6 | //g, 7 | (match) => `
${match}
` 8 | ); 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Viewer/TitleBar/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Wrapper = styled.div` 4 | margin: 20px 0 20px 0; 5 | display: flex; 6 | justify-content: space-between; 7 | align-items: center; 8 | flex-wrap: wrap; 9 | `; 10 | 11 | export const Title = styled.div` 12 | flex-grow: 1; 13 | font-size: 20px; 14 | `; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Viewer/VizFrame/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { LargeIcon } from '../../../../styles'; 3 | 4 | // Note that `position: relative;` is required due to useDimensions 5 | export const Wrapper = styled.div` 6 | display: flex; 7 | flex-direction: column; 8 | position: relative; 9 | `; 10 | 11 | export const LargeIconRightmost = styled(LargeIcon)` 12 | border-bottom-right-radius: ${(props) => props.theme.borderRadiusSmall}px; 13 | `; 14 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/Viewer/useLicenseToHtmlRenderer.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | export const useLicenseToHtmlRenderer = () => { 4 | const [renderer, setRenderer] = useState(() => () => 'Loading...'); 5 | 6 | useEffect(() => { 7 | (async () => { 8 | const renderer = (await import('spdx-to-html')).default; 9 | setRenderer(() => (spdxLicenseString) => 10 | `${renderer(spdxLicenseString)} Licensed` 11 | ); 12 | })(); 13 | }, [setRenderer]); 14 | 15 | return renderer; 16 | }; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/Body/useListener.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | export const useListener = (type, listener, element = window) => { 4 | useEffect(() => { 5 | if (element) { 6 | element.addEventListener(type, listener); 7 | return () => { 8 | element.removeEventListener(type, listener); 9 | }; 10 | } 11 | }, [type, listener, element]); 12 | }; 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/CheckBox/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { RadioButtonSVG } from '../../../svg'; 3 | import { Wrapper, Label } from '../RadioButton/styles'; 4 | 5 | export const CheckBox = ({ label, onClick, isActive }) => { 6 | return ( 7 | 8 | 9 | 10 | 11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/DeleteVizContext/fetchDeleteViz.js: -------------------------------------------------------------------------------- 1 | export const fetchDeleteViz = async (visualization) => { 2 | const response = await fetch(`/api/visualization/delete`, { 3 | method: 'POST', 4 | credentials: 'same-origin', 5 | headers: { 6 | 'Content-Type': 'application/json', 7 | }, 8 | body: JSON.stringify({ 9 | id: visualization.info.id, 10 | }), 11 | }); 12 | 13 | return await response.json(); 14 | }; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/PrettierContext/index.js: -------------------------------------------------------------------------------- 1 | import React, { createContext } from 'react'; 2 | import { usePrettier } from './usePrettier'; 3 | 4 | export const PrettierContext = createContext(); 5 | 6 | // This context is responsible for loading and running Prettier 7 | // to auto-format the active file from within the editor. 8 | export const PrettierProvider = ({ children }) => ( 9 | 10 | {children} 11 | 12 | ); 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/PrettierContext/prettierModules.js: -------------------------------------------------------------------------------- 1 | import prettier from 'prettier/standalone'; 2 | import parserBabel from 'prettier/parser-babel'; 3 | import parserHTML from 'prettier/parser-html'; 4 | import parserCSS from 'prettier/parser-postcss'; 5 | import parserMD from 'prettier/parser-markdown'; 6 | 7 | export const plugins = [parserBabel, parserHTML, parserCSS, parserMD]; 8 | 9 | export { prettier }; 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/RadioButton/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Wrapper = styled.div` 4 | cursor: pointer; 5 | display: flex; 6 | align-items: center; 7 | padding-right: 32px; 8 | `; 9 | 10 | export const Label = styled.div` 11 | margin-left: 8px; 12 | font-size: 16px; 13 | `; 14 | 15 | export const GroupWrapper = styled.div` 16 | display: flex; 17 | ${(props) => (props.vertical ? 'flex-direction: column;' : '')} 18 | `; 19 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/RunContext/generateRunId.js: -------------------------------------------------------------------------------- 1 | export const generateRunId = (() => { 2 | let runId = 0; 3 | return () => runId++ % 100; 4 | })(); 5 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/RunContext/index.js: -------------------------------------------------------------------------------- 1 | import React, { createContext } from 'react'; 2 | import { useRun } from './useRun'; 3 | 4 | export const RunContext = createContext(); 5 | 6 | // This context is responsible for figuring out when to re-run the code, 7 | // and when to recompute and store bundle.js. 8 | export const RunProvider = ({ children }) => ( 9 | {children} 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/RunContext/updateLastUpdatedTimestamp.js: -------------------------------------------------------------------------------- 1 | import { timestamp } from 'vizhub-entities'; 2 | 3 | export const updateLastUpdatedTimestamp = (viz$, submitVizInfoOp) => { 4 | const { info } = viz$.getValue(); 5 | const before = info.lastUpdatedTimestamp; 6 | const after = timestamp(); 7 | const op = [{ p: ['lastUpdatedTimestamp'], od: before, oi: after }]; 8 | submitVizInfoOp(op); 9 | }; 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/SettingsContext/SetHeight/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Input } from '../../../../Input'; 3 | import { Label } from './styles'; 4 | import { FormRow } from '../../styles'; 5 | 6 | export const SetHeight = ({ height, setHeight }) => ( 7 | 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/SettingsContext/SetHeight/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Label = styled.label` 4 | margin-left: 16px; 5 | `; 6 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/SettingsContext/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Ad = styled.div` 4 | font-style: normal; 5 | font-weight: normal; 6 | font-size: 16px; 7 | line-height: 20px; 8 | color: #ff006b; 9 | 10 | a { 11 | color: inherit; 12 | text-decoration: underline; 13 | } 14 | `; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/ShareContext/CollaboratorsBody/fetchUser.js: -------------------------------------------------------------------------------- 1 | import { fetchUsers } from './fetchUsers'; 2 | 3 | export const fetchUser = async (userId) => { 4 | try { 5 | const result = await fetchUsers([userId]); 6 | return result.users[0]; 7 | } catch (error) { 8 | console.error(error); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/ShareContext/CollaboratorsBody/fetchUsers.js: -------------------------------------------------------------------------------- 1 | export const fetchUsers = async (userIds) => { 2 | const url = `/api/user/get?ids=${userIds}`; 3 | const response = await fetch(url, { 4 | method: 'GET', 5 | credentials: 'same-origin', 6 | }); 7 | return await response.json(); 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/ShareContext/CollaboratorsBody/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const UserName = styled.div` 4 | padding-left: 12px; 5 | `; 6 | 7 | export const CollaboratorListWrapper = styled.div` 8 | padding-top: 32px; 9 | `; 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/ShareContext/LinkBody/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { SubSectionDescription } from '../../styles'; 3 | import { TextCopier } from '../TextCopier'; 4 | 5 | export const LinkBody = () => { 6 | const url = window.location.href; 7 | 8 | return ( 9 | <> 10 | 11 | Sharing this link on social media will automatically create a preview. 12 | 13 | 14 | 15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/ShareContext/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const IFrame = styled.iframe` 4 | box-shadow: ${(props) => props.theme.shadow}; 5 | `; 6 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/ShareContext/useShare.js: -------------------------------------------------------------------------------- 1 | import { useState, useCallback } from 'react'; 2 | 3 | export const useShare = () => { 4 | const [isShowingShareModal, setIsShowingShareModel] = useState(false); 5 | 6 | const showShareModal = useCallback(() => { 7 | setIsShowingShareModel(true); 8 | }, []); 9 | 10 | const hideShareModal = useCallback(() => { 11 | setIsShowingShareModel(false); 12 | }, []); 13 | 14 | return { 15 | showShareModal, 16 | hideShareModal, 17 | isShowingShareModal, 18 | }; 19 | }; 20 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/URLStateContext/modes.js: -------------------------------------------------------------------------------- 1 | export const modes = { 2 | full: 'full', 3 | mini: 'mini', 4 | micro: 'micro', 5 | hide: 'hide', 6 | embed: 'embed', 7 | viewer: 'viewer', 8 | snippet: 'snippet', 9 | }; 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/VimModeContext/index.js: -------------------------------------------------------------------------------- 1 | import React, { createContext } from 'react'; 2 | import { useVimMode } from './useVimMode'; 3 | 4 | export const VimModeContext = createContext(); 5 | 6 | export const VimModeProvider = ({ children }) => ( 7 | 8 | {children} 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/VimModeContext/useVimMode.js: -------------------------------------------------------------------------------- 1 | import { useState, useCallback } from 'react'; 2 | export const defaultKeyMap = 'sublime'; 3 | export const useVimMode = () => { 4 | const [keyMap, setKeyMap] = useState(defaultKeyMap); 5 | const isVimMode = keyMap === 'vim'; 6 | 7 | const toggleVimMode = useCallback(() => { 8 | setKeyMap(isVimMode ? defaultKeyMap : 'vim'); 9 | }, [setKeyMap, isVimMode]); 10 | 11 | return { keyMap, isVimMode, toggleVimMode }; 12 | }; 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/VizPage/VizPageDataContext/fetchVizPageData.js: -------------------------------------------------------------------------------- 1 | export const fetchVizPageData = async (vizId) => { 2 | const response = await fetch(`/api/visualization/get/${vizId}`, { 3 | method: 'GET', 4 | credentials: 'same-origin', 5 | }); 6 | return await response.json(); 7 | }; 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/pages/fakeDataLoaded.js: -------------------------------------------------------------------------------- 1 | import { minSpinnerTime } from '../constants'; 2 | 3 | export const fakeDataLoaded = () => 4 | new Promise((resolve) => { 5 | setTimeout(() => { 6 | resolve('This is the fake data. Oh yeah.'); 7 | }, minSpinnerTime); 8 | }); 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/svg/DirectoryArrowSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const DirectoryArrowSVG = ({ height = 10, fill = 'currentcolor' }) => ( 4 | 5 | 6 | 7 | ); 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/svg/FullExitSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const FullExitSVG = ({ height = 16, fill = 'currentcolor' }) => ( 4 | 5 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/svg/FullSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const FullSVG = ({ height = 16, fill = 'currentcolor' }) => ( 4 | 5 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/svg/MicroSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const MicroSVG = ({ height = 16, fill = 'currentcolor' }) => ( 4 | 5 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/svg/MiniSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const MiniSVG = ({ height = 16, fill = 'currentcolor' }) => ( 4 | 5 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/svg/NewSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NewSVG = ({ height = 11, fill = 'currentcolor' }) => ( 4 | 5 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/svg/RadioButtonSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const RadioButtonSVG = ({ height = 20, isActive }) => ( 4 | 5 | 14 | {isActive ? ( 15 | 16 | ) : null} 17 | 18 | ); 19 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/svg/SplitSVG.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const SplitSVG = ({ height = 16, fill = 'currentcolor' }) => ( 4 | 5 | 6 | 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/theme/text.js: -------------------------------------------------------------------------------- 1 | // The idea here is to centrally define a limited set of 2 | // (font-size, font-weight) combinations that are used 3 | // exclusively across the app. 4 | export const text = { 5 | huge: '32px', 6 | large: '20px', 7 | medium: '16px', 8 | small: '14px', 9 | tiny: '12px', 10 | }; 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/utils/css/index.js: -------------------------------------------------------------------------------- 1 | // https://stackoverflow.com/questions/47836390/how-to-convert-a-camel-case-string-to-dashes-in-javascript 2 | const dashed = (camel) => camel.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase()); 3 | 4 | export const objectToCSS = (object) => 5 | object 6 | ? Object.entries(object) 7 | .map(([key, value]) => `${dashed(key)}:${value};`) 8 | .join('') 9 | : ''; 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/utils/object.js: -------------------------------------------------------------------------------- 1 | export const omitUndefined = (object) => { 2 | return Object.keys(object).reduce((refinedObject, key) => { 3 | if (object[key] !== undefined) { 4 | refinedObject[key] = object[key]; 5 | } 6 | 7 | return refinedObject; 8 | }, {}); 9 | }; 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/vizRealTimeHooks/index.js: -------------------------------------------------------------------------------- 1 | export { useViz } from './useViz'; 2 | export { useVizInfo } from './useVizInfo'; 3 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/vizRealTimeHooks/usePresence.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | export const usePresence = (shareDBDoc, collection, id) => { 4 | const [presence, setPresence] = useState(); 5 | 6 | useEffect(() => { 7 | if (!shareDBDoc) { 8 | return; 9 | } 10 | setPresence(shareDBDoc.connection.getDocPresence(collection, id)); 11 | }, [shareDBDoc, collection, id]); 12 | 13 | return presence; 14 | }; 15 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/vizRealTimeHooks/useSubmitOp.js: -------------------------------------------------------------------------------- 1 | import { useMemo } from 'react'; 2 | export const useSubmitOp = (shareDBDoc) => 3 | useMemo(() => { 4 | if (!shareDBDoc) { 5 | return undefined; 6 | } 7 | 8 | return (op, propsToFindDoc) => { 9 | if (op.length > 0) { 10 | const doc = 11 | shareDBDoc instanceof Function 12 | ? shareDBDoc(propsToFindDoc) 13 | : shareDBDoc; 14 | doc.submitOp(op); 15 | } 16 | }; 17 | }, [shareDBDoc]); 18 | -------------------------------------------------------------------------------- /vizhub-v2/packages/neoFrontend/src/vizRealTimeHooks/useSubmitPresence.js: -------------------------------------------------------------------------------- 1 | import { useMemo, useCallback } from 'react'; 2 | 3 | export const useSubmitPresence = (presence) => { 4 | const localPresence = useMemo(() => { 5 | if (!presence) return; 6 | return presence.create(); 7 | }, [presence]); 8 | 9 | return useCallback( 10 | (presenceObject) => { 11 | if (!localPresence) return; 12 | localPresence.submit(presenceObject, (error) => { 13 | if (error) throw error; 14 | }); 15 | }, 16 | [localPresence] 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /vizhub-v2/packages/presenters/src/computeSrcDoc.js: -------------------------------------------------------------------------------- 1 | import magicSandbox from './magicSandbox'; 2 | import { getComputedIndexHtml } from './getComputedIndexHtml'; 3 | 4 | const transform = (files) => 5 | files 6 | .filter((file) => file.name !== 'index.html') 7 | .reduce((accumulator, file) => { 8 | accumulator[file.name] = { 9 | content: file.text, 10 | }; 11 | return accumulator; 12 | }, {}); 13 | 14 | export const computeSrcDoc = (files) => { 15 | return magicSandbox(getComputedIndexHtml(files), transform(files)); 16 | }; 17 | -------------------------------------------------------------------------------- /vizhub-v2/packages/presenters/src/datasetViewModel.js: -------------------------------------------------------------------------------- 1 | import { Dataset } from 'vizhub-entities'; 2 | 3 | export class DatasetViewModel { 4 | constructor(dataset) { 5 | this.title = dataset.info.title; 6 | this.slug = dataset.info.slug; 7 | this.format = dataset.info.format; 8 | this.sourceName = dataset.info.sourceName; 9 | this.sourceUrl = dataset.info.sourceUrl; 10 | this.text = dataset.content.text; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/presenters/src/featureFlags.js: -------------------------------------------------------------------------------- 1 | export const isPackageJSONEnabled = true; 2 | -------------------------------------------------------------------------------- /vizhub-v2/packages/presenters/src/index.js: -------------------------------------------------------------------------------- 1 | export { VisualizationViewModel } from './visualizationViewModel'; 2 | export { DatasetViewModel } from './datasetViewModel'; 3 | export { bundle } from './bundle'; 4 | export { computeSrcDoc } from './computeSrcDoc'; 5 | export { getLibraries } from './getLibraries'; 6 | export { getComputedIndexHtml, setJSDOM } from './getComputedIndexHtml'; 7 | export * from './accessors'; 8 | export * from './packageJson'; 9 | -------------------------------------------------------------------------------- /vizhub-v2/packages/presenters/src/visualizationViewModel.js: -------------------------------------------------------------------------------- 1 | export class VisualizationViewModel { 2 | constructor(visualization) { 3 | this.id = visualization.id; 4 | this.files = visualization.content.files; 5 | this.title = visualization.info.title; 6 | this.description = visualization.info.description; 7 | this.width = 960; // visualization.info.width; 8 | this.height = visualization.info.height || 500; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/scoringService/src/index.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | import { startService } from './service'; 3 | startService({}); 4 | -------------------------------------------------------------------------------- /vizhub-v2/packages/serverGateways/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /vizhub-v2/packages/serverGateways/src/constants.js: -------------------------------------------------------------------------------- 1 | // Environment variables. 2 | export const mongoURI = process.env.VIZHUB_MONGO_URI; 3 | export const mongoDatabaseName = 'vizhub'; 4 | export const redisHost = process.env.VIZHUB_REDIS_HOST; 5 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | es6: true, 4 | node: true, 5 | }, 6 | extends: 'eslint:recommended', 7 | globals: { 8 | Atomics: 'readonly', 9 | SharedArrayBuffer: 'readonly', 10 | }, 11 | parserOptions: { 12 | ecmaVersion: 2018, 13 | sourceType: 'module', 14 | }, 15 | rules: { 16 | indent: ['error', 2], 17 | 'linebreak-style': ['error', 'unix'], 18 | quotes: ['error', 'single'], 19 | semi: ['error', 'always'], 20 | }, 21 | }; 22 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/docs/useCaseTemplate.md: -------------------------------------------------------------------------------- 1 | # Name of Use Case 2 | 3 | Actor: Foo 4 | 5 | Description goes here 6 | 7 | ## Triggers 8 | 9 | ## Preconditions 10 | 11 | ## Postconditions 12 | 13 | ## Normal Course of Events 14 | 15 | ## Alternative Courses of Events 16 | 17 | ## Exception 18 | 19 | ## Includes 20 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/docs/useCasesDiagram.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v2/packages/useCases/docs/useCasesDiagram.dia -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/accessControl/allowRead.js: -------------------------------------------------------------------------------- 1 | import { isOwner } from './isOwner'; 2 | import { isCollaborator } from './isCollaborator'; 3 | 4 | export const allowRead = (vizInfo, userId) => 5 | vizInfo.privacy === 'private' 6 | ? isOwner(vizInfo, userId) || isCollaborator(vizInfo, userId) 7 | : true; 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/accessControl/allowWrite.js: -------------------------------------------------------------------------------- 1 | import { isOwner } from './isOwner'; 2 | import { isCollaborator } from './isCollaborator'; 3 | 4 | export const allowWrite = (vizInfo, userId) => 5 | vizInfo.anyoneCanEdit || 6 | isOwner(vizInfo, userId) || 7 | isCollaborator(vizInfo, userId); 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/accessControl/index.js: -------------------------------------------------------------------------------- 1 | export { allowRead } from './allowRead'; 2 | export { allowWrite } from './allowWrite'; 3 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/accessControl/isCollaborator.js: -------------------------------------------------------------------------------- 1 | export const isCollaborator = (vizInfo, userId) => 2 | vizInfo.collaborators && 3 | !!vizInfo.collaborators.find( 4 | (collaborator) => collaborator.userId === userId 5 | ); 6 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/accessControl/isOwner.js: -------------------------------------------------------------------------------- 1 | export const isCollaborator = (vizInfo, userId) => 2 | vizInfo.collaborators && 3 | !!vizInfo.collaborators.find( 4 | (collaborator) => collaborator.userId === userId 5 | ); 6 | 7 | export const isOwner = (vizInfo, userId) => vizInfo.owner === userId; 8 | 9 | export const allowRead = (vizInfo, userId) => 10 | vizInfo.privacy === 'private' 11 | ? isOwner(vizInfo, userId) || isCollaborator(vizInfo, userId) 12 | : true; 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/index.js: -------------------------------------------------------------------------------- 1 | export * from './interactors'; 2 | export * from './accessControl'; 3 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/createCommit.js: -------------------------------------------------------------------------------- 1 | export class CreateCommit { 2 | constructor({ revisionHistoryGateway }) { 3 | this.revisionHistoryGateway = revisionHistoryGateway; 4 | } 5 | 6 | async execute(requestModel) { 7 | return await this.revisionHistoryGateway.createCommit(requestModel); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/createDataset/datasetDefaults.js: -------------------------------------------------------------------------------- 1 | export const datasetDefaults = { 2 | title: 'Untitled', 3 | slug: undefined, 4 | description: 'No description', 5 | file: '', 6 | format: 'csv', 7 | }; 8 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/createEdge.js: -------------------------------------------------------------------------------- 1 | export class CreateEdge { 2 | constructor({ revisionHistoryGateway }) { 3 | this.revisionHistoryGateway = revisionHistoryGateway; 4 | } 5 | 6 | async execute(requestModel) { 7 | return await this.revisionHistoryGateway.createEdge(requestModel); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/exportVisualization/zipFiles.js: -------------------------------------------------------------------------------- 1 | import AdmZip from 'adm-zip'; 2 | 3 | export const zipFiles = (files) => { 4 | const zip = new AdmZip(); 5 | files.forEach((file) => { 6 | // Defend against potential freakish null or undefined values. 7 | const text = file.text || ''; 8 | 9 | zip.addFile(file.name, Buffer.alloc(text.length, text)); 10 | }); 11 | return zip.toBuffer(); 12 | }; 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/getAllVisualizationInfos.js: -------------------------------------------------------------------------------- 1 | export class GetAllVisualizationInfos { 2 | constructor({ visualizationGateway }) { 3 | this.visualizationGateway = visualizationGateway; 4 | } 5 | 6 | async execute() { 7 | return { 8 | visualizationInfos: 9 | await this.visualizationGateway.getAllVisualizationInfos(), 10 | }; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/getEventRecords.js: -------------------------------------------------------------------------------- 1 | import { increment } from 'multiscale-timeseries'; 2 | 3 | export class GetEventRecords { 4 | constructor({ eventRecordsGateway }) { 5 | this.eventRecordsGateway = eventRecordsGateway; 6 | } 7 | 8 | async execute(requestModel) { 9 | const { eventIDs } = requestModel; 10 | return await this.eventRecordsGateway.getEventRecords(eventIDs); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/getPreview.js: -------------------------------------------------------------------------------- 1 | import { i18n } from 'vizhub-i18n'; 2 | 3 | export class GetPreview { 4 | constructor({ imageStorageGateway }) { 5 | this.imageStorageGateway = imageStorageGateway; 6 | } 7 | 8 | async execute(requestModel) { 9 | if (!requestModel.id) { 10 | throw new Error(i18n('errorNoId')); 11 | } 12 | 13 | const preview = await this.imageStorageGateway.getPreview({ 14 | id: requestModel.id, 15 | }); 16 | 17 | return { preview }; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/getThumbnail.js: -------------------------------------------------------------------------------- 1 | import { i18n } from 'vizhub-i18n'; 2 | 3 | export class GetThumbnail { 4 | constructor({ imageStorageGateway }) { 5 | this.imageStorageGateway = imageStorageGateway; 6 | } 7 | 8 | async execute(requestModel) { 9 | if (!requestModel.id) { 10 | throw new Error(i18n('errorNoId')); 11 | } 12 | 13 | const thumbnail = await this.imageStorageGateway.getThumbnail({ 14 | id: requestModel.id, 15 | }); 16 | 17 | return { thumbnail }; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/getUser.js: -------------------------------------------------------------------------------- 1 | import { ciUser } from 'vizhub-entities'; 2 | 3 | export class GetUser { 4 | constructor({ userGateway }) { 5 | this.userGateway = userGateway; 6 | } 7 | 8 | async execute(requestModel) { 9 | const { id } = requestModel; 10 | const responseModel = { 11 | user: id === ciUser.id ? ciUser : await this.userGateway.getUser(id), 12 | }; 13 | return responseModel; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/getUserByEmail.js: -------------------------------------------------------------------------------- 1 | import { ciUser } from 'vizhub-entities'; 2 | 3 | export class GetUserByEmail { 4 | constructor({ userGateway }) { 5 | this.userGateway = userGateway; 6 | } 7 | 8 | async execute(requestModel) { 9 | const { email } = requestModel; 10 | const responseModel = { 11 | user: 12 | email === ciUser.email 13 | ? ciUser 14 | : await this.userGateway.getUserByEmail(email), 15 | }; 16 | return responseModel; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/getUserByEmailOrId.js: -------------------------------------------------------------------------------- 1 | import { ciUser } from 'vizhub-entities'; 2 | 3 | export class GetUserByEmailOrId { 4 | constructor({ userGateway }) { 5 | this.userGateway = userGateway; 6 | } 7 | 8 | async execute(requestModel) { 9 | const { email, id } = requestModel; 10 | const responseModel = { 11 | user: 12 | email === ciUser.email || id === ciUser.id 13 | ? ciUser 14 | : await this.userGateway.getUserByEmailOrId(email, id), 15 | }; 16 | return responseModel; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/getUserSearchResultsData.js: -------------------------------------------------------------------------------- 1 | export class GetUserSearchResultsData { 2 | constructor({ userGateway }) { 3 | this.userGateway = userGateway; 4 | } 5 | 6 | async execute(requestModel) { 7 | const users = await this.userGateway.searchUsers(requestModel); 8 | return { users }; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/interactors/getVisualizationInfo.js: -------------------------------------------------------------------------------- 1 | export class GetVisualizationInfo { 2 | constructor({ visualizationGateway }) { 3 | this.visualizationGateway = visualizationGateway; 4 | } 5 | 6 | async execute({ id }) { 7 | return { 8 | visualizationInfo: await this.visualizationGateway.getVisualizationInfo({ 9 | id, 10 | }), 11 | }; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/utils/generateId.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuidV4 } from 'uuid'; 2 | export const generateId = () => uuidV4().replace(/-/g, ''); 3 | -------------------------------------------------------------------------------- /vizhub-v2/packages/useCases/src/utils/removeExtension.js: -------------------------------------------------------------------------------- 1 | export const removeExtension = (fileName) => 2 | fileName.substr(0, fileName.lastIndexOf('.')); 3 | -------------------------------------------------------------------------------- /vizhub-v3/Dockerfile: -------------------------------------------------------------------------------- 1 | # Inspired by 2 | # https://nodejs.org/en/docs/guides/nodejs-docker-webapp/ 3 | # https://mherman.org/blog/dockerizing-a-react-app/ 4 | 5 | FROM node:16 6 | WORKDIR /app 7 | ENV PATH /app/node_modules/.bin:$PATH 8 | COPY package*.json ./ 9 | RUN npm install 10 | COPY . ./ 11 | EXPOSE 3000 12 | CMD [ "npm", "start" ] 13 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/.prettierignore: -------------------------------------------------------------------------------- 1 | build 2 | .prettierignore 3 | .gitignore 4 | .dockerignore 5 | *.ico 6 | *.swp 7 | *.sh 8 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-typescript", "@babel/preset-react"], 3 | "plugins": [] 4 | } 5 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/deploy.sh: -------------------------------------------------------------------------------- 1 | scp -i /path/to/your/key.pem -r build ubuntu@your.ip.address:/home/ubuntu/vizhub/vizhub-v3/vizhub-app/build 2 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vizhub-core/vizhub-legacy/2a41920a083e08aa5e3729dd437c629678e71093/vizhub-v3/vizhub-app/public/favicon.ico -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/scss/_home-page.scss: -------------------------------------------------------------------------------- 1 | .home-page { 2 | overflow: auto; 3 | } 4 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/scss/_profile-page.scss: -------------------------------------------------------------------------------- 1 | .profile-page { 2 | overflow: auto; 3 | 4 | &__avatar { 5 | width: 80px; 6 | height: 80px; 7 | } 8 | 9 | &__full-name { 10 | font-weight: bold; 11 | font-size: var(--vizhub-h3-font-size); 12 | } 13 | 14 | &__user-name { 15 | color: var(--vizhub-foreground-color-light); 16 | font-size: var(--vizhub-small-font-size); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/scss/_spinner.scss: -------------------------------------------------------------------------------- 1 | .spinner { 2 | display: flex; 3 | height: 100%; 4 | flex-direction: column; 5 | align-items: center; 6 | justify-content: center; 7 | overflow: hidden; 8 | svg { 9 | transition: opacity 2s; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | --vizhub-font-size-monospace: 18px; 3 | } 4 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/scss/_vizhub-banner.scss: -------------------------------------------------------------------------------- 1 | .vizhub-banner { 2 | display: block; 3 | text-align: center; 4 | padding: 1rem 0.5rem 1rem 0.5rem; 5 | background: linear-gradient(#ffffff, #f6eee3); 6 | color: black; 7 | text-decoration: none; 8 | } 9 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/scss/vizhub-app.scss: -------------------------------------------------------------------------------- 1 | @import './variables'; 2 | @import './spinner'; 3 | @import './viz-page'; 4 | @import './viz-preview'; 5 | @import './profile-page'; 6 | @import './home-page'; 7 | @import './vizhub-banner'; 8 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as presenters from './presenters'; 3 | 4 | export const App = ({ pageData }) => { 5 | const PagePresenter = presenters[pageData.pageName]; 6 | return ; 7 | }; 8 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/src/client.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { App } from './App'; 4 | 5 | // Underlying Philosophy: Client side navigation is not required. 6 | // Therefore, the App component accepts only static pageData 7 | // that was rendered into the HTML on the server side. 8 | ReactDOM.hydrate( 9 | , 10 | document.getElementById('vizhub-root') 11 | ); 12 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/src/environment.js: -------------------------------------------------------------------------------- 1 | // True if the app is running in the client. 2 | // False if the app is running in the server (server side rendering). 3 | export const isClient = typeof window !== 'undefined'; 4 | 5 | // True if the build is for production (with SSL and WSS enabled). 6 | // False if the build is for local development. 7 | export const isProd = isClient && window.location.protocol === 'https:'; 8 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/src/featureFlags.js: -------------------------------------------------------------------------------- 1 | // Feature flags 2 | 3 | // Enable the custom coding font. 4 | // If false, falls back to system font stack. 5 | export const enableUbuntuMonoLigaturized = true; 6 | 7 | // A way to disable client side JS, for testing during development. 8 | export const enableClientJS = true; 9 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/src/jsDelivrCombine.js: -------------------------------------------------------------------------------- 1 | // Computes a JSDelivr CDN URL that will fetch multiple JS libraries 2 | // concatenated together (they each introduce their own globals). 3 | export const jsDelivrCombine = (libs) => 4 | 'https://cdn.jsdelivr.net/combine/' + 5 | libs.map((lib) => `npm/${lib}`).join(','); 6 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/src/presenters/LoginPagePresenter/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const LoginPagePresenter = () => { 4 | return Sign in with Google; 5 | }; 6 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/src/presenters/index.js: -------------------------------------------------------------------------------- 1 | export { VizPagePresenter } from './VizPagePresenter'; 2 | export { HomePagePresenter } from './HomePagePresenter'; 3 | export { LoginPagePresenter } from './LoginPagePresenter'; 4 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/src/presenters/logShareDBError.js: -------------------------------------------------------------------------------- 1 | // TODO instrument this to log errors to the server, so they can be traced and fixed 2 | export const logShareDBError = (error) => { 3 | if (error) console.log(error); 4 | }; 5 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/src/queries.js: -------------------------------------------------------------------------------- 1 | // This module defines queries that are used both on the 2 | // server side and client side. 3 | const pageSize = 4 * 4; 4 | export const homePageVizInfosQuery = (pageIndex = 0) => ({ 5 | $skip: pageIndex * pageSize, 6 | $limit: pageSize, 7 | }); 8 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/src/ui/README.md: -------------------------------------------------------------------------------- 1 | # vizhub-app/src/ui 2 | 3 | The idea behind this directory is to keep it simple and stupid, so that the UI by itself is easier to maintain in the long run. 4 | 5 | The code in here should be purely "dumb components" that do not rely on any modules defined outside of this directory. 6 | 7 | The code in here should not even be aware of the data structures provided by `vizhub-entities`. 8 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-app/src/ui/index.js: -------------------------------------------------------------------------------- 1 | export { HomePage } from './HomePage'; 2 | export { ProfilePage } from './ProfilePage'; 3 | export { VizPage } from './VizPage'; 4 | export { Spinner } from './Spinner'; 5 | export { VizPreview } from './VizPreview'; 6 | export { AuthenticatedUserDropdown } from './AuthenticatedUserDropdown'; 7 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-build/.prettierignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .prettierignore 3 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-build/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vizhub-build", 3 | "version": "0.0.1", 4 | "description": "Common build utilities used across packages.", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "", 9 | "prettier": "prettier {*.*,**/*.*} --single-quote --write", 10 | "ncu": "ncu -u" 11 | }, 12 | "devDependencies": { 13 | "prettier": "^2.6.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-codemirror/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-codemirror/.prettierignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | *.swp 3 | dist 4 | .prettierignore 5 | .gitignore 6 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-codemirror/src/vizhubHighlightStyle.js: -------------------------------------------------------------------------------- 1 | import { EditorView } from '@codemirror/view'; 2 | 3 | // Inspired by 4 | // https://codemirror.net/6/examples/styling/ 5 | export const vizhubHighlightStyle = EditorView.theme( 6 | { 7 | '&': { 8 | color: 'white', 9 | backgroundColor: '#202e46', 10 | }, 11 | '.cm-content': { 12 | caretColor: 'white', 13 | }, 14 | }, 15 | { dark: true } 16 | // TODO VizHub editor theme code colors 17 | ); 18 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-entities/.prettierignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .prettierignore 3 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-entities/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './entities'; 2 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/.eslintignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | }, 6 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], 7 | parser: '@typescript-eslint/parser', 8 | parserOptions: { 9 | ecmaVersion: 13, 10 | sourceType: 'module', 11 | }, 12 | plugins: ['@typescript-eslint'], 13 | rules: { '@typescript-eslint/no-explicit-any': 0 }, 14 | }; 15 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/.prettierignore: -------------------------------------------------------------------------------- 1 | build 2 | *.swp 3 | .prettierignore 4 | .eslintignore 5 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-typescript"], 3 | "plugins": [] 4 | } 5 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/constants.js: -------------------------------------------------------------------------------- 1 | // Entry point for client-side code 2 | // that just needs access to constants. 3 | export { 4 | VIZ_INFO_COLLECTION, 5 | VIZ_CONTENT_COLLECTION, 6 | } from './src/DatabaseGatewaysConstants.ts'; 7 | 8 | export { 9 | VIZ_INFO_NOT_FOUND, 10 | VIZ_CONTENT_NOT_FOUND, 11 | USER_NOT_FOUND, 12 | } from './src/errorCodes.ts'; 13 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/src/DatabaseGatewaysConstants.ts: -------------------------------------------------------------------------------- 1 | export const VIZ_INFO_COLLECTION: CollectionName = 'vizInfo'; 2 | export const VIZ_CONTENT_COLLECTION: CollectionName = 'vizContent'; 3 | export const USER_COLLECTION: CollectionName = 'user'; 4 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/src/GetVizSnapshot.ts: -------------------------------------------------------------------------------- 1 | import { VizId, Viz } from 'vizhub-entities'; 2 | import { Gateways } from './Gateways'; 3 | 4 | // Convenience interactor for getting info and content together. 5 | export const GetVizSnapshot = (gateways: Gateways) => { 6 | return async (vizId: VizId): Promise => { 7 | const [vizInfoSnapshot, vizContentSnapshot] = await Promise.all([ 8 | gateways.getVizInfoSnapshot(vizId), 9 | gateways.getVizContentSnapshot(vizId), 10 | ]); 11 | return { vizInfoSnapshot, vizContentSnapshot }; 12 | }; 13 | }; 14 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/src/SaveViz.ts: -------------------------------------------------------------------------------- 1 | import { Viz } from 'vizhub-entities'; 2 | import { Gateways } from './Gateways'; 3 | 4 | // Convenience interactor for saving info and content together. 5 | export const SaveViz = (gateways: Gateways) => { 6 | return async (viz: Viz): Promise => { 7 | await Promise.all([ 8 | gateways.saveVizInfo(viz.vizInfo), 9 | gateways.saveVizContent(viz.vizContent), 10 | ]); 11 | }; 12 | }; 13 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/src/errorCodes.ts: -------------------------------------------------------------------------------- 1 | import { VizHubErrorCode } from 'vizhub-entities'; 2 | export const VIZ_INFO_NOT_FOUND: VizHubErrorCode = 'VIZ_INFO_NOT_FOUND'; 3 | export const VIZ_CONTENT_NOT_FOUND: VizHubErrorCode = 'VIZ_CONTENT_NOT_FOUND'; 4 | export const USER_NOT_FOUND: VizHubErrorCode = 'USER_NOT_FOUND'; 5 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/src/generateRandomId.js: -------------------------------------------------------------------------------- 1 | import { v4 as uuidV4 } from 'uuid'; 2 | 3 | // Generates a UUID v4 string with dashes removed (for ease of URL copying). 4 | export const generateRandomId = () => uuidV4().replace(/-/g, ''); 5 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/src/index.ts: -------------------------------------------------------------------------------- 1 | export { Gateways } from './Gateways'; 2 | export { MemoryGateways } from './MemoryGateways'; 3 | export { DatabaseGateways } from './DatabaseGateways'; 4 | export { ForkViz } from './ForkViz'; 5 | export { DeleteViz } from './DeleteViz'; 6 | export { SaveViz } from './SaveViz'; 7 | export { GetVizSnapshot } from './GetVizSnapshot'; 8 | export { FindOrCreateUser } from './FindOrCreateUser'; 9 | export { VIZ_INFO_NOT_FOUND, VIZ_CONTENT_NOT_FOUND } from './errors'; 10 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-interactors/test/test.ts: -------------------------------------------------------------------------------- 1 | import { GatewaysTest } from './GatewaysTest'; 2 | import { ForkVizTest } from './ForkVizTest'; 3 | import { DeleteVizTest } from './DeleteVizTest'; 4 | import { FindOrCreateUserTest } from './FindOrCreateUserTest'; 5 | 6 | GatewaysTest(); 7 | ForkVizTest(); 8 | DeleteVizTest(); 9 | 10 | FindOrCreateUserTest(); 11 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-runtime/.prettierignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.map 3 | .prettierignore 4 | build 5 | package-lock.json 6 | test/expectedValues 7 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-runtime/src/constants.js: -------------------------------------------------------------------------------- 1 | // This controls which file is the entry point for the Rollup build. 2 | export const input = './index.js'; 3 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-runtime/src/index.js: -------------------------------------------------------------------------------- 1 | export { build } from './build'; 2 | export { Runner } from './Runner'; 3 | export { generateSrcdoc } from './generateSrcdoc'; 4 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-runtime/src/virtual.js: -------------------------------------------------------------------------------- 1 | // A Rollup plugin for a virtual file system. 2 | // Inspired by https://github.com/Permutatrix/rollup-plugin-hypothetical/blob/master/index.js 3 | 4 | const js = (name) => (name.endsWith('.js') ? name : name + '.js'); 5 | 6 | export const virtual = (files) => ({ 7 | name: 'virtual', 8 | resolveId: (id) => (id.startsWith('./') ? id : null), 9 | load: (id) => (id.startsWith('./') ? files[js(id.substring(2))] : null), 10 | }); 11 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-runtime/test/expectedValues/index.js: -------------------------------------------------------------------------------- 1 | export { singleFileUMD } from './singleFileUMD'; 2 | export { modules } from './modules'; 3 | export { srcdocCodeOnly } from './srcdocCodeOnly'; 4 | export { srcdocCodeAndConfig } from './srcdocCodeAndConfig'; 5 | export { srcdocCodeAndDependencies } from './srcdocCodeAndDependencies'; 6 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-runtime/test/updateExpectedSrcdocValue.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | 3 | export const updateExpectedSrcdocValue = (name, value) => { 4 | fs.writeFileSync( 5 | `test/expectedValues/${name}.js`, 6 | `export const ${name} = \`${value}\`;` 7 | ); 8 | }; 9 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.swp 3 | dist 4 | package-lock.json 5 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/.prettierignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .prettierignore 3 | dist 4 | package-lock.json 5 | *.swp 6 | *.map 7 | *.svg 8 | *.ico 9 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [], 3 | "plugins": ["@babel/plugin-syntax-jsx", "@babel/plugin-transform-react-jsx"] 4 | } 5 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/icons/Arrow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/icons/README.md: -------------------------------------------------------------------------------- 1 | ![image](https://user-images.githubusercontent.com/68416/144755473-b5640f47-42ca-49ec-8d58-cca9e46561ca.png) 2 | 3 | This icon set was created by [Bozlur Rahman](https://www.truelancer.com/freelancer/bozlurrahman), a freelancer in Bangladesh who also created the VizHub logo. 4 | 5 | This is the second revision of the custom icon set originally created by [Alec Burch](https://stamen.com/people/alec-burch/), who designed the UI for VizHub 2 during a design engagement with [Stamen Design](https://stamen.com/). 6 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/icons/chevron.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/icons/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/icons/download.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/icons/mini-mode.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/icons/new.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/icons/side-by-side-mode.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/icons/upload.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/scss/_buttons.scss: -------------------------------------------------------------------------------- 1 | // A flat button. 2 | .btn-flat { 3 | border-radius: 0; 4 | } 5 | 6 | .btn-flat-light { 7 | &:focus { 8 | outline: none; 9 | box-shadow: inset 0 0 $input-btn-focus-blur $input-btn-focus-width black; 10 | } 11 | } 12 | 13 | .btn-flat-dark { 14 | &:focus { 15 | outline: none; 16 | box-shadow: inset 0 0 $input-btn-focus-blur $input-btn-focus-width white; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/scss/_forms.scss: -------------------------------------------------------------------------------- 1 | // Custom things in forms 2 | .vizhub-form-note { 3 | font-size: 14px; 4 | color: rgb(121, 121, 121); 5 | &.contextual { 6 | font-weight: bold; 7 | padding-bottom: 1rem; 8 | } 9 | // &.informational { 10 | // padding-top: 2rem; 11 | // padding-bottom: 1rem; 12 | // } 13 | } 14 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/scss/_modal.scss: -------------------------------------------------------------------------------- 1 | // Box shadow on modals. 2 | .modal-content { 3 | box-shadow: var(--vizhub-box-shadow); 4 | } 5 | 6 | // Make modal titles bold. 7 | .modal-title { 8 | font-weight: bold; 9 | } 10 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/scss/_nav.scss: -------------------------------------------------------------------------------- 1 | // Custom styling of pills so they have underlines. 2 | .nav-pills .nav-link { 3 | padding: $input-padding-y $input-padding-x; 4 | &, 5 | &:hover, 6 | &:focus { 7 | color: $body-color; 8 | } 9 | } 10 | 11 | .nav-pills .nav-link.active, 12 | .nav-pills .show > .nav-link { 13 | border-bottom-width: 4px; 14 | border-bottom-style: solid; 15 | border-bottom-color: $primary; 16 | border-radius: 0px; 17 | } 18 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/scss/_root.scss: -------------------------------------------------------------------------------- 1 | #vizhub-root { 2 | position: fixed; 3 | inset: 0; 4 | display: flex; 5 | flex-direction: column; 6 | } 7 | -------------------------------------------------------------------------------- /vizhub-v3/vizhub-ui/scss/_util.scss: -------------------------------------------------------------------------------- 1 | // Hides a thing on mobile. 2 | .hide-on-mobile { 3 | @include media-breakpoint-down(sm) { 4 | display: none !important; 5 | } 6 | } 7 | 8 | // A clickable element, with darkened background 9 | // for hover and active states. 10 | .clickable { 11 | cursor: pointer; 12 | &:hover { 13 | background-color: rgba(0, 0, 0, 0.07); 14 | } 15 | &:active { 16 | background-color: rgba(0, 0, 0, 0.14); 17 | } 18 | } 19 | --------------------------------------------------------------------------------