├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── docker ├── docker-compose-master.yml ├── docker-compose-persistent.yml ├── docker-compose.yml ├── nginx-prod.conf └── nginx.conf ├── lpa-cli.sh ├── renovate.json └── src ├── backend ├── .dockerfile ├── .gitignore ├── Dockerfile ├── build.gradle ├── docs │ ├── build.gradle │ └── src │ │ └── orchid │ │ └── resources │ │ ├── assets │ │ └── css │ │ │ ├── color.css │ │ │ └── sideNav.css │ │ ├── config.yml │ │ ├── config │ │ └── pages.yml │ │ ├── homepage.md │ │ └── pages │ │ └── chapters │ │ ├── architecture.md │ │ ├── code-structure.md │ │ ├── component-overview.md │ │ ├── configuring-discovery.md │ │ └── installation.md ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ ├── main │ ├── config │ │ ├── application.conf │ │ ├── application.properties │ │ └── reference.conf │ ├── java │ │ └── com │ │ │ └── linkedpipes │ │ │ └── lpa │ │ │ └── backend │ │ │ ├── Application.java │ │ │ ├── constants │ │ │ ├── ApplicationPropertyKeys.java │ │ │ ├── SupportedRDFMimeTypes.java │ │ │ ├── Visualizers.java │ │ │ └── package-info.java │ │ │ ├── controllers │ │ │ ├── D3ChordVisualizerController.java │ │ │ ├── DataSourceController.java │ │ │ ├── DiscoveryController.java │ │ │ ├── ExecutionController.java │ │ │ ├── MapVisualizerController.java │ │ │ ├── PipelineController.java │ │ │ ├── SkosController.java │ │ │ ├── TimelineController.java │ │ │ ├── UserController.java │ │ │ ├── VirtuosoController.java │ │ │ └── package-info.java │ │ │ ├── entities │ │ │ ├── ApplicationInstance.java │ │ │ ├── DataSource.java │ │ │ ├── DataSourceGroup.java │ │ │ ├── Discovery.java │ │ │ ├── DiscoveryDeleted.java │ │ │ ├── DiscoveryStatus.java │ │ │ ├── DiscoveryStatusReport.java │ │ │ ├── EdgeDirection.java │ │ │ ├── ErrorResponse.java │ │ │ ├── EtlStatus.java │ │ │ ├── EtlStatusReport.java │ │ │ ├── Execution.java │ │ │ ├── ExecutionDeleted.java │ │ │ ├── ExecutionStatus.java │ │ │ ├── MapQueryData.java │ │ │ ├── MarkerFilterSetup.java │ │ │ ├── Pipeline.java │ │ │ ├── PipelineExportResult.java │ │ │ ├── PipelineGroup.java │ │ │ ├── PipelineGroups.java │ │ │ ├── ServiceDescription.java │ │ │ ├── database │ │ │ │ ├── ApplicationDao.java │ │ │ │ ├── ApplicationRepository.java │ │ │ │ ├── DiscoveryDao.java │ │ │ │ ├── DiscoveryNamedGraphDao.java │ │ │ │ ├── DiscoveryNamedGraphRepository.java │ │ │ │ ├── DiscoveryRepository.java │ │ │ │ ├── ExecutionDao.java │ │ │ │ ├── ExecutionRepository.java │ │ │ │ ├── PipelineInformationDao.java │ │ │ │ ├── PipelineInformationRepository.java │ │ │ │ ├── UserDao.java │ │ │ │ ├── UserRepository.java │ │ │ │ └── package-info.java │ │ │ ├── geo │ │ │ │ ├── Coordinates.java │ │ │ │ ├── Marker.java │ │ │ │ ├── Polygon.java │ │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ ├── profile │ │ │ │ ├── Application.java │ │ │ │ ├── DiscoverySession.java │ │ │ │ ├── PipelineExecution.java │ │ │ │ ├── UserProfile.java │ │ │ │ └── package-info.java │ │ │ ├── rgml │ │ │ │ ├── Edge.java │ │ │ │ ├── Graph.java │ │ │ │ ├── Node.java │ │ │ │ ├── NodeWithDegree.java │ │ │ │ └── package-info.java │ │ │ ├── timeline │ │ │ │ ├── Instant.java │ │ │ │ ├── Interval.java │ │ │ │ ├── ThingWithInstant.java │ │ │ │ ├── ThingWithInterval.java │ │ │ │ ├── ThingWithThingWithInstant.java │ │ │ │ └── ThingWithThingWithInterval.java │ │ │ └── visualization │ │ │ │ ├── Concept.java │ │ │ │ ├── ConceptCount.java │ │ │ │ ├── ConceptCountRequest.java │ │ │ │ ├── HierarchyNode.java │ │ │ │ ├── Scheme.java │ │ │ │ └── package-info.java │ │ │ ├── exceptions │ │ │ ├── ConnectionException.java │ │ │ ├── GlobalExceptionHandler.java │ │ │ ├── LpAppsException.java │ │ │ ├── PipelineNotFoundException.java │ │ │ ├── PollingCompletedException.java │ │ │ ├── UserNotFoundException.java │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ ├── rdf │ │ │ ├── LocalizedValue.java │ │ │ ├── Prefixes.java │ │ │ ├── Property.java │ │ │ ├── package-info.java │ │ │ └── vocabulary │ │ │ │ ├── LPA.java │ │ │ │ ├── LPD.java │ │ │ │ ├── LPDConf.java │ │ │ │ ├── LPDSparql.java │ │ │ │ ├── RGML.java │ │ │ │ ├── SD.java │ │ │ │ ├── Schema.java │ │ │ │ ├── Time.java │ │ │ │ ├── Vocabulary.java │ │ │ │ └── package-info.java │ │ │ ├── services │ │ │ ├── DataSamplePipelineInputGenerator.java │ │ │ ├── DisableDatabaseConfiguration.java │ │ │ ├── DiscoveryService.java │ │ │ ├── DiscoveryServiceComponent.java │ │ │ ├── EtlService.java │ │ │ ├── EtlServiceComponent.java │ │ │ ├── ExecutorService.java │ │ │ ├── ExecutorServiceComponent.java │ │ │ ├── HandlerMethodIntrospector.java │ │ │ ├── PipelineExportService.java │ │ │ ├── PipelineExportServiceComponent.java │ │ │ ├── ScheduledExecutionService.java │ │ │ ├── ScheduledExecutionServiceComponent.java │ │ │ ├── ShutdownManager.java │ │ │ ├── TtlGenerator.java │ │ │ ├── UserService.java │ │ │ ├── UserServiceComponent.java │ │ │ ├── VisualizationService.java │ │ │ ├── VisualizationServiceComponent.java │ │ │ ├── geo │ │ │ │ └── GeoService.java │ │ │ ├── package-info.java │ │ │ ├── rgml │ │ │ │ └── RgmlService.java │ │ │ ├── timeline │ │ │ │ └── TimelineService.java │ │ │ └── virtuoso │ │ │ │ └── VirtuosoService.java │ │ │ ├── sparql │ │ │ ├── ValueFilter.java │ │ │ ├── VariableGenerator.java │ │ │ ├── extractors │ │ │ │ ├── geo │ │ │ │ │ ├── GeoPropertiesExtractor.java │ │ │ │ │ └── MarkerExtractor.java │ │ │ │ ├── package-info.java │ │ │ │ ├── rgml │ │ │ │ │ ├── EdgesExtractor.java │ │ │ │ │ ├── GraphExtractor.java │ │ │ │ │ └── NodesExtractor.java │ │ │ │ ├── timeline │ │ │ │ │ ├── InstantExtractor.java │ │ │ │ │ ├── IntervalExtractor.java │ │ │ │ │ ├── ThingWithInstantExtractor.java │ │ │ │ │ ├── ThingWithIntervalExtractor.java │ │ │ │ │ ├── ThingWithThingWithInstantExtractor.java │ │ │ │ │ └── ThingWithThingWithIntervalExtractor.java │ │ │ │ └── visualization │ │ │ │ │ ├── ConceptCountExtractor.java │ │ │ │ │ ├── ConceptsExtractor.java │ │ │ │ │ ├── HierarchyExtractor.java │ │ │ │ │ ├── HighLevelSchemeExtractor.java │ │ │ │ │ ├── SchemeExtractor.java │ │ │ │ │ ├── SchemeSubtreeExtractor.java │ │ │ │ │ └── SchemesExtractor.java │ │ │ └── queries │ │ │ │ ├── ConstructSparqlQueryProvider.java │ │ │ │ ├── DefaultDataSourceConfigurationQueryProvider.java │ │ │ │ ├── DefaultDataSourceExtractorQueryProvider.java │ │ │ │ ├── ExtractGraphQueryProvider.java │ │ │ │ ├── SelectSparqlQueryProvider.java │ │ │ │ ├── SparqlQueryProvider.java │ │ │ │ ├── geo │ │ │ │ ├── GeoPropertiesQueryProvider.java │ │ │ │ └── MarkerQueryProvider.java │ │ │ │ ├── package-info.java │ │ │ │ ├── rgml │ │ │ │ ├── EdgesQueryProvider.java │ │ │ │ ├── GraphQueryProvider.java │ │ │ │ ├── IncidentEdgesQueryProvider.java │ │ │ │ └── NodesQueryProvider.java │ │ │ │ ├── timeline │ │ │ │ ├── InstantQueryProvider.java │ │ │ │ ├── IntervalQueryProvider.java │ │ │ │ ├── ThingsWithInstantQueryProvider.java │ │ │ │ ├── ThingsWithIntervalQueryProvider.java │ │ │ │ ├── ThingsWithThingsWithInstantQueryProvider.java │ │ │ │ └── ThingsWithThingsWithIntervalQueryProvider.java │ │ │ │ └── visualization │ │ │ │ ├── ConceptsCountsQueryProvider.java │ │ │ │ ├── ConceptsQueryProvider.java │ │ │ │ ├── HighLevelSchemeQueryProvider.java │ │ │ │ ├── SchemeQueryProvider.java │ │ │ │ ├── SchemeSubtreeQueryProvider.java │ │ │ │ └── SchemesQueryProvider.java │ │ │ └── util │ │ │ ├── DefaultHttpURLConnectionFactory.java │ │ │ ├── GitHubUtils.java │ │ │ ├── HashableTuple.java │ │ │ ├── HttpFileUploader.java │ │ │ ├── HttpRequestSender.java │ │ │ ├── HttpURLConnectionFactory.java │ │ │ ├── IExecutionCallback.java │ │ │ ├── JenaUtils.java │ │ │ ├── LpAppsObjectMapper.java │ │ │ ├── Memoizer.java │ │ │ ├── RdfUtils.java │ │ │ ├── SparqlUtils.java │ │ │ ├── Streams.java │ │ │ ├── ThrowableUtils.java │ │ │ ├── ThrowingFunction.java │ │ │ ├── ThrowingSupplier.java │ │ │ ├── TriFunction.java │ │ │ ├── UrlUtils.java │ │ │ ├── package-info.java │ │ │ └── rdfbuilder │ │ │ ├── ModelBuilder.java │ │ │ ├── ResourceBuilder.java │ │ │ └── package-info.java │ └── resources │ │ ├── com │ │ └── linkedpipes │ │ │ └── lpa │ │ │ └── backend │ │ │ └── services │ │ │ ├── base.ttl │ │ │ ├── datasample.jsonld │ │ │ ├── virtuoso │ │ │ ├── data-chord.ttl │ │ │ └── data-googlemaps.ttl │ │ │ └── virtuoso_sd.ttl │ │ ├── db │ │ └── migration │ │ │ ├── R__Vacuum.sql │ │ │ ├── V1.0__Create_schema.sql │ │ │ ├── V1.1__Extended_user_profile_and_storing_discovery_and_ETL_parameters.sql │ │ │ ├── V1.2__Multiple_named_graphs.sql │ │ │ ├── V1.3__Color_schemes_on_user,_drop_applications,_named_graphs_on_delete_cascade.sql │ │ │ ├── V1.4__Applications.sql │ │ │ └── V1.5__Repeated_executions.sql │ │ └── sentry.properties │ └── test │ └── java │ └── com │ └── linkedpipes │ └── lpa │ └── backend │ ├── ApplicationTests.java │ ├── controllers │ └── DiscoveryControllerTests.java │ ├── services │ ├── DiscoveryServiceComponentTests.java │ ├── EtlServiceComponentTests.java │ └── TtlGeneratorTests.java │ ├── testutil │ ├── TestError.java │ └── ThrowingExecutable.java │ └── util │ ├── FakeHttpURLConnectionFactory.java │ ├── HttpRequestSenderTests.java │ ├── LpAppsObjectMapperTest.java │ └── UrlUtilsTests.java ├── deploy ├── deploy.sh ├── docker-compose-travis-deploy.yml ├── lpa-server-nginx.conf ├── lpa-webhook.service └── webserver.py ├── frontend ├── .babelrc ├── .dockerignore ├── .eslintrc.json ├── .flowconfig ├── .gitignore ├── .prettierrc ├── Dockerfile ├── Dockerfile-prod ├── assets │ ├── lpa_header_logo.svg │ ├── lpa_logo_small.svg │ └── lpa_svg_title.svg ├── doczrc.js ├── jsconfig.json ├── nginx.conf ├── package.json ├── src │ ├── AppRouter.jsx │ ├── components │ │ ├── Header │ │ │ ├── AboutHeader │ │ │ │ ├── AboutHeaderComponent.jsx │ │ │ │ ├── AboutHeaderContainer.jsx │ │ │ │ └── index.js │ │ │ ├── ApplicationHeader │ │ │ │ ├── ApplicationHeaderComponent.jsx │ │ │ │ ├── ApplicationHeaderContainer.jsx │ │ │ │ └── index.js │ │ │ ├── ApplicationsBrowserHeader │ │ │ │ ├── ApplicationsBrowserHeaderComponent.jsx │ │ │ │ ├── ApplicationsBrowserHeaderContainer.jsx │ │ │ │ └── index.js │ │ │ ├── DashboardHeader │ │ │ │ ├── DashboardHeaderComponent.jsx │ │ │ │ ├── DashboardHeaderContainer.jsx │ │ │ │ └── index.js │ │ │ ├── DiscoverHeader │ │ │ │ ├── DiscoverHeaderComponent.jsx │ │ │ │ ├── DiscoverHeaderContainer.jsx │ │ │ │ └── index.js │ │ │ ├── Header.mdx │ │ │ ├── HeaderComponent.jsx │ │ │ ├── HeaderContainer.jsx │ │ │ ├── SettingsHeader │ │ │ │ ├── SettingsHeaderComponent.jsx │ │ │ │ ├── SettingsHeaderContainer.jsx │ │ │ │ └── index.js │ │ │ └── index.js │ │ ├── HeaderControls │ │ │ ├── HeaderControls.mdx │ │ │ ├── HeaderControlsComponent.jsx │ │ │ ├── HeaderControlsContainer.jsx │ │ │ └── index.js │ │ ├── Icons │ │ │ ├── VisualizerIcon.mdx │ │ │ ├── VisualizerIconComponent.jsx │ │ │ └── index.js │ │ ├── Loaders │ │ │ ├── LinearLoader.mdx │ │ │ ├── LinearLoaderComponent.jsx │ │ │ └── index.js │ │ ├── NavigationBar │ │ │ ├── NavigationBar.mdx │ │ │ ├── NavigationBarContainer.jsx │ │ │ └── index.js │ │ ├── Visualizers │ │ │ ├── Chord │ │ │ │ ├── ChordVisualizer.jsx │ │ │ │ └── index.js │ │ │ ├── Maps │ │ │ │ ├── MapsVisualizer.jsx │ │ │ │ └── index.js │ │ │ ├── Timeline │ │ │ │ ├── TimelineVisualizer.jsx │ │ │ │ └── index.js │ │ │ ├── Treemap │ │ │ │ ├── TreemapVisualizer.jsx │ │ │ │ └── index.js │ │ │ ├── Visualizers.mdx │ │ │ └── index.js │ │ └── index.js │ ├── constants │ │ ├── endpoints.constants.js │ │ ├── filters.constants.js │ │ ├── global.constants.js │ │ ├── index.js │ │ ├── options.constants.js │ │ └── visualizers.constants.js │ ├── containers │ │ ├── AboutPage │ │ │ ├── AboutPage.jsx │ │ │ ├── AboutPage.mdx │ │ │ └── index.js │ │ ├── ApplicationPage │ │ │ ├── ApplicationContainer.jsx │ │ │ ├── ApplicationPage.mdx │ │ │ └── index.js │ │ ├── AuthorizationPage │ │ │ ├── AuthorizationComponent.jsx │ │ │ ├── AuthorizationContainer.jsx │ │ │ ├── AuthorizationPage.mdx │ │ │ ├── children │ │ │ │ ├── SolidProviderComponent.jsx │ │ │ │ └── index.js │ │ │ └── index.js │ │ ├── CreateVisualizerPage │ │ │ ├── CreateVIsualizerPage.mdx │ │ │ ├── CreateVisualizerComponent.jsx │ │ │ ├── CreateVisualizerContainer.jsx │ │ │ ├── children │ │ │ │ ├── Container │ │ │ │ │ ├── VisualizerContainer.jsx │ │ │ │ │ └── index.js │ │ │ │ ├── Filters │ │ │ │ │ ├── FiltersComponent.jsx │ │ │ │ │ ├── FiltersContainer.jsx │ │ │ │ │ ├── Options │ │ │ │ │ │ ├── OptionsComponent.jsx │ │ │ │ │ │ └── index.js │ │ │ │ │ ├── children │ │ │ │ │ │ ├── ChordFilter │ │ │ │ │ │ │ ├── ChordFiltersComponent.jsx │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ ├── MapFilter │ │ │ │ │ │ │ ├── MapSchemeFilterComponent.jsx │ │ │ │ │ │ │ └── index.js │ │ │ │ │ │ └── TreemapFilter │ │ │ │ │ │ │ ├── TreemapFiltersComponent.jsx │ │ │ │ │ │ │ ├── TreemapNodesFilterComponent.jsx │ │ │ │ │ │ │ └── index.js │ │ │ │ │ └── index.js │ │ │ │ ├── Header │ │ │ │ │ ├── EditVisualizerHeaderComponent.jsx │ │ │ │ │ ├── EditVisualizerHeaderContainer.jsx │ │ │ │ │ ├── VisualizerHeaderComponent.jsx │ │ │ │ │ ├── VisualizerHeaderContainer.jsx │ │ │ │ │ ├── children │ │ │ │ │ │ ├── DataRefreshControlDialog.jsx │ │ │ │ │ │ └── index.js │ │ │ │ │ └── index.js │ │ │ │ └── index.js │ │ │ └── index.js │ │ ├── DiscoverPage │ │ │ ├── DiscoverComponent.jsx │ │ │ ├── DiscoverContainer.jsx │ │ │ ├── DiscoverInputSources │ │ │ │ ├── DiscoverExamplesComponent.jsx │ │ │ │ ├── DiscoverExamplesContainer.jsx │ │ │ │ ├── DiscoverInputSourcesComponent.jsx │ │ │ │ ├── DiscoverInputSourcesContainer.jsx │ │ │ │ ├── DiscoverSelectorComponent.jsx │ │ │ │ ├── DiscoverSelectorContainer.jsx │ │ │ │ ├── children │ │ │ │ │ ├── DiscoverRdfFileDropInComponent.jsx │ │ │ │ │ ├── DiscoverRdfUrlFieldComponent.jsx │ │ │ │ │ ├── DiscoverSparqlSelectorFieldsComponent.jsx │ │ │ │ │ ├── css │ │ │ │ │ │ └── FilePondDarkStyle.css │ │ │ │ │ └── index.js │ │ │ │ └── index.js │ │ │ ├── DiscoverPage.mdx │ │ │ ├── DiscoverPipelinesExecutor │ │ │ │ ├── DiscoverPipelinesExecutorComponent.jsx │ │ │ │ ├── DiscoverPipelinesExecutorContainer.jsx │ │ │ │ └── index.js │ │ │ ├── DiscoverPipelinesPicker │ │ │ │ ├── DiscoverPipelinesHeaderComponent.jsx │ │ │ │ ├── DiscoverPipelinesPickerComponent.jsx │ │ │ │ ├── DiscoverPipelinesPickerContainer.jsx │ │ │ │ └── index.js │ │ │ ├── DiscoverVisualizerPicker │ │ │ │ ├── DiscoverVisualizerPickerComponent.jsx │ │ │ │ ├── DiscoverVisualizerPickerContainer.jsx │ │ │ │ ├── children │ │ │ │ │ ├── DiscoverVisualizerCardComponent.jsx │ │ │ │ │ ├── DiscoverVisualizerCardContainer.jsx │ │ │ │ │ └── index.js │ │ │ │ └── index.js │ │ │ ├── duck │ │ │ │ ├── actions.jsx │ │ │ │ ├── index.js │ │ │ │ ├── reducers.jsx │ │ │ │ └── types.jsx │ │ │ └── index.js │ │ ├── HomePage │ │ │ ├── HomeController.jsx │ │ │ ├── HomePage.mdx │ │ │ ├── children │ │ │ │ ├── ApplicationsTableComponent.jsx │ │ │ │ ├── DiscoveriesTableComponent.jsx │ │ │ │ ├── DiscoveriesTableContainer.jsx │ │ │ │ ├── PipelinesTableComponent.jsx │ │ │ │ ├── QuickStartComponent.jsx │ │ │ │ ├── children │ │ │ │ │ ├── DiscoveryInformationDialog.jsx │ │ │ │ │ ├── EnhancedTableHead.jsx │ │ │ │ │ └── index.js │ │ │ │ └── index.js │ │ │ └── index.js │ │ ├── NotFoundPage │ │ │ ├── NotFoundPage.jsx │ │ │ ├── NotFoundPage.mdx │ │ │ └── index.js │ │ ├── SettingsPage │ │ │ ├── Profile │ │ │ │ ├── UserProfilePage.mdx │ │ │ │ ├── UserProfilePageComponent.jsx │ │ │ │ ├── UserProfilePageContainer.jsx │ │ │ │ └── index.js │ │ │ ├── Settings │ │ │ │ ├── SettingsPage.mdx │ │ │ │ ├── SettingsPageComponent.jsx │ │ │ │ ├── SettingsPageContainer.jsx │ │ │ │ └── index.js │ │ │ ├── SettingsController.jsx │ │ │ └── index.js │ │ └── index.js │ ├── ducks │ │ ├── applicationDuck │ │ │ ├── actions.jsx │ │ │ ├── index.js │ │ │ ├── reducers.jsx │ │ │ ├── selectors.jsx │ │ │ └── types.jsx │ │ ├── discoveryDuck │ │ │ ├── actions.jsx │ │ │ ├── index.js │ │ │ ├── reducers.jsx │ │ │ ├── selectors.jsx │ │ │ └── types.jsx │ │ ├── etlDuck │ │ │ ├── actions.jsx │ │ │ ├── index.js │ │ │ ├── reducers.jsx │ │ │ ├── selectors.jsx │ │ │ └── types.jsx │ │ ├── filtersDuck │ │ │ ├── actions.jsx │ │ │ ├── index.js │ │ │ ├── reducers.jsx │ │ │ └── types.jsx │ │ ├── globalDuck │ │ │ ├── actions.jsx │ │ │ ├── index.js │ │ │ ├── reducers.jsx │ │ │ ├── selectors.jsx │ │ │ └── types.jsx │ │ ├── index.js │ │ └── userDuck │ │ │ ├── actions.jsx │ │ │ ├── index.js │ │ │ ├── reducers.jsx │ │ │ ├── selectors.jsx │ │ │ └── types.jsx │ ├── index.html │ ├── index.jsx │ ├── index.mdx │ ├── layouts │ │ ├── PrivateLayout │ │ │ ├── PrivateLayout.jsx │ │ │ └── index.js │ │ ├── PublicLayout │ │ │ ├── PublicLayout.jsx │ │ │ └── index.js │ │ └── index.js │ ├── storage │ │ ├── StorageBackend.jsx │ │ ├── StorageSparqlClient.jsx │ │ ├── StorageToolbox.jsx │ │ ├── components │ │ │ ├── StorageAccessControlDialog.jsx │ │ │ ├── StorageInboxDialog.jsx │ │ │ ├── StoragePickFolderDialog.jsx │ │ │ └── index.js │ │ ├── containers │ │ │ ├── StoragePage │ │ │ │ ├── StorageAppsBrowserComponent.jsx │ │ │ │ ├── StorageAppsBrowserContainer.jsx │ │ │ │ ├── StoragePageController.jsx │ │ │ │ ├── StorageSharedAppsBrowserComponent.jsx │ │ │ │ ├── StorageSharedAppsBrowserContainer.jsx │ │ │ │ ├── children │ │ │ │ │ ├── StorageAppsBrowserCardComponent.jsx │ │ │ │ │ └── index.js │ │ │ │ └── index.js │ │ │ └── index.js │ │ ├── index.js │ │ ├── models │ │ │ ├── AcceptedInvitation.jsx │ │ │ ├── AccessControl.jsx │ │ │ ├── ApplicationConfiguration.jsx │ │ │ ├── ApplicationMetadata.jsx │ │ │ ├── FilterConfiguration.jsx │ │ │ ├── Invitation.jsx │ │ │ ├── Item.jsx │ │ │ ├── Person.jsx │ │ │ ├── SharedApplicationConfiguration.jsx │ │ │ └── index.js │ │ └── utils │ │ │ ├── SolidUtils.jsx │ │ │ ├── index.js │ │ │ └── rdfjssourcefactory.jsx │ ├── store.jsx │ ├── utils │ │ ├── api.service.jsx │ │ ├── authentication.utils.jsx │ │ ├── discovery.service.jsx │ │ ├── etl.service.jsx │ │ ├── global.utils.jsx │ │ ├── google-analytics-wrapper.jsx │ │ ├── index.js │ │ ├── logger.service.jsx │ │ ├── socket.service.jsx │ │ ├── third-party │ │ │ ├── index.js │ │ │ └── with-authorization.component.jsx │ │ ├── user.service.jsx │ │ └── visualizers.service.jsx │ ├── withRoot.jsx │ └── wrapper.js ├── webpack.config.js └── yarn.lock └── tests ├── browserstack_plugins └── fast_selenium.py ├── e2e_tests.py └── requirements.txt /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop (please complete the following information):** 24 | - OS: [e.g. iOS] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 22] 27 | 28 | **Smartphone (please complete the following information):** 29 | - Device: [e.g. iPhone6] 30 | - OS: [e.g. iOS8.1] 31 | - Browser [e.g. stock browser, safari] 32 | - Version [e.g. 22] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Exclude bundled js 2 | bundle.js 3 | 4 | *# 5 | *.iml 6 | *.ipr 7 | *.iws 8 | *.jar 9 | *.sw? 10 | *~ 11 | .#* 12 | .*.md.html 13 | .DS_Store 14 | .classpath 15 | .factorypath 16 | .gradle 17 | .idea 18 | .metadata 19 | .project 20 | .recommenders 21 | .settings 22 | .springBeans 23 | /build 24 | /code 25 | MANIFEST.MF 26 | _site/ 27 | activemq-data 28 | bin 29 | build 30 | build.log 31 | dependency-reduced-pom.xml 32 | dump.rdb 33 | interpolated*.xml 34 | manifest.yml 35 | overridedb.* 36 | settings.xml 37 | target 38 | transaction-logs 39 | .flattened-pom.xml 40 | secrets.yml 41 | .gradletasknamecache 42 | .sts4-cache 43 | 44 | # Frontend 45 | .DS_STORE 46 | node_modules 47 | scripts/flow/*/.flowconfig 48 | *~ 49 | *.pyc 50 | .grunt 51 | _SpecRunner.html 52 | __benchmarks__ 53 | build/ 54 | remote-repo/ 55 | coverage/ 56 | flow-coverage/ 57 | .module-cache 58 | fixtures/dom/public/react-dom.js 59 | fixtures/dom/public/react.js 60 | test/the-files-to-test.generated.js 61 | *.log* 62 | chrome-user-data 63 | *.sublime-project 64 | *.sublime-workspace 65 | .idea 66 | *.iml 67 | .vscode 68 | *.swp 69 | *.swo 70 | 71 | #Database 72 | data 73 | src/backend/create.sql 74 | 75 | src/frontend/public/ 76 | 77 | src/tests/venv/ 78 | 79 | appdata/ 80 | 81 | src/frontend/eslint/ 82 | 83 | src/frontend/docs/ 84 | 85 | src/tests/.venv/ 86 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "schedule": "before 3am on the first day of the month", 4 | "assignees": ["aorumbayev"], 5 | "baseBranches": ["dependency_updates"], 6 | "separateMajorMinor": true, 7 | "rebaseStalePrs": true, 8 | "automerge": true, 9 | "major": { 10 | "automerge": false 11 | }, 12 | "minor": { 13 | "automerge": true 14 | }, 15 | "patch": { 16 | "automerge": true 17 | }, 18 | "pin": { 19 | "automerge": true 20 | }, 21 | "lockFileMaintenance": { 22 | "automerge": true, 23 | "enabled": true, 24 | "extends": "schedule:monthly" 25 | }, 26 | "docker": { 27 | "enabled": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/backend/.dockerfile: -------------------------------------------------------------------------------- 1 | config.properties 2 | -------------------------------------------------------------------------------- /src/backend/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !lib/*.jar 5 | 6 | ### STS ### 7 | .apt_generated 8 | .classpath 9 | .factorypath 10 | .project 11 | .settings 12 | .springBeans 13 | .sts4-cache 14 | 15 | ### IntelliJ IDEA ### 16 | .idea 17 | *.iws 18 | *.iml 19 | *.ipr 20 | /out/ 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ -------------------------------------------------------------------------------- /src/backend/Dockerfile: -------------------------------------------------------------------------------- 1 | # Using OpenJDK 11 2 | FROM gradle:5.6.4-jdk11 as builder 3 | 4 | # Tomcat will eventually create directories here 5 | VOLUME /tmp 6 | 7 | # copy files 8 | COPY --chown=gradle . /app 9 | WORKDIR /app 10 | 11 | # build the app 12 | RUN gradle unpack 13 | 14 | FROM openjdk:11-jre-slim 15 | 16 | # Expose port 8080 17 | EXPOSE 9005 18 | EXPOSE 9092 19 | 20 | COPY --from=builder /app/build/dependency/BOOT-INF/lib /app/lib 21 | COPY --from=builder /app/build/dependency/META-INF /app/META-INF 22 | COPY --from=builder /app/build/dependency/BOOT-INF/classes /app 23 | 24 | COPY src/main/resources/com/linkedpipes/lpa/backend/services/base.ttl /app/src/data/rdf/base.ttl 25 | 26 | ENTRYPOINT ["java","-cp","app:app/lib/*","com.linkedpipes.lpa.backend.Application"] 27 | -------------------------------------------------------------------------------- /src/backend/docs/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.eden.orchidPlugin" version "0.18.1" 3 | } 4 | 5 | repositories { 6 | jcenter() 7 | maven { url = 'https://kotlin.bintray.com/kotlinx' } 8 | maven { url = 'https://jitpack.io' } 9 | } 10 | 11 | dependencies { 12 | def orchid_version = '0.18.1' 13 | compile "io.github.javaeden.orchid:OrchidCore:${orchid_version}" 14 | orchidCompile "io.github.javaeden.orchid:OrchidCore:${orchid_version}" 15 | orchidRuntime "io.github.javaeden.orchid:OrchidPages:${orchid_version}" 16 | orchidRuntime "io.github.javaeden.orchid:OrchidJavadoc:${orchid_version}" 17 | orchidRuntime "io.github.javaeden.orchid:OrchidSearch:${orchid_version}" 18 | orchidRuntime "io.github.javaeden.orchid:OrchidBsDoc:${orchid_version}" 19 | 20 | orchidRuntime "io.github.javaeden.orchid:OrchidSyntaxHighlighter:${orchid_version}" 21 | orchidRuntime "io.github.javaeden.orchid:OrchidPluginDocs:${orchid_version}" 22 | orchidRuntime "io.github.javaeden.orchid:OrchidWritersBlocks:${orchid_version}" 23 | } 24 | 25 | project.version = '1.0.0' 26 | 27 | orchid { 28 | version = "${project.version}" 29 | theme = "BsDoc" 30 | environment = 'debug' 31 | baseUrl = 'https://docs.backend.applications.linkedpipes.com' 32 | } -------------------------------------------------------------------------------- /src/backend/docs/src/orchid/resources/assets/css/sideNav.css: -------------------------------------------------------------------------------- 1 | ul.nav { 2 | display: inline-block; 3 | } 4 | -------------------------------------------------------------------------------- /src/backend/docs/src/orchid/resources/config.yml: -------------------------------------------------------------------------------- 1 | javadoc: 2 | sourceDirs: 3 | - '../../../../src/main/java' 4 | classPages: 5 | menu: 6 | - type: 'javadocClassLinks' 7 | pages: 8 | menu: 9 | - type: 'javadocPackages' 10 | 11 | site: 12 | about: 13 | siteName: 'LinkedPipes Applications Backend' 14 | siteDescription: Learn all about Backend service in LinkedPipes Applications platform. 15 | 16 | 17 | theme: 18 | useSidebarSearch: true 19 | social: 20 | github: 'linkedpipes/applications' 21 | primaryColor: '#fba333' 22 | secondaryColor: '#00695c' 23 | linkColor: '#7E80CF' 24 | trianglifyOptions: 25 | x_colors: 'BuPu' 26 | cell_size: 55 27 | seed: 1 28 | menu: 29 | - type: 'link' 30 | title: 'Getting Started' 31 | url: '/' 32 | 33 | - type: 'submenu' 34 | title: 'Chapters' 35 | menu: 36 | - type: 'page' 37 | itemId: 'Installation' 38 | - type: 'page' 39 | itemId: 'Component overview' 40 | - type: 'page' 41 | itemId: 'Architecture' 42 | - type: 'page' 43 | itemId: 'Code Structure' 44 | - type: 'page' 45 | itemId: 'Configuring Discovery' 46 | 47 | - type: 'link' 48 | title: 'Javadoc' 49 | url: '/com/linkedpipes/lpa/backend' 50 | 51 | allPages: 52 | extraCss: 53 | - 'assets/css/sideNav.css' 54 | - 'assets/css/color.css' 55 | components: 56 | - type: "pageContent" 57 | - type: "prism" 58 | githubTheme: 'duotone-light' 59 | languages: 60 | - kotlin 61 | - java 62 | - groovy 63 | - yaml 64 | - asciidoc 65 | - markdown -------------------------------------------------------------------------------- /src/backend/docs/src/orchid/resources/config/pages.yml: -------------------------------------------------------------------------------- 1 | staticPages: 2 | menu: 3 | - type: "pageIds" 4 | -------------------------------------------------------------------------------- /src/backend/docs/src/orchid/resources/pages/chapters/architecture.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Architecture" 3 | --- 4 | 5 | ## Backend high-level architecture 6 | 7 | As per the aforementioned MVC architecture model, LPA Backend contains following main architectural components: 8 | 9 | - **Controllers** that handle deserialization and serialization of the payloads and parameters of the HTTP requests and 10 | responses. These classes are located in the 11 | [`com.linkedpipes.lpa.backend.controllers`](/com/linkedpipes/lpa/backend/controllers) java package. The controllers 12 | utilize _services_ which implement the application's business logic 13 | - **Services** are located in [`com.linkedpipes.lpa.backend.services`](/com/linkedpipes/lpa/backend/services) and 14 | provide a use-case drive high-level abstraction over the performed tasks 15 | - **Model** entities which are persisted in the persistence layer of Backend; for more information see classes in 16 | [`com.linkedpipes.lpa.backend.entities.database`](/com/linkedpipes/lpa/backend/entities/database). 17 | 18 | Usually, one controller method corresponds directly to one service method, although this may not be the case in all 19 | circumstances. A general invocation of a controller method can be split into these tasks: 20 | 21 | - receives an HTTP request 22 | - deserializes the payload and parameters of the request 23 | - validates the payload and parameters 24 | - calls a corresponding service method (or several) 25 | - serializes the response payload 26 | - returns an HTTP response back to the requester 27 | -------------------------------------------------------------------------------- /src/backend/docs/src/orchid/resources/pages/chapters/code-structure.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Code Structure" 3 | --- 4 | 5 | ## Code structure 6 | 7 | Backend implementation is located inside the `src/backend/` base directory. It is a Gradle-based project, thus it 8 | follows the Gradle directory structure: 9 | ``` 10 | src/ 11 | |-- main/ 12 | | |-- config/ contains the configuration files 13 | | |-- java/ contains the Java source code 14 | | | |-- com/linkedpipes/lpa/backend/ base package 15 | | | |-- controllers/ contains all controllers 16 | | | |-- entities/ contains the data model 17 | | | |-- services/ contains all services 18 | | | |-- ... 19 | | |-- resources/ contains the related classpath resources 20 | | |-- com/linkedpipes/lpa/backend/services/base.ttl The base.ttl file 21 | | |-- ... 22 | |-- test/ 23 | |-- java/ contains the test source code 24 | |-- resources/ contains the related classpath resources 25 | ``` 26 | -------------------------------------------------------------------------------- /src/backend/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedpipes/applications/e79c72f74e82f7257a8141b7de00ab9ec207e65f/src/backend/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/backend/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Aug 27 12:47:16 CST 2018 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip 7 | -------------------------------------------------------------------------------- /src/backend/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'backend' 2 | 3 | include 'docs' 4 | -------------------------------------------------------------------------------- /src/backend/src/main/config/application.conf: -------------------------------------------------------------------------------- 1 | lpa { 2 | hostUrl = "http://lpa-backend:9005" 3 | discoveryServiceUrl = "http://lpa-discovery:9000" 4 | etlServiceUrl = "http://lpa-etl:8080/resources" 5 | allowedOrigins = ["http://localhost:9001", "https://applications.linkedpipes.com"] 6 | virtuoso { 7 | queryEndpoint = "http://lpa-virtuoso:8890/sparql" 8 | crudEndpoint = "http://lpa-virtuoso:8890/sparql-graph-crud" 9 | } 10 | 11 | dataSample { 12 | sharedVolumeDir = "/appdata/datasample" 13 | resultGraphIri = "https://applications.linkedpipes.com/graph/test-data-sample-graph" 14 | } 15 | 16 | github { 17 | user = "LinkedPipesApps" 18 | password = "linked_pipes_team" 19 | } 20 | 21 | timeout { 22 | discoveryPollingTimeoutMins = 1440 # 24h 23 | etlPollingTimeoutMins = 1440 # 24h 24 | discoveryPollingFrequencySecs = 10 25 | etlPollingFrequencySecs = 10 26 | } 27 | 28 | github { 29 | username = "LinkedPipesApps" 30 | password = "linked_pipes_team" 31 | } 32 | } 33 | 34 | # Templates : ====== 35 | 36 | #discoveryServiceUrl = "http://demo.visualization.linkedpipes.com:8080" 37 | #etlServiceUrl = "http://xrg12.ms.mff.cuni.cz:8090/resources" 38 | #etlServiceUrl = "https://demo.etl.linkedpipes.com/resources" 39 | 40 | # ====== 41 | -------------------------------------------------------------------------------- /src/backend/src/main/config/application.properties: -------------------------------------------------------------------------------- 1 | # This is here because Spring Boot can't read .conf files 2 | server.port=9005 3 | spring.jackson.mapper.accept_case_insensitive_properties=true 4 | # Max file size. 5 | spring.servlet.multipart.max-file-size=100MB 6 | # Max request size. 7 | spring.servlet.multipart.max-request-size=100MB 8 | 9 | spring.datasource.url=jdbc:postgresql://lpa-postgres:5432/lpa 10 | spring.datasource.username=lpa 11 | spring.datasource.password=example 12 | spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQL95Dialect 13 | spring.jpa.hibernate.ddl-auto=validate 14 | spring.jpa.generate-ddl=true 15 | spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true 16 | spring.jpa.open-in-view=false 17 | 18 | #spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata 19 | #spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create 20 | #spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql 21 | -------------------------------------------------------------------------------- /src/backend/src/main/config/reference.conf: -------------------------------------------------------------------------------- 1 | lpa { 2 | hostUrl = "http://localhost:8080" 3 | discoveryServiceUrl = "http://demo.visualization.linkedpipes.com:8080" 4 | etlServiceUrl = "https://demo.etl.linkedpipes.com/resources" 5 | allowedOrigins = "http://localhost" 6 | virtuoso { 7 | queryEndpoint = "http://linked.opendata.cz/sparql" 8 | crudEndpoint = "http://linked.opendata.cz/sparql" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/constants/ApplicationPropertyKeys.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.constants; 2 | 3 | public final class ApplicationPropertyKeys { 4 | 5 | public static final String HOST_URL = "lpa.hostUrl"; 6 | public static final String VIRTUOSO_QUERY_ENDPOINT = "lpa.virtuoso.queryEndpoint"; 7 | public static final String VIRTUOSO_CRUD_ENDPOINT = "lpa.virtuoso.crudEndpoint"; 8 | public static final String DISCOVERY_SERVICE_URL = "lpa.discoveryServiceUrl"; 9 | public static final String ETL_SERVICE_URL = "lpa.etlServiceUrl"; 10 | public static final String DISCOVERY_POLLING_TIMEOUT = "lpa.timeout.discoveryPollingTimeoutMins"; 11 | public static final String ETL_POLLING_TIMEOUT = "lpa.timeout.etlPollingTimeoutMins"; 12 | public static final String DISCOVERY_POLLING_FREQUENCY = "lpa.timeout.discoveryPollingFrequencySecs"; 13 | public static final String ETL_POLLING_FREQUENCY = "lpa.timeout.etlPollingFrequencySecs"; 14 | public static final String GITHUB_USER = "lpa.github.user"; 15 | public static final String GITHUB_PASSWORD = "lpa.github.password"; 16 | public static final String DATA_SAMPLE_SHARED_VOLUME_DIR = "lpa.dataSample.sharedVolumeDir"; 17 | public static final String DATA_SAMPLE_RESULT_GRAPH_IRI = "lpa.dataSample.resultGraphIri"; 18 | 19 | private ApplicationPropertyKeys() { 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/constants/SupportedRDFMimeTypes.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.constants; 2 | 3 | import org.apache.jena.riot.Lang; 4 | import org.apache.jena.riot.RDFLanguages; 5 | import java.util.Map; 6 | 7 | import static java.util.Map.entry; 8 | 9 | public final class SupportedRDFMimeTypes { 10 | 11 | private SupportedRDFMimeTypes() { 12 | } 13 | 14 | /* 15 | Create array explicitly to allow for trailing comma after last array element, which improves diff readability. 16 | */ 17 | private static final Map.Entry[] mimeTypeToRiotLangMappings = { 18 | entry("text/turtle", RDFLanguages.TTL), 19 | entry("application/n-triples", RDFLanguages.NT), 20 | entry("application/n-quads", RDFLanguages.NQ), 21 | entry("application/trig", RDFLanguages.TRIG), 22 | entry("application/rdf+xml", RDFLanguages.RDFXML), 23 | entry("application/ld+json", RDFLanguages.JSONLD), 24 | }; 25 | 26 | @SuppressWarnings("unchecked") 27 | public static final Map mimeTypeToRiotLangMap = Map.ofEntries(mimeTypeToRiotLangMappings); 28 | } 29 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/constants/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Miscellaneous shared constants. 3 | */ 4 | package com.linkedpipes.lpa.backend.constants; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/controllers/ExecutionController.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.controllers; 2 | 3 | import com.linkedpipes.lpa.backend.exceptions.LpAppsException; 4 | import com.linkedpipes.lpa.backend.services.EtlService; 5 | import org.jetbrains.annotations.NotNull; 6 | import org.springframework.context.ApplicationContext; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.RequestParam; 10 | import org.springframework.web.bind.annotation.ResponseBody; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | @RestController 14 | public class ExecutionController { 15 | 16 | private final EtlService etlService; 17 | 18 | public ExecutionController(ApplicationContext context) { 19 | etlService = context.getBean(EtlService.class); 20 | } 21 | 22 | /** 23 | * Get the result of a pipeline execution from the ETL service. 24 | * 25 | * @param executionIri IRI of the ETL execution to get the result of 26 | * @return the result 27 | * @throws LpAppsException if the retrieval fails for any reason 28 | */ 29 | @GetMapping("/api/execution/result") 30 | @ResponseBody 31 | public ResponseEntity getResult(@NotNull @RequestParam(value = "executionIri") String executionIri) throws LpAppsException { 32 | String result = etlService.getExecutionResult(executionIri); 33 | return ResponseEntity.ok(result); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/controllers/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Controllers define API endpoints and handle requests coming from frontend. 3 | * The controllers usually call some service to handle the request. 4 | */ 5 | package com.linkedpipes.lpa.backend.controllers; 6 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/ApplicationInstance.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public class ApplicationInstance { 4 | 5 | public String visualizerCode; 6 | public String label; 7 | public String iri; 8 | public String executorIri; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/DataSource.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public class DataSource { 4 | 5 | public String uri; 6 | public String label; 7 | 8 | public DataSource(String uri) { 9 | this.uri = uri; 10 | } 11 | 12 | public DataSource() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/DataSourceGroup.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class DataSourceGroup { 7 | public List dataSources; 8 | public List pipelines; 9 | 10 | public DataSourceGroup(){ 11 | dataSources = new ArrayList<>(); 12 | pipelines = new ArrayList<>(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/Discovery.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public class Discovery { 4 | 5 | public String id; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/DiscoveryDeleted.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public class DiscoveryDeleted { 4 | public String discoveryId, socketId; 5 | } 6 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/DiscoveryStatus.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public class DiscoveryStatus { 4 | public int pipelineCount; 5 | public boolean isFinished; 6 | public long duration; 7 | } 8 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/EdgeDirection.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public enum EdgeDirection { 4 | INCOMING, 5 | OUTGOING 6 | } 7 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/ErrorResponse.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public class ErrorResponse { 4 | 5 | public String errorMessage; 6 | public int errorCode; 7 | 8 | public ErrorResponse(int errorCode, String errorMessage){ 9 | 10 | this.errorMessage = errorMessage; 11 | this.errorCode = errorCode; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/Execution.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public class Execution { 4 | public String iri; 5 | } 6 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/ExecutionDeleted.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public class ExecutionDeleted { 4 | public String executionIri, socketId; 5 | } 6 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/ExecutionStatus.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.util.Date; 6 | 7 | public class ExecutionStatus { 8 | 9 | @JsonProperty("status") 10 | public EtlStatus status; 11 | 12 | public Date started, finished; 13 | 14 | @JsonProperty("executionStarted") 15 | public long getStarted() { 16 | if (started != null) { 17 | return started.getTime() / 1000L; 18 | } else { 19 | return -1; 20 | } 21 | } 22 | 23 | @JsonProperty("executionFinished") 24 | public long getFinished() { 25 | if (finished != null) { 26 | return finished.getTime() / 1000L; 27 | } else { 28 | return -1; 29 | } 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return "ExecutionStatus{" + 35 | "status=" + status + 36 | ", started=" + started + 37 | ", finished=" + finished + 38 | '}'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/MapQueryData.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | import com.linkedpipes.lpa.backend.sparql.ValueFilter; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class MapQueryData { 11 | 12 | @NotNull 13 | public Map> filters = new HashMap<>(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/Pipeline.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public class Pipeline { 4 | 5 | public String id; 6 | public String name; 7 | public String descriptor; 8 | public int componentCount; 9 | public int minimalIteration; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/PipelineExportResult.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public class PipelineExportResult { 4 | public String pipelineId; 5 | public String etlPipelineIri; 6 | public String resultGraphIri; 7 | } 8 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/PipelineGroup.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class PipelineGroup { 7 | public ApplicationInstance visualizer; 8 | public List dataSourceGroups; 9 | 10 | public PipelineGroup(){ 11 | dataSourceGroups = new ArrayList<>(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/PipelineGroups.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class PipelineGroups { 7 | 8 | public List pipelineGroups; 9 | 10 | public PipelineGroups(){ 11 | pipelineGroups = new ArrayList<>(); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/ServiceDescription.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities; 2 | 3 | public class ServiceDescription { 4 | 5 | public String sdIri; 6 | 7 | public ServiceDescription(String serviceDescriptionIri){ 8 | sdIri = serviceDescriptionIri; 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/database/ApplicationDao.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.database; 2 | 3 | import java.io.Serializable; 4 | import javax.persistence.*; 5 | 6 | /** 7 | * Record on published applications and pipeline executions used to create them. 8 | * Applications are mapped onto user profile. 9 | */ 10 | @Entity(name="application") 11 | public class ApplicationDao implements Serializable { 12 | 13 | @Id 14 | @GeneratedValue 15 | private long id; 16 | 17 | @Column(nullable = false, columnDefinition = "TEXT") 18 | private String solidIri; 19 | 20 | @ManyToOne 21 | @JoinColumn(name="execution_id", nullable = true) 22 | private ExecutionDao execution; 23 | 24 | @ManyToOne 25 | @JoinColumn(name="user_id", nullable = false) 26 | private UserDao user; 27 | 28 | public long getId() { 29 | return this.id; 30 | } 31 | 32 | public void setSolidIri(final String solidIri) { 33 | this.solidIri = solidIri; 34 | } 35 | 36 | public String getSolidIri() { 37 | return solidIri; 38 | } 39 | 40 | public ExecutionDao getExecution() { 41 | return this.execution; 42 | } 43 | 44 | public void setExecution(final ExecutionDao execution) { 45 | this.execution = execution; 46 | } 47 | 48 | public UserDao getUser() { 49 | return this.user; 50 | } 51 | 52 | public void setUser(final UserDao user) { 53 | this.user = user; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/database/ApplicationRepository.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.database; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public interface ApplicationRepository extends CrudRepository { 8 | } 9 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/database/DiscoveryNamedGraphDao.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.database; 2 | 3 | import java.io.Serializable; 4 | import javax.persistence.*; 5 | 6 | @Entity(name="discovery_named_graph") 7 | public class DiscoveryNamedGraphDao implements Serializable { 8 | @Id 9 | @GeneratedValue 10 | private int id; 11 | 12 | @ManyToOne 13 | @JoinColumn(name="discovery_id") 14 | private DiscoveryDao discovery; 15 | 16 | @Column(nullable = true, columnDefinition = "TEXT") 17 | private String namedGraph; 18 | 19 | public String getNamedGraph() { 20 | return namedGraph; 21 | } 22 | 23 | public void setNamedGraph(String named) { 24 | this.namedGraph = named; 25 | } 26 | 27 | public DiscoveryDao getDiscovery() { 28 | return discovery; 29 | } 30 | 31 | public void setDiscovery(DiscoveryDao d) { 32 | this.discovery = d; 33 | 34 | if (!d.getNamedGraphs().contains(this)) { 35 | d.addNamedGraph(this); 36 | } 37 | } 38 | 39 | public int getId() { 40 | return id; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/database/DiscoveryNamedGraphRepository.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.database; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | import org.springframework.stereotype.Repository; 5 | 6 | @Repository 7 | public interface DiscoveryNamedGraphRepository extends CrudRepository { 8 | } 9 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/database/DiscoveryRepository.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.database; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | import org.springframework.stereotype.Repository; 5 | import java.util.List; 6 | 7 | @Repository 8 | public interface DiscoveryRepository extends CrudRepository { 9 | List findByDiscoveryId(String discoveryId); 10 | List findById(long id); 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/database/ExecutionRepository.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.database; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | import org.springframework.data.jpa.repository.Query; 5 | import org.springframework.stereotype.Repository; 6 | import java.util.List; 7 | 8 | @Repository 9 | public interface ExecutionRepository extends CrudRepository { 10 | List findByExecutionIri(String executionIri); 11 | 12 | @Query(value="select * from execution e where e.pipeline_id = ?1", nativeQuery=true) 13 | List findExecutionsUsingPipelineNative(long pipelineId); 14 | 15 | List findByScheduled(boolean scheduled); 16 | } 17 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/database/PipelineInformationRepository.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.database; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | import org.springframework.stereotype.Repository; 5 | import java.util.List; 6 | 7 | @Repository 8 | public interface PipelineInformationRepository extends CrudRepository { 9 | List findByEtlPipelineIri(String pipelineIri); 10 | List findByResultGraphIri(String resultGraphIri); 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/database/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.database; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | import org.springframework.stereotype.Repository; 5 | import java.util.List; 6 | 7 | @Repository 8 | public interface UserRepository extends CrudRepository { 9 | List findByWebId(String webId); 10 | } 11 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/database/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Spring JPA related classes like DAOs and Repositories. 3 | */ 4 | package com.linkedpipes.lpa.backend.entities.database; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/geo/Coordinates.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.geo; 2 | 3 | public class Coordinates { 4 | public Double lat; 5 | public Double lng; 6 | 7 | public Coordinates(Double latIn, Double lngIn){ 8 | lat = latIn; 9 | lng = lngIn; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/geo/Marker.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.geo; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | public class Marker { 6 | 7 | public String uri; 8 | public Coordinates coordinates; 9 | public LocalizedValue label; 10 | public String description; 11 | 12 | public Marker(String uriIn, Coordinates coordinatesIn, LocalizedValue labelIn, String descriptionIn){ 13 | uri = uriIn; 14 | coordinates = coordinatesIn; 15 | label = labelIn; 16 | description = descriptionIn; 17 | } 18 | 19 | public String toString() { 20 | return String.format("Marker{uri: \"%s\", coords: \"{%f, %f}\", label: \"%s\", desc: \"%s\"}", 21 | uri, coordinates.lat, coordinates.lng, label, description); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/geo/Polygon.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.geo; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Polygon { 7 | public List points; 8 | 9 | public Polygon(){ 10 | points = new ArrayList<>(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/geo/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Data objects representing geographical entities. 3 | */ 4 | package com.linkedpipes.lpa.backend.entities.geo; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package and its subpackages contain mainly classes used as structured data containers. These objects are meant 3 | * to be deserialized from and serialized into JSON when communicating with frontend, Discovery, or ETL. 4 | */ 5 | package com.linkedpipes.lpa.backend.entities; 6 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/profile/Application.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.profile; 2 | 3 | public class Application { 4 | public String solidIri; 5 | public boolean executionAvailable; 6 | } 7 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/profile/DiscoverySession.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.profile; 2 | 3 | import java.util.List; 4 | 5 | public class DiscoverySession { 6 | public String discoveryId, sparqlEndpointIri, dataSampleIri; 7 | public List namedGraphs; 8 | public boolean isFinished, isFailed; 9 | public long started, finished, sessionId; 10 | 11 | public static DiscoverySession create(long sessionId, String discoveryId) { 12 | DiscoverySession session = new DiscoverySession(); 13 | initBasics(session); 14 | session.isFinished = false; 15 | session.isFailed = false; 16 | session.sessionId = sessionId; 17 | session.discoveryId = discoveryId; 18 | return session; 19 | } 20 | 21 | public static DiscoverySession createError(long sessionId) { 22 | DiscoverySession session = new DiscoverySession(); 23 | initBasics(session); 24 | session.sessionId = sessionId; 25 | session.isFailed = true; 26 | session.discoveryId = null; 27 | session.isFinished = true; 28 | return session; 29 | } 30 | 31 | private static void initBasics(DiscoverySession session) { 32 | session.started = -1; 33 | session.finished = -1; 34 | session.sparqlEndpointIri = null; 35 | session.dataSampleIri = null; 36 | session.namedGraphs = null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/profile/PipelineExecution.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.profile; 2 | 3 | import com.linkedpipes.lpa.backend.entities.EtlStatus; 4 | import com.linkedpipes.lpa.backend.entities.database.ExecutionDao; 5 | 6 | public class PipelineExecution { 7 | public EtlStatus status; 8 | public String executionIri; 9 | public String etlPipelineIri; 10 | public String selectedVisualiser; 11 | public long started, finished, frequencyHours; 12 | public boolean scheduleOn, startedByUser; 13 | 14 | public static PipelineExecution getPipelineExecutionFromDao(final ExecutionDao e) { 15 | PipelineExecution exec = new PipelineExecution(); 16 | exec.status = e.getStatus(); 17 | exec.executionIri = e.getExecutionIri(); 18 | exec.etlPipelineIri = e.getPipeline().getEtlPipelineIri(); 19 | exec.selectedVisualiser = e.getSelectedVisualiser(); 20 | exec.started = e.getStarted().getTime() / 1000L; 21 | exec.scheduleOn = e.isScheduled(); 22 | exec.startedByUser = e.isStartedByUser(); 23 | exec.frequencyHours = e.getFrequencyHours(); 24 | if (e.getFinished() != null) { 25 | exec.finished = e.getFinished().getTime() / 1000L; 26 | } else { 27 | exec.finished = -1; 28 | } 29 | return exec; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/profile/UserProfile.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.profile; 2 | import java.util.List; 3 | 4 | public class UserProfile { 5 | public String webId, color; 6 | 7 | public List applications; 8 | public List discoverySessions; 9 | public List pipelineExecutions; 10 | } 11 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/profile/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Data objects representing entities related to LPA user profiles. 3 | */ 4 | package com.linkedpipes.lpa.backend.entities.profile; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/rgml/Edge.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.rgml; 2 | 3 | public class Edge { 4 | public String uri; 5 | public String source; 6 | public String target; 7 | public Double weight; 8 | 9 | //TODO maybe consider direction of edge? 10 | public Edge(String uri, String source, String target, Double weight) { 11 | this.uri = uri; 12 | this.source = source; 13 | this.target = target; 14 | this.weight = weight; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/rgml/Graph.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.rgml; 2 | 3 | public class Graph { 4 | public Boolean directed; 5 | public int nodeCount; 6 | public int edgeCount; 7 | 8 | public Graph(Boolean directed, int nodeCount, int edgeCount){ 9 | this.directed = directed; 10 | this.nodeCount = nodeCount; 11 | this.edgeCount = edgeCount; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/rgml/Node.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.rgml; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | public class Node { 6 | public String uri; 7 | public LocalizedValue label; 8 | 9 | public Node(String uri, LocalizedValue label){ 10 | this.uri = uri; 11 | this.label = label; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/rgml/NodeWithDegree.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.rgml; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | public class NodeWithDegree extends Node { 6 | public int inDegree; 7 | public int outDegree; 8 | 9 | public NodeWithDegree(String uri, LocalizedValue label, int inDegree, int outDegree){ 10 | super(uri, label); 11 | this.inDegree = inDegree; 12 | this.outDegree = outDegree; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/rgml/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Data objects representing RGML vocabulary entities. 3 | */ 4 | package com.linkedpipes.lpa.backend.entities.rgml; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/timeline/Instant.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.timeline; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | import java.util.Date; 6 | 7 | public class Instant { 8 | public String uri; 9 | public LocalizedValue label; 10 | public Date date; 11 | 12 | public Instant(String uriIn, Date dateIn){ 13 | uri = uriIn; 14 | date = dateIn; 15 | } 16 | 17 | public Instant(String uriIn, Date dateIn, LocalizedValue labelIn){ 18 | uri = uriIn; 19 | date = dateIn; 20 | label = labelIn; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/timeline/Interval.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.timeline; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | import java.util.Date; 6 | 7 | public class Interval { 8 | public String uri; 9 | public LocalizedValue label; 10 | public Date start; 11 | public Date end; 12 | 13 | public Interval(String uriIn, Date startIn, Date endIn){ 14 | uri = uriIn; 15 | start = startIn; 16 | end = endIn; 17 | } 18 | 19 | public Interval(String uriIn, Date startIn, Date endIn, LocalizedValue labelIn){ 20 | uri = uriIn; 21 | start = startIn; 22 | end = endIn; 23 | label = labelIn; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/timeline/ThingWithInstant.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.timeline; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | public class ThingWithInstant { 6 | public String uri; 7 | public LocalizedValue label; 8 | public Instant instant; 9 | 10 | public ThingWithInstant(String uriIn, Instant instantIn){ 11 | uri = uriIn; 12 | instant = instantIn; 13 | } 14 | 15 | public ThingWithInstant(String uriIn, Instant instantIn, LocalizedValue labelIn){ 16 | uri = uriIn; 17 | instant = instantIn; 18 | label = labelIn; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/timeline/ThingWithInterval.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.timeline; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | public class ThingWithInterval { 6 | public String uri; 7 | public LocalizedValue label; 8 | public Interval interval; 9 | 10 | public ThingWithInterval(String uriIn, Interval intervalIn){ 11 | uri = uriIn; 12 | interval = intervalIn; 13 | } 14 | 15 | public ThingWithInterval(String uriIn, Interval intervalIn, LocalizedValue labelIn){ 16 | uri = uriIn; 17 | interval = intervalIn; 18 | label = labelIn; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/timeline/ThingWithThingWithInstant.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.timeline; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | public class ThingWithThingWithInstant { 6 | public String uri; 7 | public LocalizedValue label; 8 | public ThingWithInstant objectWithInstant; 9 | 10 | public ThingWithThingWithInstant(String uriIn, ThingWithInstant objectWithInstantIn){ 11 | uri = uriIn; 12 | objectWithInstant = objectWithInstantIn; 13 | } 14 | 15 | public ThingWithThingWithInstant(String uriIn, ThingWithInstant objectWithInstantIn, LocalizedValue labelIn){ 16 | uri = uriIn; 17 | objectWithInstant = objectWithInstantIn; 18 | label = labelIn; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/timeline/ThingWithThingWithInterval.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.timeline; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | public class ThingWithThingWithInterval { 6 | public String uri; 7 | public LocalizedValue label; 8 | public ThingWithInterval objectWithInterval; 9 | 10 | public ThingWithThingWithInterval(String uriIn, ThingWithInterval objectWithIntervalIn){ 11 | uri = uriIn; 12 | objectWithInterval = objectWithIntervalIn; 13 | } 14 | 15 | public ThingWithThingWithInterval(String uriIn, ThingWithInterval objectWithIntervalIn, LocalizedValue labelIn){ 16 | uri = uriIn; 17 | objectWithInterval = objectWithIntervalIn; 18 | label = labelIn; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/visualization/Concept.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.visualization; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class Concept { 9 | public String uri; 10 | public LocalizedValue label; 11 | public LocalizedValue description; 12 | public String schemeUri; 13 | public Map linkUris; 14 | 15 | public Concept(){ 16 | linkUris = new HashMap<>(); 17 | } 18 | 19 | public Concept(String uriIn, LocalizedValue label, LocalizedValue description, String schemeUri, Map linkUris){ 20 | this.uri = uriIn; 21 | this.label = label; 22 | this.description = description; 23 | this.schemeUri = schemeUri; 24 | this.linkUris = linkUris; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/visualization/ConceptCount.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.visualization; 2 | 3 | public class ConceptCount { 4 | 5 | public String conceptUri; 6 | public int count; 7 | 8 | public ConceptCount(String conceptUri, int count) { 9 | this.conceptUri = conceptUri; 10 | this.count = count; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/visualization/ConceptCountRequest.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.visualization; 2 | 3 | import java.util.List; 4 | 5 | public class ConceptCountRequest { 6 | 7 | public String propertyUri; 8 | public List conceptUris; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/visualization/HierarchyNode.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.visualization; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | import java.util.List; 6 | 7 | public class HierarchyNode { 8 | public String id; 9 | public LocalizedValue label; 10 | public String parentId; 11 | public Double size; 12 | 13 | /*public HierarchyNode(LocalizedValue label, String id, Integer size) { 14 | this.label = label; 15 | this.id = id; 16 | this.size = size; 17 | } 18 | 19 | public HierarchyNode(LocalizedValue label, String id, Integer size, List children) { 20 | this.label = label; 21 | this.id = id; 22 | this.size = size; 23 | }*/ 24 | 25 | public HierarchyNode(String id, LocalizedValue label, String parentId, Double size) { 26 | this.id = id; 27 | this.label = label; 28 | this.parentId = parentId; 29 | this.size = size; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/visualization/Scheme.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.entities.visualization; 2 | 3 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 4 | 5 | public class Scheme { 6 | public String uri; 7 | public LocalizedValue label; 8 | public LocalizedValue description; 9 | 10 | public Scheme(String uri, LocalizedValue label, LocalizedValue description){ 11 | this.uri = uri; 12 | this.label = label; 13 | this.description = description; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/entities/visualization/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Data objects representing SKOS vocabulary entities. 3 | */ 4 | package com.linkedpipes.lpa.backend.entities.visualization; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/exceptions/ConnectionException.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.exceptions; 2 | 3 | import java.io.IOException; 4 | 5 | public class ConnectionException extends IOException { 6 | 7 | public ConnectionException(int errorCode, String responseMessage, String additional) { 8 | super(getMessage(errorCode, responseMessage, additional)); 9 | } 10 | 11 | public ConnectionException(int errorCode, String responseMessage, String additional, Throwable cause) { 12 | super(getMessage(errorCode, responseMessage, additional), cause); 13 | } 14 | 15 | private static String getMessage(int responseCode, String responseMessage, String additional) { 16 | return responseCode + " " + responseMessage + ": " + additional; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/exceptions/LpAppsException.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.exceptions; 2 | 3 | import org.springframework.http.HttpStatus; 4 | 5 | public class LpAppsException extends Exception { 6 | 7 | private final HttpStatus errorStatus; 8 | 9 | public LpAppsException(HttpStatus errorCode, String responseMessage) { 10 | super(responseMessage); 11 | this.errorStatus = errorCode; 12 | } 13 | 14 | public LpAppsException(HttpStatus errorCode, String responseMessage, Throwable cause) { 15 | super(responseMessage, cause); 16 | this.errorStatus = errorCode; 17 | } 18 | 19 | public HttpStatus getErrorStatus() { 20 | return this.errorStatus; 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/exceptions/PipelineNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.exceptions; 2 | 3 | import java.io.IOException; 4 | 5 | public class PipelineNotFoundException extends IOException { 6 | public PipelineNotFoundException(String pipelineId) { 7 | super(pipelineId); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/exceptions/PollingCompletedException.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.exceptions; 2 | 3 | public class PollingCompletedException extends RuntimeException { 4 | public PollingCompletedException() { 5 | super(); 6 | } 7 | 8 | public PollingCompletedException(Exception e) { 9 | super(e); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/exceptions/UserNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.exceptions; 2 | 3 | import java.io.IOException; 4 | 5 | public class UserNotFoundException extends IOException { 6 | 7 | public UserNotFoundException(String username) { 8 | super(username); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/exceptions/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Exceptions and exception handlers. 3 | */ 4 | package com.linkedpipes.lpa.backend.exceptions; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | *

3 | * Backend provides API for the LinkedPipes Applications. 4 | * It calls Discovery and ETL services and uses Virtuoso and 5 | * PostgreSQL databases for persistence. 6 | *

7 | * 8 | *

9 | * Backend uses SpringBoot. Main class is the Application class. 10 | * In controllers package there are handlers of the individual API endpoints. 11 | * Services package provides the high-level application logic. 12 | *

13 | */ 14 | package com.linkedpipes.lpa.backend; 15 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/Prefixes.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.rdf; 2 | 3 | public class Prefixes { 4 | public static final String SKOS_PREFIX = "skos"; 5 | public static final String RDFS_PREFIX = "rdfs"; 6 | public static final String DCTERMS_PREFIX = "dcterms"; 7 | public static final String RDF_PREFIX = "rdf"; 8 | public static final String SCHEMA_PREFIX = "s"; 9 | public static final String RGML_PREFIX = "rgml"; 10 | public static final String SD_PREFIX = "sd"; 11 | public static final String TIME_PREFIX = "time"; 12 | public static final String XSD_PREFIX = "xsd"; 13 | } 14 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/Property.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.rdf; 2 | 3 | public class Property { 4 | public LocalizedValue label; 5 | public String uri; 6 | public String schemeUri; 7 | 8 | public Property(LocalizedValue label, String uri, String schemeUri){ 9 | this.label = label; 10 | this.uri = uri; 11 | this.schemeUri = schemeUri; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * RDF related classes. 3 | */ 4 | package com.linkedpipes.lpa.backend.rdf; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/vocabulary/LPA.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.rdf.vocabulary; 2 | 3 | import org.apache.jena.rdf.model.Resource; 4 | 5 | public class LPA extends Vocabulary { 6 | 7 | public static final String uri = "https://applications.linkedpipes.com/"; 8 | 9 | public static class Dataset extends Vocabulary { 10 | 11 | public static final String uri = LPA.uri + "dataset/"; 12 | 13 | public static final Resource template = createResource(uri, "template"); 14 | public static final Resource output = createResource(uri, "output"); 15 | public static final Resource defaultConfiguration = createResource(uri, "defaultConfiguration"); 16 | public static final Resource defaultService = createResource(uri, "defaultService"); 17 | 18 | } 19 | 20 | public static class Generated extends Vocabulary { 21 | 22 | public static final String uri = LPA.uri + "generated-data/"; 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/vocabulary/LPD.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.rdf.vocabulary; 2 | 3 | import org.apache.jena.rdf.model.Property; 4 | import org.apache.jena.rdf.model.Resource; 5 | 6 | public class LPD extends Vocabulary { 7 | 8 | public static final String uri = "https://discovery.linkedpipes.com/vocabulary/"; 9 | 10 | public static final Resource DataSourceTemplate = createResource(uri, "DataSourceTemplate"); 11 | public static final Resource OutputDataPortTemplate = createResource(uri, "OutputDataPortTemplate"); 12 | 13 | public static final Property outputDataSample = createProperty(uri, "outputDataSample"); 14 | public static final Property outputTemplate = createProperty(uri, "outputTemplate"); 15 | public static final Property service = createProperty(uri, "service"); 16 | public static final Property componentConfigurationTemplate = createProperty(uri, "componentConfigurationTemplate"); 17 | public static final Property query = createProperty(uri, "query"); 18 | public static final Property configurationQuery = createProperty(uri, "configurationQuery"); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/vocabulary/LPDConf.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.rdf.vocabulary; 2 | 3 | import org.apache.jena.rdf.model.Resource; 4 | 5 | public class LPDConf extends Vocabulary { 6 | 7 | public static final String uri = "https://discovery.linkedpipes.com/vocabulary/dataset/dblp/configuration/"; 8 | 9 | public static final Resource Configuration = createResource(uri, "Configuration"); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/vocabulary/LPDSparql.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.rdf.vocabulary; 2 | 3 | import org.apache.jena.rdf.model.Resource; 4 | 5 | public class LPDSparql extends Vocabulary { 6 | 7 | public static final String uri = "https://discovery.linkedpipes.com/vocabulary/datasource/sparql/"; 8 | 9 | public static final Resource SparqlEndpointDataSourceConfiguration = createResource(uri, "SparqlEndpointDataSourceConfiguration"); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/vocabulary/RGML.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.rdf.vocabulary; 2 | 3 | import org.apache.jena.rdf.model.Property; 4 | import org.apache.jena.rdf.model.Resource; 5 | 6 | public class RGML extends Vocabulary { 7 | public static final String uri = "http://purl.org/puninj/2001/05/rgml-schema#"; 8 | 9 | public static final Resource Graph = createResource(uri, "Graph"); 10 | public static final Resource Node = createResource(uri, "Node"); 11 | public static final Resource Edge = createResource(uri, "Edge"); 12 | 13 | public static final Property directed = createProperty(uri, "directed"); 14 | public static final Property source = createProperty(uri, "source"); 15 | public static final Property target = createProperty(uri, "target"); 16 | public static final Property weight = createProperty(uri, "weight"); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/vocabulary/SD.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.rdf.vocabulary; 2 | 3 | import org.apache.jena.rdf.model.Property; 4 | import org.apache.jena.rdf.model.Resource; 5 | 6 | public class SD extends Vocabulary { 7 | 8 | public static final String uri = "http://www.w3.org/ns/sparql-service-description#"; 9 | 10 | public static final Resource Service = createResource(uri, "Service"); 11 | 12 | public static final Property endpoint = createProperty(uri, "endpoint"); 13 | public static final Property name = createProperty(uri, "name"); 14 | public static final Property namedGraph = createProperty(uri, "namedGraph"); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/vocabulary/Schema.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.rdf.vocabulary; 2 | 3 | import org.apache.jena.rdf.model.Property; 4 | 5 | public class Schema extends Vocabulary { 6 | 7 | public static final String uri = "http://schema.org/"; 8 | 9 | public static final Property geo = createProperty(uri, "geo"); 10 | public static final Property title = createProperty(uri, "title"); 11 | public static final Property description = createProperty(uri, "description"); 12 | public static final Property name = createProperty(uri, "name"); 13 | public static final Property latitude = createProperty(uri, "latitude"); 14 | public static final Property longitude = createProperty(uri, "longitude"); 15 | public static final Property startDate = createProperty(uri, "startDate"); 16 | public static final Property endDate = createProperty(uri, "endDate"); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/vocabulary/Time.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.rdf.vocabulary; 2 | 3 | import org.apache.jena.rdf.model.Property; 4 | 5 | public class Time extends Vocabulary { 6 | public static final String uri = "http://www.w3.org/2006/time#"; 7 | 8 | public static final Property hasBeginning = createProperty(uri, "hasBeginning"); 9 | public static final Property hasEnd = createProperty(uri, "hasEnd"); 10 | public static final Property inDateTime = createProperty(uri, "inDateTime"); 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/vocabulary/Vocabulary.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.rdf.vocabulary; 2 | 3 | import org.apache.jena.rdf.model.Property; 4 | import org.apache.jena.rdf.model.Resource; 5 | import org.apache.jena.rdf.model.ResourceFactory; 6 | 7 | abstract class Vocabulary { 8 | 9 | static Resource createResource(String nameSpace, String localName) { 10 | return ResourceFactory.createResource(nameSpace + localName); 11 | } 12 | 13 | static Property createProperty(String nameSpace, String localName) { 14 | return ResourceFactory.createProperty(nameSpace, localName); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/rdf/vocabulary/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Classes representing RDF vocabularies. 3 | */ 4 | package com.linkedpipes.lpa.backend.rdf.vocabulary; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/services/DataSamplePipelineInputGenerator.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | import com.linkedpipes.lpa.backend.util.rdfbuilder.ModelBuilder; 3 | import com.linkedpipes.lpa.backend.util.rdfbuilder.ResourceBuilder; 4 | import org.apache.jena.rdf.model.ResourceFactory; 5 | import java.util.UUID; 6 | 7 | 8 | public class DataSamplePipelineInputGenerator { 9 | public static String getDataSamplePipelineInput(String graphIri, String virtuosoEndpointIri) { 10 | ModelBuilder modelBuilder = ModelBuilder.empty().namespace("etl", "http://linked.opendata.cz/ontology/adhoc/"); 11 | ResourceBuilder resourceBuilder = modelBuilder.resource("https://applications.linkedpipes.com/ds-" + UUID.randomUUID().toString()); 12 | resourceBuilder.property(ResourceFactory.createProperty("http://linked.opendata.cz/ontology/adhoc/ep"), virtuosoEndpointIri); 13 | resourceBuilder.property(ResourceFactory.createProperty("http://linked.opendata.cz/ontology/adhoc/defaultGraphIri"), graphIri); 14 | return modelBuilder.toString(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/services/DisableDatabaseConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | 3 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 4 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.context.annotation.Profile; 7 | 8 | @Configuration 9 | @EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class) 10 | @Profile("disableDB") 11 | public class DisableDatabaseConfiguration { 12 | } 13 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/services/DiscoveryService.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | 3 | import com.linkedpipes.lpa.backend.entities.*; 4 | import com.linkedpipes.lpa.backend.exceptions.LpAppsException; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | import java.util.List; 8 | 9 | public interface DiscoveryService { 10 | 11 | Discovery startDiscoveryFromEndpoint(@NotNull String sparqlEndpointIri, @NotNull String dataSampleIri, @NotNull List namedGraphs) throws LpAppsException; 12 | 13 | Discovery startDiscoveryFromInput(String discoveryConfig) throws LpAppsException; 14 | 15 | Discovery startDiscoveryFromInputIri(String discoveryConfigIri) throws LpAppsException; 16 | 17 | DiscoveryStatus getDiscoveryStatus(String discoveryId) throws LpAppsException; 18 | 19 | PipelineGroups getPipelineGroups(String discoveryId) throws LpAppsException; 20 | 21 | PipelineExportResult exportPipeline(String discoveryId, String pipelineUri) throws LpAppsException; 22 | 23 | PipelineExportResult exportPipelineUsingSD(String discoveryId, String pipelineUri, ServiceDescription serviceDescription) throws LpAppsException; 24 | 25 | void cancelDiscovery(String discoveryId) throws LpAppsException; 26 | } -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/services/EtlService.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | 3 | import com.linkedpipes.lpa.backend.entities.Execution; 4 | import com.linkedpipes.lpa.backend.entities.ExecutionStatus; 5 | import com.linkedpipes.lpa.backend.exceptions.LpAppsException; 6 | 7 | public interface EtlService { 8 | Execution executePipeline(String etlPipelineIri) throws LpAppsException; 9 | ExecutionStatus getExecutionStatus(String executionIri) throws LpAppsException; 10 | String getExecutionResult(String executionIri) throws LpAppsException; 11 | void cancelExecution(String executionIri) throws LpAppsException; 12 | Execution executeDataSamplePipeline(String sparqlEndpointIri, String namedGraph) throws LpAppsException; 13 | } 14 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/services/PipelineExportService.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | 3 | import com.linkedpipes.lpa.backend.entities.PipelineExportResult; 4 | import com.linkedpipes.lpa.backend.exceptions.LpAppsException; 5 | import com.linkedpipes.lpa.backend.exceptions.PipelineNotFoundException; 6 | 7 | public interface PipelineExportService { 8 | PipelineExportResult exportPipeline(String discoveryId, String pipelineUri) throws LpAppsException; 9 | PipelineExportResult retrievePipelineExport(String pipelineId) throws PipelineNotFoundException; 10 | } 11 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/services/ScheduledExecutionService.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | 3 | public interface ScheduledExecutionService { 4 | void repeatExecution(long frequencyHours, boolean repeat, String executionIri, String userId, String selectedVisualiser); 5 | void stopScheduledExecution(boolean repeat, String executionIri); 6 | void stopScheduledExecution(String webId, String solidIri); 7 | } 8 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/services/ShutdownManager.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class ShutdownManager { 10 | 11 | @Autowired 12 | private ApplicationContext appContext; 13 | 14 | public void shutdown(int returnCode){ 15 | SpringApplication.exit(appContext, () -> returnCode); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/services/UserService.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | 3 | import com.linkedpipes.lpa.backend.entities.Discovery; 4 | import com.linkedpipes.lpa.backend.entities.database.DiscoveryDao; 5 | import com.linkedpipes.lpa.backend.entities.Execution; 6 | import com.linkedpipes.lpa.backend.entities.profile.*; 7 | import com.linkedpipes.lpa.backend.exceptions.LpAppsException; 8 | import com.linkedpipes.lpa.backend.exceptions.UserNotFoundException; 9 | import java.util.List; 10 | 11 | public interface UserService { 12 | UserProfile addUserIfNotPresent(String user); 13 | void setUserDiscovery(long dbId, String discoveryId, String sparqlEndpointIri, String dataSampleIri, List namedGraphs) throws UserNotFoundException; 14 | DiscoveryDao setUserDiscovery(String username) throws UserNotFoundException; 15 | void setUserExecution(String user, String execution, String etlPipelineIri, String visualizer) throws UserNotFoundException; 16 | UserProfile deleteExecution(String user, String executionIri) throws UserNotFoundException; 17 | UserProfile deleteDiscovery(String user, String discoveryId) throws UserNotFoundException; 18 | UserProfile setUserColorScheme(String user, String color) throws UserNotFoundException; 19 | UserProfile addApplication(String user, String executionIri, String solidIri) throws UserNotFoundException; 20 | UserProfile deleteApplication(String user, String solidIri) throws UserNotFoundException; 21 | PipelineExecution getExecution(String executionIri) throws LpAppsException; 22 | } 23 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/services/VisualizationService.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | 3 | import com.linkedpipes.lpa.backend.entities.visualization.*; 4 | import com.linkedpipes.lpa.backend.exceptions.LpAppsException; 5 | 6 | import java.util.List; 7 | 8 | public interface VisualizationService { 9 | List getSkosSchemes(String graphIri) throws LpAppsException; 10 | 11 | List getSkosScheme(String graphIri, String schemeUri) throws LpAppsException; 12 | 13 | List getSkosSchemeSubtree(String graphIri, String schemeUri, String conceptUri) throws LpAppsException; 14 | 15 | List getSkosConcepts(String graphIri) throws LpAppsException; 16 | 17 | List getSkosConceptsCounts(String graphIri, ConceptCountRequest request) throws LpAppsException; 18 | } 19 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/services/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Services are called by controllers. They implement the main business logic of the backend. 3 | */ 4 | package com.linkedpipes.lpa.backend.services; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/sparql/ValueFilter.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.sparql; 2 | 3 | public class ValueFilter { 4 | public String uri; 5 | public Boolean isActive; 6 | } 7 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/sparql/VariableGenerator.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.sparql; 2 | 3 | public class VariableGenerator { 4 | 5 | private int i = 0; 6 | 7 | public String getVariable(){ 8 | i++; 9 | return "?" + getName(); 10 | } 11 | 12 | private String getName(){ 13 | return "v" + Integer.toString(i); 14 | } 15 | 16 | public void reset() { 17 | i = 0; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/sparql/extractors/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Query extractors are used for extracting data gathered by a SPARQL query and returning it as a particular data 3 | * object. 4 | */ 5 | package com.linkedpipes.lpa.backend.sparql.extractors; 6 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/sparql/extractors/rgml/EdgesExtractor.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.sparql.extractors.rgml; 2 | 3 | import com.linkedpipes.lpa.backend.entities.rgml.Edge; 4 | import com.linkedpipes.lpa.backend.rdf.vocabulary.RGML; 5 | import org.apache.jena.query.QueryExecution; 6 | import org.apache.jena.rdf.model.Model; 7 | import org.apache.jena.rdf.model.Resource; 8 | import org.apache.jena.vocabulary.RDF; 9 | 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | 13 | public class EdgesExtractor { 14 | 15 | public static List extract(QueryExecution queryExec){ 16 | Model model = queryExec.execConstruct(); 17 | 18 | List edges = model.listResourcesWithProperty(RDF.type, RGML.Edge).toList(); 19 | 20 | return edges.stream().map(e -> 21 | new Edge(e.getURI(), 22 | e.getProperty(RGML.source).getResource().getURI(), 23 | e.getProperty(RGML.target).getResource().getURI(), 24 | e.getProperty(RGML.weight).getDouble())) 25 | .collect(Collectors.toList()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/sparql/extractors/rgml/GraphExtractor.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.sparql.extractors.rgml; 2 | 3 | import com.linkedpipes.lpa.backend.entities.rgml.Graph; 4 | import com.linkedpipes.lpa.backend.sparql.queries.rgml.GraphQueryProvider; 5 | import org.apache.jena.query.QueryExecution; 6 | import org.apache.jena.query.QuerySolution; 7 | import org.apache.jena.query.ResultSet; 8 | 9 | public class GraphExtractor { 10 | 11 | public static Graph extract(QueryExecution queryExec){ 12 | ResultSet result = queryExec.execSelect(); 13 | 14 | if(!result.hasNext()) 15 | return null; 16 | 17 | QuerySolution solution = result.next(); 18 | 19 | return new Graph(solution.getLiteral(GraphQueryProvider.VAR_DIRECTED).getBoolean(), 20 | solution.getLiteral(GraphQueryProvider.VAR_NODE_COUNT).getInt(), 21 | solution.getLiteral(GraphQueryProvider.VAR_EDGE_COUNT).getInt()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/sparql/extractors/rgml/NodesExtractor.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.sparql.extractors.rgml; 2 | 3 | import com.linkedpipes.lpa.backend.entities.rgml.Node; 4 | import com.linkedpipes.lpa.backend.rdf.LocalizedValue; 5 | import com.linkedpipes.lpa.backend.rdf.vocabulary.RGML; 6 | import org.apache.jena.query.QueryExecution; 7 | import org.apache.jena.rdf.model.Model; 8 | import org.apache.jena.rdf.model.Resource; 9 | import org.apache.jena.vocabulary.RDF; 10 | import org.apache.jena.vocabulary.RDFS; 11 | 12 | import java.util.List; 13 | import java.util.stream.Collectors; 14 | 15 | public class NodesExtractor { 16 | 17 | public static List extract(QueryExecution queryExec){ 18 | Model model = queryExec.execConstruct(); 19 | 20 | List nodes = model.listResourcesWithProperty(RDF.type, RGML.Node).toList(); 21 | 22 | return nodes.stream().map(n -> 23 | new Node(n.getURI(), new LocalizedValue(n, RDFS.label))) 24 | .collect(Collectors.toList()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/sparql/queries/DefaultDataSourceExtractorQueryProvider.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.sparql.queries; 2 | 3 | import org.apache.jena.arq.querybuilder.ConstructBuilder; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | public class DefaultDataSourceExtractorQueryProvider extends ConstructSparqlQueryProvider { 7 | 8 | public static final String VAR_S = var("s"); 9 | public static final String VAR_P = var("p"); 10 | public static final String VAR_O = var("o"); 11 | 12 | @NotNull 13 | @Override 14 | protected ConstructBuilder addConstructs(@NotNull ConstructBuilder builder) { 15 | return builder.addConstruct(VAR_S, VAR_P, VAR_O); 16 | } 17 | 18 | @NotNull 19 | @Override 20 | protected ConstructBuilder addWheres(@NotNull ConstructBuilder builder) { 21 | return builder.addWhere(VAR_S, VAR_P, VAR_O); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/sparql/queries/ExtractGraphQueryProvider.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.sparql.queries; 2 | 3 | import com.linkedpipes.lpa.backend.sparql.queries.ConstructSparqlQueryProvider; 4 | import org.apache.jena.arq.querybuilder.ConstructBuilder; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | public class ExtractGraphQueryProvider extends ConstructSparqlQueryProvider { 8 | 9 | // VARIABLES 10 | private static final String VAR_S = var("s"); 11 | private static final String VAR_P = var("p"); 12 | private static final String VAR_O = var("o"); 13 | 14 | @NotNull 15 | @Override 16 | protected ConstructBuilder addPrefixes(@NotNull ConstructBuilder builder) { 17 | return builder; 18 | } 19 | 20 | @NotNull 21 | @Override 22 | protected ConstructBuilder addConstructs(@NotNull ConstructBuilder builder) { 23 | return builder.addConstruct(VAR_S, VAR_P, VAR_O); 24 | } 25 | 26 | @NotNull 27 | @Override 28 | protected ConstructBuilder addWheres(@NotNull ConstructBuilder builder) { 29 | return builder.addWhere(VAR_S, VAR_P, VAR_O); 30 | } 31 | 32 | @NotNull 33 | @Override 34 | protected ConstructBuilder addOptionals(@NotNull ConstructBuilder builder) { 35 | return builder; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/sparql/queries/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Query providers are used to generate parametrized SPARQL queries which are then used to gather data from endpoints. 3 | */ 4 | package com.linkedpipes.lpa.backend.sparql.queries; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/DefaultHttpURLConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | 3 | import org.springframework.context.annotation.Profile; 4 | import org.springframework.stereotype.Service; 5 | 6 | import java.io.IOException; 7 | import java.net.HttpURLConnection; 8 | import java.net.URL; 9 | 10 | @Service 11 | @Profile("!test") 12 | public class DefaultHttpURLConnectionFactory implements HttpURLConnectionFactory { 13 | 14 | @Override 15 | public HttpURLConnection getConnectionForUrl(String urlString) throws IOException { 16 | return (HttpURLConnection) new URL(urlString).openConnection(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/GitHubUtils.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | 3 | import com.linkedpipes.lpa.backend.constants.ApplicationPropertyKeys; 4 | import org.eclipse.egit.github.core.Gist; 5 | import org.eclipse.egit.github.core.GistFile; 6 | import org.eclipse.egit.github.core.client.GitHubClient; 7 | import org.eclipse.egit.github.core.service.GistService; 8 | 9 | import java.io.IOException; 10 | import java.util.Collections; 11 | 12 | import static com.linkedpipes.lpa.backend.Application.getConfig; 13 | 14 | public final class GitHubUtils { 15 | 16 | public static String uploadGistFile(String fileName, String fileContent) throws IOException { 17 | GitHubClient client = new GitHubClient().setCredentials(getConfig().getString(ApplicationPropertyKeys.GITHUB_USER), getConfig().getString(ApplicationPropertyKeys.GITHUB_PASSWORD)); 18 | Gist gist = new Gist().setDescription("RDF file in Turtle format, uploaded by user for use in discovery."); 19 | gist.setFiles(Collections.singletonMap(fileName, new GistFile().setContent(fileContent))); 20 | gist = new GistService(client).createGist(gist); 21 | return gist.getFiles().get(fileName).getRawUrl(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/HashableTuple.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | 3 | import org.jetbrains.annotations.NotNull; 4 | import org.jetbrains.annotations.Nullable; 5 | 6 | import java.util.Arrays; 7 | 8 | public class HashableTuple { 9 | 10 | private final Object[] items; 11 | 12 | public HashableTuple(@NotNull Object... args) { 13 | this.items = args; 14 | } 15 | 16 | @Override 17 | public boolean equals(@Nullable Object o) { 18 | if (this == o) return true; 19 | if (o == null || getClass() != o.getClass()) return false; 20 | HashableTuple tuple = (HashableTuple) o; 21 | return Arrays.equals(items, tuple.items); 22 | } 23 | 24 | @Override 25 | public int hashCode() { 26 | return Arrays.hashCode(items); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/HttpFileUploader.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | 3 | import org.apache.http.entity.mime.MultipartEntityBuilder; 4 | import org.apache.http.entity.ContentType; 5 | import com.linkedpipes.lpa.backend.exceptions.LpAppsException; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.util.StreamUtils; 8 | import java.io.IOException; 9 | import com.linkedpipes.lpa.backend.Application; 10 | import org.apache.http.HttpEntity; 11 | import org.apache.http.client.methods.CloseableHttpResponse; 12 | import org.apache.http.client.methods.HttpPost; 13 | import org.apache.http.impl.client.CloseableHttpClient; 14 | import org.apache.http.impl.client.HttpClients; 15 | 16 | 17 | public class HttpFileUploader { 18 | 19 | public String uploadTTL(String endpointUrl, String data, String field, String type) throws LpAppsException { 20 | try { 21 | CloseableHttpClient httpClient = HttpClients.createDefault(); 22 | HttpPost uploadFile = new HttpPost(endpointUrl); 23 | MultipartEntityBuilder builder = MultipartEntityBuilder.create(); 24 | builder.addBinaryBody(field, data.getBytes(), ContentType.create(type), "input.ttl"); 25 | HttpEntity multipart = builder.build(); 26 | uploadFile.setEntity(multipart); 27 | CloseableHttpResponse response = httpClient.execute(uploadFile); 28 | HttpEntity responseEntity = response.getEntity(); 29 | return StreamUtils.copyToString(responseEntity.getContent(), Application.DEFAULT_CHARSET); 30 | } catch(IOException e) { 31 | throw new LpAppsException(HttpStatus.INTERNAL_SERVER_ERROR, "Error communicating with external service", e); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/HttpURLConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | 3 | import java.io.IOException; 4 | import java.net.HttpURLConnection; 5 | 6 | /** 7 | * A factory for {@link HttpURLConnection} objects and their fake subclasses to make testing easier. 8 | */ 9 | public interface HttpURLConnectionFactory { 10 | 11 | /** 12 | * Create an {@link HttpURLConnection} object which tries to connect to a given URL. 13 | * 14 | * @param urlString the URL string to connect to 15 | * @return a connection pointing to {@code urlString} 16 | * @throws IOException if the URL string is malformed or creating a connection object fails 17 | */ 18 | HttpURLConnection getConnectionForUrl(String urlString) throws IOException; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/IExecutionCallback.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | import com.linkedpipes.lpa.backend.entities.EtlStatusReport; 3 | 4 | public interface IExecutionCallback { 5 | void execute(EtlStatusReport report); 6 | } 7 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/RdfUtils.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | 3 | import com.linkedpipes.lpa.backend.util.rdfbuilder.ModelBuilder; 4 | import org.apache.jena.riot.Lang; 5 | import org.apache.jena.riot.RDFLanguages; 6 | 7 | public final class RdfUtils { 8 | 9 | public static String RdfDataToTurtleFormat(String rdfData, Lang rdfLanguage){ 10 | if (rdfLanguage != RDFLanguages.TTL) { 11 | //read rdf data into model to transform it to ttl 12 | ModelBuilder mb = ModelBuilder.fromString(rdfData, rdfLanguage); 13 | return mb.toString(); 14 | } 15 | 16 | return rdfData; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/Streams.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | 3 | import java.util.Iterator; 4 | import java.util.stream.Stream; 5 | import java.util.stream.StreamSupport; 6 | 7 | public final class Streams { 8 | 9 | private Streams() { 10 | } 11 | 12 | public static Stream sequentialFromIterable(Iterable iterable) { 13 | return StreamSupport.stream(iterable.spliterator(), false); 14 | } 15 | 16 | public static Stream sequentialFromIterator(Iterator iterator) { 17 | return sequentialFromIterable(() -> iterator); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/ThrowingFunction.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | 3 | @FunctionalInterface 4 | public interface ThrowingFunction { 5 | 6 | R apply(T t) throws X; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/ThrowingSupplier.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | 3 | /** 4 | * A functional interface for wrapping code which produces objects and may throw. 5 | * 6 | * @param type of the objects being supplied 7 | * @param type of the throwable that may be thrown by the function 8 | */ 9 | @FunctionalInterface 10 | public interface ThrowingSupplier { 11 | 12 | R get() throws X; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/TriFunction.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | 3 | @FunctionalInterface 4 | public interface TriFunction { 5 | 6 | R apply(T1 arg1, T2 arg2, T3 arg3); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * General utility classes. 3 | */ 4 | package com.linkedpipes.lpa.backend.util; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/java/com/linkedpipes/lpa/backend/util/rdfbuilder/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Classes used for building RDF models. 3 | */ 4 | package com.linkedpipes.lpa.backend.util.rdfbuilder; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/resources/com/linkedpipes/lpa/backend/services/virtuoso_sd.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix ns1: . 3 | @prefix sd: . 4 | ns1:service rdf:type sd:Service ; 5 | sd:endpoint ns1: ; 6 | sd:feature sd:DereferencesURIs , 7 | sd:UnionDefaultGraph , 8 | sd:BasicFederatedQuery . 9 | @prefix ns3: . 10 | ns1:service sd:resultFormat ns3:SPARQL_Results_XML , 11 | ns3:Turtle , 12 | ns3:SPARQL_Results_CSV , 13 | ns3:SPARQL_Results_JSON , 14 | ns3:N3 , 15 | ns3:RDF_XML , 16 | ns3:N-Triples , 17 | ns3:RDFa ; 18 | sd:supportedLanguage sd:SPARQL11Query . 19 | -------------------------------------------------------------------------------- /src/backend/src/main/resources/db/migration/R__Vacuum.sql: -------------------------------------------------------------------------------- 1 | COMMIT;VACUUM;COMMIT; 2 | -------------------------------------------------------------------------------- /src/backend/src/main/resources/db/migration/V1.0__Create_schema.sql: -------------------------------------------------------------------------------- 1 | create sequence hibernate_sequence start 1 increment 1; 2 | create table application (id int8 not null, solid_iri TEXT not null, user_id int8, primary key (id)); 3 | create table discovery (id int8 not null, discovery_id TEXT not null, executing boolean not null, started timestamp not null, user_id int8, primary key (id)); 4 | create table execution (id int8 not null, execution_iri TEXT not null, selected_visualiser varchar(255) not null, status varchar(255), user_id int8, primary key (id)); 5 | create table lpa_user (id int8 not null, web_id TEXT not null, primary key (id)); 6 | alter table if exists application add constraint FK99oev92k62cbng2q8vc8pls4o foreign key (user_id) references lpa_user; 7 | alter table if exists discovery add constraint FKtop5vf25njt7utg0jc1744dnx foreign key (user_id) references lpa_user; 8 | alter table if exists execution add constraint FKoh7dx8hd2t7gyruje5yb1k9xm foreign key (user_id) references lpa_user; 9 | -------------------------------------------------------------------------------- /src/backend/src/main/resources/db/migration/V1.1__Extended_user_profile_and_storing_discovery_and_ETL_parameters.sql: -------------------------------------------------------------------------------- 1 | alter table if exists lpa_user drop constraint if exists lpa_user_pkey cascade, drop column if exists id, add primary key (web_id); 2 | alter table if exists discovery drop column if exists user_id, add column if not exists user_web_id TEXT, add column if not exists data_sample_iri TEXT, add column if not exists finished timestamp, add column if not exists named_graph TEXT, add column if not exists sparql_endpoint_iri TEXT, add constraint FKtop5vf25njt7utg0jc1744dnx foreign key (user_web_id) references lpa_user;; 3 | create table if not exists pipeline_information ( id int8 not null, etl_pipeline_iri TEXT not null, pipeline_id TEXT not null, result_graph_iri TEXT not null, primary key (id)); 4 | alter table if exists execution drop column if exists user_id, add column if not exists user_web_id TEXT, add column if not exists finished timestamp, add column if not exists started timestamp not null, add column if not exists pipeline_id int8 not null, add constraint FKoh7dx8hd2t7gyruje5yb1k9xm foreign key (user_web_id) references lpa_user, add constraint FKg5upxfry1wjgn3sxu9nmn7jd6 foreign key (pipeline_id) references pipeline_information; 5 | alter table if exists application drop column if exists user_id, add column if not exists user_web_id TEXT, add constraint FK99oev92k62cbng2q8vc8pls4o foreign key (user_web_id) references lpa_user; 6 | -------------------------------------------------------------------------------- /src/backend/src/main/resources/db/migration/V1.2__Multiple_named_graphs.sql: -------------------------------------------------------------------------------- 1 | create table if not exists discovery_named_graph ( id SERIAL, discovery_id int8, named_graph TEXT, primary key (id)); 2 | alter table if exists discovery_named_graph add constraint FKy765fuyjbstexc foreign key (discovery_id) references discovery; 3 | 4 | insert into discovery_named_graph (discovery_id, named_graph) 5 | select id as discovery_id, named_graph from discovery; 6 | 7 | alter table if exists discovery drop column if exists named_graph; 8 | -------------------------------------------------------------------------------- /src/backend/src/main/resources/db/migration/V1.3__Color_schemes_on_user,_drop_applications,_named_graphs_on_delete_cascade.sql: -------------------------------------------------------------------------------- 1 | drop table if exists application; 2 | alter table if exists lpa_user add column if not exists color VARCHAR(255); 3 | update lpa_user set color = 'BLACK'; 4 | alter table if exists discovery_named_graph drop constraint FKy765fuyjbstexc, add constraint FKy765fuyjbstexc foreign key (discovery_id) references discovery on delete cascade; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/resources/db/migration/V1.4__Applications.sql: -------------------------------------------------------------------------------- 1 | create table if not exists application (id int8 not null, execution_id int8, user_id TEXT not null, solid_iri TEXT not null, primary key (id)); 2 | alter table if exists application add constraint FK_app_exec foreign key (execution_id) references execution, add constraint FK_app_user foreign key (user_id) references lpa_user; 3 | alter table if exists execution add column removed boolean not null default FALSE; 4 | update execution set removed = FALSE; 5 | -------------------------------------------------------------------------------- /src/backend/src/main/resources/db/migration/V1.5__Repeated_executions.sql: -------------------------------------------------------------------------------- 1 | alter table if exists execution 2 | add column repeat boolean not null default false, 3 | add column native boolean not null default true, 4 | add column frequency_hours int8 not null default -1; 5 | 6 | update execution set repeat = false, native = true, frequency_hours = -1; 7 | -------------------------------------------------------------------------------- /src/backend/src/main/resources/sentry.properties: -------------------------------------------------------------------------------- 1 | dsn=https://9c4cf79dd37b432f9b785950b9ff2553@sentry.io/1414947 2 | -------------------------------------------------------------------------------- /src/backend/src/test/java/com/linkedpipes/lpa/backend/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.junit.jupiter.api.extension.ExtendWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.ActiveProfiles; 7 | import org.springframework.test.context.junit.jupiter.SpringExtension; 8 | 9 | @ExtendWith(SpringExtension.class) 10 | @SpringBootTest 11 | @ActiveProfiles("test") 12 | class ApplicationTests { 13 | 14 | @Test 15 | void contextLoads() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/backend/src/test/java/com/linkedpipes/lpa/backend/services/DiscoveryServiceComponentTests.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | class DiscoveryServiceComponentTests { 6 | 7 | @Test 8 | void foo() { 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/test/java/com/linkedpipes/lpa/backend/services/EtlServiceComponentTests.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | class EtlServiceComponentTests { 6 | 7 | @Test 8 | void foo() { 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/test/java/com/linkedpipes/lpa/backend/services/TtlGeneratorTests.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.services; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | class TtlGeneratorTests { 6 | 7 | @Test 8 | void foo() { 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/backend/src/test/java/com/linkedpipes/lpa/backend/testutil/TestError.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.testutil; 2 | 3 | public class TestError extends Error { 4 | 5 | public TestError(Throwable cause) { 6 | super(cause); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/backend/src/test/java/com/linkedpipes/lpa/backend/testutil/ThrowingExecutable.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.testutil; 2 | 3 | /** 4 | * Represents an executable that may throw any {@link Throwable}. Used in tests to wrap code which is expected to throw 5 | * exceptions. 6 | * 7 | * @param the type of the throwable this executable throws 8 | */ 9 | @FunctionalInterface 10 | public interface ThrowingExecutable { 11 | 12 | void execute() throws T; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/backend/src/test/java/com/linkedpipes/lpa/backend/util/UrlUtilsTests.java: -------------------------------------------------------------------------------- 1 | package com.linkedpipes.lpa.backend.util; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.assertEquals; 6 | import static org.junit.jupiter.api.Assertions.assertThrows; 7 | 8 | class UrlUtilsTests { 9 | 10 | @Test 11 | void testUrlFromNothing() { 12 | assertEquals("", UrlUtils.urlFrom()); 13 | } 14 | 15 | @Test 16 | void testUrlFromStringNull() { 17 | assertEquals("", UrlUtils.urlFrom((String) null)); 18 | } 19 | 20 | @Test 21 | void testUrlFromArrayNull() { 22 | assertThrows(NullPointerException.class, () -> UrlUtils.urlFrom((String[]) null)); 23 | } 24 | 25 | @Test 26 | void testUrlFromStrings() { 27 | String expectedString = "Hello/from/the/other/side"; 28 | 29 | assertEquals(expectedString, UrlUtils.urlFrom("Hello", "from", "the", "other", "side")); 30 | } 31 | 32 | @Test 33 | void testUrlFromIgnoreEmptyStrings() { 34 | String expectedString = "http://www.example.com/example/subexample"; 35 | 36 | assertEquals(expectedString, UrlUtils.urlFrom("http://www.example.com", "", "example", "", "", "subexample", "")); 37 | } 38 | 39 | @Test 40 | void testUrlFromIgnoreSlashes() { 41 | String expectedString = "http://www.example.com/example/subexample"; 42 | 43 | assertEquals(expectedString, UrlUtils.urlFrom("http://www.example.com", "//", "example", "//////////", "//", "subexample", "/")); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/deploy/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | cd /home/project 3 | 4 | echo "Pulling from Master" 5 | if cd repo; then git pull origin master; else git clone https://github.com/linkedpipes/applications.git repo && cd repo; fi 6 | echo "Pulled successfully from master" 7 | 8 | echo "Restarting server..." 9 | docker-compose -f docker-compose-master.yml down || true 10 | docker container prune --force || true 11 | docker network prune --force || true 12 | 13 | echo "Pulling latest images..." 14 | docker-compose -f docker-compose-master.yml pull 15 | 16 | echo "Starting containers again" 17 | docker-compose -f docker-compose-master.yml up -d --force-recreate 18 | 19 | echo "Server restarted Successfully" 20 | 21 | exit 22 | -------------------------------------------------------------------------------- /src/deploy/docker-compose-travis-deploy.yml: -------------------------------------------------------------------------------- 1 | version: "3.3" 2 | services: 3 | backend: 4 | image: linkedpipes/applications:backend 5 | container_name: lpa-backend 6 | environment: 7 | SENTRY_ENVIRONMENT: "development" 8 | build: 9 | context: ../backend/ 10 | 11 | frontend-dev: 12 | image: linkedpipes/applications:frontend 13 | container_name: lpa-frontend 14 | environment: 15 | NODE_OPTIONS: --max_old_space_size=4096 16 | build: 17 | context: ../frontend/ 18 | dockerfile: Dockerfile 19 | 20 | frontend-prod: 21 | image: linkedpipes/applications:frontend-prod 22 | container_name: lpa-frontend 23 | environment: 24 | NODE_OPTIONS: --max_old_space_size=4096 25 | build: 26 | context: ../frontend/ 27 | dockerfile: Dockerfile-prod 28 | -------------------------------------------------------------------------------- /src/deploy/lpa-server-nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | 3 | # SSL configuration 4 | listen 443 ssl; 5 | listen [::]:443 ssl; 6 | 7 | ssl_certificate /etc/letsencrypt/live/applications.linkedpipes.com/fullchain.pem; 8 | ssl_certificate_key /etc/letsencrypt/live/applications.linkedpipes.com/privkey.pem; 9 | 10 | server_name www.applications.linkedpipes.com applications.linkedpipes.com; 11 | 12 | location /webhooks { 13 | proxy_pass http://localhost:8085; 14 | proxy_pass_request_headers on; 15 | proxy_set_header X-Real-IP $remote_addr; 16 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 17 | } 18 | 19 | location / { 20 | include /etc/nginx/mime.types; 21 | proxy_pass http://localhost:9001; 22 | proxy_set_header Host $host; 23 | proxy_http_version 1.1; 24 | proxy_set_header Upgrade $http_upgrade; 25 | proxy_set_header Connection 'upgrade'; 26 | proxy_pass_request_headers on; 27 | proxy_set_header X-Real-IP $remote_addr; 28 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 29 | proxy_set_header X-Forwarded-Proto $scheme; 30 | } 31 | } -------------------------------------------------------------------------------- /src/deploy/lpa-webhook.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Webhook server listening on 8085 for LPA deployments 3 | 4 | [Service] 5 | Type=simple 6 | User=project 7 | ExecStart=/usr/bin/python3 /home/project/deploy/webserver.py 8 | Restart=on-failure 9 | 10 | [Install] 11 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /src/deploy/webserver.py: -------------------------------------------------------------------------------- 1 | from threading import Thread 2 | import subprocess 3 | from slackclient import SlackClient 4 | from flask import Flask 5 | from flask import request 6 | from flask import jsonify 7 | 8 | app = Flask(__name__) 9 | 10 | 11 | slack_token = "" 12 | sc = SlackClient(slack_token) 13 | 14 | def deploy(x): 15 | print("running deployment...") 16 | subprocess.call(["/bin/bash", "home/project/deploy/deploy.sh"]) 17 | sc.api_call("chat.postMessage", channel="", text="The deployent has been completed!") 18 | 19 | 20 | @app.route('/webhooks/lpa', methods=["POST"]) 21 | def listen_webhook(): 22 | data = request.get_json() 23 | branch = data["pull_request"]["base"]["ref"] 24 | action = data["action"] 25 | merged = data["pull_request"]["merged"] 26 | if branch and "master" in branch and action == "closed" and merged: 27 | #Spawn thread to process the data 28 | sc.api_call("chat.postMessage", channel="", text="A deployment to https://applications.linkedpipes.com has started...") 29 | t = Thread(target=deploy, args=(data,)) 30 | t.start() 31 | return jsonify({"message": "deployment will be made"}), 200 32 | return jsonify({"message": "No deployment made."}), 200 33 | 34 | if __name__ == '__main__': 35 | app.run(host='0.0.0.0', port=8085) 36 | -------------------------------------------------------------------------------- /src/frontend/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react", "@babel/flow"], 3 | "plugins": [ 4 | "@babel/plugin-proposal-class-properties", 5 | "@babel/plugin-proposal-object-rest-spread", 6 | "@babel/plugin-syntax-dynamic-import", 7 | "babel-plugin-smart-webpack-import", 8 | "@babel/plugin-transform-runtime", 9 | [ 10 | "module-resolver", 11 | { 12 | "root": ["./src"], 13 | "alias": { 14 | "@components": "./src/components", 15 | "@containers": "./src/containers", 16 | "@ducks": "./src/ducks", 17 | "@utils": "./src/utils", 18 | "@constants": "./src/constants", 19 | "@layouts": "./src/layouts", 20 | "@storage": "./src/storage", 21 | "@assets": "./assets" 22 | } 23 | } 24 | ] 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/frontend/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | Dockerfile 3 | .gitignore 4 | .dockerignore 5 | README -------------------------------------------------------------------------------- /src/frontend/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | 3 | [include] 4 | 5 | [libs] 6 | 7 | [lints] 8 | 9 | [options] 10 | module.name_mapper='@components' ->'/src/components' 11 | module.name_mapper='@containers' ->'/src/containers' 12 | module.name_mapper='@ducks' ->'/src/ducks' 13 | module.name_mapper='@utils' ->'/src/utils' 14 | module.name_mapper='@storage' ->'/src/storage' 15 | module.name_mapper='@constants' ->'/src/constants' 16 | module.name_mapper='@layouts' ->'/src/layouts' 17 | module.name_mapper='@assets' ->'/assets' 18 | 19 | 20 | [strict] 21 | -------------------------------------------------------------------------------- /src/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_STORE 2 | node_modules 3 | scripts/flow/*/.flowconfig 4 | *~ 5 | *.pyc 6 | .grunt 7 | _SpecRunner.html 8 | __benchmarks__ 9 | build/ 10 | remote-repo/ 11 | coverage/ 12 | flow-coverage/ 13 | .module-cache 14 | fixtures/dom/public/react-dom.js 15 | fixtures/dom/public/react.js 16 | test/the-files-to-test.generated.js 17 | *.log* 18 | chrome-user-data 19 | *.sublime-project 20 | *.sublime-workspace 21 | .idea 22 | *.iml 23 | .vscode 24 | *.swp 25 | *.swo 26 | public/dist/* 27 | *.docz 28 | 29 | -------------------------------------------------------------------------------- /src/frontend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /src/frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | # Base image 2 | FROM node:10.18.0-alpine 3 | 4 | ENV YARN_VERSION 1.17.0 5 | # Install packages using Yarn 6 | # References: 7 | # http://bitjudo.com/blog/2014/03/13/building-efficient-dockerfiles-node-dot-js/ 8 | # https://hackernoon.com/using-yarn-with-docker-c116ad289d56 9 | 10 | # Add package.json and respective lock 11 | COPY package.json yarn.* /tmp/ 12 | 13 | # Install git 14 | RUN apk update && apk upgrade && \ 15 | apk add --no-cache bash git openssh 16 | 17 | RUN apk add --no-cache --virtual .build-deps-yarn curl \ 18 | && curl -fSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ 19 | && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ 20 | && ln -snf /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ 21 | && ln -snf /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ 22 | && rm yarn-v$YARN_VERSION.tar.gz \ 23 | && apk del .build-deps-yarn 24 | 25 | # Install packages 26 | WORKDIR /tmp 27 | RUN until yarn install --frozen-lockfile ; do echo "Retrying yarn install..."; done 28 | 29 | # Create a symlink to node_modules 30 | RUN mkdir -p /app 31 | WORKDIR /app 32 | RUN ln -s /tmp/node_modules 33 | 34 | COPY . /app 35 | 36 | EXPOSE 9001 37 | 38 | CMD ["yarn", "startDockerDev"] 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/frontend/Dockerfile-prod: -------------------------------------------------------------------------------- 1 | # build environment 2 | FROM node:10.16.3-alpine as builder 3 | 4 | ENV YARN_VERSION 1.17.0 5 | # Install packages using Yarn 6 | # References: 7 | # http://bitjudo.com/blog/2014/03/13/building-efficient-dockerfiles-node-dot-js/ 8 | # https://hackernoon.com/using-yarn-with-docker-c116ad289d56 9 | 10 | # Add package.json and respective lock 11 | ADD package.json yarn.* /tmp/ 12 | 13 | # Install git 14 | RUN apk update && apk upgrade && \ 15 | apk add --no-cache bash git openssh 16 | 17 | RUN apk add --no-cache --virtual .build-deps-yarn curl \ 18 | && curl -fSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \ 19 | && tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \ 20 | && ln -snf /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \ 21 | && ln -snf /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \ 22 | && rm yarn-v$YARN_VERSION.tar.gz \ 23 | && apk del .build-deps-yarn 24 | 25 | # Install packages 26 | RUN cd /tmp && until yarn install --frozen-lockfile ; do echo "Retrying yarn install..."; done 27 | 28 | # Create a symlink to node_modules 29 | RUN mkdir -p /usr/src/app && cd /usr/src/app && ln -s /tmp/node_modules 30 | 31 | WORKDIR /usr/src/app 32 | ENV PATH /usr/src/app/node_modules/.bin:$PATH 33 | 34 | COPY . /usr/src/app 35 | RUN yarn build 36 | 37 | 38 | # Production environment image 39 | FROM nginx:alpine 40 | COPY --from=builder /usr/src/app/public /usr/share/nginx/html 41 | COPY nginx.conf /etc/nginx/conf.d/default.conf 42 | EXPOSE 80 43 | CMD ["nginx", "-g", "daemon off;"] 44 | -------------------------------------------------------------------------------- /src/frontend/doczrc.js: -------------------------------------------------------------------------------- 1 | import { css } from 'docz-plugin-css'; 2 | 3 | export default { 4 | title: 'LinkedPipes Applications', 5 | description: 'LinkedPipes Applications frontend documentation', 6 | repository: 'https://github.com/linkedpipes/applications', 7 | ordering: 'ascending', 8 | wrapper: 'src/wrapper', 9 | menu: ['Getting Started', 'Containers', 'Components'], 10 | themeConfig: { 11 | mode: 'dark', 12 | colors: { 13 | primary: '#fba333', 14 | secondary: '#00695c', 15 | gray: 'lightslategray' 16 | }, 17 | logo: { 18 | src: 'https://i.ibb.co/0hfBm6J/lpapps-documentation-logo.png', 19 | width: 220 20 | }, 21 | repository: 'https://github.com/linkedpipes/applications' 22 | }, 23 | dest: 'docs', 24 | hashRouter: true, 25 | plugins: [css()] 26 | }; 27 | -------------------------------------------------------------------------------- /src/frontend/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./", 4 | "paths": { 5 | "@components/*": ["./src/components/*"], 6 | "@containers/*": ["./src/containers/*"], 7 | "@ducks/*": ["./src/ducks/*"], 8 | "@utils/*": ["./src/utils/*"], 9 | "@storage/*": ["./src/storage/*"], 10 | "@constants/*": ["./src/constants/*"], 11 | "@layouts/*": ["./src/layouts/*"], 12 | "@assets/*": ["./assets/*"] 13 | } 14 | }, 15 | "exclude": ["node_modules", "dist"] 16 | } 17 | -------------------------------------------------------------------------------- /src/frontend/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | client_max_body_size 0; 4 | location / { 5 | root /usr/share/nginx/html; 6 | index index.html index.htm; 7 | try_files $uri $uri/ /index.html; 8 | } 9 | } -------------------------------------------------------------------------------- /src/frontend/src/components/Header/AboutHeader/AboutHeaderComponent.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import AppBar from '@material-ui/core/AppBar'; 4 | import Grid from '@material-ui/core/Grid'; 5 | import Toolbar from '@material-ui/core/Toolbar'; 6 | import Typography from '@material-ui/core/Typography'; 7 | import { withStyles } from '@material-ui/core/styles'; 8 | 9 | const lightColor = 'rgba(255, 255, 255, 0.7)'; 10 | 11 | type Props = { 12 | classes: Object, 13 | sectionLabel: string 14 | }; 15 | 16 | const styles = theme => ({ 17 | secondaryBar: { 18 | zIndex: 0 19 | }, 20 | menuButton: { 21 | marginLeft: -theme.spacing(1) 22 | }, 23 | iconButtonAvatar: { 24 | padding: 4 25 | }, 26 | link: { 27 | textDecoration: 'none', 28 | color: lightColor, 29 | '&:hover': { 30 | color: theme.palette.common.white 31 | } 32 | }, 33 | button: { 34 | borderColor: lightColor 35 | } 36 | }); 37 | 38 | function AboutHeader(props: Props) { 39 | const { classes, sectionLabel } = props; 40 | 41 | return ( 42 | 43 | 50 | 51 | 52 | 53 | 54 | {sectionLabel} 55 | 56 | 57 | 58 | 59 | 60 | 61 | ); 62 | } 63 | 64 | export const AboutHeaderComponent = withStyles(styles)(AboutHeader); 65 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/AboutHeader/AboutHeaderContainer.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { PureComponent } from 'react'; 3 | import { AboutHeaderComponent } from './AboutHeaderComponent'; 4 | 5 | type Props = {}; 6 | 7 | const sectionLabel = 'FAQ'; 8 | 9 | class AboutHeaderContainer extends PureComponent { 10 | render() { 11 | return ; 12 | } 13 | } 14 | 15 | export const AboutHeader = AboutHeaderContainer; 16 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/AboutHeader/index.js: -------------------------------------------------------------------------------- 1 | import { AboutHeader } from './AboutHeaderContainer'; 2 | 3 | export { AboutHeader }; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/ApplicationHeader/ApplicationHeaderContainer.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { PureComponent } from 'react'; 3 | import { connect } from 'react-redux'; 4 | import { ApplicationHeaderComponent } from './ApplicationHeaderComponent'; 5 | import { globalActions } from '@ducks/globalDuck'; 6 | 7 | type Props = { 8 | handleSetApplicationSetupTabIndex: Function, 9 | applicationSetupTabIndex: Number 10 | }; 11 | 12 | const tabTitle = []; 13 | 14 | class ApplicationHeaderContainer extends PureComponent { 15 | handleTabChange = (event, tabIndex) => { 16 | this.props.handleSetApplicationSetupTabIndex(tabIndex); 17 | }; 18 | 19 | render() { 20 | const { applicationSetupTabIndex } = this.props; 21 | const { handleTabChange } = this; 22 | 23 | return ( 24 | 29 | ); 30 | } 31 | } 32 | 33 | const mapStateToProps = state => { 34 | return { 35 | applicationSetupTabIndex: state.globals.applicationSetupTabIndex 36 | }; 37 | }; 38 | 39 | const mapDispatchToProps = dispatch => { 40 | const handleSetApplicationSetupTabIndex = index => 41 | dispatch(globalActions.setSelectedApplicationSetupTabIndex(index)); 42 | 43 | return { 44 | handleSetApplicationSetupTabIndex 45 | }; 46 | }; 47 | 48 | export const ApplicationHeader = connect( 49 | mapStateToProps, 50 | mapDispatchToProps 51 | )(ApplicationHeaderContainer); 52 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/ApplicationHeader/index.js: -------------------------------------------------------------------------------- 1 | import { ApplicationHeader } from './ApplicationHeaderContainer'; 2 | 3 | export { ApplicationHeader }; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/ApplicationsBrowserHeader/ApplicationsBrowserHeaderContainer.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { PureComponent } from 'react'; 3 | import { connect } from 'react-redux'; 4 | import { ApplicationsBrowserHeaderComponent } from './ApplicationsBrowserHeaderComponent'; 5 | import { globalActions } from '@ducks/globalDuck'; 6 | 7 | type Props = { 8 | handleSetApplicationsBrowserTabIndex: Function, 9 | applicationsBrowserTabIndex: Number 10 | }; 11 | 12 | const tabTitle = [ 13 | { titleLabel: 'My Applications' }, 14 | { titleLabel: 'Shared Applications' } 15 | ]; 16 | 17 | class ApplicationsBrowserContainer extends PureComponent { 18 | handleTabChange = (event, tabIndex) => { 19 | this.props.handleSetApplicationsBrowserTabIndex(tabIndex); 20 | }; 21 | 22 | render() { 23 | const { applicationsBrowserTabIndex } = this.props; 24 | const { handleTabChange } = this; 25 | 26 | return ( 27 | 32 | ); 33 | } 34 | } 35 | 36 | const mapStateToProps = state => { 37 | return { 38 | applicationsBrowserTabIndex: state.globals.applicationsBrowserTabIndex 39 | }; 40 | }; 41 | 42 | const mapDispatchToProps = dispatch => { 43 | const handleSetApplicationsBrowserTabIndex = index => 44 | dispatch(globalActions.setSelectedApplicationsBrowserTabIndex(index)); 45 | 46 | return { 47 | handleSetApplicationsBrowserTabIndex 48 | }; 49 | }; 50 | 51 | export const ApplicationsBrowserHeader = connect( 52 | mapStateToProps, 53 | mapDispatchToProps 54 | )(ApplicationsBrowserContainer); 55 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/ApplicationsBrowserHeader/index.js: -------------------------------------------------------------------------------- 1 | import { ApplicationsBrowserHeader } from './ApplicationsBrowserHeaderContainer'; 2 | 3 | export { ApplicationsBrowserHeader }; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/DashboardHeader/DashboardHeaderContainer.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { PureComponent } from 'react'; 3 | import { connect } from 'react-redux'; 4 | import { DashboardHeaderComponent } from './DashboardHeaderComponent'; 5 | import { globalActions } from '@ducks/globalDuck'; 6 | 7 | type Props = { 8 | handleSetDashboardTabIndex: Function, 9 | dashboardTabIndex: Number 10 | }; 11 | 12 | const tabTitle = [ 13 | { titleLabel: 'Quick Start', id: 'quickstart_tab' }, 14 | { titleLabel: 'Discoveries', id: 'discoveries_tab' }, 15 | { titleLabel: 'Pipeline Executions', id: 'pipeline_executions_tab' } 16 | ]; 17 | 18 | class DashboardHeaderContainer extends PureComponent { 19 | handleTabChange = (event, tabIndex) => { 20 | this.props.handleSetDashboardTabIndex(tabIndex); 21 | }; 22 | 23 | render() { 24 | const { dashboardTabIndex } = this.props; 25 | const { handleTabChange } = this; 26 | 27 | return ( 28 | 33 | ); 34 | } 35 | } 36 | 37 | const mapStateToProps = state => { 38 | return { 39 | dashboardTabIndex: state.globals.dashboardTabIndex 40 | }; 41 | }; 42 | 43 | const mapDispatchToProps = dispatch => { 44 | const handleSetDashboardTabIndex = index => 45 | dispatch(globalActions.setSelectedDashboardTabIndex(index)); 46 | 47 | return { 48 | handleSetDashboardTabIndex 49 | }; 50 | }; 51 | 52 | export const DashboardHeader = connect( 53 | mapStateToProps, 54 | mapDispatchToProps 55 | )(DashboardHeaderContainer); 56 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/DashboardHeader/index.js: -------------------------------------------------------------------------------- 1 | import { DashboardHeader } from './DashboardHeaderContainer'; 2 | 3 | export { DashboardHeader }; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/DiscoverHeader/DiscoverHeaderContainer.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { PureComponent } from 'react'; 3 | import { connect } from 'react-redux'; 4 | import { DiscoverHeaderComponent } from './DiscoverHeaderComponent'; 5 | import { globalActions } from '@ducks/globalDuck'; 6 | 7 | type Props = { 8 | handleSetDiscoverTabIndex: Function, 9 | discoverTabIndex: Number 10 | }; 11 | 12 | const tabTitle = []; 13 | 14 | class DiscoverHeaderContainer extends PureComponent { 15 | handleTabChange = (event, tabIndex) => { 16 | this.props.handleSetDiscoverTabIndex(tabIndex); 17 | }; 18 | 19 | render() { 20 | const { discoverTabIndex } = this.props; 21 | const { handleTabChange } = this; 22 | 23 | return ( 24 | 29 | ); 30 | } 31 | } 32 | 33 | const mapStateToProps = state => { 34 | return { 35 | discoverTabIndex: state.globals.discoverTabIndex 36 | }; 37 | }; 38 | 39 | const mapDispatchToProps = dispatch => { 40 | const handleSetDiscoverTabIndex = index => 41 | dispatch(globalActions.setSelectedDiscverTabIndex(index)); 42 | 43 | return { 44 | handleSetDiscoverTabIndex 45 | }; 46 | }; 47 | 48 | export const DiscoverHeader = connect( 49 | mapStateToProps, 50 | mapDispatchToProps 51 | )(DiscoverHeaderContainer); 52 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/DiscoverHeader/index.js: -------------------------------------------------------------------------------- 1 | import { DiscoverHeader } from './DiscoverHeaderContainer'; 2 | 3 | export { DiscoverHeader }; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/Header.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Header 3 | menu: Components 4 | --- 5 | 6 | import { Playground, Props } from 'docz'; 7 | import { Header } from './HeaderContainer'; 8 | 9 | # Header 10 | 11 | Headers are a set of simple components based on the navigation [AppBar](https://material-ui.com/components/app-bar/) inside LinkedPipes Applications frontend. 12 | 13 | # Structure 14 | 15 | The `HeaderComponent.jsx` and `HeaderContainer.jsx` are used for an example in this documentation. The actual header components are inside the folders corresponding to appropriate webpages. 16 | 17 | ```.md 18 | ├── HeaderComponent.jsx # Stateless react component, responsible for ui 19 | ├── HeaderContainer.jsx # React PureComponent, responsible for states 20 | ├── AboutHeader/ # Folder containing a header components specific to About page 21 | ├── ApplicationHeader/ # Folder containing a header components specific to ApplicationHeader page 22 | ├── ApplicationsBrowserHeader/ # Folder containing a header components specific to ApplicationsBrowserHeader page 23 | ├── DashboardHeader/ # Folder containing a header components specific to DashboardHeader page 24 | ├── DiscoverHeader/ # Folder containing a header components specific to DiscoverHeader page 25 | ├── SettingsHeader/ # Folder containing a header components specific to SettingsHeader page 26 | └── index.js 27 | ``` 28 | 29 | ## Properties 30 | 31 | This is a reference example of a navigation component that you will see on every single webpage of the platform. The titles of the sections, and functionality of the tabs will differ. 32 | 33 | 34 | 35 | ## Example 36 | 37 | 38 |
39 | 40 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/HeaderContainer.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { PureComponent } from 'react'; 3 | import { HeaderComponent } from './HeaderComponent'; 4 | 5 | type Props = {}; 6 | 7 | class HeaderContainer extends PureComponent { 8 | render() { 9 | return ; 10 | } 11 | } 12 | 13 | export const Header = HeaderContainer; 14 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/SettingsHeader/SettingsHeaderContainer.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { PureComponent } from 'react'; 3 | import { connect } from 'react-redux'; 4 | import { SettingsHeaderComponent } from './SettingsHeaderComponent'; 5 | import { globalActions } from '@ducks/globalDuck'; 6 | 7 | type Props = { 8 | handleSetSettingsTabIndex: Function, 9 | settingsTabIndex: Number 10 | }; 11 | 12 | const tabTitle = [ 13 | { titleLabel: 'User Profile' }, 14 | { titleLabel: 'Application Storage' } 15 | ]; 16 | 17 | class SettingsHeaderContainer extends PureComponent { 18 | handleTabChange = (event, tabIndex) => { 19 | this.props.handleSetSettingsTabIndex(tabIndex); 20 | }; 21 | 22 | render() { 23 | const { settingsTabIndex } = this.props; 24 | const { handleTabChange } = this; 25 | 26 | return ( 27 | 32 | ); 33 | } 34 | } 35 | 36 | const mapStateToProps = state => { 37 | return { 38 | settingsTabIndex: state.globals.settingsTabIndex 39 | }; 40 | }; 41 | 42 | const mapDispatchToProps = dispatch => { 43 | const handleSetSettingsTabIndex = index => 44 | dispatch(globalActions.setSelectedSettingsTabIndex(index)); 45 | 46 | return { 47 | handleSetSettingsTabIndex 48 | }; 49 | }; 50 | 51 | export const SettingsHeader = connect( 52 | mapStateToProps, 53 | mapDispatchToProps 54 | )(SettingsHeaderContainer); 55 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/SettingsHeader/index.js: -------------------------------------------------------------------------------- 1 | import { SettingsHeader } from './SettingsHeaderContainer'; 2 | 3 | export { SettingsHeader }; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Header/index.js: -------------------------------------------------------------------------------- 1 | import { Header } from './HeaderContainer'; 2 | import { DashboardHeader } from './DashboardHeader'; 3 | import { DiscoverHeader } from './DiscoverHeader'; 4 | import { ApplicationHeader } from './ApplicationHeader'; 5 | import { ApplicationsBrowserHeader } from './ApplicationsBrowserHeader'; 6 | import { SettingsHeader } from './SettingsHeader'; 7 | import { AboutHeader } from './AboutHeader'; 8 | 9 | export { 10 | Header, 11 | DashboardHeader, 12 | DiscoverHeader, 13 | ApplicationHeader, 14 | ApplicationsBrowserHeader, 15 | SettingsHeader, 16 | AboutHeader 17 | }; 18 | -------------------------------------------------------------------------------- /src/frontend/src/components/HeaderControls/HeaderControls.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: HeaderControls 3 | menu: Components 4 | --- 5 | 6 | import { Playground, Props } from 'docz'; 7 | import { HeaderControlsComponent } from './HeaderControlsComponent'; 8 | 9 | # HeaderControls 10 | 11 | HeaderControls is a component used in the header of LinkedPipes Applications frontend. Contains MaterialUI Buttons with custom SVG icons, used in `HeaderControls` component. Allows control over main User related settings and inbox notifications. 12 | 13 | # Structure 14 | 15 | `HeaderControlsComponent` component exported from `HeaderControls` folder is represented by a stateless react component and a react `PureComponent` serving as a container. 16 | 17 | ```.md 18 | ├── HeaderControlsComponent.jsx # Stateless react component, responsible for ui 19 | ├── HeaderControlsContainer.jsx # React PureComponent, responsible for states 20 | └── index.js 21 | ``` 22 | 23 | ## Properties 24 | 25 | 26 | 27 | ## Example 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/frontend/src/components/HeaderControls/index.js: -------------------------------------------------------------------------------- 1 | import HeaderControls from './HeaderControlsContainer'; 2 | 3 | export default HeaderControls; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Icons/VisualizerIcon.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: VisualizerIcon 3 | menu: Components 4 | --- 5 | 6 | import { Playground, Props } from 'docz'; 7 | import { VisualizerIcon } from './VisualizerIconComponent'; 8 | 9 | # VisualizerIcon 10 | 11 | VisualizerIcon is a universal component used in multiple places in the platform. The goal is to provide an easy access to custom Visualizer icons based on `VisualizerCode` property. 12 | 13 | # Structure 14 | 15 | `VisualizerIcon` component exported from `Icons` folder is represented by a stateless react component. 16 | 17 | ```.md 18 | ├── VisualizerIcon.jsx # stateless react component, responsible for ui 19 | └── index.js 20 | ``` 21 | 22 | ## Properties 23 | 24 | 25 | 26 | ## Basic examples 27 | 28 | ### Map visualizer icon 29 | 30 | 31 | 35 | 36 | 37 | ### Chord visualizer icon 38 | 39 | 40 | 44 | 45 | 46 | ### Treemap visualizer icon 47 | 48 | 49 | 53 | 54 | -------------------------------------------------------------------------------- /src/frontend/src/components/Icons/index.js: -------------------------------------------------------------------------------- 1 | import { VisualizerIcon } from './VisualizerIconComponent'; 2 | 3 | export default VisualizerIcon; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Loaders/LinearLoader.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: LinearLoader 3 | menu: Components 4 | --- 5 | 6 | import { Playground, Props } from 'docz'; 7 | import { LinearLoader } from './LinearLoaderComponent'; 8 | 9 | # LinearLoader 10 | 11 | LinearLoader is a wrapper around [LinearProgress](https://material-ui.com/api/linear-progress/), that adds extra [Typography](https://material-ui.com/components/typography/) label centered above the component to indicate the loading status. 12 | 13 | # Structure 14 | 15 | `LinearLoader` component exported from `Loaders` folder is represented by a single stateless react component. 16 | 17 | ```.md 18 | ├── LinearLoaderComponent.jsx # Stateless react component 19 | └── index.js 20 | ``` 21 | 22 | ## Properties 23 | 24 | 25 | 26 | ## Example 27 | 28 | ### Variant `query` 29 | 30 | 31 | 32 | 33 | 34 | ### Variant `buffer` 35 | 36 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /src/frontend/src/components/Loaders/LinearLoaderComponent.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import { withStyles } from '@material-ui/core/styles'; 4 | import LinearProgress from '@material-ui/core/LinearProgress'; 5 | import Typography from '@material-ui/core/Typography'; 6 | 7 | const styles = { 8 | root: { 9 | flexGrow: 1 10 | }, 11 | colorPrimary: { 12 | backgroundColor: '#B2DFDB' 13 | }, 14 | barColorPrimary: { 15 | backgroundColor: '#00695C' 16 | } 17 | }; 18 | 19 | type Props = { 20 | classes: Object, 21 | labelText: string, 22 | variant: string 23 | }; 24 | 25 | const LinearLoaderComponent = ({ 26 | classes, 27 | labelText, 28 | variant = 'indeterminate' 29 | }: Props) => ( 30 |
31 | 32 | {labelText} 33 | 34 | 35 |
36 | ); 37 | 38 | export const LinearLoader = withStyles(styles)(LinearLoaderComponent); 39 | -------------------------------------------------------------------------------- /src/frontend/src/components/Loaders/index.js: -------------------------------------------------------------------------------- 1 | import { LinearLoader } from './LinearLoaderComponent'; 2 | 3 | export default LinearLoader; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/NavigationBar/NavigationBar.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: NavigationBar 3 | menu: Components 4 | --- 5 | 6 | import { Playground, Props } from 'docz'; 7 | import { NavigationBarDemo } from './NavigationBarContainer'; 8 | 9 | # NavigationBar 10 | 11 | NavigationBar is a component used in the header of LinkedPipes Applications frontend. Contains main control elements, such as menu `hamburger button` in the left right corner, and fast navigation to `inbox` and `profile` controls. 12 | 13 | # Structure 14 | 15 | `NavigationBar` component exported from `NavigationBar` folder is represented by a react `PureComponent`. 16 | 17 | ```.md 18 | ├── NavigationBarContainer.jsx # React PureComponent, responsible for states and UI 19 | └── index.js 20 | ``` 21 | 22 | ## Properties 23 | 24 | 25 | 26 | ## Example 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/frontend/src/components/NavigationBar/index.js: -------------------------------------------------------------------------------- 1 | import { NavigationBar } from './NavigationBarContainer'; 2 | 3 | export default NavigationBar; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Visualizers/Chord/index.js: -------------------------------------------------------------------------------- 1 | import ChordVisualizer from './ChordVisualizer'; 2 | 3 | export default ChordVisualizer; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Visualizers/Maps/index.js: -------------------------------------------------------------------------------- 1 | export { default as MapsVisualizer } from './MapsVisualizer'; 2 | -------------------------------------------------------------------------------- /src/frontend/src/components/Visualizers/Timeline/index.js: -------------------------------------------------------------------------------- 1 | import TimelineVisualizer from './TimelineVisualizer'; 2 | 3 | export default TimelineVisualizer; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Visualizers/Treemap/index.js: -------------------------------------------------------------------------------- 1 | import TreemapVisualizer from './TreemapVisualizer'; 2 | 3 | export default TreemapVisualizer; 4 | -------------------------------------------------------------------------------- /src/frontend/src/components/Visualizers/Visualizers.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: Visualizers 3 | menu: Components 4 | --- 5 | 6 | import { Playground, Props } from 'docz'; 7 | 8 | # Visualizers 9 | 10 | A folder containing supported third-party components used for data visualization. 11 | 12 | # Structure 13 | 14 | `Visualizers` is a folder containing various implementations of supported data visualizers. Structure is described as follows: 15 | 16 | ```.md 17 | ├── Chord/ # Folder containing Chord visualizer related Components 18 | ├── Maps/ # Folder containing Maps visualizer related Components 19 | ├── Treemap/ # Folder containing Treemap visualizer related Components 20 | └── index.js 21 | ``` 22 | 23 | ## Example 24 | 25 | For a specific examples of individual visualizers refer to: 26 | 27 | 1. [Pigen Maps](https://github.com/mariusandra/pigeon-maps) 28 | 1. [react-chord-diagram](https://github.com/langfordG/react-chord-diagram) 29 | 1. [react-google-charts](https://github.com/RakanNimer/react-google-charts) 30 | -------------------------------------------------------------------------------- /src/frontend/src/components/Visualizers/index.js: -------------------------------------------------------------------------------- 1 | import { MapsVisualizer } from './Maps'; 2 | import TreemapVisualizer from './Treemap'; 3 | import ChordVisualizer from './Chord'; 4 | import TimelineVisualizer from './Timeline'; 5 | 6 | export { 7 | MapsVisualizer, 8 | TreemapVisualizer, 9 | ChordVisualizer, 10 | TimelineVisualizer 11 | }; 12 | -------------------------------------------------------------------------------- /src/frontend/src/components/index.js: -------------------------------------------------------------------------------- 1 | import NavigationBar from './NavigationBar'; 2 | import LinearLoader from './Loaders'; 3 | import HeaderControls from './HeaderControls'; 4 | import { 5 | TreemapVisualizer, 6 | MapsVisualizer, 7 | ChordVisualizer, 8 | TimelineVisualizer 9 | } from './Visualizers'; 10 | import VisualizerIcon from './Icons'; 11 | import { 12 | Header, 13 | DashboardHeader, 14 | DiscoverHeader, 15 | ApplicationHeader, 16 | ApplicationsBrowserHeader, 17 | SettingsHeader, 18 | AboutHeader 19 | } from './Header'; 20 | 21 | export { 22 | NavigationBar, 23 | LinearLoader, 24 | HeaderControls, 25 | TreemapVisualizer, 26 | TimelineVisualizer, 27 | MapsVisualizer, 28 | VisualizerIcon, 29 | ChordVisualizer, 30 | Header, 31 | DashboardHeader, 32 | DiscoverHeader, 33 | ApplicationHeader, 34 | ApplicationsBrowserHeader, 35 | SettingsHeader, 36 | AboutHeader 37 | }; 38 | -------------------------------------------------------------------------------- /src/frontend/src/constants/endpoints.constants.js: -------------------------------------------------------------------------------- 1 | const SOCKET_IO_ENDPOINT = process.env.BASE_SOCKET_URL; 2 | const SOCKET_IO_RECONNECT = process.env.SOCKET_IO_RECONNECT; 3 | 4 | export { SOCKET_IO_ENDPOINT, SOCKET_IO_RECONNECT }; 5 | -------------------------------------------------------------------------------- /src/frontend/src/constants/filters.constants.js: -------------------------------------------------------------------------------- 1 | // import List from 'immutable/List'; 2 | // import Record from 'immutable/Record'; 3 | 4 | // export const filterTypes = { 5 | // CHECKBOX: 'CHECKBOX', 6 | // RADIO: 'RADIO' 7 | // }; 8 | 9 | // export const Filter = Record({ 10 | // property: 'new Property()', 11 | // type: filterTypes.CHECKBOX, 12 | // enabled: true, 13 | // expanded: false, 14 | // options: {}, 15 | // optionsUris: [] 16 | // }); 17 | -------------------------------------------------------------------------------- /src/frontend/src/constants/global.constants.js: -------------------------------------------------------------------------------- 1 | const DOCUMENTATION_URL = 'https://docs.applications.linkedpipes.com'; 2 | const FRONTEND_DOCUMENTATION_URL = 3 | 'https://docs.frontend.applications.linkedpipes.com'; 4 | const BACKEND_DOCUMENTATION_URL = 5 | 'https://docs.backend.applications.linkedpipes.com'; 6 | const SOLID_INFO_URL = 'https://solid.inrupt.com'; 7 | const CORE_CONCEPTS_DOCUMENTATION_URL = 8 | 'https://docs.applications.linkedpipes.com/get-started/3.core-concepts/'; 9 | const PROVIDING_SOURCES_DOCUMENTATION_URL = 10 | 'https://docs.applications.linkedpipes.com/tutorials/2.providing_sources/'; 11 | const CONFIGURING_APPLICATIONS_DOCUMENTATION_URL = 12 | 'https://docs.applications.linkedpipes.com/tutorials/4.configuring_published_applications/'; 13 | const SHARING_APPLICATIONS_DOCUMENTATION_URL = 14 | 'https://docs.applications.linkedpipes.com/tutorials/5.adding_solid_contacts_sharing/'; 15 | 16 | export { 17 | DOCUMENTATION_URL, 18 | FRONTEND_DOCUMENTATION_URL, 19 | BACKEND_DOCUMENTATION_URL, 20 | SOLID_INFO_URL, 21 | CORE_CONCEPTS_DOCUMENTATION_URL, 22 | PROVIDING_SOURCES_DOCUMENTATION_URL, 23 | CONFIGURING_APPLICATIONS_DOCUMENTATION_URL, 24 | SHARING_APPLICATIONS_DOCUMENTATION_URL 25 | }; 26 | -------------------------------------------------------------------------------- /src/frontend/src/constants/index.js: -------------------------------------------------------------------------------- 1 | import VISUALIZER_TYPE from './visualizers.constants'; 2 | import { SOCKET_IO_ENDPOINT, SOCKET_IO_RECONNECT } from './endpoints.constants'; 3 | import * as GlobalConstants from './global.constants'; 4 | 5 | export * from './filters.constants'; 6 | export * from './options.constants'; 7 | export { 8 | GlobalConstants, 9 | VISUALIZER_TYPE, 10 | SOCKET_IO_ENDPOINT, 11 | SOCKET_IO_RECONNECT 12 | }; 13 | -------------------------------------------------------------------------------- /src/frontend/src/constants/options.constants.js: -------------------------------------------------------------------------------- 1 | // import { List, Record } from 'immutable'; 2 | 3 | // export const SkosConcept = Record({ 4 | // label: '', 5 | // uri: '', 6 | // schemeUri: '', 7 | // linkUris: List() 8 | // }); 9 | 10 | // export const optionModes = { 11 | // ALWAYS_SELECT: 'ALWAYS_SELECT', 12 | // NEVER_SELECT: 'NEVER_SELECT', 13 | // USER_DEFINED: 'USER_DEFINED' 14 | // }; 15 | 16 | // export const Option = Record({ 17 | // skosConcept: new SkosConcept(), 18 | // count: null, 19 | // mode: optionModes.USER_DEFINED, 20 | // selected: false 21 | // }); 22 | -------------------------------------------------------------------------------- /src/frontend/src/constants/visualizers.constants.js: -------------------------------------------------------------------------------- 1 | const VISUALIZER_TYPE = { 2 | LABELED_TIMELINE: 'LABELED_TIMELINE', 3 | TIMELINE: 'TIMELINE', 4 | TIMELINE_PERIODS: 'TIMELINE_PERIODS', 5 | LABELED_TIMELINE_PERIODS: 'LABELED_TIMELINE_PERIODS', 6 | DCTERMS: 'DCTERMS', 7 | MAP: 'MAP', 8 | MAP_WITH_MARKER_FILTERS: 'MAP_WITH_MARKER_FILTERS', 9 | TREEMAP: 'TREEMAP', 10 | CHORD: 'CHORD', 11 | UNDEFINED: 'UNDEFINED' 12 | }; 13 | 14 | export default VISUALIZER_TYPE; 15 | -------------------------------------------------------------------------------- /src/frontend/src/containers/AboutPage/AboutPage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: AboutPage 3 | menu: Containers 4 | --- 5 | 6 | import { Playground, Props } from 'docz'; 7 | import { AboutPage } from './AboutPage'; 8 | 9 | # AboutPage 10 | 11 | AboutPage is a container representing a page with `About` and `FAQ` information. 12 | 13 | # Structure 14 | 15 | `AboutPage` component exported from `AboutPage` folder is represented by a stateless react component and a react `PureComponent` serving as a container. 16 | 17 | ```.md 18 | ├── AboutPage.jsx # React PureComponent, responsible for both UI and states 19 | ├── AboutPage.mdx # Documentation markdown that you are currently looking at 20 | └── index.js 21 | ``` 22 | 23 | ## Properties 24 | 25 | 26 | 27 | ## Example 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/frontend/src/containers/AboutPage/index.js: -------------------------------------------------------------------------------- 1 | import { AboutPage } from './AboutPage'; 2 | 3 | export default AboutPage; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/ApplicationPage/index.js: -------------------------------------------------------------------------------- 1 | import { ApplicationPage } from './ApplicationContainer'; 2 | 3 | export default ApplicationPage; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/AuthorizationPage/AuthorizationPage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: AuthorizationPage 3 | menu: Containers 4 | --- 5 | 6 | import { Playground, Props } from 'docz'; 7 | import { AuthorizationContainer } from './AuthorizationContainer'; 8 | import { AuthorizationComponent } from './AuthorizationComponent'; 9 | 10 | # AuthorizationPage 11 | 12 | AuthorizationPage is a container representing a `AuthorizationPage` webpage. 13 | 14 | # Main funcionality 15 | 16 | - Selecting SOLID `Provider` for authentication. 17 | - Switching between login by `Provider` and login by `WebID`. 18 | - Redirecting user to SOLID authentication pane. 19 | 20 | # Structure 21 | 22 | `AuthorizationPage` component exported from `AuthorizationPage` folder is represented by a stateless react component and a react `PureComponent` serving as a container. 23 | 24 | ```.md 25 | ├── AuthorizationComponent.jsx # Stateless react component, responsible for ui 26 | ├── AuthorizationContainer.jsx # React PureComponent, responsible for both UI and states 27 | ├── AuthorizationPage.mdx # Documentation markdown that you are currently looking at 28 | ├── children/ # Children components used within 'AuthorizationComponent.jsx' 29 | └── index.js 30 | ``` 31 | 32 | ## Properties 33 | 34 | ### Component 35 | 36 | 37 | 38 | ## Example 39 | 40 | Example demonstrates the combination of PureComponent responsible for states and stateless component 41 | responsible for UI working together in an isolated Playground. 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/frontend/src/containers/AuthorizationPage/children/index.js: -------------------------------------------------------------------------------- 1 | import SolidProviderComponent from './SolidProviderComponent'; 2 | 3 | export default SolidProviderComponent; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/AuthorizationPage/index.js: -------------------------------------------------------------------------------- 1 | import { AuthorizationContainer as AuthorizationPage } from './AuthorizationContainer'; 2 | 3 | export default AuthorizationPage; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/CreateVisualizerPage/children/Container/index.js: -------------------------------------------------------------------------------- 1 | import VisualizerContainer from './VisualizerContainer'; 2 | 3 | export default VisualizerContainer; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/CreateVisualizerPage/children/Filters/FiltersContainer.jsx: -------------------------------------------------------------------------------- 1 | // import React, { PureComponent } from 'react'; 2 | // import FiltersComponent from './FiltersComponent'; 3 | // import PropTypes from 'prop-types'; 4 | // import { 5 | // TOGGLE_FILTER, 6 | // TOGGLE_EXPAND_FILTER, 7 | // TOGGLE_CHECKBOX 8 | // } from '@constants'; 9 | // import { connect } from 'react-redux'; 10 | 11 | // class FiltersContainer extends PureComponent { 12 | // render() { 13 | // const { filters, handleClick, handleOptionChange } = this.props; 14 | // return ( 15 | // 20 | // ); 21 | // } 22 | // } 23 | 24 | // FiltersContainer.propTypes = { 25 | // filters: PropTypes.array, 26 | // handleClick: PropTypes.func, 27 | // handleOptionChange: PropTypes.func 28 | // }; 29 | 30 | // const mapDispatchToProps = dispatch => { 31 | // const onFilterExpand = filter => 32 | // dispatch({ type: TOGGLE_EXPAND_FILTER, payload: filter }); 33 | // const onOptionChange = (filterUri, optionUri) => 34 | // dispatch({ 35 | // type: TOGGLE_CHECKBOX, 36 | // payload: { filterUri, optionUri } 37 | // }); 38 | 39 | // return { 40 | // onFilterExpand, 41 | // onOptionChange 42 | // }; 43 | // }; 44 | 45 | // export default connect( 46 | // null, 47 | // mapDispatchToProps 48 | // )(FiltersContainer); 49 | -------------------------------------------------------------------------------- /src/frontend/src/containers/CreateVisualizerPage/children/Filters/Options/index.js: -------------------------------------------------------------------------------- 1 | import OptionsComponent from './OptionsComponent'; 2 | 3 | export default OptionsComponent; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/CreateVisualizerPage/children/Filters/children/ChordFilter/index.js: -------------------------------------------------------------------------------- 1 | import ChordFiltersComponent from './ChordFiltersComponent'; 2 | 3 | export default ChordFiltersComponent; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/CreateVisualizerPage/children/Filters/children/MapFilter/index.js: -------------------------------------------------------------------------------- 1 | import MapSchemeFilterComponent from './MapSchemeFilterComponent'; 2 | 3 | export default MapSchemeFilterComponent; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/CreateVisualizerPage/children/Filters/children/TreemapFilter/index.js: -------------------------------------------------------------------------------- 1 | import TreemapFiltersComponent from './TreemapFiltersComponent'; 2 | import TreemapNodesFilterComponent from './TreemapNodesFilterComponent'; 3 | 4 | export { TreemapFiltersComponent, TreemapNodesFilterComponent }; 5 | -------------------------------------------------------------------------------- /src/frontend/src/containers/CreateVisualizerPage/children/Filters/index.js: -------------------------------------------------------------------------------- 1 | import FiltersComponent from './FiltersComponent'; 2 | 3 | export default FiltersComponent; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/CreateVisualizerPage/children/Header/children/index.js: -------------------------------------------------------------------------------- 1 | import DataRefreshControlDialog from './DataRefreshControlDialog'; 2 | 3 | export { DataRefreshControlDialog }; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/CreateVisualizerPage/children/Header/index.js: -------------------------------------------------------------------------------- 1 | import VisualizerControllerHeader from './VisualizerHeaderContainer'; 2 | import EditVisualizerHeader from './EditVisualizerHeaderContainer'; 3 | 4 | export { EditVisualizerHeader, VisualizerControllerHeader }; 5 | -------------------------------------------------------------------------------- /src/frontend/src/containers/CreateVisualizerPage/children/index.js: -------------------------------------------------------------------------------- 1 | import { VisualizerControllerHeader, EditVisualizerHeader } from './Header'; 2 | import VisualizerContainer from './Container'; 3 | 4 | export { 5 | VisualizerControllerHeader, 6 | EditVisualizerHeader, 7 | VisualizerContainer 8 | }; 9 | -------------------------------------------------------------------------------- /src/frontend/src/containers/CreateVisualizerPage/index.js: -------------------------------------------------------------------------------- 1 | import { CreateVisualizerContainer as CreateVisualizerPage } from './CreateVisualizerContainer'; 2 | 3 | export default CreateVisualizerPage; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/DiscoverInputSources/DiscoverInputSourcesComponent.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import DiscoverSelectorContainer from './DiscoverSelectorContainer'; 4 | import { withStyles } from '@material-ui/core/styles'; 5 | 6 | type Props = { 7 | classes: { root: { width: string } }, 8 | onInputExampleClicked: any => void, 9 | onNextClicked: () => void 10 | }; 11 | 12 | const styles = () => ({ 13 | root: { 14 | width: '100%' 15 | } 16 | }); 17 | 18 | const DiscoverInputSourcesComponent = ({ 19 | classes, 20 | onInputExampleClicked, 21 | onNextClicked 22 | }: Props) => ( 23 |
24 | 28 |
29 | ); 30 | 31 | DiscoverInputSourcesComponent.propTypes = {}; 32 | 33 | export default withStyles(styles)(DiscoverInputSourcesComponent); 34 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/DiscoverInputSources/DiscoverInputSourcesContainer.jsx: -------------------------------------------------------------------------------- 1 | import DiscoverInputSourcesComponent from './DiscoverInputSourcesComponent'; 2 | import { discoverActions } from '../duck'; 3 | import { connect } from 'react-redux'; 4 | 5 | const mapStateToProps = state => { 6 | return { 7 | selectedInputExample: state.discover.selectedInputExample, 8 | activeStep: state.discover.activeStep 9 | }; 10 | }; 11 | 12 | const mapDispatchToProps = dispatch => { 13 | const onInputExampleClicked = sample => 14 | dispatch(discoverActions.setSelectedInputExample(sample)); 15 | const onNextClicked = () => dispatch(discoverActions.incrementActiveStep(1)); 16 | 17 | return { 18 | onInputExampleClicked, 19 | onNextClicked 20 | }; 21 | }; 22 | 23 | const DiscoverInputSourcesContainer = connect( 24 | mapStateToProps, 25 | mapDispatchToProps 26 | )(DiscoverInputSourcesComponent); 27 | 28 | export default DiscoverInputSourcesContainer; 29 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/DiscoverInputSources/children/index.js: -------------------------------------------------------------------------------- 1 | import DiscoverSparqlSelectorFields from './DiscoverSparqlSelectorFieldsComponent'; 2 | import DiscoverRdfUrlField from './DiscoverRdfUrlFieldComponent'; 3 | import DiscoverRdfFileDropIn from './DiscoverRdfFileDropInComponent'; 4 | 5 | export { 6 | DiscoverSparqlSelectorFields, 7 | DiscoverRdfUrlField, 8 | DiscoverRdfFileDropIn 9 | }; 10 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/DiscoverInputSources/index.js: -------------------------------------------------------------------------------- 1 | import DiscoverInputSources from './DiscoverInputSourcesContainer'; 2 | 3 | export default DiscoverInputSources; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/DiscoverPipelinesExecutor/DiscoverPipelinesExecutorComponent.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import Card from '@material-ui/core/Card'; 4 | import CardContent from '@material-ui/core/CardContent'; 5 | import { withStyles } from '@material-ui/core/styles'; 6 | import { LinearLoader } from '@components'; 7 | import { ETL_STATUS_TYPE } from '@utils'; 8 | 9 | const styles = () => ({ 10 | card: { 11 | flexGrow: 1 12 | }, 13 | loader: { 14 | width: '80%' 15 | } 16 | }); 17 | 18 | type Props = { 19 | classes: any, 20 | etlExecutionIsFinished: string, 21 | loaderLabelText: any 22 | }; 23 | 24 | const DiscoverPipelinesExecutorComponent = ({ 25 | classes, 26 | etlExecutionIsFinished, 27 | loaderLabelText 28 | }: Props) => ( 29 | 30 | 31 | {etlExecutionIsFinished === ETL_STATUS_TYPE.Finished || 32 | etlExecutionIsFinished === ETL_STATUS_TYPE.Cancelled || 33 | etlExecutionIsFinished === ETL_STATUS_TYPE.Unknown || 34 | etlExecutionIsFinished === ETL_STATUS_TYPE.Failed ? ( 35 | 42 | ) : ( 43 | 44 | )} 45 | 46 | 47 | ); 48 | 49 | export default withStyles(styles)(DiscoverPipelinesExecutorComponent); 50 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/DiscoverPipelinesExecutor/index.js: -------------------------------------------------------------------------------- 1 | import DiscoverPipelinesExecutor from './DiscoverPipelinesExecutorContainer'; 2 | 3 | export default DiscoverPipelinesExecutor; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/DiscoverPipelinesPicker/DiscoverPipelinesHeaderComponent.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import TableCell from '@material-ui/core/TableCell'; 3 | import TableHead from '@material-ui/core/TableHead'; 4 | import TableRow from '@material-ui/core/TableRow'; 5 | 6 | const rows = [ 7 | { 8 | id: 'label', 9 | disablePadding: true, 10 | label: 'Label' 11 | }, 12 | { 13 | id: 'uri', 14 | disablePadding: false, 15 | label: 'Uri' 16 | } 17 | ]; 18 | 19 | const DiscoverPipelinesHeaderComponent = () => ( 20 | 21 | 22 | 23 | Action 24 | 25 | {rows.map(row => { 26 | return ( 27 | 28 | {row.label} 29 | 30 | ); 31 | }, this)} 32 | 33 | 34 | ); 35 | 36 | export default DiscoverPipelinesHeaderComponent; 37 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/DiscoverPipelinesPicker/index.js: -------------------------------------------------------------------------------- 1 | import DiscoverPipelinesPicker from './DiscoverPipelinesPickerContainer'; 2 | 3 | export default DiscoverPipelinesPicker; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/DiscoverVisualizerPicker/DiscoverVisualizerPickerContainer.jsx: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux'; 2 | import DiscoverVisualizerPickerComponent from './DiscoverVisualizerPickerComponent'; 3 | 4 | const mapStateToProps = state => { 5 | return { 6 | visualizers: state.discovery.pipelineGroups 7 | }; 8 | }; 9 | 10 | const DiscoverVisualizerPickerContainer = connect(mapStateToProps)( 11 | DiscoverVisualizerPickerComponent 12 | ); 13 | 14 | export default DiscoverVisualizerPickerContainer; 15 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/DiscoverVisualizerPicker/children/index.js: -------------------------------------------------------------------------------- 1 | import DiscoverVisualizerCard from './DiscoverVisualizerCardContainer'; 2 | 3 | export default DiscoverVisualizerCard; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/DiscoverVisualizerPicker/index.js: -------------------------------------------------------------------------------- 1 | import DiscoverVisualizerPicker from './DiscoverVisualizerPickerContainer'; 2 | 3 | export default DiscoverVisualizerPicker; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/duck/index.js: -------------------------------------------------------------------------------- 1 | export { default as discoverActions } from './actions'; 2 | export { default as discoverTypes } from './types'; 3 | export { default as discoverReducer } from './reducers'; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/duck/types.jsx: -------------------------------------------------------------------------------- 1 | const INCREMENT_ACTIVE_STEP = 'INCREMENT_ACTIVE_STEP'; 2 | const SET_ACTIVE_STEP = 'SET_ACTIVE_STEP'; 3 | const DECREMENT_ACTIVE_STEP = 'DECREMENT_ACTIVE_STEP'; 4 | const RESET_ACTIVE_STEP = 'RESET_ACTIVE_STEP'; 5 | const SET_SELECTED_INPUT_EXAMPLE = 'SET_SELECTED_INPUT_EXAMPLE'; 6 | const SET_ETL_EXECUTION_STATUS = 'SET_ETL_EXECUTION_STATUS'; 7 | const RESET_SELECTED_INPUT_EXAMPLE = 'RESET_SELECTED_INPUT_EXAMPLE'; 8 | const SET_NAMED_GRAPH = 'SET_NAMED_GRAPH'; 9 | const SET_SPARQL_ENDPOINT_IRI = 'SET_SPARQL_ENDPOINT_IRI'; 10 | const SET_DATA_SAMPLE_IRI = 'SET_DATA_SAMPLE_IRI'; 11 | const SET_RDF_RESOURCE_URL = 'SET_RDF_RESOURCE_URL'; 12 | const SET_RDF_FILE = 'SET_RDF_FILE'; 13 | const SET_RDF_DATA_SAMPLE_FILE = 'SET_RDF_DATA_SAMPLE_FILE'; 14 | const SET_ACTIVE_DISCOVER_INPUT_TAB = 'SET_ACTIVE_DISCOVER_INPUT_TAB'; 15 | const SET_RDF_URL_DATA_SAMPLE_IRI = 'SET_RDF_URL_DATA_SAMPLE_IRI'; 16 | 17 | export default { 18 | INCREMENT_ACTIVE_STEP, 19 | SET_ACTIVE_STEP, 20 | DECREMENT_ACTIVE_STEP, 21 | RESET_ACTIVE_STEP, 22 | SET_SELECTED_INPUT_EXAMPLE, 23 | RESET_SELECTED_INPUT_EXAMPLE, 24 | SET_ETL_EXECUTION_STATUS, 25 | SET_NAMED_GRAPH, 26 | SET_SPARQL_ENDPOINT_IRI, 27 | SET_DATA_SAMPLE_IRI, 28 | SET_RDF_RESOURCE_URL, 29 | SET_RDF_FILE, 30 | SET_RDF_DATA_SAMPLE_FILE, 31 | SET_ACTIVE_DISCOVER_INPUT_TAB, 32 | SET_RDF_URL_DATA_SAMPLE_IRI 33 | }; 34 | -------------------------------------------------------------------------------- /src/frontend/src/containers/DiscoverPage/index.js: -------------------------------------------------------------------------------- 1 | import { DiscoverPage } from './DiscoverContainer'; 2 | import { discoverReducer } from './duck'; 3 | 4 | export { DiscoverPage, discoverReducer }; 5 | -------------------------------------------------------------------------------- /src/frontend/src/containers/HomePage/children/children/index.js: -------------------------------------------------------------------------------- 1 | import DiscoveryInformationDialog from './DiscoveryInformationDialog'; 2 | import EnhancedTableHead from './EnhancedTableHead'; 3 | 4 | export { EnhancedTableHead, DiscoveryInformationDialog }; 5 | -------------------------------------------------------------------------------- /src/frontend/src/containers/HomePage/children/index.js: -------------------------------------------------------------------------------- 1 | import DiscoveriesCollection from './DiscoveriesTableContainer'; 2 | import ApplicationsTable from './ApplicationsTableComponent'; 3 | import PipelinesCollection from './PipelinesTableComponent'; 4 | import { QuickStart } from './QuickStartComponent'; 5 | 6 | export { 7 | DiscoveriesCollection, 8 | ApplicationsTable, 9 | PipelinesCollection, 10 | QuickStart 11 | }; 12 | -------------------------------------------------------------------------------- /src/frontend/src/containers/HomePage/index.js: -------------------------------------------------------------------------------- 1 | import { HomePage } from './HomeController'; 2 | 3 | export default HomePage; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/NotFoundPage/NotFoundPage.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { PureComponent } from 'react'; 3 | import Typography from '@material-ui/core/Typography'; 4 | import { withStyles } from '@material-ui/core/styles'; 5 | import { GoogleAnalyticsWrapper } from '@utils'; 6 | 7 | const styles = theme => ({ 8 | root: { 9 | textAlign: 'center', 10 | paddingTop: theme.spacing(20), 11 | position: 'absolute', 12 | left: '50%', 13 | top: '40%', 14 | transform: 'translate(-50%, -50%)' 15 | }, 16 | button: { 17 | margin: theme.spacing() 18 | }, 19 | input: { 20 | display: 'none' 21 | } 22 | }); 23 | 24 | type Props = { 25 | classes: Object, 26 | location: Object 27 | }; 28 | 29 | class NotFound extends PureComponent { 30 | componentDidMount() { 31 | const page = this.props.location.pathname; 32 | GoogleAnalyticsWrapper.trackPage(page); 33 | } 34 | 35 | render() { 36 | const { classes } = this.props; 37 | return ( 38 |
39 | 40 | 404 41 | 42 | 43 | Page not found... 44 | 45 |
46 | ); 47 | } 48 | } 49 | 50 | export const NotFoundPage = withStyles(styles)(NotFound); 51 | -------------------------------------------------------------------------------- /src/frontend/src/containers/NotFoundPage/NotFoundPage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: NotFoundPage 3 | menu: Containers 4 | --- 5 | 6 | import { Playground, Props } from 'docz'; 7 | import { NotFoundPage } from './NotFoundPage'; 8 | 9 | # NotFoundPage 10 | 11 | NotFoundPage is a container representing a `NotFoundPage` page. 12 | 13 | # Main funcionality 14 | 15 | - A default page being rendered on undefined routes. 16 | 17 | # Structure 18 | 19 | `NotFoundPage` component exported from `NotFoundPage` folder is represented by a stateless react component. 20 | 21 | ```.md 22 | ├── NotFoundPage.jsx # Stateless react component, responsible for ui 23 | ├── NotFoundPage.mdx # Documentation markdown that you are currently looking at 24 | └── index.js 25 | ``` 26 | 27 | ## Properties 28 | 29 | 30 | 31 | ## Example 32 | 33 | 34 |
38 | 39 |
40 |
41 | -------------------------------------------------------------------------------- /src/frontend/src/containers/NotFoundPage/index.js: -------------------------------------------------------------------------------- 1 | import { NotFoundPage } from './NotFoundPage'; 2 | 3 | export default NotFoundPage; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/SettingsPage/Profile/UserProfilePage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: UserProfilePage 3 | menu: Containers 4 | --- 5 | 6 | import { Playground, Props } from 'docz'; 7 | import { UserProfilePage } from './UserProfilePageComponent'; 8 | 9 | # UserProfilePage 10 | 11 | UserProfilePage is a container representing a `UserProfile` page. 12 | 13 | # Main funcionality 14 | 15 | - Reset password in SOLID. 16 | - Logout from LinkedPipes Applications platform. 17 | - Display current user's WebID and Name. 18 | 19 | # Structure 20 | 21 | `UserProfilePage` component exported from `UserProfilePage` folder is represented by a stateless react component and a react `PureComponent` serving as a container. 22 | 23 | ```.md 24 | ├── UserProfilePageComponent.jsx # Stateless react component, responsible for ui 25 | ├── UserProfilePageContainer.jsx # React PureComponent, responsible for both UI and states 26 | ├── UserProfilePage.mdx # Documentation markdown that you are currently looking at 27 | └── index.js 28 | ``` 29 | 30 | ## Properties 31 | 32 | 33 | 34 | ## Example 35 | 36 | 37 | 41 | 42 | -------------------------------------------------------------------------------- /src/frontend/src/containers/SettingsPage/Profile/index.js: -------------------------------------------------------------------------------- 1 | import UserProfilePage from './UserProfilePageContainer'; 2 | 3 | export default UserProfilePage; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/SettingsPage/Settings/SettingsPage.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | name: SettingsPage 3 | menu: Containers 4 | --- 5 | 6 | import { Playground, Props } from 'docz'; 7 | import { SettingsPageComponent } from './SettingsPageComponent'; 8 | 9 | # SettingsPage 10 | 11 | UserProfilePage is a container representing a `UserProfile` page. 12 | 13 | # Main funcionality 14 | 15 | - Change default folder for application configurations in SOLID. 16 | - Toggle light or dark mode UI theme. 17 | 18 | # Structure 19 | 20 | `SettingsPage` component exported from `SettingsPage` folder is represented by a stateless react component and a react `PureComponent` serving as a container. 21 | 22 | ```.md 23 | ├── SettingsPageComponent.jsx # Stateless react component, responsible for ui 24 | ├── SettingsPageContainer.jsx # React PureComponent, responsible for both UI and states 25 | ├── SettingsPage.mdx # Documentation markdown that you are currently looking at 26 | └── index.js 27 | ``` 28 | 29 | ## Properties 30 | 31 | 32 | 33 | ## Example 34 | 35 | 36 | 44 | 45 | -------------------------------------------------------------------------------- /src/frontend/src/containers/SettingsPage/Settings/SettingsPageContainer.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React, { PureComponent, Fragment } from 'react'; 3 | import { SettingsPageComponent } from './SettingsPageComponent'; 4 | import { connect } from 'react-redux'; 5 | import { globalActions } from '@ducks/globalDuck'; 6 | import { StoragePickFolderDialog } from '@storage'; 7 | import { withAuthorization } from '@utils'; 8 | 9 | type Props = { 10 | userProfile: Object, 11 | handleUpdateChooseFolderDialogState: Function 12 | }; 13 | 14 | class SettingsPage extends PureComponent { 15 | constructor(props) { 16 | super(props); 17 | (this: any).handleChangeFolder = this.handleChangeFolder.bind(this); 18 | } 19 | 20 | handleChangeFolder() { 21 | const { handleUpdateChooseFolderDialogState } = this.props; 22 | handleUpdateChooseFolderDialogState(true); 23 | } 24 | 25 | render() { 26 | const { userProfile } = this.props; 27 | const { handleChangeFolder } = this; 28 | return ( 29 | 30 | 34 | 35 | 36 | ); 37 | } 38 | } 39 | 40 | const mapStateToProps = state => { 41 | return { 42 | userProfile: state.user 43 | }; 44 | }; 45 | 46 | const mapDispatchToProps = dispatch => { 47 | const handleUpdateChooseFolderDialogState = state => 48 | dispatch(globalActions.setChooseFolderDialogState({ state })); 49 | 50 | return { 51 | handleUpdateChooseFolderDialogState 52 | }; 53 | }; 54 | 55 | export const SettingsPageContainer = withAuthorization( 56 | connect( 57 | mapStateToProps, 58 | mapDispatchToProps 59 | )(SettingsPage) 60 | ); 61 | -------------------------------------------------------------------------------- /src/frontend/src/containers/SettingsPage/Settings/index.js: -------------------------------------------------------------------------------- 1 | import { SettingsPageContainer as SettingsPage } from './SettingsPageContainer'; 2 | 3 | export default SettingsPage; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/SettingsPage/SettingsController.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import { withStyles } from '@material-ui/core/styles'; 4 | import SettingsPage from './Settings'; 5 | import ProfilePage from './Profile'; 6 | import { connect } from 'react-redux'; 7 | import { GoogleAnalyticsWrapper } from '@utils'; 8 | 9 | const styles = () => ({ 10 | root: { 11 | flexGrow: 1 12 | } 13 | }); 14 | 15 | type Props = { 16 | location: Object, 17 | settingsTabIndex: number 18 | }; 19 | 20 | class StoragePageController extends React.Component { 21 | componentDidMount() { 22 | const page = this.props.location.pathname; 23 | GoogleAnalyticsWrapper.trackPage(page); 24 | } 25 | 26 | getContent = tabIndex => { 27 | switch (tabIndex) { 28 | case 0: 29 | return ; 30 | case 1: 31 | return ; 32 | default: 33 | return ; 34 | } 35 | }; 36 | 37 | render() { 38 | const { settingsTabIndex } = this.props; 39 | 40 | return {this.getContent(settingsTabIndex)}; 41 | } 42 | } 43 | 44 | const mapStateToProps = state => { 45 | return { 46 | settingsTabIndex: state.globals.settingsTabIndex 47 | }; 48 | }; 49 | 50 | export default connect(mapStateToProps)( 51 | withStyles(styles)(StoragePageController) 52 | ); 53 | -------------------------------------------------------------------------------- /src/frontend/src/containers/SettingsPage/index.js: -------------------------------------------------------------------------------- 1 | import SettingsPage from './SettingsController'; 2 | 3 | export default SettingsPage; 4 | -------------------------------------------------------------------------------- /src/frontend/src/containers/index.js: -------------------------------------------------------------------------------- 1 | import AuthorizationPage from './AuthorizationPage'; 2 | import ApplicationPage from './ApplicationPage'; 3 | import HomePage from './HomePage'; 4 | import { DiscoverPage, discoverReducer } from './DiscoverPage'; 5 | import AboutPage from './AboutPage'; 6 | import NotFoundPage from './NotFoundPage'; 7 | import CreateVisualizerPage from './CreateVisualizerPage'; 8 | import UserProfilePage from './SettingsPage/Profile'; 9 | import SettingsPage from './SettingsPage'; 10 | 11 | export { 12 | AuthorizationPage, 13 | ApplicationPage, 14 | HomePage, 15 | DiscoverPage, 16 | discoverReducer, 17 | AboutPage, 18 | NotFoundPage, 19 | CreateVisualizerPage, 20 | UserProfilePage, 21 | SettingsPage 22 | }; 23 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/applicationDuck/actions.jsx: -------------------------------------------------------------------------------- 1 | import types from './types'; 2 | 3 | const setApplication = applicationData => ({ 4 | type: types.SET_APPLICATION, 5 | value: applicationData 6 | }); 7 | 8 | const setApplicationMetadata = applicationMetadata => ({ 9 | type: types.SET_APPLICATION_METADATA, 10 | value: applicationMetadata 11 | }); 12 | 13 | const resetApplication = () => ({ 14 | type: types.RESET_APPLICATION 15 | }); 16 | 17 | const resetApplicationMetadata = () => ({ 18 | type: types.RESET_APPLICATION_METADATA 19 | }); 20 | 21 | const setApplicationTitle = applicationTitle => ({ 22 | type: types.SET_APPLICATION_TITLE, 23 | value: applicationTitle 24 | }); 25 | 26 | export default { 27 | setApplication, 28 | setApplicationMetadata, 29 | resetApplicationMetadata, 30 | resetApplication, 31 | setApplicationTitle 32 | }; 33 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/applicationDuck/index.js: -------------------------------------------------------------------------------- 1 | export { default as applicationActions } from './actions'; 2 | export { default as applicationTypes } from './types'; 3 | export { default as applicationSelectors } from './selectors'; 4 | export { default as applicationReducer } from './reducers'; 5 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/applicationDuck/reducers.jsx: -------------------------------------------------------------------------------- 1 | import types from './types'; 2 | 3 | const INITIAL_STATE = { 4 | selectedApplication: {}, 5 | selectedApplicationMetadata: undefined 6 | }; 7 | 8 | const applicationReducer = (state = INITIAL_STATE, action) => { 9 | switch (action.type) { 10 | case types.SET_APPLICATION: 11 | return { 12 | ...state, 13 | selectedApplication: { ...state.selectedApplication, ...action.value } 14 | }; 15 | 16 | case types.SET_APPLICATION_METADATA: 17 | return { ...state, selectedApplicationMetadata: action.value }; 18 | 19 | case types.RESET_APPLICATION_METADATA: 20 | return { ...state, selectedApplicationMetadata: undefined }; 21 | 22 | case types.RESET_APPLICATION: 23 | return { ...state, selectedApplication: {} }; 24 | 25 | case types.SET_APPLICATION_TITLE: 26 | return { 27 | ...state, 28 | selectedApplication: { 29 | ...state.selectedApplication, 30 | title: action.value 31 | } 32 | }; 33 | default: 34 | return state; 35 | } 36 | }; 37 | 38 | export default applicationReducer; 39 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/applicationDuck/selectors.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedpipes/applications/e79c72f74e82f7257a8141b7de00ab9ec207e65f/src/frontend/src/ducks/applicationDuck/selectors.jsx -------------------------------------------------------------------------------- /src/frontend/src/ducks/applicationDuck/types.jsx: -------------------------------------------------------------------------------- 1 | const SET_APPLICATION = 'SET_APPLICATION'; 2 | const RESET_APPLICATION = 'RESET_APPLICATION'; 3 | const SET_APPLICATION_TITLE = 'SET_APPLICATION_TITLE'; 4 | const SET_APPLICATION_METADATA = 'SET_APPLICATION_METADATA'; 5 | const RESET_APPLICATION_METADATA = 'RESET_APPLICATION_METADATA'; 6 | 7 | export default { 8 | SET_APPLICATION, 9 | RESET_APPLICATION, 10 | SET_APPLICATION_TITLE, 11 | SET_APPLICATION_METADATA, 12 | RESET_APPLICATION_METADATA 13 | }; 14 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/discoveryDuck/actions.jsx: -------------------------------------------------------------------------------- 1 | import types from './types'; 2 | 3 | const addDiscoveryIdAction = ({ id } = {}) => ({ 4 | type: types.SET_DISCOVERY_ID, 5 | discovery: { 6 | id 7 | } 8 | }); 9 | 10 | const addDataSampleSessionIdAction = dataSampleSessionId => ({ 11 | type: types.SET_DATA_SAMPLE_SESSION_ID, 12 | value: dataSampleSessionId 13 | }); 14 | 15 | const setPipelineGroupsAction = pipelineGroups => { 16 | return { 17 | type: types.SET_PIPELINE_GROUPS, 18 | pipelineGroups 19 | }; 20 | }; 21 | 22 | const setSelectedPipelineGroupAction = ({ selectedPipelineGroup } = {}) => { 23 | return { 24 | type: types.SET_SELECTED_PIPELINE_GROUP, 25 | selectedPipelineGroup 26 | }; 27 | }; 28 | 29 | export default { 30 | addDiscoveryIdAction, 31 | addDataSampleSessionIdAction, 32 | setPipelineGroupsAction, 33 | setSelectedPipelineGroupAction 34 | }; 35 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/discoveryDuck/index.js: -------------------------------------------------------------------------------- 1 | export { default as discoveryActions } from './actions'; 2 | export { default as discoveryTypes } from './types'; 3 | export { default as discoverySelectors } from './selectors'; 4 | export { default as discoveryReducer } from './reducers'; 5 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/discoveryDuck/reducers.jsx: -------------------------------------------------------------------------------- 1 | import types from './types'; 2 | 3 | const INITIAL_STATE = { 4 | discoveryId: undefined, 5 | dataSampleSessionId: undefined, 6 | selectedPipelineGroup: {}, 7 | datasources: [], 8 | pipelineGroups: [] 9 | }; 10 | 11 | const discoveryReducer = (state = INITIAL_STATE, action) => { 12 | switch (action.type) { 13 | case types.SET_DISCOVERY_ID: 14 | return { ...state, discoveryId: action.discovery.id }; 15 | 16 | case types.SET_DATA_SAMPLE_SESSION_ID: 17 | return { ...state, dataSampleSessionId: action.value }; 18 | 19 | case types.SET_PIPELINE_GROUPS: 20 | return { ...state, pipelineGroups: action.pipelineGroups }; 21 | 22 | case types.SET_SELECTED_PIPELINE_GROUP: 23 | return { ...state, selectedPipelineGroup: action.selectedPipelineGroup }; 24 | 25 | default: 26 | return state; 27 | } 28 | }; 29 | 30 | export default discoveryReducer; 31 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/discoveryDuck/selectors.jsx: -------------------------------------------------------------------------------- 1 | // Get datasources as plain array of uris 2 | 3 | function getDatasourcesArray(datasources) { 4 | return datasources.map(source => { 5 | return source.url; 6 | }); 7 | } 8 | 9 | function getDatasourcesForTTLGenerator(datasourcesForTTLGenerator) { 10 | return datasourcesForTTLGenerator.map(source => { 11 | return { Uri: source.url }; 12 | }); 13 | } 14 | 15 | export default { 16 | getDatasourcesArray, 17 | getDatasourcesForTTLGenerator 18 | }; 19 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/discoveryDuck/types.jsx: -------------------------------------------------------------------------------- 1 | const ADD_SOURCE = 'ADD_SOURCE'; 2 | const ADD_MULTIPLE_SOURCES = 'DECREMADD_MULTIPLE_SOURCESENT_ACTIVE_STEP'; 3 | const REMOVE_SOURCE = 'REMOVE_SOURCE'; 4 | const SET_SELECTED_PIPELINE_GROUP = 'SET_SELECTED_PIPELINE_GROUP'; 5 | const SET_PIPELINE_GROUPS = 'SET_PIPELINE_GROUPS'; 6 | const SET_DISCOVERY_ID = 'SET_DISCOVERY_ID'; 7 | const SET_DATA_SAMPLE_SESSION_ID = 'SET_DATA_SAMPLE_SESSION_ID'; 8 | 9 | export default { 10 | ADD_SOURCE, 11 | ADD_MULTIPLE_SOURCES, 12 | REMOVE_SOURCE, 13 | SET_SELECTED_PIPELINE_GROUP, 14 | SET_PIPELINE_GROUPS, 15 | SET_DISCOVERY_ID, 16 | SET_DATA_SAMPLE_SESSION_ID 17 | }; 18 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/etlDuck/actions.jsx: -------------------------------------------------------------------------------- 1 | import types from './types'; 2 | 3 | const addSelectedResultGraphIriAction = selectedResultGraphIri => ({ 4 | type: types.SET_SELECTED_RESULT_GRAPH_IRI, 5 | selectedResultGraphIri 6 | }); 7 | 8 | const setPipelineIdAction = pipelineId => ({ 9 | type: types.SET_PIPELINE_ID, 10 | pipeline: { 11 | id: pipelineId 12 | } 13 | }); 14 | 15 | const setSelectedPipelineExecution = pipelineExecution => ({ 16 | type: types.SET_PIPELINE_EXECUTION, 17 | pipelineExecution 18 | }); 19 | 20 | export default { 21 | addSelectedResultGraphIriAction, 22 | setPipelineIdAction, 23 | setSelectedPipelineExecution 24 | }; 25 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/etlDuck/index.js: -------------------------------------------------------------------------------- 1 | export { default as etlActions } from './actions'; 2 | export { default as etlTypes } from './types'; 3 | export { default as etlReducer } from './reducers'; 4 | export { default as etlSelector } from './selectors'; 5 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/etlDuck/reducers.jsx: -------------------------------------------------------------------------------- 1 | import types from './types'; 2 | 3 | const INITIAL_STATE = { 4 | selectedResultGraphIri: undefined, 5 | selectedPipelineExecution: undefined, 6 | pipelineId: undefined 7 | }; 8 | 9 | const etlReducer = (state = INITIAL_STATE, action) => { 10 | switch (action.type) { 11 | case types.SET_SELECTED_RESULT_GRAPH_IRI: 12 | return { 13 | ...state, 14 | selectedResultGraphIri: action.selectedResultGraphIri 15 | }; 16 | 17 | case types.SET_PIPELINE_ID: 18 | return { ...state, pipelineId: action.pipeline.id }; 19 | 20 | case types.SET_PIPELINE_EXECUTION: 21 | return { ...state, selectedPipelineExecution: action.pipelineExecution }; 22 | 23 | default: 24 | return state; 25 | } 26 | }; 27 | 28 | export default etlReducer; 29 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/etlDuck/selectors.jsx: -------------------------------------------------------------------------------- 1 | // // Get etl executions 2 | 3 | function getPipelineExecutionForExecutionIri(executions, executionIri) { 4 | return executions.filter(source => { 5 | return source.executionIri === executionIri; 6 | }); 7 | } 8 | 9 | export default { 10 | getPipelineExecutionForExecutionIri 11 | }; 12 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/etlDuck/types.jsx: -------------------------------------------------------------------------------- 1 | const REMOVE_EXECUTION = 'REMOVE_EXECUTION'; 2 | const ADD_EXPORT = 'ADD_EXPORT'; 3 | const REMOVE_EXPORT = 'REMOVE_EXPORT'; 4 | const SET_SELECTED_RESULT_GRAPH_IRI = 'SET_SELECTED_RESULT_GRAPH_IRI'; 5 | const SET_PIPELINE_ID = 'SET_PIPELINE_ID'; 6 | const SET_PIPELINE_EXECUTION = 'SET_PIPELINE_EXECUTION'; 7 | 8 | export default { 9 | REMOVE_EXECUTION, 10 | ADD_EXPORT, 11 | REMOVE_EXPORT, 12 | SET_SELECTED_RESULT_GRAPH_IRI, 13 | SET_PIPELINE_ID, 14 | SET_PIPELINE_EXECUTION 15 | }; 16 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/filtersDuck/index.js: -------------------------------------------------------------------------------- 1 | export { default as filtersActions } from './actions'; 2 | export { default as filtersTypes } from './types'; 3 | export { default as filtersReducer } from './reducers'; 4 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/filtersDuck/types.jsx: -------------------------------------------------------------------------------- 1 | const SET_SELECTED_SCHEME = 'SET_SELECTED_SCHEME'; 2 | const SET_SELECTED_NODES = 'SET_SELECTED_NODES'; 3 | const SET_DEFAULT_FILTERS_STATE = 'SET_DEFAULT_FILTERS_STATE'; 4 | const TOGGLE_ENABLED = 'TOGGLE_ENABLED'; 5 | const TOGGLE_VISIBLE = 'TOGGLE_VISIBLE'; 6 | const RESET_FILTERS = 'RESET_FILTERS'; 7 | const SET_FILTERS_STATE = 'SET_FILTERS_STATE'; 8 | const SET_SELECTED_MAP_OPTIONS = 'SET_SELECTED_MAP_OPTIONS'; 9 | 10 | export default { 11 | SET_SELECTED_SCHEME, 12 | SET_SELECTED_NODES, 13 | SET_DEFAULT_FILTERS_STATE, 14 | SET_FILTERS_STATE, 15 | TOGGLE_ENABLED, 16 | TOGGLE_VISIBLE, 17 | RESET_FILTERS, 18 | SET_SELECTED_MAP_OPTIONS 19 | }; 20 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/globalDuck/index.js: -------------------------------------------------------------------------------- 1 | export { default as globalActions } from './actions'; 2 | export { default as globalTypes } from './types'; 3 | export { default as globalReducer } from './reducers'; 4 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/globalDuck/selectors.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedpipes/applications/e79c72f74e82f7257a8141b7de00ab9ec207e65f/src/frontend/src/ducks/globalDuck/selectors.jsx -------------------------------------------------------------------------------- /src/frontend/src/ducks/globalDuck/types.jsx: -------------------------------------------------------------------------------- 1 | const SET_SELECTED_VISUALIZER = 'SET_SELECTED_VISUALIZER'; 2 | const SET_CHOOSE_FOLDER_DIALOG_STATE = 'SET_CHOOSE_FOLDER_DIALOG_STATE'; 3 | const SET_INBOX_DIALOG_STATE = 'SET_INBOX_DIALOG_STATE'; 4 | const SET_ACCESS_CONTROL_DIALOG_STATE = 'SET_ACCESS_CONTROL_DIALOG_STATE'; 5 | const SET_SELECTED_DASHBOARD_TAB_INDEX = 'SET_SELECTED_DASHBOARD_TAB_INDEX'; 6 | const SET_MOBILE_DRAWER_STATE = 'SET_MOBILE_DRAWER_STATE'; 7 | const SET_SELECTED_DISCOVER_TAB_INDEX = 'SET_SELECTED_DISCOVER_TAB_INDEX'; 8 | const SET_SELECTED_APPLICATION_SETUP_TAB_INDEX = 9 | 'SET_SELECTED_APPLICATION_SETUP_TAB_INDEX'; 10 | const SET_SELECTED_APPLICATIONS_BROWSER_TAB_INDEX = 11 | 'SET_SELECTED_APPLICATIONS_BROWSER_TAB_INDEX'; 12 | const SET_SELECTED_SETTINGS_TAB_INDEX = 'SET_SELECTED_SETTINGS_TAB_INDEX'; 13 | const SET_SELECTED_NAVIGATION_ITEM = 'SET_SELECTED_NAVIGATION_ITEM'; 14 | 15 | export default { 16 | SET_SELECTED_VISUALIZER, 17 | SET_CHOOSE_FOLDER_DIALOG_STATE, 18 | SET_SELECTED_DASHBOARD_TAB_INDEX, 19 | SET_INBOX_DIALOG_STATE, 20 | SET_ACCESS_CONTROL_DIALOG_STATE, 21 | SET_MOBILE_DRAWER_STATE, 22 | SET_SELECTED_DISCOVER_TAB_INDEX, 23 | SET_SELECTED_APPLICATION_SETUP_TAB_INDEX, 24 | SET_SELECTED_APPLICATIONS_BROWSER_TAB_INDEX, 25 | SET_SELECTED_SETTINGS_TAB_INDEX, 26 | SET_SELECTED_NAVIGATION_ITEM 27 | }; 28 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/index.js: -------------------------------------------------------------------------------- 1 | import discoveryDuck from './discoveryDuck'; 2 | import etlDuck from './etlDuck'; 3 | import globalDuck from './globalDuck'; 4 | import visualizersDuck from './visualizersDuck'; 5 | import userDuck from './userDuck'; 6 | import applicationDuck from './applicationDuck'; 7 | import filtersDuck from './filtersDuck'; 8 | 9 | export default { 10 | discoveryDuck, 11 | etlDuck, 12 | globalDuck, 13 | visualizersDuck, 14 | userDuck, 15 | applicationDuck, 16 | filtersDuck 17 | }; 18 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/userDuck/index.js: -------------------------------------------------------------------------------- 1 | export { default as userActions } from './actions'; 2 | export { default as userTypes } from './types'; 3 | export { default as userSelectors } from './selectors'; 4 | export { default as userReducer } from './reducers'; 5 | -------------------------------------------------------------------------------- /src/frontend/src/ducks/userDuck/selectors.jsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedpipes/applications/e79c72f74e82f7257a8141b7de00ab9ec207e65f/src/frontend/src/ducks/userDuck/selectors.jsx -------------------------------------------------------------------------------- /src/frontend/src/ducks/userDuck/types.jsx: -------------------------------------------------------------------------------- 1 | const SET_USER_PROFILE = 'SET_USER_PROFILE'; 2 | const SET_SOLID_USER_PROFILE = 'SET_SOLID_USER_PROFILE'; 3 | const SET_USER_WEBID = 'SET_USER_WEBID'; 4 | const SET_USER_SOLID_NAME = 'SET_USER_SOLID_NAME'; 5 | const SET_USER_SOLID_PROFILE_IMAGE = 'SET_USER_SOLID_PROFILE_IMAGE'; 6 | const ADD_DISCOVERY_SESSION = 'ADD_DISCOVERY_SESSION'; 7 | const ADD_EXECUTION_SESSION = 'ADD_EXECUTION_SESSION'; 8 | const DELETE_DISCOVERY_SESSION = 'DELETE_DISCOVERY_SESSION'; 9 | const DELETE_EXECUTION_SESSION = 'DELETE_EXECUTION_SESSION'; 10 | const UPDATE_EXECUTION_SESSION = 'UPDATE_EXECUTION_SESSION'; 11 | const UPDATE_DISCOVERY_SESSION = 'UPDATE_DISCOVERY_SESSION'; 12 | const UPDATE_APPLICATIONS_FOLDER = 'UPDATE_APPLICATIONS_FOLDER'; 13 | const SET_USER_SOLID_IMAGE = 'SET_USER_SOLID_IMAGE'; 14 | const SET_USER_INBOX_INVITATIONS = 'SET_USER_INBOX_INVITATIONS'; 15 | const SET_LIGHT_COLOR_THEME = 'SET_LIGHT_COLOR_THEME'; 16 | 17 | export default { 18 | SET_USER_PROFILE, 19 | SET_SOLID_USER_PROFILE, 20 | SET_USER_WEBID, 21 | SET_USER_SOLID_PROFILE_IMAGE, 22 | SET_USER_SOLID_NAME, 23 | SET_USER_SOLID_IMAGE, 24 | ADD_DISCOVERY_SESSION, 25 | ADD_EXECUTION_SESSION, 26 | DELETE_DISCOVERY_SESSION, 27 | DELETE_EXECUTION_SESSION, 28 | UPDATE_DISCOVERY_SESSION, 29 | UPDATE_EXECUTION_SESSION, 30 | UPDATE_APPLICATIONS_FOLDER, 31 | SET_USER_INBOX_INVITATIONS, 32 | SET_LIGHT_COLOR_THEME 33 | }; 34 | -------------------------------------------------------------------------------- /src/frontend/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | LPA 16 | 20 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /src/frontend/src/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import * as Sentry from '@sentry/browser'; 5 | import store from './store'; 6 | import 'normalize.css/normalize.css'; 7 | import AppRouter from './AppRouter'; 8 | import { GoogleAnalyticsWrapper } from '@utils'; 9 | 10 | const myStore = store(); 11 | 12 | if (process.env.NODE_ENV !== 'production') { 13 | localStorage.setItem('debug', 'lpapps:*'); 14 | } 15 | 16 | const jsx = ( 17 | 18 | 19 | 20 | ); 21 | 22 | if (process.env.NODE_ENV === 'production') { 23 | Sentry.init({ 24 | dsn: 'https://1da20b1a10f245cab2220da15f2a56a1@sentry.io/1283419', 25 | environment: process.env.NODE_ENV, 26 | debug: process.env.NODE_ENV !== 'production' 27 | }); 28 | } 29 | 30 | GoogleAnalyticsWrapper.initialize('UA-139954974-1'); 31 | 32 | render(jsx, document.querySelector('#app')); 33 | -------------------------------------------------------------------------------- /src/frontend/src/layouts/PrivateLayout/index.js: -------------------------------------------------------------------------------- 1 | import PrivateLayout from './PrivateLayout'; 2 | 3 | export default PrivateLayout; 4 | -------------------------------------------------------------------------------- /src/frontend/src/layouts/PublicLayout/PublicLayout.jsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import React from 'react'; 3 | import { Route, Redirect } from 'react-router-dom'; 4 | import { withStyles } from '@material-ui/core/styles'; 5 | import { connect } from 'react-redux'; 6 | 7 | const styles = () => ({ 8 | root: { 9 | display: 'flex' 10 | }, 11 | content: { 12 | flexGrow: 1, 13 | height: '100vh', 14 | overflow: 'auto' 15 | } 16 | }); 17 | 18 | type Props = { 19 | classes: Object, 20 | component: Object, 21 | webId: string, 22 | location: Object 23 | }; 24 | 25 | const PublicLayout = ({ 26 | classes, 27 | component: Component, 28 | webId, 29 | location, 30 | ...rest 31 | }: Props) => { 32 | return !webId ? ( 33 | ( 36 |
37 | 38 |
39 | )} 40 | /> 41 | ) : ( 42 | 45 | ); 46 | }; 47 | 48 | const mapStateToProps = state => { 49 | return { 50 | webId: state.user.webId 51 | }; 52 | }; 53 | 54 | export default connect(mapStateToProps)(withStyles(styles)(PublicLayout)); 55 | -------------------------------------------------------------------------------- /src/frontend/src/layouts/PublicLayout/index.js: -------------------------------------------------------------------------------- 1 | export default PublicLayout; 2 | import PublicLayout from './PublicLayout'; -------------------------------------------------------------------------------- /src/frontend/src/layouts/index.js: -------------------------------------------------------------------------------- 1 | import PrivateLayout from './PrivateLayout'; 2 | import PublicLayout from './PublicLayout'; 3 | 4 | export { PrivateLayout, PublicLayout }; 5 | -------------------------------------------------------------------------------- /src/frontend/src/storage/StorageSparqlClient.jsx: -------------------------------------------------------------------------------- 1 | import { StorageAuthenticationManager } from 'linkedpipes-storage'; 2 | 3 | class StorageSparqlClient { 4 | patchFileWithQuery = async (url, query) => { 5 | try { 6 | await StorageAuthenticationManager.fetch(url, { 7 | method: 'PATCH', 8 | body: query, 9 | headers: { 10 | 'Content-Type': 'application/sparql-update' 11 | } 12 | }); 13 | return true; 14 | } catch (error) { 15 | if (error instanceof Response && error.status === 404) return false; 16 | throw error; 17 | } 18 | }; 19 | } 20 | 21 | export default new StorageSparqlClient(); 22 | -------------------------------------------------------------------------------- /src/frontend/src/storage/components/index.js: -------------------------------------------------------------------------------- 1 | import StoragePickFolderDialog from './StoragePickFolderDialog'; 2 | import StorageAccessControlDialog from './StorageAccessControlDialog'; 3 | import StorageInboxDialog from './StorageInboxDialog'; 4 | 5 | export { 6 | StoragePickFolderDialog, 7 | StorageInboxDialog, 8 | StorageAccessControlDialog 9 | }; 10 | -------------------------------------------------------------------------------- /src/frontend/src/storage/containers/StoragePage/children/index.js: -------------------------------------------------------------------------------- 1 | import StorageAppsBrowserCardComponent from './StorageAppsBrowserCardComponent'; 2 | 3 | export { StorageAppsBrowserCardComponent }; 4 | -------------------------------------------------------------------------------- /src/frontend/src/storage/containers/StoragePage/index.js: -------------------------------------------------------------------------------- 1 | import StoragePage from './StoragePageController'; 2 | 3 | export default StoragePage; 4 | -------------------------------------------------------------------------------- /src/frontend/src/storage/containers/index.js: -------------------------------------------------------------------------------- 1 | import StoragePage from './StoragePage'; 2 | 3 | export { StoragePage }; 4 | -------------------------------------------------------------------------------- /src/frontend/src/storage/index.js: -------------------------------------------------------------------------------- 1 | // Containers 2 | import { StoragePage } from './containers'; 3 | // Components 4 | import { 5 | StoragePickFolderDialog, 6 | StorageAccessControlDialog, 7 | StorageInboxDialog 8 | } from './components'; 9 | // Utils 10 | import StorageToolbox from './StorageToolbox'; 11 | import StorageBackend from './StorageBackend'; 12 | import StorageSparqlClient from './StorageSparqlClient'; 13 | // Models 14 | import { ApplicationMetadata } from './models'; 15 | 16 | export { 17 | StoragePage, 18 | StoragePickFolderDialog, 19 | StorageAccessControlDialog, 20 | StorageToolbox, 21 | StorageSparqlClient, 22 | StorageBackend, 23 | ApplicationMetadata, 24 | StorageInboxDialog 25 | }; 26 | -------------------------------------------------------------------------------- /src/frontend/src/storage/models/AcceptedInvitation.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Model class for storing person's invitations. 3 | */ 4 | 5 | import Invitation from './Invitation'; 6 | import Person from './Person'; 7 | 8 | export default class AcceptedInvitation { 9 | senderWebId: string; 10 | 11 | sender: Person; 12 | 13 | recipientWebId: string; 14 | 15 | recipient: Person; 16 | 17 | invitation: Invitation; 18 | 19 | invitationUrl: string; 20 | 21 | constructor( 22 | sender: Person, 23 | recipient: Person, 24 | acceptedInvitation: Object, 25 | invitationUrl: string 26 | ) { 27 | this.sender = sender; 28 | this.recipient = recipient; 29 | this.senderWebId = acceptedInvitation.actor; 30 | this.recipientWebId = acceptedInvitation.target; 31 | this.invitation = new Invitation( 32 | recipient, 33 | sender, 34 | acceptedInvitation.object, 35 | undefined 36 | ); 37 | this.invitationUrl = invitationUrl; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/frontend/src/storage/models/AccessControl.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Model class for storing person's invitations. 3 | */ 4 | 5 | const ACL = term => { 6 | return `http://www.w3.org/ns/auth/acl#${term}`; 7 | }; 8 | 9 | export default class AccessControl { 10 | originalAccessControl: Object; 11 | 12 | owner: Object; 13 | 14 | public: Object; 15 | 16 | collaborators: Array; 17 | 18 | aclUrl; 19 | 20 | constructor(accessControl: Object, aclUrl: string) { 21 | this.originalAccessControl = accessControl; 22 | this.collaborators = []; 23 | this.aclUrl = aclUrl; 24 | 25 | const self = this; 26 | 27 | accessControl.forEach(element => { 28 | if (element['@id'] === `${aclUrl}#Read`) { 29 | self.public = ACL('agentClass') in element; 30 | } 31 | if (!self.collaborators.includes(element)) { 32 | self.collaborators.push(element); 33 | } 34 | }); 35 | } 36 | 37 | isPublic = (): boolean => { 38 | return this.public !== undefined; 39 | }; 40 | 41 | getCollaborators = (): Array => { 42 | const filteredCollaborators = this.collaborators.filter(object => { 43 | return ACL('agent') in object; 44 | }); 45 | return filteredCollaborators.map(object => { 46 | return object[ACL('agent')][0]['@id']; 47 | }); 48 | }; 49 | } 50 | -------------------------------------------------------------------------------- /src/frontend/src/storage/models/ApplicationMetadata.jsx: -------------------------------------------------------------------------------- 1 | import ApplicationConfiguration from './ApplicationConfiguration'; 2 | 3 | /** 4 | * Model class for storing application configuration. 5 | */ 6 | export default class ApplicationMetadata { 7 | solidFileTitle: string; 8 | 9 | solidFileUrl: string; 10 | 11 | configuration: ApplicationConfiguration; 12 | 13 | constructor({ solidFileTitle, solidFileUrl, configuration }) { 14 | this.solidFileTitle = solidFileTitle; 15 | this.solidFileUrl = solidFileUrl; 16 | this.configuration = 17 | configuration instanceof ApplicationConfiguration 18 | ? configuration 19 | : ApplicationConfiguration.from(configuration); 20 | } 21 | 22 | static from(json) { 23 | let jsonObject = json; 24 | 25 | if (typeof jsonObject === 'string' || jsonObject instanceof String) 26 | jsonObject = JSON.parse(json); 27 | 28 | return new ApplicationMetadata(jsonObject); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/frontend/src/storage/models/FilterConfiguration.jsx: -------------------------------------------------------------------------------- 1 | // /** 2 | // * Model class for storing application configuration. 3 | // */ 4 | // export default class FilterConfiguration { 5 | // type: string; 6 | 7 | // enabled: Boolean; 8 | 9 | // visible: Boolean; 10 | 11 | // filterGroups: 12 | 13 | // rawFilterConfiguration: 14 | 15 | // constructor( 16 | // rawFilterConfiguration: Object 17 | // ) { 18 | // this.type = type; 19 | // this.enabled = object; 20 | // this.title = title; 21 | // this.endpoint = endpoint; 22 | // this.creator = creator; 23 | // this.cardColor = cardColor; 24 | // this.createdAt = createdAt; 25 | // } 26 | // } 27 | -------------------------------------------------------------------------------- /src/frontend/src/storage/models/Invitation.jsx: -------------------------------------------------------------------------------- 1 | import Person from './Person'; 2 | 3 | /** 4 | * Model class for storing person's invitations. 5 | */ 6 | export default class Invitation { 7 | senderWebId: string; 8 | 9 | sender: Person; 10 | 11 | recipientWebId: string; 12 | 13 | recipient: Person; 14 | 15 | appMetadataUrl: string; 16 | 17 | object: Object; 18 | 19 | invitationUrl: string; 20 | 21 | constructor( 22 | sender: Person, 23 | recipient: Person, 24 | invitation: Object, 25 | invitationUrl: string 26 | ) { 27 | this.sender = sender; 28 | this.recipient = recipient; 29 | this.senderWebId = invitation.actor; 30 | this.recipientWebId = invitation.target; 31 | this.appMetadataUrl = invitation.object.href; 32 | this.object = invitation; 33 | this.invitationUrl = invitationUrl; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/frontend/src/storage/models/Person.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Model class for storing person's information. 3 | */ 4 | export default class Person { 5 | /** A WebID of the person. */ 6 | webId: string; 7 | 8 | /** Person's name. */ 9 | name: string; 10 | 11 | /** Person's profile image. */ 12 | image: string; 13 | 14 | constructor(webId: string, name: string, image: string) { 15 | this.webId = webId; 16 | this.name = name; 17 | this.image = image; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/frontend/src/storage/models/SharedApplicationConfiguration.jsx: -------------------------------------------------------------------------------- 1 | import ApplicationMetadata from './ApplicationMetadata'; 2 | 3 | /** 4 | * Model class for storing application configuration. 5 | */ 6 | export default class SharedApplicationConfiguration { 7 | /** Url to shared application metadata */ 8 | url: string; 9 | 10 | appMetadata: ApplicationMetadata; 11 | 12 | constructor( 13 | sharedAppConfiguration: Object, 14 | appMetadata: ApplicationMetadata 15 | ) { 16 | this.url = sharedAppConfiguration.url; 17 | this.appMetadata = appMetadata; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/frontend/src/storage/models/index.js: -------------------------------------------------------------------------------- 1 | import SharedApplicationConfiguration from './SharedApplicationConfiguration'; 2 | import ApplicationConfiguration from './ApplicationConfiguration'; 3 | import ApplicationMetadata from './ApplicationMetadata'; 4 | import Person from './Person'; 5 | import Invitation from './Invitation'; 6 | import AcceptedInvitation from './AcceptedInvitation'; 7 | import AccessControl from './AccessControl'; 8 | import { FileItem, FolderItem } from './Item'; 9 | 10 | export { 11 | AccessControl, 12 | SharedApplicationConfiguration, 13 | ApplicationConfiguration, 14 | ApplicationMetadata, 15 | AcceptedInvitation, 16 | Invitation, 17 | Person, 18 | FileItem, 19 | FolderItem 20 | }; 21 | -------------------------------------------------------------------------------- /src/frontend/src/storage/utils/index.js: -------------------------------------------------------------------------------- 1 | import Utils from './SolidUtils'; 2 | 3 | export { Utils }; 4 | -------------------------------------------------------------------------------- /src/frontend/src/store.jsx: -------------------------------------------------------------------------------- 1 | import { applyMiddleware, combineReducers, compose, createStore } from 'redux'; 2 | import logger from 'redux-logger'; 3 | import { discoveryReducer } from '@ducks/discoveryDuck'; 4 | import { globalReducer } from '@ducks/globalDuck'; 5 | import { etlReducer } from '@ducks/etlDuck'; 6 | import { userReducer } from '@ducks/userDuck'; 7 | import { applicationReducer } from '@ducks/applicationDuck'; 8 | import { filtersReducer } from '@ducks/filtersDuck'; 9 | import thunk from 'redux-thunk'; 10 | import { discoverReducer } from '@containers'; 11 | 12 | const composeEnhancers = 13 | // eslint-disable-next-line no-underscore-dangle 14 | typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ 15 | ? // eslint-disable-next-line no-underscore-dangle 16 | window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({ 17 | // Specify extenreadFolderion’s options like name, actionsBlacklist, 18 | // actionsCreators, serialize... 19 | }) 20 | : compose; 21 | 22 | const middlewares = [thunk, logger]; 23 | 24 | const enhancer = composeEnhancers(applyMiddleware(...middlewares)); 25 | 26 | const appReducer = combineReducers({ 27 | user: userReducer, 28 | globals: globalReducer, 29 | discover: discoverReducer, 30 | discovery: discoveryReducer, 31 | etl: etlReducer, 32 | application: applicationReducer, 33 | filters: filtersReducer 34 | }); 35 | 36 | const rootReducer = (state, action) => { 37 | if (action.type === 'USER_LOGOUT') { 38 | state = undefined; 39 | } 40 | 41 | return appReducer(state, action); 42 | }; 43 | 44 | const store = createStore(rootReducer, enhancer); 45 | export default () => store; 46 | -------------------------------------------------------------------------------- /src/frontend/src/utils/api.service.jsx: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import Log from './logger.service'; 3 | import * as Sentry from '@sentry/browser'; 4 | 5 | axios.defaults.baseURL = process.env.BASE_BACKEND_URL || '/api'; 6 | axios.defaults.headers.post['Content-Type'] = 'application/json'; 7 | 8 | axios.interceptors.request.use( 9 | config => { 10 | // Do something before request is sent 11 | 12 | Log.info(config, 'api.service'); 13 | return config; 14 | }, 15 | error => { 16 | // Do something with request error 17 | Log.info(error, 'api.service'); 18 | return Promise.reject(error); 19 | } 20 | ); 21 | 22 | axios.interceptors.response.use( 23 | response => { 24 | Log.info(response, 'api.service'); 25 | return response; 26 | }, 27 | error => { 28 | // handle error 29 | if (error.response) { 30 | Log.error(error.response.data, 'api.service'); 31 | Sentry.withScope(scope => { 32 | scope.setLevel('error'); 33 | scope.setExtra('api-call', error.response.data); 34 | Sentry.captureException(error); 35 | }); 36 | } 37 | 38 | return Promise.reject(error); 39 | } 40 | ); 41 | const wrappedAxios = axios; 42 | 43 | export default wrappedAxios; 44 | -------------------------------------------------------------------------------- /src/frontend/src/utils/authentication.utils.jsx: -------------------------------------------------------------------------------- 1 | import { StorageAuthenticationManager } from 'linkedpipes-storage'; 2 | 3 | const getWebIdIfSessionValid = async () => { 4 | return new Promise(async resolve => { 5 | const session = await StorageAuthenticationManager.currentSession(); 6 | 7 | if (!session) { 8 | resolve(undefined); 9 | } else { 10 | resolve(session.webId); 11 | } 12 | }); 13 | }; 14 | 15 | export default { 16 | getWebIdIfSessionValid 17 | }; 18 | -------------------------------------------------------------------------------- /src/frontend/src/utils/google-analytics-wrapper.jsx: -------------------------------------------------------------------------------- 1 | import GoogleAnalytics from 'react-ga'; 2 | 3 | const initialize = apiKey => { 4 | GoogleAnalytics.initialize(apiKey); 5 | }; 6 | 7 | const trackPage = page => { 8 | GoogleAnalytics.set({ 9 | page 10 | }); 11 | GoogleAnalytics.pageview(page); 12 | }; 13 | 14 | const trackEvent = eventData => { 15 | GoogleAnalytics.event(eventData); 16 | }; 17 | 18 | export default { 19 | initialize, 20 | trackPage, 21 | trackEvent 22 | }; 23 | -------------------------------------------------------------------------------- /src/frontend/src/utils/index.js: -------------------------------------------------------------------------------- 1 | import { VisualizersService } from './visualizers.service'; 2 | import DiscoveryService from './discovery.service'; 3 | import UserService from './user.service'; 4 | import { ETLService, ETL_STATUS_MAP, ETL_STATUS_TYPE } from './etl.service'; 5 | import GlobalUtils from './global.utils'; 6 | import SocketContext from './socket.service'; 7 | import Log from './logger.service'; 8 | import { withAuthorization } from './third-party'; 9 | import GoogleAnalyticsWrapper from './google-analytics-wrapper'; 10 | import AuthenticationService from './authentication.utils'; 11 | 12 | export { 13 | VisualizersService, 14 | DiscoveryService, 15 | UserService, 16 | SocketContext, 17 | ETLService, 18 | ETL_STATUS_MAP, 19 | ETL_STATUS_TYPE, 20 | Log, 21 | GlobalUtils, 22 | withAuthorization, 23 | GoogleAnalyticsWrapper, 24 | AuthenticationService 25 | }; 26 | -------------------------------------------------------------------------------- /src/frontend/src/utils/logger.service.jsx: -------------------------------------------------------------------------------- 1 | import debug from 'debug'; 2 | 3 | const BASE = 'lpapps'; 4 | const COLOURS = { 5 | trace: 'lightblue', 6 | info: 'blue', 7 | warn: 'pink', 8 | error: 'red' 9 | }; // choose better colours :) 10 | 11 | class Log { 12 | // eslint-disable-next-line 13 | generateMessage(level, message, source) { 14 | // Set the prefix which will cause debug to enable the message 15 | const namespace = `${BASE}:${level}`; 16 | const createDebug = debug(namespace); 17 | 18 | // Set the colour of the message based on the level 19 | createDebug.color = COLOURS[level]; 20 | 21 | if (source) { 22 | createDebug(source, message); 23 | } else { 24 | createDebug(message); 25 | } 26 | } 27 | 28 | trace(message, source) { 29 | return this.generateMessage('trace', message, source); 30 | } 31 | 32 | info(message, source) { 33 | return this.generateMessage('info', message, source); 34 | } 35 | 36 | warn(message, source) { 37 | return this.generateMessage('warn', message, source); 38 | } 39 | 40 | error(message, source) { 41 | return this.generateMessage('error', message, source); 42 | } 43 | } 44 | 45 | export default new Log(); 46 | -------------------------------------------------------------------------------- /src/frontend/src/utils/socket.service.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const SocketContext = React.createContext(); 4 | 5 | export default SocketContext; 6 | -------------------------------------------------------------------------------- /src/frontend/src/utils/third-party/index.js: -------------------------------------------------------------------------------- 1 | import { withAuthorization } from './with-authorization.component'; 2 | 3 | export { withAuthorization }; 4 | -------------------------------------------------------------------------------- /src/frontend/src/utils/third-party/with-authorization.component.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React from 'react'; 3 | import { Redirect } from 'react-router-dom'; 4 | import { connect } from 'react-redux'; 5 | 6 | const mapStateToProps = state => { 7 | return { 8 | webId: state.user.webId 9 | }; 10 | }; 11 | 12 | export const withAuthorization = (Component, Loader) => 13 | connect(mapStateToProps)( 14 | class WithAuthorization extends React.Component { 15 | render() { 16 | switch (this.props.webId) { 17 | case undefined: 18 | return ( 19 | Loader || ( 20 | 26 | ) 27 | ); 28 | case null: 29 | return ( 30 | 36 | ); 37 | default: 38 | return ; 39 | } 40 | } 41 | } 42 | ); 43 | -------------------------------------------------------------------------------- /src/frontend/src/utils/user.service.jsx: -------------------------------------------------------------------------------- 1 | import lpaAxios from './api.service'; 2 | 3 | const UserService = { 4 | getUserProfile(webIdValue) { 5 | return lpaAxios.post('/user', null, { params: { webId: webIdValue } }); 6 | }, 7 | 8 | deleteDiscovery(webId, discoveryId, socketId) { 9 | return lpaAxios.delete('/user/discovery', { 10 | params: { webId, discoveryId, socketId } 11 | }); 12 | }, 13 | 14 | deletePipelineExecution(webId, executionIri, socketId) { 15 | return lpaAxios.delete('/user/execution', { 16 | params: { webId, executionIri, socketId } 17 | }); 18 | }, 19 | 20 | postApplication(webId, solidIri, executionIri) { 21 | return lpaAxios.post('/user/application', null, { 22 | params: { webId, solidIri, executionIri } 23 | }); 24 | }, 25 | 26 | deleteApplication(webId, solidIri) { 27 | return lpaAxios.delete('/user/application', { 28 | params: { webId, solidIri } 29 | }); 30 | }, 31 | 32 | setColorTheme(webId, colorSchemeIsLight) { 33 | return lpaAxios.post('/user/color', null, { 34 | params: { webId, color: colorSchemeIsLight ? 'WHITE' : 'BLACK' } 35 | }); 36 | } 37 | }; 38 | 39 | export default UserService; 40 | -------------------------------------------------------------------------------- /src/frontend/src/wrapper.js: -------------------------------------------------------------------------------- 1 | // @flow 2 | import * as React from 'react'; 3 | import { Provider } from 'react-redux'; 4 | import withRoot from './withRoot'; 5 | import store from './store'; 6 | import { BrowserRouter as Router } from 'react-router-dom'; 7 | import { SocketContext } from '@utils'; 8 | 9 | const myStore = store(); 10 | 11 | type Props = { 12 | children: any 13 | }; 14 | 15 | // eslint-disable-next-line prefer-const 16 | let socket = {}; 17 | 18 | const Wrapper = withRoot(({ children }: Props) => ( 19 | // eslint-disable-next-line react/jsx-filename-extension 20 | 21 | 22 | {children} 23 | 24 | 25 | )); 26 | 27 | export default Wrapper; 28 | -------------------------------------------------------------------------------- /src/tests/requirements.txt: -------------------------------------------------------------------------------- 1 | astroid==2.2.5 2 | autopep8==1.4.3 3 | certifi==2019.3.9 4 | chardet==3.0.4 5 | colorama==0.4.1 6 | configparser==3.7.4 7 | crayons==0.2.0 8 | idna==2.8 9 | isort==4.3.17 10 | lazy-object-proxy==1.3.1 11 | mccabe==0.6.1 12 | pycodestyle==2.5.0 13 | pylint==2.3.1 14 | requests==2.21.0 15 | selenium==3.141.0 16 | six==1.12.0 17 | slackclient==1.3.1 18 | speedtest-cli==2.1.1 19 | typed-ast==1.3.1 20 | urllib3==1.25 21 | webdriver-manager==1.7 22 | websocket-client==0.54.0 23 | wrapt==1.11.1 24 | --------------------------------------------------------------------------------