From 3dc87973605320e197f8e12d829ff1a6097ac395 Mon Sep 17 00:00:00 2001 From: vvancak Date: Thu, 23 Feb 2017 18:57:09 +0100 Subject: [PATCH 01/84] EventTimeline : Server-side skeleton --- .../javascripts/entries/eventTimeline.js | 4 +++ .../eventTimeline/applicationRoutes.js | 16 ++++++++++ .../eventTimeline/components/Application.js | 26 ++++++++++++++++ .../eventTimeline/configuratorRoutes.js | 10 ++++++ .../eventTimeline/pages/Configurator.js | 24 ++++++++++++++ .../visualizers/eventTimeline/pages/Embed.js | 4 +++ .../eventTimeline/pages/Standalone.js | 12 +++++++ .../visualizers/eventTimeline/prefix.js | 4 +++ .../javascripts/modules/visualizers/routes.js | 2 ++ src/app/controllers/api/package.scala | 3 +- ...EventTimelineVisualizerApiController.scala | 20 ++++++++++++ src/app/model/rdf/sparql/rgml/Event.scala | 4 +++ src/app/model/rdf/sparql/rgml/Person.scala | 3 ++ .../model/rdf/sparql/rgml/RgmlService.scala | 1 + .../rdf/sparql/rgml/RgmlServiceImpl.scala | 7 +++++ .../rgml/extractor/EventExtractor.scala | 31 +++++++++++++++++++ .../sparql/rgml/query/EventPeopleQuery.scala | 26 ++++++++++++++++ .../rdf/sparql/rgml/query/EventQuery.scala | 27 ++++++++++++++++ src/app/model/rdf/vocabulary/SCHEMA.scala | 4 +++ 19 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/applicationRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/components/Application.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/configuratorRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Configurator.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Embed.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Standalone.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/prefix.js create mode 100644 src/app/controllers/assistant/api/visualizers/EventTimelineVisualizerApiController.scala create mode 100644 src/app/model/rdf/sparql/rgml/Event.scala create mode 100644 src/app/model/rdf/sparql/rgml/Person.scala create mode 100644 src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala create mode 100644 src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala create mode 100644 src/app/model/rdf/sparql/rgml/query/EventQuery.scala diff --git a/src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js b/src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js new file mode 100644 index 00000000..7854d4f8 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js @@ -0,0 +1,4 @@ +import createRoutes from '../modules/visualizers/eventTimeline/applicationRoutes' +import initEntry from '../misc/initEntry' + +initEntry(createRoutes); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/applicationRoutes.js new file mode 100644 index 00000000..70727287 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/applicationRoutes.js @@ -0,0 +1,16 @@ +import React from 'react' +import { Route, IndexRoute } from 'react-router' +import ApplicationLoader from '../../app/pages/ApplicationLoader' +import NotFound from '../../platform/pages/NotFound' +import Standalone from './pages/Standalone' +import Embed from './pages/Embed' + +export default function createRoutes(dispatch) { + return ( + + + + + + ); +} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/components/Application.js new file mode 100644 index 00000000..5a071753 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/components/Application.js @@ -0,0 +1,26 @@ +import React, { Component, PropTypes } from 'react' +import BodyPadding from '../../../../components/BodyPadding' +import { Application as ApplicationModel } from '../../../app/models' +import { Visualizer } from '../../../core/models' + +class Application extends Component { + static propTypes = { + application: PropTypes.instanceOf(ApplicationModel).isRequired, + visualizer: PropTypes.instanceOf(Visualizer).isRequired, + embed: PropTypes.bool + }; + + render() { + const { application, visualizer, embed } = this.props; + return ( + +

This is the graph visualizer application.

+

It runs in {embed ? 'embed' : 'standalone'} mode

+

{application.name}

+

{visualizer.title}

+
+ ) + } +} + +export default Application; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/configuratorRoutes.js new file mode 100644 index 00000000..c0206cd2 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/configuratorRoutes.js @@ -0,0 +1,10 @@ +import React from 'react' +import { Route } from 'react-router' +import Configurator from './pages/Configurator' +import { MODULE_PREFIX } from './prefix' + +export default function createRoutes(dispatch) { + return ( + + ); +} diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Configurator.js new file mode 100644 index 00000000..75c3ae3e --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Configurator.js @@ -0,0 +1,24 @@ +import React, { Component, PropTypes } from 'react' +import BodyPadding from '../../../../components/BodyPadding' +import { Application } from '../../../app/models' +import { Visualizer } from '../../../core/models' + +class Configurator extends Component { + static propTypes = { + application: PropTypes.instanceOf(Application).isRequired, + visualizer: PropTypes.instanceOf(Visualizer).isRequired + }; + + render() { + const { application, visualizer } = this.props; + return ( + +

This is the graph visualizer configurator.

+

{application.name}

+

{visualizer.title}

+
+ ) + } +} + +export default Configurator; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Embed.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Embed.js new file mode 100644 index 00000000..c699776d --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Embed.js @@ -0,0 +1,4 @@ +import React from 'react' +import Application from '../components/Application' + +export default props => diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Standalone.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Standalone.js new file mode 100644 index 00000000..ffa6be24 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Standalone.js @@ -0,0 +1,12 @@ +import React, { PropTypes } from 'react' +import Application from '../components/Application' +import ApplicationHeader from '../../../app/components/ApplicationHeader' + +const Standalone = props => ( +
+ + +
+); + +export default Standalone; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/prefix.js new file mode 100644 index 00000000..5cc83669 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/prefix.js @@ -0,0 +1,4 @@ +import createPrefixer from '../../../misc/createPrefixer' + +export const MODULE_PREFIX = 'eventTimeline'; +export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js index 201c205a..8d5681ed 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js @@ -4,6 +4,7 @@ import ConfiguratorsRouteFactory from './utils/ConfiguratorsRouteFactory' import dataCubeRoutes from './datacube/configuratorRoutes' import googleMapsRoutes from './googleMaps/configuratorRoutes' import chordRoutes from './chord/configuratorRoutes' +import eventTimelineRoutes from './eventTimeline/configuratorRoutes' import { Visualizer, VisualizerWithPipelines } from '../core/models' import { applicationUrl } from '../app/configuratorRoutes' @@ -14,6 +15,7 @@ const routeFactory = new ConfiguratorsRouteFactory(); routeFactory.register(dataCubeRoutes); routeFactory.register(googleMapsRoutes); routeFactory.register(chordRoutes); +routeFactory.register(eventTimelineRoutes); export default dispatch => routeFactory.createRoutes(dispatch); diff --git a/src/app/controllers/api/package.scala b/src/app/controllers/api/package.scala index f43748c2..45bb3156 100644 --- a/src/app/controllers/api/package.scala +++ b/src/app/controllers/api/package.scala @@ -4,7 +4,7 @@ import akka.actor.Props import model.actor.CheckCompatibilityResponse import model.entity._ import model.rdf.sparql.ValueFilter -import model.rdf.sparql.rgml.{Edge, Graph, Node, NodeWithDegree} +import model.rdf.sparql.rgml._ import model.rdf.sparql.datacube._ import model.rdf.sparql.fresnel.{Lens, ResourceThroughLens} import model.rdf.sparql.geo._ @@ -106,6 +106,7 @@ package object api { implicit val edgeWrites = Json.writes[Edge] implicit val lensWrites = Json.writes[Lens] implicit val resourceThroughLensWrites = Json.writes[ResourceThroughLens] + implicit val eventsWrites = Json.writes[Event] val filterPath = (JsPath \ "label").readNullable[String] and (JsPath \ "dataType").readNullable[String] and diff --git a/src/app/controllers/assistant/api/visualizers/EventTimelineVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/EventTimelineVisualizerApiController.scala new file mode 100644 index 00000000..2eff2f68 --- /dev/null +++ b/src/app/controllers/assistant/api/visualizers/EventTimelineVisualizerApiController.scala @@ -0,0 +1,20 @@ +package controllers.assistant.api.visualizers + +import scala.concurrent.Future +import model.assistant.entity.ApplicationId +import model.assistant.rest.EmptyRequest.EmptyRequest +import model.assistant.rest.Response._ +import model.rdf.sparql.rgml.RgmlService +import controllers.api.JsonImplicits._ +import scaldi.Injector + +class EventTimelineVisualizerApiController(implicit inj: Injector) extends VisualizerApiController { + val rgmlService = inject[RgmlService] + + def getEvents(id: Long) = RestAsyncAction[EmptyRequest] { implicit request => json => + withEvaluation(ApplicationId(id)) { evaluation => + val events = rgmlService.events(evaluation) + Future(Ok(SuccessResponse(data = Seq("events"->events)))) + } + } +} \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/Event.scala b/src/app/model/rdf/sparql/rgml/Event.scala new file mode 100644 index 00000000..9654bbd0 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/Event.scala @@ -0,0 +1,4 @@ +package model.rdf.sparql.rgml +import org.joda.time.DateTime + +case class Event(url:String,name:String,start:DateTime,end:DateTime,info:String) diff --git a/src/app/model/rdf/sparql/rgml/Person.scala b/src/app/model/rdf/sparql/rgml/Person.scala new file mode 100644 index 00000000..565ad2ac --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/Person.scala @@ -0,0 +1,3 @@ +package model.rdf.sparql.rgml + +case class Person (name:String,info:String) //TODO : Use this in EventExtractor in List diff --git a/src/app/model/rdf/sparql/rgml/RgmlService.scala b/src/app/model/rdf/sparql/rgml/RgmlService.scala index 8e32fa78..8cc0d0be 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlService.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlService.scala @@ -16,4 +16,5 @@ trait RgmlService { def adjacentNodes(evaluation: PipelineEvaluation, nodeUri: String, direction: Option[EdgeDirection] = None)(implicit session: Session): Option[Seq[Node]] def sampleNodesByHighestDegree(evaluation: PipelineEvaluation, size: Int)(implicit session: Session): Option[Seq[Node]] def sampleNodesWithForestFire( evaluation: PipelineEvaluation, size: Int, useWeights: Boolean = true, pF: Double = 0.2, pB: Double = 0.05)(implicit session: Session): Option[Seq[Node]] + def events(evaluation: PipelineEvaluation)(implicit session: Session): Option[Seq[Event]] } diff --git a/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala b/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala index 5049f34f..c88880eb 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala @@ -411,4 +411,11 @@ class RgmlServiceImpl(implicit val inj: Injector) extends RgmlService with Injec // As the sample consists of just node URIs, we fetch the actual resources (with labels) nodes(evaluation, makeSample) } + + def events(evaluation: PipelineEvaluation)(implicit session: Session): Option[Seq[Event]] = { + sparqlEndpointService.getResult( + evaluationToSparqlEndpoint(evaluation), + new EventQuery(), + new EventExtractor()) + } } diff --git a/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala new file mode 100644 index 00000000..ff3605c9 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala @@ -0,0 +1,31 @@ +package model.rdf.sparql.rgml.extractor + +import model.rdf.extractor.QueryExecutionResultExtractor +import model.rdf.sparql.rgml.Event +import model.rdf.sparql.rgml.query.EventQuery +import org.apache.jena.query.QueryExecution +import org.joda.time.DateTime + +import scala.collection.JavaConversions._ + + +class EventExtractor extends QueryExecutionResultExtractor[EventQuery, Seq[Event]] { + + def extract(input: QueryExecution): Option[Seq[Event]] = { + try { + val resList = input.execSelect().toList + Some(resList.map(e => Event( + e.getLiteral("event").toString(), + e.getLiteral("eventName").toString(), + DateTime.parse(e.getLiteral("start").toString()), + DateTime.parse(e.getLiteral("end").toString()), + e.getLiteral("eventInfo").toString() + ))) + } + catch { + case e: org.apache.jena.sparql.engine.http.QueryExceptionHTTP => { + None + } + } + } +} \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala new file mode 100644 index 00000000..0075c0ac --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala @@ -0,0 +1,26 @@ +package model.rdf.sparql.rgml.query +import model.rdf.sparql.query.SparqlQuery + +class EventPeopleQuery(events: Seq[String]) extends SparqlQuery { + def get: String = { + val eventUris = events.map(e => "<" + e + ">").mkString(" ") + """ + |PREFIX rdf: + |PREFIX sch: + |PREFIX dbo: + |PREFIX foaf: + | + |SELECT DISTINCT ?person ?personName ?personInfo ?event WHERE { + | ?event rdf:type sch:Event ; + | VALUES ?event { @eventUrls } + | ?person rdf:type sch:Person ; + | foaf:name ?personName ; + | foaf:isPrimaryTopicOf ?personInfo . + | + | FILTER EXISTS { ?event ?relation ?person } + |} + """ + .stripMargin + .replace("@eventUrls", eventUris) + } +} \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/query/EventQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventQuery.scala new file mode 100644 index 00000000..8c6917ae --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/query/EventQuery.scala @@ -0,0 +1,27 @@ +package model.rdf.sparql.rgml.query +import model.rdf.sparql.query.SparqlQuery + +class EventQuery extends SparqlQuery{ + def get: String = + """ + |PREFIX rdf: + |PREFIX sch: + |PREFIX dbo: + |PREFIX foaf: + | + |SELECT DISTINCT ?event ?eventName ?start ?end ?eventLink WHERE { + | ?event rdf:type sch:Event ; + | foaf:name ?eventName ; + | dbo:startDate ?start ; + | dbo:endDate ?end ; + | dbo:wikiPageExternalLink ?eventLink . + | + | ?person rdf:type sch:Person ; + | foaf:name ?personName ; + | foaf:isPrimaryTopicOf ?personLink . + | + | FILTER EXISTS { ?event ?relation ?person } + |} LIMIT 100 + """ + .stripMargin +} diff --git a/src/app/model/rdf/vocabulary/SCHEMA.scala b/src/app/model/rdf/vocabulary/SCHEMA.scala index 6df648d9..5e5ddaf5 100644 --- a/src/app/model/rdf/vocabulary/SCHEMA.scala +++ b/src/app/model/rdf/vocabulary/SCHEMA.scala @@ -1,8 +1,12 @@ package model.rdf.vocabulary +import org.apache.jena.rdf.model.Resource + object SCHEMA extends Vocabulary { override val PREFIX = "schema" override val PREFIX_URL = "http://schema.org/" + lazy val Event: Resource = m.createResource(PREFIX_URL + "Event") + lazy val Person: Resource = m.createResource(PREFIX_URL + "Person") } From 2c912138c231ffd1a660329f5aa87d230d470208 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sun, 26 Feb 2017 20:08:03 +0100 Subject: [PATCH 02/84] EventTimeline : Client-side skeleton --- .../modules/visualizers/eventTimeline/api.js | 6 +++ .../eventTimeline/components/Application.js | 5 +- .../eventTimeline/containers/EventLoader.js | 50 ++++++++++++++++++ .../eventTimeline/containers/SaveButton.js | 7 +++ .../eventTimeline/ducks/configuration.js | 37 +++++++++++++ .../visualizers/eventTimeline/ducks/dirty.js | 13 +++++ .../visualizers/eventTimeline/ducks/event.js | 52 +++++++++++++++++++ .../visualizers/eventTimeline/models.js | 11 ++++ .../eventTimeline/pages/Configurator.js | 18 +++++++ .../visualizers/eventTimeline/reducer.js | 8 +++ .../visualizers/eventTimeline/selector.js | 9 ++++ .../modules/visualizers/reducer.js | 6 ++- src/app/controllers/api/package.scala | 2 +- ...EventTimelineVisualizerApiController.scala | 9 ++-- 14 files changed, 225 insertions(+), 8 deletions(-) create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/api.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/EventLoader.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/SaveButton.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/configuration.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/dirty.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/event.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/models.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/reducer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/selector.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/api.js new file mode 100644 index 00000000..38484e2b --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/api.js @@ -0,0 +1,6 @@ +import rest from '../../../misc/rest' + +export async function getEvent(applicationId) { + const result = await rest('graphVisualizer/getEvent/' + applicationId, {}); + return result.data.event; +} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/components/Application.js index 5a071753..95843942 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/components/Application.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/components/Application.js @@ -2,6 +2,7 @@ import React, { Component, PropTypes } from 'react' import BodyPadding from '../../../../components/BodyPadding' import { Application as ApplicationModel } from '../../../app/models' import { Visualizer } from '../../../core/models' +import { EventLoader } from '../containers/EventLoader' class Application extends Component { static propTypes = { @@ -10,14 +11,16 @@ class Application extends Component { embed: PropTypes.bool }; + render() { const { application, visualizer, embed } = this.props; return ( -

This is the graph visualizer application.

+

This is the event visualizer application.

It runs in {embed ? 'embed' : 'standalone'} mode

{application.name}

{visualizer.title}

+
) } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/EventLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/EventLoader.js new file mode 100644 index 00000000..81fa2ce0 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/EventLoader.js @@ -0,0 +1,50 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from 'reselect' +import { getEvent, getEventReset, eventSelector, eventStatusSelector } from '../ducks/event' +import { PromiseStatus } from '../../../core/models' +import { Event } from '../models' + + +class EventLoader extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + event: PropTypes.instanceOf(Event).isRequired, + status: PropTypes.instanceOf(PromiseStatus).isRequired + }; + + componentWillMount() { + const {dispatch} = this.props; + dispatch(getEvent()); + } + + componentWillUnmount() { + const {dispatch} = this.props; + dispatch(getEventReset()); + } + + render() { + const {event, status} = this.props; + + if (!status.done) { + return + } + + return ( +
+

Graph info

+

Event info: {event.info }

+

Event name: {event.name}

+

Start : {event.start}

+

End: {event.end}

+
+ ) + } +} + +const selector = createStructuredSelector({ + event: eventSelector, + status: eventStatusSelector +}); + +export default connect(selector)(EventLoader); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/SaveButton.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/SaveButton.js new file mode 100644 index 00000000..f03f11f8 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/SaveButton.js @@ -0,0 +1,7 @@ +import React, { PropTypes } from 'react' +import { saveConfiguration, saveConfigurationStatusSelector } from '../ducks/configuration' +import { dirtySelector } from '../ducks/dirty' + +import createSaveButton from '../../../app/containers/createSaveButton' + +export default createSaveButton(saveConfiguration, saveConfigurationStatusSelector, dirtySelector); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/configuration.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/configuration.js new file mode 100644 index 00000000..ff3e039f --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/configuration.js @@ -0,0 +1,37 @@ +import prefix from '../prefix' +import moduleSelector from '../selector' +import { createPromiseStatusSelector } from '../../../core/ducks/promises' +import { + createGetConfiguration, createGetConfigurationReset, createSaveConfiguration +} from '../../../app/ducks/configuration' + +// Actions + +export const SAVE_CONFIGURATION = prefix('SAVE_CONFIGURATION'); +export const SAVE_CONFIGURATION_START = SAVE_CONFIGURATION + '_START'; +export const SAVE_CONFIGURATION_ERROR = SAVE_CONFIGURATION + '_ERROR'; +export const SAVE_CONFIGURATION_SUCCESS = SAVE_CONFIGURATION + '_SUCCESS'; + +export const GET_CONFIGURATION = prefix('GET_CONFIGURATION'); +export const GET_CONFIGURATION_START = GET_CONFIGURATION + '_START'; +export const GET_CONFIGURATION_ERROR = GET_CONFIGURATION + '_ERROR'; +export const GET_CONFIGURATION_SUCCESS = GET_CONFIGURATION + '_SUCCESS'; +export const GET_CONFIGURATION_RESET = GET_CONFIGURATION + '_RESET'; + +// Selectors + +export const saveConfigurationStatusSelector = createPromiseStatusSelector(SAVE_CONFIGURATION); +export const getConfigurationStatusSelector = createPromiseStatusSelector(GET_CONFIGURATION); + +export const configurationSelector = createSelector( + [moduleSelector], + state => ({ }) +); + +// Actual actions created using factories +export const saveConfiguration = + createSaveConfiguration(SAVE_CONFIGURATION, configurationSelector); +export const getConfiguration = + createGetConfiguration(GET_CONFIGURATION); +export const getConfigurationReset = + createGetConfigurationReset(GET_CONFIGURATION_RESET); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/dirty.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/dirty.js new file mode 100644 index 00000000..ae5d4042 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/dirty.js @@ -0,0 +1,13 @@ +import { createSelector } from 'reselect' +import moduleSelector from '../selector' +import { createDirtyReducer } from '../../../app/ducks/dirty' + +// Reducer + +const actions = [ ]; + +export default createDirtyReducer(actions); + +// Selectors + +export const dirtySelector = createSelector([moduleSelector], state => state.dirty); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/event.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/event.js new file mode 100644 index 00000000..4e2d69c2 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/event.js @@ -0,0 +1,52 @@ +import createAction from '../../../../misc/createAction' +import withApplicationId from '../../../app/misc/withApplicationId' +import prefix from '../prefix' +import * as api from '../api' + +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { Event } from '../models' + +import { createSelector } from 'reselect' +import { createPromiseStatusSelector } from '../../../core/ducks/promises' +import moduleSelector from '../selector' + +// Actions + +export const GET_EVENT = prefix('GET_GRAPH'); +export const GET_EVENT_START = GET_EVENT + '_START'; +export const GET_EVENT_ERROR = GET_EVENT + '_ERROR'; +export const GET_EVENT_SUCCESS = GET_EVENT + '_SUCCESS'; +export const GET_EVENT_RESET = GET_EVENT + '_RESET'; + +export function getEvent() { + return withApplicationId(id => { + const promise = api.getEvent(id); + return createAction(GET_EVENT, { promise }); + }) +} + +export function getEventReset() { + return createAction(GET_EVENT_RESET); +} + +// Reducer + +const initialState = new Event(); + +export default function eventReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + case GET_EVENT_RESET: + return initialState; + + case GET_EVENT_SUCCESS: + return new Event(action.payload); + } + + return state; +}; + +// Selectors + +export const eventStatusSelector = createPromiseStatusSelector(GET_EVENT); +export const eventSelector = createSelector([moduleSelector], state => state.event); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/models.js new file mode 100644 index 00000000..2ab04749 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/models.js @@ -0,0 +1,11 @@ +import { Record } from 'immutable'; + +export const Event = Record({ + url: "Event url", + name: "Event name", + start: date("1.1.2000"), + end: date("1.1.2000"), + info: "Event info" +}); + + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Configurator.js index 75c3ae3e..d2a7975f 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Configurator.js @@ -2,6 +2,11 @@ import React, { Component, PropTypes } from 'react' import BodyPadding from '../../../../components/BodyPadding' import { Application } from '../../../app/models' import { Visualizer } from '../../../core/models' +import { EventLoader } from '../containers/EventLoader' +import { getConfiguration, getConfigurationReset } from '../ducks/configuration' +import EditableLabel from '../../../app/containers/EditableLabel' +import SaveButton from '../containers/SaveButton' + class Configurator extends Component { static propTypes = { @@ -16,9 +21,22 @@ class Configurator extends Component {

This is the graph visualizer configurator.

{application.name}

{visualizer.title}

+ + + ) } + + componentWillMount() { + const { dispatch } = this.props; + dispatch(getConfiguration()); + } + + componentWillUnmount() { + const { dispatch } = this.props; + dispatch(getConfigurationReset()); + } } export default Configurator; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/reducer.js new file mode 100644 index 00000000..1627ff32 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/reducer.js @@ -0,0 +1,8 @@ +import { combineReducers } from 'redux'; +import event from './ducks/event' + +const rootReducer = combineReducers({ + event +}); + +export default rootReducer; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/selector.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/selector.js new file mode 100644 index 00000000..0019b8e7 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/selector.js @@ -0,0 +1,9 @@ +import { createSelector } from 'reselect' +import parentSelector from '../selector' +import { MODULE_PREFIX } from './prefix' + +export const moduleSelector = createSelector( + [parentSelector], + parentState => parentState[MODULE_PREFIX] +); +export default moduleSelector; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js index 38aa3cc2..4ad415d0 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js @@ -1,9 +1,11 @@ import { combineReducers } from 'redux'; import googleMaps from './googleMaps/reducer' import chord from './chord/reducer' +import eventTimeline from './eventTimeline/reducer' const rootReducer = combineReducers({ - googleMaps, - chord + googleMaps, + chord, + eventTimeline }); export default rootReducer; \ No newline at end of file diff --git a/src/app/controllers/api/package.scala b/src/app/controllers/api/package.scala index 45bb3156..257d65ca 100644 --- a/src/app/controllers/api/package.scala +++ b/src/app/controllers/api/package.scala @@ -106,7 +106,7 @@ package object api { implicit val edgeWrites = Json.writes[Edge] implicit val lensWrites = Json.writes[Lens] implicit val resourceThroughLensWrites = Json.writes[ResourceThroughLens] - implicit val eventsWrites = Json.writes[Event] + implicit val eventWrites = Json.writes[Event] val filterPath = (JsPath \ "label").readNullable[String] and (JsPath \ "dataType").readNullable[String] and diff --git a/src/app/controllers/assistant/api/visualizers/EventTimelineVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/EventTimelineVisualizerApiController.scala index 2eff2f68..b6e231a8 100644 --- a/src/app/controllers/assistant/api/visualizers/EventTimelineVisualizerApiController.scala +++ b/src/app/controllers/assistant/api/visualizers/EventTimelineVisualizerApiController.scala @@ -6,15 +6,16 @@ import model.assistant.rest.EmptyRequest.EmptyRequest import model.assistant.rest.Response._ import model.rdf.sparql.rgml.RgmlService import controllers.api.JsonImplicits._ +import play.api.libs.concurrent.Execution.Implicits._ import scaldi.Injector class EventTimelineVisualizerApiController(implicit inj: Injector) extends VisualizerApiController { val rgmlService = inject[RgmlService] def getEvents(id: Long) = RestAsyncAction[EmptyRequest] { implicit request => json => - withEvaluation(ApplicationId(id)) { evaluation => - val events = rgmlService.events(evaluation) - Future(Ok(SuccessResponse(data = Seq("events"->events)))) - } + withEvaluation(ApplicationId(id)) { evaluation => + val events = rgmlService.events(evaluation) + Future(Ok(SuccessResponse(data = Seq("events" -> events)))) } + } } \ No newline at end of file From 188f8bbecb145854e1d06555343e1042927f8f3d Mon Sep 17 00:00:00 2001 From: vvancak Date: Thu, 9 Mar 2017 16:06:44 +0100 Subject: [PATCH 03/84] EventTimeline: Server-side event people extraction --- src/app/controllers/api/package.scala | 1 + ...ala => EventVisualizerApiController.scala} | 9 ++++++- .../assistant/rest/EventPeopleRequest.scala | 9 +++++++ src/app/model/rdf/sparql/rgml/Person.scala | 2 +- .../model/rdf/sparql/rgml/RgmlService.scala | 1 + .../rdf/sparql/rgml/RgmlServiceImpl.scala | 7 +++++ .../rgml/extractor/EventExtractor.scala | 1 - .../rgml/extractor/PersonExtractor.scala | 26 +++++++++++++++++++ .../sparql/rgml/query/EventPeopleQuery.scala | 9 +++---- 9 files changed, 57 insertions(+), 8 deletions(-) rename src/app/controllers/assistant/api/visualizers/{EventTimelineVisualizerApiController.scala => EventVisualizerApiController.scala} (60%) create mode 100644 src/app/model/assistant/rest/EventPeopleRequest.scala create mode 100644 src/app/model/rdf/sparql/rgml/extractor/PersonExtractor.scala diff --git a/src/app/controllers/api/package.scala b/src/app/controllers/api/package.scala index 257d65ca..95630b0f 100644 --- a/src/app/controllers/api/package.scala +++ b/src/app/controllers/api/package.scala @@ -107,6 +107,7 @@ package object api { implicit val lensWrites = Json.writes[Lens] implicit val resourceThroughLensWrites = Json.writes[ResourceThroughLens] implicit val eventWrites = Json.writes[Event] + implicit val personWrites = Json.writes[Person] val filterPath = (JsPath \ "label").readNullable[String] and (JsPath \ "dataType").readNullable[String] and diff --git a/src/app/controllers/assistant/api/visualizers/EventTimelineVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala similarity index 60% rename from src/app/controllers/assistant/api/visualizers/EventTimelineVisualizerApiController.scala rename to src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala index b6e231a8..8a702ec8 100644 --- a/src/app/controllers/assistant/api/visualizers/EventTimelineVisualizerApiController.scala +++ b/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala @@ -6,10 +6,11 @@ import model.assistant.rest.EmptyRequest.EmptyRequest import model.assistant.rest.Response._ import model.rdf.sparql.rgml.RgmlService import controllers.api.JsonImplicits._ +import model.assistant.rest.EventPeopleRequest.EventPeopleRequest import play.api.libs.concurrent.Execution.Implicits._ import scaldi.Injector -class EventTimelineVisualizerApiController(implicit inj: Injector) extends VisualizerApiController { +class EventVisualizerApiController(implicit inj: Injector) extends VisualizerApiController { val rgmlService = inject[RgmlService] def getEvents(id: Long) = RestAsyncAction[EmptyRequest] { implicit request => json => @@ -18,4 +19,10 @@ class EventTimelineVisualizerApiController(implicit inj: Injector) extends Visua Future(Ok(SuccessResponse(data = Seq("events" -> events)))) } } + def getEventPeople(id: Long) = RestAsyncAction[EventPeopleRequest] { implicit request => json => + withEvaluation(ApplicationId(id)) { evaluation => + var people = rgmlService.eventPeople(evaluation, json.event) + Future(Ok(SuccessResponse(data = Seq("people" -> people)))) + } + } } \ No newline at end of file diff --git a/src/app/model/assistant/rest/EventPeopleRequest.scala b/src/app/model/assistant/rest/EventPeopleRequest.scala new file mode 100644 index 00000000..334f8a39 --- /dev/null +++ b/src/app/model/assistant/rest/EventPeopleRequest.scala @@ -0,0 +1,9 @@ +package model.assistant.rest + +import play.api.libs.json.Json + +object EventPeopleRequest { + case class EventPeopleRequest(event: String) + implicit val writes = Json.writes[EventPeopleRequest] + implicit val reads = Json.reads[EventPeopleRequest] +} diff --git a/src/app/model/rdf/sparql/rgml/Person.scala b/src/app/model/rdf/sparql/rgml/Person.scala index 565ad2ac..9c826922 100644 --- a/src/app/model/rdf/sparql/rgml/Person.scala +++ b/src/app/model/rdf/sparql/rgml/Person.scala @@ -1,3 +1,3 @@ package model.rdf.sparql.rgml -case class Person (name:String,info:String) //TODO : Use this in EventExtractor in List +case class Person (url:String, name:String,info:String) diff --git a/src/app/model/rdf/sparql/rgml/RgmlService.scala b/src/app/model/rdf/sparql/rgml/RgmlService.scala index 8cc0d0be..03e69af4 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlService.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlService.scala @@ -17,4 +17,5 @@ trait RgmlService { def sampleNodesByHighestDegree(evaluation: PipelineEvaluation, size: Int)(implicit session: Session): Option[Seq[Node]] def sampleNodesWithForestFire( evaluation: PipelineEvaluation, size: Int, useWeights: Boolean = true, pF: Double = 0.2, pB: Double = 0.05)(implicit session: Session): Option[Seq[Node]] def events(evaluation: PipelineEvaluation)(implicit session: Session): Option[Seq[Event]] + def eventPeople(evaluation: PipelineEvaluation, event: String)(implicit session: Session) : Option[Seq[Person]] } diff --git a/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala b/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala index c88880eb..7bb8257e 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala @@ -418,4 +418,11 @@ class RgmlServiceImpl(implicit val inj: Injector) extends RgmlService with Injec new EventQuery(), new EventExtractor()) } + + def eventPeople(evaluation: PipelineEvaluation, event: String)(implicit session: Session): Option[Seq[Person]] = { + sparqlEndpointService.getResult( + evaluationToSparqlEndpoint(evaluation), + new EventPeopleQuery(event), + new PersonExtractor()) + } } diff --git a/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala index ff3605c9..0367a46c 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala @@ -5,7 +5,6 @@ import model.rdf.sparql.rgml.Event import model.rdf.sparql.rgml.query.EventQuery import org.apache.jena.query.QueryExecution import org.joda.time.DateTime - import scala.collection.JavaConversions._ diff --git a/src/app/model/rdf/sparql/rgml/extractor/PersonExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/PersonExtractor.scala new file mode 100644 index 00000000..48a79501 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/extractor/PersonExtractor.scala @@ -0,0 +1,26 @@ +package model.rdf.sparql.rgml.extractor + +import model.rdf.extractor.QueryExecutionResultExtractor +import model.rdf.sparql.rgml.Person +import model.rdf.sparql.rgml.query.EventPeopleQuery +import org.apache.jena.query.QueryExecution +import scala.collection.JavaConversions._ + + +class PersonExtractor extends QueryExecutionResultExtractor[EventPeopleQuery, Seq[Person]]{ + def extract(input: QueryExecution): Option[Seq[Person]] = { + try { + val resList = input.execSelect().toList + Some(resList.map(e => Person( + e.getLiteral("person").getString(), + e.getLiteral("personName").getString(), + e.getLiteral("personInfo").getString()) + )) + } + catch { + case e: org.apache.jena.sparql.engine.http.QueryExceptionHTTP => { + None + } + } + } +} diff --git a/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala index 0075c0ac..4e706807 100644 --- a/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala @@ -1,18 +1,17 @@ package model.rdf.sparql.rgml.query import model.rdf.sparql.query.SparqlQuery -class EventPeopleQuery(events: Seq[String]) extends SparqlQuery { +class EventPeopleQuery(event: String) extends SparqlQuery { def get: String = { - val eventUris = events.map(e => "<" + e + ">").mkString(" ") """ |PREFIX rdf: |PREFIX sch: |PREFIX dbo: |PREFIX foaf: | - |SELECT DISTINCT ?person ?personName ?personInfo ?event WHERE { + |SELECT DISTINCT ?person ?personName ?personInfo WHERE { | ?event rdf:type sch:Event ; - | VALUES ?event { @eventUrls } + | VALUES ?event { <@eventUrl> } | ?person rdf:type sch:Person ; | foaf:name ?personName ; | foaf:isPrimaryTopicOf ?personInfo . @@ -21,6 +20,6 @@ class EventPeopleQuery(events: Seq[String]) extends SparqlQuery { |} """ .stripMargin - .replace("@eventUrls", eventUris) + .replace("@eventUrl", event) } } \ No newline at end of file From a5138444ed614a9c6ed22452c9737a92ae64d1b6 Mon Sep 17 00:00:00 2001 From: vvancak Date: Fri, 17 Mar 2017 16:48:52 +0100 Subject: [PATCH 04/84] EventTimeline: EventTimeline: API fixes --- .../javascripts/modules/visualizers/eventTimeline/api.js | 6 ------ .../assistant/javascripts/modules/visualizers/events/api.js | 6 ++++++ .../{eventTimeline => events}/applicationRoutes.js | 0 .../{eventTimeline => events}/components/Application.js | 0 .../{eventTimeline => events}/configuratorRoutes.js | 0 .../{eventTimeline => events}/containers/EventLoader.js | 0 .../{eventTimeline => events}/containers/SaveButton.js | 0 .../{eventTimeline => events}/ducks/configuration.js | 1 + .../visualizers/{eventTimeline => events}/ducks/dirty.js | 0 .../visualizers/{eventTimeline => events}/ducks/event.js | 2 -- .../modules/visualizers/{eventTimeline => events}/models.js | 4 ++-- .../{eventTimeline => events}/pages/Configurator.js | 0 .../visualizers/{eventTimeline => events}/pages/Embed.js | 0 .../{eventTimeline => events}/pages/Standalone.js | 0 .../modules/visualizers/{eventTimeline => events}/prefix.js | 0 .../visualizers/{eventTimeline => events}/reducer.js | 0 .../visualizers/{eventTimeline => events}/selector.js | 0 src/app/controllers/ControllerModule.scala | 3 ++- src/conf/routes | 3 +++ 19 files changed, 14 insertions(+), 11 deletions(-) delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/api.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/applicationRoutes.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/components/Application.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/configuratorRoutes.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/containers/EventLoader.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/containers/SaveButton.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/ducks/configuration.js (97%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/ducks/dirty.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/ducks/event.js (99%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/models.js (68%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/pages/Configurator.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/pages/Embed.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/pages/Standalone.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/prefix.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/reducer.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{eventTimeline => events}/selector.js (100%) diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/api.js deleted file mode 100644 index 38484e2b..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/api.js +++ /dev/null @@ -1,6 +0,0 @@ -import rest from '../../../misc/rest' - -export async function getEvent(applicationId) { - const result = await rest('graphVisualizer/getEvent/' + applicationId, {}); - return result.data.event; -} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js new file mode 100644 index 00000000..157b9ece --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js @@ -0,0 +1,6 @@ +import rest from '../../../misc/rest' + +export async function getEvents(applicationId) { + const result = await rest('eventVisualizer/getEvent/' + applicationId, {}); + return result.data.event; +} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/applicationRoutes.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/applicationRoutes.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/applicationRoutes.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/components/Application.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/configuratorRoutes.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/configuratorRoutes.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/configuratorRoutes.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/EventLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/EventLoader.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/SaveButton.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/containers/SaveButton.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/configuration.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js similarity index 97% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/configuration.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js index ff3e039f..e783eff7 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/configuration.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js @@ -1,5 +1,6 @@ import prefix from '../prefix' import moduleSelector from '../selector' +import { createSelector } from 'reselect' import { createPromiseStatusSelector } from '../../../core/ducks/promises' import { createGetConfiguration, createGetConfigurationReset, createSaveConfiguration diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/dirty.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/dirty.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/event.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/event.js similarity index 99% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/event.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/event.js index 4e2d69c2..a2c2114a 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/ducks/event.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/event.js @@ -2,7 +2,6 @@ import createAction from '../../../../misc/createAction' import withApplicationId from '../../../app/misc/withApplicationId' import prefix from '../prefix' import * as api from '../api' - import { GET_APPLICATION_START } from '../../../app/ducks/application' import { Event } from '../models' @@ -38,7 +37,6 @@ export default function eventReducer(state = initialState, action) { case GET_APPLICATION_START: case GET_EVENT_RESET: return initialState; - case GET_EVENT_SUCCESS: return new Event(action.payload); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js similarity index 68% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/models.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js index 2ab04749..d93d335a 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js @@ -3,8 +3,8 @@ import { Record } from 'immutable'; export const Event = Record({ url: "Event url", name: "Event name", - start: date("1.1.2000"), - end: date("1.1.2000"), + start: new Date("1.1.2000"), + end: new Date("1.1.2000"), info: "Event info" }); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Configurator.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Embed.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Embed.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Embed.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Embed.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Standalone.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Standalone.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/pages/Standalone.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Standalone.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/prefix.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/prefix.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/prefix.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/reducer.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/selector.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/selector.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/eventTimeline/selector.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/selector.js diff --git a/src/app/controllers/ControllerModule.scala b/src/app/controllers/ControllerModule.scala index a4c85d58..ae8b70a0 100644 --- a/src/app/controllers/ControllerModule.scala +++ b/src/app/controllers/ControllerModule.scala @@ -1,7 +1,7 @@ package controllers import controllers.assistant.api._ -import controllers.assistant.api.visualizers.{ChordVisualizerApiController, CommonVisualizerApiController, MapsVisualizerApiController} +import controllers.assistant.api.visualizers.{ChordVisualizerApiController, CommonVisualizerApiController, MapsVisualizerApiController, EventVisualizerApiController} import controllers.util.AngularController import scaldi.Module @@ -22,6 +22,7 @@ class ControllerModule extends Module { binding to new CommonApiController binding to new MapsVisualizerApiController binding to new ChordVisualizerApiController + binding to new EventVisualizerApiController binding to new CommonVisualizerApiController binding to new DashboardApiController binding to new CatalogApiController diff --git a/src/conf/routes b/src/conf/routes index ad01ed7f..9dfbb7a4 100644 --- a/src/conf/routes +++ b/src/conf/routes @@ -156,6 +156,9 @@ POST /assistant/api/chordVisualizer/getSearchableLens/:id @control POST /assistant/api/chordVisualizer/searchNodes/:id @controllers.assistant.api.visualizers.ChordVisualizerApiController.searchNodes(id: Long) POST /assistant/api/chordVisualizer/getRelatedNodes/:id @controllers.assistant.api.visualizers.ChordVisualizerApiController.getRelatedNodes(id: Long) +POST /assistant/api/eventVisualizer/getEvents/:id @controllers.assistant.api.visualizers.EventVisualizerApiController.getEvents(id: Long) +POST /assistant/api/eventVisualizer/getEventPeople/:id @controllers.assistant.api.visualizers.EventVisualizerApiController.getEventPeople(id: Long) + GET /assistant$any<.*> @controllers.assistant.PlatformController.index(any) GET /app/:id/:uid @controllers.assistant.ApplicationController.index(id: Long, uid: String, any = null) GET /app/:id/:uid/$any<.*> @controllers.assistant.ApplicationController.index(id: Long, uid: String, any) From 379fb9aef80493368493c67626a068abaf5693d3 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sat, 18 Mar 2017 13:28:52 +0100 Subject: [PATCH 05/84] EventTimeline: IDE down, changes flush --- .../javascripts/entries/eventTimeline.js | 2 +- .../modules/visualizers/events/api.js | 4 +- .../events/components/Application.js | 3 +- .../events/containers/EventLoader.js | 20 +++---- .../visualizers/events/ducks/configuration.js | 6 +-- .../modules/visualizers/events/ducks/event.js | 50 ------------------ .../visualizers/events/ducks/events.js | 52 +++++++++++++++++++ .../modules/visualizers/events/models.js | 10 ++-- .../visualizers/events/pages/Configurator.js | 6 +-- .../modules/visualizers/events/prefix.js | 2 +- .../modules/visualizers/events/reducer.js | 4 +- .../modules/visualizers/reducer.js | 4 +- .../javascripts/modules/visualizers/routes.js | 2 +- 13 files changed, 79 insertions(+), 86 deletions(-) delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/event.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js diff --git a/src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js b/src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js index 7854d4f8..9077c55c 100644 --- a/src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js +++ b/src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js @@ -1,4 +1,4 @@ -import createRoutes from '../modules/visualizers/eventTimeline/applicationRoutes' +import createRoutes from '../modules/visualizers/events/applicationRoutes' import initEntry from '../misc/initEntry' initEntry(createRoutes); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js index 157b9ece..f4fcfc02 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js @@ -1,6 +1,6 @@ import rest from '../../../misc/rest' export async function getEvents(applicationId) { - const result = await rest('eventVisualizer/getEvent/' + applicationId, {}); - return result.data.event; + const result = await rest('eventVisualizer/getEvents/' + applicationId, {}); + return result.data.events; } \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js index 95843942..727ada63 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js @@ -2,7 +2,7 @@ import React, { Component, PropTypes } from 'react' import BodyPadding from '../../../../components/BodyPadding' import { Application as ApplicationModel } from '../../../app/models' import { Visualizer } from '../../../core/models' -import { EventLoader } from '../containers/EventLoader' +import EventLoader from '../containers/EventLoader' class Application extends Component { static propTypes = { @@ -20,7 +20,6 @@ class Application extends Component {

It runs in {embed ? 'embed' : 'standalone'} mode

{application.name}

{visualizer.title}

- ) } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js index 81fa2ce0..a90c5b4c 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js @@ -1,35 +1,35 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import { createStructuredSelector } from 'reselect' -import { getEvent, getEventReset, eventSelector, eventStatusSelector } from '../ducks/event' +import { getEvents, getEventsReset, eventsSelector, eventsStatusSelector } from '../ducks/events' import { PromiseStatus } from '../../../core/models' -import { Event } from '../models' - +import PromiseResult from '../../../core/components/PromiseResult' class EventLoader extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - event: PropTypes.instanceOf(Event).isRequired, + events: PropTypes.instanceOf(Array).isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired }; componentWillMount() { const {dispatch} = this.props; - dispatch(getEvent()); + dispatch(getEvents()); } componentWillUnmount() { const {dispatch} = this.props; - dispatch(getEventReset()); + dispatch(getEventsReset()); } render() { - const {event, status} = this.props; + const {events, status} = this.props; if (!status.done) { - return + return } + let event = events[0]; return (

Graph info

@@ -43,8 +43,8 @@ class EventLoader extends Component { } const selector = createStructuredSelector({ - event: eventSelector, - status: eventStatusSelector + events: eventsSelector, + status: eventsStatusSelector }); export default connect(selector)(EventLoader); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js index e783eff7..ef068ca3 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js @@ -2,12 +2,9 @@ import prefix from '../prefix' import moduleSelector from '../selector' import { createSelector } from 'reselect' import { createPromiseStatusSelector } from '../../../core/ducks/promises' -import { - createGetConfiguration, createGetConfigurationReset, createSaveConfiguration -} from '../../../app/ducks/configuration' +import { createGetConfiguration, createGetConfigurationReset, createSaveConfiguration } from '../../../app/ducks/configuration' // Actions - export const SAVE_CONFIGURATION = prefix('SAVE_CONFIGURATION'); export const SAVE_CONFIGURATION_START = SAVE_CONFIGURATION + '_START'; export const SAVE_CONFIGURATION_ERROR = SAVE_CONFIGURATION + '_ERROR'; @@ -20,7 +17,6 @@ export const GET_CONFIGURATION_SUCCESS = GET_CONFIGURATION + '_SUCCESS'; export const GET_CONFIGURATION_RESET = GET_CONFIGURATION + '_RESET'; // Selectors - export const saveConfigurationStatusSelector = createPromiseStatusSelector(SAVE_CONFIGURATION); export const getConfigurationStatusSelector = createPromiseStatusSelector(GET_CONFIGURATION); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/event.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/event.js deleted file mode 100644 index a2c2114a..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/event.js +++ /dev/null @@ -1,50 +0,0 @@ -import createAction from '../../../../misc/createAction' -import withApplicationId from '../../../app/misc/withApplicationId' -import prefix from '../prefix' -import * as api from '../api' -import { GET_APPLICATION_START } from '../../../app/ducks/application' -import { Event } from '../models' - -import { createSelector } from 'reselect' -import { createPromiseStatusSelector } from '../../../core/ducks/promises' -import moduleSelector from '../selector' - -// Actions - -export const GET_EVENT = prefix('GET_GRAPH'); -export const GET_EVENT_START = GET_EVENT + '_START'; -export const GET_EVENT_ERROR = GET_EVENT + '_ERROR'; -export const GET_EVENT_SUCCESS = GET_EVENT + '_SUCCESS'; -export const GET_EVENT_RESET = GET_EVENT + '_RESET'; - -export function getEvent() { - return withApplicationId(id => { - const promise = api.getEvent(id); - return createAction(GET_EVENT, { promise }); - }) -} - -export function getEventReset() { - return createAction(GET_EVENT_RESET); -} - -// Reducer - -const initialState = new Event(); - -export default function eventReducer(state = initialState, action) { - switch (action.type) { - case GET_APPLICATION_START: - case GET_EVENT_RESET: - return initialState; - case GET_EVENT_SUCCESS: - return new Event(action.payload); - } - - return state; -}; - -// Selectors - -export const eventStatusSelector = createPromiseStatusSelector(GET_EVENT); -export const eventSelector = createSelector([moduleSelector], state => state.event); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js new file mode 100644 index 00000000..5e1872ac --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js @@ -0,0 +1,52 @@ +import createAction from '../../../../misc/createAction' +import withApplicationId from '../../../app/misc/withApplicationId' +import prefix from '../prefix' +import * as api from '../api' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { EventInfo } from '../models' + +import { createSelector } from 'reselect' +import { createPromiseStatusSelector } from '../../../core/ducks/promises' +import moduleSelector from '../selector' + +// Actions +export const GET_EVENTS = prefix('GET_EVENTS'); +export const GET_EVENTS_START = GET_EVENTS + '_START'; +export const GET_EVENTS_ERROR = GET_EVENTS + '_ERROR'; +export const GET_EVENTS_SUCCESS = GET_EVENTS + '_SUCCESS'; +export const GET_EVENTS_RESET = GET_EVENTS + '_RESET'; + +export function getEvents() { + return withApplicationId(id => { + const promise = api.getEvents(id); + return createAction(GET_EVENTS, { promise }); + }); +} + +export function getEventsReset() { + return createAction(GET_EVENTS_RESET); +} + +// Reducer +const initialState = []; +export default function eventsReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + case GET_EVENTS_RESET: + return initialState; + + case GET_EVENTS_SUCCESS: + return action.payload.map(ev=>new EventInfo( + ev.url, + ev.name, + new Date(ev.start), + new Date(ev.end), + ev.info) + ); + } + return state; +}; + +// Selectors +export const eventsStatusSelector = createPromiseStatusSelector(GET_EVENTS); +export const eventsSelector = createSelector([moduleSelector], state => state); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js index d93d335a..a1999318 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js @@ -1,10 +1,10 @@ import { Record } from 'immutable'; -export const Event = Record({ - url: "Event url", - name: "Event name", - start: new Date("1.1.2000"), - end: new Date("1.1.2000"), +export const EventInfo = Record({ + url: "url", + name: "name", + start: new Date(), + end: new Date(), info: "Event info" }); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js index d2a7975f..14e13a27 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js @@ -2,10 +2,8 @@ import React, { Component, PropTypes } from 'react' import BodyPadding from '../../../../components/BodyPadding' import { Application } from '../../../app/models' import { Visualizer } from '../../../core/models' -import { EventLoader } from '../containers/EventLoader' +import EventLoader from '../containers/EventLoader' import { getConfiguration, getConfigurationReset } from '../ducks/configuration' -import EditableLabel from '../../../app/containers/EditableLabel' -import SaveButton from '../containers/SaveButton' class Configurator extends Component { @@ -22,8 +20,6 @@ class Configurator extends Component {

{application.name}

{visualizer.title}

- - ) } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/prefix.js index 5cc83669..9b65606e 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/prefix.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/prefix.js @@ -1,4 +1,4 @@ import createPrefixer from '../../../misc/createPrefixer' -export const MODULE_PREFIX = 'eventTimeline'; +export const MODULE_PREFIX = 'events'; export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js index 1627ff32..c9cf6520 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js @@ -1,8 +1,8 @@ import { combineReducers } from 'redux'; -import event from './ducks/event' +import events from './ducks/events' const rootReducer = combineReducers({ - event + events }); export default rootReducer; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js index 4ad415d0..2bb5e30f 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js @@ -1,11 +1,11 @@ import { combineReducers } from 'redux'; import googleMaps from './googleMaps/reducer' import chord from './chord/reducer' -import eventTimeline from './eventTimeline/reducer' +import events from './events/reducer' const rootReducer = combineReducers({ googleMaps, chord, - eventTimeline + events }); export default rootReducer; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js index 8d5681ed..feb4418b 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js @@ -4,7 +4,7 @@ import ConfiguratorsRouteFactory from './utils/ConfiguratorsRouteFactory' import dataCubeRoutes from './datacube/configuratorRoutes' import googleMapsRoutes from './googleMaps/configuratorRoutes' import chordRoutes from './chord/configuratorRoutes' -import eventTimelineRoutes from './eventTimeline/configuratorRoutes' +import eventTimelineRoutes from './events/configuratorRoutes' import { Visualizer, VisualizerWithPipelines } from '../core/models' import { applicationUrl } from '../app/configuratorRoutes' From a342c634ad0fb1f77d9db2e1a2b4ad6d1a48b538 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sat, 18 Mar 2017 16:21:05 +0100 Subject: [PATCH 06/84] EventTimeline: Server event query fixes --- src/app/model/rdf/sparql/rgml/Event.scala | 4 +-- .../rgml/extractor/EventExtractor.scala | 26 ++++++++++++------- .../rdf/sparql/rgml/query/EventQuery.scala | 11 ++++---- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/app/model/rdf/sparql/rgml/Event.scala b/src/app/model/rdf/sparql/rgml/Event.scala index 9654bbd0..c424cdd3 100644 --- a/src/app/model/rdf/sparql/rgml/Event.scala +++ b/src/app/model/rdf/sparql/rgml/Event.scala @@ -1,4 +1,4 @@ package model.rdf.sparql.rgml -import org.joda.time.DateTime +import java.util.Date -case class Event(url:String,name:String,start:DateTime,end:DateTime,info:String) +case class Event(url:String,name:String,start:Date,end:Date,info:String) diff --git a/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala index 0367a46c..f1ea389d 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala @@ -1,24 +1,26 @@ package model.rdf.sparql.rgml.extractor +import java.util.Date +import java.text.SimpleDateFormat + import model.rdf.extractor.QueryExecutionResultExtractor import model.rdf.sparql.rgml.Event import model.rdf.sparql.rgml.query.EventQuery -import org.apache.jena.query.QueryExecution -import org.joda.time.DateTime -import scala.collection.JavaConversions._ +import org.apache.jena.query.{QueryExecution, QuerySolution} +import scala.collection.JavaConversions._ class EventExtractor extends QueryExecutionResultExtractor[EventQuery, Seq[Event]] { def extract(input: QueryExecution): Option[Seq[Event]] = { try { val resList = input.execSelect().toList - Some(resList.map(e => Event( - e.getLiteral("event").toString(), - e.getLiteral("eventName").toString(), - DateTime.parse(e.getLiteral("start").toString()), - DateTime.parse(e.getLiteral("end").toString()), - e.getLiteral("eventInfo").toString() + Some(resList.map(e => new Event( + e.getResource("event").getURI, + e.getLiteral("eventName").getString, + getDate(e, "start"), + getDate(e, "end"), + e.getResource("eventLink").getURI ))) } catch { @@ -27,4 +29,10 @@ class EventExtractor extends QueryExecutionResultExtractor[EventQuery, Seq[Event } } } + + private def getDate(qs: QuerySolution, fieldName: String): Date = { + val dateFormat = new SimpleDateFormat("YYYY-MM-DD") + val fieldValue = qs.getLiteral(fieldName).getString() + if (!fieldValue.isEmpty()) dateFormat.parse(fieldValue) else new Date + } } \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/query/EventQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventQuery.scala index 8c6917ae..f90d193f 100644 --- a/src/app/model/rdf/sparql/rgml/query/EventQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/EventQuery.scala @@ -16,11 +16,12 @@ class EventQuery extends SparqlQuery{ | dbo:endDate ?end ; | dbo:wikiPageExternalLink ?eventLink . | - | ?person rdf:type sch:Person ; - | foaf:name ?personName ; - | foaf:isPrimaryTopicOf ?personLink . - | - | FILTER EXISTS { ?event ?relation ?person } + | FILTER EXISTS { + | ?event ?relation ?person . + | ?person rdf:type sch:Person ; + | foaf:name ?personName ; + | foaf:isPrimaryTopicOf ?personLink . + | } |} LIMIT 100 """ .stripMargin From 60cda520b0c3f442ee3e2c09e12adf4f45352075 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sat, 18 Mar 2017 22:46:41 +0100 Subject: [PATCH 07/84] EventTimeline: Client-Side event extraction complete --- .../assistant/javascripts/entries/eventTimeline.js | 4 ---- .../visualizers/events/components/Application.js | 1 + .../visualizers/events/containers/EventLoader.js | 8 +------- .../modules/visualizers/events/ducks/events.js | 10 ++-------- .../javascripts/modules/visualizers/events/models.js | 6 +++--- .../javascripts/modules/visualizers/routes.js | 4 ++-- 6 files changed, 9 insertions(+), 24 deletions(-) delete mode 100644 src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js diff --git a/src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js b/src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js deleted file mode 100644 index 9077c55c..00000000 --- a/src/app/assets_webpack/assistant/javascripts/entries/eventTimeline.js +++ /dev/null @@ -1,4 +0,0 @@ -import createRoutes from '../modules/visualizers/events/applicationRoutes' -import initEntry from '../misc/initEntry' - -initEntry(createRoutes); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js index 727ada63..393fcf04 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js @@ -20,6 +20,7 @@ class Application extends Component {

It runs in {embed ? 'embed' : 'standalone'} mode

{application.name}

{visualizer.title}

+ ) } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js index a90c5b4c..e3566af1 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js @@ -28,15 +28,9 @@ class EventLoader extends Component { if (!status.done) { return } - - let event = events[0]; return (
-

Graph info

-

Event info: {event.info }

-

Event name: {event.name}

-

Start : {event.start}

-

End: {event.end}

+

{ events.forEach(ev=>{ return ev.name + "\n"}) }

) } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js index 5e1872ac..d1d53076 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js @@ -36,17 +36,11 @@ export default function eventsReducer(state = initialState, action) { return initialState; case GET_EVENTS_SUCCESS: - return action.payload.map(ev=>new EventInfo( - ev.url, - ev.name, - new Date(ev.start), - new Date(ev.end), - ev.info) - ); + return action.payload.map(ev=>new EventInfo(ev)); } return state; }; // Selectors export const eventsStatusSelector = createPromiseStatusSelector(GET_EVENTS); -export const eventsSelector = createSelector([moduleSelector], state => state); \ No newline at end of file +export const eventsSelector = createSelector([moduleSelector], state => state.events); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js index a1999318..be57fa71 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js @@ -3,9 +3,9 @@ import { Record } from 'immutable'; export const EventInfo = Record({ url: "url", name: "name", - start: new Date(), - end: new Date(), - info: "Event info" + start: "start", + end: "end", + info: "info" }); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js index feb4418b..fd3c86db 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js @@ -4,7 +4,7 @@ import ConfiguratorsRouteFactory from './utils/ConfiguratorsRouteFactory' import dataCubeRoutes from './datacube/configuratorRoutes' import googleMapsRoutes from './googleMaps/configuratorRoutes' import chordRoutes from './chord/configuratorRoutes' -import eventTimelineRoutes from './events/configuratorRoutes' +import eventsRoutes from './events/configuratorRoutes' import { Visualizer, VisualizerWithPipelines } from '../core/models' import { applicationUrl } from '../app/configuratorRoutes' @@ -15,7 +15,7 @@ const routeFactory = new ConfiguratorsRouteFactory(); routeFactory.register(dataCubeRoutes); routeFactory.register(googleMapsRoutes); routeFactory.register(chordRoutes); -routeFactory.register(eventTimelineRoutes); +routeFactory.register(eventsRoutes); export default dispatch => routeFactory.createRoutes(dispatch); From fc4e83e7212e4ab4730266d678b02e584084f380 Mon Sep 17 00:00:00 2001 From: vvancak Date: Tue, 21 Mar 2017 23:57:51 +0100 Subject: [PATCH 08/84] EventTimeline: Mocked data visualization --- .../events/containers/EventLoader.js | 33 ++++++++++++++++--- .../visualizers/events/pages/Configurator.js | 1 + src/npm-shrinkwrap.json | 20 ++++++++--- src/package.json | 2 ++ 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js index e3566af1..02dffbcc 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js @@ -4,6 +4,7 @@ import { createStructuredSelector } from 'reselect' import { getEvents, getEventsReset, eventsSelector, eventsStatusSelector } from '../ducks/events' import { PromiseStatus } from '../../../core/models' import PromiseResult from '../../../core/components/PromiseResult' +import TimelineChart from 'd3-timeline-chart' class EventLoader extends Component { static propTypes = { @@ -28,11 +29,33 @@ class EventLoader extends Component { if (!status.done) { return } - return ( -
-

{ events.forEach(ev=>{ return ev.name + "\n"}) }

-
- ) + + const element = document.getElementById("chart_placeholder"); + const data = [{ + label: 'Name', + data: [ { + label: 'I\'m a label', + type: TimelineChart.TYPE.INTERVAL, + from: new Date([2015, 2, 1]), + to: new Date([2015, 3, 1]) + }] + }, { label: 'Event', data: { + label: 'I\'m a label II', + type: TimelineChart.TYPE.INTERVAL, + from: new Date([2015, 2, 20]), + to: new Date([2015, 3, 20]) + } + }]; + + var chart = new TimelineChart(element, data, { + tip: function(d) { + return d.at || `${d.from}
${d.to}`; + }, + width: 1000, + height: 1000 + }); + + return
; } } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js index 14e13a27..976cdf36 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js @@ -19,6 +19,7 @@ class Configurator extends Component {

This is the graph visualizer configurator.

{application.name}

{visualizer.title}

+
) diff --git a/src/npm-shrinkwrap.json b/src/npm-shrinkwrap.json index 9b139910..36bf30f9 100644 --- a/src/npm-shrinkwrap.json +++ b/src/npm-shrinkwrap.json @@ -7,11 +7,6 @@ "from": "babel-polyfill@>=6.3.0 <6.4.0", "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.3.14.tgz", "dependencies": { - "core-js": { - "version": "1.2.7", - "from": "core-js@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz" - }, "babel-regenerator-runtime": { "version": "6.5.0", "from": "babel-regenerator-runtime@>=6.3.13 <7.0.0", @@ -21,6 +16,11 @@ "version": "5.8.38", "from": "babel-runtime@>=5.0.0 <6.0.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.38.tgz" + }, + "core-js": { + "version": "1.2.7", + "from": "core-js@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz" } } }, @@ -34,6 +34,16 @@ "from": "d3@>=3.5.0 <3.6.0", "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz" }, + "d3-timeline-chart": { + "version": "1.3.0", + "from": "d3-timeline-chart@latest", + "resolved": "https://registry.npmjs.org/d3-timeline-chart/-/d3-timeline-chart-1.3.0.tgz" + }, + "d3-tip": { + "version": "0.6.7", + "from": "d3-tip@0.6.7", + "resolved": "https://registry.npmjs.org/d3-tip/-/d3-tip-0.6.7.tgz" + }, "debug": { "version": "2.2.0", "from": "debug@>=2.2.0 <2.3.0", diff --git a/src/package.json b/src/package.json index 1a7dc3f9..ee2b4cf6 100644 --- a/src/package.json +++ b/src/package.json @@ -10,6 +10,8 @@ "babel-polyfill": "6.3.x", "classnames": "2.2.x", "d3": "3.5.x", + "d3-timeline-chart": "^1.3.0", + "d3-tip": "^0.6.7", "debug": "2.2.x", "flexboxgrid": "6.3.x", "hash-string": "1.0.x", From 0ec05813f2cc52dc996a83bee8df311b1670bb66 Mon Sep 17 00:00:00 2001 From: vvancak Date: Thu, 23 Mar 2017 15:33:56 +0100 Subject: [PATCH 09/84] EventTimeline: Version updates --- .../visualizers/events/containers/SaveButton.js | 7 ------- src/package.json | 12 ++++++------ 2 files changed, 6 insertions(+), 13 deletions(-) delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js deleted file mode 100644 index f03f11f8..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js +++ /dev/null @@ -1,7 +0,0 @@ -import React, { PropTypes } from 'react' -import { saveConfiguration, saveConfigurationStatusSelector } from '../ducks/configuration' -import { dirtySelector } from '../ducks/dirty' - -import createSaveButton from '../../../app/containers/createSaveButton' - -export default createSaveButton(saveConfiguration, saveConfigurationStatusSelector, dirtySelector); diff --git a/src/package.json b/src/package.json index ee2b4cf6..0d18e13a 100644 --- a/src/package.json +++ b/src/package.json @@ -11,14 +11,14 @@ "classnames": "2.2.x", "d3": "3.5.x", "d3-timeline-chart": "^1.3.0", - "d3-tip": "^0.6.7", + "d3-tip": "^0.6.8", "debug": "2.2.x", - "flexboxgrid": "6.3.x", + "flexboxgrid": "^6.3.1", "hash-string": "1.0.x", "history": "2.0.0-rc2", "immutable": "3.7.x", "lodash": "4.6.x", - "material-ui": "0.15.x", + "material-ui": "^0.15.4", "moment": "2.13.x", "react": "15.2.x", "react-dom": "15.1.x", @@ -26,10 +26,10 @@ "react-google-maps": "4.11.x", "react-helmet": "2.3.x", "react-pure-render": "1.0.x", - "react-redux": "4.4.x", + "react-redux": "^4.4.6", "react-router": "2.0.0-rc5", "react-tap-event-plugin": "1.0.x", - "redux": "^3.0.0", + "redux": "^3.6.0", "redux-form": "5.2.x", "redux-logger": "2.0.x", "redux-promise-middleware": "2.3.x", @@ -39,7 +39,7 @@ "reselect": "2.0.x", "revalidator": "0.3.x", "scriptjs": "2.5.x", - "when": "3.7.x" + "when": "^3.7.8" }, "devDependencies": { "autoprefixer": "6.3.x", From 052a5f6e0282edf4a61c74ed35568af380cf5569 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sun, 26 Mar 2017 14:12:04 +0200 Subject: [PATCH 10/84] EventTimeline: Query updates - deduplication & More people data --- .../EventVisualizerApiController.scala | 4 +- .../model/assistant/rest/EventRequest.scala | 10 +++++ src/app/model/rdf/sparql/rgml/Person.scala | 2 +- .../rdf/sparql/rgml/RgmlServiceImpl.scala | 8 ++-- .../rgml/extractor/EventExtractor.scala | 8 ++-- ...nExtractor.scala => PeopleExtractor.scala} | 12 +++--- .../sparql/rgml/query/EventPeopleQuery.scala | 22 ++++++---- .../rdf/sparql/rgml/query/EventQuery.scala | 42 ++++++++++++------- 8 files changed, 68 insertions(+), 40 deletions(-) create mode 100644 src/app/model/assistant/rest/EventRequest.scala rename src/app/model/rdf/sparql/rgml/extractor/{PersonExtractor.scala => PeopleExtractor.scala} (64%) diff --git a/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala index 8a702ec8..a2c7f371 100644 --- a/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala +++ b/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala @@ -2,10 +2,10 @@ package controllers.assistant.api.visualizers import scala.concurrent.Future import model.assistant.entity.ApplicationId -import model.assistant.rest.EmptyRequest.EmptyRequest import model.assistant.rest.Response._ import model.rdf.sparql.rgml.RgmlService import controllers.api.JsonImplicits._ +import model.assistant.rest.EventRequest.EventRequest import model.assistant.rest.EventPeopleRequest.EventPeopleRequest import play.api.libs.concurrent.Execution.Implicits._ import scaldi.Injector @@ -13,7 +13,7 @@ import scaldi.Injector class EventVisualizerApiController(implicit inj: Injector) extends VisualizerApiController { val rgmlService = inject[RgmlService] - def getEvents(id: Long) = RestAsyncAction[EmptyRequest] { implicit request => json => + def getEvents(id: Long) = RestAsyncAction[EventRequest] { implicit request => json => withEvaluation(ApplicationId(id)) { evaluation => val events = rgmlService.events(evaluation) Future(Ok(SuccessResponse(data = Seq("events" -> events)))) diff --git a/src/app/model/assistant/rest/EventRequest.scala b/src/app/model/assistant/rest/EventRequest.scala new file mode 100644 index 00000000..6a9403f2 --- /dev/null +++ b/src/app/model/assistant/rest/EventRequest.scala @@ -0,0 +1,10 @@ +package model.assistant.rest + +import java.util.Date +import play.api.libs.json.Json + +object EventRequest { + case class EventRequest(start: Date, end: Date, limit: Int) + implicit val writes = Json.writes[EventRequest] + implicit val reads = Json.reads[EventRequest] +} diff --git a/src/app/model/rdf/sparql/rgml/Person.scala b/src/app/model/rdf/sparql/rgml/Person.scala index 9c826922..1c4868b5 100644 --- a/src/app/model/rdf/sparql/rgml/Person.scala +++ b/src/app/model/rdf/sparql/rgml/Person.scala @@ -1,3 +1,3 @@ package model.rdf.sparql.rgml -case class Person (url:String, name:String,info:String) +case class Person (url:String, name:String, description: String, image: String, info:String) diff --git a/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala b/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala index 7bb8257e..7d82b015 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala @@ -1,5 +1,6 @@ package model.rdf.sparql.rgml +import java.util.Date import model.entity.PipelineEvaluation import model.rdf.sparql.rgml.extractor._ import model.rdf.sparql.rgml.query._ @@ -7,7 +8,6 @@ import model.rdf.sparql.{EvaluationToSparqlEndpoint, GenericSparqlEndpoint, Spar import play.api.db.slick.Session import scaldi.{Injectable, Injector} import model.rdf.sparql.rgml.EdgeDirection._ -import utils.Profiler import scala.collection.mutable @@ -412,10 +412,10 @@ class RgmlServiceImpl(implicit val inj: Injector) extends RgmlService with Injec nodes(evaluation, makeSample) } - def events(evaluation: PipelineEvaluation)(implicit session: Session): Option[Seq[Event]] = { + def events(evaluation: PipelineEvaluation, start: Date, end: Date, limit: Int)(implicit session: Session): Option[Seq[Event]] = { sparqlEndpointService.getResult( evaluationToSparqlEndpoint(evaluation), - new EventQuery(), + new EventQuery(start,end,limit), new EventExtractor()) } @@ -423,6 +423,6 @@ class RgmlServiceImpl(implicit val inj: Injector) extends RgmlService with Injec sparqlEndpointService.getResult( evaluationToSparqlEndpoint(evaluation), new EventPeopleQuery(event), - new PersonExtractor()) + new PeopleExtractor()) } } diff --git a/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala index f1ea389d..4bf48164 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala @@ -2,14 +2,12 @@ package model.rdf.sparql.rgml.extractor import java.util.Date import java.text.SimpleDateFormat - +import scala.collection.JavaConversions._ import model.rdf.extractor.QueryExecutionResultExtractor import model.rdf.sparql.rgml.Event import model.rdf.sparql.rgml.query.EventQuery import org.apache.jena.query.{QueryExecution, QuerySolution} -import scala.collection.JavaConversions._ - class EventExtractor extends QueryExecutionResultExtractor[EventQuery, Seq[Event]] { def extract(input: QueryExecution): Option[Seq[Event]] = { @@ -17,10 +15,10 @@ class EventExtractor extends QueryExecutionResultExtractor[EventQuery, Seq[Event val resList = input.execSelect().toList Some(resList.map(e => new Event( e.getResource("event").getURI, - e.getLiteral("eventName").getString, + e.getLiteral("name").getString, getDate(e, "start"), getDate(e, "end"), - e.getResource("eventLink").getURI + e.getResource("link").getURI ))) } catch { diff --git a/src/app/model/rdf/sparql/rgml/extractor/PersonExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala similarity index 64% rename from src/app/model/rdf/sparql/rgml/extractor/PersonExtractor.scala rename to src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala index 48a79501..204aece7 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/PersonExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala @@ -7,14 +7,16 @@ import org.apache.jena.query.QueryExecution import scala.collection.JavaConversions._ -class PersonExtractor extends QueryExecutionResultExtractor[EventPeopleQuery, Seq[Person]]{ +class PeopleExtractor extends QueryExecutionResultExtractor[EventPeopleQuery, Seq[Person]]{ def extract(input: QueryExecution): Option[Seq[Person]] = { try { val resList = input.execSelect().toList - Some(resList.map(e => Person( - e.getLiteral("person").getString(), - e.getLiteral("personName").getString(), - e.getLiteral("personInfo").getString()) + Some(resList.map(p => new Person( + p.getResource("person").getURI, + p.getLiteral("name").getString, + p.getLiteral("description").getString, + p.getResource("image").getURI, + p.getResource("link").getURI) )) } catch { diff --git a/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala index 4e706807..20bcfa3f 100644 --- a/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala @@ -8,18 +8,24 @@ class EventPeopleQuery(event: String) extends SparqlQuery { |PREFIX sch: |PREFIX dbo: |PREFIX foaf: + |PREFIX xsd: | - |SELECT DISTINCT ?person ?personName ?personInfo WHERE { - | ?event rdf:type sch:Event ; - | VALUES ?event { <@eventUrl> } - | ?person rdf:type sch:Person ; - | foaf:name ?personName ; - | foaf:isPrimaryTopicOf ?personInfo . + |PREFIX dbp: + |SELECT ?person (SAMPLE(?personName) AS ?name) (SAMPLE(?personDescription) AS ?description) (SAMPLE(?personLink) AS ?link) (SAMPLE(?personImage) AS ?image) + |WHERE { + | ?event rdf:type sch:Event . + | VALUES ?event { <@event> } | - | FILTER EXISTS { ?event ?relation ?person } + | ?person rdf:type sch:Person ; + | foaf:name ?personName; + | foaf:isPrimaryTopicOf ?personLink; + | foaf:depiction ?personImage;s + | dbp:shortDescription ?personDescription; + | ?relation ?event . |} + |GROUP BY ?person """ .stripMargin - .replace("@eventUrl", event) + .replace("@event", event) } } \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/query/EventQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventQuery.scala index f90d193f..752d3fcb 100644 --- a/src/app/model/rdf/sparql/rgml/query/EventQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/EventQuery.scala @@ -1,28 +1,40 @@ package model.rdf.sparql.rgml.query + +import java.util.Date +import java.text.SimpleDateFormat import model.rdf.sparql.query.SparqlQuery -class EventQuery extends SparqlQuery{ - def get: String = +class EventQuery(start: Date, end: Date, limit: Int) extends SparqlQuery{ + val dateFormat = new SimpleDateFormat("YYYY-MM-DD") + def get: String = """ |PREFIX rdf: |PREFIX sch: |PREFIX dbo: |PREFIX foaf: + |PREFIX xsd: + | + |SELECT ?event (SAMPLE(?eventName) AS ?name) (SAMPLE(?eventStart) AS ?start) (SAMPLE(?eventEnd) AS ?end) (SAMPLE(?eventLink) AS ?link) + |WHERE { + | ?event rdf:type sch:Event ; + | foaf:name ?eventName ; + | dbo:startDate ?eventStart ; + | dbo:endDate ?eventEnd ; + | dbo:wikiPageExternalLink ?eventLink . | - |SELECT DISTINCT ?event ?eventName ?start ?end ?eventLink WHERE { - | ?event rdf:type sch:Event ; - | foaf:name ?eventName ; - | dbo:startDate ?start ; - | dbo:endDate ?end ; - | dbo:wikiPageExternalLink ?eventLink . + | FILTER (?eventStart > "@start"^^xsd:date) + | FILTER (?eventEnd < "@end"^^xsd:date) | - | FILTER EXISTS { - | ?event ?relation ?person . - | ?person rdf:type sch:Person ; - | foaf:name ?personName ; - | foaf:isPrimaryTopicOf ?personLink . - | } - |} LIMIT 100 + | FILTER EXISTS { + | ?person rdf:type sch:Person ; + | ?relation ?event . + | } + |} + |GROUP BY ?event + |LIMIT @limit """ + .replace("@start",dateFormat.format(start)) + .replace("@end",dateFormat.format(end)) + .replace("@limit", limit.toString) .stripMargin } From 9074dedd6e72a075d9cd6cffc52ad3405eb06ff0 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sun, 26 Mar 2017 17:55:11 +0200 Subject: [PATCH 11/84] EventTimeline: client fixes --- .../api/visualizers/EventVisualizerApiController.scala | 2 +- src/app/model/rdf/sparql/rgml/RgmlService.scala | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala index a2c7f371..ae4fe302 100644 --- a/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala +++ b/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala @@ -15,7 +15,7 @@ class EventVisualizerApiController(implicit inj: Injector) extends VisualizerApi def getEvents(id: Long) = RestAsyncAction[EventRequest] { implicit request => json => withEvaluation(ApplicationId(id)) { evaluation => - val events = rgmlService.events(evaluation) + val events = rgmlService.events(evaluation, json.start, json.end, json.limit) Future(Ok(SuccessResponse(data = Seq("events" -> events)))) } } diff --git a/src/app/model/rdf/sparql/rgml/RgmlService.scala b/src/app/model/rdf/sparql/rgml/RgmlService.scala index 03e69af4..df36b591 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlService.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlService.scala @@ -1,5 +1,6 @@ package model.rdf.sparql.rgml +import java.util.Date import model.entity.PipelineEvaluation import play.api.db.slick.Session import model.rdf.sparql.rgml.EdgeDirection._ @@ -16,6 +17,6 @@ trait RgmlService { def adjacentNodes(evaluation: PipelineEvaluation, nodeUri: String, direction: Option[EdgeDirection] = None)(implicit session: Session): Option[Seq[Node]] def sampleNodesByHighestDegree(evaluation: PipelineEvaluation, size: Int)(implicit session: Session): Option[Seq[Node]] def sampleNodesWithForestFire( evaluation: PipelineEvaluation, size: Int, useWeights: Boolean = true, pF: Double = 0.2, pB: Double = 0.05)(implicit session: Session): Option[Seq[Node]] - def events(evaluation: PipelineEvaluation)(implicit session: Session): Option[Seq[Event]] + def events(evaluation: PipelineEvaluation, start: Date, end: Date, limit: Int)(implicit session: Session): Option[Seq[Event]] def eventPeople(evaluation: PipelineEvaluation, event: String)(implicit session: Session) : Option[Seq[Person]] } From e71d50ffe2a51452038f37cb6233a8e44de15ec2 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sun, 26 Mar 2017 22:18:34 +0200 Subject: [PATCH 12/84] EventTimeline: API changes --- .../assistant/javascripts/entries/events.js | 4 ++ .../modules/visualizers/events/api.js | 10 ++++- .../visualizers/events/ducks/events.js | 10 +++-- .../visualizers/events/ducks/people.js | 44 +++++++++++++++++++ .../modules/visualizers/events/models.js | 8 ++++ .../visualizers/events/pages/Configurator.js | 3 +- .../EventVisualizerApiController.scala | 8 ++-- 7 files changed, 76 insertions(+), 11 deletions(-) create mode 100644 src/app/assets_webpack/assistant/javascripts/entries/events.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js diff --git a/src/app/assets_webpack/assistant/javascripts/entries/events.js b/src/app/assets_webpack/assistant/javascripts/entries/events.js new file mode 100644 index 00000000..1aa9e398 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/entries/events.js @@ -0,0 +1,4 @@ +import createRoutes from '../modules/visualizers/events/applicationRoutes' +import initEntry from '../misc/initEntry' + +initEntry(createRoutes); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js index f4fcfc02..059b1ca5 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js @@ -1,6 +1,12 @@ import rest from '../../../misc/rest' -export async function getEvents(applicationId) { - const result = await rest('eventVisualizer/getEvents/' + applicationId, {}); +export async function getEvents(applicationId, start, end, limit) { + let payload = {"start":start, "end":end, "limit":limit}; + const result = await rest('eventVisualizer/getEvents/' + applicationId,payload); return result.data.events; +} + +export async function getEventPeople(applicationId, event) { + const result = await rest('eventVisualizer/getEventPeople/' + applicationId, {"event" : event.url}); + return result.data.people; } \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js index d1d53076..bd38e117 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js @@ -4,9 +4,9 @@ import prefix from '../prefix' import * as api from '../api' import { GET_APPLICATION_START } from '../../../app/ducks/application' import { EventInfo } from '../models' - import { createSelector } from 'reselect' import { createPromiseStatusSelector } from '../../../core/ducks/promises' +import storageReducerFactory from '../../../../misc/storageReducerFactory' import moduleSelector from '../selector' // Actions @@ -16,9 +16,9 @@ export const GET_EVENTS_ERROR = GET_EVENTS + '_ERROR'; export const GET_EVENTS_SUCCESS = GET_EVENTS + '_SUCCESS'; export const GET_EVENTS_RESET = GET_EVENTS + '_RESET'; -export function getEvents() { +export function getEvents(start,end,limit) { return withApplicationId(id => { - const promise = api.getEvents(id); + const promise = api.getEvents(id,start,end,limit); return createAction(GET_EVENTS, { promise }); }); } @@ -32,9 +32,11 @@ const initialState = []; export default function eventsReducer(state = initialState, action) { switch (action.type) { case GET_APPLICATION_START: + return initialState; case GET_EVENTS_RESET: return initialState; - + case GET_EVENTS_ERROR: + return action.payload; case GET_EVENTS_SUCCESS: return action.payload.map(ev=>new EventInfo(ev)); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js new file mode 100644 index 00000000..823c9570 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js @@ -0,0 +1,44 @@ +import createAction from '../../../../misc/createAction' +import withApplicationId from '../../../app/misc/withApplicationId' +import prefix from '../prefix' +import * as api from '../api' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { PersonInfo } from '../models' +import { createSelector } from 'reselect' +import { createPromiseStatusSelector } from '../../../core/ducks/promises' +import moduleSelector from '../selector' + +// Actions +export const GET_PEOPLE = prefix('GET_PEOPLE'); +export const GET_PEOPLE_START = GET_PEOPLE + '_START'; +export const GET_PEOPLE_ERROR = GET_PEOPLE + '_ERROR'; +export const GET_PEOPLE_SUCCESS = GET_PEOPLE + '_SUCCESS'; +export const GET_PEOPLE_RESET = GET_PEOPLE + '_RESET'; + +export function getEventPeople(event) { + return withApplicationId(id => { + const promise = api.getEventPeople(id,event); + return createAction(GET_PEOPLE, { promise }); + }); +} + +export function getEventPeopleReset() { + return createAction(GET_PEOPLE_RESET); +} + +// Reducer +const initialState = []; +export default function peopleReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + case GET_PEOPLE_RESET: + return initialState; + case GET_PEOPLE_SUCCESS: + return action.payload.map(ev=>new PersonInfo(ev)); + } + return state; +}; + +// Selectors +export const peopleStatusSelector = createPromiseStatusSelector(GET_PEOPLE); +export const peopleSelector = createSelector([moduleSelector], state => state.events); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js index be57fa71..db374c01 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js @@ -8,4 +8,12 @@ export const EventInfo = Record({ info: "info" }); +export const PersonInfo = Record({ + url: "url", + name: "name", + description: "description", + image: "image_url", + info: "info" +}); + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js index 976cdf36..f43964a8 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js @@ -5,7 +5,6 @@ import { Visualizer } from '../../../core/models' import EventLoader from '../containers/EventLoader' import { getConfiguration, getConfigurationReset } from '../ducks/configuration' - class Configurator extends Component { static propTypes = { application: PropTypes.instanceOf(Application).isRequired, @@ -19,7 +18,7 @@ class Configurator extends Component {

This is the graph visualizer configurator.

{application.name}

{visualizer.title}

-
+
) diff --git a/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala index ae4fe302..ba333fcb 100644 --- a/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala +++ b/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala @@ -20,9 +20,11 @@ class EventVisualizerApiController(implicit inj: Injector) extends VisualizerApi } } def getEventPeople(id: Long) = RestAsyncAction[EventPeopleRequest] { implicit request => json => - withEvaluation(ApplicationId(id)) { evaluation => - var people = rgmlService.eventPeople(evaluation, json.event) - Future(Ok(SuccessResponse(data = Seq("people" -> people)))) + cached { + withEvaluation(ApplicationId(id)) { evaluation => + var people = rgmlService.eventPeople(evaluation, json.event) + Future(Ok(SuccessResponse(data = Seq("people" -> people)))) + } } } } \ No newline at end of file From 2685322156bddfba903682102e2ddab88de4e6aa Mon Sep 17 00:00:00 2001 From: vvancak Date: Mon, 27 Mar 2017 00:32:25 +0200 Subject: [PATCH 13/84] EventTimeline: Events in table --- .../events/containers/EventLoader.js | 38 ++++++------------- .../modules/visualizers/events/ducks/dirty.js | 13 ------- .../visualizers/events/pages/Configurator.js | 6 +-- .../rdf/sparql/rgml/query/EventQuery.scala | 2 +- src/package.json | 1 - 5 files changed, 13 insertions(+), 47 deletions(-) delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js index 02dffbcc..3dd1c925 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js @@ -4,7 +4,6 @@ import { createStructuredSelector } from 'reselect' import { getEvents, getEventsReset, eventsSelector, eventsStatusSelector } from '../ducks/events' import { PromiseStatus } from '../../../core/models' import PromiseResult from '../../../core/components/PromiseResult' -import TimelineChart from 'd3-timeline-chart' class EventLoader extends Component { static propTypes = { @@ -15,7 +14,7 @@ class EventLoader extends Component { componentWillMount() { const {dispatch} = this.props; - dispatch(getEvents()); + dispatch(getEvents((new Date("1900-01-01")),(new Date("2017-01-01")),20)); } componentWillUnmount() { @@ -27,35 +26,20 @@ class EventLoader extends Component { const {events, status} = this.props; if (!status.done) { - return + return } - const element = document.getElementById("chart_placeholder"); - const data = [{ - label: 'Name', - data: [ { - label: 'I\'m a label', - type: TimelineChart.TYPE.INTERVAL, - from: new Date([2015, 2, 1]), - to: new Date([2015, 3, 1]) - }] - }, { label: 'Event', data: { - label: 'I\'m a label II', - type: TimelineChart.TYPE.INTERVAL, - from: new Date([2015, 2, 20]), - to: new Date([2015, 3, 20]) - } - }]; + if (events.length == 0) { + return

No events loaded - nothing to visualize.

+ } - var chart = new TimelineChart(element, data, { - tip: function(d) { - return d.at || `${d.from}
${d.to}`; - }, - width: 1000, - height: 1000 - }); + const listItems = events.map((ev) => +
  • {ev.name}
  • + ); - return
    ; + return ( +
      {listItems}
    + ); } } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js deleted file mode 100644 index ae5d4042..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js +++ /dev/null @@ -1,13 +0,0 @@ -import { createSelector } from 'reselect' -import moduleSelector from '../selector' -import { createDirtyReducer } from '../../../app/ducks/dirty' - -// Reducer - -const actions = [ ]; - -export default createDirtyReducer(actions); - -// Selectors - -export const dirtySelector = createSelector([moduleSelector], state => state.dirty); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js index f43964a8..96482771 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js @@ -15,11 +15,7 @@ class Configurator extends Component { const { application, visualizer } = this.props; return ( -

    This is the graph visualizer configurator.

    -

    {application.name}

    -

    {visualizer.title}

    -
    - + ) } diff --git a/src/app/model/rdf/sparql/rgml/query/EventQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventQuery.scala index 752d3fcb..a7cf3b4d 100644 --- a/src/app/model/rdf/sparql/rgml/query/EventQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/EventQuery.scala @@ -23,7 +23,7 @@ class EventQuery(start: Date, end: Date, limit: Int) extends SparqlQuery{ | dbo:wikiPageExternalLink ?eventLink . | | FILTER (?eventStart > "@start"^^xsd:date) - | FILTER (?eventEnd < "@end"^^xsd:date) + | FILTER (?eventStart < "@end"^^xsd:date) | | FILTER EXISTS { | ?person rdf:type sch:Person ; diff --git a/src/package.json b/src/package.json index 0d18e13a..d34fa67b 100644 --- a/src/package.json +++ b/src/package.json @@ -10,7 +10,6 @@ "babel-polyfill": "6.3.x", "classnames": "2.2.x", "d3": "3.5.x", - "d3-timeline-chart": "^1.3.0", "d3-tip": "^0.6.8", "debug": "2.2.x", "flexboxgrid": "^6.3.1", From ffca1bf4351838db63b8183e34a5b423882f7b10 Mon Sep 17 00:00:00 2001 From: vvancak Date: Mon, 27 Mar 2017 01:10:16 +0200 Subject: [PATCH 14/84] EventTimeline: Queries work, data ready --- .../modules/visualizers/events/api.js | 2 +- .../events/containers/EventLoader.js | 4 +- .../events/containers/PeopleLoader.js | 50 +++++++++++++++++++ .../visualizers/events/ducks/people.js | 7 ++- .../visualizers/events/pages/Configurator.js | 2 + .../modules/visualizers/events/reducer.js | 4 +- .../sparql/rgml/query/EventPeopleQuery.scala | 2 +- 7 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js index 059b1ca5..1ae3f85e 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js @@ -7,6 +7,6 @@ export async function getEvents(applicationId, start, end, limit) { } export async function getEventPeople(applicationId, event) { - const result = await rest('eventVisualizer/getEventPeople/' + applicationId, {"event" : event.url}); + const result = await rest('eventVisualizer/getEventPeople/' + applicationId, {"event" : event}); return result.data.people; } \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js index 3dd1c925..41b65f64 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js @@ -29,12 +29,12 @@ class EventLoader extends Component { return } - if (events.length == 0) { + if (events == null || events.length == 0) { return

    No events loaded - nothing to visualize.

    } const listItems = events.map((ev) => -
  • {ev.name}
  • +
  • {ev.name}
  • ); return ( diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js new file mode 100644 index 00000000..1369dab3 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js @@ -0,0 +1,50 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from 'reselect' +import { getEventPeople, getEventPeopleReset, peopleSelector, peopleStatusSelector } from '../ducks/people' +import { PromiseStatus } from '../../../core/models' +import PromiseResult from '../../../core/components/PromiseResult' + +class PeopleLoader extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + people: PropTypes.instanceOf(Array).isRequired, + status: PropTypes.instanceOf(PromiseStatus).isRequired + }; + + componentWillMount() { + const {dispatch} = this.props; + dispatch(getEventPeople("http://dbpedia.org/resource/World_Film_Festival_of_Bangkok")); + } + + componentWillUnmount() { + const {dispatch} = this.props; + dispatch(getEventPeopleReset()); + } + + render() { + const {people, status} = this.props; + + if (!status.done) { + return + } + + if (people==null || people.length == 0) { + return

    No people loaded - nothing to visualize.

    + } + const listItems = people.map((p) => +
  • {p.name}
  • + ); + + return ( +
      {listItems}
    + ); + } +} + +const selector = createStructuredSelector({ + people: peopleSelector, + status: peopleStatusSelector +}); + +export default connect(selector)(PeopleLoader); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js index 823c9570..0d9fc183 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js @@ -31,14 +31,17 @@ const initialState = []; export default function peopleReducer(state = initialState, action) { switch (action.type) { case GET_APPLICATION_START: + return initialState; case GET_PEOPLE_RESET: return initialState; + case GET_PEOPLE_ERROR: + return action.payload; case GET_PEOPLE_SUCCESS: - return action.payload.map(ev=>new PersonInfo(ev)); + return action.payload.map(p=>new PersonInfo(p)); } return state; }; // Selectors export const peopleStatusSelector = createPromiseStatusSelector(GET_PEOPLE); -export const peopleSelector = createSelector([moduleSelector], state => state.events); \ No newline at end of file +export const peopleSelector = createSelector([moduleSelector], state => state.people); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js index 96482771..3bd0233e 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js @@ -3,6 +3,7 @@ import BodyPadding from '../../../../components/BodyPadding' import { Application } from '../../../app/models' import { Visualizer } from '../../../core/models' import EventLoader from '../containers/EventLoader' +import PeopleLoader from '../containers/PeopleLoader' import { getConfiguration, getConfigurationReset } from '../ducks/configuration' class Configurator extends Component { @@ -16,6 +17,7 @@ class Configurator extends Component { return ( + ) } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js index c9cf6520..73f2a052 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js @@ -1,8 +1,10 @@ import { combineReducers } from 'redux'; import events from './ducks/events' +import people from './ducks/people' const rootReducer = combineReducers({ - events + events, + people }); export default rootReducer; \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala index 20bcfa3f..acc13452 100644 --- a/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala @@ -19,7 +19,7 @@ class EventPeopleQuery(event: String) extends SparqlQuery { | ?person rdf:type sch:Person ; | foaf:name ?personName; | foaf:isPrimaryTopicOf ?personLink; - | foaf:depiction ?personImage;s + | foaf:depiction ?personImage; | dbp:shortDescription ?personDescription; | ?relation ?event . |} From f53019a29d189c579efa0370717424ea6432e63c Mon Sep 17 00:00:00 2001 From: vvancak Date: Mon, 27 Mar 2017 19:20:44 +0200 Subject: [PATCH 15/84] EventTimeline: Version revert, react-addons blocking installations --- src/npm-shrinkwrap.json | 20 +++++--------------- src/package.json | 11 +++++------ 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/npm-shrinkwrap.json b/src/npm-shrinkwrap.json index 36bf30f9..9b139910 100644 --- a/src/npm-shrinkwrap.json +++ b/src/npm-shrinkwrap.json @@ -7,6 +7,11 @@ "from": "babel-polyfill@>=6.3.0 <6.4.0", "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.3.14.tgz", "dependencies": { + "core-js": { + "version": "1.2.7", + "from": "core-js@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz" + }, "babel-regenerator-runtime": { "version": "6.5.0", "from": "babel-regenerator-runtime@>=6.3.13 <7.0.0", @@ -16,11 +21,6 @@ "version": "5.8.38", "from": "babel-runtime@>=5.0.0 <6.0.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.38.tgz" - }, - "core-js": { - "version": "1.2.7", - "from": "core-js@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz" } } }, @@ -34,16 +34,6 @@ "from": "d3@>=3.5.0 <3.6.0", "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz" }, - "d3-timeline-chart": { - "version": "1.3.0", - "from": "d3-timeline-chart@latest", - "resolved": "https://registry.npmjs.org/d3-timeline-chart/-/d3-timeline-chart-1.3.0.tgz" - }, - "d3-tip": { - "version": "0.6.7", - "from": "d3-tip@0.6.7", - "resolved": "https://registry.npmjs.org/d3-tip/-/d3-tip-0.6.7.tgz" - }, "debug": { "version": "2.2.0", "from": "debug@>=2.2.0 <2.3.0", diff --git a/src/package.json b/src/package.json index d34fa67b..1a7dc3f9 100644 --- a/src/package.json +++ b/src/package.json @@ -10,14 +10,13 @@ "babel-polyfill": "6.3.x", "classnames": "2.2.x", "d3": "3.5.x", - "d3-tip": "^0.6.8", "debug": "2.2.x", - "flexboxgrid": "^6.3.1", + "flexboxgrid": "6.3.x", "hash-string": "1.0.x", "history": "2.0.0-rc2", "immutable": "3.7.x", "lodash": "4.6.x", - "material-ui": "^0.15.4", + "material-ui": "0.15.x", "moment": "2.13.x", "react": "15.2.x", "react-dom": "15.1.x", @@ -25,10 +24,10 @@ "react-google-maps": "4.11.x", "react-helmet": "2.3.x", "react-pure-render": "1.0.x", - "react-redux": "^4.4.6", + "react-redux": "4.4.x", "react-router": "2.0.0-rc5", "react-tap-event-plugin": "1.0.x", - "redux": "^3.6.0", + "redux": "^3.0.0", "redux-form": "5.2.x", "redux-logger": "2.0.x", "redux-promise-middleware": "2.3.x", @@ -38,7 +37,7 @@ "reselect": "2.0.x", "revalidator": "0.3.x", "scriptjs": "2.5.x", - "when": "^3.7.8" + "when": "3.7.x" }, "devDependencies": { "autoprefixer": "6.3.x", From 5dff18c860df8312dafdc1d8b0438961f8a36678 Mon Sep 17 00:00:00 2001 From: vvancak Date: Wed, 29 Mar 2017 00:50:57 +0200 Subject: [PATCH 16/84] EventTimeline: Data visualization added, scaling improvements pending --- .../events/components/Application.js | 18 +- .../events/components/SaveButton.js | 10 + .../visualizers/events/components/Timeline.js | 45 ++ .../events/containers/EventLoader.js | 30 +- .../events/containers/PeopleLoader.js | 5 +- .../modules/visualizers/events/ducks/dirty.js | 11 + .../visualizers/events/misc/timeline.js | 684 ++++++++++++++++++ .../visualizers/events/pages/Configurator.js | 5 +- 8 files changed, 787 insertions(+), 21 deletions(-) create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Timeline.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/timeline.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js index 393fcf04..6bb66450 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js @@ -3,6 +3,9 @@ import BodyPadding from '../../../../components/BodyPadding' import { Application as ApplicationModel } from '../../../app/models' import { Visualizer } from '../../../core/models' import EventLoader from '../containers/EventLoader' +import SaveButton from '../components/SaveButton' +import { getConfiguration, getConfigurationReset } from '../ducks/configuration' + class Application extends Component { static propTypes = { @@ -11,16 +14,23 @@ class Application extends Component { embed: PropTypes.bool }; + componentWillMount() { + const { dispatch } = this.props; + dispatch(getConfiguration()); + } + + componentWillUnmount() { + const { dispatch } = this.props; + dispatch(getConfigurationReset()); + } render() { const { application, visualizer, embed } = this.props; return ( -

    This is the event visualizer application.

    -

    It runs in {embed ? 'embed' : 'standalone'} mode

    -

    {application.name}

    -

    {visualizer.title}

    +

    This is the {visualizer.name} in {application.name} in {embed ? 'embed' : 'standalone'} mode.

    +
    ) } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js new file mode 100644 index 00000000..df19c4fd --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js @@ -0,0 +1,10 @@ +import React, { PropTypes } from 'react' +import { saveConfiguration, saveConfigurationStatusSelector } from '../ducks/configuration' +import { dirtySelector } from '../ducks/dirty' + +import createSaveButton from '../../../app/containers/createSaveButton' + +export default createSaveButton( + saveConfiguration, + saveConfigurationStatusSelector, + dirtySelector); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Timeline.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Timeline.js new file mode 100644 index 00000000..a397fe84 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Timeline.js @@ -0,0 +1,45 @@ +import React, { Component, PropTypes } from 'react' +import timeline from '../misc/timeline' +import makePureRender from '../../../../misc/makePureRender' +import {getAvailableVerticalSpace} from "../../../../components/FillInScreen"; +import {bodyPaddingSpace} from "../../../../components/BodyPadding"; +import d3 from 'd3' + +class Timeline extends Component { + static propTypes = { + data: PropTypes.instanceOf(Array).isRequired, + start: PropTypes.number.isRequired, + end: PropTypes.number.isRequired + }; + + componentDidMount(){ + this.chart = timeline(); + this.renderChart(); + } + + componentDidUpdate(){ + this.renderChart() + } + + renderChart(){ + const size = Math.max(getAvailableVerticalSpace(this.refs.timeline) - bodyPaddingSpace, 450); + + this.chart + .margin({left:70, right:30, top:0, bottom:0}) + .beginning(this.props.start) + .ending(this.props.end); + + var svg = d3.select(this.refs.timeline) + .append("svg") + .attr("width", size) + .attr("height", size/2) + .datum(this.props.data) + .call(this.chart); + } + + render() { + return
    + } +} +export default makePureRender(Timeline); + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js index 41b65f64..bac5d613 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js @@ -4,6 +4,7 @@ import { createStructuredSelector } from 'reselect' import { getEvents, getEventsReset, eventsSelector, eventsStatusSelector } from '../ducks/events' import { PromiseStatus } from '../../../core/models' import PromiseResult from '../../../core/components/PromiseResult' +import Timeline from '../components/Timeline' class EventLoader extends Component { static propTypes = { @@ -22,24 +23,31 @@ class EventLoader extends Component { dispatch(getEventsReset()); } + getChartFormat(eventInfo) { + var start = parseInt(eventInfo.start); + var end = parseInt(eventInfo.end); + var data = { + class: eventInfo.url, + label: eventInfo.name, + times: [{ + starting_time: start, + ending_time: end}] + }; + return data; + } + render() { const {events, status} = this.props; - if (!status.done) { return } - - if (events == null || events.length == 0) { + else if (!events || events.length == 0) { return

    No events loaded - nothing to visualize.

    } - - const listItems = events.map((ev) => -
  • {ev.name}
  • - ); - - return ( -
      {listItems}
    - ); + var data = events.map(this.getChartFormat); + var start = Math.min(data.map(d=>d.times.starting_time)); + var end = Math.max(data.map(d=>d.times.ending_time)); + return } } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js index 1369dab3..2f86ca0c 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js @@ -32,12 +32,9 @@ class PeopleLoader extends Component { if (people==null || people.length == 0) { return

    No people loaded - nothing to visualize.

    } - const listItems = people.map((p) => -
  • {p.name}
  • - ); return ( -
      {listItems}
    +

    {people[0].name}

    ); } } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js new file mode 100644 index 00000000..d441b886 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js @@ -0,0 +1,11 @@ +import { createSelector } from 'reselect' +import moduleSelector from '../selector' +import { createDirtyReducer } from '../../../app/ducks/dirty' + +// Reducer +const actions = [ ]; + +export default createDirtyReducer(actions); + +// Selectors +export const dirtySelector = createSelector([moduleSelector], state => state.dirty); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/timeline.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/timeline.js new file mode 100644 index 00000000..c1308701 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/timeline.js @@ -0,0 +1,684 @@ +import d3 from 'd3' + +export default function timeline() { + var DISPLAY_TYPES = ["circle", "rect"], + hover = function () {}, + mouseover = function () {}, + mouseout = function () {}, + click = function () {}, + scroll = function () {}, + labelFunction = function(label) { return label; }, + navigateLeft = function () {}, + navigateRight = function () {}, + orient = "bottom", + width = null, + height = null, + rowSeparatorsColor = null, + backgroundColor = null, + tickFormat = { format: d3.time.format("%I %p"), + tickTime: d3.time.hours, + tickInterval: 1, + tickSize: 6, + tickValues: null + }, + colorCycle = d3.scale.category20(), + colorPropertyName = null, + display = "rect", + beginning = 0, + labelMargin = 0, + ending = 0, + margin = {left: 30, right:30, top: 30, bottom:30}, + stacked = false, + rotateTicks = false, + timeIsRelative = false, + fullLengthBackgrounds = false, + itemHeight = 20, + itemMargin = 5, + navMargin = 60, + showTimeAxis = true, + showAxisTop = false, + showTodayLine = false, + timeAxisTick = false, + timeAxisTickFormat = {stroke: "stroke-dasharray", spacing: "4 10"}, + showTodayFormat = {marginTop: 25, marginBottom: 0, width: 1, color: colorCycle}, + showBorderLine = false, + showBorderFormat = {marginTop: 25, marginBottom: 0, width: 1, color: colorCycle}, + showAxisHeaderBackground = false, + showAxisNav = false, + showAxisCalendarYear = false, + axisBgColor = "white", + chartData = {} + ; + + var appendTimeAxis = function(g, xAxis, yPosition) { + + if(showAxisHeaderBackground){ appendAxisHeaderBackground(g, 0, 0); } + + if(showAxisNav){ appendTimeAxisNav(g) }; + + var axis = g.append("g") + .attr("class", "axis") + .attr("transform", "translate(" + 0 + "," + yPosition + ")") + .call(xAxis); + }; + + var appendTimeAxisCalendarYear = function (nav) { + var calendarLabel = beginning.getFullYear(); + + if (beginning.getFullYear() != ending.getFullYear()) { + calendarLabel = beginning.getFullYear() + "-" + ending.getFullYear() + } + + nav.append("text") + .attr("transform", "translate(" + 20 + ", 0)") + .attr("x", 0) + .attr("y", 14) + .attr("class", "calendarYear") + .text(calendarLabel) + ; + }; + var appendTimeAxisNav = function (g) { + var timelineBlocks = 6; + var leftNavMargin = (margin.left - navMargin); + var incrementValue = (width - margin.left)/timelineBlocks; + var rightNavMargin = (width - margin.right - incrementValue + navMargin); + + var nav = g.append('g') + .attr("class", "axis") + .attr("transform", "translate(0, 20)") + ; + + if(showAxisCalendarYear) { appendTimeAxisCalendarYear(nav) }; + + nav.append("text") + .attr("transform", "translate(" + leftNavMargin + ", 0)") + .attr("x", 0) + .attr("y", 14) + .attr("class", "chevron") + .text("<") + .on("click", function () { + return navigateLeft(beginning, chartData); + }) + ; + + nav.append("text") + .attr("transform", "translate(" + rightNavMargin + ", 0)") + .attr("x", 0) + .attr("y", 14) + .attr("class", "chevron") + .text(">") + .on("click", function () { + return navigateRight(ending, chartData); + }) + ; + }; + + var appendAxisHeaderBackground = function (g, xAxis, yAxis) { + g.insert("rect") + .attr("class", "row-green-bar") + .attr("x", xAxis) + .attr("width", width) + .attr("y", yAxis) + .attr("height", itemHeight) + .attr("fill", axisBgColor); + }; + + var appendTimeAxisTick = function(g, xAxis, maxStack) { + g.append("g") + .attr("class", "axis") + .attr("transform", "translate(" + 0 + "," + (margin.top + (itemHeight + itemMargin) * maxStack) + ")") + .attr(timeAxisTickFormat.stroke, timeAxisTickFormat.spacing) + .call(xAxis.tickFormat("").tickSize(-(margin.top + (itemHeight + itemMargin) * (maxStack - 1) + 3), 0, 0)); + }; + + var appendBackgroundBar = function (yAxisMapping, index, g, data, datum) { + var greenbarYAxis = ((itemHeight + itemMargin) * yAxisMapping[index]) + margin.top; + g.selectAll("svg").data(data).enter() + .insert("rect") + .attr("class", "row-green-bar") + .attr("x", fullLengthBackgrounds ? 0 : margin.left) + .attr("width", fullLengthBackgrounds ? width : (width - margin.right - margin.left)) + .attr("y", greenbarYAxis) + .attr("height", itemHeight) + .attr("fill", backgroundColor instanceof Function ? backgroundColor(datum, index) : backgroundColor) + ; + }; + + var appendLabel = function (gParent, yAxisMapping, index, hasLabel, datum) { + var fullItemHeight = itemHeight + itemMargin; + var rowsDown = margin.top + (fullItemHeight/2) + fullItemHeight * (yAxisMapping[index] || 1); + + gParent.append("text") + .attr("class", "timeline-label") + .attr("transform", "translate(" + labelMargin + "," + rowsDown + ")") + .text(hasLabel ? labelFunction(datum.label) : datum.id) + .on("click", function (d, i) { click(d, index, datum); }); + }; + + function timeline (gParent) { + var g = gParent.append("g"); + var gParentSize = gParent[0][0].getBoundingClientRect(); + + var gParentItem = d3.select(gParent[0][0]); + + var yAxisMapping = {}, + maxStack = 1, + minTime = 0, + maxTime = 0; + + setWidth(); + + // check if the user wants relative time + // if so, substract the first timestamp from each subsequent timestamps + if(timeIsRelative){ + g.each(function (d, i) { + d.forEach(function (datum, index) { + datum.forEach(function (data, j) { + data.starting_time = this.startExtractor() + + if(index === 0 && j === 0){ + originTime = time.starting_time //Store the timestamp that will serve as origin + time.starting_time = 0; //Set the origin + time.ending_time = time.ending_time - originTime; //Store the relative time (millis) + }else{ + time.starting_time = time.starting_time - originTime; + time.ending_time = time.ending_time - originTime; + } + }); + }); + }); + } + + // check how many stacks we're gonna need + // do this here so that we can draw the axis before the graph + if (stacked || ending === 0 || beginning === 0) { + g.each(function (d, i) { + d.forEach(function (datum, index) { + + // create y mapping for stacked graph + if (stacked && Object.keys(yAxisMapping).indexOf(index) == -1) { + yAxisMapping[index] = maxStack; + maxStack++; + } + + // figure out beginning and ending times if they are unspecified + datum.times.forEach(function (time, i) { + if(beginning === 0) + if (time.starting_time < minTime || (minTime === 0 && timeIsRelative === false)) + minTime = time.starting_time; + if(ending === 0) + if (time.ending_time > maxTime) + maxTime = time.ending_time; + }); + }); + }); + + if (ending === 0) { + ending = maxTime; + } + if (beginning === 0) { + beginning = minTime; + } + } + + var scaleFactor = (1/(ending - beginning)) * (width - margin.left - margin.right); + + // draw the axis + var xScale = d3.time.scale() + .domain([beginning, ending]) + .range([margin.left, width - margin.right]); + + var xAxis = d3.svg.axis() + .scale(xScale) + .orient(orient) + .tickFormat(tickFormat.format) + .tickSize(tickFormat.tickSize); + + if (tickFormat.tickValues != null) { + xAxis.tickValues(tickFormat.tickValues); + } else { + xAxis.ticks(tickFormat.numTicks || tickFormat.tickTime, tickFormat.tickInterval); + } + + // draw the chart + g.each(function(d, i) { + chartData = d; + d.forEach( function(datum, index){ + var data = datum.times; + var hasLabel = (typeof(datum.label) != "undefined"); + + // issue warning about using id per data set. Ids should be individual to data elements + if (typeof(datum.id) != "undefined") { + console.warn("d3Timeline Warning: Ids per dataset is deprecated in favor of a 'class' key. Ids are now per data element."); + } + + if (backgroundColor) { appendBackgroundBar(yAxisMapping, index, g, data, datum); } + + g.selectAll("svg").data(data).enter() + .append(function(d, i) { + return document.createElementNS(d3.ns.prefix.svg, "display" in d? d.display:display); + }) + .attr("x", getXPos) + .attr("y", getStackPosition) + .attr("width", function (d, i) { + return (d.ending_time - d.starting_time) * scaleFactor; + }) + .attr("cy", function(d, i) { + return getStackPosition(d, i) + itemHeight/2; + }) + .attr("cx", getXPos) + .attr("r", itemHeight / 2) + .attr("height", itemHeight) + .style("fill", function(d, i){ + var dColorPropName; + if (d.color) return d.color; + if( colorPropertyName ){ + dColorPropName = d[colorPropertyName]; + if ( dColorPropName ) { + return colorCycle( dColorPropName ); + } else { + return colorCycle( datum[colorPropertyName] ); + } + } + return colorCycle(index); + }) + .on("mousemove", function (d, i) { + hover(d, index, datum); + }) + .on("mouseover", function (d, i) { + mouseover(d, i, datum); + }) + .on("mouseout", function (d, i) { + mouseout(d, i, datum); + }) + .on("click", function (d, i) { + click(d, index, datum); + }) + .attr("class", function (d, i) { + return datum.class ? "timelineSeries_"+datum.class : "timelineSeries_"+index; + }) + .attr("id", function(d, i) { + // use deprecated id field + if (datum.id && !d.id) { + return 'timelineItem_'+datum.id; + } + + return d.id ? d.id : "timelineItem_"+index+"_"+i; + }) + ; + + g.selectAll("svg").data(data).enter() + .append("text") + .attr("x", getXTextPos) + .attr("y", getStackTextPosition) + .text(function(d) { + return d.label; + }) + ; + + if (rowSeparatorsColor) { + var lineYAxis = ( itemHeight + itemMargin / 2 + margin.top + (itemHeight + itemMargin) * yAxisMapping[index]); + gParent.append("svg:line") + .attr("class", "row-separator") + .attr("x1", 0 + margin.left) + .attr("x2", width - margin.right) + .attr("y1", lineYAxis) + .attr("y2", lineYAxis) + .attr("stroke-width", 1) + .attr("stroke", rowSeparatorsColor); + } + + // add the label + if (hasLabel) { appendLabel(gParent, yAxisMapping, index, hasLabel, datum); } + + if (typeof(datum.icon) !== "undefined") { + gParent.append("image") + .attr("class", "timeline-label") + .attr("transform", "translate("+ 0 +","+ (margin.top + (itemHeight + itemMargin) * yAxisMapping[index])+")") + .attr("xlink:href", datum.icon) + .attr("width", margin.left) + .attr("height", itemHeight); + } + + function getStackPosition(d, i) { + if (stacked) { + return margin.top + (itemHeight + itemMargin) * yAxisMapping[index]; + } + return margin.top; + } + function getStackTextPosition(d, i) { + if (stacked) { + return margin.top + (itemHeight + itemMargin) * yAxisMapping[index] + itemHeight * 0.75; + } + return margin.top + itemHeight * 0.75; + } + }); + }); + + var belowLastItem = (margin.top + (itemHeight + itemMargin) * maxStack); + var aboveFirstItem = margin.top; + var timeAxisYPosition = showAxisTop ? aboveFirstItem : belowLastItem; + if (showTimeAxis) { appendTimeAxis(g, xAxis, timeAxisYPosition); } + if (timeAxisTick) { appendTimeAxisTick(g, xAxis, maxStack); } + + if (width > gParentSize.width) { + var move = function() { + var x = Math.min(0, Math.max(gParentSize.width - width, d3.event.translate[0])); + zoom.translate([x, 0]); + g.attr("transform", "translate(" + x + ",0)"); + scroll(x*scaleFactor, xScale); + }; + + var zoom = d3.behavior.zoom().x(xScale).on("zoom", move); + + gParent + .attr("class", "scrollable") + .call(zoom); + } + + if (rotateTicks) { + g.selectAll(".tick text") + .attr("transform", function(d) { + return "rotate(" + rotateTicks + ")translate(" + + (this.getBBox().width / 2 + 10) + "," // TODO: change this 10 + + this.getBBox().height / 2 + ")"; + }); + } + + var gSize = g[0][0].getBoundingClientRect(); + setHeight(); + + if (showBorderLine) { + g.each(function (d, i) { + d.forEach(function (datum) { + var times = datum.times; + times.forEach(function (time) { + appendLine(xScale(time.starting_time), showBorderFormat); + appendLine(xScale(time.ending_time), showBorderFormat); + }); + }); + }); + } + + if (showTodayLine) { + var todayLine = xScale(new Date()); + appendLine(todayLine, showTodayFormat); + } + + function getXPos(d, i) { + return margin.left + (d.starting_time - beginning) * scaleFactor; + } + + function getXTextPos(d, i) { + return margin.left + (d.starting_time - beginning) * scaleFactor + 5; + } + + function setHeight() { + if (!height && !gParentItem.attr("height")) { + if (itemHeight) { + // set height based off of item height + height = gSize.height + gSize.top - gParentSize.top; + // set bounding rectangle height + d3.select(gParent[0][0]).attr("height", height); + } else { + throw "height of the timeline is not set"; + } + } else { + if (!height) { + height = gParentItem.attr("height"); + } else { + gParentItem.attr("height", height); + } + } + } + + function setWidth() { + if (!width && !gParentSize.width) { + try { + width = gParentItem.attr("width"); + if (!width) { + throw "width of the timeline is not set. As of Firefox 27, timeline().with(x) needs to be explicitly set in order to render"; + } + } catch (err) { + console.log( err ); + } + } else if (!(width && gParentSize.width)) { + try { + width = gParentItem.attr("width"); + } catch (err) { + console.log( err ); + } + } + // if both are set, do nothing + } + + function appendLine(lineScale, lineFormat) { + gParent.append("svg:line") + .attr("x1", lineScale) + .attr("y1", lineFormat.marginTop) + .attr("x2", lineScale) + .attr("y2", height - lineFormat.marginBottom) + .style("stroke", lineFormat.color)//"rgb(6,120,155)") + .style("stroke-width", lineFormat.width); + } + } + + // === SETTINGS === + timeline.margin = function (p) { + if (!arguments.length) return margin; + margin = p; + return timeline; + }; + + timeline.orient = function (orientation) { + if (!arguments.length) return orient; + orient = orientation; + return timeline; + }; + + timeline.itemHeight = function (h) { + if (!arguments.length) return itemHeight; + itemHeight = h; + return timeline; + }; + + timeline.itemMargin = function (h) { + if (!arguments.length) return itemMargin; + itemMargin = h; + return timeline; + }; + + timeline.navMargin = function (h) { + if (!arguments.length) return navMargin; + navMargin = h; + return timeline; + }; + + timeline.height = function (h) { + if (!arguments.length) return height; + height = h; + return timeline; + }; + + timeline.width = function (w) { + if (!arguments.length) return width; + width = w; + return timeline; + }; + + timeline.display = function (displayType) { + if (!arguments.length || (DISPLAY_TYPES.indexOf(displayType) == -1)) return display; + display = displayType; + return timeline; + }; + + timeline.labelFormat = function(f) { + if (!arguments.length) return labelFunction; + labelFunction = f; + return timeline; + }; + + timeline.tickFormat = function (format) { + if (!arguments.length) return tickFormat; + tickFormat = format; + return timeline; + }; + + // Mouse actions + timeline.hover = function (hoverFunc) { + if (!arguments.length) return hover; + hover = hoverFunc; + return timeline; + }; + + timeline.mouseover = function (mouseoverFunc) { + if (!arguments.length) return mouseover; + mouseover = mouseoverFunc; + return timeline; + }; + + timeline.mouseout = function (mouseoutFunc) { + if (!arguments.length) return mouseout; + mouseout = mouseoutFunc; + return timeline; + }; + + timeline.click = function (clickFunc) { + if (!arguments.length) return click; + click = clickFunc; + return timeline; + }; + + timeline.scroll = function (scrollFunc) { + if (!arguments.length) return scroll; + scroll = scrollFunc; + return timeline; + }; + + timeline.colors = function (colorFormat) { + if (!arguments.length) return colorCycle; + colorCycle = colorFormat; + return timeline; + }; + + timeline.beginning = function (b) { + if (!arguments.length) return beginning; + beginning = b; + return timeline; + }; + + timeline.ending = function (e) { + if (!arguments.length) return ending; + ending = e; + return timeline; + }; + + timeline.labelMargin = function (m) { + if (!arguments.length) return labelMargin; + labelMargin = m; + return timeline; + }; + + timeline.rotateTicks = function (degrees) { + if (!arguments.length) return rotateTicks; + rotateTicks = degrees; + return timeline; + }; + + timeline.stack = function () { + stacked = !stacked; + return timeline; + }; + + timeline.relativeTime = function() { + timeIsRelative = !timeIsRelative; + return timeline; + }; + + timeline.showBorderLine = function () { + showBorderLine = !showBorderLine; + return timeline; + }; + + timeline.showBorderFormat = function(borderFormat) { + if (!arguments.length) return showBorderFormat; + showBorderFormat = borderFormat; + return timeline; + }; + + timeline.showToday = function () { + showTodayLine = !showTodayLine; + return timeline; + }; + + timeline.showTodayFormat = function(todayFormat) { + if (!arguments.length) return showTodayFormat; + showTodayFormat = todayFormat; + return timeline; + }; + + timeline.colorProperty = function(colorProp) { + if (!arguments.length) return colorPropertyName; + colorPropertyName = colorProp; + return timeline; + }; + + timeline.rowSeparators = function (color) { + if (!arguments.length) return rowSeparatorsColor; + rowSeparatorsColor = color; + return timeline; + + }; + + timeline.background = function (color) { + if (!arguments.length) return backgroundColor; + backgroundColor = color; + return timeline; + }; + + timeline.showTimeAxis = function () { + showTimeAxis = !showTimeAxis; + return timeline; + }; + + timeline.showAxisTop = function () { + showAxisTop = !showAxisTop; + return timeline; + }; + + timeline.showAxisCalendarYear = function () { + showAxisCalendarYear = !showAxisCalendarYear; + return timeline; + }; + + timeline.showTimeAxisTick = function () { + timeAxisTick = !timeAxisTick; + return timeline; + }; + + timeline.fullLengthBackgrounds = function () { + fullLengthBackgrounds = !fullLengthBackgrounds; + return timeline; + }; + + timeline.showTimeAxisTickFormat = function(format) { + if (!arguments.length) return timeAxisTickFormat; + timeAxisTickFormat = format; + return timeline; + }; + + timeline.showAxisHeaderBackground = function(bgColor) { + showAxisHeaderBackground = !showAxisHeaderBackground; + if(bgColor) { (axisBgColor = bgColor) }; + return timeline; + }; + + timeline.navigate = function (navigateBackwards, navigateForwards) { + if (!arguments.length) return [navigateLeft, navigateRight]; + navigateLeft = navigateBackwards; + navigateRight = navigateForwards; + showAxisNav = !showAxisNav; + return timeline; + }; + return timeline; +}; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js index 3bd0233e..a61005f8 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js @@ -3,7 +3,8 @@ import BodyPadding from '../../../../components/BodyPadding' import { Application } from '../../../app/models' import { Visualizer } from '../../../core/models' import EventLoader from '../containers/EventLoader' -import PeopleLoader from '../containers/PeopleLoader' +import PeopleLoader from '../containers/PeopleLoader' //TODO +import SaveButton from '../components/SaveButton' import { getConfiguration, getConfigurationReset } from '../ducks/configuration' class Configurator extends Component { @@ -17,7 +18,7 @@ class Configurator extends Component { return ( - + ) } From 44cf369b9f30d69e831620237ac05e5c6309e4ac Mon Sep 17 00:00:00 2001 From: vvancak Date: Thu, 30 Mar 2017 18:30:10 +0200 Subject: [PATCH 17/84] EventTimeline: Visualizer component rewritten to use TimeSeries --- .../events/components/SaveButton.js | 5 +- .../visualizers/events/components/Timeline.js | 45 -- .../events/containers/EventLoader.js | 21 +- .../events/containers/TimelineContainer.js | 22 + .../modules/visualizers/events/ducks/dirty.js | 5 +- .../visualizers/events/misc/TimeSeries.js | 210 ++++++ .../modules/visualizers/events/misc/style.css | 111 +++ .../visualizers/events/misc/timeline.js | 684 ------------------ src/npm-shrinkwrap.json | 15 +- src/package.json | 1 + 10 files changed, 362 insertions(+), 757 deletions(-) delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Timeline.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/style.css delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/timeline.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js index df19c4fd..04a83be7 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js @@ -4,7 +4,4 @@ import { dirtySelector } from '../ducks/dirty' import createSaveButton from '../../../app/containers/createSaveButton' -export default createSaveButton( - saveConfiguration, - saveConfigurationStatusSelector, - dirtySelector); \ No newline at end of file +export default createSaveButton(saveConfiguration, saveConfigurationStatusSelector, dirtySelector); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Timeline.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Timeline.js deleted file mode 100644 index a397fe84..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Timeline.js +++ /dev/null @@ -1,45 +0,0 @@ -import React, { Component, PropTypes } from 'react' -import timeline from '../misc/timeline' -import makePureRender from '../../../../misc/makePureRender' -import {getAvailableVerticalSpace} from "../../../../components/FillInScreen"; -import {bodyPaddingSpace} from "../../../../components/BodyPadding"; -import d3 from 'd3' - -class Timeline extends Component { - static propTypes = { - data: PropTypes.instanceOf(Array).isRequired, - start: PropTypes.number.isRequired, - end: PropTypes.number.isRequired - }; - - componentDidMount(){ - this.chart = timeline(); - this.renderChart(); - } - - componentDidUpdate(){ - this.renderChart() - } - - renderChart(){ - const size = Math.max(getAvailableVerticalSpace(this.refs.timeline) - bodyPaddingSpace, 450); - - this.chart - .margin({left:70, right:30, top:0, bottom:0}) - .beginning(this.props.start) - .ending(this.props.end); - - var svg = d3.select(this.refs.timeline) - .append("svg") - .attr("width", size) - .attr("height", size/2) - .datum(this.props.data) - .call(this.chart); - } - - render() { - return
    - } -} -export default makePureRender(Timeline); - diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js index bac5d613..b1a36c49 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js @@ -4,7 +4,7 @@ import { createStructuredSelector } from 'reselect' import { getEvents, getEventsReset, eventsSelector, eventsStatusSelector } from '../ducks/events' import { PromiseStatus } from '../../../core/models' import PromiseResult from '../../../core/components/PromiseResult' -import Timeline from '../components/Timeline' +import TimelineContainer from './TimelineContainer' class EventLoader extends Component { static propTypes = { @@ -23,19 +23,6 @@ class EventLoader extends Component { dispatch(getEventsReset()); } - getChartFormat(eventInfo) { - var start = parseInt(eventInfo.start); - var end = parseInt(eventInfo.end); - var data = { - class: eventInfo.url, - label: eventInfo.name, - times: [{ - starting_time: start, - ending_time: end}] - }; - return data; - } - render() { const {events, status} = this.props; if (!status.done) { @@ -44,10 +31,8 @@ class EventLoader extends Component { else if (!events || events.length == 0) { return

    No events loaded - nothing to visualize.

    } - var data = events.map(this.getChartFormat); - var start = Math.min(data.map(d=>d.times.starting_time)); - var end = Math.max(data.map(d=>d.times.ending_time)); - return + debugger; + return } } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js new file mode 100644 index 00000000..5fb464da --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js @@ -0,0 +1,22 @@ +import React, { Component, PropTypes } from 'react' +import TimeSeries from '../misc/TimeSeries' +import makePureRender from '../../../../misc/makePureRender' + +class TimelineContainer extends Component { + static propTypes = { + data: PropTypes.instanceOf(Array).isRequired + }; + + componentDidMount(){ + var domEl = 'timeseries'; + var data = this.props.data; + var chart = new TimeSeries(domEl,data,true); + } + + render() { + require('../misc/style.css'); + return
    + } +} +export default makePureRender(TimelineContainer); + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js index d441b886..fe51fc5d 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js @@ -3,7 +3,10 @@ import moduleSelector from '../selector' import { createDirtyReducer } from '../../../app/ducks/dirty' // Reducer -const actions = [ ]; +const actions = [ + + +]; export default createDirtyReducer(actions); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js new file mode 100644 index 00000000..6513244b --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js @@ -0,0 +1,210 @@ +import d3 from 'd3' +import moment from 'moment' +import * as _ from 'underscore' +import {getAvailableVerticalSpace} from "../../../../components/FillInScreen"; +import {log} from "debug"; + +class TimeSeries { + constructor(spaced, data, enableBrush) { + var classd = spaced.replace(new RegExp(" "), "."); + render(classd, spaced, data, enableBrush); + +// --------------------------------------------------------------------------------------------- +// ---------------------------------- Time Manipulation ---------------------------------------- +// --------------------------------------------------------------------------------------------- + function lessThanDay(d) { + return (d === "hours" || d === "minutes" || d === "seconds") ? true : false; + } + + function getDate(d) { + var date = moment(d); + date.hour(1); + date.minute(0); + date.second(0); + return date.valueOf(); + } + + function getTime(d) { + var date = moment(d); + date.date(1); + date.month(0); + date.year(2012); + return date.valueOf(); + } + + /* + Given a list of time stamps, compute the minimum and maxium dates. Return a padded + version of the min and max dates based on the temporal distance between them. + */ + function timeRangePad(dates) { + var minDate, maxDate, pad; + if (dates.length > 1) { + minDate = moment(_.min(dates)); + maxDate = moment(_.max(dates)); + pad = getDatePadding(minDate, maxDate); + minDate.subtract(1, pad); + maxDate.add(1, pad); + } else { + minDate = moment(dates[0]).subtract(1, 'hour'); + maxDate = moment(dates[0]).add(1, 'hour'); + } + return { + 'minDate': minDate, + 'maxDate': maxDate, + 'pad': pad + }; + }; + + function getDatePadding(minDate, maxDate) { + if (maxDate.diff(minDate, 'years') > 0) + return 'months'; + else if (maxDate.diff(minDate, 'months') > 0) + return 'days'; + else if (maxDate.diff(minDate, 'days') > 0) + return 'days'; + else if (maxDate.diff(minDate, 'hours') > 0) + return 'hours'; + else if (maxDate.diff(minDate, 'minutes') > 0) + return 'minutes'; + else + return 'seconds'; + } + +// --------------------------------------------------------------------------------------------- +// ------------------------------------- Rendering --------------------------------------------- +// --------------------------------------------------------------------------------------------- + + function render(classd, spaced, data, enableBrush) { + + var padding = timeRangePad(_.pluck(data, 'start')); + + var margin = { + top: 10, + right: 25, + bottom: 15, + left: 35 + } +// var width = window.innerWidth - 150; + var width = getAvailableVerticalSpace(document.getElementsByClassName(spaced)[0]); + var height = (lessThanDay(padding.pad)) ? (100 - margin.top - margin.bottom) : (300 - margin.top - margin.bottom); + + var x = d3.time.scale().range([0 + margin.right, width - margin.left]), + y = d3.time.scale() + .range([margin.top, height - margin.bottom - margin.top]); + + var ticks = width > 800 ? 8 : 4; + + x.domain(d3.extent([padding.minDate, padding.maxDate])); + + var xFormat, yFormat; + if (lessThanDay(padding.pad)) { + xFormat = "%H:%M"; + yFormat = "%m/%d/%y"; + y.domain(d3.extent([padding.minDate])); + } else { + xFormat = "%m/%d/%y"; + yFormat = "%H:%M"; + var start = new Date(2012, 0, 1, 0, 0, 0, 0).getTime(); + var stop = new Date(2012, 0, 1, 23, 59, 59, 59).getTime(); + y.domain(d3.extent([start, stop])); + } + + var xAxis = d3.svg.axis().scale(x).orient("bottom") + .ticks(ticks) + .tickSize(-height, 0) + .tickFormat(d3.time.format(xFormat)); + + var yAxis = d3.svg.axis().scale(y).orient("left") + .ticks(5) + .tickSize(-width + margin.right, margin.left) + .tickFormat(d3.time.format(yFormat)); + + var svg = d3.select("." + classd).append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom); + + var context = svg.append("g") + .attr("class", "context") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + context.append("g") + .attr("class", "x axis") + .attr("transform", "translate(" + margin.left + "," + (margin.top + (height - margin.bottom)) + ")") + .call(xAxis); + + context.append("g") + .attr("class", "y axis") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")") + .call(yAxis); + + var circles = context.append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")") + + circles.selectAll(".circ") + .data(data) + .enter().append("circle") + .attr("class", "circ") + .attr("cx", function (d) { + return (lessThanDay(padding.pad)) ? x(d.start) : x(getDate(d.start)); + }) + .attr("cy", function (d, i) { + return (lessThanDay(padding.pad)) ? y(getDate(d.start)) : y(getTime(d.start)); + }) + .attr("r", 9) + .on("click", function (d) { + log(new Date(d.start)); + }) + + // ----------------------------------------- Brush --------------------------------------------- + + if (enableBrush) { + var brush = d3.svg.brush() + .x(x) + .on("brush", _.throttle(brushed, 200)); + + circles.append("g") + .attr("class", "brush") + .call(brush) + .selectAll("rect") + .attr("y", -6) + .attr("height", height - margin.bottom); + + var brushEl = '
    Click and drag on the timeseries to create a brush.
    '; + window.document.getElementsByClassName(spaced)[0].insertAdjacentHTML('beforeend', brushEl); + + function brushed() { + if (!brush.empty()) { + d3.select('.clear-brush').style("display", "inline-block"); + d3.select('.brush-info')[0][0].innerText = brush.extent(); + } + } + + d3.select('.clear-brush').on("click", function (d) { + if (!brush.empty()) { + d3.selectAll("g.brush").call(brush.clear()); + d3.select('.brush-info')[0][0].innerText = ""; + d3.select('.clear-brush').style("display", "none"); + } + }) + + TimeSeries.getBrushExtent = function () { + if (brush) + return brush.extent(); + } + } + } + } + /* Use this function, in conjunction to setting a time element to 'selected', to highlight the + data point on the timeseries. */ + redraw() { + d3.selectAll(".circ") + .transition(10) + .style("opacity", function(d) { + return d.selected ? 1 : 0.6; + }) + .attr("r", function(d) { + return d.selected ? 15 : 7; + }); + } +} +export default TimeSeries; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/style.css b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/style.css new file mode 100644 index 00000000..be83396b --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/style.css @@ -0,0 +1,111 @@ +body { + font: 16px 'Open Sans'; + color: #2C3E50; +} +a { + text-decoration: none; + color: #3498DB; +} +.container { + margin: 1%; +} +.text { + width: 100%; +} +.text p { + width: 75%; + margin: auto; + padding: 10px 0px; + text-align: center; +} +code { + width: 95%; + margin: auto; + text-align: center; +} +@media screen and (min-width: 800px) { + code { + width: 70%; + } +} +.header { + width: 100%; + text-align: center; + margin: 1% 0; +} +.header img { + padding-top: 10px; +} +.header div { + font-weight: 700; + font-size: 1.6em; + padding-top: 10px; +} +.dac-logo { + display: none; +} +@media screen and (min-width: 800px) { + .dac-logo { + display: block; + position: absolute; + left: 5px; + top: 5px; + } + .dac-logo img { + width: 120px; + } +} +.contact { + width: 50%; + margin: auto; + text-align: center; +} +.footer { + font-size: 0.9em; + text-align: center; + padding: 5px; +} +/** Styles for TIMESERIES */ + +.timeseries { + width: 100%; + padding: 2% 0; +} +.circ { + fill: #D35400; + opacity: 0.6; + stroke: rgba(211, 84, 0, 0.7); + stroke-width: 5px; +} +.domain { + display: none; +} +.axis path, .axis line { + fill: none; + stroke: #000; + shape-rendering: crispEdges; +} +.axis text { + font-size: 12px; +} +.tick line { + stroke: #d5d5d5; + opacity: 0.7; +} +.brush .extent { + stroke: #fff; + fill-opacity: .125; + shape-rendering: crispEdges; +} +.clear-brush { + display: none; +} +.brush-control { + padding: .5%; + width: 100%; + text-align: center; +} +.brush-info { + display: inline-block; + font-size: 14px; +} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/timeline.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/timeline.js deleted file mode 100644 index c1308701..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/timeline.js +++ /dev/null @@ -1,684 +0,0 @@ -import d3 from 'd3' - -export default function timeline() { - var DISPLAY_TYPES = ["circle", "rect"], - hover = function () {}, - mouseover = function () {}, - mouseout = function () {}, - click = function () {}, - scroll = function () {}, - labelFunction = function(label) { return label; }, - navigateLeft = function () {}, - navigateRight = function () {}, - orient = "bottom", - width = null, - height = null, - rowSeparatorsColor = null, - backgroundColor = null, - tickFormat = { format: d3.time.format("%I %p"), - tickTime: d3.time.hours, - tickInterval: 1, - tickSize: 6, - tickValues: null - }, - colorCycle = d3.scale.category20(), - colorPropertyName = null, - display = "rect", - beginning = 0, - labelMargin = 0, - ending = 0, - margin = {left: 30, right:30, top: 30, bottom:30}, - stacked = false, - rotateTicks = false, - timeIsRelative = false, - fullLengthBackgrounds = false, - itemHeight = 20, - itemMargin = 5, - navMargin = 60, - showTimeAxis = true, - showAxisTop = false, - showTodayLine = false, - timeAxisTick = false, - timeAxisTickFormat = {stroke: "stroke-dasharray", spacing: "4 10"}, - showTodayFormat = {marginTop: 25, marginBottom: 0, width: 1, color: colorCycle}, - showBorderLine = false, - showBorderFormat = {marginTop: 25, marginBottom: 0, width: 1, color: colorCycle}, - showAxisHeaderBackground = false, - showAxisNav = false, - showAxisCalendarYear = false, - axisBgColor = "white", - chartData = {} - ; - - var appendTimeAxis = function(g, xAxis, yPosition) { - - if(showAxisHeaderBackground){ appendAxisHeaderBackground(g, 0, 0); } - - if(showAxisNav){ appendTimeAxisNav(g) }; - - var axis = g.append("g") - .attr("class", "axis") - .attr("transform", "translate(" + 0 + "," + yPosition + ")") - .call(xAxis); - }; - - var appendTimeAxisCalendarYear = function (nav) { - var calendarLabel = beginning.getFullYear(); - - if (beginning.getFullYear() != ending.getFullYear()) { - calendarLabel = beginning.getFullYear() + "-" + ending.getFullYear() - } - - nav.append("text") - .attr("transform", "translate(" + 20 + ", 0)") - .attr("x", 0) - .attr("y", 14) - .attr("class", "calendarYear") - .text(calendarLabel) - ; - }; - var appendTimeAxisNav = function (g) { - var timelineBlocks = 6; - var leftNavMargin = (margin.left - navMargin); - var incrementValue = (width - margin.left)/timelineBlocks; - var rightNavMargin = (width - margin.right - incrementValue + navMargin); - - var nav = g.append('g') - .attr("class", "axis") - .attr("transform", "translate(0, 20)") - ; - - if(showAxisCalendarYear) { appendTimeAxisCalendarYear(nav) }; - - nav.append("text") - .attr("transform", "translate(" + leftNavMargin + ", 0)") - .attr("x", 0) - .attr("y", 14) - .attr("class", "chevron") - .text("<") - .on("click", function () { - return navigateLeft(beginning, chartData); - }) - ; - - nav.append("text") - .attr("transform", "translate(" + rightNavMargin + ", 0)") - .attr("x", 0) - .attr("y", 14) - .attr("class", "chevron") - .text(">") - .on("click", function () { - return navigateRight(ending, chartData); - }) - ; - }; - - var appendAxisHeaderBackground = function (g, xAxis, yAxis) { - g.insert("rect") - .attr("class", "row-green-bar") - .attr("x", xAxis) - .attr("width", width) - .attr("y", yAxis) - .attr("height", itemHeight) - .attr("fill", axisBgColor); - }; - - var appendTimeAxisTick = function(g, xAxis, maxStack) { - g.append("g") - .attr("class", "axis") - .attr("transform", "translate(" + 0 + "," + (margin.top + (itemHeight + itemMargin) * maxStack) + ")") - .attr(timeAxisTickFormat.stroke, timeAxisTickFormat.spacing) - .call(xAxis.tickFormat("").tickSize(-(margin.top + (itemHeight + itemMargin) * (maxStack - 1) + 3), 0, 0)); - }; - - var appendBackgroundBar = function (yAxisMapping, index, g, data, datum) { - var greenbarYAxis = ((itemHeight + itemMargin) * yAxisMapping[index]) + margin.top; - g.selectAll("svg").data(data).enter() - .insert("rect") - .attr("class", "row-green-bar") - .attr("x", fullLengthBackgrounds ? 0 : margin.left) - .attr("width", fullLengthBackgrounds ? width : (width - margin.right - margin.left)) - .attr("y", greenbarYAxis) - .attr("height", itemHeight) - .attr("fill", backgroundColor instanceof Function ? backgroundColor(datum, index) : backgroundColor) - ; - }; - - var appendLabel = function (gParent, yAxisMapping, index, hasLabel, datum) { - var fullItemHeight = itemHeight + itemMargin; - var rowsDown = margin.top + (fullItemHeight/2) + fullItemHeight * (yAxisMapping[index] || 1); - - gParent.append("text") - .attr("class", "timeline-label") - .attr("transform", "translate(" + labelMargin + "," + rowsDown + ")") - .text(hasLabel ? labelFunction(datum.label) : datum.id) - .on("click", function (d, i) { click(d, index, datum); }); - }; - - function timeline (gParent) { - var g = gParent.append("g"); - var gParentSize = gParent[0][0].getBoundingClientRect(); - - var gParentItem = d3.select(gParent[0][0]); - - var yAxisMapping = {}, - maxStack = 1, - minTime = 0, - maxTime = 0; - - setWidth(); - - // check if the user wants relative time - // if so, substract the first timestamp from each subsequent timestamps - if(timeIsRelative){ - g.each(function (d, i) { - d.forEach(function (datum, index) { - datum.forEach(function (data, j) { - data.starting_time = this.startExtractor() - - if(index === 0 && j === 0){ - originTime = time.starting_time //Store the timestamp that will serve as origin - time.starting_time = 0; //Set the origin - time.ending_time = time.ending_time - originTime; //Store the relative time (millis) - }else{ - time.starting_time = time.starting_time - originTime; - time.ending_time = time.ending_time - originTime; - } - }); - }); - }); - } - - // check how many stacks we're gonna need - // do this here so that we can draw the axis before the graph - if (stacked || ending === 0 || beginning === 0) { - g.each(function (d, i) { - d.forEach(function (datum, index) { - - // create y mapping for stacked graph - if (stacked && Object.keys(yAxisMapping).indexOf(index) == -1) { - yAxisMapping[index] = maxStack; - maxStack++; - } - - // figure out beginning and ending times if they are unspecified - datum.times.forEach(function (time, i) { - if(beginning === 0) - if (time.starting_time < minTime || (minTime === 0 && timeIsRelative === false)) - minTime = time.starting_time; - if(ending === 0) - if (time.ending_time > maxTime) - maxTime = time.ending_time; - }); - }); - }); - - if (ending === 0) { - ending = maxTime; - } - if (beginning === 0) { - beginning = minTime; - } - } - - var scaleFactor = (1/(ending - beginning)) * (width - margin.left - margin.right); - - // draw the axis - var xScale = d3.time.scale() - .domain([beginning, ending]) - .range([margin.left, width - margin.right]); - - var xAxis = d3.svg.axis() - .scale(xScale) - .orient(orient) - .tickFormat(tickFormat.format) - .tickSize(tickFormat.tickSize); - - if (tickFormat.tickValues != null) { - xAxis.tickValues(tickFormat.tickValues); - } else { - xAxis.ticks(tickFormat.numTicks || tickFormat.tickTime, tickFormat.tickInterval); - } - - // draw the chart - g.each(function(d, i) { - chartData = d; - d.forEach( function(datum, index){ - var data = datum.times; - var hasLabel = (typeof(datum.label) != "undefined"); - - // issue warning about using id per data set. Ids should be individual to data elements - if (typeof(datum.id) != "undefined") { - console.warn("d3Timeline Warning: Ids per dataset is deprecated in favor of a 'class' key. Ids are now per data element."); - } - - if (backgroundColor) { appendBackgroundBar(yAxisMapping, index, g, data, datum); } - - g.selectAll("svg").data(data).enter() - .append(function(d, i) { - return document.createElementNS(d3.ns.prefix.svg, "display" in d? d.display:display); - }) - .attr("x", getXPos) - .attr("y", getStackPosition) - .attr("width", function (d, i) { - return (d.ending_time - d.starting_time) * scaleFactor; - }) - .attr("cy", function(d, i) { - return getStackPosition(d, i) + itemHeight/2; - }) - .attr("cx", getXPos) - .attr("r", itemHeight / 2) - .attr("height", itemHeight) - .style("fill", function(d, i){ - var dColorPropName; - if (d.color) return d.color; - if( colorPropertyName ){ - dColorPropName = d[colorPropertyName]; - if ( dColorPropName ) { - return colorCycle( dColorPropName ); - } else { - return colorCycle( datum[colorPropertyName] ); - } - } - return colorCycle(index); - }) - .on("mousemove", function (d, i) { - hover(d, index, datum); - }) - .on("mouseover", function (d, i) { - mouseover(d, i, datum); - }) - .on("mouseout", function (d, i) { - mouseout(d, i, datum); - }) - .on("click", function (d, i) { - click(d, index, datum); - }) - .attr("class", function (d, i) { - return datum.class ? "timelineSeries_"+datum.class : "timelineSeries_"+index; - }) - .attr("id", function(d, i) { - // use deprecated id field - if (datum.id && !d.id) { - return 'timelineItem_'+datum.id; - } - - return d.id ? d.id : "timelineItem_"+index+"_"+i; - }) - ; - - g.selectAll("svg").data(data).enter() - .append("text") - .attr("x", getXTextPos) - .attr("y", getStackTextPosition) - .text(function(d) { - return d.label; - }) - ; - - if (rowSeparatorsColor) { - var lineYAxis = ( itemHeight + itemMargin / 2 + margin.top + (itemHeight + itemMargin) * yAxisMapping[index]); - gParent.append("svg:line") - .attr("class", "row-separator") - .attr("x1", 0 + margin.left) - .attr("x2", width - margin.right) - .attr("y1", lineYAxis) - .attr("y2", lineYAxis) - .attr("stroke-width", 1) - .attr("stroke", rowSeparatorsColor); - } - - // add the label - if (hasLabel) { appendLabel(gParent, yAxisMapping, index, hasLabel, datum); } - - if (typeof(datum.icon) !== "undefined") { - gParent.append("image") - .attr("class", "timeline-label") - .attr("transform", "translate("+ 0 +","+ (margin.top + (itemHeight + itemMargin) * yAxisMapping[index])+")") - .attr("xlink:href", datum.icon) - .attr("width", margin.left) - .attr("height", itemHeight); - } - - function getStackPosition(d, i) { - if (stacked) { - return margin.top + (itemHeight + itemMargin) * yAxisMapping[index]; - } - return margin.top; - } - function getStackTextPosition(d, i) { - if (stacked) { - return margin.top + (itemHeight + itemMargin) * yAxisMapping[index] + itemHeight * 0.75; - } - return margin.top + itemHeight * 0.75; - } - }); - }); - - var belowLastItem = (margin.top + (itemHeight + itemMargin) * maxStack); - var aboveFirstItem = margin.top; - var timeAxisYPosition = showAxisTop ? aboveFirstItem : belowLastItem; - if (showTimeAxis) { appendTimeAxis(g, xAxis, timeAxisYPosition); } - if (timeAxisTick) { appendTimeAxisTick(g, xAxis, maxStack); } - - if (width > gParentSize.width) { - var move = function() { - var x = Math.min(0, Math.max(gParentSize.width - width, d3.event.translate[0])); - zoom.translate([x, 0]); - g.attr("transform", "translate(" + x + ",0)"); - scroll(x*scaleFactor, xScale); - }; - - var zoom = d3.behavior.zoom().x(xScale).on("zoom", move); - - gParent - .attr("class", "scrollable") - .call(zoom); - } - - if (rotateTicks) { - g.selectAll(".tick text") - .attr("transform", function(d) { - return "rotate(" + rotateTicks + ")translate(" - + (this.getBBox().width / 2 + 10) + "," // TODO: change this 10 - + this.getBBox().height / 2 + ")"; - }); - } - - var gSize = g[0][0].getBoundingClientRect(); - setHeight(); - - if (showBorderLine) { - g.each(function (d, i) { - d.forEach(function (datum) { - var times = datum.times; - times.forEach(function (time) { - appendLine(xScale(time.starting_time), showBorderFormat); - appendLine(xScale(time.ending_time), showBorderFormat); - }); - }); - }); - } - - if (showTodayLine) { - var todayLine = xScale(new Date()); - appendLine(todayLine, showTodayFormat); - } - - function getXPos(d, i) { - return margin.left + (d.starting_time - beginning) * scaleFactor; - } - - function getXTextPos(d, i) { - return margin.left + (d.starting_time - beginning) * scaleFactor + 5; - } - - function setHeight() { - if (!height && !gParentItem.attr("height")) { - if (itemHeight) { - // set height based off of item height - height = gSize.height + gSize.top - gParentSize.top; - // set bounding rectangle height - d3.select(gParent[0][0]).attr("height", height); - } else { - throw "height of the timeline is not set"; - } - } else { - if (!height) { - height = gParentItem.attr("height"); - } else { - gParentItem.attr("height", height); - } - } - } - - function setWidth() { - if (!width && !gParentSize.width) { - try { - width = gParentItem.attr("width"); - if (!width) { - throw "width of the timeline is not set. As of Firefox 27, timeline().with(x) needs to be explicitly set in order to render"; - } - } catch (err) { - console.log( err ); - } - } else if (!(width && gParentSize.width)) { - try { - width = gParentItem.attr("width"); - } catch (err) { - console.log( err ); - } - } - // if both are set, do nothing - } - - function appendLine(lineScale, lineFormat) { - gParent.append("svg:line") - .attr("x1", lineScale) - .attr("y1", lineFormat.marginTop) - .attr("x2", lineScale) - .attr("y2", height - lineFormat.marginBottom) - .style("stroke", lineFormat.color)//"rgb(6,120,155)") - .style("stroke-width", lineFormat.width); - } - } - - // === SETTINGS === - timeline.margin = function (p) { - if (!arguments.length) return margin; - margin = p; - return timeline; - }; - - timeline.orient = function (orientation) { - if (!arguments.length) return orient; - orient = orientation; - return timeline; - }; - - timeline.itemHeight = function (h) { - if (!arguments.length) return itemHeight; - itemHeight = h; - return timeline; - }; - - timeline.itemMargin = function (h) { - if (!arguments.length) return itemMargin; - itemMargin = h; - return timeline; - }; - - timeline.navMargin = function (h) { - if (!arguments.length) return navMargin; - navMargin = h; - return timeline; - }; - - timeline.height = function (h) { - if (!arguments.length) return height; - height = h; - return timeline; - }; - - timeline.width = function (w) { - if (!arguments.length) return width; - width = w; - return timeline; - }; - - timeline.display = function (displayType) { - if (!arguments.length || (DISPLAY_TYPES.indexOf(displayType) == -1)) return display; - display = displayType; - return timeline; - }; - - timeline.labelFormat = function(f) { - if (!arguments.length) return labelFunction; - labelFunction = f; - return timeline; - }; - - timeline.tickFormat = function (format) { - if (!arguments.length) return tickFormat; - tickFormat = format; - return timeline; - }; - - // Mouse actions - timeline.hover = function (hoverFunc) { - if (!arguments.length) return hover; - hover = hoverFunc; - return timeline; - }; - - timeline.mouseover = function (mouseoverFunc) { - if (!arguments.length) return mouseover; - mouseover = mouseoverFunc; - return timeline; - }; - - timeline.mouseout = function (mouseoutFunc) { - if (!arguments.length) return mouseout; - mouseout = mouseoutFunc; - return timeline; - }; - - timeline.click = function (clickFunc) { - if (!arguments.length) return click; - click = clickFunc; - return timeline; - }; - - timeline.scroll = function (scrollFunc) { - if (!arguments.length) return scroll; - scroll = scrollFunc; - return timeline; - }; - - timeline.colors = function (colorFormat) { - if (!arguments.length) return colorCycle; - colorCycle = colorFormat; - return timeline; - }; - - timeline.beginning = function (b) { - if (!arguments.length) return beginning; - beginning = b; - return timeline; - }; - - timeline.ending = function (e) { - if (!arguments.length) return ending; - ending = e; - return timeline; - }; - - timeline.labelMargin = function (m) { - if (!arguments.length) return labelMargin; - labelMargin = m; - return timeline; - }; - - timeline.rotateTicks = function (degrees) { - if (!arguments.length) return rotateTicks; - rotateTicks = degrees; - return timeline; - }; - - timeline.stack = function () { - stacked = !stacked; - return timeline; - }; - - timeline.relativeTime = function() { - timeIsRelative = !timeIsRelative; - return timeline; - }; - - timeline.showBorderLine = function () { - showBorderLine = !showBorderLine; - return timeline; - }; - - timeline.showBorderFormat = function(borderFormat) { - if (!arguments.length) return showBorderFormat; - showBorderFormat = borderFormat; - return timeline; - }; - - timeline.showToday = function () { - showTodayLine = !showTodayLine; - return timeline; - }; - - timeline.showTodayFormat = function(todayFormat) { - if (!arguments.length) return showTodayFormat; - showTodayFormat = todayFormat; - return timeline; - }; - - timeline.colorProperty = function(colorProp) { - if (!arguments.length) return colorPropertyName; - colorPropertyName = colorProp; - return timeline; - }; - - timeline.rowSeparators = function (color) { - if (!arguments.length) return rowSeparatorsColor; - rowSeparatorsColor = color; - return timeline; - - }; - - timeline.background = function (color) { - if (!arguments.length) return backgroundColor; - backgroundColor = color; - return timeline; - }; - - timeline.showTimeAxis = function () { - showTimeAxis = !showTimeAxis; - return timeline; - }; - - timeline.showAxisTop = function () { - showAxisTop = !showAxisTop; - return timeline; - }; - - timeline.showAxisCalendarYear = function () { - showAxisCalendarYear = !showAxisCalendarYear; - return timeline; - }; - - timeline.showTimeAxisTick = function () { - timeAxisTick = !timeAxisTick; - return timeline; - }; - - timeline.fullLengthBackgrounds = function () { - fullLengthBackgrounds = !fullLengthBackgrounds; - return timeline; - }; - - timeline.showTimeAxisTickFormat = function(format) { - if (!arguments.length) return timeAxisTickFormat; - timeAxisTickFormat = format; - return timeline; - }; - - timeline.showAxisHeaderBackground = function(bgColor) { - showAxisHeaderBackground = !showAxisHeaderBackground; - if(bgColor) { (axisBgColor = bgColor) }; - return timeline; - }; - - timeline.navigate = function (navigateBackwards, navigateForwards) { - if (!arguments.length) return [navigateLeft, navigateRight]; - navigateLeft = navigateBackwards; - navigateRight = navigateForwards; - showAxisNav = !showAxisNav; - return timeline; - }; - return timeline; -}; \ No newline at end of file diff --git a/src/npm-shrinkwrap.json b/src/npm-shrinkwrap.json index 9b139910..159f3e49 100644 --- a/src/npm-shrinkwrap.json +++ b/src/npm-shrinkwrap.json @@ -7,11 +7,6 @@ "from": "babel-polyfill@>=6.3.0 <6.4.0", "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.3.14.tgz", "dependencies": { - "core-js": { - "version": "1.2.7", - "from": "core-js@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz" - }, "babel-regenerator-runtime": { "version": "6.5.0", "from": "babel-regenerator-runtime@>=6.3.13 <7.0.0", @@ -21,6 +16,11 @@ "version": "5.8.38", "from": "babel-runtime@>=5.0.0 <6.0.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-5.8.38.tgz" + }, + "core-js": { + "version": "1.2.7", + "from": "core-js@>=1.0.1 <2.0.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz" } } }, @@ -935,6 +935,11 @@ "from": "scriptjs@>=2.5.0 <2.6.0", "resolved": "https://registry.npmjs.org/scriptjs/-/scriptjs-2.5.8.tgz" }, + "underscore": { + "version": "1.8.3", + "from": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz" + }, "when": { "version": "3.7.7", "from": "when@>=3.7.0 <3.8.0", diff --git a/src/package.json b/src/package.json index 1a7dc3f9..f2bd4833 100644 --- a/src/package.json +++ b/src/package.json @@ -37,6 +37,7 @@ "reselect": "2.0.x", "revalidator": "0.3.x", "scriptjs": "2.5.x", + "underscore": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", "when": "3.7.x" }, "devDependencies": { From 4b3f1d7ee46fed063ab7baea360ab47944b46a7f Mon Sep 17 00:00:00 2001 From: vvancak Date: Fri, 31 Mar 2017 23:27:25 +0200 Subject: [PATCH 18/84] EventTimeline: Configuration selections, EventInfo visualization base --- .../modules/visualizers/events/api.js | 7 +- .../events/components/Application.js | 11 +-- .../events/components/ConfigToolbar.js | 61 +++++++++++++ .../events/components/Visualization.js | 48 +++++++++++ .../events/components/VisualizationMessage.js | 15 ++++ .../events/containers/EventInfoContainer.js | 85 +++++++++++++++++++ .../events/containers/EventLoader.js | 44 ---------- .../events/containers/PeopleLoader.js | 47 ---------- .../events/containers/TimelineContainer.js | 60 ++++++++++--- .../visualizers/events/ducks/configuration.js | 18 ++-- .../modules/visualizers/events/ducks/dirty.js | 4 +- .../events/ducks/selectedEvents.js | 32 +++++++ .../misc/{style.css => TimeSeriesStyle.css} | 0 .../modules/visualizers/events/models.js | 7 ++ .../visualizers/events/pages/Configurator.js | 20 +---- .../modules/visualizers/events/reducer.js | 4 +- 16 files changed, 324 insertions(+), 139 deletions(-) create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/VisualizationMessage.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/{style.css => TimeSeriesStyle.css} (100%) diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js index 1ae3f85e..beacd0af 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js @@ -1,12 +1,13 @@ import rest from '../../../misc/rest' export async function getEvents(applicationId, start, end, limit) { - let payload = {"start":start, "end":end, "limit":limit}; + let payload = {start:start.getTime(), end:end.getTime(), limit:limit}; + debugger; const result = await rest('eventVisualizer/getEvents/' + applicationId,payload); return result.data.events; } -export async function getEventPeople(applicationId, event) { - const result = await rest('eventVisualizer/getEventPeople/' + applicationId, {"event" : event}); +export async function getEventPeople(applicationId, eventUrl) { + const result = await rest('eventVisualizer/getEventPeople/' + applicationId, {event : eventUrl}); return result.data.people; } \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js index 6bb66450..62b85edf 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js @@ -2,10 +2,10 @@ import React, { Component, PropTypes } from 'react' import BodyPadding from '../../../../components/BodyPadding' import { Application as ApplicationModel } from '../../../app/models' import { Visualizer } from '../../../core/models' -import EventLoader from '../containers/EventLoader' +import Visualization from '../components/Visualization' import SaveButton from '../components/SaveButton' import { getConfiguration, getConfigurationReset } from '../ducks/configuration' - +import ConfigToolbar from "./ConfigToolbar"; class Application extends Component { static propTypes = { @@ -25,11 +25,12 @@ class Application extends Component { } render() { - const { application, visualizer, embed } = this.props; + const { embed } = this.props; return ( -

    This is the {visualizer.name} in {application.name} in {embed ? 'embed' : 'standalone'} mode.

    - +

    {embed ? 'Embed' : 'Standalone'} mode.

    + +
    ) diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js new file mode 100644 index 00000000..ceaa8f76 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js @@ -0,0 +1,61 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import {createStructuredSelector} from "reselect"; +import {configurationSelector, getConfiguration} from '../ducks/configuration' +import { Configuration } from '../models' +import moment from "moment"; + +class ConfigToolbar extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + configuration: PropTypes.instanceOf(Configuration).isRequired, + }; + + componentWillMount() { + const { dispatch } = this.props; + dispatch(getConfiguration()); + } + //TODO: Update configuration. + /*componentDidUpdate(){ + var configuration = this.props.configuration; + configuration.start = document.getElementsByName("start")[0].value; + configuration.end = document.getElementsByName("end")[0].value; + configuration.limit = document.getElementsByName("limit")[0].value; + dispatch() + }*/ + + render() { + const {configuration} = this.props; + + var startString = moment(configuration.start).format('YYYY-MM-DD'); + var endString = moment(configuration.end).format('YYYY-MM-DD'); + return
    + + + + + + + + + + + + +
    TimeSeries StartTimeSeries EndMax event count
    + + + + + + + +
    +
    + } +} +const selector = createStructuredSelector({ + configuration: configurationSelector +}); + +export default connect(selector)(ConfigToolbar); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js new file mode 100644 index 00000000..c62dafd9 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js @@ -0,0 +1,48 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import {createStructuredSelector} from "reselect"; +import { configurationSelector } from '../ducks/configuration' +import {selectedEventSelector} from "../ducks/selectedEvents"; +import TimelineContainer from '../containers/TimelineContainer' +import EventInfoContainer from '../containers/EventInfoContainer' +import {Configuration, EventInfo} from '../models' +import { getConfiguration, getConfigurationReset } from '../ducks/configuration' +import CenteredMessage from '../../../../components/CenteredMessage' +import VisualizationMessage from '../components/VisualizationMessage' + +class Visualization extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + selectedEvent: PropTypes.instanceOf(EventInfo), + configuration: PropTypes.instanceOf(Configuration).isRequired + }; + + componentWillMount() { + const { dispatch } = this.props; + dispatch(getConfiguration()); + } + + componentWillUnmount() { + const { dispatch } = this.props; + dispatch(getConfigurationReset()); + } + + render() { + const {configuration, selectedEvent} = this.props; + if(!configuration){ + return + An error occurred while loading the configuration. + + } + return
    + + +
    + } +} +const selector = createStructuredSelector({ + configuration: configurationSelector, + selectedEvent: selectedEventSelector +}); + +export default connect(selector)(Visualization); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/VisualizationMessage.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/VisualizationMessage.js new file mode 100644 index 00000000..3b7274e7 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/VisualizationMessage.js @@ -0,0 +1,15 @@ +import React from 'react' + +const style = { + textAlign: 'center', + marginTop: '100px', + color: 'rgba(0, 0, 0, 0.5)' +}; + +const VisualizationMessage = ({ children }) => ( +
    + {children} +
    +); + +export default VisualizationMessage; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js new file mode 100644 index 00000000..f56f3da0 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js @@ -0,0 +1,85 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from 'reselect' +import { getEventPeople, getEventPeopleReset, peopleSelector, peopleStatusSelector } from '../ducks/people' +import { PromiseStatus } from '../../../core/models' +import PromiseResult from '../../../core/components/PromiseResult' +import { EventInfo } from '../models' +import moment from "moment"; +import CenteredMessage from '../../../../components/CenteredMessage' +import VisualizationMessage from '../components/VisualizationMessage' + +class PeopleLoader extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + event: PropTypes.instanceOf(EventInfo).isRequired, + people: PropTypes.instanceOf(Array).isRequired, + status: PropTypes.instanceOf(PromiseStatus).isRequired + }; + + componentWillMount() { + const { dispatch, event } = this.props.dispatch; + if (event) { + dispatch(getEventPeople(event.url)); + } + } + + componentWillUnmount() { + const {dispatch} = this.props; + dispatch(getEventPeopleReset()); + } + + render() { + const {people, event, status} = this.props; + + if (!status.done) { + return + } + + if(!event){ + return + + To view more information about events, click on them in the timeline. + + } + + if (!people){ + return + + Error loading people connected to this event + + } + + var renderPerson = function(person){ + return + + Person Image + +

    {person.name}

    +

    {person.description}

    + Wiki Link + + + } + + var startString = moment(event.start).format('YYYYMMDD'); + var endString = moment(event.end).format('YYYYMMDD'); + return
    +

    {event.name}

    +

    {event.description}

    +

    From {startString} to {endString}

    + Event Link +
    + + {people.map(p=>renderPerson(p))} +
    +
    + } +} + +const selector = createStructuredSelector({ + people: peopleSelector, + status: peopleStatusSelector +}); + +export default connect(selector)(PeopleLoader); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js deleted file mode 100644 index b1a36c49..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventLoader.js +++ /dev/null @@ -1,44 +0,0 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from 'reselect' -import { getEvents, getEventsReset, eventsSelector, eventsStatusSelector } from '../ducks/events' -import { PromiseStatus } from '../../../core/models' -import PromiseResult from '../../../core/components/PromiseResult' -import TimelineContainer from './TimelineContainer' - -class EventLoader extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, - events: PropTypes.instanceOf(Array).isRequired, - status: PropTypes.instanceOf(PromiseStatus).isRequired - }; - - componentWillMount() { - const {dispatch} = this.props; - dispatch(getEvents((new Date("1900-01-01")),(new Date("2017-01-01")),20)); - } - - componentWillUnmount() { - const {dispatch} = this.props; - dispatch(getEventsReset()); - } - - render() { - const {events, status} = this.props; - if (!status.done) { - return - } - else if (!events || events.length == 0) { - return

    No events loaded - nothing to visualize.

    - } - debugger; - return - } -} - -const selector = createStructuredSelector({ - events: eventsSelector, - status: eventsStatusSelector -}); - -export default connect(selector)(EventLoader); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js deleted file mode 100644 index 2f86ca0c..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/PeopleLoader.js +++ /dev/null @@ -1,47 +0,0 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from 'reselect' -import { getEventPeople, getEventPeopleReset, peopleSelector, peopleStatusSelector } from '../ducks/people' -import { PromiseStatus } from '../../../core/models' -import PromiseResult from '../../../core/components/PromiseResult' - -class PeopleLoader extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, - people: PropTypes.instanceOf(Array).isRequired, - status: PropTypes.instanceOf(PromiseStatus).isRequired - }; - - componentWillMount() { - const {dispatch} = this.props; - dispatch(getEventPeople("http://dbpedia.org/resource/World_Film_Festival_of_Bangkok")); - } - - componentWillUnmount() { - const {dispatch} = this.props; - dispatch(getEventPeopleReset()); - } - - render() { - const {people, status} = this.props; - - if (!status.done) { - return - } - - if (people==null || people.length == 0) { - return

    No people loaded - nothing to visualize.

    - } - - return ( -

    {people[0].name}

    - ); - } -} - -const selector = createStructuredSelector({ - people: peopleSelector, - status: peopleStatusSelector -}); - -export default connect(selector)(PeopleLoader); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js index 5fb464da..055c6eef 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js @@ -1,22 +1,62 @@ import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { getEvents, getEventsReset, eventsSelector, eventsStatusSelector } from '../ducks/events' +import { PromiseStatus } from '../../../core/models' +import PromiseResult from '../../../core/components/PromiseResult' import TimeSeries from '../misc/TimeSeries' -import makePureRender from '../../../../misc/makePureRender' +import CenteredMessage from '../../../../components/CenteredMessage' +import VisualizationMessage from '../components/VisualizationMessage' +import {createStructuredSelector} from "reselect"; +import {Configuration} from "../models" class TimelineContainer extends Component { static propTypes = { - data: PropTypes.instanceOf(Array).isRequired + dispatch: PropTypes.func.isRequired, + events: PropTypes.instanceOf(Array).isRequired, + configuration: PropTypes.instanceOf(Configuration).isRequired, + status: PropTypes.instanceOf(PromiseStatus).isRequired }; - componentDidMount(){ - var domEl = 'timeseries'; - var data = this.props.data; - var chart = new TimeSeries(domEl,data,true); + componentWillMount(){ + const {dispatch, configuration} = this.props; + this.className = 'timeseries-chart'; + dispatch(getEvents(configuration.start,configuration.end,configuration.limit)); } + componentDidUpdate(){ + const {events} = this.props; + var elements = document.getElementsByClassName(this.className); + if (elements.length > 0) { + if (this.chart != null) { + this.chart.redraw(); + } + else { + this.chart = new TimeSeries(this.className, events, true); + } + } + } + componentWillUnmount() { + const {dispatch} = this.props; + dispatch(getEventsReset()); + } render() { - require('../misc/style.css'); - return
    + const {events, status} = this.props; + require('../misc/TimeSeriesStyle.css'); + + if (!status.done) { + return + } + + if (!events || events.length == 0) { + return + No events were loaded. Check the configuration. + + } + return
    } } -export default makePureRender(TimelineContainer); - +const selector = createStructuredSelector({ + events: eventsSelector, + status: eventsStatusSelector +}); +export default connect(selector)(TimelineContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js index ef068ca3..0410da21 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js @@ -1,10 +1,10 @@ +import { createSelector } from 'reselect' import prefix from '../prefix' import moduleSelector from '../selector' -import { createSelector } from 'reselect' import { createPromiseStatusSelector } from '../../../core/ducks/promises' import { createGetConfiguration, createGetConfigurationReset, createSaveConfiguration } from '../../../app/ducks/configuration' +import {Configuration} from "../models"; -// Actions export const SAVE_CONFIGURATION = prefix('SAVE_CONFIGURATION'); export const SAVE_CONFIGURATION_START = SAVE_CONFIGURATION + '_START'; export const SAVE_CONFIGURATION_ERROR = SAVE_CONFIGURATION + '_ERROR'; @@ -20,15 +20,11 @@ export const GET_CONFIGURATION_RESET = GET_CONFIGURATION + '_RESET'; export const saveConfigurationStatusSelector = createPromiseStatusSelector(SAVE_CONFIGURATION); export const getConfigurationStatusSelector = createPromiseStatusSelector(GET_CONFIGURATION); -export const configurationSelector = createSelector( - [moduleSelector], - state => ({ }) +export const configurationSelector = createSelector([moduleSelector], state => new Configuration(state.configuration) ); // Actual actions created using factories -export const saveConfiguration = - createSaveConfiguration(SAVE_CONFIGURATION, configurationSelector); -export const getConfiguration = - createGetConfiguration(GET_CONFIGURATION); -export const getConfigurationReset = - createGetConfigurationReset(GET_CONFIGURATION_RESET); \ No newline at end of file +export const saveConfiguration = createSaveConfiguration(SAVE_CONFIGURATION, configurationSelector); +export const getConfiguration = createGetConfiguration(GET_CONFIGURATION); +export const getConfigurationReset = createGetConfigurationReset(GET_CONFIGURATION_RESET); + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js index fe51fc5d..bcf141a6 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js @@ -1,11 +1,11 @@ import { createSelector } from 'reselect' import moduleSelector from '../selector' import { createDirtyReducer } from '../../../app/ducks/dirty' +import {SELECT_EVENT} from "./selectedEvents"; // Reducer const actions = [ - - + SELECT_EVENT ]; export default createDirtyReducer(actions); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js new file mode 100644 index 00000000..90ef051d --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js @@ -0,0 +1,32 @@ +import { createSelector } from 'reselect' +import prefix from '../prefix' +import createAction from '../../../../misc/createAction' +import moduleSelector from '../selector' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { GET_CONFIGURATION_SUCCESS } from './configuration' + +// Actions + +export const SELECT_EVENT = prefix('SELECT_EVENT'); +export function selectEvent(event) { + return createAction(SELECT_EVENT, { event }); +} + +// Reducer +const initialState = null; +export default function selectedListReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_CONFIGURATION_SUCCESS: + if ("configuration" in action.payload) { + return action.payload.configuration.selectedEvent; + } + case SELECT_EVENT: + return action.payload.event; + } + return state; +} + +// Selectors +export const selectedEventSelector = createSelector([moduleSelector],state => state.selectedEvent); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/style.css b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeriesStyle.css similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/style.css rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeriesStyle.css diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js index db374c01..72c9e1ab 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js @@ -16,4 +16,11 @@ export const PersonInfo = Record({ info: "info" }); +export const Configuration = Record({ + start: new Date("01 01 2010"), + end: new Date("01 01 2018"), + limit: 100, + selectedEvent: null +}); + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js index a61005f8..e93c2b57 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js @@ -2,10 +2,9 @@ import React, { Component, PropTypes } from 'react' import BodyPadding from '../../../../components/BodyPadding' import { Application } from '../../../app/models' import { Visualizer } from '../../../core/models' -import EventLoader from '../containers/EventLoader' -import PeopleLoader from '../containers/PeopleLoader' //TODO +import Visualization from '../components/Visualization' +import ConfigToolbar from '../components/ConfigToolbar' import SaveButton from '../components/SaveButton' -import { getConfiguration, getConfigurationReset } from '../ducks/configuration' class Configurator extends Component { static propTypes = { @@ -14,24 +13,13 @@ class Configurator extends Component { }; render() { - const { application, visualizer } = this.props; return ( - + + ) } - - componentWillMount() { - const { dispatch } = this.props; - dispatch(getConfiguration()); - } - - componentWillUnmount() { - const { dispatch } = this.props; - dispatch(getConfigurationReset()); - } } - export default Configurator; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js index 73f2a052..22f13a4f 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js @@ -1,10 +1,12 @@ import { combineReducers } from 'redux'; import events from './ducks/events' import people from './ducks/people' +import selectedEvents from './ducks/selectedEvents' const rootReducer = combineReducers({ events, - people + people, + selectedEvents }); export default rootReducer; \ No newline at end of file From e8a8dbc22a7327b6619cc5fc4e03d0c1a93b2c93 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sat, 1 Apr 2017 15:44:57 +0200 Subject: [PATCH 19/84] EventTimeline: Start/End selections work --- .../modules/visualizers/events/api.js | 8 ++- .../events/components/Application.js | 1 - .../events/components/ConfigToolbar.js | 71 +++++++++++-------- .../events/components/SaveButton.js | 2 +- .../events/components/Visualization.js | 8 +-- .../events/containers/EventInfoContainer.js | 2 +- .../events/containers/TimelineContainer.js | 39 +++++----- .../visualizers/events/ducks/configuration.js | 58 +++++++++------ .../visualizers/events/ducks/events.js | 6 +- .../events/ducks/selectedEvents.js | 7 +- .../visualizers/events/misc/TimeSeries.js | 22 +++--- .../modules/visualizers/events/models.js | 3 +- .../visualizers/events/pages/Configurator.js | 1 - .../modules/visualizers/events/reducer.js | 4 +- 14 files changed, 125 insertions(+), 107 deletions(-) diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js index beacd0af..91678126 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js @@ -1,7 +1,11 @@ import rest from '../../../misc/rest' -export async function getEvents(applicationId, start, end, limit) { - let payload = {start:start.getTime(), end:end.getTime(), limit:limit}; +export async function getEvents(applicationId, config) { + var start = config.start.getTime(); + var end = config.end.getTime(); + var limit = parseInt(config.limit); + + let payload = {"start":start, "end":end, "limit":limit}; debugger; const result = await rest('eventVisualizer/getEvents/' + applicationId,payload); return result.data.events; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js index 62b85edf..c271c706 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js @@ -31,7 +31,6 @@ class Application extends Component {

    {embed ? 'Embed' : 'Standalone'} mode.

    - ) } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js index ceaa8f76..62be7e47 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js @@ -1,7 +1,7 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import {createStructuredSelector} from "reselect"; -import {configurationSelector, getConfiguration} from '../ducks/configuration' +import {configSelector, setConfiguration} from '../ducks/configuration' import { Configuration } from '../models' import moment from "moment"; @@ -13,16 +13,21 @@ class ConfigToolbar extends Component { componentWillMount() { const { dispatch } = this.props; - dispatch(getConfiguration()); + dispatch(setConfiguration(new Configuration())); + } + + handleNewConfig(){ + const {dispatch, configuration} = this.props; + + var start = document.getElementsByName("start")[0].value; + var end = document.getElementsByName("end")[0].value; + var limit = document.getElementsByName("limit")[0].value; + var newConfig = {start:new Date(start), end:new Date(end), limit:limit}; + + if (configuration != newConfig) { + dispatch(setConfiguration(newConfig)); + } } - //TODO: Update configuration. - /*componentDidUpdate(){ - var configuration = this.props.configuration; - configuration.start = document.getElementsByName("start")[0].value; - configuration.end = document.getElementsByName("end")[0].value; - configuration.limit = document.getElementsByName("limit")[0].value; - dispatch() - }*/ render() { const {configuration} = this.props; @@ -31,31 +36,35 @@ class ConfigToolbar extends Component { var endString = moment(configuration.end).format('YYYY-MM-DD'); return
    - - - - - - - - - - - + + + + + + + + + + + + + + +
    TimeSeries StartTimeSeries EndMax event count
    - - - - - - - -
    TimeSeries StartTimeSeries EndMax event count
    + + + + + + + this.handleNewConfig()}/> +
    - } + } } const selector = createStructuredSelector({ - configuration: configurationSelector + configuration: configSelector }); export default connect(selector)(ConfigToolbar); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js index 04a83be7..df8fe22b 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js @@ -4,4 +4,4 @@ import { dirtySelector } from '../ducks/dirty' import createSaveButton from '../../../app/containers/createSaveButton' -export default createSaveButton(saveConfiguration, saveConfigurationStatusSelector, dirtySelector); \ No newline at end of file +//export default createSaveButton(saveConfiguration, saveConfigurationStatusSelector, dirtySelector); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js index c62dafd9..0da87aa5 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js @@ -1,12 +1,12 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import {createStructuredSelector} from "reselect"; -import { configurationSelector } from '../ducks/configuration' +import { configSelector } from '../ducks/configuration' import {selectedEventSelector} from "../ducks/selectedEvents"; import TimelineContainer from '../containers/TimelineContainer' import EventInfoContainer from '../containers/EventInfoContainer' import {Configuration, EventInfo} from '../models' -import { getConfiguration, getConfigurationReset } from '../ducks/configuration' +import { getConfiguration, getConfigurationReset} from '../ducks/configuration' import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' @@ -17,7 +17,7 @@ class Visualization extends Component { configuration: PropTypes.instanceOf(Configuration).isRequired }; - componentWillMount() { + componentWillUpdate(){ const { dispatch } = this.props; dispatch(getConfiguration()); } @@ -41,7 +41,7 @@ class Visualization extends Component { } } const selector = createStructuredSelector({ - configuration: configurationSelector, + configuration: configSelector, selectedEvent: selectedEventSelector }); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js index f56f3da0..d1bb8f7b 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js @@ -17,7 +17,7 @@ class PeopleLoader extends Component { status: PropTypes.instanceOf(PromiseStatus).isRequired }; - componentWillMount() { + componentWillUpdate() { const { dispatch, event } = this.props.dispatch; if (event) { dispatch(getEventPeople(event.url)); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js index 055c6eef..afe96c73 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js @@ -4,8 +4,6 @@ import { getEvents, getEventsReset, eventsSelector, eventsStatusSelector } from import { PromiseStatus } from '../../../core/models' import PromiseResult from '../../../core/components/PromiseResult' import TimeSeries from '../misc/TimeSeries' -import CenteredMessage from '../../../../components/CenteredMessage' -import VisualizationMessage from '../components/VisualizationMessage' import {createStructuredSelector} from "reselect"; import {Configuration} from "../models" @@ -19,39 +17,42 @@ class TimelineContainer extends Component { componentWillMount(){ const {dispatch, configuration} = this.props; + dispatch(getEvents(configuration)); this.className = 'timeseries-chart'; - dispatch(getEvents(configuration.start,configuration.end,configuration.limit)); + } + + componentWillReceiveProps(nextProps){ + const {dispatch, configuration} = nextProps; + if (this.props.configuration != configuration) { + dispatch(getEvents(configuration)); + } } componentDidUpdate(){ - const {events} = this.props; - var elements = document.getElementsByClassName(this.className); - if (elements.length > 0) { - if (this.chart != null) { - this.chart.redraw(); - } - else { - this.chart = new TimeSeries(this.className, events, true); - } + const {events, status} = this.props; + + if (this.chart && this.chart.exists(this.className)) { + this.chart.destroy(this.className) + } + + if (status.done) { + this.chart = new TimeSeries(this.className, events, true); } } + componentWillUnmount() { const {dispatch} = this.props; dispatch(getEventsReset()); } + render() { - const {events, status} = this.props; - require('../misc/TimeSeriesStyle.css'); + const {status} = this.props; if (!status.done) { return } - if (!events || events.length == 0) { - return - No events were loaded. Check the configuration. - - } + require('../misc/TimeSeriesStyle.css'); return
    } } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js index 0410da21..7adcc69e 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js @@ -1,30 +1,42 @@ -import { createSelector } from 'reselect' +import createAction from '../../../../misc/createAction' import prefix from '../prefix' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { Configuration } from '../models' +import { createSelector } from 'reselect' import moduleSelector from '../selector' -import { createPromiseStatusSelector } from '../../../core/ducks/promises' -import { createGetConfiguration, createGetConfigurationReset, createSaveConfiguration } from '../../../app/ducks/configuration' -import {Configuration} from "../models"; -export const SAVE_CONFIGURATION = prefix('SAVE_CONFIGURATION'); -export const SAVE_CONFIGURATION_START = SAVE_CONFIGURATION + '_START'; -export const SAVE_CONFIGURATION_ERROR = SAVE_CONFIGURATION + '_ERROR'; -export const SAVE_CONFIGURATION_SUCCESS = SAVE_CONFIGURATION + '_SUCCESS'; +// Actions +export const GET_CONFIG = prefix('GET_CONFIG'); +export const SET_CONFIG = prefix('SET_CONFIG'); +export const GET_CONFIG_RESET = GET_CONFIG + '_RESET'; -export const GET_CONFIGURATION = prefix('GET_CONFIGURATION'); -export const GET_CONFIGURATION_START = GET_CONFIGURATION + '_START'; -export const GET_CONFIGURATION_ERROR = GET_CONFIGURATION + '_ERROR'; -export const GET_CONFIGURATION_SUCCESS = GET_CONFIGURATION + '_SUCCESS'; -export const GET_CONFIGURATION_RESET = GET_CONFIGURATION + '_RESET'; +export function getConfiguration() { + return createAction(GET_CONFIG); +} +export function setConfiguration(config) { + return createAction(SET_CONFIG, {config}) +} +export function getConfigurationReset() { + return createAction(GET_CONFIG_RESET); +} -// Selectors -export const saveConfigurationStatusSelector = createPromiseStatusSelector(SAVE_CONFIGURATION); -export const getConfigurationStatusSelector = createPromiseStatusSelector(GET_CONFIGURATION); +// Reducer +const initialState = new Configuration(); +export default function configReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_CONFIG_RESET: + return initialState; + case SET_CONFIG: + return Configuration(action.payload.config); + case GET_CONFIG: + return new Configuration(state); + default: + return state; + } +}; -export const configurationSelector = createSelector([moduleSelector], state => new Configuration(state.configuration) -); - -// Actual actions created using factories -export const saveConfiguration = createSaveConfiguration(SAVE_CONFIGURATION, configurationSelector); -export const getConfiguration = createGetConfiguration(GET_CONFIGURATION); -export const getConfigurationReset = createGetConfigurationReset(GET_CONFIGURATION_RESET); +// Selectors +export const configSelector = createSelector([moduleSelector], state => state.config); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js index bd38e117..2b59fcfd 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js @@ -16,9 +16,9 @@ export const GET_EVENTS_ERROR = GET_EVENTS + '_ERROR'; export const GET_EVENTS_SUCCESS = GET_EVENTS + '_SUCCESS'; export const GET_EVENTS_RESET = GET_EVENTS + '_RESET'; -export function getEvents(start,end,limit) { +export function getEvents(config) { return withApplicationId(id => { - const promise = api.getEvents(id,start,end,limit); + const promise = api.getEvents(id,config); return createAction(GET_EVENTS, { promise }); }); } @@ -36,7 +36,7 @@ export default function eventsReducer(state = initialState, action) { case GET_EVENTS_RESET: return initialState; case GET_EVENTS_ERROR: - return action.payload; + return initialState; case GET_EVENTS_SUCCESS: return action.payload.map(ev=>new EventInfo(ev)); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js index 90ef051d..aadaf4c1 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js @@ -3,7 +3,6 @@ import prefix from '../prefix' import createAction from '../../../../misc/createAction' import moduleSelector from '../selector' import { GET_APPLICATION_START } from '../../../app/ducks/application' -import { GET_CONFIGURATION_SUCCESS } from './configuration' // Actions @@ -14,14 +13,10 @@ export function selectEvent(event) { // Reducer const initialState = null; -export default function selectedListReducer(state = initialState, action) { +export default function selectedEventReducer(state = initialState, action) { switch (action.type) { case GET_APPLICATION_START: return initialState; - case GET_CONFIGURATION_SUCCESS: - if ("configuration" in action.payload) { - return action.payload.configuration.selectedEvent; - } case SELECT_EVENT: return action.payload.event; } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js index 6513244b..1a9f1190 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js @@ -185,7 +185,7 @@ class TimeSeries { d3.select('.brush-info')[0][0].innerText = ""; d3.select('.clear-brush').style("display", "none"); } - }) + }); TimeSeries.getBrushExtent = function () { if (brush) @@ -194,17 +194,15 @@ class TimeSeries { } } } - /* Use this function, in conjunction to setting a time element to 'selected', to highlight the - data point on the timeseries. */ - redraw() { - d3.selectAll(".circ") - .transition(10) - .style("opacity", function(d) { - return d.selected ? 1 : 0.6; - }) - .attr("r", function(d) { - return d.selected ? 15 : 7; - }); + exists(spaced) { + var classd = spaced.replace(new RegExp(" "), "."); + if (d3.select("." + classd).select("svg")) return true; + return false; + } + + destroy(spaced) { + var classd = spaced.replace(new RegExp(" "), "."); + d3.select("." + classd).select("svg").remove(); } } export default TimeSeries; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js index 72c9e1ab..9646efea 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js @@ -19,8 +19,7 @@ export const PersonInfo = Record({ export const Configuration = Record({ start: new Date("01 01 2010"), end: new Date("01 01 2018"), - limit: 100, - selectedEvent: null + limit: 100 }); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js index e93c2b57..3c6eb260 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js @@ -17,7 +17,6 @@ class Configurator extends Component { - ) } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js index 22f13a4f..abf2ee89 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js @@ -2,11 +2,13 @@ import { combineReducers } from 'redux'; import events from './ducks/events' import people from './ducks/people' import selectedEvents from './ducks/selectedEvents' +import config from './ducks/configuration' const rootReducer = combineReducers({ events, people, - selectedEvents + selectedEvents, + config }); export default rootReducer; \ No newline at end of file From 491fd209e28692868084a68cb6125f03d85c8dd4 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sun, 2 Apr 2017 01:19:26 +0200 Subject: [PATCH 20/84] Event people selection works, more data needed --- .../modules/visualizers/events/api.js | 5 +- .../events/components/Application.js | 1 - .../events/components/SaveButton.js | 7 -- .../events/components/Visualization.js | 15 +++- .../events/containers/EventInfoContainer.js | 79 +++++++++++-------- .../events/containers/TimelineContainer.js | 11 ++- .../modules/visualizers/events/ducks/dirty.js | 14 ---- .../visualizers/events/ducks/people.js | 4 +- .../visualizers/events/ducks/selectedEvent.js | 41 ++++++++++ .../events/ducks/selectedEvents.js | 27 ------- .../visualizers/events/misc/TimeSeries.js | 7 +- .../modules/visualizers/events/models.js | 7 +- .../visualizers/events/pages/Configurator.js | 1 - .../modules/visualizers/events/reducer.js | 4 +- 14 files changed, 120 insertions(+), 103 deletions(-) delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvent.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js index 91678126..202734d0 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js @@ -6,12 +6,11 @@ export async function getEvents(applicationId, config) { var limit = parseInt(config.limit); let payload = {"start":start, "end":end, "limit":limit}; - debugger; const result = await rest('eventVisualizer/getEvents/' + applicationId,payload); return result.data.events; } -export async function getEventPeople(applicationId, eventUrl) { - const result = await rest('eventVisualizer/getEventPeople/' + applicationId, {event : eventUrl}); +export async function getEventPeople(applicationId, event) { + const result = await rest('eventVisualizer/getEventPeople/' + applicationId, {"event" : event}); return result.data.people; } \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js index c271c706..f188e15d 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js @@ -3,7 +3,6 @@ import BodyPadding from '../../../../components/BodyPadding' import { Application as ApplicationModel } from '../../../app/models' import { Visualizer } from '../../../core/models' import Visualization from '../components/Visualization' -import SaveButton from '../components/SaveButton' import { getConfiguration, getConfigurationReset } from '../ducks/configuration' import ConfigToolbar from "./ConfigToolbar"; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js deleted file mode 100644 index df8fe22b..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/SaveButton.js +++ /dev/null @@ -1,7 +0,0 @@ -import React, { PropTypes } from 'react' -import { saveConfiguration, saveConfigurationStatusSelector } from '../ducks/configuration' -import { dirtySelector } from '../ducks/dirty' - -import createSaveButton from '../../../app/containers/createSaveButton' - -//export default createSaveButton(saveConfiguration, saveConfigurationStatusSelector, dirtySelector); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js index 0da87aa5..3f215920 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js @@ -2,10 +2,10 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import {createStructuredSelector} from "reselect"; import { configSelector } from '../ducks/configuration' -import {selectedEventSelector} from "../ducks/selectedEvents"; +import {getSelectedEvent, getSelectedEventReset, selectedEventSelector} from "../ducks/selectedEvent"; import TimelineContainer from '../containers/TimelineContainer' import EventInfoContainer from '../containers/EventInfoContainer' -import {Configuration, EventInfo} from '../models' +import {Configuration, SelectedEvent} from '../models' import { getConfiguration, getConfigurationReset} from '../ducks/configuration' import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' @@ -13,17 +13,24 @@ import VisualizationMessage from '../components/VisualizationMessage' class Visualization extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - selectedEvent: PropTypes.instanceOf(EventInfo), + selectedEvent: PropTypes.instanceOf(SelectedEvent).isRequired, configuration: PropTypes.instanceOf(Configuration).isRequired }; + componentWillMount(){ + const {dispatch} = this.props; + dispatch(getSelectedEvent()); + } + componentWillUpdate(){ const { dispatch } = this.props; + dispatch(getSelectedEvent()); dispatch(getConfiguration()); } componentWillUnmount() { const { dispatch } = this.props; + dispatch(getSelectedEventReset()); dispatch(getConfigurationReset()); } @@ -36,7 +43,7 @@ class Visualization extends Component { } return
    - +
    } } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js index d1bb8f7b..16d5f02f 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js @@ -4,23 +4,23 @@ import { createStructuredSelector } from 'reselect' import { getEventPeople, getEventPeopleReset, peopleSelector, peopleStatusSelector } from '../ducks/people' import { PromiseStatus } from '../../../core/models' import PromiseResult from '../../../core/components/PromiseResult' -import { EventInfo } from '../models' +import { SelectedEvent } from '../models' import moment from "moment"; import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' -class PeopleLoader extends Component { +class EventInfoContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - event: PropTypes.instanceOf(EventInfo).isRequired, + selectedEvent: PropTypes.instanceOf(SelectedEvent).isRequired, people: PropTypes.instanceOf(Array).isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired }; - componentWillUpdate() { - const { dispatch, event } = this.props.dispatch; - if (event) { - dispatch(getEventPeople(event.url)); + componentWillReceiveProps(nextProps){ + const {dispatch, selectedEvent} = nextProps; + if (selectedEvent.isValid && this.props.selectedEvent != selectedEvent) { + dispatch(getEventPeople(selectedEvent.event)); } } @@ -30,49 +30,58 @@ class PeopleLoader extends Component { } render() { - const {people, event, status} = this.props; + const {people, selectedEvent, status} = this.props; - if (!status.done) { - return - } - - if(!event){ - return - + if(!selectedEvent.isValid){ + return To view more information about events, click on them in the timeline. } - if (!people){ - return - - Error loading people connected to this event + if (!status.done) { + return + } + + if (people.length == 0){ + return + Could not load people for selected event. } var renderPerson = function(person){ - return - - Person Image + var style = {width: 100, height:150, "object-fit": 'contain'}; + return + Person Image

    {person.name}

    {person.description}

    Wiki Link - } + }; + + var event = selectedEvent.event; + var startString = moment(event.start).format('DD.MM.YYYY'); + var endString = moment(event.end).format('DD.MM.YYYY'); - var startString = moment(event.start).format('YYYYMMDD'); - var endString = moment(event.end).format('YYYYMMDD'); - return
    -

    {event.name}

    -

    {event.description}

    -

    From {startString} to {endString}

    - Event Link -
    - - {people.map(p=>renderPerson(p))} -
    + return
    +
    +

    {event.name}

    +

    {event.description}

    +

    From {startString} to {endString}

    + Event Link +
    +
    +
    + + + + + + + {people.map(p=>renderPerson(p))} +
    People associated with this event:
    +
    } } @@ -82,4 +91,4 @@ const selector = createStructuredSelector({ status: peopleStatusSelector }); -export default connect(selector)(PeopleLoader); +export default connect(selector)(EventInfoContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js index afe96c73..509097d9 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js @@ -1,6 +1,7 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import { getEvents, getEventsReset, eventsSelector, eventsStatusSelector } from '../ducks/events' +import { selectEvent } from '../ducks/selectedEvent' import { PromiseStatus } from '../../../core/models' import PromiseResult from '../../../core/components/PromiseResult' import TimeSeries from '../misc/TimeSeries' @@ -17,12 +18,16 @@ class TimelineContainer extends Component { componentWillMount(){ const {dispatch, configuration} = this.props; - dispatch(getEvents(configuration)); + this.className = 'timeseries-chart'; + this.callBack = (ev)=>dispatch(selectEvent(ev)); + + dispatch(getEvents(configuration)); } componentWillReceiveProps(nextProps){ const {dispatch, configuration} = nextProps; + if (this.props.configuration != configuration) { dispatch(getEvents(configuration)); } @@ -36,7 +41,7 @@ class TimelineContainer extends Component { } if (status.done) { - this.chart = new TimeSeries(this.className, events, true); + this.chart = new TimeSeries(this.className, events, false, this.callBack); } } @@ -56,8 +61,10 @@ class TimelineContainer extends Component { return
    } } + const selector = createStructuredSelector({ events: eventsSelector, status: eventsStatusSelector }); + export default connect(selector)(TimelineContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js deleted file mode 100644 index bcf141a6..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js +++ /dev/null @@ -1,14 +0,0 @@ -import { createSelector } from 'reselect' -import moduleSelector from '../selector' -import { createDirtyReducer } from '../../../app/ducks/dirty' -import {SELECT_EVENT} from "./selectedEvents"; - -// Reducer -const actions = [ - SELECT_EVENT -]; - -export default createDirtyReducer(actions); - -// Selectors -export const dirtySelector = createSelector([moduleSelector], state => state.dirty); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js index 0d9fc183..4c9ccfb7 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js @@ -17,7 +17,7 @@ export const GET_PEOPLE_RESET = GET_PEOPLE + '_RESET'; export function getEventPeople(event) { return withApplicationId(id => { - const promise = api.getEventPeople(id,event); + const promise = api.getEventPeople(id,event.url); return createAction(GET_PEOPLE, { promise }); }); } @@ -35,7 +35,7 @@ export default function peopleReducer(state = initialState, action) { case GET_PEOPLE_RESET: return initialState; case GET_PEOPLE_ERROR: - return action.payload; + return [action.payload]; case GET_PEOPLE_SUCCESS: return action.payload.map(p=>new PersonInfo(p)); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvent.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvent.js new file mode 100644 index 00000000..9c8066ca --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvent.js @@ -0,0 +1,41 @@ +import { createSelector } from 'reselect' +import prefix from '../prefix' +import createAction from '../../../../misc/createAction' +import moduleSelector from '../selector' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import {SelectedEvent} from "../models"; + +// Actions +export const SET_SELECTED_EVENT = prefix('SET_SELECTED_EVENT'); +export function selectEvent(selectedEvent) { + return createAction(SET_SELECTED_EVENT, { selectedEvent }); +} +export const GET_SELECTED_EVENT = prefix('GET_SELECTED_EVENT'); +export function getSelectedEvent() { + return createAction(GET_SELECTED_EVENT) +} + +export const GET_SELECTED_EVENT_RESET = GET_SELECTED_EVENT + "RESET"; +export function getSelectedEventReset(){ + return createAction(GET_SELECTED_EVENT_RESET); +} + +// Reducer +const initialState = new SelectedEvent(); +export default function selectedEventReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_SELECTED_EVENT_RESET: + return initialState; + case GET_SELECTED_EVENT: + return new SelectedEvent(state); + case SET_SELECTED_EVENT: + return new SelectedEvent({isValid: true, event: action.payload.selectedEvent}); + default: + return state; + } +} + +// Selectors +export const selectedEventSelector = createSelector([moduleSelector],state => state.selectedEvent); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js deleted file mode 100644 index aadaf4c1..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvents.js +++ /dev/null @@ -1,27 +0,0 @@ -import { createSelector } from 'reselect' -import prefix from '../prefix' -import createAction from '../../../../misc/createAction' -import moduleSelector from '../selector' -import { GET_APPLICATION_START } from '../../../app/ducks/application' - -// Actions - -export const SELECT_EVENT = prefix('SELECT_EVENT'); -export function selectEvent(event) { - return createAction(SELECT_EVENT, { event }); -} - -// Reducer -const initialState = null; -export default function selectedEventReducer(state = initialState, action) { - switch (action.type) { - case GET_APPLICATION_START: - return initialState; - case SELECT_EVENT: - return action.payload.event; - } - return state; -} - -// Selectors -export const selectedEventSelector = createSelector([moduleSelector],state => state.selectedEvent); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js index 1a9f1190..4e43f183 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js @@ -2,10 +2,9 @@ import d3 from 'd3' import moment from 'moment' import * as _ from 'underscore' import {getAvailableVerticalSpace} from "../../../../components/FillInScreen"; -import {log} from "debug"; class TimeSeries { - constructor(spaced, data, enableBrush) { + constructor(spaced, data, enableBrush, callback) { var classd = spaced.replace(new RegExp(" "), "."); render(classd, spaced, data, enableBrush); @@ -152,8 +151,8 @@ class TimeSeries { }) .attr("r", 9) .on("click", function (d) { - log(new Date(d.start)); - }) + callback(d); + }); // ----------------------------------------- Brush --------------------------------------------- diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js index 9646efea..cae37bd0 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js @@ -17,9 +17,14 @@ export const PersonInfo = Record({ }); export const Configuration = Record({ - start: new Date("01 01 2010"), + start: new Date("01 01 2000"), end: new Date("01 01 2018"), limit: 100 }); +export const SelectedEvent = Record({ + isValid: false, + event: new EventInfo +}); + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js index 3c6eb260..c9f197ac 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js @@ -4,7 +4,6 @@ import { Application } from '../../../app/models' import { Visualizer } from '../../../core/models' import Visualization from '../components/Visualization' import ConfigToolbar from '../components/ConfigToolbar' -import SaveButton from '../components/SaveButton' class Configurator extends Component { static propTypes = { diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js index abf2ee89..6e0e879b 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js @@ -1,13 +1,13 @@ import { combineReducers } from 'redux'; import events from './ducks/events' import people from './ducks/people' -import selectedEvents from './ducks/selectedEvents' +import selectedEvent from './ducks/selectedEvent' import config from './ducks/configuration' const rootReducer = combineReducers({ events, people, - selectedEvents, + selectedEvent, config }); From 3db97453e9a05656b7eef7cf1183fce7e14aabae Mon Sep 17 00:00:00 2001 From: vvancak Date: Sun, 2 Apr 2017 19:25:07 +0200 Subject: [PATCH 21/84] EventTimeline: Start & End -> single Date (more data & people) --- .../visualizers/events/applicationRoutes.js | 2 +- .../events/components/Application.js | 11 --- .../events/components/ConfigToolbar.js | 7 +- .../events/containers/EventInfoContainer.js | 82 ++++++++++--------- .../events/containers/TimelineContainer.js | 10 ++- .../visualizers/events/ducks/events.js | 1 - .../visualizers/events/misc/TimeSeries.js | 6 +- .../modules/visualizers/events/models.js | 3 +- src/app/model/rdf/sparql/rgml/Event.scala | 2 +- .../rgml/extractor/EventExtractor.scala | 3 +- .../rgml/extractor/PeopleExtractor.scala | 19 +++-- .../sparql/rgml/query/EventPeopleQuery.scala | 15 ++-- .../rdf/sparql/rgml/query/EventQuery.scala | 59 +++++++------ 13 files changed, 113 insertions(+), 107 deletions(-) diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/applicationRoutes.js index 70727287..b0f3e4c3 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/applicationRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/applicationRoutes.js @@ -8,7 +8,7 @@ import Embed from './pages/Embed' export default function createRoutes(dispatch) { return ( - + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js index f188e15d..6af29284 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js @@ -3,7 +3,6 @@ import BodyPadding from '../../../../components/BodyPadding' import { Application as ApplicationModel } from '../../../app/models' import { Visualizer } from '../../../core/models' import Visualization from '../components/Visualization' -import { getConfiguration, getConfigurationReset } from '../ducks/configuration' import ConfigToolbar from "./ConfigToolbar"; class Application extends Component { @@ -13,16 +12,6 @@ class Application extends Component { embed: PropTypes.bool }; - componentWillMount() { - const { dispatch } = this.props; - dispatch(getConfiguration()); - } - - componentWillUnmount() { - const { dispatch } = this.props; - dispatch(getConfigurationReset()); - } - render() { const { embed } = this.props; return ( diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js index 62be7e47..04aea769 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js @@ -1,7 +1,7 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import {createStructuredSelector} from "reselect"; -import {configSelector, setConfiguration} from '../ducks/configuration' +import {configSelector, getConfigurationReset, setConfiguration} from '../ducks/configuration' import { Configuration } from '../models' import moment from "moment"; @@ -16,6 +16,11 @@ class ConfigToolbar extends Component { dispatch(setConfiguration(new Configuration())); } + componentWillUnmount(){ + const {dispatch} = this.props; + dispatch(getConfigurationReset()) + } + handleNewConfig(){ const {dispatch, configuration} = this.props; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js index 16d5f02f..0ddca1f9 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js @@ -32,56 +32,58 @@ class EventInfoContainer extends Component { render() { const {people, selectedEvent, status} = this.props; - if(!selectedEvent.isValid){ - return - To view more information about events, click on them in the timeline. - - } + // EVENT INFO: + var eventComponent = + To view more information about events, click on them in the timeline. + ; - if (!status.done) { - return - } + if(selectedEvent.isValid){ + var event = selectedEvent.event; + var dateString = moment(event.date).format('DD.MM.YYYY'); - if (people.length == 0){ - return - Could not load people for selected event. - + eventComponent =
    +

    Event info:

    +

    {event.name}

    +

    {event.description}

    +

    {dateString}

    + Event Link +
    ; } - var renderPerson = function(person){ - var style = {width: 100, height:150, "object-fit": 'contain'}; - return - Person Image - -

    {person.name}

    -

    {person.description}

    - Wiki Link - - - }; + // EVENT PEOPLE: + var peopleComponent = + Could not load people for selected event. + ; - var event = selectedEvent.event; - var startString = moment(event.start).format('DD.MM.YYYY'); - var endString = moment(event.end).format('DD.MM.YYYY'); + if (!status.done) { + peopleComponent = + } + if (people.length > 0) { + var renderPerson = function (person) { + var style = {width: 100, height: 150, "objectFit": 'contain'}; + return + No image available + +

    {person.name}

    +

    {person.description}

    + Wiki Link + + + }; - return
    -
    -

    {event.name}

    -

    {event.description}

    -

    From {startString} to {endString}

    - Event Link -
    -
    -
    + peopleComponent =
    +

    People associated with this event

    - - - - - {people.map(p=>renderPerson(p))}
    People associated with this event:
    + } + + // RENDER + return
    + {eventComponent} +
    + {peopleComponent}
    } } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js index 509097d9..3448b950 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js @@ -7,6 +7,8 @@ import PromiseResult from '../../../core/components/PromiseResult' import TimeSeries from '../misc/TimeSeries' import {createStructuredSelector} from "reselect"; import {Configuration} from "../models" +import CenteredMessage from '../../../../components/CenteredMessage' +import VisualizationMessage from '../components/VisualizationMessage' class TimelineContainer extends Component { static propTypes = { @@ -51,12 +53,18 @@ class TimelineContainer extends Component { } render() { - const {status} = this.props; + const {status, events} = this.props; if (!status.done) { return } + if (events.length == 0) { + return + Could not load people for selected event. + + } + require('../misc/TimeSeriesStyle.css'); return
    } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js index 2b59fcfd..9635a55c 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js @@ -6,7 +6,6 @@ import { GET_APPLICATION_START } from '../../../app/ducks/application' import { EventInfo } from '../models' import { createSelector } from 'reselect' import { createPromiseStatusSelector } from '../../../core/ducks/promises' -import storageReducerFactory from '../../../../misc/storageReducerFactory' import moduleSelector from '../selector' // Actions diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js index 4e43f183..7ccbf0e0 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js @@ -75,7 +75,7 @@ class TimeSeries { function render(classd, spaced, data, enableBrush) { - var padding = timeRangePad(_.pluck(data, 'start')); + var padding = timeRangePad(_.pluck(data, 'date')); var margin = { top: 10, @@ -144,10 +144,10 @@ class TimeSeries { .enter().append("circle") .attr("class", "circ") .attr("cx", function (d) { - return (lessThanDay(padding.pad)) ? x(d.start) : x(getDate(d.start)); + return (lessThanDay(padding.pad)) ? x(d.date) : x(getDate(d.date)); }) .attr("cy", function (d, i) { - return (lessThanDay(padding.pad)) ? y(getDate(d.start)) : y(getTime(d.start)); + return (lessThanDay(padding.pad)) ? y(getDate(d.date)) : y(getTime(d.date)); }) .attr("r", 9) .on("click", function (d) { diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js index cae37bd0..9abec774 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js @@ -3,8 +3,7 @@ import { Record } from 'immutable'; export const EventInfo = Record({ url: "url", name: "name", - start: "start", - end: "end", + date: new Date("2001-01-01"), info: "info" }); diff --git a/src/app/model/rdf/sparql/rgml/Event.scala b/src/app/model/rdf/sparql/rgml/Event.scala index c424cdd3..195f1e72 100644 --- a/src/app/model/rdf/sparql/rgml/Event.scala +++ b/src/app/model/rdf/sparql/rgml/Event.scala @@ -1,4 +1,4 @@ package model.rdf.sparql.rgml import java.util.Date -case class Event(url:String,name:String,start:Date,end:Date,info:String) +case class Event(url:String,name:String,date:Date,info:String) diff --git a/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala index 4bf48164..89b9dc43 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala @@ -16,8 +16,7 @@ class EventExtractor extends QueryExecutionResultExtractor[EventQuery, Seq[Event Some(resList.map(e => new Event( e.getResource("event").getURI, e.getLiteral("name").getString, - getDate(e, "start"), - getDate(e, "end"), + getDate(e, "date"), e.getResource("link").getURI ))) } diff --git a/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala index 204aece7..a067830e 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala @@ -11,12 +11,19 @@ class PeopleExtractor extends QueryExecutionResultExtractor[EventPeopleQuery, Se def extract(input: QueryExecution): Option[Seq[Person]] = { try { val resList = input.execSelect().toList - Some(resList.map(p => new Person( - p.getResource("person").getURI, - p.getLiteral("name").getString, - p.getLiteral("description").getString, - p.getResource("image").getURI, - p.getResource("link").getURI) + Some(resList.map(p => { + var description = if (p.contains("description")) p.getLiteral("description").getString else "no_description" + var image = if (p.contains("image")) p.getResource("image").getURI else "no_image" + var link = if (p.contains("link")) p.getResource("link").getURI else "no_link" + + new Person( + p.getResource("person").getURI, + p.getLiteral("name").getString, + description, + image, + link + ) + } )) } catch { diff --git a/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala index acc13452..870ad552 100644 --- a/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala @@ -13,15 +13,14 @@ class EventPeopleQuery(event: String) extends SparqlQuery { |PREFIX dbp: |SELECT ?person (SAMPLE(?personName) AS ?name) (SAMPLE(?personDescription) AS ?description) (SAMPLE(?personLink) AS ?link) (SAMPLE(?personImage) AS ?image) |WHERE { - | ?event rdf:type sch:Event . - | VALUES ?event { <@event> } - | | ?person rdf:type sch:Person ; - | foaf:name ?personName; - | foaf:isPrimaryTopicOf ?personLink; - | foaf:depiction ?personImage; - | dbp:shortDescription ?personDescription; - | ?relation ?event . + | foaf:name ?personName. + | + | OPTIONAL {?person foaf:isPrimaryTopicOf ?personLink} + | OPTIONAL {?person dbp:shortDescription ?personDescription} + | OPTIONAL {?person foaf:depiction ?personImage} + | + | <@event> ?relation ?person. |} |GROUP BY ?person """ diff --git a/src/app/model/rdf/sparql/rgml/query/EventQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventQuery.scala index a7cf3b4d..7d1c7879 100644 --- a/src/app/model/rdf/sparql/rgml/query/EventQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/EventQuery.scala @@ -7,34 +7,33 @@ import model.rdf.sparql.query.SparqlQuery class EventQuery(start: Date, end: Date, limit: Int) extends SparqlQuery{ val dateFormat = new SimpleDateFormat("YYYY-MM-DD") def get: String = - """ - |PREFIX rdf: - |PREFIX sch: - |PREFIX dbo: - |PREFIX foaf: - |PREFIX xsd: - | - |SELECT ?event (SAMPLE(?eventName) AS ?name) (SAMPLE(?eventStart) AS ?start) (SAMPLE(?eventEnd) AS ?end) (SAMPLE(?eventLink) AS ?link) - |WHERE { - | ?event rdf:type sch:Event ; - | foaf:name ?eventName ; - | dbo:startDate ?eventStart ; - | dbo:endDate ?eventEnd ; - | dbo:wikiPageExternalLink ?eventLink . - | - | FILTER (?eventStart > "@start"^^xsd:date) - | FILTER (?eventStart < "@end"^^xsd:date) - | - | FILTER EXISTS { - | ?person rdf:type sch:Person ; - | ?relation ?event . - | } - |} - |GROUP BY ?event - |LIMIT @limit - """ - .replace("@start",dateFormat.format(start)) - .replace("@end",dateFormat.format(end)) - .replace("@limit", limit.toString) - .stripMargin + """ + |PREFIX rdf: + |PREFIX sch: + |PREFIX dbo: + |PREFIX foaf: + |PREFIX xsd: + | + |SELECT ?event (SAMPLE(?eventName) AS ?name) (SAMPLE(?eventDate) AS ?date) (SAMPLE(?eventLink) AS ?link) + |WHERE { + | ?event rdf:type sch:Event ; + | foaf:name ?eventName ; + | dbo:date ?eventDate ; + | dbo:wikiPageExternalLink ?eventLink . + | + | FILTER (?eventDate > "@start"^^xsd:date) + | FILTER (?eventDate < "@end"^^xsd:date) + | + | FILTER EXISTS { + | ?person rdf:type sch:Person. + | ?event ?relation ?person. + | } + |} + |GROUP BY ?event + |LIMIT @limit + """ + .replace("@start",dateFormat.format(start)) + .replace("@end",dateFormat.format(end)) + .replace("@limit", limit.toString) + .stripMargin } From 8f7918d792601302a331682f1418928a7cd8e677 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sat, 8 Apr 2017 17:03:33 +0200 Subject: [PATCH 22/84] EventTimeline: Configuration saving --- .../modules/visualizers/events/api.js | 8 +- .../events/components/ConfigToolbar.js | 80 +++++++++++-------- .../events/components/Visualization.js | 25 +++--- .../events/containers/EventInfoContainer.js | 9 ++- .../events/containers/SaveButton.js | 10 +++ .../events/containers/TimelineContainer.js | 16 ++-- .../visualizers/events/ducks/configuration.js | 64 +++++++-------- .../modules/visualizers/events/ducks/dirty.js | 13 +++ .../visualizers/events/ducks/events.js | 4 +- .../visualizers/events/ducks/selectedEvent.js | 4 + .../visualizers/events/ducks/settings.js | 55 +++++++++++++ .../modules/visualizers/events/models.js | 2 +- .../visualizers/events/pages/Configurator.js | 13 +++ .../modules/visualizers/events/reducer.js | 6 +- .../rgml/extractor/PeopleExtractor.scala | 6 +- 15 files changed, 211 insertions(+), 104 deletions(-) create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/settings.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js index 202734d0..b82652b0 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js @@ -1,9 +1,9 @@ import rest from '../../../misc/rest' -export async function getEvents(applicationId, config) { - var start = config.start.getTime(); - var end = config.end.getTime(); - var limit = parseInt(config.limit); +export async function getEvents(applicationId, settings) { + var start = settings.start.getTime(); + var end = settings.end.getTime(); + var limit = parseInt(settings.limit); let payload = {"start":start, "end":end, "limit":limit}; const result = await rest('eventVisualizer/getEvents/' + applicationId,payload); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js index 04aea769..60e5b2dc 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js @@ -1,75 +1,91 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import {createStructuredSelector} from "reselect"; -import {configSelector, getConfigurationReset, setConfiguration} from '../ducks/configuration' -import { Configuration } from '../models' +import {settingsSelector, getSettingsReset, getSettings, setSettings} from '../ducks/settings' +import { Settings } from '../models' import moment from "moment"; +import {getSelectedEventReset} from "../ducks/selectedEvent"; class ConfigToolbar extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - configuration: PropTypes.instanceOf(Configuration).isRequired, + settings: PropTypes.instanceOf(Settings).isRequired, }; componentWillMount() { const { dispatch } = this.props; - dispatch(setConfiguration(new Configuration())); + dispatch(getSettings()); + } + + componentWillReceiveProps(nextProps){ + const {settings} = nextProps; + + if (this.props.settings != settings) { + var startString = moment(settings.start).format('YYYY-MM-DD'); + var endString = moment(settings.end).format('YYYY-MM-DD'); + + document.getElementsByName("start")[0].value = startString; + document.getElementsByName("end")[0].value = endString; + document.getElementsByName("limit")[0].value = settings.limit; + } } componentWillUnmount(){ const {dispatch} = this.props; - dispatch(getConfigurationReset()) + dispatch(getSettingsReset()) } handleNewConfig(){ - const {dispatch, configuration} = this.props; + const {dispatch, settings} = this.props; var start = document.getElementsByName("start")[0].value; var end = document.getElementsByName("end")[0].value; var limit = document.getElementsByName("limit")[0].value; - var newConfig = {start:new Date(start), end:new Date(end), limit:limit}; + var newSettings = {start:new Date(start), end:new Date(end), limit:limit}; - if (configuration != newConfig) { - dispatch(setConfiguration(newConfig)); + if (settings != newSettings) { + dispatch(setSettings(newSettings)); + dispatch(getSelectedEventReset()); } } render() { - const {configuration} = this.props; + const settings = this.props.settings; + + var startString = moment(settings.start).format('YYYY-MM-DD'); + var endString = moment(settings.end).format('YYYY-MM-DD'); - var startString = moment(configuration.start).format('YYYY-MM-DD'); - var endString = moment(configuration.end).format('YYYY-MM-DD'); return
    - - - - - + + + + + - - - - - - + + + + + +
    TimeSeries StartTimeSeries EndMax event count
    TimeSeries StartTimeSeries EndMax event count
    - - - - - - - this.handleNewConfig()}/> -
    + + + + + + + this.handleNewConfig()}/> +
    } } const selector = createStructuredSelector({ - configuration: configSelector + settings: settingsSelector }); export default connect(selector)(ConfigToolbar); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js index 3f215920..2db28648 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js @@ -1,12 +1,12 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import {createStructuredSelector} from "reselect"; -import { configSelector } from '../ducks/configuration' +import { settingsSelector } from '../ducks/settings' import {getSelectedEvent, getSelectedEventReset, selectedEventSelector} from "../ducks/selectedEvent"; import TimelineContainer from '../containers/TimelineContainer' import EventInfoContainer from '../containers/EventInfoContainer' -import {Configuration, SelectedEvent} from '../models' -import { getConfiguration, getConfigurationReset} from '../ducks/configuration' +import {Settings, SelectedEvent} from '../models' +import { getSettings, getSettingsReset} from '../ducks/settings' import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' @@ -14,41 +14,36 @@ class Visualization extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, selectedEvent: PropTypes.instanceOf(SelectedEvent).isRequired, - configuration: PropTypes.instanceOf(Configuration).isRequired + settings: PropTypes.instanceOf(Settings).isRequired }; - componentWillMount(){ - const {dispatch} = this.props; - dispatch(getSelectedEvent()); - } - componentWillUpdate(){ const { dispatch } = this.props; dispatch(getSelectedEvent()); - dispatch(getConfiguration()); + dispatch(getSettings()); } componentWillUnmount() { const { dispatch } = this.props; dispatch(getSelectedEventReset()); - dispatch(getConfigurationReset()); + dispatch(getSettingsReset()); } render() { - const {configuration, selectedEvent} = this.props; - if(!configuration){ + const {settings, selectedEvent} = this.props; + if(!settings){ return An error occurred while loading the configuration. } return
    - +
    } } const selector = createStructuredSelector({ - configuration: configSelector, + settings: settingsSelector, selectedEvent: selectedEventSelector }); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js index 0ddca1f9..cdfc8e53 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js @@ -19,8 +19,13 @@ class EventInfoContainer extends Component { componentWillReceiveProps(nextProps){ const {dispatch, selectedEvent} = nextProps; - if (selectedEvent.isValid && this.props.selectedEvent != selectedEvent) { - dispatch(getEventPeople(selectedEvent.event)); + if (this.props.selectedEvent != selectedEvent) { + if (selectedEvent.isValid) { + dispatch(getEventPeople(selectedEvent.event)); + } + else { + dispatch(getEventPeopleReset()); + } } } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js new file mode 100644 index 00000000..369b0019 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js @@ -0,0 +1,10 @@ +import React from 'react' +import { saveConfiguration, saveConfigurationStatusSelector } from '../ducks/configuration' +import { dirtySelector } from '../ducks/dirty' + +import createSaveButton from '../../../app/containers/createSaveButton' + +export default createSaveButton( + saveConfiguration, + saveConfigurationStatusSelector, + dirtySelector); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js index 3448b950..1e2ffa8a 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js @@ -6,7 +6,7 @@ import { PromiseStatus } from '../../../core/models' import PromiseResult from '../../../core/components/PromiseResult' import TimeSeries from '../misc/TimeSeries' import {createStructuredSelector} from "reselect"; -import {Configuration} from "../models" +import {Settings} from "../models" import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' @@ -14,24 +14,22 @@ class TimelineContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, events: PropTypes.instanceOf(Array).isRequired, - configuration: PropTypes.instanceOf(Configuration).isRequired, + settings: PropTypes.instanceOf(Settings).isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired }; componentWillMount(){ - const {dispatch, configuration} = this.props; + const {dispatch} = this.props; this.className = 'timeseries-chart'; this.callBack = (ev)=>dispatch(selectEvent(ev)); - - dispatch(getEvents(configuration)); } componentWillReceiveProps(nextProps){ - const {dispatch, configuration} = nextProps; + const {dispatch, settings} = nextProps; - if (this.props.configuration != configuration) { - dispatch(getEvents(configuration)); + if (this.props.settings != settings) { + dispatch(getEvents(settings)); } } @@ -61,7 +59,7 @@ class TimelineContainer extends Component { if (events.length == 0) { return - Could not load people for selected event. + No events were loaded. Check the settings please. } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js index 7adcc69e..ac20bdd9 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js @@ -1,42 +1,38 @@ -import createAction from '../../../../misc/createAction' import prefix from '../prefix' -import { GET_APPLICATION_START } from '../../../app/ducks/application' -import { Configuration } from '../models' -import { createSelector } from 'reselect' import moduleSelector from '../selector' +import { createPromiseStatusSelector } from '../../../core/ducks/promises' +import {createGetConfiguration, createGetConfigurationReset, createSaveConfiguration} from '../../../app/ducks/configuration' +import {SelectedEvent, Settings} from "../models"; +import {createSelector} from "reselect"; // Actions -export const GET_CONFIG = prefix('GET_CONFIG'); -export const SET_CONFIG = prefix('SET_CONFIG'); -export const GET_CONFIG_RESET = GET_CONFIG + '_RESET'; +export const SAVE_CONFIGURATION = prefix('SAVE_CONFIGURATION'); +export const SAVE_CONFIGURATION_START = SAVE_CONFIGURATION + '_START'; +export const SAVE_CONFIGURATION_ERROR = SAVE_CONFIGURATION + '_ERROR'; +export const SAVE_CONFIGURATION_SUCCESS = SAVE_CONFIGURATION + '_SUCCESS'; -export function getConfiguration() { - return createAction(GET_CONFIG); -} -export function setConfiguration(config) { - return createAction(SET_CONFIG, {config}) -} -export function getConfigurationReset() { - return createAction(GET_CONFIG_RESET); -} - -// Reducer -const initialState = new Configuration(); -export default function configReducer(state = initialState, action) { - switch (action.type) { - case GET_APPLICATION_START: - return initialState; - case GET_CONFIG_RESET: - return initialState; - case SET_CONFIG: - return Configuration(action.payload.config); - case GET_CONFIG: - return new Configuration(state); - default: - return state; - } -}; +export const GET_CONFIGURATION = prefix('GET_CONFIGURATION'); +export const GET_CONFIGURATION_START = GET_CONFIGURATION + '_START'; +export const GET_CONFIGURATION_ERROR = GET_CONFIGURATION + '_ERROR'; +export const GET_CONFIGURATION_SUCCESS = GET_CONFIGURATION + '_SUCCESS'; +export const GET_CONFIGURATION_RESET = GET_CONFIGURATION + '_RESET'; // Selectors -export const configSelector = createSelector([moduleSelector], state => state.config); +export const saveConfigurationStatusSelector = createPromiseStatusSelector(SAVE_CONFIGURATION); +export const getConfigurationStatusSelector = createPromiseStatusSelector(GET_CONFIGURATION); + +export const configurationSelector = createSelector( + [moduleSelector], + state => ({ + settings: new Settings(state.settings), + selectedEvent: new SelectedEvent(state.selectedEvent) + }) +); +// Actual actions created using factories +export const saveConfiguration = + createSaveConfiguration(SAVE_CONFIGURATION, configurationSelector); +export const getConfiguration = + createGetConfiguration(GET_CONFIGURATION); +export const getConfigurationReset = + createGetConfigurationReset(GET_CONFIGURATION_RESET); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js new file mode 100644 index 00000000..5cd9201b --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js @@ -0,0 +1,13 @@ +import { createSelector } from 'reselect' +import moduleSelector from '../selector' +import { createDirtyReducer } from '../../../app/ducks/dirty' +import { GET_SELECTED_EVENT, GET_SELECTED_EVENT_RESET } from './selectedEvent' +import { GET_SETTINGS, GET_SETTINGS_RESET} from './settings' + +// Reducer +const actions = [ GET_SETTINGS, GET_SETTINGS_RESET, GET_SELECTED_EVENT, GET_SELECTED_EVENT_RESET]; + +export default createDirtyReducer(actions); + +// Selectors +export const dirtySelector = createSelector([moduleSelector], state => state.dirty); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js index 9635a55c..d9f419a5 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js @@ -15,9 +15,9 @@ export const GET_EVENTS_ERROR = GET_EVENTS + '_ERROR'; export const GET_EVENTS_SUCCESS = GET_EVENTS + '_SUCCESS'; export const GET_EVENTS_RESET = GET_EVENTS + '_RESET'; -export function getEvents(config) { +export function getEvents(settings) { return withApplicationId(id => { - const promise = api.getEvents(id,config); + const promise = api.getEvents(id,settings); return createAction(GET_EVENTS, { promise }); }); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvent.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvent.js index 9c8066ca..31e7c312 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvent.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvent.js @@ -4,6 +4,7 @@ import createAction from '../../../../misc/createAction' import moduleSelector from '../selector' import { GET_APPLICATION_START } from '../../../app/ducks/application' import {SelectedEvent} from "../models"; +import {GET_CONFIGURATION_SUCCESS} from "./configuration"; // Actions export const SET_SELECTED_EVENT = prefix('SET_SELECTED_EVENT'); @@ -30,6 +31,9 @@ export default function selectedEventReducer(state = initialState, action) { return initialState; case GET_SELECTED_EVENT: return new SelectedEvent(state); + case GET_CONFIGURATION_SUCCESS: + if ("selectedEvent" in action.payload) return new SelectedEvent(action.payload.selectedEvent); + else return state; case SET_SELECTED_EVENT: return new SelectedEvent({isValid: true, event: action.payload.selectedEvent}); default: diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/settings.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/settings.js new file mode 100644 index 00000000..3b72a5c1 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/settings.js @@ -0,0 +1,55 @@ +import createAction from '../../../../misc/createAction' +import prefix from '../prefix' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { Settings } from '../models' +import { createSelector } from 'reselect' +import moduleSelector from '../selector' +import {GET_CONFIGURATION_SUCCESS} from "./configuration"; + +// Actions +export const GET_SETTINGS = prefix('GET_SETTINGS'); +export const SET_SETTINGS = prefix('SET_SETTINGS'); +export const GET_SETTINGS_RESET = GET_SETTINGS + '_RESET'; + +export function getSettings() { + return createAction(GET_SETTINGS); +} +export function setSettings(settings) { + return createAction(SET_SETTINGS, {settings}) +} +export function getSettingsReset() { + return createAction(GET_SETTINGS_RESET); +} + +// Reducer +const initialState = new Settings(); +export default function configReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_SETTINGS_RESET: + return initialState; + case SET_SETTINGS: + return new Settings(action.payload.settings); + case GET_CONFIGURATION_SUCCESS: + return parseSavedSettings(action.payload); + case GET_SETTINGS: + return new Settings(state); + default: + return state; + } +}; + +function parseSavedSettings(payload){ + if ("settings" in payload) { + var start = new Date(payload.settings.start); + var end = new Date(payload.settings.end); + var limit = payload.settings.limit; + return new Settings({start: start, end: end, limit: limit}); + } + else return initialState; +} + +// Selectors +export const settingsSelector = createSelector([moduleSelector], state => state.settings); + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js index 9abec774..d1ad1703 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js @@ -15,7 +15,7 @@ export const PersonInfo = Record({ info: "info" }); -export const Configuration = Record({ +export const Settings = Record({ start: new Date("01 01 2000"), end: new Date("01 01 2018"), limit: 100 diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js index c9f197ac..ea098664 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js @@ -4,6 +4,8 @@ import { Application } from '../../../app/models' import { Visualizer } from '../../../core/models' import Visualization from '../components/Visualization' import ConfigToolbar from '../components/ConfigToolbar' +import SaveButton from '../containers/SaveButton' +import {getConfiguration, getConfigurationReset} from "../ducks/configuration"; class Configurator extends Component { static propTypes = { @@ -11,11 +13,22 @@ class Configurator extends Component { visualizer: PropTypes.instanceOf(Visualizer).isRequired }; + componentWillMount() { + const { dispatch } = this.props; + dispatch(getConfiguration()); + } + + componentWillUnmount() { + const { dispatch } = this.props; + dispatch(getConfigurationReset()); + } + render() { return ( + ) } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js index 6e0e879b..8a7e5941 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js @@ -2,13 +2,15 @@ import { combineReducers } from 'redux'; import events from './ducks/events' import people from './ducks/people' import selectedEvent from './ducks/selectedEvent' -import config from './ducks/configuration' +import settings from './ducks/settings' +import dirty from './ducks/dirty' const rootReducer = combineReducers({ events, people, selectedEvent, - config + settings, + dirty }); export default rootReducer; \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala index a067830e..fbabbdda 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala @@ -12,9 +12,9 @@ class PeopleExtractor extends QueryExecutionResultExtractor[EventPeopleQuery, Se try { val resList = input.execSelect().toList Some(resList.map(p => { - var description = if (p.contains("description")) p.getLiteral("description").getString else "no_description" - var image = if (p.contains("image")) p.getResource("image").getURI else "no_image" - var link = if (p.contains("link")) p.getResource("link").getURI else "no_link" + var description = if (p.contains("description")) p.getLiteral("description").getString else "No description available." + var image = if (p.contains("image")) p.getResource("image").getURI else "" + var link = if (p.contains("link")) p.getResource("link").getURI else "" new Person( p.getResource("person").getURI, From a6b3d1c6ade8ead2f972aedc1a7dd68cdee0885c Mon Sep 17 00:00:00 2001 From: vvancak Date: Sun, 30 Apr 2017 23:39:12 +0200 Subject: [PATCH 23/84] Timeline : Queries & Extractors --- src/app/controllers/api/package.scala | 1 + .../assistant/rest/RelatedNodesRequest.scala | 2 +- .../model/rdf/extractor/CountExtractor.scala | 23 +++++++ .../rdf/sparql/SparqlEndpointService.scala | 5 +- .../sparql/SparqlEndpointServiceImpl.scala | 15 ++++- .../ResourcesThroughLensExtractor.scala | 2 +- .../rdf/sparql/query/SparqlCountQuery.scala | 5 ++ src/app/model/rdf/sparql/rgml/Event.scala | 4 -- src/app/model/rdf/sparql/rgml/Person.scala | 3 - .../rgml/extractor/EdgesExtractor.scala | 2 +- .../rgml/extractor/GraphExtractor.scala | 2 +- ...Extractor.scala => InstantExtractor.scala} | 18 +++-- .../rgml/extractor/IntervalExtractor.scala | 34 ++++++++++ .../rgml/extractor/NodesExtractor.scala | 2 +- .../extractor/NodesWithDegreeExtractor.scala | 2 +- .../rgml/extractor/PeopleExtractor.scala | 35 ---------- .../ThingToInstantConnectionExtractor.scala | 26 ++++++++ .../ThingToIntervalConnectionExtractor.scala | 26 ++++++++ ...oThingWithInstantConnectionExtractor.scala | 27 ++++++++ ...ThingWithIntervalConnectionExtractor.scala | 27 ++++++++ .../rdf/sparql/rgml/models/Connection.scala | 3 + .../rdf/sparql/rgml/{ => models}/Edge.scala | 2 +- .../rgml/{ => models}/EdgeDirection.scala | 3 +- .../rdf/sparql/rgml/{ => models}/Graph.scala | 2 +- .../rdf/sparql/rgml/models/Instant.scala | 4 ++ .../rdf/sparql/rgml/models/Interval.scala | 4 ++ .../rdf/sparql/rgml/{ => models}/Node.scala | 2 +- .../rgml/{ => models}/NodeWithDegree.scala | 2 +- .../rgml/query/AdjacentNodesQuery.scala | 4 +- .../sparql/rgml/query/EventPeopleQuery.scala | 30 --------- .../rdf/sparql/rgml/query/EventQuery.scala | 39 ----------- .../rgml/query/IncidentEdgesQuery.scala | 2 +- .../rdf/sparql/rgml/query/InstantQuery.scala | 60 +++++++++++++++++ .../rdf/sparql/rgml/query/IntervalQuery.scala | 66 +++++++++++++++++++ .../rdf/sparql/rgml/query/QueryHelpers.scala | 41 ++++++++++++ .../rgml/query/ThingsWithInstantQuery.scala | 38 +++++++++++ .../rgml/query/ThingsWithIntervalQuery.scala | 39 +++++++++++ .../ThingsWithThingsWithInstantQuery.scala | 41 ++++++++++++ .../ThingsWithThingsWithIntervalQuery.scala | 41 ++++++++++++ 39 files changed, 546 insertions(+), 138 deletions(-) create mode 100644 src/app/model/rdf/extractor/CountExtractor.scala create mode 100644 src/app/model/rdf/sparql/query/SparqlCountQuery.scala delete mode 100644 src/app/model/rdf/sparql/rgml/Event.scala delete mode 100644 src/app/model/rdf/sparql/rgml/Person.scala rename src/app/model/rdf/sparql/rgml/extractor/{EventExtractor.scala => InstantExtractor.scala} (56%) create mode 100644 src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala delete mode 100644 src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala create mode 100644 src/app/model/rdf/sparql/rgml/extractor/ThingToInstantConnectionExtractor.scala create mode 100644 src/app/model/rdf/sparql/rgml/extractor/ThingToIntervalConnectionExtractor.scala create mode 100644 src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithInstantConnectionExtractor.scala create mode 100644 src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithIntervalConnectionExtractor.scala create mode 100644 src/app/model/rdf/sparql/rgml/models/Connection.scala rename src/app/model/rdf/sparql/rgml/{ => models}/Edge.scala (67%) rename src/app/model/rdf/sparql/rgml/{ => models}/EdgeDirection.scala (91%) rename src/app/model/rdf/sparql/rgml/{ => models}/Graph.scala (65%) create mode 100644 src/app/model/rdf/sparql/rgml/models/Instant.scala create mode 100644 src/app/model/rdf/sparql/rgml/models/Interval.scala rename src/app/model/rdf/sparql/rgml/{ => models}/Node.scala (71%) rename src/app/model/rdf/sparql/rgml/{ => models}/NodeWithDegree.scala (78%) delete mode 100644 src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala delete mode 100644 src/app/model/rdf/sparql/rgml/query/EventQuery.scala create mode 100644 src/app/model/rdf/sparql/rgml/query/InstantQuery.scala create mode 100644 src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala create mode 100644 src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala create mode 100644 src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala create mode 100644 src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala create mode 100644 src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala create mode 100644 src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala diff --git a/src/app/controllers/api/package.scala b/src/app/controllers/api/package.scala index 95630b0f..6634d021 100644 --- a/src/app/controllers/api/package.scala +++ b/src/app/controllers/api/package.scala @@ -8,6 +8,7 @@ import model.rdf.sparql.rgml._ import model.rdf.sparql.datacube._ import model.rdf.sparql.fresnel.{Lens, ResourceThroughLens} import model.rdf.sparql.geo._ +import model.rdf.sparql.rgml.models.{Edge, Graph, Node, NodeWithDegree} import model.rdf.sparql.visualization.{Concept, HierarchyNode, Scheme} import model.rdf.{LocalizedValue, Property} import model.service.component.DataReference diff --git a/src/app/model/assistant/rest/RelatedNodesRequest.scala b/src/app/model/assistant/rest/RelatedNodesRequest.scala index 0fad18c6..ca29fc92 100644 --- a/src/app/model/assistant/rest/RelatedNodesRequest.scala +++ b/src/app/model/assistant/rest/RelatedNodesRequest.scala @@ -1,5 +1,5 @@ package model.assistant.rest -import model.rdf.sparql.rgml.EdgeDirection._ +import model.rdf.sparql.rgml.models.EdgeDirection._ import play.api.libs.json.Json diff --git a/src/app/model/rdf/extractor/CountExtractor.scala b/src/app/model/rdf/extractor/CountExtractor.scala new file mode 100644 index 00000000..04b53476 --- /dev/null +++ b/src/app/model/rdf/extractor/CountExtractor.scala @@ -0,0 +1,23 @@ +package model.rdf.sparql.extractor + +import model.rdf.extractor.QueryExecutionResultExtractor +import model.rdf.sparql.query.SparqlCountQuery +import org.apache.jena.query.QueryExecution + +class CountExtractor extends QueryExecutionResultExtractor[SparqlCountQuery, Integer] { + + def extract(input: QueryExecution): Option[Integer] = { + try { + val resultSet = input.execSelect() + if (resultSet.hasNext()) { + Some(resultSet.next().getLiteral("count").getInt()) + } + else None + } + catch { + case e: org.apache.jena.sparql.engine.http.QueryExceptionHTTP => { + None + } + } + } +} \ No newline at end of file diff --git a/src/app/model/rdf/sparql/SparqlEndpointService.scala b/src/app/model/rdf/sparql/SparqlEndpointService.scala index a23ccfc1..61a47d70 100644 --- a/src/app/model/rdf/sparql/SparqlEndpointService.scala +++ b/src/app/model/rdf/sparql/SparqlEndpointService.scala @@ -1,12 +1,13 @@ package model.rdf.sparql import _root_.model.rdf.extractor.QueryExecutionResultExtractor -import _root_.model.rdf.sparql.query.SparqlQuery +import _root_.model.rdf.sparql.query.{SparqlQuery, SparqlCountQuery} trait SparqlEndpointService { def getResult[Q <: SparqlQuery, R](sparqlEndpoint: SparqlEndpoint, query: Q, extractor: QueryExecutionResultExtractor[Q, R]): Option[R] - def dereference[Q <: SparqlQuery, R](uri: String, query: Q, extractor: QueryExecutionResultExtractor[Q, R]): Option[R] + def getCount[Q<: SparqlCountQuery](sparqlEndpoint: SparqlEndpoint, query: Q, extractor: QueryExecutionResultExtractor[Q,Integer]): Option[Integer] + def dereference[Q <: SparqlQuery, R](uri: String, query: Q, extractor: QueryExecutionResultExtractor[Q, R]): Option[R] } diff --git a/src/app/model/rdf/sparql/SparqlEndpointServiceImpl.scala b/src/app/model/rdf/sparql/SparqlEndpointServiceImpl.scala index 5597dd5f..99402949 100644 --- a/src/app/model/rdf/sparql/SparqlEndpointServiceImpl.scala +++ b/src/app/model/rdf/sparql/SparqlEndpointServiceImpl.scala @@ -2,7 +2,7 @@ package model.rdf.sparql import _root_.model.rdf.Graph import _root_.model.rdf.extractor.QueryExecutionResultExtractor -import _root_.model.rdf.sparql.query.SparqlQuery +import _root_.model.rdf.sparql.query.{SparqlQuery, SparqlCountQuery} import org.apache.jena.query.{QueryExecution, QueryExecutionFactory} import org.apache.jena.sparql.engine.http.QueryExceptionHTTP import scaldi.Injector @@ -19,6 +19,15 @@ class SparqlEndpointServiceImpl(implicit inj: Injector) extends SparqlEndpointSe } } + def getCount[Q<: SparqlCountQuery](sparqlEndpoint: SparqlEndpoint, query: Q, extractor: QueryExecutionResultExtractor[Q,Integer]): Option[Integer] = { + try { + extractor.extract(count(sparqlEndpoint,query)) + } + catch { + case qEx: QueryExceptionHTTP => throw qEx + } + } + def dereference[Q <: SparqlQuery, R](uri: String, query: Q, extractor: QueryExecutionResultExtractor[Q, R]): Option[R] = { try { val request = Http(uri) @@ -43,4 +52,8 @@ class SparqlEndpointServiceImpl(implicit inj: Injector) extends SparqlEndpointSe def execution(sparqlEndpoint: SparqlEndpoint, query: SparqlQuery): QueryExecution = { sparqlEndpoint.queryExecutionFactory()(query.get) } + + def count(sparqlEndpoint: SparqlEndpoint, query: SparqlCountQuery):QueryExecution = { + sparqlEndpoint.queryExecutionFactory()(query.getCount) + } } diff --git a/src/app/model/rdf/sparql/fresnel/extractor/ResourcesThroughLensExtractor.scala b/src/app/model/rdf/sparql/fresnel/extractor/ResourcesThroughLensExtractor.scala index a735053b..ae97de5c 100644 --- a/src/app/model/rdf/sparql/fresnel/extractor/ResourcesThroughLensExtractor.scala +++ b/src/app/model/rdf/sparql/fresnel/extractor/ResourcesThroughLensExtractor.scala @@ -4,7 +4,7 @@ import model.rdf.LocalizedValue import model.rdf.extractor.QueryExecutionResultExtractor import model.rdf.sparql.fresnel.{Lens, ResourceThroughLens} import model.rdf.sparql.fresnel.query.ResourcesThroughLensQuery -import model.rdf.sparql.rgml.Edge +import model.rdf.sparql.rgml.models.Edge import model.rdf.sparql.rgml.query.EdgesQuery import model.rdf.vocabulary.RGML import org.apache.jena.query.QueryExecution diff --git a/src/app/model/rdf/sparql/query/SparqlCountQuery.scala b/src/app/model/rdf/sparql/query/SparqlCountQuery.scala new file mode 100644 index 00000000..80543f3f --- /dev/null +++ b/src/app/model/rdf/sparql/query/SparqlCountQuery.scala @@ -0,0 +1,5 @@ +package model.rdf.sparql.query + +trait SparqlCountQuery { + def getCount : String +} diff --git a/src/app/model/rdf/sparql/rgml/Event.scala b/src/app/model/rdf/sparql/rgml/Event.scala deleted file mode 100644 index 195f1e72..00000000 --- a/src/app/model/rdf/sparql/rgml/Event.scala +++ /dev/null @@ -1,4 +0,0 @@ -package model.rdf.sparql.rgml -import java.util.Date - -case class Event(url:String,name:String,date:Date,info:String) diff --git a/src/app/model/rdf/sparql/rgml/Person.scala b/src/app/model/rdf/sparql/rgml/Person.scala deleted file mode 100644 index 1c4868b5..00000000 --- a/src/app/model/rdf/sparql/rgml/Person.scala +++ /dev/null @@ -1,3 +0,0 @@ -package model.rdf.sparql.rgml - -case class Person (url:String, name:String, description: String, image: String, info:String) diff --git a/src/app/model/rdf/sparql/rgml/extractor/EdgesExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/EdgesExtractor.scala index d41800d2..a41cb17a 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/EdgesExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/EdgesExtractor.scala @@ -1,7 +1,7 @@ package model.rdf.sparql.rgml.extractor import model.rdf.extractor.QueryExecutionResultExtractor -import model.rdf.sparql.rgml.Edge +import model.rdf.sparql.rgml.models.Edge import model.rdf.sparql.rgml.query.EdgesQuery import model.rdf.vocabulary.RGML import org.apache.jena.query.QueryExecution diff --git a/src/app/model/rdf/sparql/rgml/extractor/GraphExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/GraphExtractor.scala index 80abf05e..e0bba4d1 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/GraphExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/GraphExtractor.scala @@ -1,7 +1,7 @@ package model.rdf.sparql.rgml.extractor import model.rdf.extractor.QueryExecutionResultExtractor -import model.rdf.sparql.rgml.Graph +import model.rdf.sparql.rgml.models.Graph import model.rdf.sparql.rgml.query.GraphQuery import org.apache.jena.query.QueryExecution diff --git a/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala similarity index 56% rename from src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala rename to src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala index 89b9dc43..1049a057 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/EventExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala @@ -4,20 +4,18 @@ import java.util.Date import java.text.SimpleDateFormat import scala.collection.JavaConversions._ import model.rdf.extractor.QueryExecutionResultExtractor -import model.rdf.sparql.rgml.Event -import model.rdf.sparql.rgml.query.EventQuery +import model.rdf.sparql.rgml.models.Instant +import model.rdf.sparql.rgml.query.InstantQuery import org.apache.jena.query.{QueryExecution, QuerySolution} -class EventExtractor extends QueryExecutionResultExtractor[EventQuery, Seq[Event]] { +class InstantExtractor extends QueryExecutionResultExtractor[InstantQuery, Seq[Instant]] { - def extract(input: QueryExecution): Option[Seq[Event]] = { + def extract(input: QueryExecution): Option[Seq[Instant]] = { try { val resList = input.execSelect().toList - Some(resList.map(e => new Event( - e.getResource("event").getURI, - e.getLiteral("name").getString, - getDate(e, "date"), - e.getResource("link").getURI + Some(resList.map(e => new Instant( + e.getResource("url").getURI, + getDate(e, "date") ))) } catch { @@ -30,6 +28,6 @@ class EventExtractor extends QueryExecutionResultExtractor[EventQuery, Seq[Event private def getDate(qs: QuerySolution, fieldName: String): Date = { val dateFormat = new SimpleDateFormat("YYYY-MM-DD") val fieldValue = qs.getLiteral(fieldName).getString() - if (!fieldValue.isEmpty()) dateFormat.parse(fieldValue) else new Date + return dateFormat.parse(fieldValue) } } \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala new file mode 100644 index 00000000..a82b9cd0 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala @@ -0,0 +1,34 @@ +package model.rdf.sparql.rgml.extractor + +import java.text.SimpleDateFormat +import java.util.Date + +import scala.collection.JavaConversions._ +import model.rdf.extractor.QueryExecutionResultExtractor +import model.rdf.sparql.rgml.models.Interval +import model.rdf.sparql.rgml.query.IntervalQuery +import org.apache.jena.query.{QueryExecution, QuerySolution} + +class IntervalExtractor extends QueryExecutionResultExtractor[IntervalQuery, Seq[Interval]] { + def extract(input: QueryExecution): Option[Seq[Interval]] = { + try { + val resList = input.execSelect().toList + Some(resList.map(e => new Interval( + e.getResource("url").getURI, + getDate(e, "start"), + getDate(e, "end") + ))) + } + catch { + case e: org.apache.jena.sparql.engine.http.QueryExceptionHTTP => { + None + } + } + } + + private def getDate(qs: QuerySolution, fieldName: String): Date = { + val dateFormat = new SimpleDateFormat("YYYY-MM-DD") + val fieldValue = qs.getLiteral(fieldName).getString() + return dateFormat.parse(fieldValue) + } +} diff --git a/src/app/model/rdf/sparql/rgml/extractor/NodesExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/NodesExtractor.scala index f38fa051..90bc5edd 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/NodesExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/NodesExtractor.scala @@ -2,7 +2,7 @@ package model.rdf.sparql.rgml.extractor import model.rdf.LocalizedValue import model.rdf.extractor.QueryExecutionResultExtractor -import model.rdf.sparql.rgml.Node +import model.rdf.sparql.rgml.models.Node import model.rdf.sparql.rgml.query.NodesQuery import model.rdf.vocabulary.RGML import org.apache.jena.query.QueryExecution diff --git a/src/app/model/rdf/sparql/rgml/extractor/NodesWithDegreeExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/NodesWithDegreeExtractor.scala index 1f83e27a..9d1926aa 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/NodesWithDegreeExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/NodesWithDegreeExtractor.scala @@ -3,7 +3,7 @@ package model.rdf.sparql.rgml.extractor import model.rdf.LocalizedValue import model.rdf.extractor.QueryExecutionResultExtractor import model.rdf.sparql.rgml.query.{NodesQuery, NodesWithDegreeQuery} -import model.rdf.sparql.rgml.{Graph, NodeWithDegree} +import model.rdf.sparql.rgml.models.{Graph, NodeWithDegree} import model.rdf.vocabulary.RGML import org.apache.jena.query.QueryExecution import org.apache.jena.vocabulary.{RDF, RDFS} diff --git a/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala deleted file mode 100644 index fbabbdda..00000000 --- a/src/app/model/rdf/sparql/rgml/extractor/PeopleExtractor.scala +++ /dev/null @@ -1,35 +0,0 @@ -package model.rdf.sparql.rgml.extractor - -import model.rdf.extractor.QueryExecutionResultExtractor -import model.rdf.sparql.rgml.Person -import model.rdf.sparql.rgml.query.EventPeopleQuery -import org.apache.jena.query.QueryExecution -import scala.collection.JavaConversions._ - - -class PeopleExtractor extends QueryExecutionResultExtractor[EventPeopleQuery, Seq[Person]]{ - def extract(input: QueryExecution): Option[Seq[Person]] = { - try { - val resList = input.execSelect().toList - Some(resList.map(p => { - var description = if (p.contains("description")) p.getLiteral("description").getString else "No description available." - var image = if (p.contains("image")) p.getResource("image").getURI else "" - var link = if (p.contains("link")) p.getResource("link").getURI else "" - - new Person( - p.getResource("person").getURI, - p.getLiteral("name").getString, - description, - image, - link - ) - } - )) - } - catch { - case e: org.apache.jena.sparql.engine.http.QueryExceptionHTTP => { - None - } - } - } -} diff --git a/src/app/model/rdf/sparql/rgml/extractor/ThingToInstantConnectionExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/ThingToInstantConnectionExtractor.scala new file mode 100644 index 00000000..1049431c --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/extractor/ThingToInstantConnectionExtractor.scala @@ -0,0 +1,26 @@ +package model.rdf.sparql.rgml.extractor + +import scala.collection.JavaConversions._ +import model.rdf.extractor.QueryExecutionResultExtractor +import model.rdf.sparql.rgml.models.Connection +import model.rdf.sparql.rgml.query.{ThingsWithInstantQuery} +import org.apache.jena.query.QueryExecution + +class ThingToInstantConnectionExtractor extends QueryExecutionResultExtractor[ThingsWithInstantQuery, Seq[Connection]] { + + def extract(input: QueryExecution): Option[Seq[Connection]] = { + try { + val resList = input.execSelect().toList + Some(resList.map(e => new Connection( + e.getResource("thing").getURI, + e.getResource("connection").getURI, + e.getResource("instant").getURI + ))) + } + catch { + case e: org.apache.jena.sparql.engine.http.QueryExceptionHTTP => { + None + } + } + } +} diff --git a/src/app/model/rdf/sparql/rgml/extractor/ThingToIntervalConnectionExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/ThingToIntervalConnectionExtractor.scala new file mode 100644 index 00000000..b1251f36 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/extractor/ThingToIntervalConnectionExtractor.scala @@ -0,0 +1,26 @@ +package model.rdf.sparql.rgml.extractor + +import scala.collection.JavaConversions._ +import model.rdf.extractor.QueryExecutionResultExtractor +import model.rdf.sparql.rgml.models.Connection +import model.rdf.sparql.rgml.query.ThingsWithIntervalQuery +import org.apache.jena.query.QueryExecution + +class ThingToIntervalConnectionExtractor extends QueryExecutionResultExtractor[ThingsWithIntervalQuery, Seq[Connection]] { + + def extract(input: QueryExecution): Option[Seq[Connection]] = { + try { + val resList = input.execSelect().toList + Some(resList.map(e => new Connection( + e.getResource("thing").getURI, + e.getResource("connection").getURI, + e.getResource("interval").getURI + ))) + } + catch { + case e: org.apache.jena.sparql.engine.http.QueryExceptionHTTP => { + None + } + } + } +} diff --git a/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithInstantConnectionExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithInstantConnectionExtractor.scala new file mode 100644 index 00000000..19c26a00 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithInstantConnectionExtractor.scala @@ -0,0 +1,27 @@ +package model.rdf.sparql.rgml.extractor + +import scala.collection.JavaConversions._ +import model.rdf.extractor.QueryExecutionResultExtractor +import model.rdf.sparql.rgml.models.Connection +import model.rdf.sparql.rgml.query.ThingsWithThingsWithInstantQuery +import org.apache.jena.query.QueryExecution + +class ThingToThingWithInstantConnectionExtractor + extends QueryExecutionResultExtractor[ThingsWithThingsWithInstantQuery, Seq[Connection]] { + + def extract(input: QueryExecution): Option[Seq[Connection]] = { + try { + val resList = input.execSelect().toList + Some(resList.map(e => new Connection( + e.getResource("outerThing").getURI, + e.getResource("connection").getURI, + e.getResource("innerThing").getURI + ))) + } + catch { + case e: org.apache.jena.sparql.engine.http.QueryExceptionHTTP => { + None + } + } + } +} \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithIntervalConnectionExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithIntervalConnectionExtractor.scala new file mode 100644 index 00000000..539cf44f --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithIntervalConnectionExtractor.scala @@ -0,0 +1,27 @@ +package model.rdf.sparql.rgml.extractor + +import scala.collection.JavaConversions._ +import model.rdf.extractor.QueryExecutionResultExtractor +import model.rdf.sparql.rgml.models.Connection +import org.apache.jena.query.QueryExecution +import model.rdf.sparql.rgml.query.{ThingsWithThingsWithIntervalQuery} + +class ThingToThingWithIntervalConnectionExtractor + extends QueryExecutionResultExtractor[ThingsWithThingsWithIntervalQuery, Seq[Connection]] { + + def extract(input: QueryExecution): Option[Seq[Connection]] = { + try { + val resList = input.execSelect().toList + Some(resList.map(e => new Connection( + e.getResource("outerThing").getURI, + e.getResource("connection").getURI, + e.getResource("innerThing").getURI + ))) + } + catch { + case e: org.apache.jena.sparql.engine.http.QueryExceptionHTTP => { + None + } + } + } +} diff --git a/src/app/model/rdf/sparql/rgml/models/Connection.scala b/src/app/model/rdf/sparql/rgml/models/Connection.scala new file mode 100644 index 00000000..87677969 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/models/Connection.scala @@ -0,0 +1,3 @@ +package model.rdf.sparql.rgml.models + +case class Connection(outerUrl: String, connectionUrl: String, innerUrl: String) diff --git a/src/app/model/rdf/sparql/rgml/Edge.scala b/src/app/model/rdf/sparql/rgml/models/Edge.scala similarity index 67% rename from src/app/model/rdf/sparql/rgml/Edge.scala rename to src/app/model/rdf/sparql/rgml/models/Edge.scala index cd3b2a7f..819dfa3a 100644 --- a/src/app/model/rdf/sparql/rgml/Edge.scala +++ b/src/app/model/rdf/sparql/rgml/models/Edge.scala @@ -1,3 +1,3 @@ -package model.rdf.sparql.rgml +package model.rdf.sparql.rgml.models case class Edge(uri: String, source: String, target: String, weight: Double) diff --git a/src/app/model/rdf/sparql/rgml/EdgeDirection.scala b/src/app/model/rdf/sparql/rgml/models/EdgeDirection.scala similarity index 91% rename from src/app/model/rdf/sparql/rgml/EdgeDirection.scala rename to src/app/model/rdf/sparql/rgml/models/EdgeDirection.scala index 7f1852bf..e7cecac1 100644 --- a/src/app/model/rdf/sparql/rgml/EdgeDirection.scala +++ b/src/app/model/rdf/sparql/rgml/models/EdgeDirection.scala @@ -1,4 +1,5 @@ -package model.rdf.sparql.rgml +package model.rdf.sparql.rgml.models + import play.api.libs.json._ object EdgeDirection extends Enumeration { diff --git a/src/app/model/rdf/sparql/rgml/Graph.scala b/src/app/model/rdf/sparql/rgml/models/Graph.scala similarity index 65% rename from src/app/model/rdf/sparql/rgml/Graph.scala rename to src/app/model/rdf/sparql/rgml/models/Graph.scala index ab7db7ba..7291a89e 100644 --- a/src/app/model/rdf/sparql/rgml/Graph.scala +++ b/src/app/model/rdf/sparql/rgml/models/Graph.scala @@ -1,3 +1,3 @@ -package model.rdf.sparql.rgml +package model.rdf.sparql.rgml.models case class Graph(directed: Boolean, nodeCount: Int, edgeCount: Int) diff --git a/src/app/model/rdf/sparql/rgml/models/Instant.scala b/src/app/model/rdf/sparql/rgml/models/Instant.scala new file mode 100644 index 00000000..1d9e93fd --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/models/Instant.scala @@ -0,0 +1,4 @@ +package model.rdf.sparql.rgml.models +import java.util.Date + +case class Instant(url: String, date: Date) diff --git a/src/app/model/rdf/sparql/rgml/models/Interval.scala b/src/app/model/rdf/sparql/rgml/models/Interval.scala new file mode 100644 index 00000000..0a59665d --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/models/Interval.scala @@ -0,0 +1,4 @@ +package model.rdf.sparql.rgml.models +import java.util.Date + +case class Interval(url:String, start: Date, end:Date) diff --git a/src/app/model/rdf/sparql/rgml/Node.scala b/src/app/model/rdf/sparql/rgml/models/Node.scala similarity index 71% rename from src/app/model/rdf/sparql/rgml/Node.scala rename to src/app/model/rdf/sparql/rgml/models/Node.scala index 6653385c..eb00dad4 100644 --- a/src/app/model/rdf/sparql/rgml/Node.scala +++ b/src/app/model/rdf/sparql/rgml/models/Node.scala @@ -1,4 +1,4 @@ -package model.rdf.sparql.rgml +package model.rdf.sparql.rgml.models import model.rdf.LocalizedValue diff --git a/src/app/model/rdf/sparql/rgml/NodeWithDegree.scala b/src/app/model/rdf/sparql/rgml/models/NodeWithDegree.scala similarity index 78% rename from src/app/model/rdf/sparql/rgml/NodeWithDegree.scala rename to src/app/model/rdf/sparql/rgml/models/NodeWithDegree.scala index 60c05572..e038c8db 100644 --- a/src/app/model/rdf/sparql/rgml/NodeWithDegree.scala +++ b/src/app/model/rdf/sparql/rgml/models/NodeWithDegree.scala @@ -1,4 +1,4 @@ -package model.rdf.sparql.rgml +package model.rdf.sparql.rgml.models import model.rdf.LocalizedValue diff --git a/src/app/model/rdf/sparql/rgml/query/AdjacentNodesQuery.scala b/src/app/model/rdf/sparql/rgml/query/AdjacentNodesQuery.scala index fc5f0ded..212ec4c9 100644 --- a/src/app/model/rdf/sparql/rgml/query/AdjacentNodesQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/AdjacentNodesQuery.scala @@ -1,7 +1,7 @@ package model.rdf.sparql.rgml.query -import model.rdf.sparql.rgml.Graph -import model.rdf.sparql.rgml.EdgeDirection._ +import model.rdf.sparql.rgml.models.EdgeDirection._ +import model.rdf.sparql.rgml.models.Graph class AdjacentNodesQuery(nodeUri: String, direction: EdgeDirection = Outgoing) extends NodesQuery { diff --git a/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala deleted file mode 100644 index 870ad552..00000000 --- a/src/app/model/rdf/sparql/rgml/query/EventPeopleQuery.scala +++ /dev/null @@ -1,30 +0,0 @@ -package model.rdf.sparql.rgml.query -import model.rdf.sparql.query.SparqlQuery - -class EventPeopleQuery(event: String) extends SparqlQuery { - def get: String = { - """ - |PREFIX rdf: - |PREFIX sch: - |PREFIX dbo: - |PREFIX foaf: - |PREFIX xsd: - | - |PREFIX dbp: - |SELECT ?person (SAMPLE(?personName) AS ?name) (SAMPLE(?personDescription) AS ?description) (SAMPLE(?personLink) AS ?link) (SAMPLE(?personImage) AS ?image) - |WHERE { - | ?person rdf:type sch:Person ; - | foaf:name ?personName. - | - | OPTIONAL {?person foaf:isPrimaryTopicOf ?personLink} - | OPTIONAL {?person dbp:shortDescription ?personDescription} - | OPTIONAL {?person foaf:depiction ?personImage} - | - | <@event> ?relation ?person. - |} - |GROUP BY ?person - """ - .stripMargin - .replace("@event", event) - } -} \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/query/EventQuery.scala b/src/app/model/rdf/sparql/rgml/query/EventQuery.scala deleted file mode 100644 index 7d1c7879..00000000 --- a/src/app/model/rdf/sparql/rgml/query/EventQuery.scala +++ /dev/null @@ -1,39 +0,0 @@ -package model.rdf.sparql.rgml.query - -import java.util.Date -import java.text.SimpleDateFormat -import model.rdf.sparql.query.SparqlQuery - -class EventQuery(start: Date, end: Date, limit: Int) extends SparqlQuery{ - val dateFormat = new SimpleDateFormat("YYYY-MM-DD") - def get: String = - """ - |PREFIX rdf: - |PREFIX sch: - |PREFIX dbo: - |PREFIX foaf: - |PREFIX xsd: - | - |SELECT ?event (SAMPLE(?eventName) AS ?name) (SAMPLE(?eventDate) AS ?date) (SAMPLE(?eventLink) AS ?link) - |WHERE { - | ?event rdf:type sch:Event ; - | foaf:name ?eventName ; - | dbo:date ?eventDate ; - | dbo:wikiPageExternalLink ?eventLink . - | - | FILTER (?eventDate > "@start"^^xsd:date) - | FILTER (?eventDate < "@end"^^xsd:date) - | - | FILTER EXISTS { - | ?person rdf:type sch:Person. - | ?event ?relation ?person. - | } - |} - |GROUP BY ?event - |LIMIT @limit - """ - .replace("@start",dateFormat.format(start)) - .replace("@end",dateFormat.format(end)) - .replace("@limit", limit.toString) - .stripMargin -} diff --git a/src/app/model/rdf/sparql/rgml/query/IncidentEdgesQuery.scala b/src/app/model/rdf/sparql/rgml/query/IncidentEdgesQuery.scala index b4b05448..a163e903 100644 --- a/src/app/model/rdf/sparql/rgml/query/IncidentEdgesQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/IncidentEdgesQuery.scala @@ -1,6 +1,6 @@ package model.rdf.sparql.rgml.query -import model.rdf.sparql.rgml.EdgeDirection._ +import model.rdf.sparql.rgml.models.EdgeDirection._ class IncidentEdgesQuery(nodeUri: String, direction: EdgeDirection) extends EdgesQuery { diff --git a/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala new file mode 100644 index 00000000..3d1c918e --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala @@ -0,0 +1,60 @@ +package model.rdf.sparql.rgml.query + +import java.util.Date +import java.text.SimpleDateFormat + +import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} + +class InstantQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInstantUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { + def get: String = { + val select = "SELECT ?instant ?date" + val group = "GROUP BY ?instant ?date" + val limit = QueryHelpers.limit(maybeLimit) + return query(select,group,limit) + } + + def getCount: String = { + val select = "COUNT(?instant) AS ?count" + val group = "" + val limit = "" + return query(select, group, limit) + } + + private def query(select: String, group: String, limit: String) : String = + s""" + |PREFIX time: + |PREFIX xsd: + | + |${select} + |WHERE { + | ?instant time:inXSDDateTime ?date. + | + | ${startFilter} + | ${endFilter} + | + | ${QueryHelpers.limitValues("instant",maybeInstantUrls)} + |} + | + |${group} + |${limit} + """ + .stripMargin + + private def startFilter: String = { + maybeStart match { + case Some(start) => { + return s"""FILTER (xsd:dateTime(?date) > xsd:dateTime("${QueryHelpers.dateToString(start)}"))""" + } + case None => "" + } + } + + private def endFilter: String = { + maybeEnd match { + case Some(end) => { + return s"""FILTER (xsd:dateTime(?date) < xsd:dateTime("${QueryHelpers.dateToString(end)}"))""" + } + case None => "" + } + } +} \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala new file mode 100644 index 00000000..0231a41d --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala @@ -0,0 +1,66 @@ +package model.rdf.sparql.rgml.query + +import java.util.Date +import java.text.SimpleDateFormat + +import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} + +class IntervalQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeIntervalUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { + def get: String = { + val select = "SELECT ?interval ?start ?end" + val group = "GROUP BY ?interval ?start ?end" + val limit = QueryHelpers.limit(maybeLimit) + return query(select,group,limit) + } + + def getCount: String = { + val select = "COUNT(?interval) AS ?count" + val group = "" + val limit = "" + return query(select, group, limit) + } + + private def query(select:String, group:String, limit: String) : String = + s""" + |PREFIX time: + |PREFIX xsd: + | + |${select} + |WHERE { + | ?interval time:hasBeginning ?beginning . + | ?interval time:hasEnd ?end . + | + | ${startFilter} + | ${endFilter} + | + | ${QueryHelpers.limitValues("interval",maybeIntervalUrls)} + |} + | + |${group} + |${limit} + """ + .stripMargin + + + private def startFilter: String = { + val dateFormat = new SimpleDateFormat("YYYY-MM-DD") + maybeStart match { + case Some(start) => { + val startString = dateFormat.format(start) + return s"""FILTER (xsd:dateTime(?begin) > xsd:dateTime("$startString"))""" + } + case None => "" + } + } + + private def endFilter: String = { + val dateFormat = new SimpleDateFormat("YYYY-MM-DD") + maybeEnd match { + case Some(end) => { + val endString = dateFormat.format(end) + return s"""FILTER (xsd:dateTime(?end) < xsd:dateTime("$endString"))""" + } + case None => "" + } + } +} \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala b/src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala new file mode 100644 index 00000000..7118fca1 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala @@ -0,0 +1,41 @@ +package model.rdf.sparql.rgml.query + +import java.text.SimpleDateFormat +import java.util.Date + +object QueryHelpers { + def limitValues(fieldName: String,maybeUrlList: Option[Seq[String]]) : String = { + maybeUrlList match { + case Some(list) => { + val urls = list.map(url => "<" + url + ">").mkString(" ") + return s"VALUES ?$fieldName {$urls}" + } + case None => "" + } + } + + def limit(maybeLimit: Option[Integer]) : String = { + maybeLimit match { + case Some(value) => s"LIMIT $value" + case None => "" + } + } + + def select(variables: Seq[String]) : String = { + val variableList = variables.map(v => "?" + v ).mkString(" ") + return s"SELECT ${variableList}" + } + + def group(variables: Seq[String]) : String = { + val variableList = variables.map(v => "?" + v ).mkString(" ") + return s"GROUP BY ${variableList}" + } + + def count(variable: String) : String = { + return s"SELECT COUNT(?${variable}) AS ?count" + } + + def dateToString(date: Date): String = { + new SimpleDateFormat("YYYY-MM-DD" ).format(date) + } +} diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala new file mode 100644 index 00000000..231548f7 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala @@ -0,0 +1,38 @@ +package model.rdf.sparql.rgml.query + +import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} + +class ThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { + def get: String = { + val select = "SELECT ?thing ?connection ?instant" + val group = "GROUP BY ?thing ?connection ?instant" + val limit = QueryHelpers.limit(maybeLimit) + return query(select,group,limit) + } + + def getCount: String = { + val select = "COUNT(?thing) AS ?count" + val group = "" + val limit = "" + return query(select,group,limit) + } + + private def query(select: String, group: String, limit: String) : String = + s""" + |PREFIX time: + | + |${select} + |WHERE { + | ?thing ?connection ?instant. + | + | ?instant time:inXSDDateTime ?date. + | + | ${QueryHelpers.limitValues("thing", maybeThingsUrls)} + | ${QueryHelpers.limitValues("connection", maybeConnectionUrls)} + |} + | + |${group} + |${limit} + """ + .stripMargin +} \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala new file mode 100644 index 00000000..cd87bf71 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala @@ -0,0 +1,39 @@ +package model.rdf.sparql.rgml.query + +import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} + +class ThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { + def get: String = { + val select = "SELECT ?thing ?connection ?interval" + val group = "GROUP BY ?thing ?connection ?interval" + val limit = QueryHelpers.limit(maybeLimit) + return query(select,group,limit) + } + + def getCount: String = { + val select = "COUNT(?thing) AS ?count" + val group = "" + val limit = "" + return query(select,group,limit) + } + + private def query(select: String, group: String, limit: String) : String = + s""" + |PREFIX time: + | + |${select} + |WHERE { + | ?thing ?connection ?interval. + | + | ?interval time:hasBeginning ?beginning . + | ?interval time:hasEnd ?end . + | + | ${QueryHelpers.limitValues("thing", maybeThingsUrls)} + | ${QueryHelpers.limitValues("connection", maybeConnectionUrls)} + |} + | + |${group} + |${limit} + """ + .stripMargin +} diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala new file mode 100644 index 00000000..64e68773 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala @@ -0,0 +1,41 @@ +package model.rdf.sparql.rgml.query + +import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} + +class ThingsWithThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { + + def get: String = { + val select = "SELECT ?outerThing ?connection ?innerThing" + val group = "GROUP BY ?outerThing ?connection ?innerThing" + val limit = QueryHelpers.limit(maybeLimit) + return query(select,group,limit) + } + + def getCount: String = { + val select = "COUNT(?thing) AS ?count" + val group = "" + val limit = "" + return query(select,group,limit) + } + + private def query(select:String, group:String, limit: String) : String = + s""" + |PREFIX time: + | + |${select} + |WHERE { + | ?outerThing ?connection ?innerThing. + | + | ?innerThing ?hasInterval ?instant. + | + | ?instant time:inXSDDateTime ?date. + | + | ${QueryHelpers.limitValues("outerThing", maybeThingsUrls)} + | ${QueryHelpers.limitValues("connection", maybeConnectionUrls)} + |} + | + |${group} + |${limit} + """ + .stripMargin +} \ No newline at end of file diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala new file mode 100644 index 00000000..dda2b3a1 --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala @@ -0,0 +1,41 @@ +package model.rdf.sparql.rgml.query + +import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} + +class ThingsWithThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { + def get: String = { + val select = "SELECT ?outerThing ?connection ?innerThing" + val group = "GROUP BY ?outerThing ?connection ?innerThing" + val limit = QueryHelpers.limit(maybeLimit) + return query(select,group,limit) + } + + def getCount: String = { + val select = "SELECT COUNT(?outerThing) AS ?count" + val group = "" + val limit = "" + return query(select,group,limit) + } + + private def query(select:String, group:String, limit: String) : String = + s""" + |PREFIX time: + | + |${select} + |WHERE { + | ?outerThing ?connection ?innerThing. + | + | ?innerThing ?hasInterval ?interval. + | + | ?interval time:hasBeginning ?beginning . + | ?interval time:hasEnd ?end . + | + | ${QueryHelpers.limitValues("outerThing",maybeThingsUrls)} + | ${QueryHelpers.limitValues("connection",maybeConnectionUrls)} + |} + | + |${group} + |${limit} + """ + .stripMargin +} From 9b564562cbba57413f83baea6365779cc6fa1917 Mon Sep 17 00:00:00 2001 From: vvancak Date: Mon, 1 May 2017 17:04:28 +0200 Subject: [PATCH 24/84] TimeLine: Service API --- src/app/controllers/ControllerModule.scala | 4 +- src/app/controllers/api/package.scala | 12 ++- .../EventVisualizerApiController.scala | 30 ------ .../TimeLineVisualizerApiController.scala | 100 ++++++++++++++++++ .../assistant/rest/ConnectionRequest.scala | 9 ++ .../model/assistant/rest/EventRequest.scala | 10 -- .../assistant/rest/UrlsStartEndRequest.scala | 10 ++ src/app/model/rdf/Count.scala | 3 + .../model/rdf/extractor/CountExtractor.scala | 7 +- .../rdf/sparql/SparqlEndpointService.scala | 5 +- .../sparql/SparqlEndpointServiceImpl.scala | 3 +- .../rdf/sparql/query/SparqlCountQuery.scala | 2 +- .../rdf/sparql/rgml/RgmlCountService.scala | 15 +++ .../sparql/rgml/RgmlCountServiceImpl.scala | 72 +++++++++++++ .../model/rdf/sparql/rgml/RgmlService.scala | 12 ++- .../rdf/sparql/rgml/RgmlServiceImpl.scala | 72 ++++++++++--- .../rdf/sparql/rgml/query/InstantQuery.scala | 6 +- .../rdf/sparql/rgml/query/IntervalQuery.scala | 14 +-- .../rdf/sparql/rgml/query/QueryHelpers.scala | 2 +- .../rgml/query/ThingsWithInstantQuery.scala | 4 +- .../rgml/query/ThingsWithIntervalQuery.scala | 4 +- .../ThingsWithThingsWithInstantQuery.scala | 4 +- .../ThingsWithThingsWithIntervalQuery.scala | 4 +- src/conf/routes | 21 +++- 24 files changed, 329 insertions(+), 96 deletions(-) delete mode 100644 src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala create mode 100644 src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala create mode 100644 src/app/model/assistant/rest/ConnectionRequest.scala delete mode 100644 src/app/model/assistant/rest/EventRequest.scala create mode 100644 src/app/model/assistant/rest/UrlsStartEndRequest.scala create mode 100644 src/app/model/rdf/Count.scala create mode 100644 src/app/model/rdf/sparql/rgml/RgmlCountService.scala create mode 100644 src/app/model/rdf/sparql/rgml/RgmlCountServiceImpl.scala diff --git a/src/app/controllers/ControllerModule.scala b/src/app/controllers/ControllerModule.scala index ae8b70a0..2c8dc76e 100644 --- a/src/app/controllers/ControllerModule.scala +++ b/src/app/controllers/ControllerModule.scala @@ -1,7 +1,7 @@ package controllers import controllers.assistant.api._ -import controllers.assistant.api.visualizers.{ChordVisualizerApiController, CommonVisualizerApiController, MapsVisualizerApiController, EventVisualizerApiController} +import controllers.assistant.api.visualizers.{ChordVisualizerApiController, CommonVisualizerApiController, MapsVisualizerApiController, TimeLineVisualizerApiController} import controllers.util.AngularController import scaldi.Module @@ -22,7 +22,7 @@ class ControllerModule extends Module { binding to new CommonApiController binding to new MapsVisualizerApiController binding to new ChordVisualizerApiController - binding to new EventVisualizerApiController + binding to new TimeLineVisualizerApiController binding to new CommonVisualizerApiController binding to new DashboardApiController binding to new CatalogApiController diff --git a/src/app/controllers/api/package.scala b/src/app/controllers/api/package.scala index 6634d021..6a912675 100644 --- a/src/app/controllers/api/package.scala +++ b/src/app/controllers/api/package.scala @@ -4,13 +4,12 @@ import akka.actor.Props import model.actor.CheckCompatibilityResponse import model.entity._ import model.rdf.sparql.ValueFilter -import model.rdf.sparql.rgml._ import model.rdf.sparql.datacube._ import model.rdf.sparql.fresnel.{Lens, ResourceThroughLens} import model.rdf.sparql.geo._ -import model.rdf.sparql.rgml.models.{Edge, Graph, Node, NodeWithDegree} +import model.rdf.sparql.rgml.models._ import model.rdf.sparql.visualization.{Concept, HierarchyNode, Scheme} -import model.rdf.{LocalizedValue, Property} +import model.rdf.{Count, LocalizedValue, Property} import model.service.component.DataReference import play.api.db import play.api.db.slick._ @@ -107,8 +106,11 @@ package object api { implicit val edgeWrites = Json.writes[Edge] implicit val lensWrites = Json.writes[Lens] implicit val resourceThroughLensWrites = Json.writes[ResourceThroughLens] - implicit val eventWrites = Json.writes[Event] - implicit val personWrites = Json.writes[Person] + + implicit val countWrites = Json.writes[Count] + implicit val intervalWrites = Json.writes[Interval] + implicit val instantWrites = Json.writes[Instant] + implicit val connectonWrites = Json.writes[Connection] val filterPath = (JsPath \ "label").readNullable[String] and (JsPath \ "dataType").readNullable[String] and diff --git a/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala deleted file mode 100644 index ba333fcb..00000000 --- a/src/app/controllers/assistant/api/visualizers/EventVisualizerApiController.scala +++ /dev/null @@ -1,30 +0,0 @@ -package controllers.assistant.api.visualizers - -import scala.concurrent.Future -import model.assistant.entity.ApplicationId -import model.assistant.rest.Response._ -import model.rdf.sparql.rgml.RgmlService -import controllers.api.JsonImplicits._ -import model.assistant.rest.EventRequest.EventRequest -import model.assistant.rest.EventPeopleRequest.EventPeopleRequest -import play.api.libs.concurrent.Execution.Implicits._ -import scaldi.Injector - -class EventVisualizerApiController(implicit inj: Injector) extends VisualizerApiController { - val rgmlService = inject[RgmlService] - - def getEvents(id: Long) = RestAsyncAction[EventRequest] { implicit request => json => - withEvaluation(ApplicationId(id)) { evaluation => - val events = rgmlService.events(evaluation, json.start, json.end, json.limit) - Future(Ok(SuccessResponse(data = Seq("events" -> events)))) - } - } - def getEventPeople(id: Long) = RestAsyncAction[EventPeopleRequest] { implicit request => json => - cached { - withEvaluation(ApplicationId(id)) { evaluation => - var people = rgmlService.eventPeople(evaluation, json.event) - Future(Ok(SuccessResponse(data = Seq("people" -> people)))) - } - } - } -} \ No newline at end of file diff --git a/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala new file mode 100644 index 00000000..1c6b4dd2 --- /dev/null +++ b/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala @@ -0,0 +1,100 @@ +package controllers.assistant.api.visualizers + +import controllers.api.JsonImplicits._ +import play.api.libs.concurrent.Execution.Implicits._ +import model.assistant.entity.ApplicationId +import model.assistant.rest.Response._ +import model.assistant.rest.ThingsConnectionRequest.ThingsConnectionsRequest +import model.assistant.rest.UrlsStartEndRequest.UrlsStartEndRequest +import model.rdf.sparql.rgml.{RgmlCountService, RgmlService} +import scaldi.Injector +import scala.concurrent.Future + +class TimeLineVisualizerApiController(implicit inj: Injector) extends VisualizerApiController { + val rgmlService = inject[RgmlService] + val rgmlCountService = inject[RgmlCountService] + + def getIntervals(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => + withEvaluation(ApplicationId(id)) { evaluation => + val intervals = rgmlService.intervals(evaluation, json.start, json.end, json.urls, json.limit) + Future(Ok(SuccessResponse(data = Seq("intervals" -> intervals)))) + } + } + + def getIntervalsCount(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => + withEvaluation(ApplicationId(id)) { evaluation => + val count = rgmlCountService.intervals(evaluation, json.start, json.end, json.urls, json.limit) + Future(Ok(SuccessResponse(data = Seq("count" -> count)))) + } + } + + def getInstants(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => + withEvaluation(ApplicationId(id)) { evaluation => + val instants = rgmlService.instants(evaluation, json.start, json.end, json.urls, json.limit) + Future(Ok(SuccessResponse(data = Seq("instants" -> instants)))) + } + } + + def getInstantsCount(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => + withEvaluation(ApplicationId(id)) { evaluation => + val count = rgmlCountService.instants(evaluation, json.start, json.end, json.urls, json.limit) + Future(Ok(SuccessResponse(data = Seq("count" -> count)))) + } + } + + def getThingWithIntervals(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request =>json => + withEvaluation(ApplicationId(id)) { evaluation => + val thingsWithIntervals = rgmlService.thingsWithIntervals(evaluation, json.things, json.connections, json.limit) + Future(Ok(SuccessResponse(data = Seq("thingsWithIntervals" -> thingsWithIntervals)))) + } + } + + def getThingsWithIntervalsCount(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request => json => + withEvaluation(ApplicationId(id)) { evaluation => + val count = rgmlCountService.thingsWithIntervals(evaluation, json.things, json.connections, json.limit) + Future(Ok(SuccessResponse(data = Seq("count" -> count)))) + } + } + + def getThingsWithInstants(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request =>json => + withEvaluation(ApplicationId(id)) { evaluation => + val thingsWithInstants = rgmlService.thingsWithInstants(evaluation, json.things, json.connections, json.limit) + Future(Ok(SuccessResponse(data = Seq("thingsWithInstants" -> thingsWithInstants)))) + } + } + + def getThingsWithInstantsCount(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request => json => + withEvaluation(ApplicationId(id)) { evaluation => + val count = rgmlCountService.thingsWithInstants(evaluation, json.things, json.connections, json.limit) + Future(Ok(SuccessResponse(data = Seq("count" -> count)))) + } + } + + def getThingsWithThingsWithIntervals(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request =>json => + withEvaluation(ApplicationId(id)) { evaluation => + val thingsWithThingsWithIntervals = rgmlService.thingsWithThingsWithIntervals(evaluation, json.things, json.connections, json.limit) + Future(Ok(SuccessResponse(data = Seq("thingsWithThingsWithIntervals" -> thingsWithThingsWithIntervals)))) + } + } + + def getThingsWithThingsWithIntervalsCount(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request => json => + withEvaluation(ApplicationId(id)) { evaluation => + val count = rgmlCountService.thingsWithThingsWithIntervals(evaluation, json.things, json.connections, json.limit) + Future(Ok(SuccessResponse(data = Seq("count" -> count)))) + } + } + + def getThingsWithThingsWithInstants(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request =>json => + withEvaluation(ApplicationId(id)) { evaluation => + val thingsWithThingsWithInstants = rgmlService.thingsWithThingsWithInstants(evaluation, json.things, json.connections, json.limit) + Future(Ok(SuccessResponse(data = Seq("thingsWithThingsWithInstants" -> thingsWithThingsWithInstants)))) + } + } + + def getThingsWithThingsWithInstantsCount(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request => json => + withEvaluation(ApplicationId(id)) { evaluation => + val count = rgmlCountService.thingsWithThingsWithInstants(evaluation, json.things, json.connections, json.limit) + Future(Ok(SuccessResponse(data = Seq("count" -> count)))) + } + } +} \ No newline at end of file diff --git a/src/app/model/assistant/rest/ConnectionRequest.scala b/src/app/model/assistant/rest/ConnectionRequest.scala new file mode 100644 index 00000000..6e08e5a2 --- /dev/null +++ b/src/app/model/assistant/rest/ConnectionRequest.scala @@ -0,0 +1,9 @@ +package model.assistant.rest + +import play.api.libs.json.Json + +object ThingsConnectionRequest { + case class ThingsConnectionsRequest(things: Seq[String], connections: Seq[String], limit: Int) + implicit val writes = Json.writes[ThingsConnectionsRequest] + implicit val reads = Json.reads[ThingsConnectionsRequest] +} diff --git a/src/app/model/assistant/rest/EventRequest.scala b/src/app/model/assistant/rest/EventRequest.scala deleted file mode 100644 index 6a9403f2..00000000 --- a/src/app/model/assistant/rest/EventRequest.scala +++ /dev/null @@ -1,10 +0,0 @@ -package model.assistant.rest - -import java.util.Date -import play.api.libs.json.Json - -object EventRequest { - case class EventRequest(start: Date, end: Date, limit: Int) - implicit val writes = Json.writes[EventRequest] - implicit val reads = Json.reads[EventRequest] -} diff --git a/src/app/model/assistant/rest/UrlsStartEndRequest.scala b/src/app/model/assistant/rest/UrlsStartEndRequest.scala new file mode 100644 index 00000000..34b6bea0 --- /dev/null +++ b/src/app/model/assistant/rest/UrlsStartEndRequest.scala @@ -0,0 +1,10 @@ +package model.assistant.rest + +import java.util.Date +import play.api.libs.json.Json + +object UrlsStartEndRequest { + case class UrlsStartEndRequest(urls: Seq[String], start: Date, end: Date, limit: Int) + implicit val writes = Json.writes[UrlsStartEndRequest] + implicit val reads = Json.reads[UrlsStartEndRequest] +} diff --git a/src/app/model/rdf/Count.scala b/src/app/model/rdf/Count.scala new file mode 100644 index 00000000..c53082f2 --- /dev/null +++ b/src/app/model/rdf/Count.scala @@ -0,0 +1,3 @@ +package model.rdf + +case class Count(value: Int) diff --git a/src/app/model/rdf/extractor/CountExtractor.scala b/src/app/model/rdf/extractor/CountExtractor.scala index 04b53476..e1d7b6cd 100644 --- a/src/app/model/rdf/extractor/CountExtractor.scala +++ b/src/app/model/rdf/extractor/CountExtractor.scala @@ -1,16 +1,17 @@ package model.rdf.sparql.extractor +import model.rdf.Count import model.rdf.extractor.QueryExecutionResultExtractor import model.rdf.sparql.query.SparqlCountQuery import org.apache.jena.query.QueryExecution -class CountExtractor extends QueryExecutionResultExtractor[SparqlCountQuery, Integer] { +class CountExtractor extends QueryExecutionResultExtractor[SparqlCountQuery, Count] { - def extract(input: QueryExecution): Option[Integer] = { + def extract(input: QueryExecution): Option[Count] = { try { val resultSet = input.execSelect() if (resultSet.hasNext()) { - Some(resultSet.next().getLiteral("count").getInt()) + Some(new Count(resultSet.next().getLiteral("count").getInt())) } else None } diff --git a/src/app/model/rdf/sparql/SparqlEndpointService.scala b/src/app/model/rdf/sparql/SparqlEndpointService.scala index 61a47d70..11579c7a 100644 --- a/src/app/model/rdf/sparql/SparqlEndpointService.scala +++ b/src/app/model/rdf/sparql/SparqlEndpointService.scala @@ -1,13 +1,14 @@ package model.rdf.sparql import _root_.model.rdf.extractor.QueryExecutionResultExtractor -import _root_.model.rdf.sparql.query.{SparqlQuery, SparqlCountQuery} +import _root_.model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} +import _root_.model.rdf.Count trait SparqlEndpointService { def getResult[Q <: SparqlQuery, R](sparqlEndpoint: SparqlEndpoint, query: Q, extractor: QueryExecutionResultExtractor[Q, R]): Option[R] - def getCount[Q<: SparqlCountQuery](sparqlEndpoint: SparqlEndpoint, query: Q, extractor: QueryExecutionResultExtractor[Q,Integer]): Option[Integer] + def getCount[Q<: SparqlCountQuery](sparqlEndpoint: SparqlEndpoint, query: Q, extractor: QueryExecutionResultExtractor[Q,Count]): Option[Count] def dereference[Q <: SparqlQuery, R](uri: String, query: Q, extractor: QueryExecutionResultExtractor[Q, R]): Option[R] } diff --git a/src/app/model/rdf/sparql/SparqlEndpointServiceImpl.scala b/src/app/model/rdf/sparql/SparqlEndpointServiceImpl.scala index 99402949..05ef327c 100644 --- a/src/app/model/rdf/sparql/SparqlEndpointServiceImpl.scala +++ b/src/app/model/rdf/sparql/SparqlEndpointServiceImpl.scala @@ -2,6 +2,7 @@ package model.rdf.sparql import _root_.model.rdf.Graph import _root_.model.rdf.extractor.QueryExecutionResultExtractor +import _root_.model.rdf.Count import _root_.model.rdf.sparql.query.{SparqlQuery, SparqlCountQuery} import org.apache.jena.query.{QueryExecution, QueryExecutionFactory} import org.apache.jena.sparql.engine.http.QueryExceptionHTTP @@ -19,7 +20,7 @@ class SparqlEndpointServiceImpl(implicit inj: Injector) extends SparqlEndpointSe } } - def getCount[Q<: SparqlCountQuery](sparqlEndpoint: SparqlEndpoint, query: Q, extractor: QueryExecutionResultExtractor[Q,Integer]): Option[Integer] = { + def getCount[Q<: SparqlCountQuery](sparqlEndpoint: SparqlEndpoint, query: Q, extractor: QueryExecutionResultExtractor[Q,Count]): Option[Count] = { try { extractor.extract(count(sparqlEndpoint,query)) } diff --git a/src/app/model/rdf/sparql/query/SparqlCountQuery.scala b/src/app/model/rdf/sparql/query/SparqlCountQuery.scala index 80543f3f..4bc9557b 100644 --- a/src/app/model/rdf/sparql/query/SparqlCountQuery.scala +++ b/src/app/model/rdf/sparql/query/SparqlCountQuery.scala @@ -1,5 +1,5 @@ package model.rdf.sparql.query -trait SparqlCountQuery { +trait SparqlCountQuery extends SparqlQuery{ def getCount : String } diff --git a/src/app/model/rdf/sparql/rgml/RgmlCountService.scala b/src/app/model/rdf/sparql/rgml/RgmlCountService.scala new file mode 100644 index 00000000..32f7fcfe --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/RgmlCountService.scala @@ -0,0 +1,15 @@ +package model.rdf.sparql.rgml + +import java.util.Date +import model.entity.PipelineEvaluation +import model.rdf.Count +import play.api.db.slick.Session + +trait RgmlCountService { + def intervals(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Count] + def instants(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Count] + def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] + def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] + def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] + def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] +} diff --git a/src/app/model/rdf/sparql/rgml/RgmlCountServiceImpl.scala b/src/app/model/rdf/sparql/rgml/RgmlCountServiceImpl.scala new file mode 100644 index 00000000..c2891efe --- /dev/null +++ b/src/app/model/rdf/sparql/rgml/RgmlCountServiceImpl.scala @@ -0,0 +1,72 @@ +package model.rdf.sparql.rgml + +import java.util.Date +import model.entity.PipelineEvaluation +import model.rdf.Count +import model.rdf.sparql.extractor.CountExtractor +import model.rdf.sparql.{EvaluationToSparqlEndpoint, SparqlEndpointService} +import model.rdf.sparql.rgml.query._ +import play.api.db.slick.Session +import scaldi.{Injectable, Injector} + +class RgmlCountServiceImpl(implicit val inj: Injector) extends RgmlCountService with Injectable with EvaluationToSparqlEndpoint { + var sparqlEndpointService = inject[SparqlEndpointService] + + override def intervals(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeUrl = if (urls.nonEmpty) Some(urls) else None + sparqlEndpointService.getCount( + evaluationToSparqlEndpoint(evaluation), + new IntervalQuery(Some(start),Some(end),maybeUrl,maybeLimit), + new CountExtractor()) + } + + override def instants(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeUrl = if (urls.nonEmpty) Some(urls) else None + sparqlEndpointService.getCount( + evaluationToSparqlEndpoint(evaluation), + new InstantQuery(Some(start),Some(end),maybeUrl,maybeLimit), + new CountExtractor()) + } + + override def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeThingUrls = if (thingUrls.nonEmpty) Some(thingUrls) else None + val maybeConnUrls = if (connectionUrls.nonEmpty) Some(connectionUrls) else None + sparqlEndpointService.getCount( + evaluationToSparqlEndpoint(evaluation), + new ThingsWithIntervalQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new CountExtractor()) + } + + override def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeThingUrls = if (thingUrls.nonEmpty) Some(thingUrls) else None + val maybeConnUrls = if (connectionUrls.nonEmpty) Some(connectionUrls) else None + sparqlEndpointService.getCount( + evaluationToSparqlEndpoint(evaluation), + new ThingsWithInstantQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new CountExtractor()) + } + + override def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeThingUrls = if (thingUrls.nonEmpty) Some(thingUrls) else None + val maybeConnUrls = if (connectionUrls.nonEmpty) Some(connectionUrls) else None + sparqlEndpointService.getCount( + evaluationToSparqlEndpoint(evaluation), + new ThingsWithThingsWithIntervalQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new CountExtractor()) + } + + override def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeThingUrls = if (thingUrls.nonEmpty) Some(thingUrls) else None + val maybeConnUrls = if (connectionUrls.nonEmpty) Some(connectionUrls) else None + sparqlEndpointService.getCount( + evaluationToSparqlEndpoint(evaluation), + new ThingsWithThingsWithInstantQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new CountExtractor()) + } +} diff --git a/src/app/model/rdf/sparql/rgml/RgmlService.scala b/src/app/model/rdf/sparql/rgml/RgmlService.scala index df36b591..427d4032 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlService.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlService.scala @@ -1,9 +1,11 @@ package model.rdf.sparql.rgml import java.util.Date + import model.entity.PipelineEvaluation import play.api.db.slick.Session -import model.rdf.sparql.rgml.EdgeDirection._ +import model.rdf.sparql.rgml.models._ +import model.rdf.sparql.rgml.models.EdgeDirection._ trait RgmlService { def graph(evaluation: PipelineEvaluation)(implicit session: Session): Option[Graph] @@ -17,6 +19,10 @@ trait RgmlService { def adjacentNodes(evaluation: PipelineEvaluation, nodeUri: String, direction: Option[EdgeDirection] = None)(implicit session: Session): Option[Seq[Node]] def sampleNodesByHighestDegree(evaluation: PipelineEvaluation, size: Int)(implicit session: Session): Option[Seq[Node]] def sampleNodesWithForestFire( evaluation: PipelineEvaluation, size: Int, useWeights: Boolean = true, pF: Double = 0.2, pB: Double = 0.05)(implicit session: Session): Option[Seq[Node]] - def events(evaluation: PipelineEvaluation, start: Date, end: Date, limit: Int)(implicit session: Session): Option[Seq[Event]] - def eventPeople(evaluation: PipelineEvaluation, event: String)(implicit session: Session) : Option[Seq[Person]] + def intervals(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Interval]] + def instants(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Instant]] + def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] + def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] + def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] + def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] } diff --git a/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala b/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala index 7d82b015..834660a9 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala @@ -1,13 +1,15 @@ package model.rdf.sparql.rgml import java.util.Date + import model.entity.PipelineEvaluation import model.rdf.sparql.rgml.extractor._ import model.rdf.sparql.rgml.query._ import model.rdf.sparql.{EvaluationToSparqlEndpoint, GenericSparqlEndpoint, SparqlEndpointService} import play.api.db.slick.Session import scaldi.{Injectable, Injector} -import model.rdf.sparql.rgml.EdgeDirection._ +import model.rdf.sparql.rgml.models.EdgeDirection._ +import model.rdf.sparql.rgml.models.{EdgeDirection => _, _} import scala.collection.mutable @@ -308,11 +310,11 @@ class RgmlServiceImpl(implicit val inj: Injector) extends RgmlService with Injec * @param pB probability that the "fire" will spread over an incoming edge */ override def sampleNodesWithForestFire( - evaluation: PipelineEvaluation, - size: Int, - useWeights: Boolean = true, - pF: Double = 0.2, - pB: Double = 0.05)(implicit session: Session): + evaluation: PipelineEvaluation, + size: Int, + useWeights: Boolean = true, + pF: Double = 0.2, + pB: Double = 0.05)(implicit session: Session): Option[Seq[Node]] = { val random = scala.util.Random @@ -365,7 +367,7 @@ class RgmlServiceImpl(implicit val inj: Injector) extends RgmlService with Injec .filterNot(sample.contains) .distinct .take(size - sample.size) // To make sure that we don't collect more nodes than we need. - + if (nextFrontier.isEmpty) sample else @@ -412,17 +414,61 @@ class RgmlServiceImpl(implicit val inj: Injector) extends RgmlService with Injec nodes(evaluation, makeSample) } - def events(evaluation: PipelineEvaluation, start: Date, end: Date, limit: Int)(implicit session: Session): Option[Seq[Event]] = { + override def intervals(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Interval]] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeUrl = if (urls.size > 0) Some(urls) else None + sparqlEndpointService.getResult( + evaluationToSparqlEndpoint(evaluation), + new IntervalQuery(Some(start),Some(end),maybeUrl,maybeLimit), + new IntervalExtractor()) + } + + override def instants(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Instant]] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeUrl = if (urls.size > 0) Some(urls) else None + sparqlEndpointService.getResult( + evaluationToSparqlEndpoint(evaluation), + new InstantQuery(Some(start),Some(end),maybeUrl,maybeLimit), + new InstantExtractor()) + } + + override def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeThingUrls = if (thingUrls.size > 0) Some(thingUrls) else None + val maybeConnUrls = if (connectionUrls.size > 0) Some(connectionUrls) else None + sparqlEndpointService.getResult( + evaluationToSparqlEndpoint(evaluation), + new ThingsWithIntervalQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingToIntervalConnectionExtractor()) + } + + override def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeThingUrls = if (thingUrls.size > 0) Some(thingUrls) else None + val maybeConnUrls = if (connectionUrls.size > 0) Some(connectionUrls) else None + sparqlEndpointService.getResult( + evaluationToSparqlEndpoint(evaluation), + new ThingsWithInstantQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingToInstantConnectionExtractor()) + } + + override def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeThingUrls = if (thingUrls.size > 0) Some(thingUrls) else None + val maybeConnUrls = if (connectionUrls.size > 0) Some(connectionUrls) else None sparqlEndpointService.getResult( evaluationToSparqlEndpoint(evaluation), - new EventQuery(start,end,limit), - new EventExtractor()) + new ThingsWithThingsWithIntervalQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingToThingWithIntervalConnectionExtractor()) } - def eventPeople(evaluation: PipelineEvaluation, event: String)(implicit session: Session): Option[Seq[Person]] = { + override def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { + val maybeLimit = if (limit > 0) Some(limit) else None + val maybeThingUrls = if (thingUrls.size > 0) Some(thingUrls) else None + val maybeConnUrls = if (connectionUrls.size > 0) Some(connectionUrls) else None sparqlEndpointService.getResult( evaluationToSparqlEndpoint(evaluation), - new EventPeopleQuery(event), - new PeopleExtractor()) + new ThingsWithThingsWithInstantQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingToThingWithInstantConnectionExtractor()) } } diff --git a/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala index 3d1c918e..fb4d97ba 100644 --- a/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala @@ -1,11 +1,9 @@ package model.rdf.sparql.rgml.query import java.util.Date -import java.text.SimpleDateFormat +import model.rdf.sparql.query.{SparqlCountQuery} -import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} - -class InstantQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInstantUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { +class InstantQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInstantUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { val select = "SELECT ?instant ?date" val group = "GROUP BY ?instant ?date" diff --git a/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala index 0231a41d..90769211 100644 --- a/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala @@ -1,11 +1,9 @@ package model.rdf.sparql.rgml.query import java.util.Date -import java.text.SimpleDateFormat +import model.rdf.sparql.query.{SparqlCountQuery} -import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} - -class IntervalQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeIntervalUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { +class IntervalQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeIntervalUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { val select = "SELECT ?interval ?start ?end" val group = "GROUP BY ?interval ?start ?end" @@ -43,22 +41,18 @@ class IntervalQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInter private def startFilter: String = { - val dateFormat = new SimpleDateFormat("YYYY-MM-DD") maybeStart match { case Some(start) => { - val startString = dateFormat.format(start) - return s"""FILTER (xsd:dateTime(?begin) > xsd:dateTime("$startString"))""" + return s"""FILTER (xsd:dateTime(?begin) > xsd:dateTime("${QueryHelpers.dateToString(start)}"))""" } case None => "" } } private def endFilter: String = { - val dateFormat = new SimpleDateFormat("YYYY-MM-DD") maybeEnd match { case Some(end) => { - val endString = dateFormat.format(end) - return s"""FILTER (xsd:dateTime(?end) < xsd:dateTime("$endString"))""" + return s"""FILTER (xsd:dateTime(?end) < xsd:dateTime("${QueryHelpers.dateToString(end)}"))""" } case None => "" } diff --git a/src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala b/src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala index 7118fca1..fabac522 100644 --- a/src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala +++ b/src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala @@ -14,7 +14,7 @@ object QueryHelpers { } } - def limit(maybeLimit: Option[Integer]) : String = { + def limit(maybeLimit: Option[Int]) : String = { maybeLimit match { case Some(value) => s"LIMIT $value" case None => "" diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala index 231548f7..d2640510 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala @@ -1,8 +1,8 @@ package model.rdf.sparql.rgml.query -import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} +import model.rdf.sparql.query.{SparqlCountQuery} -class ThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { +class ThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { val select = "SELECT ?thing ?connection ?instant" val group = "GROUP BY ?thing ?connection ?instant" diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala index cd87bf71..9f543120 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala @@ -1,8 +1,8 @@ package model.rdf.sparql.rgml.query -import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} +import model.rdf.sparql.query.{SparqlCountQuery} -class ThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { +class ThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { val select = "SELECT ?thing ?connection ?interval" val group = "GROUP BY ?thing ?connection ?interval" diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala index 64e68773..d062a930 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala @@ -1,8 +1,8 @@ package model.rdf.sparql.rgml.query -import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} +import model.rdf.sparql.query.{SparqlCountQuery} -class ThingsWithThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { +class ThingsWithThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { val select = "SELECT ?outerThing ?connection ?innerThing" diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala index dda2b3a1..19292e7d 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala @@ -1,8 +1,8 @@ package model.rdf.sparql.rgml.query -import model.rdf.sparql.query.{SparqlCountQuery, SparqlQuery} +import model.rdf.sparql.query.{SparqlCountQuery} -class ThingsWithThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Integer]) extends SparqlQuery with SparqlCountQuery { +class ThingsWithThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { val select = "SELECT ?outerThing ?connection ?innerThing" val group = "GROUP BY ?outerThing ?connection ?innerThing" diff --git a/src/conf/routes b/src/conf/routes index 9dfbb7a4..e72a35a7 100644 --- a/src/conf/routes +++ b/src/conf/routes @@ -98,7 +98,7 @@ POST /api/v1/datacube/slices/:id GET /dereference/labels @controllers.api.VisualizationApiController.dereferenceLabels(uri: String) -# Assistant +# === ASSISTANT === POST /assistant/api/auth/signUp @controllers.assistant.api.AuthApiController.signUp POST /assistant/api/auth/signIn @controllers.assistant.api.AuthApiController.signIn POST /assistant/api/auth/googleSignIn @controllers.assistant.api.AuthApiController.googleSignIn @@ -142,11 +142,13 @@ POST /assistant/api/common/getVirtuosoStatus @controllers.assi POST /assistant/api/commonVisualizer/getLabels/:id @controllers.assistant.api.visualizers.CommonVisualizerApiController.getLabels(id: Long) +#maps POST /assistant/api/mapsVisualizer/getProperties/:id @controllers.assistant.api.visualizers.MapsVisualizerApiController.getProperties(id: Long) POST /assistant/api/mapsVisualizer/getSkosConcepts/:id @controllers.assistant.api.visualizers.MapsVisualizerApiController.getSkosConcepts(id: Long) POST /assistant/api/mapsVisualizer/getSkosConceptsCounts/:id @controllers.assistant.api.visualizers.MapsVisualizerApiController.getSkosConceptsCounts(id: Long) POST /assistant/api/mapsVisualizer/getMarkers/:id @controllers.assistant.api.visualizers.MapsVisualizerApiController.getMarkers(id: Long) +#chord POST /assistant/api/chordVisualizer/getGraph/:id @controllers.assistant.api.visualizers.ChordVisualizerApiController.getGraph(id: Long) POST /assistant/api/chordVisualizer/getSampleNodes/:id @controllers.assistant.api.visualizers.ChordVisualizerApiController.getSampleNodes(id: Long) POST /assistant/api/chordVisualizer/getNodes/:id @controllers.assistant.api.visualizers.ChordVisualizerApiController.getNodes(id: Long) @@ -156,8 +158,21 @@ POST /assistant/api/chordVisualizer/getSearchableLens/:id @control POST /assistant/api/chordVisualizer/searchNodes/:id @controllers.assistant.api.visualizers.ChordVisualizerApiController.searchNodes(id: Long) POST /assistant/api/chordVisualizer/getRelatedNodes/:id @controllers.assistant.api.visualizers.ChordVisualizerApiController.getRelatedNodes(id: Long) -POST /assistant/api/eventVisualizer/getEvents/:id @controllers.assistant.api.visualizers.EventVisualizerApiController.getEvents(id: Long) -POST /assistant/api/eventVisualizer/getEventPeople/:id @controllers.assistant.api.visualizers.EventVisualizerApiController.getEventPeople(id: Long) +#timeline - getters +POST /assistant/api/timeLineVisualizer/getIntervals/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getIntervals(id: Long) +POST /assistant/api/timeLineVisualizer/getInstants/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getInstants(id: Long) +POST /assistant/api/timeLineVisualizer/getThingsWIntervals/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getThingWithIntervals(id: Long) +POST /assistant/api/timeLineVisualizer/getThingsWInstants/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getThingsWithInstants(id: Long) +POST /assistant/api/timeLineVisualizer/getThingsWThingsWIntervals/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getThingsWithThingsWithIntervals(id: Long) +POST /assistant/api/timeLineVisualizer/getThingsWThingsWInstants/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getThingsWithThingsWithInstants(id: Long) + +#timeline - counts +POST /assistant/api/timeLineVisualizer/getIntervals/count/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getIntervalsCount(id: Long) +POST /assistant/api/timeLineVisualizer/getInstants/count/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getInstantsCount(id: Long) +POST /assistant/api/timeLineVisualizer/getThingsWIntervals/count/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getThingsWithIntervalsCount(id: Long) +POST /assistant/api/timeLineVisualizer/getThingsWInstants/count/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getThingsWithInstantsCount(id: Long) +POST /assistant/api/timeLineVisualizer/getThingsWThingsWIntervals/count/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getThingsWithThingsWithIntervalsCount(id: Long) +POST /assistant/api/timeLineVisualizer/getThingsWThingsWInstants/count/:id @controllers.assistant.api.visualizers.TimeLineVisualizerApiController.getThingsWithThingsWithInstantsCount(id: Long) GET /assistant$any<.*> @controllers.assistant.PlatformController.index(any) GET /app/:id/:uid @controllers.assistant.ApplicationController.index(id: Long, uid: String, any = null) From 5bf6606041185e5635b77914f64bab5e857ff6bd Mon Sep 17 00:00:00 2001 From: vvancak Date: Mon, 1 May 2017 23:55:14 +0200 Subject: [PATCH 25/84] TimeLine: Moved from eventTimeLine, JavaScript api & module preparation --- .../assistant/javascripts/entries/events.js | 2 +- .../modules/visualizers/events/api.js | 16 ----- .../events/containers/SaveButton.js | 10 --- .../modules/visualizers/events/ducks/dirty.js | 13 ---- .../modules/visualizers/events/models.js | 29 -------- .../modules/visualizers/events/reducer.js | 16 ----- .../modules/visualizers/reducer.js | 4 +- .../javascripts/modules/visualizers/routes.js | 4 +- .../modules/visualizers/timeline/api.js | 67 +++++++++++++++++++ .../{events => timeline}/applicationRoutes.js | 0 .../components/Application.js | 0 .../components/ConfigToolbar.js | 0 .../components/Visualization.js | 6 +- .../components/VisualizationMessage.js | 0 .../configuratorRoutes.js | 0 .../containers/InfoContainer.js} | 4 +- .../containers/TimelineContainer.js | 0 .../ducks/configuration.js | 0 .../{events => timeline}/ducks/events.js | 0 .../{events => timeline}/ducks/people.js | 0 .../ducks/selectedEvent.js | 0 .../{events => timeline}/ducks/settings.js | 0 .../{events => timeline}/misc/TimeSeries.js | 0 .../misc/TimeSeriesStyle.css | 8 +++ .../modules/visualizers/timeline/models.js | 30 +++++++++ .../pages/Configurator.js | 0 .../{events => timeline}/pages/Embed.js | 0 .../{events => timeline}/pages/Standalone.js | 0 .../{events => timeline}/prefix.js | 2 +- .../modules/visualizers/timeline/reducer.js | 7 ++ .../{events => timeline}/selector.js | 0 31 files changed, 123 insertions(+), 95 deletions(-) delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/applicationRoutes.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/components/Application.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/components/ConfigToolbar.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/components/Visualization.js (92%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/components/VisualizationMessage.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/configuratorRoutes.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events/containers/EventInfoContainer.js => timeline/containers/InfoContainer.js} (97%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/containers/TimelineContainer.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/ducks/configuration.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/ducks/events.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/ducks/people.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/ducks/selectedEvent.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/ducks/settings.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/misc/TimeSeries.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/misc/TimeSeriesStyle.css (93%) create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/pages/Configurator.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/pages/Embed.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/pages/Standalone.js (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/prefix.js (71%) create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/{events => timeline}/selector.js (100%) diff --git a/src/app/assets_webpack/assistant/javascripts/entries/events.js b/src/app/assets_webpack/assistant/javascripts/entries/events.js index 1aa9e398..74197193 100644 --- a/src/app/assets_webpack/assistant/javascripts/entries/events.js +++ b/src/app/assets_webpack/assistant/javascripts/entries/events.js @@ -1,4 +1,4 @@ -import createRoutes from '../modules/visualizers/events/applicationRoutes' +import createRoutes from '../modules/visualizers/timeline/applicationRoutes' import initEntry from '../misc/initEntry' initEntry(createRoutes); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js deleted file mode 100644 index b82652b0..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/api.js +++ /dev/null @@ -1,16 +0,0 @@ -import rest from '../../../misc/rest' - -export async function getEvents(applicationId, settings) { - var start = settings.start.getTime(); - var end = settings.end.getTime(); - var limit = parseInt(settings.limit); - - let payload = {"start":start, "end":end, "limit":limit}; - const result = await rest('eventVisualizer/getEvents/' + applicationId,payload); - return result.data.events; -} - -export async function getEventPeople(applicationId, event) { - const result = await rest('eventVisualizer/getEventPeople/' + applicationId, {"event" : event}); - return result.data.people; -} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js deleted file mode 100644 index 369b0019..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/SaveButton.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react' -import { saveConfiguration, saveConfigurationStatusSelector } from '../ducks/configuration' -import { dirtySelector } from '../ducks/dirty' - -import createSaveButton from '../../../app/containers/createSaveButton' - -export default createSaveButton( - saveConfiguration, - saveConfigurationStatusSelector, - dirtySelector); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js deleted file mode 100644 index 5cd9201b..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/dirty.js +++ /dev/null @@ -1,13 +0,0 @@ -import { createSelector } from 'reselect' -import moduleSelector from '../selector' -import { createDirtyReducer } from '../../../app/ducks/dirty' -import { GET_SELECTED_EVENT, GET_SELECTED_EVENT_RESET } from './selectedEvent' -import { GET_SETTINGS, GET_SETTINGS_RESET} from './settings' - -// Reducer -const actions = [ GET_SETTINGS, GET_SETTINGS_RESET, GET_SELECTED_EVENT, GET_SELECTED_EVENT_RESET]; - -export default createDirtyReducer(actions); - -// Selectors -export const dirtySelector = createSelector([moduleSelector], state => state.dirty); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js deleted file mode 100644 index d1ad1703..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/models.js +++ /dev/null @@ -1,29 +0,0 @@ -import { Record } from 'immutable'; - -export const EventInfo = Record({ - url: "url", - name: "name", - date: new Date("2001-01-01"), - info: "info" -}); - -export const PersonInfo = Record({ - url: "url", - name: "name", - description: "description", - image: "image_url", - info: "info" -}); - -export const Settings = Record({ - start: new Date("01 01 2000"), - end: new Date("01 01 2018"), - limit: 100 -}); - -export const SelectedEvent = Record({ - isValid: false, - event: new EventInfo -}); - - diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js deleted file mode 100644 index 8a7e5941..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/reducer.js +++ /dev/null @@ -1,16 +0,0 @@ -import { combineReducers } from 'redux'; -import events from './ducks/events' -import people from './ducks/people' -import selectedEvent from './ducks/selectedEvent' -import settings from './ducks/settings' -import dirty from './ducks/dirty' - -const rootReducer = combineReducers({ - events, - people, - selectedEvent, - settings, - dirty -}); - -export default rootReducer; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js index 2bb5e30f..bb45c3c4 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/reducer.js @@ -1,11 +1,11 @@ import { combineReducers } from 'redux'; import googleMaps from './googleMaps/reducer' import chord from './chord/reducer' -import events from './events/reducer' +import timeline from './timeline/reducer' const rootReducer = combineReducers({ googleMaps, chord, - events + timeline }); export default rootReducer; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js index fd3c86db..53caaef5 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js @@ -4,7 +4,7 @@ import ConfiguratorsRouteFactory from './utils/ConfiguratorsRouteFactory' import dataCubeRoutes from './datacube/configuratorRoutes' import googleMapsRoutes from './googleMaps/configuratorRoutes' import chordRoutes from './chord/configuratorRoutes' -import eventsRoutes from './events/configuratorRoutes' +import timelineRoutes from './timeline/configuratorRoutes' import { Visualizer, VisualizerWithPipelines } from '../core/models' import { applicationUrl } from '../app/configuratorRoutes' @@ -15,7 +15,7 @@ const routeFactory = new ConfiguratorsRouteFactory(); routeFactory.register(dataCubeRoutes); routeFactory.register(googleMapsRoutes); routeFactory.register(chordRoutes); -routeFactory.register(eventsRoutes); +routeFactory.register(timelineRoutes); export default dispatch => routeFactory.createRoutes(dispatch); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js new file mode 100644 index 00000000..a5ed7fd5 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js @@ -0,0 +1,67 @@ +import rest from '../../../misc/rest' + +export async function getIntervals(applicationId, urls, start, end, limit) { + let payload = {"urls":urls, "start":start.getTime(), "end":end.getTime(), "limit":limit}; + const result = await rest('timeLineVisualizer/getIntervals/' + applicationId, payload); + return result.data.intervals; +} + +export async function getInstants(applicationId, urls, start, end, limit) { + let payload = {"urls":urls, "start":start.getTime(), "end":end.getTime(), "limit":limit}; + const result = await rest('timeLineVisualizer/getInstants/' + applicationId, payload); + return result.data.instants; +} + +export async function getThingsWIntervals(applicationId, things, connections, limit) { + let payload = {"things":things, "connections":connections, "limit":limit}; + const result = await rest('timeLineVisualizer/getThingsWIntervals/' + applicationId, payload); + return result.data.intervals; +} +export async function getThingsWInstants(applicationId, things, connections, limit) { + let payload = {"things":things, "connections":connections, "limit":limit}; + const result = await rest('timeLineVisualizer/getThingsWInstants/' + applicationId, payload); + return result.data.instants; +} +export async function getThingsWThingsWIntervals(applicationId, things, connections, limit) { + let payload = {"things": things, "connections": connections, "limit": limit}; + const result = await rest('timeLineVisualizer/getThingsWThingsWIntervals/' + applicationId, payload); + return result.data.intervals; +} +export async function getThingsWThingsWInstants(applicationId, things, connections, limit) { + let payload = {"things": things, "connections": connections, "limit": limit}; + const result = await rest('timeLineVisualizer/getThingsWThingsWInstants/' + applicationId, payload); + return result.data.instants; +} + +export async function getIntervalsCount(applicationId, urls, start, end, limit) { + let payload = {"urls":urls, "start":start.getTime(), "end":end.getTime(), "limit":limit}; + const result = await rest('timeLineVisualizer/getIntervals/count/' + applicationId, payload); + return result.data.count; +} + +export async function getInstantsCount(applicationId, urls, start, end, limit) { + let payload = {"urls":urls, "start":start.getTime(), "end":end.getTime(), "limit":limit}; + const result = await rest('timeLineVisualizer/getInstants/count/' + applicationId, payload); + return result.data.count; +} + +export async function getThingsWIntervalsCount(applicationId, things, connections, limit) { + let payload = {"things":things, "connections":connections, "limit":limit}; + const result = await rest('timeLineVisualizer/getThingsWIntervals/count/' + applicationId, payload); + return result.data.count; +} +export async function getThingsWInstantsCount(applicationId, things, connections, limit) { + let payload = {"things":things, "connections":connections, "limit":limit}; + const result = await rest('timeLineVisualizer/getThingsWInstants/count/' + applicationId, payload); + return result.data.count; +} +export async function getThingsWThingsWIntervalsCount(applicationId, things, connections, limit) { + let payload = {"things": things, "connections": connections, "limit": limit}; + const result = await rest('timeLineVisualizer/getThingsWThingsWIntervals/count/' + applicationId, payload); + return result.data.count; +} +export async function getThingsWThingsWInstantsCount(applicationId, things, connections, limit) { + let payload = {"things": things, "connections": connections, "limit": limit}; + const result = await rest('timeLineVisualizer/getThingsWThingsWInstants/count/' + applicationId, payload); + return result.data.count; +} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/applicationRoutes.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/applicationRoutes.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/applicationRoutes.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Application.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Application.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Application.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigToolbar.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/ConfigToolbar.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigToolbar.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Visualization.js similarity index 92% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Visualization.js index 2db28648..b345fda2 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/Visualization.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Visualization.js @@ -4,7 +4,7 @@ import {createStructuredSelector} from "reselect"; import { settingsSelector } from '../ducks/settings' import {getSelectedEvent, getSelectedEventReset, selectedEventSelector} from "../ducks/selectedEvent"; import TimelineContainer from '../containers/TimelineContainer' -import EventInfoContainer from '../containers/EventInfoContainer' +import EventInfoContainer from '../containers/InfoContainer' import {Settings, SelectedEvent} from '../models' import { getSettings, getSettingsReset} from '../ducks/settings' import CenteredMessage from '../../../../components/CenteredMessage' @@ -19,13 +19,13 @@ class Visualization extends Component { componentWillUpdate(){ const { dispatch } = this.props; - dispatch(getSelectedEvent()); + dispatch(getSelected()); dispatch(getSettings()); } componentWillUnmount() { const { dispatch } = this.props; - dispatch(getSelectedEventReset()); + dispatch(getSelected()); dispatch(getSettingsReset()); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/VisualizationMessage.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/VisualizationMessage.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/components/VisualizationMessage.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/VisualizationMessage.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/configuratorRoutes.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/configuratorRoutes.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/configuratorRoutes.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InfoContainer.js similarity index 97% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InfoContainer.js index cdfc8e53..c9d2b6f5 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/EventInfoContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InfoContainer.js @@ -9,7 +9,7 @@ import moment from "moment"; import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' -class EventInfoContainer extends Component { +class InfoContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, selectedEvent: PropTypes.instanceOf(SelectedEvent).isRequired, @@ -98,4 +98,4 @@ const selector = createStructuredSelector({ status: peopleStatusSelector }); -export default connect(selector)(EventInfoContainer); +export default connect(selector)(InfoContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimelineContainer.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/containers/TimelineContainer.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimelineContainer.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/configuration.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/configuration.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/configuration.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/events.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/events.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/events.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/people.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/people.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/people.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvent.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedEvent.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/selectedEvent.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedEvent.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/settings.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/settings.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/ducks/settings.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/settings.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeSeries.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeries.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeSeries.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeriesStyle.css b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeSeriesStyle.css similarity index 93% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeriesStyle.css rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeSeriesStyle.css index be83396b..dc2fe0e8 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/misc/TimeSeriesStyle.css +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeSeriesStyle.css @@ -77,6 +77,14 @@ code { stroke: rgba(211, 84, 0, 0.7); stroke-width: 5px; } + +.rect { + fill: #D35400; + opacity: 0.6; + stroke: rgba(211, 84, 0, 0.7); + stroke-width: 5px; +} + .domain { display: none; } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js new file mode 100644 index 00000000..c3897c7e --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js @@ -0,0 +1,30 @@ +import { Record } from 'immutable'; + +export const Interval = Record({ + url: "url", + start: new Date(), + end: new Date() +}); + +export const Instant = Record({ + url: "url", + start: new Date(), + end: new Date() +}); + +export const Connection = Record({ + outerThing: "url", + connection: "url", + innerThing: "url" +}); + +export const Count = Record({ + value: 123 +}); + + +export const Limit = Record({ + value: 100 +}); + + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Configurator.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Configurator.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Configurator.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Embed.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Embed.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Embed.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Embed.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Standalone.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Standalone.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/pages/Standalone.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Standalone.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/prefix.js similarity index 71% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/prefix.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/prefix.js index 9b65606e..3e419cfb 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/prefix.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/prefix.js @@ -1,4 +1,4 @@ import createPrefixer from '../../../misc/createPrefixer' -export const MODULE_PREFIX = 'events'; +export const MODULE_PREFIX = 'timeline'; export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js new file mode 100644 index 00000000..0d1784ed --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js @@ -0,0 +1,7 @@ +import { combineReducers } from 'redux'; + +const rootReducer = combineReducers({ + //TODO: Add reducers +}); + +export default rootReducer; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/selector.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/selector.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/events/selector.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/selector.js From c8869e4c87e0505c29f7cd0a36eb224d2f7977e5 Mon Sep 17 00:00:00 2001 From: vvancak Date: Thu, 4 May 2017 18:17:55 +0200 Subject: [PATCH 26/84] TimeLine: Server fixes (injection & extractors) --- .../api/visualizers/TimeLineVisualizerApiController.scala | 2 +- src/app/model/rdf/RdfModule.scala | 3 ++- src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala | 2 +- .../model/rdf/sparql/rgml/extractor/IntervalExtractor.scala | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala index 1c6b4dd2..30842d27 100644 --- a/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala +++ b/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala @@ -10,7 +10,7 @@ import model.rdf.sparql.rgml.{RgmlCountService, RgmlService} import scaldi.Injector import scala.concurrent.Future -class TimeLineVisualizerApiController(implicit inj: Injector) extends VisualizerApiController { +class TimeLineVisualizerApiController(implicit val inj: Injector) extends VisualizerApiController { val rgmlService = inject[RgmlService] val rgmlCountService = inject[RgmlCountService] diff --git a/src/app/model/rdf/RdfModule.scala b/src/app/model/rdf/RdfModule.scala index 35ee5c7f..ed8f1941 100644 --- a/src/app/model/rdf/RdfModule.scala +++ b/src/app/model/rdf/RdfModule.scala @@ -8,7 +8,7 @@ import scaldi.Module import model.rdf.sparql.datacube.{DataCubeService, DataCubeServiceImpl} import model.rdf.sparql.fresnel.{FresnelService, FresnelServiceImpl} import model.rdf.sparql.geo.{GeoService, GeoServiceImpl} -import model.rdf.sparql.rgml.{RgmlService, RgmlServiceImpl} +import model.rdf.sparql.rgml.{RgmlCountService, RgmlCountServiceImpl, RgmlService, RgmlServiceImpl} import model.rdf.sparql.{SparqlEndpointService, SparqlEndpointServiceImpl} class RdfModule extends Module { @@ -17,6 +17,7 @@ class RdfModule extends Module { bind [VisualizationService] to new VisualizationServiceImpl bind [GeoService] to new GeoServiceImpl bind [RgmlService] to new RgmlServiceImpl + bind [RgmlCountService] to new RgmlCountServiceImpl bind [FresnelService] to new FresnelServiceImpl bind [PipelineExtractor] to new PipelineExtractor diff --git a/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala index 1049a057..97141d68 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala @@ -14,7 +14,7 @@ class InstantExtractor extends QueryExecutionResultExtractor[InstantQuery, Seq[I try { val resList = input.execSelect().toList Some(resList.map(e => new Instant( - e.getResource("url").getURI, + e.getResource("instant").getURI, getDate(e, "date") ))) } diff --git a/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala index a82b9cd0..143a5faa 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala @@ -14,7 +14,7 @@ class IntervalExtractor extends QueryExecutionResultExtractor[IntervalQuery, Seq try { val resList = input.execSelect().toList Some(resList.map(e => new Interval( - e.getResource("url").getURI, + e.getResource("interval").getURI, getDate(e, "start"), getDate(e, "end") ))) From e03f1799b5ca195d5b691a70c26126505af0fce3 Mon Sep 17 00:00:00 2001 From: vvancak Date: Fri, 5 May 2017 00:23:38 +0200 Subject: [PATCH 27/84] TimeLine : Visualization cleanup & refactor --- .../entries/{events.js => timeline.js} | 0 .../visualizers/timeline/applicationRoutes.js | 2 +- .../timeline/components/Application.js | 6 +- ...nfigToolbar.js => ConfigurationToolbar.js} | 4 +- .../timeline/components/Visualization.js | 6 +- .../timeline/containers/InfoContainer.js | 101 ---------- .../timeline/containers/TimelineContainer.js | 46 ++--- .../timeline/ducks/configuration.js | 38 ---- .../visualizers/timeline/ducks/events.js | 47 ----- .../visualizers/timeline/ducks/instants.js | 43 ++++ .../visualizers/timeline/ducks/intervals.js | 43 ++++ .../visualizers/timeline/ducks/people.js | 47 ----- .../timeline/ducks/selectedEvent.js | 45 ----- .../visualizers/timeline/ducks/settings.js | 55 ------ .../misc/{TimeSeries.js => TimeLine.js} | 187 +++++++++--------- ...{TimeSeriesStyle.css => TimeLineStyle.css} | 0 .../modules/visualizers/timeline/models.js | 3 +- .../timeline/pages/Configurator.js | 16 +- .../modules/visualizers/timeline/reducer.js | 3 +- src/npm-shrinkwrap.json | 5 - src/package.json | 1 - src/project/build.properties | 1 + 22 files changed, 216 insertions(+), 483 deletions(-) rename src/app/assets_webpack/assistant/javascripts/entries/{events.js => timeline.js} (100%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/{ConfigToolbar.js => ConfigurationToolbar.js} (98%) delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InfoContainer.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/configuration.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/events.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/people.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedEvent.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/settings.js rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/{TimeSeries.js => TimeLine.js} (55%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/{TimeSeriesStyle.css => TimeLineStyle.css} (100%) create mode 100644 src/project/build.properties diff --git a/src/app/assets_webpack/assistant/javascripts/entries/events.js b/src/app/assets_webpack/assistant/javascripts/entries/timeline.js similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/entries/events.js rename to src/app/assets_webpack/assistant/javascripts/entries/timeline.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/applicationRoutes.js index b0f3e4c3..85b3dba8 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/applicationRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/applicationRoutes.js @@ -8,7 +8,7 @@ import Embed from './pages/Embed' export default function createRoutes(dispatch) { return ( - + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Application.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Application.js index 6af29284..6ffe4f4f 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Application.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Application.js @@ -2,8 +2,7 @@ import React, { Component, PropTypes } from 'react' import BodyPadding from '../../../../components/BodyPadding' import { Application as ApplicationModel } from '../../../app/models' import { Visualizer } from '../../../core/models' -import Visualization from '../components/Visualization' -import ConfigToolbar from "./ConfigToolbar"; +import TimelineContainer from '../containers/TimelineContainer' class Application extends Component { static propTypes = { @@ -17,8 +16,7 @@ class Application extends Component { return (

    {embed ? 'Embed' : 'Standalone'} mode.

    - - +
    ) } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigToolbar.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigurationToolbar.js similarity index 98% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigToolbar.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigurationToolbar.js index 60e5b2dc..39a28bb3 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigToolbar.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigurationToolbar.js @@ -1,3 +1,4 @@ +/* import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import {createStructuredSelector} from "reselect"; @@ -88,4 +89,5 @@ const selector = createStructuredSelector({ settings: settingsSelector }); -export default connect(selector)(ConfigToolbar); \ No newline at end of file +export default connect(selector)(ConfigToolbar); +*/ \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Visualization.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Visualization.js index b345fda2..658ed3ec 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Visualization.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Visualization.js @@ -1,3 +1,4 @@ +/* import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import {createStructuredSelector} from "reselect"; @@ -36,6 +37,7 @@ class Visualization extends Component { An error occurred while loading the configuration. } + return
    @@ -47,4 +49,6 @@ const selector = createStructuredSelector({ selectedEvent: selectedEventSelector }); -export default connect(selector)(Visualization); \ No newline at end of file +export default connect(selector)(Visualization); + +*/ \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InfoContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InfoContainer.js deleted file mode 100644 index c9d2b6f5..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InfoContainer.js +++ /dev/null @@ -1,101 +0,0 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from 'reselect' -import { getEventPeople, getEventPeopleReset, peopleSelector, peopleStatusSelector } from '../ducks/people' -import { PromiseStatus } from '../../../core/models' -import PromiseResult from '../../../core/components/PromiseResult' -import { SelectedEvent } from '../models' -import moment from "moment"; -import CenteredMessage from '../../../../components/CenteredMessage' -import VisualizationMessage from '../components/VisualizationMessage' - -class InfoContainer extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, - selectedEvent: PropTypes.instanceOf(SelectedEvent).isRequired, - people: PropTypes.instanceOf(Array).isRequired, - status: PropTypes.instanceOf(PromiseStatus).isRequired - }; - - componentWillReceiveProps(nextProps){ - const {dispatch, selectedEvent} = nextProps; - if (this.props.selectedEvent != selectedEvent) { - if (selectedEvent.isValid) { - dispatch(getEventPeople(selectedEvent.event)); - } - else { - dispatch(getEventPeopleReset()); - } - } - } - - componentWillUnmount() { - const {dispatch} = this.props; - dispatch(getEventPeopleReset()); - } - - render() { - const {people, selectedEvent, status} = this.props; - - // EVENT INFO: - var eventComponent = - To view more information about events, click on them in the timeline. - ; - - if(selectedEvent.isValid){ - var event = selectedEvent.event; - var dateString = moment(event.date).format('DD.MM.YYYY'); - - eventComponent =
    -

    Event info:

    -

    {event.name}

    -

    {event.description}

    -

    {dateString}

    - Event Link -
    ; - } - - // EVENT PEOPLE: - var peopleComponent = - Could not load people for selected event. - ; - - if (!status.done) { - peopleComponent = - } - if (people.length > 0) { - var renderPerson = function (person) { - var style = {width: 100, height: 150, "objectFit": 'contain'}; - return - No image available - -

    {person.name}

    -

    {person.description}

    - Wiki Link - - - }; - - peopleComponent =
    -

    People associated with this event

    - - {people.map(p=>renderPerson(p))} -
    -
    - } - - // RENDER - return
    - {eventComponent} -
    - {peopleComponent} -
    - } -} - -const selector = createStructuredSelector({ - people: peopleSelector, - status: peopleStatusSelector -}); - -export default connect(selector)(InfoContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimelineContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimelineContainer.js index 1e2ffa8a..e9591cb9 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimelineContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimelineContainer.js @@ -1,76 +1,64 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' -import { getEvents, getEventsReset, eventsSelector, eventsStatusSelector } from '../ducks/events' -import { selectEvent } from '../ducks/selectedEvent' +import { getInstants, getInstantsReset, instantsSelector, instantsStatusSelector } from '../ducks/instants' import { PromiseStatus } from '../../../core/models' import PromiseResult from '../../../core/components/PromiseResult' -import TimeSeries from '../misc/TimeSeries' +import TimeLine from '../misc/TimeLine' import {createStructuredSelector} from "reselect"; -import {Settings} from "../models" import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' class TimelineContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - events: PropTypes.instanceOf(Array).isRequired, - settings: PropTypes.instanceOf(Settings).isRequired, + instants: PropTypes.instanceOf(Array).isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired }; componentWillMount(){ const {dispatch} = this.props; - + dispatch(getInstants()) this.className = 'timeseries-chart'; - this.callBack = (ev)=>dispatch(selectEvent(ev)); + this.chart = new TimeLine(this.className, ()=>{}) // TODO: callback } componentWillReceiveProps(nextProps){ - const {dispatch, settings} = nextProps; - - if (this.props.settings != settings) { - dispatch(getEvents(settings)); - } - } - - componentDidUpdate(){ - const {events, status} = this.props; - - if (this.chart && this.chart.exists(this.className)) { - this.chart.destroy(this.className) - } + if (this.props.instants == null) return; - if (status.done) { - this.chart = new TimeSeries(this.className, events, false, this.callBack); + const {instants} = nextProps; + if (this.props.instants != instants) { + this.chart.destroy(); + this.chart.instants(instants); } } componentWillUnmount() { const {dispatch} = this.props; - dispatch(getEventsReset()); + dispatch(getInstantsReset()); + this.chart.destroy(); } render() { - const {status, events} = this.props; + const {status, instants} = this.props; if (!status.done) { return } - if (events.length == 0) { + if (instants.length == 0) { return No events were loaded. Check the settings please. } - require('../misc/TimeSeriesStyle.css'); + require('../misc/TimeLineStyle.css'); return
    } } const selector = createStructuredSelector({ - events: eventsSelector, - status: eventsStatusSelector + instants: instantsSelector, + status: instantsStatusSelector }); export default connect(selector)(TimelineContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/configuration.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/configuration.js deleted file mode 100644 index ac20bdd9..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/configuration.js +++ /dev/null @@ -1,38 +0,0 @@ -import prefix from '../prefix' -import moduleSelector from '../selector' -import { createPromiseStatusSelector } from '../../../core/ducks/promises' -import {createGetConfiguration, createGetConfigurationReset, createSaveConfiguration} from '../../../app/ducks/configuration' -import {SelectedEvent, Settings} from "../models"; -import {createSelector} from "reselect"; - -// Actions -export const SAVE_CONFIGURATION = prefix('SAVE_CONFIGURATION'); -export const SAVE_CONFIGURATION_START = SAVE_CONFIGURATION + '_START'; -export const SAVE_CONFIGURATION_ERROR = SAVE_CONFIGURATION + '_ERROR'; -export const SAVE_CONFIGURATION_SUCCESS = SAVE_CONFIGURATION + '_SUCCESS'; - -export const GET_CONFIGURATION = prefix('GET_CONFIGURATION'); -export const GET_CONFIGURATION_START = GET_CONFIGURATION + '_START'; -export const GET_CONFIGURATION_ERROR = GET_CONFIGURATION + '_ERROR'; -export const GET_CONFIGURATION_SUCCESS = GET_CONFIGURATION + '_SUCCESS'; -export const GET_CONFIGURATION_RESET = GET_CONFIGURATION + '_RESET'; - -// Selectors -export const saveConfigurationStatusSelector = createPromiseStatusSelector(SAVE_CONFIGURATION); -export const getConfigurationStatusSelector = createPromiseStatusSelector(GET_CONFIGURATION); - -export const configurationSelector = createSelector( - [moduleSelector], - state => ({ - settings: new Settings(state.settings), - selectedEvent: new SelectedEvent(state.selectedEvent) - }) -); - -// Actual actions created using factories -export const saveConfiguration = - createSaveConfiguration(SAVE_CONFIGURATION, configurationSelector); -export const getConfiguration = - createGetConfiguration(GET_CONFIGURATION); -export const getConfigurationReset = - createGetConfigurationReset(GET_CONFIGURATION_RESET); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/events.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/events.js deleted file mode 100644 index d9f419a5..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/events.js +++ /dev/null @@ -1,47 +0,0 @@ -import createAction from '../../../../misc/createAction' -import withApplicationId from '../../../app/misc/withApplicationId' -import prefix from '../prefix' -import * as api from '../api' -import { GET_APPLICATION_START } from '../../../app/ducks/application' -import { EventInfo } from '../models' -import { createSelector } from 'reselect' -import { createPromiseStatusSelector } from '../../../core/ducks/promises' -import moduleSelector from '../selector' - -// Actions -export const GET_EVENTS = prefix('GET_EVENTS'); -export const GET_EVENTS_START = GET_EVENTS + '_START'; -export const GET_EVENTS_ERROR = GET_EVENTS + '_ERROR'; -export const GET_EVENTS_SUCCESS = GET_EVENTS + '_SUCCESS'; -export const GET_EVENTS_RESET = GET_EVENTS + '_RESET'; - -export function getEvents(settings) { - return withApplicationId(id => { - const promise = api.getEvents(id,settings); - return createAction(GET_EVENTS, { promise }); - }); -} - -export function getEventsReset() { - return createAction(GET_EVENTS_RESET); -} - -// Reducer -const initialState = []; -export default function eventsReducer(state = initialState, action) { - switch (action.type) { - case GET_APPLICATION_START: - return initialState; - case GET_EVENTS_RESET: - return initialState; - case GET_EVENTS_ERROR: - return initialState; - case GET_EVENTS_SUCCESS: - return action.payload.map(ev=>new EventInfo(ev)); - } - return state; -}; - -// Selectors -export const eventsStatusSelector = createPromiseStatusSelector(GET_EVENTS); -export const eventsSelector = createSelector([moduleSelector], state => state.events); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js new file mode 100644 index 00000000..7bf4b5ad --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js @@ -0,0 +1,43 @@ +import createAction from '../../../../misc/createAction' +import withApplicationId from '../../../app/misc/withApplicationId' +import prefix from '../prefix' +import * as api from '../api' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { Instant } from '../models' +import { createSelector } from 'reselect' +import { createPromiseStatusSelector } from '../../../core/ducks/promises' +import moduleSelector from '../selector' + +// Actions +export const GET_INSTANTS = prefix('GET_INSTANTS'); +export const GET_INSTANTS_SUCCESS = GET_INSTANTS + '_SUCCESS'; +export const GET_INSTANTS_RESET = GET_INSTANTS + '_RESET'; + +export function getInstants() { + return withApplicationId(id => { + const promise = api.getInstants(id,[],new Date("01-01-0000"), new Date("01-01-2010"),100); + return createAction(GET_INSTANTS, { promise }); + }); +} + +export function getInstantsReset() { + return createAction(GET_INSTANTS_RESET); +} + +// Reducer +const initialState = []; +export default function instantsReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_INSTANTS_RESET: + return initialState; + case GET_INSTANTS_SUCCESS: + return action.payload.map(i=>new Instant(i)); + } + return state; +}; + +// Selectors +export const instantsStatusSelector = createPromiseStatusSelector(GET_INSTANTS); +export const instantsSelector = createSelector([moduleSelector], state => state.instants); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js new file mode 100644 index 00000000..a5d903a3 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js @@ -0,0 +1,43 @@ +import createAction from '../../../../misc/createAction' +import withApplicationId from '../../../app/misc/withApplicationId' +import prefix from '../prefix' +import * as api from '../api' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { Interval } from '../models' +import { createSelector } from 'reselect' +import { createPromiseStatusSelector } from '../../../core/ducks/promises' +import moduleSelector from '../selector' + +// Actions +export const GET_INTERVALS = prefix('GET_INTERVALS'); +export const GET_INTERVALS_SUCCESS = GET_INTERVALS + '_SUCCESS'; +export const GET_INTERVALS_RESET = GET_INTERVALS + '_RESET'; + +export function getIntervals() { + return withApplicationId(id => { + const promise = api.getIntervals(id,[],new Date("01-01-2000"), new Date("01-01-2010"),100); + return createAction(GET_INTERVALS, { promise }); + }); +} + +export function getIntervalsReset() { + return createAction(GET_INTERVALS_RESET); +} + +// Reducer +const initialState = []; +export default function intervalsReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_INTERVALS_RESET: + return initialState; + case GET_INTERVALS_SUCCESS: + return action.payload.map(i=>new Interval(i)); + } + return state; +}; + +// Selectors +export const intervalsStatusSelector = createPromiseStatusSelector(GET_INTERVALS); +export const intervalsSelector = createSelector([moduleSelector], state => state.intervals); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/people.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/people.js deleted file mode 100644 index 4c9ccfb7..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/people.js +++ /dev/null @@ -1,47 +0,0 @@ -import createAction from '../../../../misc/createAction' -import withApplicationId from '../../../app/misc/withApplicationId' -import prefix from '../prefix' -import * as api from '../api' -import { GET_APPLICATION_START } from '../../../app/ducks/application' -import { PersonInfo } from '../models' -import { createSelector } from 'reselect' -import { createPromiseStatusSelector } from '../../../core/ducks/promises' -import moduleSelector from '../selector' - -// Actions -export const GET_PEOPLE = prefix('GET_PEOPLE'); -export const GET_PEOPLE_START = GET_PEOPLE + '_START'; -export const GET_PEOPLE_ERROR = GET_PEOPLE + '_ERROR'; -export const GET_PEOPLE_SUCCESS = GET_PEOPLE + '_SUCCESS'; -export const GET_PEOPLE_RESET = GET_PEOPLE + '_RESET'; - -export function getEventPeople(event) { - return withApplicationId(id => { - const promise = api.getEventPeople(id,event.url); - return createAction(GET_PEOPLE, { promise }); - }); -} - -export function getEventPeopleReset() { - return createAction(GET_PEOPLE_RESET); -} - -// Reducer -const initialState = []; -export default function peopleReducer(state = initialState, action) { - switch (action.type) { - case GET_APPLICATION_START: - return initialState; - case GET_PEOPLE_RESET: - return initialState; - case GET_PEOPLE_ERROR: - return [action.payload]; - case GET_PEOPLE_SUCCESS: - return action.payload.map(p=>new PersonInfo(p)); - } - return state; -}; - -// Selectors -export const peopleStatusSelector = createPromiseStatusSelector(GET_PEOPLE); -export const peopleSelector = createSelector([moduleSelector], state => state.people); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedEvent.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedEvent.js deleted file mode 100644 index 31e7c312..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedEvent.js +++ /dev/null @@ -1,45 +0,0 @@ -import { createSelector } from 'reselect' -import prefix from '../prefix' -import createAction from '../../../../misc/createAction' -import moduleSelector from '../selector' -import { GET_APPLICATION_START } from '../../../app/ducks/application' -import {SelectedEvent} from "../models"; -import {GET_CONFIGURATION_SUCCESS} from "./configuration"; - -// Actions -export const SET_SELECTED_EVENT = prefix('SET_SELECTED_EVENT'); -export function selectEvent(selectedEvent) { - return createAction(SET_SELECTED_EVENT, { selectedEvent }); -} -export const GET_SELECTED_EVENT = prefix('GET_SELECTED_EVENT'); -export function getSelectedEvent() { - return createAction(GET_SELECTED_EVENT) -} - -export const GET_SELECTED_EVENT_RESET = GET_SELECTED_EVENT + "RESET"; -export function getSelectedEventReset(){ - return createAction(GET_SELECTED_EVENT_RESET); -} - -// Reducer -const initialState = new SelectedEvent(); -export default function selectedEventReducer(state = initialState, action) { - switch (action.type) { - case GET_APPLICATION_START: - return initialState; - case GET_SELECTED_EVENT_RESET: - return initialState; - case GET_SELECTED_EVENT: - return new SelectedEvent(state); - case GET_CONFIGURATION_SUCCESS: - if ("selectedEvent" in action.payload) return new SelectedEvent(action.payload.selectedEvent); - else return state; - case SET_SELECTED_EVENT: - return new SelectedEvent({isValid: true, event: action.payload.selectedEvent}); - default: - return state; - } -} - -// Selectors -export const selectedEventSelector = createSelector([moduleSelector],state => state.selectedEvent); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/settings.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/settings.js deleted file mode 100644 index 3b72a5c1..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/settings.js +++ /dev/null @@ -1,55 +0,0 @@ -import createAction from '../../../../misc/createAction' -import prefix from '../prefix' -import { GET_APPLICATION_START } from '../../../app/ducks/application' -import { Settings } from '../models' -import { createSelector } from 'reselect' -import moduleSelector from '../selector' -import {GET_CONFIGURATION_SUCCESS} from "./configuration"; - -// Actions -export const GET_SETTINGS = prefix('GET_SETTINGS'); -export const SET_SETTINGS = prefix('SET_SETTINGS'); -export const GET_SETTINGS_RESET = GET_SETTINGS + '_RESET'; - -export function getSettings() { - return createAction(GET_SETTINGS); -} -export function setSettings(settings) { - return createAction(SET_SETTINGS, {settings}) -} -export function getSettingsReset() { - return createAction(GET_SETTINGS_RESET); -} - -// Reducer -const initialState = new Settings(); -export default function configReducer(state = initialState, action) { - switch (action.type) { - case GET_APPLICATION_START: - return initialState; - case GET_SETTINGS_RESET: - return initialState; - case SET_SETTINGS: - return new Settings(action.payload.settings); - case GET_CONFIGURATION_SUCCESS: - return parseSavedSettings(action.payload); - case GET_SETTINGS: - return new Settings(state); - default: - return state; - } -}; - -function parseSavedSettings(payload){ - if ("settings" in payload) { - var start = new Date(payload.settings.start); - var end = new Date(payload.settings.end); - var limit = payload.settings.limit; - return new Settings({start: start, end: end, limit: limit}); - } - else return initialState; -} - -// Selectors -export const settingsSelector = createSelector([moduleSelector], state => state.settings); - diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeSeries.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js similarity index 55% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeSeries.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js index 7ccbf0e0..82f4d165 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeSeries.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js @@ -1,16 +1,12 @@ import d3 from 'd3' import moment from 'moment' -import * as _ from 'underscore' import {getAvailableVerticalSpace} from "../../../../components/FillInScreen"; -class TimeSeries { - constructor(spaced, data, enableBrush, callback) { +class TimeLine { + constructor(spaced, callback) { var classd = spaced.replace(new RegExp(" "), "."); - render(classd, spaced, data, enableBrush); -// --------------------------------------------------------------------------------------------- -// ---------------------------------- Time Manipulation ---------------------------------------- -// --------------------------------------------------------------------------------------------- + // Time helpers function lessThanDay(d) { return (d === "hours" || d === "minutes" || d === "seconds") ? true : false; } @@ -31,15 +27,26 @@ class TimeSeries { return date.valueOf(); } - /* - Given a list of time stamps, compute the minimum and maxium dates. Return a padded - version of the min and max dates based on the temporal distance between them. - */ - function timeRangePad(dates) { + function getDatePadding(minDate, maxDate) { + if (maxDate.diff(minDate, 'years') > 0) + return 'months'; + else if (maxDate.diff(minDate, 'months') > 0) + return 'days'; + else if (maxDate.diff(minDate, 'days') > 0) + return 'days'; + else if (maxDate.diff(minDate, 'hours') > 0) + return 'hours'; + else if (maxDate.diff(minDate, 'minutes') > 0) + return 'minutes'; + else + return 'seconds'; + } + + this.timeRangePad = function (dates) { var minDate, maxDate, pad; if (dates.length > 1) { - minDate = moment(_.min(dates)); - maxDate = moment(_.max(dates)); + minDate = moment(Math.min.apply(null,dates)); + maxDate = moment(Math.max.apply(null,dates)); pad = getDatePadding(minDate, maxDate); minDate.subtract(1, pad); maxDate.add(1, pad); @@ -54,36 +61,18 @@ class TimeSeries { }; }; - function getDatePadding(minDate, maxDate) { - if (maxDate.diff(minDate, 'years') > 0) - return 'months'; - else if (maxDate.diff(minDate, 'months') > 0) - return 'days'; - else if (maxDate.diff(minDate, 'days') > 0) - return 'days'; - else if (maxDate.diff(minDate, 'hours') > 0) - return 'hours'; - else if (maxDate.diff(minDate, 'minutes') > 0) - return 'minutes'; - else - return 'seconds'; - } - // --------------------------------------------------------------------------------------------- // ------------------------------------- Rendering --------------------------------------------- // --------------------------------------------------------------------------------------------- - function render(classd, spaced, data, enableBrush) { - - var padding = timeRangePad(_.pluck(data, 'date')); - + this.render = function (padding, drawFunc) { var margin = { top: 10, right: 25, bottom: 15, left: 35 - } -// var width = window.innerWidth - 150; + }; + var width = getAvailableVerticalSpace(document.getElementsByClassName(spaced)[0]); var height = (lessThanDay(padding.pad)) ? (100 - margin.top - margin.bottom) : (300 - margin.top - margin.bottom); @@ -136,72 +125,78 @@ class TimeSeries { .attr("transform", "translate(" + margin.left + "," + margin.top + ")") .call(yAxis); - var circles = context.append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")") + drawFunc(); + + this.circles = function(data, extract){ + var circles = context.append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")") + + circles.selectAll(".circ") + .data(data) + .enter().append("circle") + .attr("class", "circ") + .attr("cx", function (d) { + var value = extract(d); + return (lessThanDay(padding.pad)) ? x(value) : x(getDate(value)); + }) + .attr("cy", function (d, i) { + var value = extract(d); + return (lessThanDay(padding.pad)) ? y(getDate(value)) : y(getTime(value)); + }) + .attr("r", 9) + .on("click", function (d) { + callback(d); + }); + }; - circles.selectAll(".circ") - .data(data) - .enter().append("circle") - .attr("class", "circ") - .attr("cx", function (d) { - return (lessThanDay(padding.pad)) ? x(d.date) : x(getDate(d.date)); - }) - .attr("cy", function (d, i) { - return (lessThanDay(padding.pad)) ? y(getDate(d.date)) : y(getTime(d.date)); - }) - .attr("r", 9) - .on("click", function (d) { - callback(d); - }); - - // ----------------------------------------- Brush --------------------------------------------- - - if (enableBrush) { - var brush = d3.svg.brush() - .x(x) - .on("brush", _.throttle(brushed, 200)); - - circles.append("g") - .attr("class", "brush") - .call(brush) - .selectAll("rect") - .attr("y", -6) - .attr("height", height - margin.bottom); - - var brushEl = '
    Click and drag on the timeseries to create a brush.
    '; - window.document.getElementsByClassName(spaced)[0].insertAdjacentHTML('beforeend', brushEl); - - function brushed() { - if (!brush.empty()) { - d3.select('.clear-brush').style("display", "inline-block"); - d3.select('.brush-info')[0][0].innerText = brush.extent(); - } - } - - d3.select('.clear-brush').on("click", function (d) { - if (!brush.empty()) { - d3.selectAll("g.brush").call(brush.clear()); - d3.select('.brush-info')[0][0].innerText = ""; - d3.select('.clear-brush').style("display", "none"); - } - }); - - TimeSeries.getBrushExtent = function () { - if (brush) - return brush.extent(); - } + //TODO: Check values... + this.rectangles = function(data, start,end){ + var rectangles = context.append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")") + + rectangles.selectAll(".rect") + .data(data) + .enter().append("rect") + .attr("class", "rect") + .attr("x", function (d) { + var value = start(d); + return (lessThanDay(padding.pad)) ? x(value) : x(getDate(value)); + }) + .attr("y", function (d, i) { + var value = start(d); + return (lessThanDay(padding.pad)) ? y(getDate(value)) : y(getTime(value)); + }) + .attr("width", function(d){ + var value = end(d) - start(d); + return (lessThanDay(padding.pad)) ? x(value) : x(getDate(value)); + }) + .attr("height", function(d){ + var value = end(d) - start(d); + return (lessThanDay(padding.pad)) ? y(getDate(value) + 18) : y(getTime(value)); + }) + .on("click", function (d) { + callback(d); + }); + } + + this.destroy = function() { + d3.select("." + classd).removeAll(); } } } - exists(spaced) { - var classd = spaced.replace(new RegExp(" "), "."); - if (d3.select("." + classd).select("svg")) return true; - return false; + + instants(data) { + var padding = this.timeRangePad(data.map(d=>d.date)); + var drawFunc = this.circles(data,d=>d.date); + this.render(padding,drawFunc); } - destroy(spaced) { - var classd = spaced.replace(new RegExp(" "), "."); - d3.select("." + classd).select("svg").remove(); + intervals(data) { + var dates = data.map(d=>d.start).append(data.map(d=>d.end)); + var padding = this.timeRangePad(dates) + + var drawFunc = this.rectangles(data, d=>d.start, d=>d.end); + this.render(padding,drawFunc); } } -export default TimeSeries; \ No newline at end of file +export default TimeLine; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeSeriesStyle.css b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLineStyle.css similarity index 100% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeSeriesStyle.css rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLineStyle.css diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js index c3897c7e..1946aa8a 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js @@ -8,8 +8,7 @@ export const Interval = Record({ export const Instant = Record({ url: "url", - start: new Date(), - end: new Date() + date: new Date() }); export const Connection = Record({ diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Configurator.js index ea098664..cb4fc7bc 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Configurator.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Configurator.js @@ -2,10 +2,7 @@ import React, { Component, PropTypes } from 'react' import BodyPadding from '../../../../components/BodyPadding' import { Application } from '../../../app/models' import { Visualizer } from '../../../core/models' -import Visualization from '../components/Visualization' -import ConfigToolbar from '../components/ConfigToolbar' -import SaveButton from '../containers/SaveButton' -import {getConfiguration, getConfigurationReset} from "../ducks/configuration"; +import TimelineContainer from '../containers/TimelineContainer' class Configurator extends Component { static propTypes = { @@ -13,7 +10,7 @@ class Configurator extends Component { visualizer: PropTypes.instanceOf(Visualizer).isRequired }; - componentWillMount() { + /* componentWillMount() { const { dispatch } = this.props; dispatch(getConfiguration()); } @@ -21,16 +18,17 @@ class Configurator extends Component { componentWillUnmount() { const { dispatch } = this.props; dispatch(getConfigurationReset()); - } + }*/ render() { return ( + + ) + /*return ( - - - ) + )*/ } } export default Configurator; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js index 0d1784ed..503c4692 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js @@ -1,7 +1,8 @@ import { combineReducers } from 'redux'; +import instants from './ducks/instants' const rootReducer = combineReducers({ - //TODO: Add reducers + instants }); export default rootReducer; \ No newline at end of file diff --git a/src/npm-shrinkwrap.json b/src/npm-shrinkwrap.json index 159f3e49..86a86670 100644 --- a/src/npm-shrinkwrap.json +++ b/src/npm-shrinkwrap.json @@ -935,11 +935,6 @@ "from": "scriptjs@>=2.5.0 <2.6.0", "resolved": "https://registry.npmjs.org/scriptjs/-/scriptjs-2.5.8.tgz" }, - "underscore": { - "version": "1.8.3", - "from": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz" - }, "when": { "version": "3.7.7", "from": "when@>=3.7.0 <3.8.0", diff --git a/src/package.json b/src/package.json index f2bd4833..1a7dc3f9 100644 --- a/src/package.json +++ b/src/package.json @@ -37,7 +37,6 @@ "reselect": "2.0.x", "revalidator": "0.3.x", "scriptjs": "2.5.x", - "underscore": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", "when": "3.7.x" }, "devDependencies": { diff --git a/src/project/build.properties b/src/project/build.properties new file mode 100644 index 00000000..64317fda --- /dev/null +++ b/src/project/build.properties @@ -0,0 +1 @@ +sbt.version=0.13.15 From dbd2c260020ff63de75f7103371e806e82d2a9a3 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sat, 6 May 2017 23:28:02 +0200 Subject: [PATCH 28/84] TimeLine : Server-Side fixes --- ...ineContainer.js => TimeLineInstantsContainer.js} | 1 + .../containers/TimeLineIntervalsContainer.js | 3 +++ .../TimeLineVisualizerApiController.scala | 8 ++++---- .../model/assistant/rest/UrlsStartEndRequest.scala | 2 +- .../sparql/rgml/extractor/InstantExtractor.scala | 2 +- .../sparql/rgml/extractor/IntervalExtractor.scala | 7 ++++--- src/app/model/rdf/sparql/rgml/models/Interval.scala | 2 +- .../model/rdf/sparql/rgml/query/InstantQuery.scala | 2 +- .../model/rdf/sparql/rgml/query/IntervalQuery.scala | 13 ++++++++----- .../sparql/rgml/query/ThingsWithInstantQuery.scala | 2 +- .../sparql/rgml/query/ThingsWithIntervalQuery.scala | 2 +- .../query/ThingsWithThingsWithInstantQuery.scala | 2 +- 12 files changed, 27 insertions(+), 19 deletions(-) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/{TimelineContainer.js => TimeLineInstantsContainer.js} (97%) create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimelineContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js similarity index 97% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimelineContainer.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js index e9591cb9..94a47908 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimelineContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js @@ -12,6 +12,7 @@ class TimelineContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, instants: PropTypes.instanceOf(Array).isRequired, + urls: PropTypes.instanceOf(Array).isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired }; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js new file mode 100644 index 00000000..b99eb276 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js @@ -0,0 +1,3 @@ +/** + * Created by vladislav on 6.5.17. + */ diff --git a/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala index 30842d27..9839654e 100644 --- a/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala +++ b/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala @@ -16,28 +16,28 @@ class TimeLineVisualizerApiController(implicit val inj: Injector) extends Visual def getIntervals(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => withEvaluation(ApplicationId(id)) { evaluation => - val intervals = rgmlService.intervals(evaluation, json.start, json.end, json.urls, json.limit) + val intervals = rgmlService.intervals(evaluation, json.begin, json.end, json.urls, json.limit) Future(Ok(SuccessResponse(data = Seq("intervals" -> intervals)))) } } def getIntervalsCount(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => withEvaluation(ApplicationId(id)) { evaluation => - val count = rgmlCountService.intervals(evaluation, json.start, json.end, json.urls, json.limit) + val count = rgmlCountService.intervals(evaluation, json.begin, json.end, json.urls, json.limit) Future(Ok(SuccessResponse(data = Seq("count" -> count)))) } } def getInstants(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => withEvaluation(ApplicationId(id)) { evaluation => - val instants = rgmlService.instants(evaluation, json.start, json.end, json.urls, json.limit) + val instants = rgmlService.instants(evaluation, json.begin, json.end, json.urls, json.limit) Future(Ok(SuccessResponse(data = Seq("instants" -> instants)))) } } def getInstantsCount(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => withEvaluation(ApplicationId(id)) { evaluation => - val count = rgmlCountService.instants(evaluation, json.start, json.end, json.urls, json.limit) + val count = rgmlCountService.instants(evaluation, json.begin, json.end, json.urls, json.limit) Future(Ok(SuccessResponse(data = Seq("count" -> count)))) } } diff --git a/src/app/model/assistant/rest/UrlsStartEndRequest.scala b/src/app/model/assistant/rest/UrlsStartEndRequest.scala index 34b6bea0..3e0e0e79 100644 --- a/src/app/model/assistant/rest/UrlsStartEndRequest.scala +++ b/src/app/model/assistant/rest/UrlsStartEndRequest.scala @@ -4,7 +4,7 @@ import java.util.Date import play.api.libs.json.Json object UrlsStartEndRequest { - case class UrlsStartEndRequest(urls: Seq[String], start: Date, end: Date, limit: Int) + case class UrlsStartEndRequest(urls: Seq[String], begin: Date, end: Date, limit: Int) implicit val writes = Json.writes[UrlsStartEndRequest] implicit val reads = Json.reads[UrlsStartEndRequest] } diff --git a/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala index 97141d68..f1a936a5 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala @@ -26,7 +26,7 @@ class InstantExtractor extends QueryExecutionResultExtractor[InstantQuery, Seq[I } private def getDate(qs: QuerySolution, fieldName: String): Date = { - val dateFormat = new SimpleDateFormat("YYYY-MM-DD") + val dateFormat = new SimpleDateFormat("yyyy-MM-DD") val fieldValue = qs.getLiteral(fieldName).getString() return dateFormat.parse(fieldValue) } diff --git a/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala index 143a5faa..5793086f 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala @@ -15,7 +15,7 @@ class IntervalExtractor extends QueryExecutionResultExtractor[IntervalQuery, Seq val resList = input.execSelect().toList Some(resList.map(e => new Interval( e.getResource("interval").getURI, - getDate(e, "start"), + getDate(e, "begin"), getDate(e, "end") ))) } @@ -27,8 +27,9 @@ class IntervalExtractor extends QueryExecutionResultExtractor[IntervalQuery, Seq } private def getDate(qs: QuerySolution, fieldName: String): Date = { - val dateFormat = new SimpleDateFormat("YYYY-MM-DD") + val dateFormat = new SimpleDateFormat("yyyy-MM-DD") val fieldValue = qs.getLiteral(fieldName).getString() - return dateFormat.parse(fieldValue) + val date = dateFormat.parse(fieldValue) + return date; } } diff --git a/src/app/model/rdf/sparql/rgml/models/Interval.scala b/src/app/model/rdf/sparql/rgml/models/Interval.scala index 0a59665d..1be4c909 100644 --- a/src/app/model/rdf/sparql/rgml/models/Interval.scala +++ b/src/app/model/rdf/sparql/rgml/models/Interval.scala @@ -1,4 +1,4 @@ package model.rdf.sparql.rgml.models import java.util.Date -case class Interval(url:String, start: Date, end:Date) +case class Interval(url:String, begin: Date, end:Date) diff --git a/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala index fb4d97ba..2e838638 100644 --- a/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala @@ -12,7 +12,7 @@ class InstantQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInstan } def getCount: String = { - val select = "COUNT(?instant) AS ?count" + val select = "SELECT COUNT(?instant) AS ?count" val group = "" val limit = "" return query(select, group, limit) diff --git a/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala index 90769211..fa428f7b 100644 --- a/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala @@ -5,14 +5,14 @@ import model.rdf.sparql.query.{SparqlCountQuery} class IntervalQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeIntervalUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { - val select = "SELECT ?interval ?start ?end" - val group = "GROUP BY ?interval ?start ?end" + val select = "SELECT ?interval ?begin ?end" + val group = "GROUP BY ?interval ?begin ?end" val limit = QueryHelpers.limit(maybeLimit) return query(select,group,limit) } def getCount: String = { - val select = "COUNT(?interval) AS ?count" + val select = "SELECT COUNT(?interval) AS ?count" val group = "" val limit = "" return query(select, group, limit) @@ -25,8 +25,11 @@ class IntervalQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInter | |${select} |WHERE { - | ?interval time:hasBeginning ?beginning . - | ?interval time:hasEnd ?end . + | ?interval time:hasBeginning ?begin_url . + | ?interval time:hasEnd ?end_url . + | + | ?begin_url time:inXSDDateTime ?begin. + | ?end_url time:inXSDDateTime ?end. | | ${startFilter} | ${endFilter} diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala index d2640510..dcb2c431 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala @@ -11,7 +11,7 @@ class ThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], maybeConnecti } def getCount: String = { - val select = "COUNT(?thing) AS ?count" + val select = "SELECT COUNT(?thing) AS ?count" val group = "" val limit = "" return query(select,group,limit) diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala index 9f543120..8e960303 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala @@ -11,7 +11,7 @@ class ThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], maybeConnect } def getCount: String = { - val select = "COUNT(?thing) AS ?count" + val select = "SELECT COUNT(?thing) AS ?count" val group = "" val limit = "" return query(select,group,limit) diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala index d062a930..c3e9b7a1 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala @@ -12,7 +12,7 @@ class ThingsWithThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], may } def getCount: String = { - val select = "COUNT(?thing) AS ?count" + val select = "SELECT COUNT(?thing) AS ?count" val group = "" val limit = "" return query(select,group,limit) From 61f24ba870438db2e2b993410562bfd3c764bec5 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sat, 6 May 2017 23:29:17 +0200 Subject: [PATCH 29/84] TimeLine: intervals in client-side --- .../modules/visualizers/timeline/api.js | 16 +-- .../containers/TimeLineInstantsContainer.js | 24 ++-- .../containers/TimeLineIntervalsContainer.js | 66 +++++++++- .../visualizers/timeline/ducks/instants.js | 2 +- .../visualizers/timeline/ducks/intervals.js | 2 +- .../visualizers/timeline/misc/TimeLine.js | 115 +++++++++--------- .../modules/visualizers/timeline/models.js | 2 +- .../modules/visualizers/timeline/reducer.js | 6 +- 8 files changed, 148 insertions(+), 85 deletions(-) diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js index a5ed7fd5..8bfd34aa 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js @@ -1,13 +1,13 @@ import rest from '../../../misc/rest' -export async function getIntervals(applicationId, urls, start, end, limit) { - let payload = {"urls":urls, "start":start.getTime(), "end":end.getTime(), "limit":limit}; +export async function getIntervals(applicationId, urls, begin, end, limit) { + let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit":limit}; const result = await rest('timeLineVisualizer/getIntervals/' + applicationId, payload); return result.data.intervals; } -export async function getInstants(applicationId, urls, start, end, limit) { - let payload = {"urls":urls, "start":start.getTime(), "end":end.getTime(), "limit":limit}; +export async function getInstants(applicationId, urls, begin, end, limit) { + let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit":limit}; const result = await rest('timeLineVisualizer/getInstants/' + applicationId, payload); return result.data.instants; } @@ -33,14 +33,14 @@ export async function getThingsWThingsWInstants(applicationId, things, connectio return result.data.instants; } -export async function getIntervalsCount(applicationId, urls, start, end, limit) { - let payload = {"urls":urls, "start":start.getTime(), "end":end.getTime(), "limit":limit}; +export async function getIntervalsCount(applicationId, urls, begin, end, limit) { + let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit":limit}; const result = await rest('timeLineVisualizer/getIntervals/count/' + applicationId, payload); return result.data.count; } -export async function getInstantsCount(applicationId, urls, start, end, limit) { - let payload = {"urls":urls, "start":start.getTime(), "end":end.getTime(), "limit":limit}; +export async function getInstantsCount(applicationId, urls, begin, end, limit) { + let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit":limit}; const result = await rest('timeLineVisualizer/getInstants/count/' + applicationId, payload); return result.data.count; } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js index 94a47908..e09017db 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js @@ -8,7 +8,7 @@ import {createStructuredSelector} from "reselect"; import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' -class TimelineContainer extends Component { +class TimeLineInstantsContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, instants: PropTypes.instanceOf(Array).isRequired, @@ -18,18 +18,16 @@ class TimelineContainer extends Component { componentWillMount(){ const {dispatch} = this.props; - dispatch(getInstants()) - this.className = 'timeseries-chart'; + this.className = "timeseries-chart"; this.chart = new TimeLine(this.className, ()=>{}) // TODO: callback + dispatch(getInstants()); // TODO: urls, settings. } - componentWillReceiveProps(nextProps){ - if (this.props.instants == null) return; - - const {instants} = nextProps; - if (this.props.instants != instants) { + componentDidUpdate() { + const {instants} = this.props; + if (instants.length > 0) { this.chart.destroy(); - this.chart.instants(instants); + this.chart.instants(this.props.instants); } } @@ -43,12 +41,12 @@ class TimelineContainer extends Component { const {status, instants} = this.props; if (!status.done) { - return + return } - if (instants.length == 0) { + else if (instants.length == 0) { return - No events were loaded. Check the settings please. + No instants were loaded. Check the settings please. } @@ -62,4 +60,4 @@ const selector = createStructuredSelector({ status: instantsStatusSelector }); -export default connect(selector)(TimelineContainer); \ No newline at end of file +export default connect(selector)(TimeLineInstantsContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js index b99eb276..845642b9 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js @@ -1,3 +1,63 @@ -/** - * Created by vladislav on 6.5.17. - */ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { getIntervals, getIntervalsReset, intervalsSelector, intervalsStatusSelector } from '../ducks/intervals' +import { PromiseStatus } from '../../../core/models' +import PromiseResult from '../../../core/components/PromiseResult' +import TimeLine from '../misc/TimeLine' +import {createStructuredSelector} from "reselect"; +import CenteredMessage from '../../../../components/CenteredMessage' +import VisualizationMessage from '../components/VisualizationMessage' + +class TimeLineIntervalsContainer extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + intervals: PropTypes.instanceOf(Array).isRequired, + urls: PropTypes.instanceOf(Array).isRequired, + status: PropTypes.instanceOf(PromiseStatus).isRequired + }; + + componentWillMount(){ + const {dispatch} = this.props; + this.className = "timeseries-chart"; + this.chart = new TimeLine(this.className, ()=>{}) // TODO: callback + dispatch(getIntervals()); // TODO: urls, settings. + } + + componentDidUpdate() { + const {intervals} = this.props; + if (intervals.length > 0) { + this.chart.destroy(); + this.chart.intervals(this.props.intervals); + } + } + + componentWillUnmount() { + const {dispatch} = this.props; + dispatch(getIntervalsReset()); + this.chart.destroy(); + } + + render() { + const {status, intervals} = this.props; + + if (!status.done) { + return + } + + else if (intervals.length == 0) { + return + No intervals were loaded. Check the settings please. + + } + + require('../misc/TimeLineStyle.css'); + return
    + } +} + +const selector = createStructuredSelector({ + intervals: intervalsSelector, + status: intervalsStatusSelector +}); + +export default connect(selector)(TimeLineIntervalsContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js index 7bf4b5ad..aaa1384e 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js @@ -15,7 +15,7 @@ export const GET_INSTANTS_RESET = GET_INSTANTS + '_RESET'; export function getInstants() { return withApplicationId(id => { - const promise = api.getInstants(id,[],new Date("01-01-0000"), new Date("01-01-2010"),100); + const promise = api.getInstants(id,[],new Date("2000-01-01"), new Date("2018-01-01"),100); return createAction(GET_INSTANTS, { promise }); }); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js index a5d903a3..cc0f07a0 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js @@ -15,7 +15,7 @@ export const GET_INTERVALS_RESET = GET_INTERVALS + '_RESET'; export function getIntervals() { return withApplicationId(id => { - const promise = api.getIntervals(id,[],new Date("01-01-2000"), new Date("01-01-2010"),100); + const promise = api.getIntervals(id,[],new Date("2000-01-01"), new Date("2018-01-01"),100); return createAction(GET_INTERVALS, { promise }); }); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js index 82f4d165..6bda27b4 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js @@ -3,14 +3,13 @@ import moment from 'moment' import {getAvailableVerticalSpace} from "../../../../components/FillInScreen"; class TimeLine { - constructor(spaced, callback) { - var classd = spaced.replace(new RegExp(" "), "."); + constructor(classd, callback) { + this.classd = classd; - // Time helpers - function lessThanDay(d) { - return (d === "hours" || d === "minutes" || d === "seconds") ? true : false; - } + this.circles = function(){}; + this.rectangles = function(){}; + // === HELPERS === function getDate(d) { var date = moment(d); date.hour(1); @@ -61,11 +60,9 @@ class TimeLine { }; }; -// --------------------------------------------------------------------------------------------- -// ------------------------------------- Rendering --------------------------------------------- -// --------------------------------------------------------------------------------------------- - + // === RENDER === this.render = function (padding, drawFunc) { + // Constants var margin = { top: 10, right: 25, @@ -73,30 +70,33 @@ class TimeLine { left: 35 }; - var width = getAvailableVerticalSpace(document.getElementsByClassName(spaced)[0]); - var height = (lessThanDay(padding.pad)) ? (100 - margin.top - margin.bottom) : (300 - margin.top - margin.bottom); + var size = { + height: 18, + radius: 9, + rx:7, + ry:7 + }; + + // Check element existence + var element = document.getElementsByClassName(classd)[0]; + if (!element) return; + + // Axes + var width = getAvailableVerticalSpace(element); + var height = 300 - margin.top - margin.bottom; var x = d3.time.scale().range([0 + margin.right, width - margin.left]), - y = d3.time.scale() - .range([margin.top, height - margin.bottom - margin.top]); + y = d3.time.scale().range([margin.top, height - margin.bottom - margin.top]); - var ticks = width > 800 ? 8 : 4; + var xFormat = "%m/%d/%y", + yFormat = "%H:%M", + start = new Date(2012, 0, 1, 0, 0, 0, 0).getTime(), + stop = new Date(2012, 0, 1, 23, 59, 59, 59).getTime(); x.domain(d3.extent([padding.minDate, padding.maxDate])); + y.domain(d3.extent([start, stop])); - var xFormat, yFormat; - if (lessThanDay(padding.pad)) { - xFormat = "%H:%M"; - yFormat = "%m/%d/%y"; - y.domain(d3.extent([padding.minDate])); - } else { - xFormat = "%m/%d/%y"; - yFormat = "%H:%M"; - var start = new Date(2012, 0, 1, 0, 0, 0, 0).getTime(); - var stop = new Date(2012, 0, 1, 23, 59, 59, 59).getTime(); - y.domain(d3.extent([start, stop])); - } - + var ticks = width > 800 ? 8 : 4; var xAxis = d3.svg.axis().scale(x).orient("bottom") .ticks(ticks) .tickSize(-height, 0) @@ -107,6 +107,7 @@ class TimeLine { .tickSize(-width + margin.right, margin.left) .tickFormat(d3.time.format(yFormat)); + // SVG drawing var svg = d3.select("." + classd).append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom); @@ -125,9 +126,8 @@ class TimeLine { .attr("transform", "translate(" + margin.left + "," + margin.top + ")") .call(yAxis); - drawFunc(); - - this.circles = function(data, extract){ + // instants => circles + this.circles = function(data){ var circles = context.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") @@ -136,21 +136,19 @@ class TimeLine { .enter().append("circle") .attr("class", "circ") .attr("cx", function (d) { - var value = extract(d); - return (lessThanDay(padding.pad)) ? x(value) : x(getDate(value)); + return x(getDate(d.date)); }) .attr("cy", function (d, i) { - var value = extract(d); - return (lessThanDay(padding.pad)) ? y(getDate(value)) : y(getTime(value)); + return y(getTime(d.date)); }) - .attr("r", 9) + .attr("r", size.radius) .on("click", function (d) { callback(d); }); }; - //TODO: Check values... - this.rectangles = function(data, start,end){ + // intervals => rectangles + this.rectangles = function(data){ var rectangles = context.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")") @@ -159,44 +157,49 @@ class TimeLine { .enter().append("rect") .attr("class", "rect") .attr("x", function (d) { - var value = start(d); - return (lessThanDay(padding.pad)) ? x(value) : x(getDate(value)); + return x(getDate(d.begin)); }) .attr("y", function (d, i) { - var value = start(d); - return (lessThanDay(padding.pad)) ? y(getDate(value)) : y(getTime(value)); + return y(getTime(d.begin)); }) + .attr("rx", size.rx) + .attr("ry", size.ry) .attr("width", function(d){ - var value = end(d) - start(d); - return (lessThanDay(padding.pad)) ? x(value) : x(getDate(value)); - }) - .attr("height", function(d){ - var value = end(d) - start(d); - return (lessThanDay(padding.pad)) ? y(getDate(value) + 18) : y(getTime(value)); + var e = x(getDate(d.end)); + var b = x(getDate(d.begin)); + return ( e - b ) + 20; // TODO: No data, fixed intervals. }) + .attr("height", size.height) .on("click", function (d) { callback(d); }); - } + }; - this.destroy = function() { - d3.select("." + classd).removeAll(); - } + drawFunc(); } } instants(data) { var padding = this.timeRangePad(data.map(d=>d.date)); - var drawFunc = this.circles(data,d=>d.date); + var drawFunc = () => this.circles(data); this.render(padding,drawFunc); } intervals(data) { - var dates = data.map(d=>d.start).append(data.map(d=>d.end)); - var padding = this.timeRangePad(dates) + var begins = data.map(d=>d.begin) + var ends = data.map(d=>d.end); + var padding = this.timeRangePad(begins.concat(ends)); - var drawFunc = this.rectangles(data, d=>d.start, d=>d.end); + var drawFunc = () => this.rectangles(data); this.render(padding,drawFunc); } + + // SVG destroying + destroy(){ + var elements = d3.select("svg"); + if (elements != null){ + elements.remove(); + } + } } export default TimeLine; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js index 1946aa8a..04959791 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js @@ -2,7 +2,7 @@ import { Record } from 'immutable'; export const Interval = Record({ url: "url", - start: new Date(), + begin: new Date(), end: new Date() }); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js index 503c4692..375c2a8d 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js @@ -1,8 +1,10 @@ -import { combineReducers } from 'redux'; +import { combineReducers } from 'redux' import instants from './ducks/instants' +import intervals from './ducks/intervals' const rootReducer = combineReducers({ - instants + instants, + intervals, }); export default rootReducer; \ No newline at end of file From 021d19cb643f02d22ff356c8fa71d7fe2d16da77 Mon Sep 17 00:00:00 2001 From: vvancak Date: Mon, 8 May 2017 20:19:46 +0200 Subject: [PATCH 30/84] TimeLine: Added server support for get connection by type --- .../TimeLineVisualizerApiController.scala | 16 ++++++------- ...st.scala => ThingsConnectionRequest.scala} | 2 +- .../rdf/sparql/rgml/RgmlCountService.scala | 8 +++---- .../sparql/rgml/RgmlCountServiceImpl.scala | 20 +++++++++------- .../model/rdf/sparql/rgml/RgmlService.scala | 8 +++---- .../rdf/sparql/rgml/RgmlServiceImpl.scala | 24 ++++++++++++------- .../ThingToInstantConnectionExtractor.scala | 1 + .../ThingToIntervalConnectionExtractor.scala | 1 + ...oThingWithInstantConnectionExtractor.scala | 1 + ...ThingWithIntervalConnectionExtractor.scala | 1 + .../rdf/sparql/rgml/models/Connection.scala | 2 +- .../rgml/query/ThingsWithInstantQuery.scala | 11 ++++++--- .../rgml/query/ThingsWithIntervalQuery.scala | 11 ++++++--- .../ThingsWithThingsWithInstantQuery.scala | 15 ++++++++---- .../ThingsWithThingsWithIntervalQuery.scala | 16 +++++++++---- 15 files changed, 86 insertions(+), 51 deletions(-) rename src/app/model/assistant/rest/{ConnectionRequest.scala => ThingsConnectionRequest.scala} (64%) diff --git a/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala index 9839654e..092f0451 100644 --- a/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala +++ b/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala @@ -44,56 +44,56 @@ class TimeLineVisualizerApiController(implicit val inj: Injector) extends Visual def getThingWithIntervals(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request =>json => withEvaluation(ApplicationId(id)) { evaluation => - val thingsWithIntervals = rgmlService.thingsWithIntervals(evaluation, json.things, json.connections, json.limit) + val thingsWithIntervals = rgmlService.thingsWithIntervals(evaluation, json.things, json.thingTypes, json.connections, json.limit) Future(Ok(SuccessResponse(data = Seq("thingsWithIntervals" -> thingsWithIntervals)))) } } def getThingsWithIntervalsCount(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request => json => withEvaluation(ApplicationId(id)) { evaluation => - val count = rgmlCountService.thingsWithIntervals(evaluation, json.things, json.connections, json.limit) + val count = rgmlCountService.thingsWithIntervals(evaluation, json.things, json.thingTypes, json.connections, json.limit) Future(Ok(SuccessResponse(data = Seq("count" -> count)))) } } def getThingsWithInstants(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request =>json => withEvaluation(ApplicationId(id)) { evaluation => - val thingsWithInstants = rgmlService.thingsWithInstants(evaluation, json.things, json.connections, json.limit) + val thingsWithInstants = rgmlService.thingsWithInstants(evaluation, json.things, json.thingTypes, json.connections, json.limit) Future(Ok(SuccessResponse(data = Seq("thingsWithInstants" -> thingsWithInstants)))) } } def getThingsWithInstantsCount(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request => json => withEvaluation(ApplicationId(id)) { evaluation => - val count = rgmlCountService.thingsWithInstants(evaluation, json.things, json.connections, json.limit) + val count = rgmlCountService.thingsWithInstants(evaluation, json.things, json.thingTypes, json.connections, json.limit) Future(Ok(SuccessResponse(data = Seq("count" -> count)))) } } def getThingsWithThingsWithIntervals(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request =>json => withEvaluation(ApplicationId(id)) { evaluation => - val thingsWithThingsWithIntervals = rgmlService.thingsWithThingsWithIntervals(evaluation, json.things, json.connections, json.limit) + val thingsWithThingsWithIntervals = rgmlService.thingsWithThingsWithIntervals(evaluation, json.things, json.thingTypes, json.connections, json.limit) Future(Ok(SuccessResponse(data = Seq("thingsWithThingsWithIntervals" -> thingsWithThingsWithIntervals)))) } } def getThingsWithThingsWithIntervalsCount(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request => json => withEvaluation(ApplicationId(id)) { evaluation => - val count = rgmlCountService.thingsWithThingsWithIntervals(evaluation, json.things, json.connections, json.limit) + val count = rgmlCountService.thingsWithThingsWithIntervals(evaluation, json.things, json.thingTypes, json.connections, json.limit) Future(Ok(SuccessResponse(data = Seq("count" -> count)))) } } def getThingsWithThingsWithInstants(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request =>json => withEvaluation(ApplicationId(id)) { evaluation => - val thingsWithThingsWithInstants = rgmlService.thingsWithThingsWithInstants(evaluation, json.things, json.connections, json.limit) + val thingsWithThingsWithInstants = rgmlService.thingsWithThingsWithInstants(evaluation, json.things, json.thingTypes, json.connections, json.limit) Future(Ok(SuccessResponse(data = Seq("thingsWithThingsWithInstants" -> thingsWithThingsWithInstants)))) } } def getThingsWithThingsWithInstantsCount(id: Long) = RestAsyncAction[ThingsConnectionsRequest] { implicit request => json => withEvaluation(ApplicationId(id)) { evaluation => - val count = rgmlCountService.thingsWithThingsWithInstants(evaluation, json.things, json.connections, json.limit) + val count = rgmlCountService.thingsWithThingsWithInstants(evaluation, json.things, json.thingTypes, json.connections, json.limit) Future(Ok(SuccessResponse(data = Seq("count" -> count)))) } } diff --git a/src/app/model/assistant/rest/ConnectionRequest.scala b/src/app/model/assistant/rest/ThingsConnectionRequest.scala similarity index 64% rename from src/app/model/assistant/rest/ConnectionRequest.scala rename to src/app/model/assistant/rest/ThingsConnectionRequest.scala index 6e08e5a2..17d3570f 100644 --- a/src/app/model/assistant/rest/ConnectionRequest.scala +++ b/src/app/model/assistant/rest/ThingsConnectionRequest.scala @@ -3,7 +3,7 @@ package model.assistant.rest import play.api.libs.json.Json object ThingsConnectionRequest { - case class ThingsConnectionsRequest(things: Seq[String], connections: Seq[String], limit: Int) + case class ThingsConnectionsRequest(things: Seq[String], thingTypes: Seq[String], connections: Seq[String], limit: Int) implicit val writes = Json.writes[ThingsConnectionsRequest] implicit val reads = Json.reads[ThingsConnectionsRequest] } diff --git a/src/app/model/rdf/sparql/rgml/RgmlCountService.scala b/src/app/model/rdf/sparql/rgml/RgmlCountService.scala index 32f7fcfe..c2003e52 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlCountService.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlCountService.scala @@ -8,8 +8,8 @@ import play.api.db.slick.Session trait RgmlCountService { def intervals(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Count] def instants(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Count] - def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] - def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] - def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] - def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] + def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] + def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] + def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] + def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] } diff --git a/src/app/model/rdf/sparql/rgml/RgmlCountServiceImpl.scala b/src/app/model/rdf/sparql/rgml/RgmlCountServiceImpl.scala index c2891efe..63fc9059 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlCountServiceImpl.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlCountServiceImpl.scala @@ -30,43 +30,47 @@ class RgmlCountServiceImpl(implicit val inj: Injector) extends RgmlCountService new CountExtractor()) } - override def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { + override def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { val maybeLimit = if (limit > 0) Some(limit) else None val maybeThingUrls = if (thingUrls.nonEmpty) Some(thingUrls) else None + val maybeThingTypes = if (thingTypes.nonEmpty) Some(thingTypes) else None val maybeConnUrls = if (connectionUrls.nonEmpty) Some(connectionUrls) else None sparqlEndpointService.getCount( evaluationToSparqlEndpoint(evaluation), - new ThingsWithIntervalQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingsWithIntervalQuery(maybeThingUrls, maybeThingTypes, maybeConnUrls, maybeLimit), new CountExtractor()) } - override def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { + override def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { val maybeLimit = if (limit > 0) Some(limit) else None val maybeThingUrls = if (thingUrls.nonEmpty) Some(thingUrls) else None + val maybeThingTypes = if (thingTypes.nonEmpty) Some(thingTypes) else None val maybeConnUrls = if (connectionUrls.nonEmpty) Some(connectionUrls) else None sparqlEndpointService.getCount( evaluationToSparqlEndpoint(evaluation), - new ThingsWithInstantQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingsWithInstantQuery(maybeThingUrls, maybeThingTypes, maybeConnUrls, maybeLimit), new CountExtractor()) } - override def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { + override def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { val maybeLimit = if (limit > 0) Some(limit) else None val maybeThingUrls = if (thingUrls.nonEmpty) Some(thingUrls) else None + val maybeThingTypes = if (thingTypes.nonEmpty) Some(thingTypes) else None val maybeConnUrls = if (connectionUrls.nonEmpty) Some(connectionUrls) else None sparqlEndpointService.getCount( evaluationToSparqlEndpoint(evaluation), - new ThingsWithThingsWithIntervalQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingsWithThingsWithIntervalQuery(maybeThingUrls, maybeThingTypes, maybeConnUrls, maybeLimit), new CountExtractor()) } - override def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { + override def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Count] = { val maybeLimit = if (limit > 0) Some(limit) else None val maybeThingUrls = if (thingUrls.nonEmpty) Some(thingUrls) else None + val maybeThingTypes = if (thingTypes.nonEmpty) Some(thingTypes) else None val maybeConnUrls = if (connectionUrls.nonEmpty) Some(connectionUrls) else None sparqlEndpointService.getCount( evaluationToSparqlEndpoint(evaluation), - new ThingsWithThingsWithInstantQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingsWithThingsWithInstantQuery(maybeThingUrls, maybeThingTypes, maybeConnUrls, maybeLimit), new CountExtractor()) } } diff --git a/src/app/model/rdf/sparql/rgml/RgmlService.scala b/src/app/model/rdf/sparql/rgml/RgmlService.scala index 427d4032..41c7aa3d 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlService.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlService.scala @@ -21,8 +21,8 @@ trait RgmlService { def sampleNodesWithForestFire( evaluation: PipelineEvaluation, size: Int, useWeights: Boolean = true, pF: Double = 0.2, pB: Double = 0.05)(implicit session: Session): Option[Seq[Node]] def intervals(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Interval]] def instants(evaluation: PipelineEvaluation, start: Date, end: Date, urls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Instant]] - def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] - def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] - def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] - def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] + def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] + def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] + def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] + def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] } diff --git a/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala b/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala index 834660a9..2e9d0912 100644 --- a/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala +++ b/src/app/model/rdf/sparql/rgml/RgmlServiceImpl.scala @@ -432,43 +432,49 @@ class RgmlServiceImpl(implicit val inj: Injector) extends RgmlService with Injec new InstantExtractor()) } - override def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { + override def thingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { val maybeLimit = if (limit > 0) Some(limit) else None val maybeThingUrls = if (thingUrls.size > 0) Some(thingUrls) else None + val maybeThingTypes = if (thingTypes.size > 0) Some(thingTypes) else None val maybeConnUrls = if (connectionUrls.size > 0) Some(connectionUrls) else None - sparqlEndpointService.getResult( + + val result = sparqlEndpointService.getResult( evaluationToSparqlEndpoint(evaluation), - new ThingsWithIntervalQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingsWithIntervalQuery(maybeThingUrls, maybeThingTypes, maybeConnUrls, maybeLimit), new ThingToIntervalConnectionExtractor()) + return result; } - override def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { + override def thingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { val maybeLimit = if (limit > 0) Some(limit) else None val maybeThingUrls = if (thingUrls.size > 0) Some(thingUrls) else None + val maybeThingTypes = if (thingTypes.size > 0) Some(thingTypes) else None val maybeConnUrls = if (connectionUrls.size > 0) Some(connectionUrls) else None sparqlEndpointService.getResult( evaluationToSparqlEndpoint(evaluation), - new ThingsWithInstantQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingsWithInstantQuery(maybeThingUrls, maybeThingTypes, maybeConnUrls, maybeLimit), new ThingToInstantConnectionExtractor()) } - override def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { + override def thingsWithThingsWithIntervals(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { val maybeLimit = if (limit > 0) Some(limit) else None val maybeThingUrls = if (thingUrls.size > 0) Some(thingUrls) else None + val maybeThingTypes = if (thingTypes.size > 0) Some(thingTypes) else None val maybeConnUrls = if (connectionUrls.size > 0) Some(connectionUrls) else None sparqlEndpointService.getResult( evaluationToSparqlEndpoint(evaluation), - new ThingsWithThingsWithIntervalQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingsWithThingsWithIntervalQuery(maybeThingUrls, maybeThingTypes, maybeConnUrls, maybeLimit), new ThingToThingWithIntervalConnectionExtractor()) } - override def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { + override def thingsWithThingsWithInstants(evaluation: PipelineEvaluation, thingUrls: Seq[String], thingTypes: Seq[String], connectionUrls: Seq[String], limit: Int)(implicit session: Session): Option[Seq[Connection]] = { val maybeLimit = if (limit > 0) Some(limit) else None val maybeThingUrls = if (thingUrls.size > 0) Some(thingUrls) else None + val maybeThingTypes = if (thingTypes.size > 0) Some(thingTypes) else None val maybeConnUrls = if (connectionUrls.size > 0) Some(connectionUrls) else None sparqlEndpointService.getResult( evaluationToSparqlEndpoint(evaluation), - new ThingsWithThingsWithInstantQuery(maybeThingUrls, maybeConnUrls, maybeLimit), + new ThingsWithThingsWithInstantQuery(maybeThingUrls, maybeThingTypes, maybeConnUrls, maybeLimit), new ThingToThingWithInstantConnectionExtractor()) } } diff --git a/src/app/model/rdf/sparql/rgml/extractor/ThingToInstantConnectionExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/ThingToInstantConnectionExtractor.scala index 1049431c..791dc60c 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/ThingToInstantConnectionExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/ThingToInstantConnectionExtractor.scala @@ -13,6 +13,7 @@ class ThingToInstantConnectionExtractor extends QueryExecutionResultExtractor[Th val resList = input.execSelect().toList Some(resList.map(e => new Connection( e.getResource("thing").getURI, + e.getResource("thingType").getURI, e.getResource("connection").getURI, e.getResource("instant").getURI ))) diff --git a/src/app/model/rdf/sparql/rgml/extractor/ThingToIntervalConnectionExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/ThingToIntervalConnectionExtractor.scala index b1251f36..7d54d20f 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/ThingToIntervalConnectionExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/ThingToIntervalConnectionExtractor.scala @@ -13,6 +13,7 @@ class ThingToIntervalConnectionExtractor extends QueryExecutionResultExtractor[T val resList = input.execSelect().toList Some(resList.map(e => new Connection( e.getResource("thing").getURI, + e.getResource("thingType").getURI, e.getResource("connection").getURI, e.getResource("interval").getURI ))) diff --git a/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithInstantConnectionExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithInstantConnectionExtractor.scala index 19c26a00..16fd1684 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithInstantConnectionExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithInstantConnectionExtractor.scala @@ -14,6 +14,7 @@ class ThingToThingWithInstantConnectionExtractor val resList = input.execSelect().toList Some(resList.map(e => new Connection( e.getResource("outerThing").getURI, + e.getResource("outerThingType").getURI, e.getResource("connection").getURI, e.getResource("innerThing").getURI ))) diff --git a/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithIntervalConnectionExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithIntervalConnectionExtractor.scala index 539cf44f..5b6506b0 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithIntervalConnectionExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/ThingToThingWithIntervalConnectionExtractor.scala @@ -14,6 +14,7 @@ class ThingToThingWithIntervalConnectionExtractor val resList = input.execSelect().toList Some(resList.map(e => new Connection( e.getResource("outerThing").getURI, + e.getResource("outerThingType").getURI, e.getResource("connection").getURI, e.getResource("innerThing").getURI ))) diff --git a/src/app/model/rdf/sparql/rgml/models/Connection.scala b/src/app/model/rdf/sparql/rgml/models/Connection.scala index 87677969..401afcda 100644 --- a/src/app/model/rdf/sparql/rgml/models/Connection.scala +++ b/src/app/model/rdf/sparql/rgml/models/Connection.scala @@ -1,3 +1,3 @@ package model.rdf.sparql.rgml.models -case class Connection(outerUrl: String, connectionUrl: String, innerUrl: String) +case class Connection(outer: String, outerType: String, connection: String, inner: String) diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala index dcb2c431..53f5d2c9 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala @@ -2,10 +2,13 @@ package model.rdf.sparql.rgml.query import model.rdf.sparql.query.{SparqlCountQuery} -class ThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { +class ThingsWithInstantQuery( maybeThingsUrls: Option[Seq[String]], + maybeThingsTypes: Option[Seq[String]], + maybeConnectionUrls: Option[Seq[String]], + maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { - val select = "SELECT ?thing ?connection ?instant" - val group = "GROUP BY ?thing ?connection ?instant" + val select = "SELECT ?thing ?thingType ?connection ?instant" + val group = "GROUP BY ?thing ?thingType ?connection ?instant" val limit = QueryHelpers.limit(maybeLimit) return query(select,group,limit) } @@ -24,10 +27,12 @@ class ThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], maybeConnecti |${select} |WHERE { | ?thing ?connection ?instant. + | ?thing a ?thingType. | | ?instant time:inXSDDateTime ?date. | | ${QueryHelpers.limitValues("thing", maybeThingsUrls)} + | ${QueryHelpers.limitValues("thingType", maybeThingsTypes)} | ${QueryHelpers.limitValues("connection", maybeConnectionUrls)} |} | diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala index 8e960303..006460da 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala @@ -2,10 +2,13 @@ package model.rdf.sparql.rgml.query import model.rdf.sparql.query.{SparqlCountQuery} -class ThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { +class ThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], + maybeThingsTypes: Option[Seq[String]], + maybeConnectionUrls: Option[Seq[String]], + maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { - val select = "SELECT ?thing ?connection ?interval" - val group = "GROUP BY ?thing ?connection ?interval" + val select = "SELECT ?thing ?thingType ?connection ?interval" + val group = "GROUP BY ?thing ?thingType ?connection ?interval" val limit = QueryHelpers.limit(maybeLimit) return query(select,group,limit) } @@ -24,11 +27,13 @@ class ThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], maybeConnect |${select} |WHERE { | ?thing ?connection ?interval. + | ?thing a ?thingType. | | ?interval time:hasBeginning ?beginning . | ?interval time:hasEnd ?end . | | ${QueryHelpers.limitValues("thing", maybeThingsUrls)} + | ${QueryHelpers.limitValues("thingType", maybeThingsTypes)} | ${QueryHelpers.limitValues("connection", maybeConnectionUrls)} |} | diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala index c3e9b7a1..558c6dcc 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala @@ -2,17 +2,19 @@ package model.rdf.sparql.rgml.query import model.rdf.sparql.query.{SparqlCountQuery} -class ThingsWithThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { - +class ThingsWithThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], + maybeThingsTypes: Option[Seq[String]], + maybeConnectionUrls: Option[Seq[String]], + maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { - val select = "SELECT ?outerThing ?connection ?innerThing" - val group = "GROUP BY ?outerThing ?connection ?innerThing" + val select = "SELECT ?outerThing ?outerThingType ?connection ?innerThing" + val group = "GROUP BY ?outerThing ?outerThingType ?connection ?innerThing" val limit = QueryHelpers.limit(maybeLimit) return query(select,group,limit) } def getCount: String = { - val select = "SELECT COUNT(?thing) AS ?count" + val select = "SELECT COUNT(?outerThing) AS ?count" val group = "" val limit = "" return query(select,group,limit) @@ -26,11 +28,14 @@ class ThingsWithThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], may |WHERE { | ?outerThing ?connection ?innerThing. | + | ?outerThing a ?outerThingType. + | | ?innerThing ?hasInterval ?instant. | | ?instant time:inXSDDateTime ?date. | | ${QueryHelpers.limitValues("outerThing", maybeThingsUrls)} + | ${QueryHelpers.limitValues("outerThingType", maybeThingsTypes)} | ${QueryHelpers.limitValues("connection", maybeConnectionUrls)} |} | diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala index 19292e7d..77249d87 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala @@ -2,10 +2,13 @@ package model.rdf.sparql.rgml.query import model.rdf.sparql.query.{SparqlCountQuery} -class ThingsWithThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], maybeConnectionUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { +class ThingsWithThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], + maybeThingsTypes: Option[Seq[String]], + maybeConnectionUrls: Option[Seq[String]], + maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { - val select = "SELECT ?outerThing ?connection ?innerThing" - val group = "GROUP BY ?outerThing ?connection ?innerThing" + val select = "SELECT ?outerThing ?outerThingType ?connection ?innerThing" + val group = "GROUP BY ?outerThing ?outerThingType ?connection ?innerThing" val limit = QueryHelpers.limit(maybeLimit) return query(select,group,limit) } @@ -25,13 +28,16 @@ class ThingsWithThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], ma |WHERE { | ?outerThing ?connection ?innerThing. | + | ?outerThing a ?outerThingType. + | | ?innerThing ?hasInterval ?interval. | | ?interval time:hasBeginning ?beginning . | ?interval time:hasEnd ?end . | - | ${QueryHelpers.limitValues("outerThing",maybeThingsUrls)} - | ${QueryHelpers.limitValues("connection",maybeConnectionUrls)} + | ${QueryHelpers.limitValues("outerThing", maybeThingsUrls)} + | ${QueryHelpers.limitValues("outerThingType", maybeThingsTypes)} + | ${QueryHelpers.limitValues("connection", maybeConnectionUrls)} |} | |${group} From b5f9b4fd98038e5c48a721c52d2acd1eced4c074 Mon Sep 17 00:00:00 2001 From: vvancak Date: Mon, 8 May 2017 20:21:02 +0200 Subject: [PATCH 31/84] TimeLine: Things Connected to Intervals/Instants - init implementation --- .../modules/visualizers/timeline/api.js | 40 ++--- .../FirstLevelConnectionContainer.js | 109 ++++++++++++++ .../SecondLevelConnectionContainer.js | 103 +++++++++++++ .../containers/TimeLineInstantsContainer.js | 37 ++++- .../containers/TimeLineIntervalsContainer.js | 40 +++-- .../visualizers/timeline/ducks/firstLevel.js | 50 +++++++ .../visualizers/timeline/ducks/instants.js | 4 +- .../visualizers/timeline/ducks/intervals.js | 4 +- .../visualizers/timeline/ducks/secondLevel.js | 50 +++++++ .../timeline/ducks/selectedConnFirstLevel.js | 44 ++++++ .../timeline/ducks/selectedConnSecondLevel.js | 44 ++++++ .../ducks/selectedThingSecondLevel.js | 44 ++++++ .../timeline/ducks/selectedTypeFirstLevel.js | 44 ++++++ .../visualizers/timeline/ducks/utils.js | 11 ++ .../timeline/misc/ConfigToolbar.js | 137 ++++++++++++++++++ .../visualizers/timeline/misc/TimeLine.js | 2 +- .../modules/visualizers/timeline/models.js | 5 +- .../modules/visualizers/timeline/reducer.js | 12 ++ 18 files changed, 736 insertions(+), 44 deletions(-) create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/firstLevel.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/secondLevel.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedConnFirstLevel.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedConnSecondLevel.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedThingSecondLevel.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedTypeFirstLevel.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/utils.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ConfigToolbar.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js index 8bfd34aa..d29d83e5 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js @@ -12,25 +12,25 @@ export async function getInstants(applicationId, urls, begin, end, limit) { return result.data.instants; } -export async function getThingsWIntervals(applicationId, things, connections, limit) { - let payload = {"things":things, "connections":connections, "limit":limit}; +export async function getThingsWIntervals(applicationId, things, thingTypes, connections, limit) { + let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit":limit}; const result = await rest('timeLineVisualizer/getThingsWIntervals/' + applicationId, payload); - return result.data.intervals; + return result.data.thingsWithIntervals; } -export async function getThingsWInstants(applicationId, things, connections, limit) { - let payload = {"things":things, "connections":connections, "limit":limit}; +export async function getThingsWInstants(applicationId, things, thingTypes, connections, limit) { + let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit":limit}; const result = await rest('timeLineVisualizer/getThingsWInstants/' + applicationId, payload); - return result.data.instants; + return result.data.thingsWithInstants; } -export async function getThingsWThingsWIntervals(applicationId, things, connections, limit) { - let payload = {"things": things, "connections": connections, "limit": limit}; +export async function getThingsWThingsWIntervals(applicationId, things, thingTypes, connections, limit) { + let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": limit}; const result = await rest('timeLineVisualizer/getThingsWThingsWIntervals/' + applicationId, payload); - return result.data.intervals; + return result.data.thingsWithThingsWithIntervals; } -export async function getThingsWThingsWInstants(applicationId, things, connections, limit) { - let payload = {"things": things, "connections": connections, "limit": limit}; +export async function getThingsWThingsWInstants(applicationId, things, thingTypes, connections, limit) { + let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": limit}; const result = await rest('timeLineVisualizer/getThingsWThingsWInstants/' + applicationId, payload); - return result.data.instants; + return result.data.thingsWithThingsWithInstants; } export async function getIntervalsCount(applicationId, urls, begin, end, limit) { @@ -45,23 +45,23 @@ export async function getInstantsCount(applicationId, urls, begin, end, limit) { return result.data.count; } -export async function getThingsWIntervalsCount(applicationId, things, connections, limit) { - let payload = {"things":things, "connections":connections, "limit":limit}; +export async function getThingsWIntervalsCount(applicationId, things, thingTypes, connections, limit) { + let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit":limit}; const result = await rest('timeLineVisualizer/getThingsWIntervals/count/' + applicationId, payload); return result.data.count; } -export async function getThingsWInstantsCount(applicationId, things, connections, limit) { - let payload = {"things":things, "connections":connections, "limit":limit}; +export async function getThingsWInstantsCount(applicationId, things, thingTypes, connections, limit) { + let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit":limit}; const result = await rest('timeLineVisualizer/getThingsWInstants/count/' + applicationId, payload); return result.data.count; } -export async function getThingsWThingsWIntervalsCount(applicationId, things, connections, limit) { - let payload = {"things": things, "connections": connections, "limit": limit}; +export async function getThingsWThingsWIntervalsCount(applicationId, things, thingTypes, connections, limit) { + let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": limit}; const result = await rest('timeLineVisualizer/getThingsWThingsWIntervals/count/' + applicationId, payload); return result.data.count; } -export async function getThingsWThingsWInstantsCount(applicationId, things, connections, limit) { - let payload = {"things": things, "connections": connections, "limit": limit}; +export async function getThingsWThingsWInstantsCount(applicationId, things, thingTypes, connections, limit) { + let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": limit}; const result = await rest('timeLineVisualizer/getThingsWThingsWInstants/count/' + applicationId, payload); return result.data.count; } \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js new file mode 100644 index 00000000..86b28241 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js @@ -0,0 +1,109 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { getFirstLevelReset, firstLevelSelector, firstLevelStatusSelector } from '../ducks/firstLevel' +import { secondLevelSelector } from '../ducks/secondLevel' +import { setSelectTypeFL, setUnSelectTypeFL, getSelectedTypeFLReset, selectedTypeFLSelector } from '../ducks/selectedTypeFirstLevel' +import { setSelectConnFL, setUnSelectConnFL, getSelectedConnFLReset, selectedConnFLSelector } from '../ducks/selectedConnFirstLevel' +import { PromiseStatus } from '../../../core/models' +import { createStructuredSelector } from "reselect"; + +import PromiseResult from '../../../core/components/PromiseResult' +import ConfigToolbar from '../misc/ConfigToolbar' +import CenteredMessage from '../../../../components/CenteredMessage' +import VisualizationMessage from '../components/VisualizationMessage' + +class FirstLevelConnectionContainer extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + + // Levels + firstLevel: PropTypes.instanceOf(Array).isRequired, + secondLevel: PropTypes.instanceOf(Array).isRequired, + + // Level loading + firstLevelLoader: PropTypes.func.isRequired, + status: PropTypes.instanceOf(PromiseStatus).isRequired, + + // Value selectors + selectedTypeFL: PropTypes.instanceOf(Array).isRequired, + selectedConnFL: PropTypes.instanceOf(Array).isRequired + + //TODO Limiter + }; + + componentWillMount(){ + this.load(); + } + + componentWillUnmount() { + const {dispatch} = this.props; + + dispatch(getFirstLevelReset()); + dispatch(getSelectedTypeFLReset()); + dispatch(getSelectedConnFLReset()); + } + + load(){ + const{dispatch, firstLevelLoader, secondLevel, selectedTypeFL, selectedConnFL} = this.props; + + var urls = secondLevel.map(l=>l.inner); + dispatch(firstLevelLoader(urls, selectedTypeFL, selectedConnFL, 100)); + } + + reset(){ + const{dispatch, firstLevelLoader, secondLevel} = this.props; + + dispatch(getSelectedTypeFLReset()); + dispatch(getSelectedConnFLReset()); + + var urls = secondLevel.map(l=>l.inner); + dispatch(firstLevelLoader(urls, [], [], 100)) + } + + render() { + const {dispatch, status, firstLevel, selectedTypeFL, selectedConnFL} = this.props; + + if (!status.done) { + return + } + + else if (firstLevel.length == 0) { + return + No connected things were loaded. Check the settings please. + + } + + return
    + t.outerType} + getValue={t=>t.outerType} + selectedKeys={selectedTypeFL} + onChecked={k=>dispatch(setSelectTypeFL(k))} + onUnchecked={k=>dispatch(setUnSelectTypeFL(k))} + /> + t.connection} + getValue={t=>t.connection} + selectedKeys={selectedConnFL} + onChecked={k=>dispatch(setSelectConnFL(k))} + onUnchecked={k=>dispatch(setUnSelectConnFL(k))} + /> + this.load()}/> + this.reset()}/> +
    + } +} + +const selector = createStructuredSelector({ + firstLevel: firstLevelSelector, + secondLevel: secondLevelSelector, + status: firstLevelStatusSelector, + selectedTypeFL: selectedTypeFLSelector, + selectedConnFL: selectedConnFLSelector +}); + +export default connect(selector)(FirstLevelConnectionContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js new file mode 100644 index 00000000..fa10258d --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js @@ -0,0 +1,103 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { getSecondLevelReset, secondLevelSelector, secondLevelStatusSelector } from '../ducks/secondLevel' +import { setSelectThingSL, setUnSelectThingSL, getSelectedThingSLReset, selectedThingSLSelector } from '../ducks/selectedThingSecondLevel' +import { setSelectConnSL, setUnSelectConnSL, getSelectedConnSLReset, selectedConnSLSelector } from '../ducks/selectedConnSecondLevel' +import { PromiseStatus } from '../../../core/models' +import { createStructuredSelector } from "reselect"; + +import PromiseResult from '../../../core/components/PromiseResult' +import ConfigToolbar from '../misc/ConfigToolbar' +import CenteredMessage from '../../../../components/CenteredMessage' +import VisualizationMessage from '../components/VisualizationMessage' + +class SecondLevelConnectionContainer extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + + // Levels + secondLevel: PropTypes.instanceOf(Array).isRequired, + + // Level loading + secondLevelLoader: PropTypes.func.isRequired, + status: PropTypes.instanceOf(PromiseStatus).isRequired, + + // Value selectors + selectedThingSL: PropTypes.instanceOf(Array).isRequired, + selectedConnSL: PropTypes.instanceOf(Array).isRequired + + //TODO Limiter + }; + + componentWillMount(){ + this.load(); + } + + componentWillUnmount() { + const {dispatch} = this.props; + + dispatch(getSecondLevelReset()); + dispatch(getSelectedThingSLReset()); + dispatch(getSelectedConnSLReset()); + } + + load(){ + const{dispatch, secondLevelLoader, selectedThingSL, selectedConnSL} = this.props; + dispatch(secondLevelLoader(selectedThingSL, [], selectedConnSL, 100)); + } + + reset(){ + const{dispatch, secondLevelLoader} = this.props; + + dispatch(getSelectedThingSLReset()); + dispatch(getSelectedConnSLReset()); + + dispatch(secondLevelLoader([],[],[],100)) + } + + render() { + const {dispatch, status, secondLevel, selectedThingSL, selectedConnSL} = this.props; + + if (!status.done) { + return + } + + else if (secondLevel.length == 0) { + return + No connected things were loaded. Check the settings please. + + } + + return
    + t.outer} + getValue={t=>t.outer} + selectedKeys={selectedThingSL} + onChecked={k=>dispatch(setSelectThingSL(k))} + onUnchecked={k=>dispatch(setUnSelectThingSL(k))} + /> + t.connection} + getValue={t=>t.connection} + selectedKeys={selectedConnSL} + onChecked={k=>dispatch(setSelectConnSL(k))} + onUnchecked={k=>dispatch(setUnSelectConnSL(k))} + /> + this.load()}/> + this.reset()}/> +
    + } +} + +const selector = createStructuredSelector({ + secondLevel: secondLevelSelector, + status: secondLevelStatusSelector, + selectedThingSL: selectedThingSLSelector, + selectedConnSL: selectedConnSLSelector +}); + +export default connect(selector)(SecondLevelConnectionContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js index e09017db..89d363df 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js @@ -1,31 +1,51 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import { getInstants, getInstantsReset, instantsSelector, instantsStatusSelector } from '../ducks/instants' +import { firstLevelSelector } from '../ducks/firstLevel' import { PromiseStatus } from '../../../core/models' +import {createStructuredSelector} from "reselect"; + import PromiseResult from '../../../core/components/PromiseResult' import TimeLine from '../misc/TimeLine' -import {createStructuredSelector} from "reselect"; import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' class TimeLineInstantsContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, + + // Levels + firstLevel: PropTypes.instanceOf(Array).isRequired, + + // Instants loading instants: PropTypes.instanceOf(Array).isRequired, - urls: PropTypes.instanceOf(Array).isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired + + // TODO limit }; componentWillMount(){ - const {dispatch} = this.props; this.className = "timeseries-chart"; - this.chart = new TimeLine(this.className, ()=>{}) // TODO: callback - dispatch(getInstants()); // TODO: urls, settings. + this.chart = new TimeLine(this.className, ()=>{}); // TODO: callback + + this.begin = new Date("2000-01-01"); + this.end = new Date("2018-01-01"); + + this.props.dispatch(getInstants([], this.start, this.end, 100)) + } + + componentWillReceiveProps(nextProps) { + const {dispatch, firstLevel} = this.props; + + if (firstLevel != nextProps.firstLevel) { + var urls = nextProps.firstLevel.map(t => t.inner); + dispatch(getInstants(urls, this.begin, this.end, 100)); + } } componentDidUpdate() { - const {instants} = this.props; - if (instants.length > 0) { + const { instants, status } = this.props; + if (status.done && instants.length > 0) { this.chart.destroy(); this.chart.instants(this.props.instants); } @@ -57,7 +77,8 @@ class TimeLineInstantsContainer extends Component { const selector = createStructuredSelector({ instants: instantsSelector, - status: instantsStatusSelector + status: instantsStatusSelector, + firstLevel: firstLevelSelector }); export default connect(selector)(TimeLineInstantsContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js index 845642b9..7ec1c6e5 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js @@ -1,31 +1,51 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import { getIntervals, getIntervalsReset, intervalsSelector, intervalsStatusSelector } from '../ducks/intervals' +import { firstLevelSelector } from '../ducks/firstLevel' import { PromiseStatus } from '../../../core/models' +import {createStructuredSelector} from "reselect"; + import PromiseResult from '../../../core/components/PromiseResult' import TimeLine from '../misc/TimeLine' -import {createStructuredSelector} from "reselect"; import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' class TimeLineIntervalsContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, + + // Levels + firstLevel: PropTypes.instanceOf(Array).isRequired, + + // Intervals loading intervals: PropTypes.instanceOf(Array).isRequired, - urls: PropTypes.instanceOf(Array).isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired + + // TODO limit }; componentWillMount(){ - const {dispatch} = this.props; this.className = "timeseries-chart"; - this.chart = new TimeLine(this.className, ()=>{}) // TODO: callback - dispatch(getIntervals()); // TODO: urls, settings. + this.chart = new TimeLine(this.className, ()=>{}); // TODO: callback + + this.begin = new Date("2000-01-01"); + this.end = new Date("2018-01-01"); + + this.props.dispatch(getIntervals([], this.start, this.end, 100)) + } + + componentWillReceiveProps(nextProps) { + const {dispatch, firstLevel} = this.props; + + if (firstLevel != nextProps.firstLevel) { + var urls = nextProps.firstLevel.map(t => t.inner); + dispatch(getIntervals(urls, this.begin, this.end, 100)); + } } componentDidUpdate() { - const {intervals} = this.props; - if (intervals.length > 0) { + const { intervals, status } = this.props; + if (status.done && intervals.length > 0) { this.chart.destroy(); this.chart.intervals(this.props.intervals); } @@ -37,11 +57,12 @@ class TimeLineIntervalsContainer extends Component { this.chart.destroy(); } + render() { const {status, intervals} = this.props; if (!status.done) { - return + return } else if (intervals.length == 0) { @@ -57,7 +78,8 @@ class TimeLineIntervalsContainer extends Component { const selector = createStructuredSelector({ intervals: intervalsSelector, - status: intervalsStatusSelector + status: intervalsStatusSelector, + firstLevel: firstLevelSelector }); export default connect(selector)(TimeLineIntervalsContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/firstLevel.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/firstLevel.js new file mode 100644 index 00000000..c4dd8e9b --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/firstLevel.js @@ -0,0 +1,50 @@ +import createAction from '../../../../misc/createAction' +import withApplicationId from '../../../app/misc/withApplicationId' +import prefix from '../prefix' +import * as api from '../api' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { Connection } from '../models' +import { createSelector } from 'reselect' +import { createPromiseStatusSelector } from '../../../core/ducks/promises' +import moduleSelector from '../selector' + +// Actions +export const GET_TFL = prefix('GET_THINGS_FIRST'); +export const GET_TFL_SUCCESS = GET_TFL + '_SUCCESS'; +export const GET_TFL_RESET = GET_TFL + '_RESET'; + +export function getFirstLevelIntervals(things, thingTypes, connections, limit) { + return withApplicationId(id => { + const promise = api.getThingsWIntervals(id, things, thingTypes, connections,limit); + return createAction(GET_TFL, { promise }); + }); +} + +export function getFirstLevelInstants(things, thingTypes, connections, limit) { + return withApplicationId(id => { + const promise = api.getThingsWInstants(id, things, thingTypes, connections,limit); + return createAction(GET_TFL, { promise }); + }); +} + +export function getFirstLevelReset() { + return createAction(GET_TFL_RESET); +} + +// Reducer +const initialState = []; +export default function firstLevelReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_TFL_RESET: + return initialState; + case GET_TFL_SUCCESS: + return action.payload.map(i=>new Connection(i)); + } + return state; +}; + +// Selectors +export const firstLevelStatusSelector = createPromiseStatusSelector(GET_TFL); +export const firstLevelSelector = createSelector([moduleSelector], state => state.firstLevel); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js index aaa1384e..fa8ea7a9 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/instants.js @@ -13,9 +13,9 @@ export const GET_INSTANTS = prefix('GET_INSTANTS'); export const GET_INSTANTS_SUCCESS = GET_INSTANTS + '_SUCCESS'; export const GET_INSTANTS_RESET = GET_INSTANTS + '_RESET'; -export function getInstants() { +export function getInstants(urls, start, end, limit) { return withApplicationId(id => { - const promise = api.getInstants(id,[],new Date("2000-01-01"), new Date("2018-01-01"),100); + const promise = api.getInstants(id, urls, start, end, limit); return createAction(GET_INSTANTS, { promise }); }); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js index cc0f07a0..52051cc5 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/intervals.js @@ -13,9 +13,9 @@ export const GET_INTERVALS = prefix('GET_INTERVALS'); export const GET_INTERVALS_SUCCESS = GET_INTERVALS + '_SUCCESS'; export const GET_INTERVALS_RESET = GET_INTERVALS + '_RESET'; -export function getIntervals() { +export function getIntervals(urls, start, end, limit) { return withApplicationId(id => { - const promise = api.getIntervals(id,[],new Date("2000-01-01"), new Date("2018-01-01"),100); + const promise = api.getIntervals(id, urls, start, end, limit); return createAction(GET_INTERVALS, { promise }); }); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/secondLevel.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/secondLevel.js new file mode 100644 index 00000000..0d4acc29 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/secondLevel.js @@ -0,0 +1,50 @@ +import createAction from '../../../../misc/createAction' +import withApplicationId from '../../../app/misc/withApplicationId' +import prefix from '../prefix' +import * as api from '../api' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { Connection } from '../models' +import { createSelector } from 'reselect' +import { createPromiseStatusSelector } from '../../../core/ducks/promises' +import moduleSelector from '../selector' + +// Actions +export const GET_TSL = prefix('GET_THINGS_SECOND'); +export const GET_TSL_SUCCESS = GET_TSL + '_SUCCESS'; +export const GET_TSL_RESET = GET_TSL + '_RESET'; + +export function getSecondLevelInstants(things, thingTypes, connections, limit) { + return withApplicationId(id => { + const promise = api.getThingsWThingsWInstants(id,things,thingTypes,connections,limit); + return createAction(GET_TSL, { promise }); + }); +} + +export function getSecondLevelIntervals(things, thingTypes, connections, limit) { + return withApplicationId(id => { + const promise = api.getThingsWThingsWIntervals(id,things,thingTypes,connections,limit); + return createAction(GET_TSL, { promise }); + }); +} + +export function getSecondLevelReset() { + return createAction(GET_TSL_RESET); +} + +// Reducer +const initialState = []; +export default function secondLevelReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_TSL_RESET: + return initialState; + case GET_TSL_SUCCESS: + return action.payload.map(i=>new Connection(i)); + } + return state; +}; + +// Selectors +export const secondLevelStatusSelector = createPromiseStatusSelector(GET_TSL); +export const secondLevelSelector = createSelector([moduleSelector], state => state.secondLevel); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedConnFirstLevel.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedConnFirstLevel.js new file mode 100644 index 00000000..23df5f62 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedConnFirstLevel.js @@ -0,0 +1,44 @@ +import createAction from '../../../../misc/createAction' +import prefix from '../prefix' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { createSelector } from 'reselect' +import {appendKey, removeKey} from './utils' +import moduleSelector from '../selector' + +// Actions +export const SET_SELECT_CFL = prefix('SET_SELECT_CONNECTIONS_FIRST'); +export const SET_UNSELECT_CFL = prefix('SET_UNSELECT_CONNECTIONS_FIRST'); +export const GET_SELECTED_CFL_RESET = prefix("GET_SELECTED_CONNECTIONS_FIRST_RESET"); + + + +export function setSelectConnFL(key) { + return createAction(SET_SELECT_CFL, { key }); +} + +export function setUnSelectConnFL(key){ + return createAction(SET_UNSELECT_CFL,{ key }); +} + +export function getSelectedConnFLReset() { + return createAction(GET_SELECTED_CFL_RESET); +} + +// Reducer +const initialState = []; +export default function selectedConnFLReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_SELECTED_CFL_RESET: + return initialState; + case SET_SELECT_CFL: + return appendKey(state,action.payload.key); + case SET_UNSELECT_CFL: + return removeKey(state,action.payload.key); + } + return state; +}; + +// Selectors +export const selectedConnFLSelector = createSelector([moduleSelector], state => state.selectedConnFL); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedConnSecondLevel.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedConnSecondLevel.js new file mode 100644 index 00000000..568f841f --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedConnSecondLevel.js @@ -0,0 +1,44 @@ +import createAction from '../../../../misc/createAction' +import prefix from '../prefix' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { createSelector } from 'reselect' +import {appendKey, removeKey} from './utils' +import moduleSelector from '../selector' + +// Actions +export const SET_SELECT_CSL = prefix('SET_SELECT_CONNECTIONS_SECOND'); +export const SET_UNSELECT_CSL = prefix('SET_UNSELECT_CONNECTIONS_SECOND'); +export const GET_SELECTED_CSL_RESET = prefix("GET_SELECTED_CONNECTIONS_SECOND_RESET"); + + + +export function setSelectConnSL(key) { + return createAction(SET_SELECT_CSL, { key }); +} + +export function setUnSelectConnSL(key){ + return createAction(SET_UNSELECT_CSL,{ key }); +} + +export function getSelectedConnSLReset() { + return createAction(GET_SELECTED_CSL_RESET); +} + +// Reducer +const initialState = []; +export default function selectedConnSLReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_SELECTED_CSL_RESET: + return initialState; + case SET_SELECT_CSL: + return appendKey(state,action.payload.key); + case SET_UNSELECT_CSL: + return removeKey(state,action.payload.key); + } + return state; +}; + +// Selectors +export const selectedConnSLSelector = createSelector([moduleSelector], state => state.selectedConnSL); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedThingSecondLevel.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedThingSecondLevel.js new file mode 100644 index 00000000..dd864946 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedThingSecondLevel.js @@ -0,0 +1,44 @@ +import createAction from '../../../../misc/createAction' +import prefix from '../prefix' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { createSelector } from 'reselect' +import {appendKey, removeKey} from './utils' +import moduleSelector from '../selector' + +// Actions +export const SET_SELECT_TSL = prefix('SET_SELECT_THING_SECOND'); +export const SET_UNSELECT_TSL = prefix('SET_UNSELECT_THING_SECOND'); +export const GET_SELECTED_TSL_RESET = prefix("GET_SELECTED_THING_SECOND_RESET"); + + + +export function setSelectThingSL(key) { + return createAction(SET_SELECT_TSL, { key }); +} + +export function setUnSelectThingSL(key){ + return createAction(SET_UNSELECT_TSL,{ key }); +} + +export function getSelectedThingSLReset() { + return createAction(GET_SELECTED_TSL_RESET); +} + +// Reducer +const initialState = []; +export default function selectedThingSLReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_SELECTED_TSL_RESET: + return initialState; + case SET_SELECT_TSL: + return appendKey(state,action.payload.key); + case SET_UNSELECT_TSL: + return removeKey(state,action.payload.key); + } + return state; +}; + +// Selectors +export const selectedThingSLSelector = createSelector([moduleSelector], state => state.selectedThingSL); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedTypeFirstLevel.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedTypeFirstLevel.js new file mode 100644 index 00000000..7690ebc5 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedTypeFirstLevel.js @@ -0,0 +1,44 @@ +import createAction from '../../../../misc/createAction' +import prefix from '../prefix' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { createSelector } from 'reselect' +import {appendKey, removeKey} from './utils' +import moduleSelector from '../selector' + +// Actions +export const SET_SELECT_TFL = prefix('SET_SELECT_TYPE_FL'); +export const SET_UNSELECT_TFL = prefix('SET_UNSELECT_TYPE_FL'); +export const GET_SELECTED_TFL_RESET = prefix("GET_SELECTED_TYPE_FL_RESET"); + + + +export function setSelectTypeFL(key) { + return createAction(SET_SELECT_TFL, { key }); +} + +export function setUnSelectTypeFL(key){ + return createAction(SET_UNSELECT_TFL,{ key }); +} + +export function getSelectedTypeFLReset() { + return createAction(GET_SELECTED_TFL_RESET); +} + +// Reducer +const initialState = []; +export default function selectedTypeFLReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_SELECTED_TFL_RESET: + return initialState; + case SET_SELECT_TFL: + return appendKey(state,action.payload.key); + case SET_UNSELECT_TFL: + return removeKey(state,action.payload.key); + } + return state; +}; + +// Selectors +export const selectedTypeFLSelector = createSelector([moduleSelector], state => state.selectedTypeFL); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/utils.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/utils.js new file mode 100644 index 00000000..2ada458e --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/utils.js @@ -0,0 +1,11 @@ +export function appendKey(array,key){ + return [key].concat(array); +} + +export function removeKey(array,key){ + var retArr = []; + for (let i of array){ + if (i != key) retArr.push(i) + } + return retArr; +} diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ConfigToolbar.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ConfigToolbar.js new file mode 100644 index 00000000..c70cf250 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ConfigToolbar.js @@ -0,0 +1,137 @@ +import React, { Component, PropTypes } from 'react' + +class ConfigToolbar extends Component { + static propTypes = { + things: PropTypes.array.isRequired, + label: PropTypes.string.isRequired, + + getKey: PropTypes.func.isRequired, + getValue: PropTypes.func.isRequired, + selectedKeys: PropTypes.array.isRequired, + + onChecked: PropTypes.func.isRequired, + onUnchecked: PropTypes.func.isRequired + }; + + // SEARCH & DEDUPLICATION + setNeedle(){ + var elements = document.getElementsByName("search"); + if (elements.length > 0) + this.needle = elements[0].value.toLowerCase(); + + if (this.needle && this.needle != ''){ + this.forceUpdate(); + } + }; + + resetNeedle(){ + this.needle=''; + + var elements = document.getElementsByName("search"); + if (elements.length > 0) { + elements[0].value = ''; + } + this.forceUpdate(); + } + + getMapToRender(){ + const {things,getKey, getValue} = this.props; + + // Deduplication + function getKVP(t){ + return [getKey(t), getValue(t)]; + } + var map = new Map(things.map(t => getKVP(t))); + + // Search + var matchingValues = new Map(); + if (this.needle && this.needle != '') { + for (var [key,value] of map) { + if (value.toLowerCase().startsWith(this.needle)) { + matchingValues.set(key, value); + } + } + } + else { + matchingValues = map; + } + + return matchingValues; + } + + // === CHECKBOXES === + isChecked(key) { + const {selectedKeys} = this.props; + if (selectedKeys.length > 0) { + if (selectedKeys.indexOf(key) > -1) { + return true; + } + } + return false; + } + + getCheckboxRows(map) { + const {onChecked, onUnchecked} = this.props; + + var counter = 0; + var rows = []; + + if (map.size > 0) { + for (const [key,value] of map) { + + // Checkbox props + const checked = this.isChecked(key); + function onChange(key) { + if (checked) onUnchecked(key); + else onChecked(key); + } + + // Row render + rows.push( + + onChange(key)} defaultChecked={checked}/> + {value} + + ); + + if (counter++ > 10) break; + } + } + else rows = + No values found. Try increasing the limit. + ; + + return rows; + } + + // === RENDERING === + render() { + var values = this.getMapToRender(); + var rows = this.getCheckboxRows(values); + + return
    + + + + + + + + +
    this.setNeedle()}/>this.resetNeedle()}/>
    + +
    + + + + + + + + + {rows} +
    SELECT{this.props.label}
    +
    + } +} +export default ConfigToolbar; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js index 6bda27b4..8cd438f3 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js @@ -186,7 +186,7 @@ class TimeLine { } intervals(data) { - var begins = data.map(d=>d.begin) + var begins = data.map(d=>d.begin); var ends = data.map(d=>d.end); var padding = this.timeRangePad(begins.concat(ends)); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js index 04959791..16dd4325 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js @@ -12,9 +12,10 @@ export const Instant = Record({ }); export const Connection = Record({ - outerThing: "url", + outer: "thing_url", + outerType: "type_url", connection: "url", - innerThing: "url" + inner: "thing_url" }); export const Count = Record({ diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js index 375c2a8d..1c57844a 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js @@ -1,10 +1,22 @@ import { combineReducers } from 'redux' import instants from './ducks/instants' import intervals from './ducks/intervals' +import firstLevel from './ducks/firstLevel' +import secondLevel from './ducks/secondLevel' +import selectedTypeFL from './ducks/selectedTypeFirstLevel' +import selectedThingSL from './ducks/selectedThingSecondLevel' +import selectedConnFL from './ducks/selectedConnFirstLevel' +import selectedConnSL from './ducks/selectedConnSecondLevel' const rootReducer = combineReducers({ instants, intervals, + firstLevel, + secondLevel, + selectedTypeFL, + selectedConnFL, + selectedThingSL, + selectedConnSL }); export default rootReducer; \ No newline at end of file From 376dfc18b9176cae3b179abf85e6ef54f68213cc Mon Sep 17 00:00:00 2001 From: vvancak Date: Tue, 9 May 2017 00:17:38 +0200 Subject: [PATCH 32/84] TimeLine: Limits --- .../timeline/containers/LimiterContainer.js | 59 +++++++++++++++++++ .../visualizers/timeline/ducks/limit.js | 36 +++++++++++ .../modules/visualizers/timeline/models.js | 9 --- .../modules/visualizers/timeline/reducer.js | 6 +- 4 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/limit.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js new file mode 100644 index 00000000..76bc0e46 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js @@ -0,0 +1,59 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { getCountReset, countSelector, countStatusSelector } from '../ducks/count' +import { getLimitReset, setLimit, limitSelector } from '../ducks/limit' +import { PromiseStatus } from '../../../core/models' +import {createStructuredSelector} from "reselect"; +import {Count, Limit} from "../models"; + +import PromiseResult from '../../../core/components/PromiseResult' +import CenteredMessage from '../../../../components/CenteredMessage' +import VisualizationMessage from '../components/VisualizationMessage' + +class LimiterContainer extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + + // Count Loaders + count: PropTypes.instanceOf(Count).isRequired, + status: PropTypes.instanceOf(PromiseStatus).isRequired, + + // Limit + limit: PropTypes.instanceOf(Limit).isRequired + }; + + componentWillUnmount() { + const {dispatch} = this.props; + + dispatch(getCountReset()); + dispatch(getLimitReset()); + } + + render() { + const {status, count, limit} = this.props; + + var CountVisualizer; + if (!status.done) { + CountVisualizer = + } + + else { + CountVisualizer = + Total {count} records loaded. + + } + + return
    + {CountVisualizer} +
    + + } +} + +const selector = createStructuredSelector({ + count: countSelector, + status: countStatusSelector, + limit: limitSelector +}); + +export default connect(selector)(LimiterContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/limit.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/limit.js new file mode 100644 index 00000000..43d85f18 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/limit.js @@ -0,0 +1,36 @@ +import createAction from '../../../../misc/createAction' +import prefix from '../prefix' +import moduleSelector from '../selector' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { createSelector } from 'reselect' + +export const limit_default = 100; + +// Actions +export const SET_LIMIT = prefix('SET_LIMIT'); +export const GET_LIMIT_RESET = prefix("GET_LIMIT_RESET"); + +export function setLimit(limit){ + return createAction(SET_LIMIT,{ limit }); +} + +export function getLimitReset() { + return createAction(GET_LIMIT_RESET); +} + +// Reducer +const initialState = limit_default; +export default function limitReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_LIMIT_RESET: + return initialState; + case SET_LIMIT: + return action.payload.limit; + } + return state; +}; + +// Selectors +export const limitSelector = createSelector([moduleSelector], state => state.limit); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js index 16dd4325..684015b2 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js @@ -18,13 +18,4 @@ export const Connection = Record({ inner: "thing_url" }); -export const Count = Record({ - value: 123 -}); - - -export const Limit = Record({ - value: 100 -}); - diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js index 1c57844a..8ec4e345 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/reducer.js @@ -7,6 +7,8 @@ import selectedTypeFL from './ducks/selectedTypeFirstLevel' import selectedThingSL from './ducks/selectedThingSecondLevel' import selectedConnFL from './ducks/selectedConnFirstLevel' import selectedConnSL from './ducks/selectedConnSecondLevel' +import count from './ducks/count' +import limit from './ducks/limit' const rootReducer = combineReducers({ instants, @@ -16,7 +18,9 @@ const rootReducer = combineReducers({ selectedTypeFL, selectedConnFL, selectedThingSL, - selectedConnSL + selectedConnSL, + count, + limit }); export default rootReducer; \ No newline at end of file From 6d6e3f74d410dbc56c2cb1c7008b0d0b074c11da Mon Sep 17 00:00:00 2001 From: vvancak Date: Tue, 9 May 2017 23:32:13 +0200 Subject: [PATCH 33/84] TimeLine: Visualization fixes, Usage of official components --- .../timeline/configuratorRoutes.js | 4 +- .../FirstLevelConnectionContainer.js | 51 ++++++++++++++---- .../timeline/containers/LimiterContainer.js | 45 +++++++++++++--- .../SecondLevelConnectionContainer.js | 35 +++++++++---- .../containers/TimeLineInstantsContainer.js | 27 ++++++---- .../containers/TimeLineIntervalsContainer.js | 33 ++++++------ .../timeline/misc/ConfigToolbar.js | 52 +++++++++++-------- .../visualizers/timeline/misc/TimeLine.js | 16 ++++-- .../timeline/pages/Configurator.js | 34 ------------ .../pages/ThingsWithThingsWithIntervals.js | 43 +++++++++++++++ 10 files changed, 222 insertions(+), 118 deletions(-) delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Configurator.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/configuratorRoutes.js index c0206cd2..ab5fa7cf 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/configuratorRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/configuratorRoutes.js @@ -1,10 +1,10 @@ import React from 'react' import { Route } from 'react-router' -import Configurator from './pages/Configurator' +import ThingsWithThingsWithIntervals from './pages/ThingsWithThingsWithIntervals' import { MODULE_PREFIX } from './prefix' export default function createRoutes(dispatch) { return ( - + ); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js index 86b28241..056271d5 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js @@ -2,6 +2,7 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import { getFirstLevelReset, firstLevelSelector, firstLevelStatusSelector } from '../ducks/firstLevel' import { secondLevelSelector } from '../ducks/secondLevel' +import { limitSelector } from '../ducks/limit' import { setSelectTypeFL, setUnSelectTypeFL, getSelectedTypeFLReset, selectedTypeFLSelector } from '../ducks/selectedTypeFirstLevel' import { setSelectConnFL, setUnSelectConnFL, getSelectedConnFLReset, selectedConnFLSelector } from '../ducks/selectedConnFirstLevel' import { PromiseStatus } from '../../../core/models' @@ -11,6 +12,8 @@ import PromiseResult from '../../../core/components/PromiseResult' import ConfigToolbar from '../misc/ConfigToolbar' import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' +import Button from "../../../../components/Button"; + class FirstLevelConnectionContainer extends Component { static propTypes = { @@ -22,19 +25,32 @@ class FirstLevelConnectionContainer extends Component { // Level loading firstLevelLoader: PropTypes.func.isRequired, + firstLevelCount: PropTypes.func.isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired, // Value selectors selectedTypeFL: PropTypes.instanceOf(Array).isRequired, - selectedConnFL: PropTypes.instanceOf(Array).isRequired + selectedConnFL: PropTypes.instanceOf(Array).isRequired, - //TODO Limiter + limit: PropTypes.instanceOf(Number).isRequired }; componentWillMount(){ this.load(); } + componentWillReceiveProps(nextProps) { + const {dispatch, firstLevelLoader, firstLevelCount, secondLevel, limit} = this.props; + if (secondLevel != nextProps.secondLevel) { + dispatch(getSelectedTypeFLReset()); + dispatch(getSelectedConnFLReset()); + + var urls = nextProps.secondLevel.map(l=>l.inner); + dispatch(firstLevelLoader(urls, [], [], limit)); + dispatch(firstLevelCount(urls, [], [])); + } + } + componentWillUnmount() { const {dispatch} = this.props; @@ -44,20 +60,22 @@ class FirstLevelConnectionContainer extends Component { } load(){ - const{dispatch, firstLevelLoader, secondLevel, selectedTypeFL, selectedConnFL} = this.props; + const{dispatch, firstLevelLoader, firstLevelCount, secondLevel, selectedTypeFL, selectedConnFL, limit} = this.props; var urls = secondLevel.map(l=>l.inner); - dispatch(firstLevelLoader(urls, selectedTypeFL, selectedConnFL, 100)); + dispatch(firstLevelLoader(urls, selectedTypeFL, selectedConnFL, limit)); + dispatch(firstLevelCount(urls, selectedTypeFL, selectedConnFL)) } reset(){ - const{dispatch, firstLevelLoader, secondLevel} = this.props; + const{dispatch, firstLevelLoader, firstLevelCount, secondLevel, limit} = this.props; dispatch(getSelectedTypeFLReset()); dispatch(getSelectedConnFLReset()); var urls = secondLevel.map(l=>l.inner); - dispatch(firstLevelLoader(urls, [], [], 100)) + dispatch(firstLevelLoader(urls, [], [], limit.value)); + dispatch(firstLevelCount(urls, [], [])); } render() { @@ -73,10 +91,12 @@ class FirstLevelConnectionContainer extends Component { } + var buttonsEnabled = selectedTypeFL.length > 0 || selectedConnFL.length > 0; + return
    t.outerType} getValue={t=>t.outerType} selectedKeys={selectedTypeFL} @@ -85,15 +105,23 @@ class FirstLevelConnectionContainer extends Component { /> t.connection} getValue={t=>t.connection} selectedKeys={selectedConnFL} onChecked={k=>dispatch(setSelectConnFL(k))} onUnchecked={k=>dispatch(setUnSelectConnFL(k))} /> - this.load()}/> - this.reset()}/> +
    } } @@ -103,7 +131,8 @@ const selector = createStructuredSelector({ secondLevel: secondLevelSelector, status: firstLevelStatusSelector, selectedTypeFL: selectedTypeFLSelector, - selectedConnFL: selectedConnFLSelector + selectedConnFL: selectedConnFLSelector, + limit: limitSelector }); export default connect(selector)(FirstLevelConnectionContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js index 76bc0e46..c5e2695d 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js @@ -1,25 +1,25 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import { getCountReset, countSelector, countStatusSelector } from '../ducks/count' -import { getLimitReset, setLimit, limitSelector } from '../ducks/limit' +import { getLimitReset, setLimit, limitSelector, limit_default} from '../ducks/limit' import { PromiseStatus } from '../../../core/models' -import {createStructuredSelector} from "reselect"; -import {Count, Limit} from "../models"; +import { createStructuredSelector } from "reselect"; import PromiseResult from '../../../core/components/PromiseResult' import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' +import Button from "../../../../components/Button"; class LimiterContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, // Count Loaders - count: PropTypes.instanceOf(Count).isRequired, + count: PropTypes.instanceOf(Number).isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired, // Limit - limit: PropTypes.instanceOf(Limit).isRequired + limit: PropTypes.instanceOf(Number).isRequired }; componentWillUnmount() { @@ -29,6 +29,26 @@ class LimiterContainer extends Component { dispatch(getLimitReset()); } + setLimit() { + const {dispatch} = this.props; + + var elements = document.getElementsByName("limit"); + if (elements.length > 0) { + const value = parseInt(elements[0].value); + dispatch(setLimit(value)); + } + } + + resetLimit(){ + const {dispatch, limit} = this.props; + dispatch(getLimitReset()); + + var elements = document.getElementsByName("limit"); + if (elements.length > 0) { + elements[0].value = limit_default; + } + }; + render() { const {status, count, limit} = this.props; @@ -39,11 +59,24 @@ class LimiterContainer extends Component { else { CountVisualizer = - Total {count} records loaded. + Total {count} records were loaded. Try increasing the limit to load more. } + var resetEnabled = limit != limit_default; + return
    + + + + + + +
    LIMITthis.setLimit()}/>
    {CountVisualizer}
    diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js index fa10258d..bd67b172 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js @@ -1,6 +1,7 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import { getSecondLevelReset, secondLevelSelector, secondLevelStatusSelector } from '../ducks/secondLevel' +import { limitSelector } from '../ducks/limit' import { setSelectThingSL, setUnSelectThingSL, getSelectedThingSLReset, selectedThingSLSelector } from '../ducks/selectedThingSecondLevel' import { setSelectConnSL, setUnSelectConnSL, getSelectedConnSLReset, selectedConnSLSelector } from '../ducks/selectedConnSecondLevel' import { PromiseStatus } from '../../../core/models' @@ -10,6 +11,7 @@ import PromiseResult from '../../../core/components/PromiseResult' import ConfigToolbar from '../misc/ConfigToolbar' import CenteredMessage from '../../../../components/CenteredMessage' import VisualizationMessage from '../components/VisualizationMessage' +import Button from "../../../../components/Button"; class SecondLevelConnectionContainer extends Component { static propTypes = { @@ -24,9 +26,9 @@ class SecondLevelConnectionContainer extends Component { // Value selectors selectedThingSL: PropTypes.instanceOf(Array).isRequired, - selectedConnSL: PropTypes.instanceOf(Array).isRequired + selectedConnSL: PropTypes.instanceOf(Array).isRequired, - //TODO Limiter + limit: PropTypes.instanceOf(Number).isRequired }; componentWillMount(){ @@ -42,17 +44,17 @@ class SecondLevelConnectionContainer extends Component { } load(){ - const{dispatch, secondLevelLoader, selectedThingSL, selectedConnSL} = this.props; - dispatch(secondLevelLoader(selectedThingSL, [], selectedConnSL, 100)); + const{dispatch, secondLevelLoader, selectedThingSL, selectedConnSL, limit} = this.props; + dispatch(secondLevelLoader(selectedThingSL, [], selectedConnSL, limit)); } reset(){ - const{dispatch, secondLevelLoader} = this.props; + const{dispatch, secondLevelLoader, limit} = this.props; dispatch(getSelectedThingSLReset()); dispatch(getSelectedConnSLReset()); - dispatch(secondLevelLoader([],[],[],100)) + dispatch(secondLevelLoader([],[],[],limit)) } render() { @@ -68,10 +70,12 @@ class SecondLevelConnectionContainer extends Component { } + var buttonsEnabled = selectedThingSL.length > 0 || selectedConnSL.length > 0; + return
    t.outer} getValue={t=>t.outer} selectedKeys={selectedThingSL} @@ -80,15 +84,23 @@ class SecondLevelConnectionContainer extends Component { /> t.connection} getValue={t=>t.connection} selectedKeys={selectedConnSL} onChecked={k=>dispatch(setSelectConnSL(k))} onUnchecked={k=>dispatch(setUnSelectConnSL(k))} /> - this.load()}/> - this.reset()}/> +
    } } @@ -97,7 +109,8 @@ const selector = createStructuredSelector({ secondLevel: secondLevelSelector, status: secondLevelStatusSelector, selectedThingSL: selectedThingSLSelector, - selectedConnSL: selectedConnSLSelector + selectedConnSL: selectedConnSLSelector, + limit: limitSelector }); export default connect(selector)(SecondLevelConnectionContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js index 89d363df..8d4ac80e 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js @@ -1,6 +1,7 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import { getInstants, getInstantsReset, instantsSelector, instantsStatusSelector } from '../ducks/instants' +import { limitSelector } from '../ducks/limit' import { firstLevelSelector } from '../ducks/firstLevel' import { PromiseStatus } from '../../../core/models' import {createStructuredSelector} from "reselect"; @@ -19,35 +20,40 @@ class TimeLineInstantsContainer extends Component { // Instants loading instants: PropTypes.instanceOf(Array).isRequired, - status: PropTypes.instanceOf(PromiseStatus).isRequired + status: PropTypes.instanceOf(PromiseStatus).isRequired, - // TODO limit + limit: PropTypes.instanceOf(Number).isRequired }; componentWillMount(){ + const {dispatch, limit} = this.props; + this.className = "timeseries-chart"; this.chart = new TimeLine(this.className, ()=>{}); // TODO: callback this.begin = new Date("2000-01-01"); this.end = new Date("2018-01-01"); - this.props.dispatch(getInstants([], this.start, this.end, 100)) + dispatch(getInstants([], this.start, this.end, limit)); } componentWillReceiveProps(nextProps) { - const {dispatch, firstLevel} = this.props; + const {dispatch, firstLevel, limit} = this.props; if (firstLevel != nextProps.firstLevel) { var urls = nextProps.firstLevel.map(t => t.inner); - dispatch(getInstants(urls, this.begin, this.end, 100)); + dispatch(getInstants(urls, this.begin, this.end, limit)); + } + + if (nextProps.status.done && nextProps.instants != this.props.instants) { + this.needChartUpdate = true; } } componentDidUpdate() { - const { instants, status } = this.props; - if (status.done && instants.length > 0) { - this.chart.destroy(); - this.chart.instants(this.props.instants); + const { instants } = this.props; + if (this.needChartUpdate) { + this.chart.instants(instants); } } @@ -78,7 +84,8 @@ class TimeLineInstantsContainer extends Component { const selector = createStructuredSelector({ instants: instantsSelector, status: instantsStatusSelector, - firstLevel: firstLevelSelector + firstLevel: firstLevelSelector, + limit: limitSelector }); export default connect(selector)(TimeLineInstantsContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js index 7ec1c6e5..4e1b4062 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js @@ -1,6 +1,7 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import { getIntervals, getIntervalsReset, intervalsSelector, intervalsStatusSelector } from '../ducks/intervals' +import { limitSelector } from '../ducks/limit' import { firstLevelSelector } from '../ducks/firstLevel' import { PromiseStatus } from '../../../core/models' import {createStructuredSelector} from "reselect"; @@ -19,42 +20,41 @@ class TimeLineIntervalsContainer extends Component { // Intervals loading intervals: PropTypes.instanceOf(Array).isRequired, - status: PropTypes.instanceOf(PromiseStatus).isRequired + status: PropTypes.instanceOf(PromiseStatus).isRequired, - // TODO limit + limit: PropTypes.instanceOf(Number).isRequired }; componentWillMount(){ + const {dispatch, limit} = this.props; + this.className = "timeseries-chart"; this.chart = new TimeLine(this.className, ()=>{}); // TODO: callback this.begin = new Date("2000-01-01"); this.end = new Date("2018-01-01"); - this.props.dispatch(getIntervals([], this.start, this.end, 100)) + dispatch(getIntervals([], this.start, this.end, limit)) } componentWillReceiveProps(nextProps) { - const {dispatch, firstLevel} = this.props; + const {dispatch, firstLevel, limit} = this.props; if (firstLevel != nextProps.firstLevel) { var urls = nextProps.firstLevel.map(t => t.inner); - dispatch(getIntervals(urls, this.begin, this.end, 100)); + dispatch(getIntervals(urls, this.begin, this.end, limit)); } - } - componentDidUpdate() { - const { intervals, status } = this.props; - if (status.done && intervals.length > 0) { - this.chart.destroy(); - this.chart.intervals(this.props.intervals); + if (nextProps.status.done && nextProps.intervals != this.props.intervals) { + this.needChartUpdate = true; } } - componentWillUnmount() { - const {dispatch} = this.props; - dispatch(getIntervalsReset()); - this.chart.destroy(); + componentDidUpdate() { + const { intervals } = this.props; + if (this.needChartUpdate) { + this.chart.intervals(intervals); + } } @@ -79,7 +79,8 @@ class TimeLineIntervalsContainer extends Component { const selector = createStructuredSelector({ intervals: intervalsSelector, status: intervalsStatusSelector, - firstLevel: firstLevelSelector + firstLevel: firstLevelSelector, + limit: limitSelector }); export default connect(selector)(TimeLineIntervalsContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ConfigToolbar.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ConfigToolbar.js index c70cf250..eefae500 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ConfigToolbar.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ConfigToolbar.js @@ -1,9 +1,13 @@ import React, { Component, PropTypes } from 'react' +import Checkbox from "../../../../components/Checkbox" +import Button from "../../../../components/Button" +import SubHeadLine from "../../../../components/Subheadline" +import CenteredMessage from "../../../../components/CenteredMessage"; class ConfigToolbar extends Component { static propTypes = { things: PropTypes.array.isRequired, - label: PropTypes.string.isRequired, + header: PropTypes.string.isRequired, getKey: PropTypes.func.isRequired, getValue: PropTypes.func.isRequired, @@ -35,19 +39,16 @@ class ConfigToolbar extends Component { } getMapToRender(){ - const {things,getKey, getValue} = this.props; + const {things, getKey, getValue} = this.props; // Deduplication - function getKVP(t){ - return [getKey(t), getValue(t)]; - } - var map = new Map(things.map(t => getKVP(t))); + var map = new Map(things.map(t => [getKey(t), getValue(t)])); // Search var matchingValues = new Map(); if (this.needle && this.needle != '') { for (var [key,value] of map) { - if (value.toLowerCase().startsWith(this.needle)) { + if (value.toLowerCase().includes(this.needle)) { matchingValues.set(key, value); } } @@ -89,7 +90,7 @@ class ConfigToolbar extends Component { // Row render rows.push( - onChange(key)} defaultChecked={checked}/> + onChange(key)} defaultChecked={checked}/> {value} ); @@ -98,7 +99,7 @@ class ConfigToolbar extends Component { } } else rows = - No values found. Try increasing the limit. + No values found. ; return rows; @@ -109,27 +110,32 @@ class ConfigToolbar extends Component { var values = this.getMapToRender(); var rows = this.getCheckboxRows(values); + var resetEnabled = (this.needle && this.needle != ''); + return
    + - + - - - + + + + - +
    this.setNeedle()}/>this.resetNeedle()}/>SEARCH:this.setNeedle()}/> +
    -
    - - - - - - - - {rows} + + {rows} +
    SELECT{this.props.label}
    } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js index 8cd438f3..f61668a8 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js @@ -129,7 +129,7 @@ class TimeLine { // instants => circles this.circles = function(data){ var circles = context.append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); circles.selectAll(".circ") .data(data) @@ -150,7 +150,7 @@ class TimeLine { // intervals => rectangles this.rectangles = function(data){ var rectangles = context.append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); rectangles.selectAll(".rect") .data(data) @@ -180,24 +180,30 @@ class TimeLine { } instants(data) { + this.destroy(); + var padding = this.timeRangePad(data.map(d=>d.date)); var drawFunc = () => this.circles(data); + this.render(padding,drawFunc); } intervals(data) { + this.destroy(); + var begins = data.map(d=>d.begin); var ends = data.map(d=>d.end); var padding = this.timeRangePad(begins.concat(ends)); - var drawFunc = () => this.rectangles(data); + this.render(padding,drawFunc); } // SVG destroying destroy(){ - var elements = d3.select("svg"); - if (elements != null){ + debugger; + var elements = d3.selectAll("svg"); + if (elements != null && elements.length > 0){ elements.remove(); } } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Configurator.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Configurator.js deleted file mode 100644 index cb4fc7bc..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Configurator.js +++ /dev/null @@ -1,34 +0,0 @@ -import React, { Component, PropTypes } from 'react' -import BodyPadding from '../../../../components/BodyPadding' -import { Application } from '../../../app/models' -import { Visualizer } from '../../../core/models' -import TimelineContainer from '../containers/TimelineContainer' - -class Configurator extends Component { - static propTypes = { - application: PropTypes.instanceOf(Application).isRequired, - visualizer: PropTypes.instanceOf(Visualizer).isRequired - }; - - /* componentWillMount() { - const { dispatch } = this.props; - dispatch(getConfiguration()); - } - - componentWillUnmount() { - const { dispatch } = this.props; - dispatch(getConfigurationReset()); - }*/ - - render() { - return ( - - ) - /*return ( - - - - )*/ - } -} -export default Configurator; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js new file mode 100644 index 00000000..80f46c06 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js @@ -0,0 +1,43 @@ +import React, { Component, PropTypes } from 'react' +import { Application } from '../../../app/models' +import { Visualizer } from '../../../core/models' + +import { getFirstLevelIntervals } from '../ducks/firstLevel' +import { getFirstLevelIntervalsCount } from '../ducks/count' + +import { getSecondLevelIntervals } from '../ducks/secondLevel' + +import BodyPadding from '../../../../components/BodyPadding' +import SecondLevelConnectionContainer from '../containers/SecondLevelConnectionContainer' +import FirstLevelConnectionContainer from '../containers/FirstLevelConnectionContainer' +import TimeLineIntervalsContainer from '../containers/TimeLineIntervalsContainer' +import LimiterContainer from '../containers/LimiterContainer' + +class Configurator extends Component { + static propTypes = { + application: PropTypes.instanceOf(Application).isRequired, + visualizer: PropTypes.instanceOf(Visualizer).isRequired + }; + + render() { + + return ( + + + + + + + + + + + +
    +
    + +
    + ) + } +} +export default Configurator; \ No newline at end of file From 9bca10b6692b99f716dedcd09dcf34f039d9a326 Mon Sep 17 00:00:00 2001 From: vvancak Date: Thu, 11 May 2017 17:24:14 +0200 Subject: [PATCH 34/84] TimeLine: Counts --- .../modules/visualizers/timeline/api.js | 36 +++---- .../components/ConfigurationToolbar.js | 93 ---------------- .../timeline/components/Visualization.js | 54 ---------- .../components/VisualizationMessage.js | 15 --- .../containers/CountFirstLevelContainer.js | 54 ++++++++++ .../containers/CountSecondLevelContainer.js | 54 ++++++++++ .../containers/CountZeroLevelContainer.js | 65 +++++++++++ .../FirstLevelConnectionContainer.js | 8 +- .../timeline/containers/LimiterContainer.js | 36 +------ .../SecondLevelConnectionContainer.js | 17 +-- .../containers/TimeLineInstantsContainer.js | 19 ++-- .../containers/TimeLineIntervalsContainer.js | 23 ++-- .../visualizers/timeline/ducks/count.js | 102 ++++++++++++++++++ .../visualizers/timeline/misc/TimeLine.js | 9 +- .../modules/visualizers/timeline/models.js | 6 ++ .../pages/ThingsWithThingsWithIntervals.js | 26 ++++- .../rdf/sparql/rgml/query/InstantQuery.scala | 2 +- .../rdf/sparql/rgml/query/IntervalQuery.scala | 2 +- .../rgml/query/ThingsWithInstantQuery.scala | 2 +- .../rgml/query/ThingsWithIntervalQuery.scala | 2 +- .../ThingsWithThingsWithInstantQuery.scala | 2 +- .../ThingsWithThingsWithIntervalQuery.scala | 2 +- 22 files changed, 372 insertions(+), 257 deletions(-) delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigurationToolbar.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Visualization.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/VisualizationMessage.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/count.js diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js index d29d83e5..18d69d52 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js @@ -33,35 +33,35 @@ export async function getThingsWThingsWInstants(applicationId, things, thingType return result.data.thingsWithThingsWithInstants; } -export async function getIntervalsCount(applicationId, urls, begin, end, limit) { - let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit":limit}; +export async function getIntervalsCount(applicationId, urls, begin, end) { + let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit": -1}; const result = await rest('timeLineVisualizer/getIntervals/count/' + applicationId, payload); - return result.data.count; + return result.data.count.value; } -export async function getInstantsCount(applicationId, urls, begin, end, limit) { - let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit":limit}; +export async function getInstantsCount(applicationId, urls, begin, end) { + let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit": -1}; const result = await rest('timeLineVisualizer/getInstants/count/' + applicationId, payload); - return result.data.count; + return result.data.count.value; } -export async function getThingsWIntervalsCount(applicationId, things, thingTypes, connections, limit) { - let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit":limit}; +export async function getThingsWIntervalsCount(applicationId, things, thingTypes, connections) { + let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit": -1}; const result = await rest('timeLineVisualizer/getThingsWIntervals/count/' + applicationId, payload); - return result.data.count; + return result.data.count.value; } -export async function getThingsWInstantsCount(applicationId, things, thingTypes, connections, limit) { - let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit":limit}; +export async function getThingsWInstantsCount(applicationId, things, thingTypes, connections) { + let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit": -1}; const result = await rest('timeLineVisualizer/getThingsWInstants/count/' + applicationId, payload); - return result.data.count; + return result.data.count.value; } -export async function getThingsWThingsWIntervalsCount(applicationId, things, thingTypes, connections, limit) { - let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": limit}; +export async function getThingsWThingsWIntervalsCount(applicationId, things, thingTypes, connections) { + let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": -1}; const result = await rest('timeLineVisualizer/getThingsWThingsWIntervals/count/' + applicationId, payload); - return result.data.count; + return result.data.count.value; } -export async function getThingsWThingsWInstantsCount(applicationId, things, thingTypes, connections, limit) { - let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": limit}; +export async function getThingsWThingsWInstantsCount(applicationId, things, thingTypes, connections) { + let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": -1}; const result = await rest('timeLineVisualizer/getThingsWThingsWInstants/count/' + applicationId, payload); - return result.data.count; + return result.data.count.value; } \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigurationToolbar.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigurationToolbar.js deleted file mode 100644 index 39a28bb3..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/ConfigurationToolbar.js +++ /dev/null @@ -1,93 +0,0 @@ -/* -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import {createStructuredSelector} from "reselect"; -import {settingsSelector, getSettingsReset, getSettings, setSettings} from '../ducks/settings' -import { Settings } from '../models' -import moment from "moment"; -import {getSelectedEventReset} from "../ducks/selectedEvent"; - -class ConfigToolbar extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, - settings: PropTypes.instanceOf(Settings).isRequired, - }; - - componentWillMount() { - const { dispatch } = this.props; - dispatch(getSettings()); - } - - componentWillReceiveProps(nextProps){ - const {settings} = nextProps; - - if (this.props.settings != settings) { - var startString = moment(settings.start).format('YYYY-MM-DD'); - var endString = moment(settings.end).format('YYYY-MM-DD'); - - document.getElementsByName("start")[0].value = startString; - document.getElementsByName("end")[0].value = endString; - document.getElementsByName("limit")[0].value = settings.limit; - } - } - - componentWillUnmount(){ - const {dispatch} = this.props; - dispatch(getSettingsReset()) - } - - handleNewConfig(){ - const {dispatch, settings} = this.props; - - var start = document.getElementsByName("start")[0].value; - var end = document.getElementsByName("end")[0].value; - var limit = document.getElementsByName("limit")[0].value; - var newSettings = {start:new Date(start), end:new Date(end), limit:limit}; - - if (settings != newSettings) { - dispatch(setSettings(newSettings)); - dispatch(getSelectedEventReset()); - } - } - - render() { - const settings = this.props.settings; - - var startString = moment(settings.start).format('YYYY-MM-DD'); - var endString = moment(settings.end).format('YYYY-MM-DD'); - - return
    - - - - - - - - - - - - - - - - -
    TimeSeries StartTimeSeries EndMax event count
    - - - - - - - this.handleNewConfig()}/> -
    -
    - } -} -const selector = createStructuredSelector({ - settings: settingsSelector -}); - -export default connect(selector)(ConfigToolbar); -*/ \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Visualization.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Visualization.js deleted file mode 100644 index 658ed3ec..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/Visualization.js +++ /dev/null @@ -1,54 +0,0 @@ -/* -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import {createStructuredSelector} from "reselect"; -import { settingsSelector } from '../ducks/settings' -import {getSelectedEvent, getSelectedEventReset, selectedEventSelector} from "../ducks/selectedEvent"; -import TimelineContainer from '../containers/TimelineContainer' -import EventInfoContainer from '../containers/InfoContainer' -import {Settings, SelectedEvent} from '../models' -import { getSettings, getSettingsReset} from '../ducks/settings' -import CenteredMessage from '../../../../components/CenteredMessage' -import VisualizationMessage from '../components/VisualizationMessage' - -class Visualization extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, - selectedEvent: PropTypes.instanceOf(SelectedEvent).isRequired, - settings: PropTypes.instanceOf(Settings).isRequired - }; - - componentWillUpdate(){ - const { dispatch } = this.props; - dispatch(getSelected()); - dispatch(getSettings()); - } - - componentWillUnmount() { - const { dispatch } = this.props; - dispatch(getSelected()); - dispatch(getSettingsReset()); - } - - render() { - const {settings, selectedEvent} = this.props; - if(!settings){ - return - An error occurred while loading the configuration. - - } - - return
    - - -
    - } -} -const selector = createStructuredSelector({ - settings: settingsSelector, - selectedEvent: selectedEventSelector -}); - -export default connect(selector)(Visualization); - -*/ \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/VisualizationMessage.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/VisualizationMessage.js deleted file mode 100644 index 3b7274e7..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/VisualizationMessage.js +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react' - -const style = { - textAlign: 'center', - marginTop: '100px', - color: 'rgba(0, 0, 0, 0.5)' -}; - -const VisualizationMessage = ({ children }) => ( -
    - {children} -
    -); - -export default VisualizationMessage; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js new file mode 100644 index 00000000..c6b23e1a --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js @@ -0,0 +1,54 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { getCountReset, countFirstSelector, countFirstStatusSelector} from '../ducks/count' +import { firstLevelSelector, firstLevelStatusSelector} from '../ducks/firstLevel' +import { createStructuredSelector } from "reselect"; +import { PromiseStatus } from "../../../core/models"; + +import PromiseResult from "../../../core/components/PromiseResult"; +import CenteredMessage from "../../../../components/CenteredMessage"; + +class CountFirstLevelContainer extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + + count: PropTypes.instanceOf(Number).isRequired, + countStatus: PropTypes.instanceOf(PromiseStatus).isRequired, + + things: PropTypes.instanceOf(Array).isRequired, + thingsStatus: PropTypes.instanceOf(PromiseStatus).isRequired, + }; + + componentWillUnmount() { + const {dispatch} = this.props; + + dispatch(getCountReset()); + } + + render() { + const {count, countStatus, things, thingsStatus} = this.props; + + if (!countStatus.done) { + return + } + + if (!thingsStatus.done){ + return + } + + var loaded = things.length; + return + Loaded {loaded} records out of {count} available. Increase limit to load more. + + } +} + +const selector = createStructuredSelector({ + count: countFirstSelector, + countStatus: countFirstStatusSelector, + + things: firstLevelSelector, + thingsStatus: firstLevelStatusSelector +}); + +export default connect(selector)(CountFirstLevelContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js new file mode 100644 index 00000000..49758398 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js @@ -0,0 +1,54 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { getCountReset, countSecondSelector, countSecondStatusSelector} from '../ducks/count' +import { secondLevelSelector, secondLevelStatusSelector} from '../ducks/secondLevel' +import { createStructuredSelector } from "reselect"; +import { PromiseStatus } from "../../../core/models"; + +import PromiseResult from "../../../core/components/PromiseResult"; +import CenteredMessage from "../../../../components/CenteredMessage"; + +class CountSecondLevelContainer extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + + count: PropTypes.instanceOf(Number).isRequired, + countStatus: PropTypes.instanceOf(PromiseStatus).isRequired, + + things: PropTypes.instanceOf(Array).isRequired, + thingsStatus: PropTypes.instanceOf(PromiseStatus).isRequired, + }; + + componentWillUnmount() { + const {dispatch} = this.props; + + dispatch(getCountReset()); + } + + render() { + const {count, countStatus, things, thingsStatus} = this.props; + + if (!countStatus.done) { + return + } + + if (!thingsStatus.done){ + return + } + + var loaded = things.length; + return + Loaded {loaded} records out of {count} available. Increase limit to load more. + + } +} + +const selector = createStructuredSelector({ + count: countSecondSelector, + countStatus: countSecondStatusSelector, + + things: secondLevelSelector, + thingsStatus: secondLevelStatusSelector +}); + +export default connect(selector)(CountSecondLevelContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js new file mode 100644 index 00000000..de270f9d --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js @@ -0,0 +1,65 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { getCountReset, countZeroSelector, countZeroStatusSelector} from '../ducks/count' +import { intervalsSelector, intervalsStatusSelector} from '../ducks/intervals' +import { instantsSelector, instantsStatusSelector} from '../ducks/instants' +import { createStructuredSelector } from "reselect"; +import { PromiseStatus } from "../../../core/models"; + +import PromiseResult from "../../../core/components/PromiseResult"; +import CenteredMessage from "../../../../components/CenteredMessage"; + +class CountZeroLevelContainer extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + + count: PropTypes.instanceOf(Number).isRequired, + countStatus: PropTypes.instanceOf(PromiseStatus).isRequired, + + intervals: PropTypes.instanceOf(Array).isRequired, + intervalsStatus: PropTypes.instanceOf(PromiseStatus).isRequired, + + instants: PropTypes.instanceOf(Array).isRequired, + instantsStatus: PropTypes.instanceOf(PromiseStatus).isRequired + + }; + + componentWillUnmount() { + const {dispatch} = this.props; + + dispatch(getCountReset()); + } + + render() { + const {count, countStatus, instants, instantsStatus, intervals, intervalsStatus} = this.props; + + if (!countStatus.done) { + return + } + + if (!instantsStatus.done && !intervalsStatus.done){ + return + } + + let loaded; + if (instantsStatus.done) loaded = instants.length; + if (intervalsStatus.done) loaded = intervals.length; + + return + Loaded {loaded} records out of {count} available. Increase limit to load more. + + } +} + +const selector = createStructuredSelector({ + count: countZeroSelector, + countStatus: countZeroStatusSelector, + + instants: instantsSelector, + instantsStatus: instantsStatusSelector, + + intervals: intervalsSelector, + intervalsStatus: intervalsStatusSelector +}); + +export default connect(selector)(CountZeroLevelContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js index 056271d5..ad42c030 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js @@ -11,13 +11,13 @@ import { createStructuredSelector } from "reselect"; import PromiseResult from '../../../core/components/PromiseResult' import ConfigToolbar from '../misc/ConfigToolbar' import CenteredMessage from '../../../../components/CenteredMessage' -import VisualizationMessage from '../components/VisualizationMessage' import Button from "../../../../components/Button"; class FirstLevelConnectionContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, + isInitial: PropTypes.instanceOf(Boolean), // Levels firstLevel: PropTypes.instanceOf(Array).isRequired, @@ -36,7 +36,7 @@ class FirstLevelConnectionContainer extends Component { }; componentWillMount(){ - this.load(); + if (this.props.isInitial) this.load(); } componentWillReceiveProps(nextProps) { @@ -86,9 +86,7 @@ class FirstLevelConnectionContainer extends Component { } else if (firstLevel.length == 0) { - return - No connected things were loaded. Check the settings please. - + return No connected things were loaded. Check the settings please. } var buttonsEnabled = selectedTypeFL.length > 0 || selectedConnFL.length > 0; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js index c5e2695d..5bb71943 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js @@ -1,31 +1,18 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' -import { getCountReset, countSelector, countStatusSelector } from '../ducks/count' import { getLimitReset, setLimit, limitSelector, limit_default} from '../ducks/limit' -import { PromiseStatus } from '../../../core/models' import { createStructuredSelector } from "reselect"; - -import PromiseResult from '../../../core/components/PromiseResult' -import CenteredMessage from '../../../../components/CenteredMessage' -import VisualizationMessage from '../components/VisualizationMessage' import Button from "../../../../components/Button"; class LimiterContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - - // Count Loaders - count: PropTypes.instanceOf(Number).isRequired, - status: PropTypes.instanceOf(PromiseStatus).isRequired, - - // Limit limit: PropTypes.instanceOf(Number).isRequired }; componentWillUnmount() { const {dispatch} = this.props; - dispatch(getCountReset()); dispatch(getLimitReset()); } @@ -50,42 +37,27 @@ class LimiterContainer extends Component { }; render() { - const {status, count, limit} = this.props; - - var CountVisualizer; - if (!status.done) { - CountVisualizer = - } - - else { - CountVisualizer = - Total {count} records were loaded. Try increasing the limit to load more. - - } + const {limit} = this.props; var resetEnabled = limit != limit_default; - return
    LIMIT this.setLimit()}/>
    - {CountVisualizer}
    } } const selector = createStructuredSelector({ - count: countSelector, - status: countStatusSelector, limit: limitSelector }); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js index bd67b172..4c62fedb 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js @@ -10,18 +10,19 @@ import { createStructuredSelector } from "reselect"; import PromiseResult from '../../../core/components/PromiseResult' import ConfigToolbar from '../misc/ConfigToolbar' import CenteredMessage from '../../../../components/CenteredMessage' -import VisualizationMessage from '../components/VisualizationMessage' import Button from "../../../../components/Button"; class SecondLevelConnectionContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, + isInitial: PropTypes.instanceOf(Boolean), // Levels secondLevel: PropTypes.instanceOf(Array).isRequired, // Level loading secondLevelLoader: PropTypes.func.isRequired, + secondLevelCount: PropTypes.func.isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired, // Value selectors @@ -32,7 +33,7 @@ class SecondLevelConnectionContainer extends Component { }; componentWillMount(){ - this.load(); + if (this.props.isInitial) this.load(); } componentWillUnmount() { @@ -44,17 +45,19 @@ class SecondLevelConnectionContainer extends Component { } load(){ - const{dispatch, secondLevelLoader, selectedThingSL, selectedConnSL, limit} = this.props; + const{dispatch, secondLevelLoader, secondLevelCount, selectedThingSL, selectedConnSL, limit} = this.props; dispatch(secondLevelLoader(selectedThingSL, [], selectedConnSL, limit)); + dispatch(secondLevelCount(selectedThingSL, [], selectedConnSL)); } reset(){ - const{dispatch, secondLevelLoader, limit} = this.props; + const{dispatch, secondLevelLoader, secondLevelCount, limit} = this.props; dispatch(getSelectedThingSLReset()); dispatch(getSelectedConnSLReset()); - dispatch(secondLevelLoader([],[],[],limit)) + dispatch(secondLevelLoader([],[],[],limit)); + dispatch(secondLevelCount([],[],[])); } render() { @@ -65,9 +68,7 @@ class SecondLevelConnectionContainer extends Component { } else if (secondLevel.length == 0) { - return - No connected things were loaded. Check the settings please. - + return No connected things were loaded. Check the settings please. } var buttonsEnabled = selectedThingSL.length > 0 || selectedConnSL.length > 0; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js index 8d4ac80e..e4598652 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js @@ -1,6 +1,7 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import { getInstants, getInstantsReset, instantsSelector, instantsStatusSelector } from '../ducks/instants' +import { getInstantsCount } from '../ducks/count' import { limitSelector } from '../ducks/limit' import { firstLevelSelector } from '../ducks/firstLevel' import { PromiseStatus } from '../../../core/models' @@ -9,11 +10,11 @@ import {createStructuredSelector} from "reselect"; import PromiseResult from '../../../core/components/PromiseResult' import TimeLine from '../misc/TimeLine' import CenteredMessage from '../../../../components/CenteredMessage' -import VisualizationMessage from '../components/VisualizationMessage' class TimeLineInstantsContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, + isInitial: PropTypes.instanceOf(Boolean), // Levels firstLevel: PropTypes.instanceOf(Array).isRequired, @@ -25,16 +26,19 @@ class TimeLineInstantsContainer extends Component { limit: PropTypes.instanceOf(Number).isRequired }; - componentWillMount(){ + componentWillMount() { const {dispatch, limit} = this.props; this.className = "timeseries-chart"; - this.chart = new TimeLine(this.className, ()=>{}); // TODO: callback + this.chart = new TimeLine(this.className, () => { + }); // TODO: callback this.begin = new Date("2000-01-01"); this.end = new Date("2018-01-01"); - - dispatch(getInstants([], this.start, this.end, limit)); + if (this.props.isInitial) { + dispatch(getInstants([], this.start, this.end, limit)); + dispatch(getInstantsCount([], this.start, this.end, limit)); + } } componentWillReceiveProps(nextProps) { @@ -43,6 +47,7 @@ class TimeLineInstantsContainer extends Component { if (firstLevel != nextProps.firstLevel) { var urls = nextProps.firstLevel.map(t => t.inner); dispatch(getInstants(urls, this.begin, this.end, limit)); + dispatch(getInstantsCount(urls, this.begin, this.end, limit)); } if (nextProps.status.done && nextProps.instants != this.props.instants) { @@ -71,9 +76,7 @@ class TimeLineInstantsContainer extends Component { } else if (instants.length == 0) { - return - No instants were loaded. Check the settings please. - + return No instants were loaded. Check the settings please. } require('../misc/TimeLineStyle.css'); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js index 4e1b4062..d025187b 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js @@ -1,6 +1,7 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' import { getIntervals, getIntervalsReset, intervalsSelector, intervalsStatusSelector } from '../ducks/intervals' +import { getIntervalsCount } from '../ducks/count' import { limitSelector } from '../ducks/limit' import { firstLevelSelector } from '../ducks/firstLevel' import { PromiseStatus } from '../../../core/models' @@ -9,11 +10,11 @@ import {createStructuredSelector} from "reselect"; import PromiseResult from '../../../core/components/PromiseResult' import TimeLine from '../misc/TimeLine' import CenteredMessage from '../../../../components/CenteredMessage' -import VisualizationMessage from '../components/VisualizationMessage' class TimeLineIntervalsContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, + isInitial: PropTypes.instanceOf(Boolean), // Levels firstLevel: PropTypes.instanceOf(Array).isRequired, @@ -25,16 +26,20 @@ class TimeLineIntervalsContainer extends Component { limit: PropTypes.instanceOf(Number).isRequired }; - componentWillMount(){ + componentWillMount() { const {dispatch, limit} = this.props; this.className = "timeseries-chart"; - this.chart = new TimeLine(this.className, ()=>{}); // TODO: callback + this.chart = new TimeLine(this.className, () => { + }); // TODO: callback this.begin = new Date("2000-01-01"); this.end = new Date("2018-01-01"); - dispatch(getIntervals([], this.start, this.end, limit)) + if (this.props.isInitial) { + dispatch(getIntervals([], this.start, this.end, limit)) + dispatch(getIntervalsCount([], this.start, this.end, this.limit)); + } } componentWillReceiveProps(nextProps) { @@ -43,6 +48,7 @@ class TimeLineIntervalsContainer extends Component { if (firstLevel != nextProps.firstLevel) { var urls = nextProps.firstLevel.map(t => t.inner); dispatch(getIntervals(urls, this.begin, this.end, limit)); + dispatch(getIntervalsCount(urls, this.begin, this.end, limit)); } if (nextProps.status.done && nextProps.intervals != this.props.intervals) { @@ -57,6 +63,11 @@ class TimeLineIntervalsContainer extends Component { } } + componentWillUnmount(){ + const {dispatch} = this.props; + dispatch(getIntervalsReset()); + this.chart.destroy(); + } render() { const {status, intervals} = this.props; @@ -66,9 +77,7 @@ class TimeLineIntervalsContainer extends Component { } else if (intervals.length == 0) { - return - No intervals were loaded. Check the settings please. - + return No intervals were loaded. Check the settings please. } require('../misc/TimeLineStyle.css'); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/count.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/count.js new file mode 100644 index 00000000..f8b984d2 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/count.js @@ -0,0 +1,102 @@ +import createAction from '../../../../misc/createAction' +import withApplicationId from '../../../app/misc/withApplicationId' +import prefix from '../prefix' +import * as api from '../api' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { Count } from '../models' +import { createSelector } from 'reselect' +import { createPromiseStatusSelector } from '../../../core/ducks/promises' +import moduleSelector from '../selector' + +// ===ACTIONS=== + +// Level 0 => instants & intervals +export const GET_COUNT_ZERO = prefix('GET_COUNT_ZERO'); +export const GET_COUNT_ZERO_SUCCESS = GET_COUNT_ZERO + "_SUCCESS"; + +export function getIntervalsCount(urls,begin,end){ + return withApplicationId(id => { + const promise = api.getIntervalsCount(id, urls, begin, end); + return createAction(GET_COUNT_ZERO, { promise }); + }); +} + +export function getInstantsCount(urls,begin,end){ + return withApplicationId(id => { + const promise = api.getInstantsCount(id, urls, begin, end); + return createAction(GET_COUNT_ZERO, { promise }); + }); +} + +// Level 1 => Things with Instants / Intervals +export const GET_COUNT_FIRST = prefix('GET_COUNT_FIRST'); +export const GET_COUNT_FIRST_SUCCESS = GET_COUNT_FIRST + "_SUCCESS"; + +export function getFirstLevelIntervalsCount(things, thingTypes, connections) { + return withApplicationId(id => { + const promise = api.getThingsWIntervalsCount(id, things, thingTypes, connections); + return createAction(GET_COUNT_FIRST, { promise }); + }); +} + +export function getFirstLevelInstantsCount(things, thingTypes, connections) { + return withApplicationId(id => { + const promise = api.getThingsWInstantsCount(id, things, thingTypes, connections); + return createAction(GET_COUNT_FIRST, { promise }); + }); +} + +// Level 2 => Things with Things with Instants / Intervals +export const GET_COUNT_SECOND = prefix('GET_COUNT_SECOND'); +export const GET_COUNT_SECOND_SUCCESS = GET_COUNT_SECOND + "_SUCCESS"; + +export function getSecondLevelIntervalsCount(things, thingTypes, connections) { + return withApplicationId(id => { + const promise = api.getThingsWThingsWIntervalsCount(id, things, thingTypes, connections); + return createAction(GET_COUNT_SECOND, { promise }); + }); +} + +export function getSecondLevelInstantsCount(things, thingTypes, connections) { + return withApplicationId(id => { + const promise = api.getThingsWThingsWInstantsCount(id, things, thingTypes, connections); + return createAction(GET_COUNT_SECOND, { promise }); + }); +} + +export const GET_COUNT_RES = prefix("GET_COUNTS_RESET"); +export function getCountReset() { + return createAction(GET_COUNT_RES); +} + +// ===REDUCERS=== +const initialState = new Count(); +export default function countReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_COUNT_RES: + return initialState; + case GET_COUNT_ZERO_SUCCESS: + return new Count({"zero": action.payload, "first": state.first, "second":state.second}); + case GET_COUNT_FIRST_SUCCESS: + return new Count({"zero": state.zero, "first": action.payload, "second":state.second}); + case GET_COUNT_SECOND_SUCCESS: + return new Count({"zero": state.zero, "first": state.first, "second":action.payload}); + } + return state; +}; + +// ===SELECTORS=== + +// Level 0 +export const countZeroStatusSelector = createPromiseStatusSelector(GET_COUNT_ZERO); +export const countZeroSelector = createSelector([moduleSelector], state => state.count.zero); + +// Level 1 +export const countFirstStatusSelector = createPromiseStatusSelector(GET_COUNT_FIRST); +export const countFirstSelector = createSelector([moduleSelector], state => state.count.first); + +// Level 2 +export const countSecondStatusSelector = createPromiseStatusSelector(GET_COUNT_SECOND); +export const countSecondSelector = createSelector([moduleSelector], state => state.count.second); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js index f61668a8..60641833 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js @@ -180,29 +180,26 @@ class TimeLine { } instants(data) { - this.destroy(); - var padding = this.timeRangePad(data.map(d=>d.date)); var drawFunc = () => this.circles(data); + this.destroy(); this.render(padding,drawFunc); } intervals(data) { - this.destroy(); - var begins = data.map(d=>d.begin); var ends = data.map(d=>d.end); var padding = this.timeRangePad(begins.concat(ends)); var drawFunc = () => this.rectangles(data); + this.destroy(); this.render(padding,drawFunc); } // SVG destroying destroy(){ - debugger; - var elements = d3.selectAll("svg"); + var elements = d3.selectAll("." + this.classd).selectAll("svg"); if (elements != null && elements.length > 0){ elements.remove(); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js index 684015b2..be213cff 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/models.js @@ -18,4 +18,10 @@ export const Connection = Record({ inner: "thing_url" }); +export const Count = Record({ + zero: 0, + first: 0, + second:0 +}); + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js index 80f46c06..7522f8ff 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js @@ -1,16 +1,18 @@ import React, { Component, PropTypes } from 'react' import { Application } from '../../../app/models' import { Visualizer } from '../../../core/models' - import { getFirstLevelIntervals } from '../ducks/firstLevel' -import { getFirstLevelIntervalsCount } from '../ducks/count' - +import { getFirstLevelIntervalsCount, getSecondLevelIntervalsCount} from '../ducks/count' import { getSecondLevelIntervals } from '../ducks/secondLevel' import BodyPadding from '../../../../components/BodyPadding' + import SecondLevelConnectionContainer from '../containers/SecondLevelConnectionContainer' import FirstLevelConnectionContainer from '../containers/FirstLevelConnectionContainer' import TimeLineIntervalsContainer from '../containers/TimeLineIntervalsContainer' +import CountSecondLevelContainer from '../containers/CountSecondLevelContainer' +import CountFirstLevelContainer from '../containers/CountFirstLevelContainer' +import CountZeroLevelContainer from '../containers/CountZeroLevelContainer' import LimiterContainer from '../containers/LimiterContainer' class Configurator extends Component { @@ -29,13 +31,27 @@ class Configurator extends Component { - - + + + + + + + +
    + ) } diff --git a/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala index 2e838638..1bea8172 100644 --- a/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/InstantQuery.scala @@ -12,7 +12,7 @@ class InstantQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInstan } def getCount: String = { - val select = "SELECT COUNT(?instant) AS ?count" + val select = "SELECT (count(distinct(?instant)) AS ?count)" val group = "" val limit = "" return query(select, group, limit) diff --git a/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala index fa428f7b..caa986e3 100644 --- a/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/IntervalQuery.scala @@ -12,7 +12,7 @@ class IntervalQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInter } def getCount: String = { - val select = "SELECT COUNT(?interval) AS ?count" + val select = "SELECT (count(distinct(?interval)) AS ?count)" val group = "" val limit = "" return query(select, group, limit) diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala index 53f5d2c9..584d569e 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithInstantQuery.scala @@ -14,7 +14,7 @@ class ThingsWithInstantQuery( maybeThingsUrls: Option[Seq[String]], } def getCount: String = { - val select = "SELECT COUNT(?thing) AS ?count" + val select = "SELECT (count(distinct(?thing)) AS ?count)" val group = "" val limit = "" return query(select,group,limit) diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala index 006460da..9e004bdf 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithIntervalQuery.scala @@ -14,7 +14,7 @@ class ThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], } def getCount: String = { - val select = "SELECT COUNT(?thing) AS ?count" + val select = "SELECT (count(distinct(?thing)) AS ?count)" val group = "" val limit = "" return query(select,group,limit) diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala index 558c6dcc..ed2142bf 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithInstantQuery.scala @@ -14,7 +14,7 @@ class ThingsWithThingsWithInstantQuery(maybeThingsUrls: Option[Seq[String]], } def getCount: String = { - val select = "SELECT COUNT(?outerThing) AS ?count" + val select = "SELECT (count(distinct(?outerThing)) AS ?count)" val group = "" val limit = "" return query(select,group,limit) diff --git a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala index 77249d87..2893e3e8 100644 --- a/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala +++ b/src/app/model/rdf/sparql/rgml/query/ThingsWithThingsWithIntervalQuery.scala @@ -14,7 +14,7 @@ class ThingsWithThingsWithIntervalQuery(maybeThingsUrls: Option[Seq[String]], } def getCount: String = { - val select = "SELECT COUNT(?outerThing) AS ?count" + val select = "SELECT (count(distinct(?outerThing)) AS ?count)" val group = "" val limit = "" return query(select,group,limit) From 88e188821a03682e96eab23918aa289b032083a1 Mon Sep 17 00:00:00 2001 From: vvancak Date: Thu, 11 May 2017 23:44:03 +0200 Subject: [PATCH 35/84] TimeLine : Labels --- .../FirstLevelConnectionContainer.js | 6 +- .../SecondLevelConnectionContainer.js | 4 +- .../visualizers/timeline/ducks/limit.js | 2 +- .../{ConfigToolbar.js => ValueSelector.js} | 141 +++++++++++------- .../pages/ThingsWithThingsWithIntervals.js | 2 + 5 files changed, 96 insertions(+), 59 deletions(-) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/{ConfigToolbar.js => ValueSelector.js} (50%) diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js index ad42c030..6e37c360 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js @@ -9,7 +9,7 @@ import { PromiseStatus } from '../../../core/models' import { createStructuredSelector } from "reselect"; import PromiseResult from '../../../core/components/PromiseResult' -import ConfigToolbar from '../misc/ConfigToolbar' +import ConfigToolbar from '../misc/ValueSelector' import CenteredMessage from '../../../../components/CenteredMessage' import Button from "../../../../components/Button"; @@ -74,7 +74,7 @@ class FirstLevelConnectionContainer extends Component { dispatch(getSelectedConnFLReset()); var urls = secondLevel.map(l=>l.inner); - dispatch(firstLevelLoader(urls, [], [], limit.value)); + dispatch(firstLevelLoader(urls, [], [], limit)); dispatch(firstLevelCount(urls, [], [])); } @@ -94,7 +94,7 @@ class FirstLevelConnectionContainer extends Component { return
    t.outerType} getValue={t=>t.outerType} selectedKeys={selectedTypeFL} diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js index 4c62fedb..2a874f83 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js @@ -8,7 +8,7 @@ import { PromiseStatus } from '../../../core/models' import { createStructuredSelector } from "reselect"; import PromiseResult from '../../../core/components/PromiseResult' -import ConfigToolbar from '../misc/ConfigToolbar' +import ConfigToolbar from '../misc/ValueSelector' import CenteredMessage from '../../../../components/CenteredMessage' import Button from "../../../../components/Button"; @@ -76,7 +76,7 @@ class SecondLevelConnectionContainer extends Component { return
    t.outer} getValue={t=>t.outer} selectedKeys={selectedThingSL} diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/limit.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/limit.js index 43d85f18..b1dd9318 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/limit.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/limit.js @@ -4,7 +4,7 @@ import moduleSelector from '../selector' import { GET_APPLICATION_START } from '../../../app/ducks/application' import { createSelector } from 'reselect' -export const limit_default = 100; +export const limit_default = 20; // Actions export const SET_LIMIT = prefix('SET_LIMIT'); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ConfigToolbar.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ValueSelector.js similarity index 50% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ConfigToolbar.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ValueSelector.js index eefae500..39525a12 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ConfigToolbar.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ValueSelector.js @@ -1,23 +1,34 @@ import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from "reselect"; +import { getLabels, labelsSelector} from "../../../app/ducks/labels" +import { langSelector } from "../../../app/ducks/lang" + import Checkbox from "../../../../components/Checkbox" import Button from "../../../../components/Button" import SubHeadLine from "../../../../components/Subheadline" import CenteredMessage from "../../../../components/CenteredMessage"; +import LocalizedValue from "../../../app/containers/LocalizedValue"; +import {extractFromLocalizedValue} from "../../../app/misc/languageUtils"; -class ConfigToolbar extends Component { +class ValueSelector extends Component { static propTypes = { + dispatch: PropTypes.func.isRequired, + + labels: PropTypes.instanceOf(Map).isRequired, + language: PropTypes.instanceOf(Object).isRequired, + things: PropTypes.array.isRequired, header: PropTypes.string.isRequired, getKey: PropTypes.func.isRequired, - getValue: PropTypes.func.isRequired, selectedKeys: PropTypes.array.isRequired, onChecked: PropTypes.func.isRequired, onUnchecked: PropTypes.func.isRequired }; - // SEARCH & DEDUPLICATION + // SEARCH setNeedle(){ var elements = document.getElementsByName("search"); if (elements.length > 0) @@ -38,29 +49,28 @@ class ConfigToolbar extends Component { this.forceUpdate(); } - getMapToRender(){ - const {things, getKey, getValue} = this.props; - - // Deduplication - var map = new Map(things.map(t => [getKey(t), getValue(t)])); - - // Search - var matchingValues = new Map(); - if (this.needle && this.needle != '') { - for (var [key,value] of map) { - if (value.toLowerCase().includes(this.needle)) { - matchingValues.set(key, value); - } - } - } - else { - matchingValues = map; - } - - return matchingValues; + getSearchComponent(){ + var resetEnabled = (this.needle && this.needle != ''); + return + + + + + + + +
    SEARCH:this.setNeedle()}/> + +
    } - // === CHECKBOXES === + // === CHECKBOX LIST === isChecked(key) { const {selectedKeys} = this.props; if (selectedKeys.length > 0) { @@ -71,14 +81,55 @@ class ConfigToolbar extends Component { return false; } - getCheckboxRows(map) { + getLabel(key){ + const {dispatch,labels} = this.props; + if (!labels.has(key)) { + dispatch(getLabels([key])); + return key; + } + else { + return extractFromLocalizedValue(this.props.language, labels.get(key), key); + } + } + + getMatchingRecords(map) { + var matchingValues = new Map(); + + for (var [key, label] of map) { + if (label.toLowerCase().contains(this.needle)) { + matchingValues.set(key, label); + } + } + + return matchingValues; + } + + getValuesForVisualization(){ + const {things, getKey} = this.props; + + // Deduplication + var map = new Map(things.map(t => { + var key = getKey(t); + return [key, this.getLabel(key)] + })); + + // Needle Search + if (this.needle && this.needle != '') { + return this.getMatchingRecords(map); + } + else return map; + } + + getCheckboxRows() { const {onChecked, onUnchecked} = this.props; + var valuesMap = this.getValuesForVisualization(); + var counter = 0; var rows = []; - if (map.size > 0) { - for (const [key,value] of map) { + if (valuesMap.size > 0) { + for (const [key,label] of valuesMap) { // Checkbox props const checked = this.isChecked(key); @@ -91,7 +142,7 @@ class ConfigToolbar extends Component { rows.push( onChange(key)} defaultChecked={checked}/> - {value} + ); @@ -105,39 +156,23 @@ class ConfigToolbar extends Component { return rows; } - // === RENDERING === +// === RENDERING === render() { - var values = this.getMapToRender(); - var rows = this.getCheckboxRows(values); - - var resetEnabled = (this.needle && this.needle != ''); - return
    - - - - - - - - -
    SEARCH:this.setNeedle()}/> - -
    + {this.getSearchComponent()}
    - {rows} + {this.getCheckboxRows()}
    } } -export default ConfigToolbar; \ No newline at end of file +const selector = createStructuredSelector({ + labels: labelsSelector, + language: langSelector +}); + +export default connect(selector)(ValueSelector); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js index 7522f8ff..7d52842a 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/ThingsWithThingsWithIntervals.js @@ -14,6 +14,7 @@ import CountSecondLevelContainer from '../containers/CountSecondLevelContainer' import CountFirstLevelContainer from '../containers/CountFirstLevelContainer' import CountZeroLevelContainer from '../containers/CountZeroLevelContainer' import LimiterContainer from '../containers/LimiterContainer' +import LanguageSwitch from "../../../app/containers/LanguageSwitch"; class Configurator extends Component { static propTypes = { @@ -29,6 +30,7 @@ class Configurator extends Component { + From 981450e2794094caa79cd711dc75d78a7c219198 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sat, 13 May 2017 21:26:35 +0200 Subject: [PATCH 36/84] TimeLine: Server Time extraction fixes --- .../TimeLineVisualizerApiController.scala | 16 ++++++++-------- .../assistant/rest/UrlsStartEndRequest.scala | 2 +- .../sparql/rgml/extractor/InstantExtractor.scala | 2 +- .../rgml/extractor/IntervalExtractor.scala | 2 +- .../rdf/sparql/rgml/query/QueryHelpers.scala | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala b/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala index 092f0451..d226d9dc 100644 --- a/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala +++ b/src/app/controllers/assistant/api/visualizers/TimeLineVisualizerApiController.scala @@ -14,30 +14,30 @@ class TimeLineVisualizerApiController(implicit val inj: Injector) extends Visual val rgmlService = inject[RgmlService] val rgmlCountService = inject[RgmlCountService] - def getIntervals(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => + def getIntervals(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request =>json => withEvaluation(ApplicationId(id)) { evaluation => - val intervals = rgmlService.intervals(evaluation, json.begin, json.end, json.urls, json.limit) + val intervals = rgmlService.intervals(evaluation, json.start, json.end, json.urls, json.limit) Future(Ok(SuccessResponse(data = Seq("intervals" -> intervals)))) } } - def getIntervalsCount(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => + def getIntervalsCount(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request =>json => withEvaluation(ApplicationId(id)) { evaluation => - val count = rgmlCountService.intervals(evaluation, json.begin, json.end, json.urls, json.limit) + val count = rgmlCountService.intervals(evaluation, json.start, json.end, json.urls, json.limit) Future(Ok(SuccessResponse(data = Seq("count" -> count)))) } } - def getInstants(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => + def getInstants(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request =>json => withEvaluation(ApplicationId(id)) { evaluation => - val instants = rgmlService.instants(evaluation, json.begin, json.end, json.urls, json.limit) + val instants = rgmlService.instants(evaluation, json.start, json.end, json.urls, json.limit) Future(Ok(SuccessResponse(data = Seq("instants" -> instants)))) } } - def getInstantsCount(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request => json => + def getInstantsCount(id: Long) = RestAsyncAction[UrlsStartEndRequest] { implicit request =>json => withEvaluation(ApplicationId(id)) { evaluation => - val count = rgmlCountService.instants(evaluation, json.begin, json.end, json.urls, json.limit) + val count = rgmlCountService.instants(evaluation, json.start, json.end, json.urls, json.limit) Future(Ok(SuccessResponse(data = Seq("count" -> count)))) } } diff --git a/src/app/model/assistant/rest/UrlsStartEndRequest.scala b/src/app/model/assistant/rest/UrlsStartEndRequest.scala index 3e0e0e79..34b6bea0 100644 --- a/src/app/model/assistant/rest/UrlsStartEndRequest.scala +++ b/src/app/model/assistant/rest/UrlsStartEndRequest.scala @@ -4,7 +4,7 @@ import java.util.Date import play.api.libs.json.Json object UrlsStartEndRequest { - case class UrlsStartEndRequest(urls: Seq[String], begin: Date, end: Date, limit: Int) + case class UrlsStartEndRequest(urls: Seq[String], start: Date, end: Date, limit: Int) implicit val writes = Json.writes[UrlsStartEndRequest] implicit val reads = Json.reads[UrlsStartEndRequest] } diff --git a/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala index f1a936a5..cf9c1db2 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/InstantExtractor.scala @@ -26,7 +26,7 @@ class InstantExtractor extends QueryExecutionResultExtractor[InstantQuery, Seq[I } private def getDate(qs: QuerySolution, fieldName: String): Date = { - val dateFormat = new SimpleDateFormat("yyyy-MM-DD") + val dateFormat = new SimpleDateFormat("yyyy-MM-dd") val fieldValue = qs.getLiteral(fieldName).getString() return dateFormat.parse(fieldValue) } diff --git a/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala b/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala index 5793086f..6d451b85 100644 --- a/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala +++ b/src/app/model/rdf/sparql/rgml/extractor/IntervalExtractor.scala @@ -27,7 +27,7 @@ class IntervalExtractor extends QueryExecutionResultExtractor[IntervalQuery, Seq } private def getDate(qs: QuerySolution, fieldName: String): Date = { - val dateFormat = new SimpleDateFormat("yyyy-MM-DD") + val dateFormat = new SimpleDateFormat("yyyy-MM-dd") val fieldValue = qs.getLiteral(fieldName).getString() val date = dateFormat.parse(fieldValue) return date; diff --git a/src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala b/src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala index fabac522..4691e81f 100644 --- a/src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala +++ b/src/app/model/rdf/sparql/rgml/query/QueryHelpers.scala @@ -36,6 +36,6 @@ object QueryHelpers { } def dateToString(date: Date): String = { - new SimpleDateFormat("YYYY-MM-DD" ).format(date) + new SimpleDateFormat("yyyy-MM-dd" ).format(date) } } From 285070d82da91988dd6bdae5ec64632f9fc37235 Mon Sep 17 00:00:00 2001 From: vvancak Date: Sat, 13 May 2017 22:10:58 +0200 Subject: [PATCH 37/84] TimeLine : Selected Time Record, Time Range & Pages visualizers definitions --- .../modules/visualizers/timeline/api.js | 42 ++++----- .../containers/CountFirstLevelContainer.js | 7 +- .../containers/CountSecondLevelContainer.js | 7 +- .../containers/CountZeroLevelContainer.js | 7 +- .../FirstLevelConnectionContainer.js | 9 +- .../timeline/containers/InstantVisualizer.js | 46 ++++++++++ .../timeline/containers/IntervalVisualizer.js | 51 +++++++++++ .../timeline/containers/LevelsVisualizer.js | 88 +++++++++++++++++++ .../timeline/containers/LimiterContainer.js | 8 +- .../SecondLevelConnectionContainer.js | 5 +- .../containers/TimeLineInstantsContainer.js | 47 ++++++---- .../containers/TimeLineIntervalsContainer.js | 57 +++++++----- .../timeline/containers/TimeRangeContainer.js | 74 ++++++++++++++++ .../visualizers/timeline/ducks/count.js | 14 +-- .../timeline/ducks/selectedTimeRecord.js | 35 ++++++++ .../visualizers/timeline/ducks/timeRange.js | 36 ++++++++ .../visualizers/timeline/misc/TimeLine.js | 8 +- .../timeline/misc/ValueSelector.js | 19 ++-- .../modules/visualizers/timeline/models.js | 5 ++ .../visualizers/timeline/pages/Instants.js | 25 ++++++ .../timeline/pages/InstantsToFirstLevel.js | 48 ++++++++++ .../timeline/pages/InstantsToSecondLevel.js | 58 ++++++++++++ .../visualizers/timeline/pages/Intervals.js | 25 ++++++ .../timeline/pages/IntervalsToFirstLevel.js | 49 +++++++++++ ...Intervals.js => IntervalsToSecondLevel.js} | 28 +++--- .../modules/visualizers/timeline/reducer.js | 4 + 26 files changed, 687 insertions(+), 115 deletions(-) create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InstantVisualizer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/IntervalVisualizer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LevelsVisualizer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRangeContainer.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedTimeRecord.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/timeRange.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Instants.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/InstantsToFirstLevel.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/InstantsToSecondLevel.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Intervals.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/IntervalsToFirstLevel.js rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/{ThingsWithThingsWithIntervals.js => IntervalsToSecondLevel.js} (76%) diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js index 18d69d52..91931828 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js @@ -1,67 +1,67 @@ import rest from '../../../misc/rest' -export async function getIntervals(applicationId, urls, begin, end, limit) { - let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit":limit}; +export async function getIntervals(applicationId, urls, timeRange, limit) { + let payload = { "urls" : urls, "start" : timeRange.begin.getTime(), "end" : timeRange.end.getTime(), "limit" : limit }; const result = await rest('timeLineVisualizer/getIntervals/' + applicationId, payload); return result.data.intervals; } -export async function getInstants(applicationId, urls, begin, end, limit) { - let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit":limit}; +export async function getInstants(applicationId, urls, timeRange, limit) { + let payload = { "urls" : urls, "start" : timeRange.begin.getTime(), "end" : timeRange.end.getTime(), "limit" : limit }; const result = await rest('timeLineVisualizer/getInstants/' + applicationId, payload); return result.data.instants; } export async function getThingsWIntervals(applicationId, things, thingTypes, connections, limit) { - let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit":limit}; + let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : limit}; const result = await rest('timeLineVisualizer/getThingsWIntervals/' + applicationId, payload); return result.data.thingsWithIntervals; } export async function getThingsWInstants(applicationId, things, thingTypes, connections, limit) { - let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit":limit}; + let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : limit}; const result = await rest('timeLineVisualizer/getThingsWInstants/' + applicationId, payload); return result.data.thingsWithInstants; } export async function getThingsWThingsWIntervals(applicationId, things, thingTypes, connections, limit) { - let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": limit}; + let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : limit}; const result = await rest('timeLineVisualizer/getThingsWThingsWIntervals/' + applicationId, payload); return result.data.thingsWithThingsWithIntervals; } export async function getThingsWThingsWInstants(applicationId, things, thingTypes, connections, limit) { - let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": limit}; + let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : limit}; const result = await rest('timeLineVisualizer/getThingsWThingsWInstants/' + applicationId, payload); return result.data.thingsWithThingsWithInstants; } -export async function getIntervalsCount(applicationId, urls, begin, end) { - let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit": -1}; +export async function getIntervalsCount(applicationId, urls, timeRange) { + let payload = { "urls" : urls, "start" : timeRange.begin.getTime(), "end" : timeRange.end.getTime(), "limit" : -1 }; const result = await rest('timeLineVisualizer/getIntervals/count/' + applicationId, payload); return result.data.count.value; } -export async function getInstantsCount(applicationId, urls, begin, end) { - let payload = {"urls":urls, "begin":begin.getTime(), "end":end.getTime(), "limit": -1}; +export async function getInstantsCount(applicationId, urls, timeRange) { + let payload = { "urls" : urls, "start" : timeRange.begin.getTime(), "end" : timeRange.end.getTime(), "limit" : -1 }; const result = await rest('timeLineVisualizer/getInstants/count/' + applicationId, payload); - return result.data.count.value; + return result.data.count; } export async function getThingsWIntervalsCount(applicationId, things, thingTypes, connections) { - let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit": -1}; + let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : -1}; const result = await rest('timeLineVisualizer/getThingsWIntervals/count/' + applicationId, payload); - return result.data.count.value; + return result.data.count; } export async function getThingsWInstantsCount(applicationId, things, thingTypes, connections) { - let payload = {"things":things, "thingTypes":thingTypes, "connections":connections, "limit": -1}; + let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : -1}; const result = await rest('timeLineVisualizer/getThingsWInstants/count/' + applicationId, payload); - return result.data.count.value; + return result.data.count; } export async function getThingsWThingsWIntervalsCount(applicationId, things, thingTypes, connections) { - let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": -1}; + let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : -1 }; const result = await rest('timeLineVisualizer/getThingsWThingsWIntervals/count/' + applicationId, payload); - return result.data.count.value; + return result.data.count; } export async function getThingsWThingsWInstantsCount(applicationId, things, thingTypes, connections) { - let payload = {"things": things, "thingTypes":thingTypes, "connections": connections, "limit": -1}; + let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : -1 }; const result = await rest('timeLineVisualizer/getThingsWThingsWInstants/count/' + applicationId, payload); - return result.data.count.value; + return result.data.count; } \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js index c6b23e1a..73d1931e 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js @@ -1,10 +1,11 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' -import { getCountReset, countFirstSelector, countFirstStatusSelector} from '../ducks/count' -import { firstLevelSelector, firstLevelStatusSelector} from '../ducks/firstLevel' import { createStructuredSelector } from "reselect"; import { PromiseStatus } from "../../../core/models"; +import { getCountReset, countFirstSelector, countFirstStatusSelector} from '../ducks/count' +import { firstLevelSelector, firstLevelStatusSelector} from '../ducks/firstLevel' + import PromiseResult from "../../../core/components/PromiseResult"; import CenteredMessage from "../../../../components/CenteredMessage"; @@ -12,7 +13,7 @@ class CountFirstLevelContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - count: PropTypes.instanceOf(Number).isRequired, + count: PropTypes.number.isRequired, countStatus: PropTypes.instanceOf(PromiseStatus).isRequired, things: PropTypes.instanceOf(Array).isRequired, diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js index 49758398..8c73bfb3 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js @@ -1,10 +1,11 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' -import { getCountReset, countSecondSelector, countSecondStatusSelector} from '../ducks/count' -import { secondLevelSelector, secondLevelStatusSelector} from '../ducks/secondLevel' import { createStructuredSelector } from "reselect"; import { PromiseStatus } from "../../../core/models"; +import { getCountReset, countSecondSelector, countSecondStatusSelector} from '../ducks/count' +import { secondLevelSelector, secondLevelStatusSelector} from '../ducks/secondLevel' + import PromiseResult from "../../../core/components/PromiseResult"; import CenteredMessage from "../../../../components/CenteredMessage"; @@ -12,7 +13,7 @@ class CountSecondLevelContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - count: PropTypes.instanceOf(Number).isRequired, + count: PropTypes.number.isRequired, countStatus: PropTypes.instanceOf(PromiseStatus).isRequired, things: PropTypes.instanceOf(Array).isRequired, diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js index de270f9d..02dce18c 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js @@ -1,10 +1,11 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' +import { createStructuredSelector } from "reselect"; +import { PromiseStatus } from "../../../core/models"; + import { getCountReset, countZeroSelector, countZeroStatusSelector} from '../ducks/count' import { intervalsSelector, intervalsStatusSelector} from '../ducks/intervals' import { instantsSelector, instantsStatusSelector} from '../ducks/instants' -import { createStructuredSelector } from "reselect"; -import { PromiseStatus } from "../../../core/models"; import PromiseResult from "../../../core/components/PromiseResult"; import CenteredMessage from "../../../../components/CenteredMessage"; @@ -13,7 +14,7 @@ class CountZeroLevelContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - count: PropTypes.instanceOf(Number).isRequired, + count: PropTypes.number.isRequired, countStatus: PropTypes.instanceOf(PromiseStatus).isRequired, intervals: PropTypes.instanceOf(Array).isRequired, diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js index 6e37c360..8ace38f2 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelConnectionContainer.js @@ -1,12 +1,13 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' +import { PromiseStatus } from '../../../core/models' +import { createStructuredSelector } from "reselect"; + import { getFirstLevelReset, firstLevelSelector, firstLevelStatusSelector } from '../ducks/firstLevel' import { secondLevelSelector } from '../ducks/secondLevel' import { limitSelector } from '../ducks/limit' import { setSelectTypeFL, setUnSelectTypeFL, getSelectedTypeFLReset, selectedTypeFLSelector } from '../ducks/selectedTypeFirstLevel' import { setSelectConnFL, setUnSelectConnFL, getSelectedConnFLReset, selectedConnFLSelector } from '../ducks/selectedConnFirstLevel' -import { PromiseStatus } from '../../../core/models' -import { createStructuredSelector } from "reselect"; import PromiseResult from '../../../core/components/PromiseResult' import ConfigToolbar from '../misc/ValueSelector' @@ -17,7 +18,7 @@ import Button from "../../../../components/Button"; class FirstLevelConnectionContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - isInitial: PropTypes.instanceOf(Boolean), + isInitial: PropTypes.bool, // Levels firstLevel: PropTypes.instanceOf(Array).isRequired, @@ -32,7 +33,7 @@ class FirstLevelConnectionContainer extends Component { selectedTypeFL: PropTypes.instanceOf(Array).isRequired, selectedConnFL: PropTypes.instanceOf(Array).isRequired, - limit: PropTypes.instanceOf(Number).isRequired + limit: PropTypes.number.isRequired }; componentWillMount(){ diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InstantVisualizer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InstantVisualizer.js new file mode 100644 index 00000000..77db8e4e --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InstantVisualizer.js @@ -0,0 +1,46 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from "reselect"; +import CenteredMessage from "../../../../components/CenteredMessage"; + +import { selectedTimeRecordSelector } from '../ducks/selectedTimeRecord' + +import Label from "../../../app/containers/Label"; +import LevelsVisualizer from "./LevelsVisualizer"; + +class InstantVisualizer extends Component { + static propTypes = { + selectedTimeRecord: PropTypes.instanceOf(Array).isRequired + }; + + render() { + const {selectedTimeRecord} = this.props; + + if (selectedTimeRecord.length == 0) { + return Select events on the Time Line to view them. + } + + var instant = selectedTimeRecord[0]; + return
    + + + + + + + + + + + +
    Name:
    Date:{new Date(instant.date).toDateString()}
    + +
    + } +} + +const selector = createStructuredSelector({ + selectedTimeRecord: selectedTimeRecordSelector, +}); + +export default connect(selector)(InstantVisualizer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/IntervalVisualizer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/IntervalVisualizer.js new file mode 100644 index 00000000..f47fd6fa --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/IntervalVisualizer.js @@ -0,0 +1,51 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from "reselect"; +import CenteredMessage from "../../../../components/CenteredMessage"; + +import { selectedTimeRecordSelector } from '../ducks/selectedTimeRecord' + +import Label from "../../../app/containers/Label"; +import LevelsVisualizer from "./LevelsVisualizer"; + +class IntervalVisualizer extends Component { + static propTypes = { + selectedTimeRecord: PropTypes.instanceOf(Array).isRequired + }; + + render() { + const {selectedTimeRecord} = this.props; + + if (selectedTimeRecord.length == 0) { + return Select events on the Time Line to view them. + } + + var interval = selectedTimeRecord[0]; + return
    + + + + + + + + + + + + + + + +
    Name:
    Begin:{new Date(interval.begin).toDateString()}
    End:{new Date(interval.end).toDateString()}
    + +
    + + } +} + +const selector = createStructuredSelector({ + selectedTimeRecord: selectedTimeRecordSelector, +}); + +export default connect(selector)(IntervalVisualizer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LevelsVisualizer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LevelsVisualizer.js new file mode 100644 index 00000000..aa092da2 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LevelsVisualizer.js @@ -0,0 +1,88 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from "reselect"; + +import { selectedTimeRecordSelector } from '../ducks/selectedTimeRecord' +import { firstLevelSelector} from '../ducks/firstLevel' +import { secondLevelSelector } from '../ducks/secondLevel' + +import Label from "../../../app/containers/Label"; +import SubHeadLine from "../../../../components/Subheadline" + +class LevelsVisualizer extends Component { + static propTypes = { + timeRecordUrl: PropTypes.string.isRequired, + firstLevel: PropTypes.instanceOf(Array).isRequired, + secondLevel: PropTypes.instanceOf(Array).isRequired + }; + + renderConnection(conn){ + return
    + + + + + + + + + + + + + + + + + + + +
    Name:
    Type:
    Connected by:
    Connected to:
    +
    + } + + render() { + const {timeRecordUrl, firstLevel, secondLevel} = this.props; + + var matchingFirstLevel = []; + for (let conn of firstLevel) { + if (conn.inner == timeRecordUrl) matchingFirstLevel.push(conn) + } + + var firstVis; + if (matchingFirstLevel.length > 0){ + firstVis =
    + + {matchingFirstLevel.map(m=>this.renderConnection(m))} +
    + } + + var matchingSecondLevel = []; + for (let i of matchingFirstLevel){ + for (let j of secondLevel){ + if (i.outer == j.inner) matchingSecondLevel.push(j) + } + } + var secondVis; + if (matchingSecondLevel.length > 0){ + secondVis =
    + + {matchingSecondLevel.map(m=>this.renderConnection(m))} +
    + } + + return
    + {firstVis} + {secondVis} +
    + + } +} + +const selector = createStructuredSelector({ + selectedTimeRecord: selectedTimeRecordSelector, + firstLevel: firstLevelSelector, + secondLevel: secondLevelSelector +}); + +export default connect(selector)(LevelsVisualizer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js index 5bb71943..dc7fcfd2 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js @@ -1,13 +1,15 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' -import { getLimitReset, setLimit, limitSelector, limit_default} from '../ducks/limit' import { createStructuredSelector } from "reselect"; + +import { getLimitReset, setLimit, limitSelector, limit_default} from '../ducks/limit' + import Button from "../../../../components/Button"; class LimiterContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - limit: PropTypes.instanceOf(Number).isRequired + limit: PropTypes.number.isRequired }; componentWillUnmount() { @@ -42,6 +44,7 @@ class LimiterContainer extends Component { var resetEnabled = limit != limit_default; return
    + @@ -51,6 +54,7 @@ class LimiterContainer extends Component { label="RESET" /> +
    LIMIT this.setLimit()}/>
    diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js index 2a874f83..2bd8814f 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js @@ -1,5 +1,6 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' + import { getSecondLevelReset, secondLevelSelector, secondLevelStatusSelector } from '../ducks/secondLevel' import { limitSelector } from '../ducks/limit' import { setSelectThingSL, setUnSelectThingSL, getSelectedThingSLReset, selectedThingSLSelector } from '../ducks/selectedThingSecondLevel' @@ -15,7 +16,7 @@ import Button from "../../../../components/Button"; class SecondLevelConnectionContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - isInitial: PropTypes.instanceOf(Boolean), + isInitial: PropTypes.bool, // Levels secondLevel: PropTypes.instanceOf(Array).isRequired, @@ -29,7 +30,7 @@ class SecondLevelConnectionContainer extends Component { selectedThingSL: PropTypes.instanceOf(Array).isRequired, selectedConnSL: PropTypes.instanceOf(Array).isRequired, - limit: PropTypes.instanceOf(Number).isRequired + limit: PropTypes.number.isRequired }; componentWillMount(){ diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js index e4598652..d06f81a6 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js @@ -1,11 +1,15 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' +import { createStructuredSelector } from "reselect"; +import { PromiseStatus } from '../../../core/models' +import { TimeRange } from "../models"; + import { getInstants, getInstantsReset, instantsSelector, instantsStatusSelector } from '../ducks/instants' import { getInstantsCount } from '../ducks/count' import { limitSelector } from '../ducks/limit' +import { timeRangeSelector } from '../ducks/timeRange' import { firstLevelSelector } from '../ducks/firstLevel' -import { PromiseStatus } from '../../../core/models' -import {createStructuredSelector} from "reselect"; +import { setSelectTimeRecord, getSelectTimeRecordReset } from '../ducks/selectedTimeRecord' import PromiseResult from '../../../core/components/PromiseResult' import TimeLine from '../misc/TimeLine' @@ -14,7 +18,7 @@ import CenteredMessage from '../../../../components/CenteredMessage' class TimeLineInstantsContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - isInitial: PropTypes.instanceOf(Boolean), + isInitial: PropTypes.bool, // Levels firstLevel: PropTypes.instanceOf(Array).isRequired, @@ -23,34 +27,36 @@ class TimeLineInstantsContainer extends Component { instants: PropTypes.instanceOf(Array).isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired, - limit: PropTypes.instanceOf(Number).isRequired + // Loading settings + timeRange: PropTypes.instanceOf(TimeRange).isRequired, + limit: PropTypes.number.isRequired }; componentWillMount() { - const {dispatch, limit} = this.props; + const {dispatch, timeRange, limit} = this.props; this.className = "timeseries-chart"; - this.chart = new TimeLine(this.className, () => { - }); // TODO: callback + this.chart = new TimeLine(this.className, (r)=>dispatch(setSelectTimeRecord(r))); - this.begin = new Date("2000-01-01"); - this.end = new Date("2018-01-01"); if (this.props.isInitial) { - dispatch(getInstants([], this.start, this.end, limit)); - dispatch(getInstantsCount([], this.start, this.end, limit)); + dispatch(getInstants([], timeRange, limit)); + dispatch(getInstantsCount([], timeRange)); } } componentWillReceiveProps(nextProps) { - const {dispatch, firstLevel, limit} = this.props; + const {dispatch, firstLevel, timeRange, limit} = this.props; - if (firstLevel != nextProps.firstLevel) { + var needUpdate = (firstLevel != nextProps.firstLevel || timeRange != nextProps.timeRange); + + if (needUpdate) { var urls = nextProps.firstLevel.map(t => t.inner); - dispatch(getInstants(urls, this.begin, this.end, limit)); - dispatch(getInstantsCount(urls, this.begin, this.end, limit)); + dispatch(getInstants(urls, nextProps.timeRange, limit)); + dispatch(getInstantsCount(urls, nextProps.timeRange)); } if (nextProps.status.done && nextProps.instants != this.props.instants) { + dispatch(getSelectTimeRecordReset()); this.needChartUpdate = true; } } @@ -59,12 +65,16 @@ class TimeLineInstantsContainer extends Component { const { instants } = this.props; if (this.needChartUpdate) { this.chart.instants(instants); + this.needChartUpdate = false; } } componentWillUnmount() { const {dispatch} = this.props; + dispatch(getInstantsReset()); + dispatch(getSelectTimeRecordReset()); + this.chart.destroy(); } @@ -85,10 +95,11 @@ class TimeLineInstantsContainer extends Component { } const selector = createStructuredSelector({ - instants: instantsSelector, - status: instantsStatusSelector, + instants: instantsSelector, + status: instantsStatusSelector, firstLevel: firstLevelSelector, - limit: limitSelector + timeRange: timeRangeSelector, + limit: limitSelector }); export default connect(selector)(TimeLineInstantsContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js index d025187b..f42ba62f 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js @@ -1,11 +1,15 @@ import React, { Component, PropTypes } from 'react' import { connect } from 'react-redux' +import { createStructuredSelector } from "reselect"; +import { PromiseStatus } from '../../../core/models' +import { TimeRange } from "../models"; + import { getIntervals, getIntervalsReset, intervalsSelector, intervalsStatusSelector } from '../ducks/intervals' import { getIntervalsCount } from '../ducks/count' import { limitSelector } from '../ducks/limit' +import { timeRangeSelector } from '../ducks/timeRange' import { firstLevelSelector } from '../ducks/firstLevel' -import { PromiseStatus } from '../../../core/models' -import {createStructuredSelector} from "reselect"; +import { setSelectTimeRecord, getSelectTimeRecordReset } from '../ducks/selectedTimeRecord' import PromiseResult from '../../../core/components/PromiseResult' import TimeLine from '../misc/TimeLine' @@ -14,58 +18,66 @@ import CenteredMessage from '../../../../components/CenteredMessage' class TimeLineIntervalsContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - isInitial: PropTypes.instanceOf(Boolean), + isInitial: PropTypes.bool, // Levels firstLevel: PropTypes.instanceOf(Array).isRequired, - // Intervals loading + // Instants loading intervals: PropTypes.instanceOf(Array).isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired, - limit: PropTypes.instanceOf(Number).isRequired + // Loading settings + timeRange: PropTypes.instanceOf(TimeRange).isRequired, + limit: PropTypes.number.isRequired }; componentWillMount() { - const {dispatch, limit} = this.props; + const {dispatch, timeRange, limit} = this.props; this.className = "timeseries-chart"; - this.chart = new TimeLine(this.className, () => { - }); // TODO: callback - - this.begin = new Date("2000-01-01"); - this.end = new Date("2018-01-01"); + this.chart = new TimeLine(this.className, (r)=>dispatch(setSelectTimeRecord(r))); if (this.props.isInitial) { - dispatch(getIntervals([], this.start, this.end, limit)) - dispatch(getIntervalsCount([], this.start, this.end, this.limit)); + dispatch(getIntervals([], timeRange, limit)) + dispatch(getIntervalsCount([], timeRange, this.limit)); } } componentWillReceiveProps(nextProps) { - const {dispatch, firstLevel, limit} = this.props; + const {dispatch, intervals, firstLevel, timeRange, limit} = this.props; - if (firstLevel != nextProps.firstLevel) { + var needUpdate = (firstLevel != nextProps.firstLevel || timeRange != nextProps.timeRange); + + if (needUpdate){ var urls = nextProps.firstLevel.map(t => t.inner); - dispatch(getIntervals(urls, this.begin, this.end, limit)); - dispatch(getIntervalsCount(urls, this.begin, this.end, limit)); + dispatch(getIntervals(urls, nextProps.timeRange, limit)); + dispatch(getIntervalsCount(urls, nextProps.timeRange, limit)); } - if (nextProps.status.done && nextProps.intervals != this.props.intervals) { - this.needChartUpdate = true; + if (nextProps.status.done) { + if (nextProps.intervals != intervals || nextProps.timeRange != timeRange) { + dispatch(getSelectTimeRecordReset()); + this.needChartUpdate = true; + } } } componentDidUpdate() { const { intervals } = this.props; + if (this.needChartUpdate) { this.chart.intervals(intervals); + this.needChartUpdate = false; } } componentWillUnmount(){ const {dispatch} = this.props; + dispatch(getIntervalsReset()); + dispatch(getSelectTimeRecordReset()); + this.chart.destroy(); } @@ -86,10 +98,11 @@ class TimeLineIntervalsContainer extends Component { } const selector = createStructuredSelector({ - intervals: intervalsSelector, - status: intervalsStatusSelector, + intervals: intervalsSelector, + status: intervalsStatusSelector, firstLevel: firstLevelSelector, - limit: limitSelector + timeRange: timeRangeSelector, + limit: limitSelector }); export default connect(selector)(TimeLineIntervalsContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRangeContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRangeContainer.js new file mode 100644 index 00000000..89d121d2 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRangeContainer.js @@ -0,0 +1,74 @@ +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from "reselect"; +import {TimeRange} from "../models"; +import moment from 'moment' + +import { setSelectTime, getSelectedTimeReset, timeRangeSelector } from '../ducks/timeRange' + +import Button from "../../../../components/Button"; + +class TimeRangeContainer extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + timeRange: PropTypes.instanceOf(TimeRange).isRequired + }; + + + componentWillUnmount(){ + const { dispatch } = this.props; + dispatch(getSelectedTimeReset()); + } + + setTimeRange(){ + const { dispatch } = this.props; + + var begin = document.getElementsByName("begin_input")[0].value; + var end = document.getElementsByName("end_input")[0].value; + + dispatch(setSelectTime(new Date(begin), new Date(end))); + } + + render() { + const { timeRange } = this.props; + + var beginString = moment(timeRange.begin).format('YYYY-MM-DD'); + var endString = moment(timeRange.end).format('YYYY-MM-DD'); + + return
    + + + + + + + + + + + +
    Time Range from to + +
    +
    + + } +} + +const selector = createStructuredSelector({ + timeRange: timeRangeSelector +}); + +export default connect(selector)(TimeRangeContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/count.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/count.js index f8b984d2..056ebc91 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/count.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/count.js @@ -14,16 +14,16 @@ import moduleSelector from '../selector' export const GET_COUNT_ZERO = prefix('GET_COUNT_ZERO'); export const GET_COUNT_ZERO_SUCCESS = GET_COUNT_ZERO + "_SUCCESS"; -export function getIntervalsCount(urls,begin,end){ +export function getIntervalsCount(urls, timeRange){ return withApplicationId(id => { - const promise = api.getIntervalsCount(id, urls, begin, end); + const promise = api.getIntervalsCount(id, urls, timeRange); return createAction(GET_COUNT_ZERO, { promise }); }); } -export function getInstantsCount(urls,begin,end){ +export function getInstantsCount(urls, timeRange){ return withApplicationId(id => { - const promise = api.getInstantsCount(id, urls, begin, end); + const promise = api.getInstantsCount(id, urls, timeRange); return createAction(GET_COUNT_ZERO, { promise }); }); } @@ -78,11 +78,11 @@ export default function countReducer(state = initialState, action) { case GET_COUNT_RES: return initialState; case GET_COUNT_ZERO_SUCCESS: - return new Count({"zero": action.payload, "first": state.first, "second":state.second}); + return new Count({"zero": action.payload.value, "first": state.first, "second":state.second}); case GET_COUNT_FIRST_SUCCESS: - return new Count({"zero": state.zero, "first": action.payload, "second":state.second}); + return new Count({"zero": state.zero, "first": action.payload.value, "second":state.second}); case GET_COUNT_SECOND_SUCCESS: - return new Count({"zero": state.zero, "first": state.first, "second":action.payload}); + return new Count({"zero": state.zero, "first": state.first, "second":action.payload.value}); } return state; }; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedTimeRecord.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedTimeRecord.js new file mode 100644 index 00000000..622367bf --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/selectedTimeRecord.js @@ -0,0 +1,35 @@ +import createAction from '../../../../misc/createAction' +import prefix from '../prefix' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { createSelector } from 'reselect' +import moduleSelector from '../selector' + +// Actions +export const SET_SELECT_TIME_RECORD = prefix('SET_SELECT_TIME_RECORD'); +export const GET_SELECTED_TIME_RECORD_RESET = prefix("GET_SELECTED_TIME_RECORD_RESET"); + +export function setSelectTimeRecord(rec) { + return createAction(SET_SELECT_TIME_RECORD, { rec }); +} + + +export function getSelectTimeRecordReset() { + return createAction(GET_SELECTED_TIME_RECORD_RESET); +} + +// Reducer +const initialState = []; +export default function selectedTRReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_SELECTED_TIME_RECORD_RESET: + return initialState; + case SET_SELECT_TIME_RECORD: + return [action.payload.rec]; + } + return state; +}; + +// Selectors +export const selectedTimeRecordSelector = createSelector([moduleSelector], state => state.selectedTimeRecord); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/timeRange.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/timeRange.js new file mode 100644 index 00000000..df620084 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/timeRange.js @@ -0,0 +1,36 @@ +import createAction from '../../../../misc/createAction' +import prefix from '../prefix' +import { GET_APPLICATION_START } from '../../../app/ducks/application' +import { createSelector } from 'reselect' +import moduleSelector from '../selector' + +import { TimeRange } from '../models' + +// Actions +export const SET_SELECT_TIME = prefix('SET_SELECT_TIME'); +export const GET_SELECT_TIME_RESET = prefix("GET_SELECT_TIME_RESET"); + +export function setSelectTime(begin, end) { + return createAction(SET_SELECT_TIME, { begin, end }); +} + +export function getSelectedTimeReset() { + return createAction(GET_SELECT_TIME_RESET); +} + +// Reducer +const initialState = new TimeRange(); +export default function timeRangeReducer(state = initialState, action) { + switch (action.type) { + case GET_APPLICATION_START: + return initialState; + case GET_SELECT_TIME_RESET: + return initialState; + case SET_SELECT_TIME: + return new TimeRange(action.payload); + } + return state; +}; + +// Selectors +export const timeRangeSelector = createSelector([moduleSelector], state => state.timeRange); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js index 60641833..a05376ac 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/TimeLine.js @@ -142,9 +142,7 @@ class TimeLine { return y(getTime(d.date)); }) .attr("r", size.radius) - .on("click", function (d) { - callback(d); - }); + .on("click", callback); }; // intervals => rectangles @@ -170,9 +168,7 @@ class TimeLine { return ( e - b ) + 20; // TODO: No data, fixed intervals. }) .attr("height", size.height) - .on("click", function (d) { - callback(d); - }); + .on("click", callback); }; drawFunc(); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ValueSelector.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ValueSelector.js index 39525a12..b0d44af7 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ValueSelector.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/misc/ValueSelector.js @@ -4,6 +4,8 @@ import { createStructuredSelector } from "reselect"; import { getLabels, labelsSelector} from "../../../app/ducks/labels" import { langSelector } from "../../../app/ducks/lang" +import { Map as immutableMap} from 'immutable' + import Checkbox from "../../../../components/Checkbox" import Button from "../../../../components/Button" import SubHeadLine from "../../../../components/Subheadline" @@ -15,8 +17,8 @@ class ValueSelector extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, - labels: PropTypes.instanceOf(Map).isRequired, - language: PropTypes.instanceOf(Object).isRequired, + labels: PropTypes.instanceOf(immutableMap).isRequired, + language: PropTypes.string.isRequired, things: PropTypes.array.isRequired, header: PropTypes.string.isRequired, @@ -56,12 +58,11 @@ class ValueSelector extends Component { SEARCH: this.setNeedle()}/> - +
    } } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Instants.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Instants.js index 772391cd..dbd5d5cb 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Instants.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Instants.js @@ -1,20 +1,16 @@ -import React, { Component } from 'react' +import React, {Component} from "react"; -import BodyPadding from '../../../../components/BodyPadding' -import TimeLineInstantsContainer from '../containers/TimeLineInstantsContainer' -import CountZeroLevelContainer from '../containers/CountZeroLevelContainer' -import InstantVisualizer from '../containers/InstantVisualizer' -import LimiterContainer from '../containers/LimiterContainer' -import TimeRangeContainer from "../containers/TimeRangeContainer" +import BodyPadding from "../../../../components/BodyPadding"; +import TimeLineInstantsContainer from "../containers/TimeLineInstantsContainer"; +import InstantVisualizer from "../containers/InstantVisualizer"; +import LimiterContainer from "../containers/LimiterContainer"; class Instants extends Component { render() { return ( - -
    diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/InstantsToFirstLevel.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/InstantsToFirstLevel.js index 2db28c1b..666db73d 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/InstantsToFirstLevel.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/InstantsToFirstLevel.js @@ -1,16 +1,13 @@ -import React, { Component } from 'react' +import React, {Component} from "react"; -import { getFirstLevelInstants } from '../ducks/firstLevel' -import { getFirstLevelInstantsCount } from '../ducks/count' +import {getFirstLevelInstants} from "../ducks/firstLevel"; +import {getFirstLevelInstantsCount} from "../ducks/count"; -import BodyPadding from '../../../../components/BodyPadding' -import FirstLevelConnectionContainer from '../containers/FirstLevelConnectionContainer' -import TimeLineInstantsContainer from '../containers/TimeLineInstantsContainer' -import CountFirstLevelContainer from '../containers/CountFirstLevelContainer' -import CountZeroLevelContainer from '../containers/CountZeroLevelContainer' -import LimiterContainer from '../containers/LimiterContainer' -import InstantVisualizer from '../containers/InstantVisualizer' -import TimeRangeContainer from "../containers/TimeRangeContainer" +import BodyPadding from "../../../../components/BodyPadding"; +import FirstLevelConnectionContainer from "../containers/FirstLevelConnectionContainer"; +import TimeLineInstantsContainer from "../containers/TimeLineInstantsContainer"; +import LimiterContainer from "../containers/LimiterContainer"; +import InstantVisualizer from "../containers/InstantVisualizer"; class InstantsToFirstLevel extends Component { render() { @@ -22,22 +19,19 @@ class InstantsToFirstLevel extends Component { - + -
    - -
    diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/InstantsToSecondLevel.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/InstantsToSecondLevel.js index c62af4ec..c807db01 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/InstantsToSecondLevel.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/InstantsToSecondLevel.js @@ -1,19 +1,15 @@ -import React, { Component } from 'react' +import React, {Component} from "react"; -import { getFirstLevelInstants } from '../ducks/firstLevel' -import { getFirstLevelInstantsCount, getSecondLevelInstantsCount} from '../ducks/count' -import { getSecondLevelInstants } from '../ducks/secondLevel' +import {getFirstLevelInstants} from "../ducks/firstLevel"; +import {getFirstLevelInstantsCount, getSecondLevelInstantsCount} from "../ducks/count"; +import {getSecondLevelInstants} from "../ducks/secondLevel"; -import BodyPadding from '../../../../components/BodyPadding' -import SecondLevelConnectionContainer from '../containers/SecondLevelConnectionContainer' -import FirstLevelConnectionContainer from '../containers/FirstLevelConnectionContainer' -import TimeLineInstantsContainer from '../containers/TimeLineInstantsContainer' -import CountSecondLevelContainer from '../containers/CountSecondLevelContainer' -import CountFirstLevelContainer from '../containers/CountFirstLevelContainer' -import CountZeroLevelContainer from '../containers/CountZeroLevelContainer' -import LimiterContainer from '../containers/LimiterContainer' -import InstantVisualizer from '../containers/InstantVisualizer' -import TimeRangeContainer from "../containers/TimeRangeContainer" +import BodyPadding from "../../../../components/BodyPadding"; +import SecondLevelConnectionContainer from "../containers/SecondLevelConnectionContainer"; +import FirstLevelConnectionContainer from "../containers/FirstLevelConnectionContainer"; +import TimeLineInstantsContainer from "../containers/TimeLineInstantsContainer"; +import LimiterContainer from "../containers/LimiterContainer"; +import InstantVisualizer from "../containers/InstantVisualizer"; class InstantsToSecondLevel extends Component { render() { @@ -25,29 +21,25 @@ class InstantsToSecondLevel extends Component { - + - - + -
    - -
    diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Intervals.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Intervals.js index 000562c3..57423c87 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Intervals.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Intervals.js @@ -1,20 +1,16 @@ -import React, { Component } from 'react' +import React, {Component} from "react"; -import BodyPadding from '../../../../components/BodyPadding' -import TimeLineIntervalsContainer from '../containers/TimeLineIntervalsContainer' -import CountZeroLevelContainer from '../containers/CountZeroLevelContainer' -import LimiterContainer from '../containers/LimiterContainer' -import IntervalVisualizer from '../containers/IntervalVisualizer' -import TimeRangeContainer from "../containers/TimeRangeContainer"; +import BodyPadding from "../../../../components/BodyPadding"; +import TimeLineIntervalsContainer from "../containers/TimeLineIntervalsContainer"; +import LimiterContainer from "../containers/LimiterContainer"; +import IntervalVisualizer from "../containers/IntervalVisualizer"; class Intervals extends Component { render() { return ( - -
    diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/IntervalsToFirstLevel.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/IntervalsToFirstLevel.js index dcb6a6a7..e6d64de3 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/IntervalsToFirstLevel.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/IntervalsToFirstLevel.js @@ -1,17 +1,14 @@ -import React, { Component } from 'react' +import React, {Component} from "react"; -import { getFirstLevelIntervals } from '../ducks/firstLevel' -import { getFirstLevelIntervalsCount } from '../ducks/count' +import {getFirstLevelIntervals} from "../ducks/firstLevel"; +import {getFirstLevelIntervalsCount} from "../ducks/count"; -import BodyPadding from '../../../../components/BodyPadding' +import BodyPadding from "../../../../components/BodyPadding"; -import FirstLevelConnectionContainer from '../containers/FirstLevelConnectionContainer' -import TimeLineIntervalsContainer from '../containers/TimeLineIntervalsContainer' -import CountFirstLevelContainer from '../containers/CountFirstLevelContainer' -import CountZeroLevelContainer from '../containers/CountZeroLevelContainer' -import LimiterContainer from '../containers/LimiterContainer' -import IntervalVisualizer from '../containers/IntervalVisualizer' -import TimeRangeContainer from "../containers/TimeRangeContainer"; +import FirstLevelConnectionContainer from "../containers/FirstLevelConnectionContainer"; +import TimeLineIntervalsContainer from "../containers/TimeLineIntervalsContainer"; +import LimiterContainer from "../containers/LimiterContainer"; +import IntervalVisualizer from "../containers/IntervalVisualizer"; class IntervalsToFirstLevel extends Component { render() { @@ -23,22 +20,19 @@ class IntervalsToFirstLevel extends Component { - + -
    - -
    diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/IntervalsToSecondLevel.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/IntervalsToSecondLevel.js index c7c999f9..d806a24b 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/IntervalsToSecondLevel.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/IntervalsToSecondLevel.js @@ -1,20 +1,16 @@ -import React, { Component } from 'react' +import React, {Component} from "react"; -import { getFirstLevelIntervals } from '../ducks/firstLevel' -import { getFirstLevelIntervalsCount, getSecondLevelIntervalsCount} from '../ducks/count' -import { getSecondLevelIntervals } from '../ducks/secondLevel' +import {getFirstLevelIntervals} from "../ducks/firstLevel"; +import {getFirstLevelIntervalsCount, getSecondLevelIntervalsCount} from "../ducks/count"; +import {getSecondLevelIntervals} from "../ducks/secondLevel"; -import BodyPadding from '../../../../components/BodyPadding' +import BodyPadding from "../../../../components/BodyPadding"; -import SecondLevelConnectionContainer from '../containers/SecondLevelConnectionContainer' -import FirstLevelConnectionContainer from '../containers/FirstLevelConnectionContainer' -import TimeLineIntervalsContainer from '../containers/TimeLineIntervalsContainer' -import CountSecondLevelContainer from '../containers/CountSecondLevelContainer' -import CountFirstLevelContainer from '../containers/CountFirstLevelContainer' -import CountZeroLevelContainer from '../containers/CountZeroLevelContainer' -import LimiterContainer from '../containers/LimiterContainer' -import IntervalVisualizer from '../containers/IntervalVisualizer' -import TimeRangeContainer from "../containers/TimeRangeContainer"; +import SecondLevelConnectionContainer from "../containers/SecondLevelConnectionContainer"; +import FirstLevelConnectionContainer from "../containers/FirstLevelConnectionContainer"; +import TimeLineIntervalsContainer from "../containers/TimeLineIntervalsContainer"; +import LimiterContainer from "../containers/LimiterContainer"; +import IntervalVisualizer from "../containers/IntervalVisualizer"; class IntervalsToSecondLevel extends Component { render() { @@ -26,29 +22,25 @@ class IntervalsToSecondLevel extends Component { - + - - + -
    - -
    From 0c839202196b5ef96343c69ba24fe03dc3e053be Mon Sep 17 00:00:00 2001 From: vvancak Date: Sun, 21 May 2017 16:52:02 +0200 Subject: [PATCH 43/84] TimeLine: Routes, Bundles, Code autoformat --- .../javascripts/entries/timeline-instants.js | 4 ++ .../javascripts/entries/timeline-intervals.js | 4 ++ .../entries/timeline-things-instants.js | 5 ++ .../entries/timeline-things-intervals.js | 4 ++ .../timeline-things-things-instants.js | 6 +++ .../timeline-things-things-intervals.js | 5 ++ .../assistant/javascripts/entries/timeline.js | 4 -- .../javascripts/modules/visualizers/routes.js | 14 ++++- .../modules/visualizers/timeline/api.js | 26 +++++----- .../visualizers/timeline/applicationRoutes.js | 27 ---------- .../components/instants/applicationRoutes.js | 14 +++++ .../components/instants/configuratorRoutes.js | 10 ++++ .../timeline/components/instants/prefix.js | 5 ++ .../components/intervals/applicationRoutes.js | 14 +++++ .../intervals/configuratorRoutes.js | 10 ++++ .../timeline/components/intervals/prefix.js | 5 ++ .../thingsInstants/applicationRoutes.js | 14 +++++ .../thingsInstants/configuratorRoutes.js | 10 ++++ .../components/thingsInstants/prefix.js | 5 ++ .../thingsIntervals/applicationRoutes.js | 14 +++++ .../thingsIntervals/configuratorRoutes.js | 10 ++++ .../components/thingsIntervals/prefix.js | 5 ++ .../thingsThingsInstants/applicationRoutes.js | 14 +++++ .../configuratorRoutes.js | 10 ++++ .../components/thingsThingsInstants/prefix.js | 5 ++ .../applicationRoutes.js | 14 +++++ .../configuratorRoutes.js | 10 ++++ .../thingsThingsIntervals/prefix.js | 5 ++ .../timeline/configuratorRoutes.js | 10 ---- .../containers/CountFirstLevelContainer.js | 17 ++++--- .../containers/CountSecondLevelContainer.js | 17 ++++--- .../containers/CountZeroLevelContainer.js | 16 +++--- .../timeline/containers/InstantVisualizer.js | 10 ++-- .../timeline/containers/IntervalVisualizer.js | 8 +-- .../timeline/containers/LevelsVisualizer.js | 28 +++++----- .../timeline/containers/LimiterContainer.js | 14 ++--- .../containers/TimeLineInstantsContainer.js | 50 +++++++++--------- .../containers/TimeLineIntervalsContainer.js | 51 ++++++++++--------- .../timeline/containers/TimeRangeContainer.js | 36 ++++++------- .../visualizers/timeline/ducks/count.js | 40 +++++++-------- .../visualizers/timeline/ducks/firstLevel.js | 28 +++++----- .../visualizers/timeline/ducks/instants.js | 22 ++++---- .../visualizers/timeline/ducks/intervals.js | 22 ++++---- .../visualizers/timeline/ducks/limit.js | 14 ++--- .../visualizers/timeline/ducks/secondLevel.js | 28 +++++----- .../timeline/ducks/selectedConnFirstLevel.js | 24 ++++----- .../timeline/ducks/selectedConnSecondLevel.js | 24 ++++----- .../ducks/selectedThingSecondLevel.js | 24 ++++----- .../timeline/ducks/selectedTimeRecord.js | 13 +++-- .../timeline/ducks/selectedTypeFirstLevel.js | 24 ++++----- .../visualizers/timeline/ducks/timeRange.js | 14 ++--- .../visualizers/timeline/ducks/utils.js | 6 +-- .../visualizers/timeline/misc/TimeLine.js | 34 +++++++------ .../timeline/misc/TimeLineStyle.css | 23 +++++++++ .../modules/visualizers/timeline/models.js | 2 +- .../modules/visualizers/timeline/prefix.js | 2 +- .../modules/visualizers/timeline/reducer.js | 26 +++++----- .../modules/visualizers/timeline/selector.js | 6 +-- 58 files changed, 547 insertions(+), 359 deletions(-) create mode 100644 src/app/assets_webpack/assistant/javascripts/entries/timeline-instants.js create mode 100644 src/app/assets_webpack/assistant/javascripts/entries/timeline-intervals.js create mode 100644 src/app/assets_webpack/assistant/javascripts/entries/timeline-things-instants.js create mode 100644 src/app/assets_webpack/assistant/javascripts/entries/timeline-things-intervals.js create mode 100644 src/app/assets_webpack/assistant/javascripts/entries/timeline-things-things-instants.js create mode 100644 src/app/assets_webpack/assistant/javascripts/entries/timeline-things-things-intervals.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/entries/timeline.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/applicationRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/applicationRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/configuratorRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/prefix.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/applicationRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/configuratorRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/prefix.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/applicationRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/configuratorRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/prefix.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/applicationRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/configuratorRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/prefix.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/applicationRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/configuratorRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/prefix.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/applicationRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/configuratorRoutes.js create mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/prefix.js delete mode 100644 src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/configuratorRoutes.js diff --git a/src/app/assets_webpack/assistant/javascripts/entries/timeline-instants.js b/src/app/assets_webpack/assistant/javascripts/entries/timeline-instants.js new file mode 100644 index 00000000..18cc845a --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/entries/timeline-instants.js @@ -0,0 +1,4 @@ +import initEntry from "../misc/initEntry"; +import timelineInstantsRoutes from "../modules/visualizers/timeline/components/instants/applicationRoutes"; + +initEntry(timelineInstantsRoutes); diff --git a/src/app/assets_webpack/assistant/javascripts/entries/timeline-intervals.js b/src/app/assets_webpack/assistant/javascripts/entries/timeline-intervals.js new file mode 100644 index 00000000..39a2a6c2 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/entries/timeline-intervals.js @@ -0,0 +1,4 @@ +import initEntry from "../misc/initEntry"; +import timelineIntervalsRoutes from "../modules/visualizers/timeline/components/intervals/applicationRoutes"; + +initEntry(timelineIntervalsRoutes); diff --git a/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-instants.js b/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-instants.js new file mode 100644 index 00000000..6f4af5fa --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-instants.js @@ -0,0 +1,5 @@ +import initEntry from "../misc/initEntry"; +import timelineThingsInstantsRoutes from "../modules/visualizers/timeline/components/thingsInstants/applicationRoutes"; + +initEntry(timelineThingsInstantsRoutes); + diff --git a/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-intervals.js b/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-intervals.js new file mode 100644 index 00000000..53bf699b --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-intervals.js @@ -0,0 +1,4 @@ +import initEntry from "../misc/initEntry"; +import timelineThingsIntervalsRoutes from "../modules/visualizers/timeline/components/thingsIntervals/applicationRoutes"; + +initEntry(timelineThingsIntervalsRoutes); diff --git a/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-things-instants.js b/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-things-instants.js new file mode 100644 index 00000000..0c57b47e --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-things-instants.js @@ -0,0 +1,6 @@ +import initEntry from "../misc/initEntry"; +import timelineThingsThingsInstantsRoutes from "../modules/visualizers/timeline/components/thingsThingsInstants/applicationRoutes"; + + +initEntry(timelineThingsThingsInstantsRoutes); + diff --git a/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-things-intervals.js b/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-things-intervals.js new file mode 100644 index 00000000..0191d76b --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/entries/timeline-things-things-intervals.js @@ -0,0 +1,5 @@ +import initEntry from "../misc/initEntry"; +import timelineThingsThingsIntervalsRoutes from "../modules/visualizers/timeline/components/thingsThingsInstants/applicationRoutes"; + + +initEntry(timelineThingsThingsIntervalsRoutes); diff --git a/src/app/assets_webpack/assistant/javascripts/entries/timeline.js b/src/app/assets_webpack/assistant/javascripts/entries/timeline.js deleted file mode 100644 index 74197193..00000000 --- a/src/app/assets_webpack/assistant/javascripts/entries/timeline.js +++ /dev/null @@ -1,4 +0,0 @@ -import createRoutes from '../modules/visualizers/timeline/applicationRoutes' -import initEntry from '../misc/initEntry' - -initEntry(createRoutes); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js index 53caaef5..cad6374c 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/routes.js @@ -4,7 +4,12 @@ import ConfiguratorsRouteFactory from './utils/ConfiguratorsRouteFactory' import dataCubeRoutes from './datacube/configuratorRoutes' import googleMapsRoutes from './googleMaps/configuratorRoutes' import chordRoutes from './chord/configuratorRoutes' -import timelineRoutes from './timeline/configuratorRoutes' +import timelineInstantsRoutes from './timeline/components/instants/configuratorRoutes' +import timelineIntervalsRoutes from './timeline/components/intervals/configuratorRoutes' +import timelineThingsInstantsRoutes from './timeline/components/thingsInstants/configuratorRoutes' +import timelineThingsIntervalsRoutes from './timeline/components/thingsIntervals/configuratorRoutes' +import timelineThingsThingsInstantsRoutes from './timeline/components/thingsThingsInstants/configuratorRoutes' +import timelineThingsThingsIntervalsRoutes from './timeline/components/thingsThingsInstants/configuratorRoutes' import { Visualizer, VisualizerWithPipelines } from '../core/models' import { applicationUrl } from '../app/configuratorRoutes' @@ -15,7 +20,12 @@ const routeFactory = new ConfiguratorsRouteFactory(); routeFactory.register(dataCubeRoutes); routeFactory.register(googleMapsRoutes); routeFactory.register(chordRoutes); -routeFactory.register(timelineRoutes); +routeFactory.register(timelineInstantsRoutes); +routeFactory.register(timelineIntervalsRoutes); +routeFactory.register(timelineThingsInstantsRoutes); +routeFactory.register(timelineThingsIntervalsRoutes); +routeFactory.register(timelineThingsThingsInstantsRoutes); +routeFactory.register(timelineThingsThingsIntervalsRoutes); export default dispatch => routeFactory.createRoutes(dispatch); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js index 91931828..1f9f255e 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/api.js @@ -1,67 +1,67 @@ -import rest from '../../../misc/rest' +import rest from "../../../misc/rest"; export async function getIntervals(applicationId, urls, timeRange, limit) { - let payload = { "urls" : urls, "start" : timeRange.begin.getTime(), "end" : timeRange.end.getTime(), "limit" : limit }; + let payload = {"urls": urls, "start": timeRange.begin.getTime(), "end": timeRange.end.getTime(), "limit": limit}; const result = await rest('timeLineVisualizer/getIntervals/' + applicationId, payload); return result.data.intervals; } export async function getInstants(applicationId, urls, timeRange, limit) { - let payload = { "urls" : urls, "start" : timeRange.begin.getTime(), "end" : timeRange.end.getTime(), "limit" : limit }; + let payload = {"urls": urls, "start": timeRange.begin.getTime(), "end": timeRange.end.getTime(), "limit": limit}; const result = await rest('timeLineVisualizer/getInstants/' + applicationId, payload); return result.data.instants; } export async function getThingsWIntervals(applicationId, things, thingTypes, connections, limit) { - let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : limit}; + let payload = {"things": things, "thingTypes": thingTypes, "connections": connections, "limit": limit}; const result = await rest('timeLineVisualizer/getThingsWIntervals/' + applicationId, payload); return result.data.thingsWithIntervals; } export async function getThingsWInstants(applicationId, things, thingTypes, connections, limit) { - let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : limit}; + let payload = {"things": things, "thingTypes": thingTypes, "connections": connections, "limit": limit}; const result = await rest('timeLineVisualizer/getThingsWInstants/' + applicationId, payload); return result.data.thingsWithInstants; } export async function getThingsWThingsWIntervals(applicationId, things, thingTypes, connections, limit) { - let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : limit}; + let payload = {"things": things, "thingTypes": thingTypes, "connections": connections, "limit": limit}; const result = await rest('timeLineVisualizer/getThingsWThingsWIntervals/' + applicationId, payload); return result.data.thingsWithThingsWithIntervals; } export async function getThingsWThingsWInstants(applicationId, things, thingTypes, connections, limit) { - let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : limit}; + let payload = {"things": things, "thingTypes": thingTypes, "connections": connections, "limit": limit}; const result = await rest('timeLineVisualizer/getThingsWThingsWInstants/' + applicationId, payload); return result.data.thingsWithThingsWithInstants; } export async function getIntervalsCount(applicationId, urls, timeRange) { - let payload = { "urls" : urls, "start" : timeRange.begin.getTime(), "end" : timeRange.end.getTime(), "limit" : -1 }; + let payload = {"urls": urls, "start": timeRange.begin.getTime(), "end": timeRange.end.getTime(), "limit": -1}; const result = await rest('timeLineVisualizer/getIntervals/count/' + applicationId, payload); return result.data.count.value; } export async function getInstantsCount(applicationId, urls, timeRange) { - let payload = { "urls" : urls, "start" : timeRange.begin.getTime(), "end" : timeRange.end.getTime(), "limit" : -1 }; + let payload = {"urls": urls, "start": timeRange.begin.getTime(), "end": timeRange.end.getTime(), "limit": -1}; const result = await rest('timeLineVisualizer/getInstants/count/' + applicationId, payload); return result.data.count; } export async function getThingsWIntervalsCount(applicationId, things, thingTypes, connections) { - let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : -1}; + let payload = {"things": things, "thingTypes": thingTypes, "connections": connections, "limit": -1}; const result = await rest('timeLineVisualizer/getThingsWIntervals/count/' + applicationId, payload); return result.data.count; } export async function getThingsWInstantsCount(applicationId, things, thingTypes, connections) { - let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : -1}; + let payload = {"things": things, "thingTypes": thingTypes, "connections": connections, "limit": -1}; const result = await rest('timeLineVisualizer/getThingsWInstants/count/' + applicationId, payload); return result.data.count; } export async function getThingsWThingsWIntervalsCount(applicationId, things, thingTypes, connections) { - let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : -1 }; + let payload = {"things": things, "thingTypes": thingTypes, "connections": connections, "limit": -1}; const result = await rest('timeLineVisualizer/getThingsWThingsWIntervals/count/' + applicationId, payload); return result.data.count; } export async function getThingsWThingsWInstantsCount(applicationId, things, thingTypes, connections) { - let payload = { "things" : things, "thingTypes" : thingTypes, "connections" : connections, "limit" : -1 }; + let payload = {"things": things, "thingTypes": thingTypes, "connections": connections, "limit": -1}; const result = await rest('timeLineVisualizer/getThingsWThingsWInstants/count/' + applicationId, payload); return result.data.count; } \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/applicationRoutes.js deleted file mode 100644 index 00a4cd27..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/applicationRoutes.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react' -import { Route } from 'react-router' -import ApplicationLoader from '../../app/pages/ApplicationLoader' -import NotFound from '../../platform/pages/NotFound' -import Instants from "./pages/Instants" -import Intervals from "./pages/Intervals" -import InstantsToFirstLevel from "./pages/InstantsToFirstLevel" -import IntervalsToFirstLevel from "./pages/IntervalsToFirstLevel" -import InstantsToSecondLevel from "./pages/InstantsToSecondLevel" -import IntervalsToSecondLevel from "./pages/IntervalsToSecondLevel" - -export default function createRoutes(dispatch) { - return ( - - - - - - - - - - - - - ); -} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/applicationRoutes.js new file mode 100644 index 00000000..65768a6c --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/applicationRoutes.js @@ -0,0 +1,14 @@ +import React from "react"; +import {IndexRoute, Route} from "react-router"; +import ApplicationLoader from "../../../../app/pages/ApplicationLoader"; +import Instants from "../../pages/Instants"; +import NotFound from "../../../../platform/pages/NotFound"; + +export default function createRoutes(dispatch) { + return ( + + + + + ); +} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/configuratorRoutes.js new file mode 100644 index 00000000..743cb245 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/configuratorRoutes.js @@ -0,0 +1,10 @@ +import React from "react"; +import {Route} from "react-router"; +import {MODULE_PREFIX} from "./prefix"; +import Instants from "../../pages/Instants"; + +export default function createRoutes(dispatch) { + return ( + + ); +} diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/prefix.js new file mode 100644 index 00000000..4c68cf7d --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/instants/prefix.js @@ -0,0 +1,5 @@ +import createPrefixer from "../../../../../misc/createPrefixer"; +import {MODULE_PREFIX as PARENT_MODULE_PREFIX} from "../../prefix"; + +export const MODULE_PREFIX = PARENT_MODULE_PREFIX + "-" + "instants"; +export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/applicationRoutes.js new file mode 100644 index 00000000..c4b71e71 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/applicationRoutes.js @@ -0,0 +1,14 @@ +import React from "react"; +import {IndexRoute, Route} from "react-router"; +import ApplicationLoader from "../../../../app/pages/ApplicationLoader"; +import NotFound from "../../../../platform/pages/NotFound"; +import Intervals from "../../pages/Intervals"; + +export default function createRoutes(dispatch) { + return ( + + + + + ); +} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/configuratorRoutes.js new file mode 100644 index 00000000..9edc1d6f --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/configuratorRoutes.js @@ -0,0 +1,10 @@ +import React from "react"; +import {Route} from "react-router"; +import {MODULE_PREFIX} from "./prefix"; +import Intervals from "../../pages/Intervals"; + +export default function createRoutes(dispatch) { + return ( + + ); +} diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/prefix.js new file mode 100644 index 00000000..4c47e9f8 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/intervals/prefix.js @@ -0,0 +1,5 @@ +import createPrefixer from "../../../../../misc/createPrefixer"; +import {MODULE_PREFIX as PARENT_MODULE_PREFIX} from "../../prefix"; + +export const MODULE_PREFIX = PARENT_MODULE_PREFIX + "-" + "intervals"; +export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/applicationRoutes.js new file mode 100644 index 00000000..f1afe0af --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/applicationRoutes.js @@ -0,0 +1,14 @@ +import React from "react"; +import {IndexRoute, Route} from "react-router"; +import ApplicationLoader from "../../../../app/pages/ApplicationLoader"; +import NotFound from "../../../../platform/pages/NotFound"; +import InstantsToFirstLevel from "../../pages/InstantsToFirstLevel"; + +export default function createRoutes(dispatch) { + return ( + + + + + ); +} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/configuratorRoutes.js new file mode 100644 index 00000000..e4eb9bb9 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/configuratorRoutes.js @@ -0,0 +1,10 @@ +import React from "react"; +import {Route} from "react-router"; +import {MODULE_PREFIX} from "./prefix"; +import InstantsToFirstLevel from "../../pages/InstantsToFirstLevel"; + +export default function createRoutes(dispatch) { + return ( + + ); +} diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/prefix.js new file mode 100644 index 00000000..98a2f523 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsInstants/prefix.js @@ -0,0 +1,5 @@ +import createPrefixer from "../../../../../misc/createPrefixer"; +import {MODULE_PREFIX as PARENT_MODULE_PREFIX} from "../../prefix"; + +export const MODULE_PREFIX = PARENT_MODULE_PREFIX + "-" + "things-instants"; +export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/applicationRoutes.js new file mode 100644 index 00000000..148a62cd --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/applicationRoutes.js @@ -0,0 +1,14 @@ +import React from "react"; +import {IndexRoute, Route} from "react-router"; +import ApplicationLoader from "../../../../app/pages/ApplicationLoader"; +import NotFound from "../../../../platform/pages/NotFound"; +import IntervalsToFirstLevel from "../../pages/IntervalsToFirstLevel"; + +export default function createRoutes(dispatch) { + return ( + + + + + ); +} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/configuratorRoutes.js new file mode 100644 index 00000000..da01fcaf --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/configuratorRoutes.js @@ -0,0 +1,10 @@ +import React from "react"; +import {Route} from "react-router"; +import {MODULE_PREFIX} from "./prefix"; +import IntervalsToFirstLevel from "../../pages/IntervalsToFirstLevel"; + +export default function createRoutes(dispatch) { + return ( + + ); +} diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/prefix.js new file mode 100644 index 00000000..f7368471 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsIntervals/prefix.js @@ -0,0 +1,5 @@ +import createPrefixer from "../../../../../misc/createPrefixer"; +import {MODULE_PREFIX as PARENT_MODULE_PREFIX} from "../../prefix"; + +export const MODULE_PREFIX = PARENT_MODULE_PREFIX + "-" + "things-intervals"; +export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/applicationRoutes.js new file mode 100644 index 00000000..0621c156 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/applicationRoutes.js @@ -0,0 +1,14 @@ +import React from "react"; +import {IndexRoute, Route} from "react-router"; +import ApplicationLoader from "../../../../app/pages/ApplicationLoader"; +import NotFound from "../../../../platform/pages/NotFound"; +import InstantsToSecondLevel from "../../pages/InstantsToSecondLevel"; + +export default function createRoutes(dispatch) { + return ( + + + + + ); +} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/configuratorRoutes.js new file mode 100644 index 00000000..3bec8611 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/configuratorRoutes.js @@ -0,0 +1,10 @@ +import React from "react"; +import {Route} from "react-router"; +import {MODULE_PREFIX} from "./prefix"; +import InstantsToSecondLevel from "../../pages/InstantsToSecondLevel"; + +export default function createRoutes(dispatch) { + return ( + + ); +} diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/prefix.js new file mode 100644 index 00000000..05dded81 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsInstants/prefix.js @@ -0,0 +1,5 @@ +import createPrefixer from "../../../../../misc/createPrefixer"; +import {MODULE_PREFIX as PARENT_MODULE_PREFIX} from "../../prefix"; + +export const MODULE_PREFIX = PARENT_MODULE_PREFIX + "-" + "things-things-instants"; +export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/applicationRoutes.js new file mode 100644 index 00000000..b1cc404b --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/applicationRoutes.js @@ -0,0 +1,14 @@ +import React from "react"; +import {IndexRoute, Route} from "react-router"; +import ApplicationLoader from "../../../../app/pages/ApplicationLoader"; +import NotFound from "../../../../platform/pages/NotFound"; +import IntervalsToSecondLevel from "../../pages/IntervalsToSecondLevel"; + +export default function createRoutes(dispatch) { + return ( + + + + + ); +} \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/configuratorRoutes.js new file mode 100644 index 00000000..cf0a24be --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/configuratorRoutes.js @@ -0,0 +1,10 @@ +import React from "react"; +import {Route} from "react-router"; +import {MODULE_PREFIX} from "./prefix"; +import IntervalsToSecondLevel from "../../pages/IntervalsToSecondLevel"; + +export default function createRoutes(dispatch) { + return ( + + ); +} diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/prefix.js new file mode 100644 index 00000000..539f4851 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/thingsThingsIntervals/prefix.js @@ -0,0 +1,5 @@ +import createPrefixer from "../../../../../misc/createPrefixer"; +import {MODULE_PREFIX as PARENT_MODULE_PREFIX} from "../../prefix"; + +export const MODULE_PREFIX = PARENT_MODULE_PREFIX + "-" + "things-things-intervals"; +export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/configuratorRoutes.js deleted file mode 100644 index ab5fa7cf..00000000 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/configuratorRoutes.js +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react' -import { Route } from 'react-router' -import ThingsWithThingsWithIntervals from './pages/ThingsWithThingsWithIntervals' -import { MODULE_PREFIX } from './prefix' - -export default function createRoutes(dispatch) { - return ( - - ); -} diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js index 416ed14d..b2517891 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountFirstLevelContainer.js @@ -1,10 +1,10 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from "reselect"; -import { PromiseStatus } from "../../../core/models"; +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; +import {PromiseStatus} from "../../../core/models"; -import { getCountReset, countFirstSelector, countFirstStatusSelector} from '../ducks/count' -import { firstLevelSelector, firstLevelStatusSelector} from '../ducks/firstLevel' +import {countFirstSelector, countFirstStatusSelector, getCountReset} from "../ducks/count"; +import {firstLevelSelector, firstLevelStatusSelector} from "../ducks/firstLevel"; import PromiseResult from "../../../core/components/PromiseResult"; import CenteredMessage from "../../../../components/CenteredMessage"; @@ -33,8 +33,9 @@ class CountFirstLevelContainer extends Component { return } - if (!thingsStatus.done){ - return + if (!thingsStatus.done) { + return } var loaded = things.length; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js index f179528e..13b44b9e 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountSecondLevelContainer.js @@ -1,10 +1,10 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from "reselect"; -import { PromiseStatus } from "../../../core/models"; +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; +import {PromiseStatus} from "../../../core/models"; -import { getCountReset, countSecondSelector, countSecondStatusSelector} from '../ducks/count' -import { secondLevelSelector, secondLevelStatusSelector} from '../ducks/secondLevel' +import {countSecondSelector, countSecondStatusSelector, getCountReset} from "../ducks/count"; +import {secondLevelSelector, secondLevelStatusSelector} from "../ducks/secondLevel"; import PromiseResult from "../../../core/components/PromiseResult"; import CenteredMessage from "../../../../components/CenteredMessage"; @@ -33,8 +33,9 @@ class CountSecondLevelContainer extends Component { return } - if (!thingsStatus.done){ - return + if (!thingsStatus.done) { + return } var loaded = things.length; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js index 71138c2b..ddbd2c15 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/CountZeroLevelContainer.js @@ -1,11 +1,11 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from "reselect"; -import { PromiseStatus } from "../../../core/models"; +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; +import {PromiseStatus} from "../../../core/models"; -import { getCountReset, countZeroSelector, countZeroStatusSelector} from '../ducks/count' -import { intervalsSelector, intervalsStatusSelector} from '../ducks/intervals' -import { instantsSelector, instantsStatusSelector} from '../ducks/instants' +import {countZeroSelector, countZeroStatusSelector, getCountReset} from "../ducks/count"; +import {intervalsSelector, intervalsStatusSelector} from "../ducks/intervals"; +import {instantsSelector, instantsStatusSelector} from "../ducks/instants"; import PromiseResult from "../../../core/components/PromiseResult"; import CenteredMessage from "../../../../components/CenteredMessage"; @@ -38,7 +38,7 @@ class CountZeroLevelContainer extends Component { return } - if (!instantsStatus.done && !intervalsStatus.done){ + if (!instantsStatus.done && !intervalsStatus.done) { return } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InstantVisualizer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InstantVisualizer.js index e48ab62c..698bc036 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InstantVisualizer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/InstantVisualizer.js @@ -1,12 +1,12 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from "reselect"; +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; import CenteredMessage from "../../../../components/CenteredMessage"; -import { selectedTimeRecordSelector } from '../ducks/selectedTimeRecord' +import {selectedTimeRecordSelector} from "../ducks/selectedTimeRecord"; import Label from "../../../app/containers/Label"; -import Comment from "../../../app/containers/Comment" +import Comment from "../../../app/containers/Comment"; import LevelsVisualizer from "./LevelsVisualizer"; import makePureRender from "../../../../misc/makePureRender"; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/IntervalVisualizer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/IntervalVisualizer.js index 9e8b2346..e935bc37 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/IntervalVisualizer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/IntervalVisualizer.js @@ -1,9 +1,9 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from "reselect"; +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; import CenteredMessage from "../../../../components/CenteredMessage"; -import { selectedTimeRecordSelector } from '../ducks/selectedTimeRecord' +import {selectedTimeRecordSelector} from "../ducks/selectedTimeRecord"; import Label from "../../../app/containers/Label"; import LevelsVisualizer from "./LevelsVisualizer"; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LevelsVisualizer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LevelsVisualizer.js index 6d0e9618..e3525910 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LevelsVisualizer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LevelsVisualizer.js @@ -1,13 +1,13 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from "reselect"; +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; -import { selectedTimeRecordSelector } from '../ducks/selectedTimeRecord' -import { firstLevelSelector} from '../ducks/firstLevel' -import { secondLevelSelector } from '../ducks/secondLevel' +import {selectedTimeRecordSelector} from "../ducks/selectedTimeRecord"; +import {firstLevelSelector} from "../ducks/firstLevel"; +import {secondLevelSelector} from "../ducks/secondLevel"; import Label from "../../../app/containers/Label"; -import SubHeadLine from "../../../../components/Subheadline" +import SubHeadLine from "../../../../components/Subheadline"; import Comment from "../../../app/containers/Comment"; class LevelsVisualizer extends Component { @@ -17,7 +17,7 @@ class LevelsVisualizer extends Component { secondLevel: PropTypes.instanceOf(Array).isRequired }; - renderConnection(conn){ + renderConnection(conn) { return
    @@ -63,24 +63,24 @@ class LevelsVisualizer extends Component { } var firstVis; - if (matchingFirstLevel.length > 0){ + if (matchingFirstLevel.length > 0) { firstVis =
    - {matchingFirstLevel.map(m=>this.renderConnection(m))} + {matchingFirstLevel.map(m => this.renderConnection(m))}
    } var matchingSecondLevel = []; - for (let i of matchingFirstLevel){ - for (let j of secondLevel){ + for (let i of matchingFirstLevel) { + for (let j of secondLevel) { if (i.outer == j.inner) matchingSecondLevel.push(j) } } var secondVis; - if (matchingSecondLevel.length > 0){ + if (matchingSecondLevel.length > 0) { secondVis =
    - {matchingSecondLevel.map(m=>this.renderConnection(m))} + {matchingSecondLevel.map(m => this.renderConnection(m))}
    } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js index dc7fcfd2..792048b4 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/LimiterContainer.js @@ -1,8 +1,8 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from "reselect"; +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; -import { getLimitReset, setLimit, limitSelector, limit_default} from '../ducks/limit' +import {getLimitReset, limit_default, limitSelector, setLimit} from "../ducks/limit"; import Button from "../../../../components/Button"; @@ -28,7 +28,7 @@ class LimiterContainer extends Component { } } - resetLimit(){ + resetLimit() { const {dispatch, limit} = this.props; dispatch(getLimitReset()); @@ -47,9 +47,9 @@ class LimiterContainer extends Component { - + diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js index b1a47c16..9003b484 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineInstantsContainer.js @@ -1,20 +1,21 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from "reselect"; -import { PromiseStatus } from '../../../core/models' -import { TimeRange } from "../models"; - -import { getInstants, getInstantsReset, instantsSelector, instantsStatusSelector } from '../ducks/instants' -import { getInstantsCount } from '../ducks/count' -import { limitSelector } from '../ducks/limit' -import { timeRangeSelector } from '../ducks/timeRange' -import { firstLevelSelector } from '../ducks/firstLevel' -import { setSelectTimeRecord, getSelectTimeRecordReset } from '../ducks/selectedTimeRecord' - -import PromiseResult from '../../../core/components/PromiseResult' -import TimeLine from '../misc/TimeLine' -import CenteredMessage from '../../../../components/CenteredMessage' +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; +import {PromiseStatus} from "../../../core/models"; +import {TimeRange} from "../models"; + +import {getInstants, getInstantsReset, instantsSelector, instantsStatusSelector} from "../ducks/instants"; +import {getInstantsCount} from "../ducks/count"; +import {limitSelector} from "../ducks/limit"; +import {getSelectedTimeReset, timeRangeSelector} from "../ducks/timeRange"; +import {firstLevelSelector} from "../ducks/firstLevel"; +import {getSelectTimeRecordReset, setSelectTimeRecord} from "../ducks/selectedTimeRecord"; + +import PromiseResult from "../../../core/components/PromiseResult"; +import TimeLine from "../misc/TimeLine"; +import CenteredMessage from "../../../../components/CenteredMessage"; import CountZeroLevelContainer from "./CountZeroLevelContainer"; +import TimeRangeContainer from "./TimeRangeContainer"; class TimeLineInstantsContainer extends Component { static propTypes = { @@ -37,7 +38,7 @@ class TimeLineInstantsContainer extends Component { const {dispatch, timeRange, limit} = this.props; this.className = "timeseries-chart"; - this.chart = new TimeLine(this.className, (r)=>dispatch(setSelectTimeRecord(r))); + this.chart = new TimeLine(this.className, (r) => dispatch(setSelectTimeRecord(r))); if (this.props.isInitial) { dispatch(getInstants([], timeRange, limit)); @@ -63,7 +64,7 @@ class TimeLineInstantsContainer extends Component { } componentDidUpdate() { - const { instants } = this.props; + const {instants} = this.props; if (this.needChartUpdate) { this.chart.instants(instants); this.needChartUpdate = false; @@ -74,6 +75,7 @@ class TimeLineInstantsContainer extends Component { const {dispatch} = this.props; dispatch(getInstantsReset()); + dispatch(getSelectedTimeReset()); dispatch(getSelectTimeRecordReset()); this.chart.destroy(); @@ -91,18 +93,20 @@ class TimeLineInstantsContainer extends Component { } require('../misc/TimeLineStyle.css'); - return
    + return
    + +
    } } const selector = createStructuredSelector({ - instants: instantsSelector, - status: instantsStatusSelector, + instants: instantsSelector, + status: instantsStatusSelector, firstLevel: firstLevelSelector, - timeRange: timeRangeSelector, - limit: limitSelector + timeRange: timeRangeSelector, + limit: limitSelector }); export default connect(selector)(TimeLineInstantsContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js index f5a022e2..dc211289 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeLineIntervalsContainer.js @@ -1,19 +1,19 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from "reselect"; -import { PromiseStatus } from '../../../core/models' -import { TimeRange } from "../models"; - -import { getIntervals, getIntervalsReset, intervalsSelector, intervalsStatusSelector } from '../ducks/intervals' -import { getIntervalsCount } from '../ducks/count' -import { limitSelector } from '../ducks/limit' -import { timeRangeSelector } from '../ducks/timeRange' -import { firstLevelSelector } from '../ducks/firstLevel' -import { setSelectTimeRecord, getSelectTimeRecordReset } from '../ducks/selectedTimeRecord' - -import PromiseResult from '../../../core/components/PromiseResult' -import TimeLine from '../misc/TimeLine' -import CenteredMessage from '../../../../components/CenteredMessage' +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; +import {PromiseStatus} from "../../../core/models"; +import {TimeRange} from "../models"; + +import {getIntervals, getIntervalsReset, intervalsSelector, intervalsStatusSelector} from "../ducks/intervals"; +import {getIntervalsCount} from "../ducks/count"; +import {limitSelector} from "../ducks/limit"; +import {getSelectedTimeReset, timeRangeSelector} from "../ducks/timeRange"; +import {firstLevelSelector} from "../ducks/firstLevel"; +import {getSelectTimeRecordReset, setSelectTimeRecord} from "../ducks/selectedTimeRecord"; + +import PromiseResult from "../../../core/components/PromiseResult"; +import TimeLine from "../misc/TimeLine"; +import CenteredMessage from "../../../../components/CenteredMessage"; import CountZeroLevelContainer from "./CountZeroLevelContainer"; import TimeRangeContainer from "./TimeRangeContainer"; import {Paper} from "material-ui"; @@ -39,7 +39,7 @@ class TimeLineIntervalsContainer extends Component { const {dispatch, timeRange, limit} = this.props; this.className = "timeseries-chart"; - this.chart = new TimeLine(this.className, (r)=>dispatch(setSelectTimeRecord(r))); + this.chart = new TimeLine(this.className, (r) => dispatch(setSelectTimeRecord(r))); if (this.props.isInitial) { dispatch(getIntervals([], timeRange, limit)) @@ -52,7 +52,7 @@ class TimeLineIntervalsContainer extends Component { var needUpdate = (firstLevel != nextProps.firstLevel || timeRange != nextProps.timeRange); - if (needUpdate){ + if (needUpdate) { var urls = nextProps.firstLevel.map(t => t.inner); dispatch(getIntervals(urls, nextProps.timeRange, limit)); dispatch(getIntervalsCount(urls, nextProps.timeRange, limit)); @@ -67,7 +67,7 @@ class TimeLineIntervalsContainer extends Component { } componentDidUpdate() { - const { intervals } = this.props; + const {intervals} = this.props; if (this.needChartUpdate) { this.chart.intervals(intervals); @@ -75,10 +75,11 @@ class TimeLineIntervalsContainer extends Component { } } - componentWillUnmount(){ + componentWillUnmount() { const {dispatch} = this.props; dispatch(getIntervalsReset()); + dispatch(getSelectedTimeReset()); dispatch(getSelectTimeRecordReset()); this.chart.destroy(); @@ -98,18 +99,18 @@ class TimeLineIntervalsContainer extends Component { require('../misc/TimeLineStyle.css'); return -
    +
    } } const selector = createStructuredSelector({ - intervals: intervalsSelector, - status: intervalsStatusSelector, + intervals: intervalsSelector, + status: intervalsStatusSelector, firstLevel: firstLevelSelector, - timeRange: timeRangeSelector, - limit: limitSelector + timeRange: timeRangeSelector, + limit: limitSelector }); export default connect(selector)(TimeLineIntervalsContainer); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRangeContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRangeContainer.js index 96682974..100e4c93 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRangeContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRangeContainer.js @@ -1,10 +1,10 @@ -import React, { Component, PropTypes } from 'react' -import { connect } from 'react-redux' -import { createStructuredSelector } from "reselect"; +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; import {TimeRange} from "../models"; -import moment from 'moment' +import moment from "moment"; -import { setSelectTime, getSelectedTimeReset, timeRangeSelector } from '../ducks/timeRange' +import {getSelectedTimeReset, setSelectTime, timeRangeSelector} from "../ducks/timeRange"; import Button from "../../../../components/Button"; @@ -14,14 +14,8 @@ class TimeRangeContainer extends Component { timeRange: PropTypes.instanceOf(TimeRange).isRequired }; - - componentWillUnmount(){ - const { dispatch } = this.props; - dispatch(getSelectedTimeReset()); - } - - setTimeRange(){ - const { dispatch } = this.props; + setTimeRange() { + const {dispatch} = this.props; var begin = document.getElementsByName("begin_input")[0].value; var end = document.getElementsByName("end_input")[0].value; @@ -29,14 +23,14 @@ class TimeRangeContainer extends Component { dispatch(setSelectTime(new Date(begin), new Date(end))); } - resetTimeRange(){ - const { dispatch } = this.props; + resetTimeRange() { + const {dispatch} = this.props; dispatch(getSelectedTimeReset()); } - componentDidUpdate(){ - const { timeRange } = this.props; + componentDidUpdate() { + const {timeRange} = this.props; var beginString = moment(timeRange.begin).format('YYYY-MM-DD'); var endString = moment(timeRange.end).format('YYYY-MM-DD'); @@ -46,7 +40,7 @@ class TimeRangeContainer extends Component { } render() { - const { timeRange } = this.props; + const {timeRange} = this.props; var beginString = moment(timeRange.begin).format('YYYY-MM-DD'); var endString = moment(timeRange.end).format('YYYY-MM-DD'); @@ -55,13 +49,13 @@ class TimeRangeContainer extends Component {
    LIMITthis.setLimit()}/> this.setLimit()}/>
    - +
    Time Range from Time Range from to
    +
    } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js index cf89bf46..dd1bca17 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/SecondLevelConnectionContainer.js @@ -23,6 +23,7 @@ import ConfigToolbar from "../misc/ValueSelector"; import CenteredMessage from "../../../../components/CenteredMessage"; import Button from "../../../../components/Button"; import {AppBar, Paper} from "material-ui"; +import CountSecondLevelContainer from "./CountSecondLevelContainer"; class SecondLevelConnectionContainer extends Component { static propTypes = { @@ -106,16 +107,17 @@ class SecondLevelConnectionContainer extends Component { onChecked={k => dispatch(setSelectConnSL(k))} onUnchecked={k => dispatch(setUnSelectConnSL(k))} /> -
    + } +} + +const selector = createStructuredSelector({ + coordinates: coordinatesSelector, + coordinatesStatus: coordinatesStatusSelector, + + coordinatesCount: coordinatesCountSelector, + coordinatesCountStatus: coordinatesCountStatusSelector, + + places: placesSelector, + limit: limitSelector +}); + +export default connect(selector)(CoordinatesLoader); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/GoogleMapsCircles.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/GoogleMapsCircles.js new file mode 100644 index 00000000..a95a3cb5 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/GoogleMapsCircles.js @@ -0,0 +1,76 @@ +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {Set as ImmutableSet} from "immutable"; +import {Circle} from "react-google-maps"; +import GoogleMap from "../../../../components/GoogleMap"; +import {mapStateSelector, updateMapState} from "../ducks/mapState"; +import {toggledMarkersSelector, toggleMarker} from "../ducks/toggledMarkers"; +import {coordinatesSelector, coordinatesStatusSelector, getCoordinates} from "../ducks/coordinates"; +import {MapState} from "../models"; +import {createStructuredSelector} from "reselect"; +import makePureRender from "../../../../misc/makePureRender"; + +class GoogleMapsCircles extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + isInitial: PropTypes.bool.isRequired, + + coordinates: PropTypes.instanceOf(Array).isRequired, + mapState: PropTypes.instanceOf(MapState).isRequired + }; + + static contextTypes = { + store: PropTypes.object.isRequired + }; + + componentWillMount() { + const {dispatch} = this.props; + dispatch(getCoordinates([], 10)); + } + + render() { + const {dispatch, coordinates, mapState} = this.props; + debugger; + return ( + dispatch(updateMapState({zoomLevel}))} + onCenterChanged={center => dispatch(updateMapState({center}))} + defaultZoom={mapState.zoomLevel} + defaultCenter={mapState.center.toJS()}> + + {coordinates.map(c => { + const coorsMapFormat = { + lat: parseFloat(c.latitude.toFixed(5)), + lng: parseFloat(c.longitude.toFixed(5)) + }; + + return { + dispatch(toggleMarker(c.url)) + }}/> + } + )} + + ); + } +} + + +const selector = createStructuredSelector({ + coordinates: coordinatesSelector, + coordStatus: coordinatesStatusSelector, + toggledMarkers: toggledMarkersSelector, + mapState: mapStateSelector +}); + + +export default connect(selector)(makePureRender(GoogleMapsCircles)); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/GoogleMapsMarkers.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/GoogleMapsMarkers.js new file mode 100644 index 00000000..7eb30f86 --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/GoogleMapsMarkers.js @@ -0,0 +1,86 @@ +import React, {Component, PropTypes} from "react"; +import {connect, Provider} from "react-redux"; +import {Set as ImmutableSet} from "immutable"; +import {InfoWindow, Marker} from "react-google-maps"; +import MarkerClusterer from "react-google-maps/lib/addons/MarkerClusterer"; +import GoogleMap from "../../../../components/GoogleMap"; +import {mapStateSelector, updateMapState} from "../ducks/mapState"; +import {toggledMarkersSelector, toggleMarker} from "../ducks/toggledMarkers"; +import {coordinatesSelector} from "../ducks/coordinates"; +import MapMarker from "../components/MapMarker"; +import {MapState} from "../models"; +import {createStructuredSelector} from "reselect"; + +class GoogleMapsMarkers extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + coordinates: PropTypes.instanceOf(Array).isRequired, + mapState: PropTypes.instanceOf(MapState).isRequired, + toggledMarkers: PropTypes.instanceOf(ImmutableSet).isRequired + }; + + static contextTypes = { + store: PropTypes.object.isRequired + }; + + infoWindow(url) { + const {toggledMarkers, dispatch} = this.props; + if (toggledMarkers.contains(url)) { + return ( + dispatch(toggleMarker(url))}> + + + + + + ); + } + return ""; + } + + marker(coors) { + const {dispatch} = this.props; + + const position = { + lat: parseFloat(coors.latitude.toFixed(5)), + lng: parseFloat(coors.longitude.toFixed(5)) + }; + + return ( + dispatch(toggleMarker(coors.url))} + defaultAnimation={null}> + {this.infoWindow(coors.url)} + + ) + } + + render() { + const {dispatch, coordinates, mapState} = this.props; + return ( + dispatch(updateMapState({zoomLevel}))} + onCenterChanged={center => dispatch(updateMapState({center}))} + defaultZoom={mapState.zoomLevel} + defaultCenter={mapState.center.toJS()}> + + + {coordinates.map(c=>this.marker(c))} + + + ); + }; +} + +const selector = createStructuredSelector({ + coordinates: coordinatesSelector, + toggledMarkers: toggledMarkersSelector, + mapState: mapStateSelector +}); +export default connect(selector)(GoogleMapsMarkers); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/PlacesLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/PlacesLoader.js new file mode 100644 index 00000000..04ae530f --- /dev/null +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/PlacesLoader.js @@ -0,0 +1,110 @@ +import React, {Component, PropTypes} from "react"; +import {connect} from "react-redux"; +import {createStructuredSelector} from "reselect"; +import {Set as ImmutableSet} from "immutable"; +import {getPlacesCount} from "../ducks/counts"; +import {getPlaces, getPlacesReset, placesSelector, placesStatusSelector} from "../ducks/places"; +import {PromiseStatus} from "../../../core/models"; +import PromiseResult from "../../../core/components/PromiseResult"; +import Button from "../../../../components/Button"; +import {limitSelector} from "../../../app/ducks/limit"; +import {Paper} from "material-ui"; +import RecordSelector from "../../../common/RecordSelector"; +import {selectedPlaceTypesSelector, setSelectedPlaceTypesReset, setSelectPlaceType} from "../ducks/selectedPlaceTypes"; +import CenteredMessage from "../../../../components/CenteredMessage"; +import {thingsWithPlacesSelector} from "../ducks/thingsWithPlaces"; + +class PlacesLoader extends Component { + static propTypes = { + dispatch: PropTypes.func.isRequired, + isInitial: PropTypes.bool.isRequired, + + places: PropTypes.array.isRequired, + status: PropTypes.instanceOf(PromiseStatus).isRequired, + selectedPlaceTypes: PropTypes.instanceOf(ImmutableSet).isRequired, + + thingsWithPlaces: PropTypes.array.isRequired, + limit: PropTypes.number.isRequired + }; + + load(thingsWithPlaces) { + const {dispatch, selectedPlaceTypes,limit} = this.props; + + var urls = thingsWithPlaces.map(p => p.inner); + dispatch(getPlaces(urls, [...selectedPlaceTypes], limit)); + dispatch(getPlacesCount(urls, [...selectedPlaceTypes])); + } + + reload(thingsWithPlaces) { + const {dispatch} = this.props; + dispatch(setSelectedPlaceTypesReset()); + this.load(thingsWithPlaces); + } + + componentWillMount() { + const {isInitial, thingsWithPlaces} = this.props; + if (isInitial) { + this.load(thingsWithPlaces); + } + } + + componentWillReceiveProps(nextProps) { + if (nextProps.thingsWithPlaces != this.props.thingsWithPlaces) { + this.reload(nextProps.thingsWithPlaces); + } + } + + componentWillUnmount(){ + const {dispatch} = this.props; + dispatch(getPlacesReset()); + dispatch(setSelectedPlaceTypesReset()); + } + + render() { + const {dispatch, places, status, selectedPlaceTypes, thingsWithPlaces} = this.props; + + if (!status.done) { + return + } + + else if (places.length == 0) { + return No connected places were loaded. Check the settings please. + } + + var buttonsEnabled = selectedPlaceTypes.length > 0 || selectedPlaceTypes.length > 0; + + return + t.outerType} + getValue={t => t.outerType} + selectedKeys={selectedPlaceTypes} + onKeySelect={k => dispatch(setSelectPlaceType(k))} + onKeyUnselect={k => dispatch(setSelectPlaceType(k))} + /> +
    diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/dirty.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/dirty.js index ad8986d9..1de16c24 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/dirty.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/ducks/dirty.js @@ -1,19 +1,24 @@ import {createSelector} from "reselect"; import moduleSelector from "../selector"; import {createDirtyReducer} from "../../../app/ducks/dirty"; -import {SET_SELECT_FL_PREDICATE} from "./selectedFirstLevelPredicates"; -import {SET_SELECT_FL_TYPE} from "./selectedFirstLevelTypes"; -import {SET_SELECT_SL_PREDICATE} from "./selectedSecondLevelPredicates"; -import {SET_SELECT_SL_THING} from "./selectedSecondLevelThings"; -import {SET_TIME_RANGE} from "./timeRange"; +import {SET_SELECT_FL_PREDICATE, SET_SELECT_FL_PREDICATE_RESET} from "./selectedFirstLevelPredicates"; +import {SET_SELECT_FL_TYPE, SET_SELECT_FL_TYPE_RESET} from "./selectedFirstLevelTypes"; +import {SET_SELECT_SL_PREDICATE, SET_SELECT_SL_PREDICATE_RESET} from "./selectedSecondLevelPredicates"; +import {SET_SELECT_SL_THING, SET_SELECT_SL_THING_RESET} from "./selectedSecondLevelThings"; +import {SET_TIME_RANGE, SET_TIME_RANGE_RESET} from "./timeRange"; // Reducer const actions = [ SET_SELECT_FL_PREDICATE, + SET_SELECT_FL_PREDICATE_RESET, SET_SELECT_FL_TYPE, + SET_SELECT_FL_TYPE_RESET, SET_SELECT_SL_PREDICATE, + SET_SELECT_SL_PREDICATE_RESET, SET_SELECT_SL_THING, - SET_TIME_RANGE + SET_SELECT_SL_THING_RESET, + SET_TIME_RANGE, + SET_TIME_RANGE_RESET ]; export default createDirtyReducer(actions); diff --git a/src/app/model/assistant/InstallBundle.scala b/src/app/model/assistant/InstallBundle.scala index d70b38fc..13f7e7e7 100644 --- a/src/app/model/assistant/InstallBundle.scala +++ b/src/app/model/assistant/InstallBundle.scala @@ -16,7 +16,17 @@ object InstallBundle { "SPARQL endpoint data source" -> "https://raw.githubusercontent.com/ldvm/vocabulary/master/rdf/examples/datasources/ldvm-ds-sparql.ttl", "RÚIAN" -> "https://raw.githubusercontent.com/ldvm/vocabulary/master/rdf/examples/datasources/ldvm-ds-ruian.ttl", "linked.opendata.cz" -> "https://raw.githubusercontent.com/ldvm/vocabulary/master/rdf/examples/datasources/ldvm-ds-ldcz.ttl", - "internal.opendata.cz" -> "https://raw.githubusercontent.com/ldvm/vocabulary/master/rdf/examples/datasources/ldvm-ds-int-od-cz.ttl" + "internal.opendata.cz" -> "https://raw.githubusercontent.com/ldvm/vocabulary/master/rdf/examples/datasources/ldvm-ds-int-od-cz.ttl", + "Time Line Instants Visualizer" -> "https://raw.githubusercontent.com/vvancak/vocabulary/master/rdf/examples/visualizers/ldvm-v-timeline-instants.ttl", + "Time Line Things with Instants Visualizer" -> "https://raw.githubusercontent.com/vvancak/vocabulary/master/rdf/examples/visualizers/ldvm-v-timeline-things-instants.ttl", + "Time Line Things with Things with Instants Visualizer" -> "https://raw.githubusercontent.com/vvancak/vocabulary/master/rdf/examples/visualizers/ldvm-v-timeline-things-things-instants.ttl", + "Time Line Intervals Visualizer" -> "https://raw.githubusercontent.com/vvancak/vocabulary/master/rdf/examples/visualizers/ldvm-v-timeline-intervals.ttl", + "Time Line Things with Intervals Visualizer" -> "https://raw.githubusercontent.com/vvancak/vocabulary/master/rdf/examples/visualizers/ldvm-v-timeline-things-intervals.ttl", + "Time Line Things with Things with Intervals Visualizer" -> "https://raw.githubusercontent.com/vvancak/vocabulary/master/rdf/examples/visualizers/ldvm-v-timeline-things-things-intervals.ttl", + "Google Maps Coordinates Visualizer" -> "https://raw.githubusercontent.com/vvancak/vocabulary/master/rdf/examples/visualizers/ldvm-v-googlemaps-coordinates.ttl", + "Google Maps Places Visualizer" -> "https://raw.githubusercontent.com/vvancak/vocabulary/master/rdf/examples/visualizers/ldvm-v-googlemaps-places.ttl", + "Google Maps Quantified Places Visualizer" -> "https://raw.githubusercontent.com/vvancak/vocabulary/master/rdf/examples/visualizers/ldvm-v-googlemaps-quantified-places.ttl", + "Google Maps Quantified Things Visualizer" -> "https://raw.githubusercontent.com/vvancak/vocabulary/master/rdf/examples/visualizers/ldvm-v-googlemaps-quantified-things.ttl" ) val dataSources = List( @@ -28,6 +38,16 @@ object InstallBundle { val visualizers = List ( ("D3.js Chord Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/chord/ChordVisualizerTemplate", "chord", "donut_large"), - ("Google Maps Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/gmaps/GoogleMapsVisualizerTemplate", "googleMaps", "map") + ("Google Maps Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/gmaps/GoogleMapsVisualizerTemplate", "googleMaps", "map"), + ("Time Line Instants Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/timeline-instants/TimeLineVisualizerTemplate", "timeline-instants", "timeline"), + ("Time Line Things with Instants Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/timeline-things-instants/TimeLineVisualizerTemplate", "timeline-things-instants", "timeline"), + ("Time Line Things with Things with Instants Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/timeline-things-things-instants/TimeLineVisualizerTemplate", "timeline-things-things-instants", "timeline"), + ("Time Line Intervals Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/timeline-intervals/TimeLineVisualizerTemplate", "timeline-intervals", "timeline"), + ("Time Line Things with Intervals Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/timeline-things-intervals/TimeLineVisualizerTemplate", "timeline-things-intervals", "timeline"), + ("Time Line Things with Things with Intervals Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/timeline-things-things-intervals/TimeLineVisualizerTemplate", "timeline-things-things-intervals", "timeline"), + ("Google Maps Coordinates Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/googlemaps-coordinates/GoogleMapsVisualizerTemplate","googleMaps-coordinates", "map"), + ("Google Maps Places Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/googlemaps-places/GoogleMapsVisualizerTemplate", "googleMaps-places", "map"), + ("Google Maps Quantified Places Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/googlemaps-quantified-places/GoogleMapsVisualizerTemplate", "googleMaps-quantified-places", "map"), + ("Google Maps Quantified Things Visualizer", "http://linked.opendata.cz/resource/ldvm/visualizer/googlemaps-quantified-things/GoogleMapsVisualizerTemplate", "googleMaps-quantified-things", "map") ) } diff --git a/src/app/model/rdf/sparql/timeline/extractor/InstantExtractor.scala b/src/app/model/rdf/sparql/timeline/extractor/InstantExtractor.scala index c85f19cb..e2b95240 100644 --- a/src/app/model/rdf/sparql/timeline/extractor/InstantExtractor.scala +++ b/src/app/model/rdf/sparql/timeline/extractor/InstantExtractor.scala @@ -17,7 +17,7 @@ class InstantExtractor extends QueryExecutionResultExtractor[InstantQuery, Seq[I val resList = input.execSelect().toList Some(resList.map(e => new Instant( e.getResource("instant").getURI, - getDate(e, "date") + getDate(e) ))) } catch { @@ -27,9 +27,20 @@ class InstantExtractor extends QueryExecutionResultExtractor[InstantQuery, Seq[I } } - private def getDate(qs: QuerySolution, fieldName: String): Date = { + private def getDate(qs: QuerySolution): Date = { val dateFormat = new SimpleDateFormat("yyyy-MM-dd") - val fieldValue = qs.getLiteral(fieldName).getString() - return dateFormat.parse(fieldValue) + val fieldValue = qs.getLiteral("date").getString() + + val hour = qs.getLiteral("hour") + val minute = qs.getLiteral("minute") + val second = qs.getLiteral("second") + + val date = dateFormat.parse(fieldValue) + + if (hour != null) date.setHours(hour.getInt) + if (minute != null) date.setMinutes(minute.getInt) + if (second!= null) date.setSeconds(second.getInt) + + return date } } \ No newline at end of file diff --git a/src/app/model/rdf/sparql/timeline/extractor/IntervalExtractor.scala b/src/app/model/rdf/sparql/timeline/extractor/IntervalExtractor.scala index f510a19d..708fdd08 100644 --- a/src/app/model/rdf/sparql/timeline/extractor/IntervalExtractor.scala +++ b/src/app/model/rdf/sparql/timeline/extractor/IntervalExtractor.scala @@ -30,7 +30,17 @@ class IntervalExtractor extends QueryExecutionResultExtractor[IntervalQuery, Seq private def getDate(qs: QuerySolution, fieldName: String): Date = { val dateFormat = new SimpleDateFormat("yyyy-MM-dd") val fieldValue = qs.getLiteral(fieldName).getString() - val date = dateFormat.parse(fieldValue) - return date; + + val hour = qs.getLiteral(fieldName + "_hour") + val minute = qs.getLiteral(fieldName + "_minute") + val second = qs.getLiteral(fieldName + "_second") + + val date = dateFormat.parse(fieldValue) + + if (hour != null) date.setHours(hour.getInt) + if (minute != null) date.setMinutes(minute.getInt) + if (second!= null) date.setSeconds(second.getInt) + + return date } } diff --git a/src/app/model/rdf/sparql/timeline/query/InstantQuery.scala b/src/app/model/rdf/sparql/timeline/query/InstantQuery.scala index 11b72c8b..618f2785 100644 --- a/src/app/model/rdf/sparql/timeline/query/InstantQuery.scala +++ b/src/app/model/rdf/sparql/timeline/query/InstantQuery.scala @@ -7,8 +7,8 @@ import model.rdf.sparql.query.SparqlCountQuery class InstantQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInstantUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { - val select = "SELECT ?instant ?date" - val group = "GROUP BY ?instant ?date" + val select = "SELECT ?instant ?date ?hour ?minute ?second" + val group = "GROUP BY ?instant ?date ?hour ?minute ?second" val limit = QueryHelpers.limit(maybeLimit) return query(select, group, limit) } @@ -29,6 +29,10 @@ class InstantQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInstan |WHERE { | ?instant time:inDateTime ?date_url. | + | OPTIONAL { ?date_url time:hour ?hour } + | OPTIONAL { ?date_url time:minute ?minute } + | OPTIONAL { ?date_url time:second ?second } + | | ${QueryHelpers.bindTimeDescriptionToXSDDate("date_url", "date")} | | ${startFilter} diff --git a/src/app/model/rdf/sparql/timeline/query/IntervalQuery.scala b/src/app/model/rdf/sparql/timeline/query/IntervalQuery.scala index 0ded6db5..eddb6478 100644 --- a/src/app/model/rdf/sparql/timeline/query/IntervalQuery.scala +++ b/src/app/model/rdf/sparql/timeline/query/IntervalQuery.scala @@ -7,8 +7,8 @@ import model.rdf.sparql.query.SparqlCountQuery class IntervalQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeIntervalUrls: Option[Seq[String]], maybeLimit: Option[Int]) extends SparqlCountQuery { def get: String = { - val select = "SELECT ?interval ?begin ?end" - val group = "GROUP BY ?interval ?begin ?end" + val select = "SELECT ?interval ?begin ?begin_hour ?begin_minute ?begin_second ?end ?end_hour ?end_minute ?end_second" + val group = "GROUP BY ?interval ?begin ?begin_hour ?begin_minute ?begin_second ?end ?end_hour ?end_minute ?end_second" val limit = QueryHelpers.limit(maybeLimit) return query(select, group, limit) } @@ -33,6 +33,14 @@ class IntervalQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInter | ?begin_desc time:inDateTime ?begin_url. | ?end_desc time:inDateTime ?end_url. | + | OPTIONAL { ?begin_url time:hour ?begin_hour } + | OPTIONAL { ?begin_url time:minute ?begin_minute } + | OPTIONAL { ?begin_url time:second ?begin_second } + | + | OPTIONAL { ?end_url time:hour ?begin_hour } + | OPTIONAL { ?end_url time:minute ?begin_minute } + | OPTIONAL { ?end_url time:second ?begin_second } + | | ${QueryHelpers.bindTimeDescriptionToXSDDate("begin_url", "begin")} | ${QueryHelpers.bindTimeDescriptionToXSDDate("end_url", "end")} | From d95c8e3bc54131602874af75181bcecb9166b1fd Mon Sep 17 00:00:00 2001 From: vvancak Date: Mon, 17 Jul 2017 16:28:57 +0200 Subject: [PATCH 76/84] TimeLine: removing usage of deprecated methods --- .../common/components/ConfigurationToolbar.js | 2 +- .../timeline/components/InstantVisualizer.js | 3 +-- .../timeline/components/IntervalVisualizer.js | 5 ++-- .../timeline/extractor/InstantExtractor.scala | 23 +++++++++++-------- .../extractor/IntervalExtractor.scala | 23 +++++++++++-------- .../sparql/timeline/query/InstantQuery.scala | 1 + .../sparql/timeline/query/IntervalQuery.scala | 2 ++ 7 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/app/assets_webpack/assistant/javascripts/modules/common/components/ConfigurationToolbar.js b/src/app/assets_webpack/assistant/javascripts/modules/common/components/ConfigurationToolbar.js index 9c66513f..b8dcf326 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/common/components/ConfigurationToolbar.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/common/components/ConfigurationToolbar.js @@ -37,7 +37,7 @@ export default class ConfigurationToolbar extends Component { // Drawer bug - if width is set, component ignores open property let width = "0%"; - if (this.open) width = "20%"; + if (this.open) width = "30%"; let configButton =
    Date-Time: - {moment(instant.date).toString()} + {new Date(instant.date).toUTCString()}
    diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/IntervalVisualizer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/IntervalVisualizer.js index d300107d..a158e8bc 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/IntervalVisualizer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/IntervalVisualizer.js @@ -6,7 +6,6 @@ import SubHeadLine from "../../../../components/Subheadline"; import {selectedTimeRecordSelector} from "../ducks/selectedTimeRecord"; import LevelsVisualizer from "./LevelsVisualizer"; import ObjectInfo from "../../../app/containers/ObjectInfo"; -import moment from "moment"; class IntervalVisualizer extends Component { static propTypes = { @@ -26,10 +25,10 @@ class IntervalVisualizer extends Component {
    Begin: - {moment(interval.begin).toString()} + {new Date(interval.begin).toUTCString()}
    End: - {moment(interval.end).toString()} + {new Date(interval.end).toUTCString()}
    diff --git a/src/app/model/rdf/sparql/timeline/extractor/InstantExtractor.scala b/src/app/model/rdf/sparql/timeline/extractor/InstantExtractor.scala index e2b95240..d0c2196b 100644 --- a/src/app/model/rdf/sparql/timeline/extractor/InstantExtractor.scala +++ b/src/app/model/rdf/sparql/timeline/extractor/InstantExtractor.scala @@ -1,7 +1,7 @@ package model.rdf.sparql.timeline.extractor import java.text.SimpleDateFormat -import java.util.Date +import java.util.{Date, TimeZone} import model.rdf.extractor.QueryExecutionResultExtractor import model.rdf.sparql.timeline.models.Instant @@ -28,19 +28,24 @@ class InstantExtractor extends QueryExecutionResultExtractor[InstantQuery, Seq[I } private def getDate(qs: QuerySolution): Date = { - val dateFormat = new SimpleDateFormat("yyyy-MM-dd") - val fieldValue = qs.getLiteral("date").getString() + val dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + // Set time zone + val zone = qs.getLiteral("zone") + val zoneString = if (zone == null) "GMT" else zone.getString + dateFormat.setTimeZone(TimeZone.getTimeZone(zoneString)) + + // Parse optional time val hour = qs.getLiteral("hour") val minute = qs.getLiteral("minute") val second = qs.getLiteral("second") - val date = dateFormat.parse(fieldValue) - - if (hour != null) date.setHours(hour.getInt) - if (minute != null) date.setMinutes(minute.getInt) - if (second!= null) date.setSeconds(second.getInt) + val HH = if (hour == null) "00" else hour.getString + val mm = if (minute == null) "00" else minute.getString + val ss = if (second == null) "00" else second.getString - return date + // Parse full date-time value + val date = qs.getLiteral("date").getString + return dateFormat.parse(s"""${date} ${HH}:${mm}:${ss}""") } } \ No newline at end of file diff --git a/src/app/model/rdf/sparql/timeline/extractor/IntervalExtractor.scala b/src/app/model/rdf/sparql/timeline/extractor/IntervalExtractor.scala index 708fdd08..72094fcb 100644 --- a/src/app/model/rdf/sparql/timeline/extractor/IntervalExtractor.scala +++ b/src/app/model/rdf/sparql/timeline/extractor/IntervalExtractor.scala @@ -1,7 +1,7 @@ package model.rdf.sparql.timeline.extractor import java.text.SimpleDateFormat -import java.util.Date +import java.util.{Date, TimeZone} import model.rdf.extractor.QueryExecutionResultExtractor import model.rdf.sparql.timeline.models.Interval @@ -28,19 +28,24 @@ class IntervalExtractor extends QueryExecutionResultExtractor[IntervalQuery, Seq } private def getDate(qs: QuerySolution, fieldName: String): Date = { - val dateFormat = new SimpleDateFormat("yyyy-MM-dd") - val fieldValue = qs.getLiteral(fieldName).getString() + val dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + // Set time zone + val zone = qs.getLiteral(fieldName + "_zone") + val zoneString = if (zone == null) "GMT" else zone.getString + dateFormat.setTimeZone(TimeZone.getTimeZone(zoneString)) + + // Parse optional time val hour = qs.getLiteral(fieldName + "_hour") val minute = qs.getLiteral(fieldName + "_minute") val second = qs.getLiteral(fieldName + "_second") - val date = dateFormat.parse(fieldValue) - - if (hour != null) date.setHours(hour.getInt) - if (minute != null) date.setMinutes(minute.getInt) - if (second!= null) date.setSeconds(second.getInt) + val HH = if (hour == null) "00" else hour.getString + val mm = if (minute == null) "00" else minute.getString + val ss = if (second == null) "00" else second.getString - return date + // Parse full date-time value + val date = qs.getLiteral(fieldName).getString + return dateFormat.parse(s"""${date} ${HH}:${mm}:${ss}""") } } diff --git a/src/app/model/rdf/sparql/timeline/query/InstantQuery.scala b/src/app/model/rdf/sparql/timeline/query/InstantQuery.scala index 618f2785..d66b85d2 100644 --- a/src/app/model/rdf/sparql/timeline/query/InstantQuery.scala +++ b/src/app/model/rdf/sparql/timeline/query/InstantQuery.scala @@ -32,6 +32,7 @@ class InstantQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInstan | OPTIONAL { ?date_url time:hour ?hour } | OPTIONAL { ?date_url time:minute ?minute } | OPTIONAL { ?date_url time:second ?second } + | OPTIONAL { ?date_url time:timeZone ?zone } | | ${QueryHelpers.bindTimeDescriptionToXSDDate("date_url", "date")} | diff --git a/src/app/model/rdf/sparql/timeline/query/IntervalQuery.scala b/src/app/model/rdf/sparql/timeline/query/IntervalQuery.scala index eddb6478..b9d784c7 100644 --- a/src/app/model/rdf/sparql/timeline/query/IntervalQuery.scala +++ b/src/app/model/rdf/sparql/timeline/query/IntervalQuery.scala @@ -36,10 +36,12 @@ class IntervalQuery(maybeStart: Option[Date], maybeEnd: Option[Date], maybeInter | OPTIONAL { ?begin_url time:hour ?begin_hour } | OPTIONAL { ?begin_url time:minute ?begin_minute } | OPTIONAL { ?begin_url time:second ?begin_second } + | OPTIONAL { ?begin_url time:timeZone ?begin_zone } | | OPTIONAL { ?end_url time:hour ?begin_hour } | OPTIONAL { ?end_url time:minute ?begin_minute } | OPTIONAL { ?end_url time:second ?begin_second } + | OPTIONAL { ?end_url time:timeZone ?end_zone } | | ${QueryHelpers.bindTimeDescriptionToXSDDate("begin_url", "begin")} | ${QueryHelpers.bindTimeDescriptionToXSDDate("end_url", "end")} From bf1d8c8c9081d1f98537c7b870f7c52a720411fc Mon Sep 17 00:00:00 2001 From: vvancak Date: Tue, 18 Jul 2017 14:22:29 +0200 Subject: [PATCH 77/84] TimeLine: Naming tweaks, comments --- ...tantVisualizer.js => InstantInfoWindow.js} | 8 ++-- ...valVisualizer.js => IntervalInfoWindow.js} | 8 ++-- ...evelsVisualizer.js => LevelsInfoWindow.js} | 4 +- .../timeline/containers/FirstLevelLoader.js | 39 ++++++++++++------- .../timeline/containers/InstantsLoader.js | 3 +- .../timeline/containers/IntervalsLoader.js | 5 ++- .../timeline/containers/SecondLevelLoader.js | 18 +++++++-- .../{TimeRange.js => TimeRangeContainer.js} | 2 + .../visualizers/timeline/pages/Instants.js | 6 ++- .../timeline/pages/InstantsToFirstLevel.js | 6 ++- .../timeline/pages/InstantsToSecondLevel.js | 6 ++- .../visualizers/timeline/pages/Intervals.js | 6 ++- .../timeline/pages/IntervalsToFirstLevel.js | 6 ++- .../timeline/pages/IntervalsToSecondLevel.js | 6 ++- 14 files changed, 81 insertions(+), 42 deletions(-) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/{InstantVisualizer.js => InstantInfoWindow.js} (84%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/{IntervalVisualizer.js => IntervalInfoWindow.js} (85%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/{LevelsVisualizer.js => LevelsInfoWindow.js} (95%) rename src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/{TimeRange.js => TimeRangeContainer.js} (96%) diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/InstantVisualizer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/InstantInfoWindow.js similarity index 84% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/InstantVisualizer.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/InstantInfoWindow.js index 81e96c72..887e53e0 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/InstantVisualizer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/InstantInfoWindow.js @@ -3,12 +3,12 @@ import {connect} from "react-redux"; import {createStructuredSelector} from "reselect"; import CenteredMessage from "../../../../components/CenteredMessage"; import {selectedTimeRecordSelector} from "../ducks/selectedTimeRecord"; -import LevelsVisualizer from "./LevelsVisualizer"; +import LevelsInfoWindow from "./LevelsInfoWindow"; import makePureRender from "../../../../misc/makePureRender"; import ObjectInfo from "../../../app/containers/ObjectInfo"; import SubHeadLine from "../../../../components/Subheadline"; -class InstantVisualizer extends Component { +class InstantInfoWindow extends Component { static propTypes = { selectedTimeRecord: PropTypes.instanceOf(Array).isRequired }; @@ -29,7 +29,7 @@ class InstantVisualizer extends Component { Date-Time: {new Date(instant.date).toUTCString()}
    - +
    } } @@ -38,4 +38,4 @@ const selector = createStructuredSelector({ selectedTimeRecord: selectedTimeRecordSelector, }); -export default connect(selector)(makePureRender(InstantVisualizer)); \ No newline at end of file +export default connect(selector)(makePureRender(InstantInfoWindow)); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/IntervalVisualizer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/IntervalInfoWindow.js similarity index 85% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/IntervalVisualizer.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/IntervalInfoWindow.js index a158e8bc..14a19428 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/IntervalVisualizer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/IntervalInfoWindow.js @@ -4,10 +4,10 @@ import {createStructuredSelector} from "reselect"; import CenteredMessage from "../../../../components/CenteredMessage"; import SubHeadLine from "../../../../components/Subheadline"; import {selectedTimeRecordSelector} from "../ducks/selectedTimeRecord"; -import LevelsVisualizer from "./LevelsVisualizer"; +import LevelsInfoWindow from "./LevelsInfoWindow"; import ObjectInfo from "../../../app/containers/ObjectInfo"; -class IntervalVisualizer extends Component { +class IntervalInfoWindow extends Component { static propTypes = { selectedTimeRecord: PropTypes.instanceOf(Array).isRequired }; @@ -30,7 +30,7 @@ class IntervalVisualizer extends Component { End: {new Date(interval.end).toUTCString()}
    - +
    } @@ -40,4 +40,4 @@ const selector = createStructuredSelector({ selectedTimeRecord: selectedTimeRecordSelector, }); -export default connect(selector)(IntervalVisualizer); +export default connect(selector)(IntervalInfoWindow); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/LevelsVisualizer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/LevelsInfoWindow.js similarity index 95% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/LevelsVisualizer.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/LevelsInfoWindow.js index af14d45b..67a6783f 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/LevelsVisualizer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/components/LevelsInfoWindow.js @@ -8,7 +8,7 @@ import {secondLevelSelector} from "../ducks/secondLevel"; import SubHeadLine from "../../../../components/Subheadline"; import ObjectInfo from "../../../app/containers/ObjectInfo"; -class LevelsVisualizer extends Component { +class LevelsInfoWindow extends Component { static propTypes = { timeRecordUrl: PropTypes.string.isRequired, firstLevel: PropTypes.instanceOf(Array).isRequired, @@ -70,4 +70,4 @@ const selector = createStructuredSelector({ secondLevel: secondLevelSelector }); -export default connect(selector)(LevelsVisualizer); +export default connect(selector)(LevelsInfoWindow); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelLoader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelLoader.js index 3c571575..ae9d37f9 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelLoader.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/FirstLevelLoader.js @@ -38,7 +38,7 @@ class FirstLevelLoader extends Component { firstLevelCount: PropTypes.func.isRequired, status: PropTypes.instanceOf(PromiseStatus).isRequired, - // Value selectors + // Configurations selectors selectedFirstLevelTypes: PropTypes.instanceOf(ImmutableSet).isRequired, selectedFirstLevelPredicates: PropTypes.instanceOf(ImmutableSet).isRequired, @@ -48,24 +48,23 @@ class FirstLevelLoader extends Component { componentWillMount() { const {isInitial, secondLevel} = this.props; + // Load data only if this loader is initial (responsible for the first load) if (isInitial) { this.load(secondLevel); } } componentWillReceiveProps(nextProps) { - const {dispatch, firstLevelLoader, firstLevelCount, secondLevel, limit} = this.props; + const {secondLevel} = this.props; + + // Reload data only on second level change if (secondLevel != nextProps.secondLevel) { - // Do not reset selected things on app startup + // Previous second level data contained data => reset whole component if (secondLevel.length > 0) { - dispatch(setSelectedFirstLevelTypesReset()); - dispatch(setSelectedFirstLevelPredicatesReset()); - - var urls = nextProps.secondLevel.map(l => l.inner); - dispatch(firstLevelLoader(urls, [], [], limit)); - dispatch(firstLevelCount(urls, [], [])); + this.reset(nextProps.secondLevel); } + // Previous second level data was empty => Application startup (level 2 finished, starting level 1) => just load. else { this.load(nextProps.secondLevel); } @@ -80,6 +79,7 @@ class FirstLevelLoader extends Component { dispatch(setSelectedFirstLevelPredicatesReset()); } + // Load first level data according to second level data load(secondLevel) { const {dispatch, firstLevelLoader, firstLevelCount, selectedFirstLevelTypes, selectedFirstLevelPredicates, limit} = this.props; @@ -88,8 +88,9 @@ class FirstLevelLoader extends Component { dispatch(firstLevelCount(urls, [...selectedFirstLevelTypes], [...selectedFirstLevelPredicates])) } - reset() { - const {dispatch, firstLevelLoader, firstLevelCount, secondLevel, limit} = this.props; + // Reset the loaded data + all configurations supported at this level + reset(secondLevel) { + const {dispatch, firstLevelLoader, firstLevelCount, limit} = this.props; dispatch(setSelectedFirstLevelTypesReset()); dispatch(setSelectedFirstLevelPredicatesReset()); @@ -109,7 +110,14 @@ class FirstLevelLoader extends Component { } else if (firstLevel.length == 0) { - return No connected things were loaded. Check the settings please. + return
    + No first level things were loaded. Check the configuration. +
    } var buttonsEnabled = selectedFirstLevelTypes.size > 0 || selectedFirstLevelPredicates.size > 0; @@ -136,7 +144,7 @@ class FirstLevelLoader extends Component { label="LOAD" />
    } var buttonsEnabled = selectedSecondLevelThings.size > 0 || selectedSecondLevelPredicates.size > 0; @@ -118,8 +128,10 @@ class SecondLevelLoader extends Component { const selector = createStructuredSelector({ secondLevel: secondLevelSelector, status: secondLevelStatusSelector, + selectedSecondLevelThings: selectedSecondLevelThingsSelector, selectedSecondLevelPredicates: selectedSecondLevelPredicatesSelector, + limit: limitSelector }); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRange.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRangeContainer.js similarity index 96% rename from src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRange.js rename to src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRangeContainer.js index b163bee9..f6d97f05 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRange.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/containers/TimeRangeContainer.js @@ -9,6 +9,7 @@ import {setTimeRangeReset, setTimeRange, timeRangeSelector} from "../ducks/timeR import Button from "../../../../components/Button"; import {setSelectTimeRecordReset} from "../ducks/selectedTimeRecord"; + class TimeRangeContainer extends Component { static propTypes = { dispatch: PropTypes.func.isRequired, @@ -34,6 +35,7 @@ class TimeRangeContainer extends Component { componentDidUpdate() { const {timeRange} = this.props; + // The render() method sets only default value, so we will have to add the actual value manually var beginString = moment(timeRange.begin).format('YYYY-MM-DD'); var endString = moment(timeRange.end).format('YYYY-MM-DD'); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Instants.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Instants.js index 90f72c1d..d1fa26b8 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Instants.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/timeline/pages/Instants.js @@ -2,7 +2,7 @@ import React, {Component, PropTypes} from "react"; import BodyPadding from "../../../../components/BodyPadding"; import TimeLineInstants from "../components/TimeLineInstants"; import LimiterContainer from "../../../app/containers/LimiterContainer"; -import InstantVisualizer from "../components/InstantVisualizer"; +import InstantInfoWindow from "../components/InstantInfoWindow"; import InstantsLoader from "../containers/InstantsLoader"; import {PromiseStatus} from "../../../core/models"; import {getConfiguration, getConfigurationStatusSelector} from "../ducks/configuration"; @@ -30,6 +30,7 @@ class Instants extends Component { loadingMessage="Loading configuration..."/> } + // Specify which loaders are in the configuration toolbar let configurations = new Map([ ["TIME RANGE",
    + this.forceUpdate(); + } + + getSearchComponent() { + var resetEnabled = (this.needle && this.needle != ''); + return
    + this.setNeedle()} hintText={'\tSearch ...'}/> +
    + } + + // === CHECKBOX LIST === + isChecked(key) { + const {selectedKeys} = this.props; + if (selectedKeys.contains(key)) { + return true; } - - // === CHECKBOX LIST === - isChecked(key) { - const {selectedKeys} = this.props; - if (selectedKeys.contains(key)) { - return true; - } - return false; + return false; + } + + getLabel(key) { + const {dispatch, labels} = this.props; + if (!labels.has(key)) { + dispatch(getLabels([key])); + return key; } - - getLabel(key) { - const {dispatch, labels} = this.props; - if (!labels.has(key)) { - dispatch(getLabels([key])); - return key; - } - else { - return extractFromLocalizedValue(this.props.language, labels.get(key), key); - } + else { + return extractFromLocalizedValue(this.props.language, labels.get(key), key); } + } - getMatchingRecords(map) { - var matchingValues = new Map(); + getMatchingRecords(map) { + var matchingValues = new Map(); - for (const [key, value] of map) { - if (value.toLowerCase().includes(this.needle)) { - matchingValues.set(key, value); - } - } - - return matchingValues; + for (const [key, value] of map) { + if (value.toLowerCase().includes(this.needle)) { + matchingValues.set(key, value); + } } - getValuesForVisualization() { - const {records, getKey} = this.props; + return matchingValues; + } - // Deduplication - var map = new Map(records.map(t => { - var key = getKey(t); - return [key, this.getLabel(key)] - })); + getValuesForVisualization() { + const {records, getKey} = this.props; - // Needle Search - if (this.needle && this.needle != '') { - return this.getMatchingRecords(map); - } - else return map; - } + // Deduplication + var map = new Map(records.map(t => { + var key = getKey(t); + return [key, this.getLabel(key)] + })); - getCheckboxRows(valuesMap) { - const {onKeySelect} = this.props; - - var valuesMap = this.getValuesForVisualization(); - - var counter = 0; - var rows = []; - - if (valuesMap.size > 0) { - for (const [key, value] of valuesMap) { - - // Checkbox props - const checked = this.isChecked(key); - - // Row render - only for current page - var currentPage = parseInt(counter / 10); - if (currentPage == this.page) { - rows.push( - - onKeySelect(key)} - defaultChecked={checked} - label={value}/> - - ); - } - ++counter; - } + // Needle Search + if (this.needle && this.needle != '') { + return this.getMatchingRecords(map); + } + else return map; + } + + getCheckboxRows(valuesMap) { + const {onKeySelect} = this.props; + + var valuesMap = this.getValuesForVisualization(); + + var counter = 0; + var rows = []; + + if (valuesMap.size > 0) { + for (const [key, value] of valuesMap) { + + // Checkbox props + const checked = this.isChecked(key); + + // Row render - only for current page + var currentPage = parseInt(counter / 10); + if (currentPage == this.page) { + rows.push( + + onKeySelect(key)} + defaultChecked={checked} + label={value}/> + + ); } - else rows = - No values found. - ; - - return rows; + ++counter; + } } + else rows = + No values found. + ; + + return rows; + } + + // Bottom navigation + getNavigationToolbar(totalPages) { + const nextEnabled = this.page < totalPages; + const nextFunc = () => { + ++this.page; + this.forceUpdate(); + }; - // Bottom navigation - getNavigationToolbar(totalPages) { - const nextEnabled = this.page < totalPages; - const nextFunc = () => { - ++this.page; - this.forceUpdate(); - }; - - const prevEnabled = this.page > 0; - const prevFunc = () => { - --this.page; - this.forceUpdate(); - }; - - return ( -
    - Page {this.page + 1} of {totalPages + 1} - - - - - - - -
    - -
    -
    - ); - } + const prevEnabled = this.page > 0; + const prevFunc = () => { + --this.page; + this.forceUpdate(); + }; + + return ( +
    + Page {this.page + 1} of {totalPages + 1} + + + + + + + +
    + +
    +
    + ); + } // === RENDERING === - render() { - var valuesMap = this.getValuesForVisualization(); - var pages = parseInt(valuesMap.size / 10); - if (valuesMap.size > 0 && valuesMap.size % 10 == 0) --pages; - - return
    - {this.props.header} - {this.getSearchComponent()} - - {this.getCheckboxRows(valuesMap)} - - {this.getNavigationToolbar(pages)} -
    -
    - } + render() { + var valuesMap = this.getValuesForVisualization(); + var pages = parseInt(valuesMap.size / 10); + if (valuesMap.size > 0 && valuesMap.size % 10 == 0) --pages; + + return
    + {this.props.header} + {this.getSearchComponent()} + + {this.getCheckboxRows(valuesMap)} + + {this.getNavigationToolbar(pages)} +
    +
    + } } const selector = createStructuredSelector({ - labels: labelsSelector, - language: langSelector + labels: labelsSelector, + language: langSelector }); export default connect(selector)(RecordSelector); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/common/utils/apiUtils.js b/src/app/assets_webpack/assistant/javascripts/modules/common/utils/apiUtils.js index a783c250..b6102e1a 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/common/utils/apiUtils.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/common/utils/apiUtils.js @@ -2,66 +2,66 @@ // Apply callbacks until limit reaches out. export async function applyByBatchesWithLimit(arr, batchSize, limit, callback) { - var retArr = []; - var remaining = limit; + var retArr = []; + var remaining = limit; - // For calls with empty array - if (arr.length == 0) { - return await callback(arr, limit); - } + // For calls with empty array + if (arr.length == 0) { + return await callback(arr, limit); + } - for (var i = 0; i < arr.length / batchSize && remaining > 0; ++i) { + for (var i = 0; i < arr.length / batchSize && remaining > 0; ++i) { - // Boundaries - const maybeEnd = (i + 1) * batchSize; - const end = maybeEnd < arr.length ? maybeEnd : arr.length; - const begin = i * batchSize; + // Boundaries + const maybeEnd = (i + 1) * batchSize; + const end = maybeEnd < arr.length ? maybeEnd : arr.length; + const begin = i * batchSize; - // Call function with array slice - var slice = arr.slice(begin, end); - var result = await callback(slice, remaining); + // Call function with array slice + var slice = arr.slice(begin, end); + var result = await callback(slice, remaining); - // Incorrect result => return only last result ( error state ) - if (!Array.isArray(result)) { - return result; - } + // Incorrect result => return only last result ( error state ) + if (!Array.isArray(result)) { + return result; + } - // Correct result => append to retArr - retArr = retArr.concat(result); + // Correct result => append to retArr + retArr = retArr.concat(result); - // Reevaluate limit - remaining -= result.length; - } - return retArr; + // Reevaluate limit + remaining -= result.length; + } + return retArr; } // Apply callbacks & count total of values returned export async function applyByBatchesCount(arr, batchSize, callback) { - var retCount = {value: 0}; + var retCount = {value: 0}; - // For calls with empty array - if (arr.length == 0) { - return await callback(arr); - } + // For calls with empty array + if (arr.length == 0) { + return await callback(arr); + } - for (var i = 0; i < arr.length / batchSize; ++i) { + for (var i = 0; i < arr.length / batchSize; ++i) { - // Boundaries - const maybeEnd = (i + 1) * batchSize; - const end = maybeEnd < arr.length ? maybeEnd : arr.length; - const begin = i * batchSize; + // Boundaries + const maybeEnd = (i + 1) * batchSize; + const end = maybeEnd < arr.length ? maybeEnd : arr.length; + const begin = i * batchSize; - // Call function with array slice - var slice = arr.slice(begin, end); - var result = await callback(slice); - - // Incorrect result => return only last result ( error state ) - if (!Number.isInteger(result.value)) { - return result; - } + // Call function with array slice + var slice = arr.slice(begin, end); + var result = await callback(slice); - // Correct result => append to retArr - retCount.value += result.value; + // Incorrect result => return only last result ( error state ) + if (!Number.isInteger(result.value)) { + return result; } - return retCount; + + // Correct result => append to retArr + retCount.value += result.value; + } + return retCount; } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/common/utils/arrayUtils.js b/src/app/assets_webpack/assistant/javascripts/modules/common/utils/arrayUtils.js index ed7d7ad4..2bf9cd6e 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/common/utils/arrayUtils.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/common/utils/arrayUtils.js @@ -1,8 +1,8 @@ -export function getDistinctCount(getKey, array){ - var set = new Set(); - for (var element of array){ - var key = getKey(element); - if (!set.has(key)) set.add(key); - } - return set.size; +export function getDistinctCount(getKey, array) { + var set = new Set(); + for (var element of array) { + var key = getKey(element); + if (!set.has(key)) set.add(key); + } + return set.size; } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/actions.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/actions.js index c8d5153e..40a7481b 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/actions.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/actions.js @@ -1,40 +1,40 @@ -import createAction from "../../../misc/createAction"; -import * as api from "./api"; -import {applicationSelector} from "../../app/ducks/application"; -import {GET_PROPERTIES} from "./ducks/properties"; -import {GET_SKOS_CONCEPTS} from "./ducks/skosConcepts"; -import {GET_SKOS_CONCEPTS_COUNTS} from "./ducks/skosConceptsCounts"; +import createAction from '../../../misc/createAction' +import * as api from './api' +import { applicationSelector } from '../../app/ducks/application' +import { GET_PROPERTIES } from './ducks/properties' +import { GET_SKOS_CONCEPTS } from './ducks/skosConcepts' +import { GET_SKOS_CONCEPTS_COUNTS } from './ducks/skosConceptsCounts' export function queryDataset() { - return (dispatch, getState) => { - const appId = applicationSelector(getState()).id; + return (dispatch, getState) => { + const appId = applicationSelector(getState()).id; - // Get properties - const getPropertiesPromise = api.getProperties(appId); - dispatch(createAction(GET_PROPERTIES, {promise: getPropertiesPromise})); + // Get properties + const getPropertiesPromise = api.getProperties(appId); + dispatch(createAction(GET_PROPERTIES, { promise: getPropertiesPromise })); - // Get Skos concepts for each property - getPropertiesPromise.then(properties => { - properties.forEach(property => { - const getSkosConceptsPromise = api.getSkosConcepts(appId, [property.schemeUri]); - dispatch(createAction(GET_SKOS_CONCEPTS, - {promise: getSkosConceptsPromise}, - {id: property.schemeUri})); + // Get Skos concepts for each property + getPropertiesPromise.then(properties => { + properties.forEach(property => { + const getSkosConceptsPromise = api.getSkosConcepts(appId, [property.schemeUri]); + dispatch(createAction(GET_SKOS_CONCEPTS, + { promise: getSkosConceptsPromise }, + { id: property.schemeUri })); - // Get Skos concepts counts for each property - getSkosConceptsPromise.then(skosConcepts => { - const conceptUris = skosConcepts[property.schemeUri].map(concept => concept.uri); - const getSkosConceptsCountsPromise = - api.getSkosConceptsCounts(appId, property.uri, conceptUris) - .then(counts => ({ - [property.uri]: counts - })); + // Get Skos concepts counts for each property + getSkosConceptsPromise.then(skosConcepts => { + const conceptUris = skosConcepts[property.schemeUri].map(concept => concept.uri); + const getSkosConceptsCountsPromise = + api.getSkosConceptsCounts(appId, property.uri, conceptUris) + .then(counts => ({ + [property.uri]: counts + })); - dispatch(createAction(GET_SKOS_CONCEPTS_COUNTS, - {promise: getSkosConceptsCountsPromise}, - {id: property.uri})); - }); - }); + dispatch(createAction(GET_SKOS_CONCEPTS_COUNTS, + { promise: getSkosConceptsCountsPromise }, + { id: property.uri })); }); - } + }); + }); + } } \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/api.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/api.js index 3b064c7f..2458508a 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/api.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/api.js @@ -1,131 +1,131 @@ -import rest from "../../../misc/rest"; -import {applyByBatchesCount, applyByBatchesWithLimit} from "../../common/utils/apiUtils"; +import rest from '../../../misc/rest' +import { applyByBatchesCount, applyByBatchesWithLimit } from '../../common/utils/apiUtils' const BATCH_SIZE = 100; export async function getProperties(id) { - const result = await rest('mapsVisualizer/getProperties/' + id, {}); - return result.data.properties; + const result = await rest('mapsVisualizer/getProperties/' + id, {}); + return result.data.properties; } export async function getSkosConcepts(id, conceptUris) { - const result = await rest('mapsVisualizer/getSkosConcepts/' + id, {conceptUris}); - return result.data.skosConcepts; + const result = await rest('mapsVisualizer/getSkosConcepts/' + id, { conceptUris }); + return result.data.skosConcepts; } export async function getSkosConceptsCounts(id, propertyUri, conceptUris) { - const result = await rest('mapsVisualizer/getSkosConceptsCounts/' + id, {propertyUri, conceptUris}); - return result.data.skosConceptsCounts; + const result = await rest('mapsVisualizer/getSkosConceptsCounts/' + id, { propertyUri, conceptUris }); + return result.data.skosConceptsCounts; } export async function getMarkers(id, mapQueryData) { - const result = await rest('mapsVisualizer/getMarkers/' + id, mapQueryData); - return result.data.markers; + const result = await rest('mapsVisualizer/getMarkers/' + id, mapQueryData); + return result.data.markers; } export async function getCoordinates(id, urls, limit) { - const batchFunc = async function (batchUrls, batchLimit) { - let payload = { - "urls": batchUrls, - "limit": batchLimit - }; - const result = await rest('mapsVisualizer/getCoordinates/' + id, payload); - return result.data.coordinates; + const batchFunc = async function (batchUrls, batchLimit) { + let payload = { + 'urls': batchUrls, + 'limit': batchLimit }; - return applyByBatchesWithLimit(urls, BATCH_SIZE, limit, batchFunc); + const result = await rest('mapsVisualizer/getCoordinates/' + id, payload); + return result.data.coordinates; + }; + return applyByBatchesWithLimit(urls, BATCH_SIZE, limit, batchFunc); } export async function getPlaces(id, urls, placesTypes, limit) { - const batchFunc = async function (batchUrls, batchLimit) { - let payload = { - "urls": batchUrls, - "placeTypes": placesTypes, - "limit": batchLimit - }; - const result = await rest('mapsVisualizer/getPlaces/' + id, payload); - return result.data.places; + const batchFunc = async function (batchUrls, batchLimit) { + let payload = { + 'urls': batchUrls, + 'placeTypes': placesTypes, + 'limit': batchLimit }; - return applyByBatchesWithLimit(urls, BATCH_SIZE, limit, batchFunc); + const result = await rest('mapsVisualizer/getPlaces/' + id, payload); + return result.data.places; + }; + return applyByBatchesWithLimit(urls, BATCH_SIZE, limit, batchFunc); } export async function getQuantifiedThings(id, urls, valuePredicates, placePredicates, limit) { - const batchFunc = async function (batchUrls, batchLimit) { - let payload = { - "urls": batchUrls, - "valuePredicates": valuePredicates, - "placePredicates": placePredicates, - "limit": batchLimit - }; - const result = await rest('mapsVisualizer/getQuantifiedThings/' + id, payload); - return result.data.quantifiedThings; + const batchFunc = async function (batchUrls, batchLimit) { + let payload = { + 'urls': batchUrls, + 'valuePredicates': valuePredicates, + 'placePredicates': placePredicates, + 'limit': batchLimit }; - return applyByBatchesWithLimit(urls, BATCH_SIZE, limit, batchFunc); + const result = await rest('mapsVisualizer/getQuantifiedThings/' + id, payload); + return result.data.quantifiedThings; + }; + return applyByBatchesWithLimit(urls, BATCH_SIZE, limit, batchFunc); } export async function getQuantifiedPlaces(id, urls, placeTypes, valuePredicates, limit) { - const batchFunc = async function (batchUrls, batchLimit) { - let payload = { - "urls": batchUrls, - "placeTypes": placeTypes, - "valuePredicates": valuePredicates, - "limit": batchLimit - }; - const result = await rest('mapsVisualizer/getQuantifiedPlaces/' + id, payload); - return result.data.quantifiedPlaces; + const batchFunc = async function (batchUrls, batchLimit) { + let payload = { + 'urls': batchUrls, + 'placeTypes': placeTypes, + 'valuePredicates': valuePredicates, + 'limit': batchLimit }; - return applyByBatchesWithLimit(urls, BATCH_SIZE, limit, batchFunc); + const result = await rest('mapsVisualizer/getQuantifiedPlaces/' + id, payload); + return result.data.quantifiedPlaces; + }; + return applyByBatchesWithLimit(urls, BATCH_SIZE, limit, batchFunc); } export async function getCoordinatesCount(id, urls) { - const batchFunc = async function (batchUrls) { + const batchFunc = async function (batchUrls) { - let payload = { - "urls": batchUrls, - "limit": -1 - }; - const result = await rest('mapsVisualizer/getCoordinates/count/' + id, payload); - return result.data.count; + let payload = { + 'urls': batchUrls, + 'limit': -1 }; - return applyByBatchesCount(urls, BATCH_SIZE, batchFunc); + const result = await rest('mapsVisualizer/getCoordinates/count/' + id, payload); + return result.data.count; + }; + return applyByBatchesCount(urls, BATCH_SIZE, batchFunc); } export async function getPlacesCount(id, urls, placesTypes) { - const batchFunc = async function (batchUrls) { - let payload = { - "urls": batchUrls, - "placeTypes": placesTypes, - "limit": -1 - }; - const result = await rest('mapsVisualizer/getPlaces/count/' + id, payload); - return result.data.count; + const batchFunc = async function (batchUrls) { + let payload = { + 'urls': batchUrls, + 'placeTypes': placesTypes, + 'limit': -1 }; - return applyByBatchesCount(urls, BATCH_SIZE, batchFunc); + const result = await rest('mapsVisualizer/getPlaces/count/' + id, payload); + return result.data.count; + }; + return applyByBatchesCount(urls, BATCH_SIZE, batchFunc); } export async function getQuantifiedThingsCount(id, urls, valuePredicates, placePredicates) { - const batchFunc = async function (batchUrls) { - let payload = { - "urls": batchUrls, - "valuePredicates": valuePredicates, - "placePredicates": placePredicates, - "limit": -1 - }; - const result = await rest('mapsVisualizer/getQuantifiedThings/count/' + id, payload); - return result.data.count; + const batchFunc = async function (batchUrls) { + let payload = { + 'urls': batchUrls, + 'valuePredicates': valuePredicates, + 'placePredicates': placePredicates, + 'limit': -1 }; - return applyByBatchesCount(urls, BATCH_SIZE, batchFunc); + const result = await rest('mapsVisualizer/getQuantifiedThings/count/' + id, payload); + return result.data.count; + }; + return applyByBatchesCount(urls, BATCH_SIZE, batchFunc); } export async function getQuantifiedPlacesCount(id, urls, placeTypes, valuePredicates) { - const batchFunc = async function (batchUrls) { - let payload = { - "urls": batchUrls, - "placeTypes": placeTypes, - "valuePredicates": valuePredicates, - "limit": -1 - }; - const result = await rest('mapsVisualizer/getQuantifiedPlaces/count/' + id, payload); - return result.data.count; + const batchFunc = async function (batchUrls) { + let payload = { + 'urls': batchUrls, + 'placeTypes': placeTypes, + 'valuePredicates': valuePredicates, + 'limit': -1 }; - return applyByBatchesCount(urls, BATCH_SIZE, batchFunc); + const result = await rest('mapsVisualizer/getQuantifiedPlaces/count/' + id, payload); + return result.data.count; + }; + return applyByBatchesCount(urls, BATCH_SIZE, batchFunc); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/applicationRoutes.js index 19c99069..11883f3d 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/applicationRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/applicationRoutes.js @@ -1,15 +1,15 @@ -import React from "react"; -import {IndexRoute, Route} from "react-router"; -import ApplicationLoader from "../../../../app/pages/ApplicationLoader"; -import NotFound from "../../../../platform/pages/NotFound"; -import Coordinates from "../../pages/Coordinates"; +import React from 'react' +import { IndexRoute, Route } from 'react-router' +import ApplicationLoader from '../../../../app/pages/ApplicationLoader' +import NotFound from '../../../../platform/pages/NotFound' +import Coordinates from '../../pages/Coordinates' export default function createRoutes(dispatch) { - return ( - - - - - - ); + return ( + + + + + + ); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/configuratorRoutes.js index 37e1356f..47fbddc4 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/configuratorRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/configuratorRoutes.js @@ -1,10 +1,10 @@ -import React from "react"; -import {Route} from "react-router"; -import {MODULE_PREFIX} from "./prefix"; -import Coordinates from "../../pages/Coordinates"; +import React from 'react' +import { Route } from 'react-router' +import { MODULE_PREFIX } from './prefix' +import Coordinates from '../../pages/Coordinates' export default function createRoutes(dispatch) { - return ( - - ); + return ( + + ); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/prefix.js index ed7f0356..5ceaafa8 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/prefix.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/coordinates/prefix.js @@ -1,5 +1,5 @@ -import createPrefixer from "../../../../../misc/createPrefixer"; -import {MODULE_PREFIX as PARENT_MODULE_PREFIX} from "../../prefix"; +import createPrefixer from '../../../../../misc/createPrefixer' +import { MODULE_PREFIX as PARENT_MODULE_PREFIX } from '../../prefix' -export const MODULE_PREFIX = PARENT_MODULE_PREFIX + "-coordinates"; +export const MODULE_PREFIX = PARENT_MODULE_PREFIX + '-coordinates'; export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/applicationRoutes.js index 6bd4c989..8c4cef9d 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/applicationRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/applicationRoutes.js @@ -1,15 +1,15 @@ -import React from "react"; -import {IndexRoute, Route} from "react-router"; -import ApplicationLoader from "../../../../app/pages/ApplicationLoader"; -import NotFound from "../../../../platform/pages/NotFound"; -import Places from "../../pages/Places"; +import React from 'react' +import { IndexRoute, Route } from 'react-router' +import ApplicationLoader from '../../../../app/pages/ApplicationLoader' +import NotFound from '../../../../platform/pages/NotFound' +import Places from '../../pages/Places' export default function createRoutes(dispatch) { - return ( - - - - - - ); + return ( + + + + + + ); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/configuratorRoutes.js index ac2e0700..830121d8 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/configuratorRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/configuratorRoutes.js @@ -1,10 +1,10 @@ -import React from "react"; -import {Route} from "react-router"; -import {MODULE_PREFIX} from "./prefix"; -import Places from "../../pages/Places"; +import React from 'react' +import { Route } from 'react-router' +import { MODULE_PREFIX } from './prefix' +import Places from '../../pages/Places' export default function createRoutes(dispatch) { - return ( - - ); + return ( + + ); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/prefix.js index bb225fe0..4be71b8c 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/prefix.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/places/prefix.js @@ -1,5 +1,5 @@ -import createPrefixer from "../../../../../misc/createPrefixer"; -import {MODULE_PREFIX as PARENT_MODULE_PREFIX} from "../../prefix"; +import createPrefixer from '../../../../../misc/createPrefixer' +import { MODULE_PREFIX as PARENT_MODULE_PREFIX } from '../../prefix' -export const MODULE_PREFIX = PARENT_MODULE_PREFIX + "-places"; +export const MODULE_PREFIX = PARENT_MODULE_PREFIX + '-places'; export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/applicationRoutes.js index 67687545..24cd1485 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/applicationRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/applicationRoutes.js @@ -1,15 +1,15 @@ -import React from "react"; -import {IndexRoute, Route} from "react-router"; -import ApplicationLoader from "../../../../app/pages/ApplicationLoader"; -import NotFound from "../../../../platform/pages/NotFound"; -import QuantifiedPlaces from "../../pages/QuantifiedPlaces"; +import React from 'react' +import { IndexRoute, Route } from 'react-router' +import ApplicationLoader from '../../../../app/pages/ApplicationLoader' +import NotFound from '../../../../platform/pages/NotFound' +import QuantifiedPlaces from '../../pages/QuantifiedPlaces' export default function createRoutes(dispatch) { - return ( - - - - - - ); + return ( + + + + + + ); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/configuratorRoutes.js index a5b38508..b1c01191 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/configuratorRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/configuratorRoutes.js @@ -1,10 +1,10 @@ -import React from "react"; -import {Route} from "react-router"; -import {MODULE_PREFIX} from "./prefix"; -import QuantifiedPlaces from "../../pages/QuantifiedPlaces"; +import React from 'react' +import { Route } from 'react-router' +import { MODULE_PREFIX } from './prefix' +import QuantifiedPlaces from '../../pages/QuantifiedPlaces' export default function createRoutes(dispatch) { - return ( - - ); + return ( + + ); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/prefix.js index 8bb97505..8ad6e6ac 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/prefix.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedPlaces/prefix.js @@ -1,5 +1,5 @@ -import createPrefixer from "../../../../../misc/createPrefixer"; -import {MODULE_PREFIX as PARENT_MODULE_PREFIX} from "../../prefix"; +import createPrefixer from '../../../../../misc/createPrefixer' +import { MODULE_PREFIX as PARENT_MODULE_PREFIX } from '../../prefix' -export const MODULE_PREFIX = PARENT_MODULE_PREFIX + "-quantified-places"; +export const MODULE_PREFIX = PARENT_MODULE_PREFIX + '-quantified-places'; export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/applicationRoutes.js index d1bced57..c0e4739c 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/applicationRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/applicationRoutes.js @@ -1,15 +1,15 @@ -import React from "react"; -import {IndexRoute, Route} from "react-router"; -import ApplicationLoader from "../../../../app/pages/ApplicationLoader"; -import NotFound from "../../../../platform/pages/NotFound"; -import QuantifiedThings from "../../pages/QuantifiedThings"; +import React from 'react' +import { IndexRoute, Route } from 'react-router' +import ApplicationLoader from '../../../../app/pages/ApplicationLoader' +import NotFound from '../../../../platform/pages/NotFound' +import QuantifiedThings from '../../pages/QuantifiedThings' export default function createRoutes(dispatch) { - return ( - - - - - - ); + return ( + + + + + + ); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/configuratorRoutes.js index bd22a6b2..81362911 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/configuratorRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/configuratorRoutes.js @@ -1,10 +1,10 @@ -import React from "react"; -import {Route} from "react-router"; -import {MODULE_PREFIX} from "./prefix"; -import QuantifiedThings from "../../pages/QuantifiedThings"; +import React from 'react' +import { Route } from 'react-router' +import { MODULE_PREFIX } from './prefix' +import QuantifiedThings from '../../pages/QuantifiedThings' export default function createRoutes(dispatch) { - return ( - - ); + return ( + + ); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/prefix.js index d393d4cf..0eddcda9 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/prefix.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/quantifiedThings/prefix.js @@ -1,5 +1,5 @@ -import createPrefixer from "../../../../../misc/createPrefixer"; -import {MODULE_PREFIX as PARENT_MODULE_PREFIX} from "../../prefix"; +import createPrefixer from '../../../../../misc/createPrefixer' +import { MODULE_PREFIX as PARENT_MODULE_PREFIX } from '../../prefix' -export const MODULE_PREFIX = PARENT_MODULE_PREFIX + "-quantified-things"; +export const MODULE_PREFIX = PARENT_MODULE_PREFIX + '-quantified-things'; export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/applicationRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/applicationRoutes.js index 6b743b1f..6a6b4bef 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/applicationRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/applicationRoutes.js @@ -1,16 +1,16 @@ -import React from "react"; -import {IndexRoute, Route} from "react-router"; -import ApplicationLoader from "../../../../app/pages/ApplicationLoader"; -import NotFound from "../../../../platform/pages/NotFound"; -import Standalone from "../../pages/Standalone"; -import Embed from "../../pages/Embed"; +import React from 'react' +import { IndexRoute, Route } from 'react-router' +import ApplicationLoader from '../../../../app/pages/ApplicationLoader' +import NotFound from '../../../../platform/pages/NotFound' +import Standalone from '../../pages/Standalone' +import Embed from '../../pages/Embed' export default function createRoutes(dispatch) { - return ( - - - - - - ); + return ( + + + + + + ); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/configuratorRoutes.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/configuratorRoutes.js index 18e4da4a..d080ba3d 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/configuratorRoutes.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/configuratorRoutes.js @@ -1,10 +1,10 @@ -import React from "react"; -import {Route} from "react-router"; -import Configurator from "../../pages/Configurator"; -import {MODULE_PREFIX} from "./prefix"; +import React from 'react' +import { Route } from 'react-router' +import Configurator from '../../pages/Configurator' +import { MODULE_PREFIX } from './prefix' export default function createRoutes(dispatch) { - return ( - - ); + return ( + + ); } diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/prefix.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/prefix.js index 6f33e23b..471b17ef 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/prefix.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/bundles/v1/prefix.js @@ -1,5 +1,5 @@ -import createPrefixer from "../../../../../misc/createPrefixer"; -import {MODULE_PREFIX as PARENT_MODULE_PREFIX} from "../../prefix"; +import createPrefixer from '../../../../../misc/createPrefixer' +import { MODULE_PREFIX as PARENT_MODULE_PREFIX } from '../../prefix' export const MODULE_PREFIX = PARENT_MODULE_PREFIX; export default createPrefixer(MODULE_PREFIX); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/ApplicationFilters.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/ApplicationFilters.js index e9995b43..1b52c912 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/ApplicationFilters.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/ApplicationFilters.js @@ -1,37 +1,37 @@ -import React, {PropTypes} from "react"; -import {Map} from "immutable"; -import Paper from "material-ui/Paper"; -import RefreshMapButton from "../containers/RefreshMapButton"; -import FillInScreen from "../../../../components/FillInScreen"; -import Padding from "../../../../components/Padding"; -import FilterPreview from "../containers/FilterPreview"; -import ExpandableFilters from "./ExpandableFilters"; -import NoFiltersAvailable from "./NoFiltersAvailable"; +import React, { PropTypes } from 'react' +import { Map } from 'immutable' +import Paper from 'material-ui/Paper'; +import RefreshMapButton from '../containers/RefreshMapButton' +import FillInScreen from '../../../../components/FillInScreen' +import Padding from '../../../../components/Padding' +import FilterPreview from '../containers/FilterPreview' +import ExpandableFilters from './ExpandableFilters' +import NoFiltersAvailable from './NoFiltersAvailable' -const ApplicationFilters = ({filters, expandable}) => { +const ApplicationFilters = ({ filters, expandable }) => { - return - - -
    - {filters.size == 0 && } - {filters.toList().map(filter => -
    - -
    - )} -
    -
    - - - -
    + return + + +
    + {filters.size == 0 && } + {filters.toList().map(filter => +
    + +
    + )} +
    +
    + + + +
    }; ApplicationFilters.propTypes = { - filters: PropTypes.instanceOf(Map), - expandable: PropTypes.bool.isRequired + filters: PropTypes.instanceOf(Map), + expandable: PropTypes.bool.isRequired }; export default ApplicationFilters; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/ExpandableFilters.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/ExpandableFilters.js index cb872266..51b06b20 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/ExpandableFilters.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/ExpandableFilters.js @@ -1,70 +1,70 @@ -import React, {Component} from "react"; -import * as theme from "../../../../misc/theme"; -import materialTheme from "../../../../misc/materialTheme"; -import IconButton from "../../../../components/IconButton"; +import React, { Component, PropTypes } from 'react' +import * as theme from '../../../../misc/theme' +import materialTheme from '../../../../misc/materialTheme' +import IconButton from '../../../../components/IconButton' const headerStyle = { - backgroundColor: theme.primary, - color: 'white', - textAlign: 'center', - textTransform: 'uppercase', - fontSize: '14px', - fontWeight: 500, - padding: materialTheme.spacing.desktopGutterLess + 'px', - position: 'relative' + backgroundColor: theme.primary, + color: 'white', + textAlign: 'center', + textTransform: 'uppercase', + fontSize: '14px', + fontWeight: 500, + padding: materialTheme.spacing.desktopGutterLess + 'px', + position: 'relative' }; const iconStyle = { - position: 'absolute', - left: 0, - top: 0 + position: 'absolute', + left: 0, + top: 0 }; class ExpandableFilters extends Component { - constructor() { - super(); + constructor() { + super(); - this.state = { - expanded: false - } + this.state = { + expanded: false } + } - toggleExpanded(e) { - e.stopPropagation(); - this.setState({ - expanded: !this.state.expanded - }); - } + toggleExpanded(e) { + e.stopPropagation(); + this.setState({ + expanded: !this.state.expanded + }); + } - renderHeader(expandable, expanded) { - const style = Object.assign({}, headerStyle, expandable ? {cursor: 'pointer '} : {}); + renderHeader(expandable, expanded) { + const style = Object.assign({}, headerStyle, expandable ? { cursor: 'pointer '} : {}); - return
    - {expandable && this.renderExpandButton(expanded)} - Available filters -
    - } + return
    + {expandable && this.renderExpandButton(expanded)} + Available filters +
    + } - renderExpandButton(expanded) { - return - } + renderExpandButton(expanded) { + return + } - render() { - const {expandable} = this.props; - const {expanded} = this.state; + render() { + const { expandable } = this.props; + const { expanded } = this.state; - return
    - {this.renderHeader(expandable, expanded)} -
    - {this.props.children} -
    -
    - } + return
    + {this.renderHeader(expandable, expanded)} +
    + {this.props.children} +
    +
    + } } export default ExpandableFilters; \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/FilterHeader.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/FilterHeader.js index ed40094e..b57d028d 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/FilterHeader.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/FilterHeader.js @@ -1,116 +1,117 @@ -import React, {PropTypes} from "react"; -import Divider from "material-ui/Divider"; -import MenuItem from "material-ui/MenuItem"; -import {Filter, filterTypes as types, optionModes as modes} from "../models"; -import EditableLabel from "../../../app/containers/EditableLabel"; -import SidebarItem from "./SidebarItem"; +import React, { PropTypes } from 'react' +import Divider from 'material-ui/Divider' +import MenuItem from 'material-ui/MenuItem' +import { Filter } from '../models' +import EditableLabel from '../../../app/containers/EditableLabel' +import { filterTypes as types, optionModes as modes } from '../models' +import SidebarItem from './SidebarItem' const headerStyle = { - backgroundColor: '#f7f7f7' + backgroundColor: '#f7f7f7' }; const disabledHeaderStyle = { - textDecoration: 'line-through', - color: 'rgba(0, 0, 0, 0.3)' + textDecoration: 'line-through', + color: 'rgba(0, 0, 0, 0.3)' }; const h3Style = { - fontWeight: 'normal', - fontSize: '1.05rem', - margin: 0, - padding: 0 + fontWeight: 'normal', + fontSize: '1.05rem', + margin: 0, + padding: 0 }; const countStyle = { - fontSize: '0.9rem', - color: 'rgba(0, 0, 0, 0.6)', - fontWeight: 'bold' + fontSize: '0.9rem', + color: 'rgba(0, 0, 0, 0.6)', + fontWeight: 'bold' }; -const FilterConfigHeader = ({filter, configurable, configureAllOptions, configureFilter, expandFilter, selectAllOptions}) => { - const {property} = filter; +const FilterConfigHeader = ({ filter, configurable, configureAllOptions, configureFilter, expandFilter, selectAllOptions }) => { + const { property } = filter; - const previewMenuItems = ( -
    - selectAllOptions(true)} - disabled={filter.type == types.RADIO} - /> - selectAllOptions(false)} - disabled={filter.type == types.RADIO} - /> -
    ); + const previewMenuItems = ( +
    + selectAllOptions(true)} + disabled={filter.type == types.RADIO} + /> + selectAllOptions(false)} + disabled={filter.type == types.RADIO} + /> +
    ); - const renderCheckedCount = () => { - const checked = filter.options.filter(option => option.selected).size; - const total = filter.options.filter(option => option.mode != modes.SELECT_NEVER).size; - return ({checked}/{total}) - }; + const renderCheckedCount = () => { + const checked = filter.options.filter(option => option.selected).size; + const total = filter.options.filter(option => option.mode != modes.SELECT_NEVER).size; + return ({checked}/{total}) + }; - const configMenuItems = ( -
    - configureAllOptions({mode: modes.SELECT_ALWAYS})} - /> - configureAllOptions({mode: modes.SELECT_NEVER})} - /> - configureAllOptions({mode: modes.USER_DEFINED})} - /> - - configureFilter({enabled: true})} - /> - configureFilter({enabled: false})} - /> - - configureFilter({type: types.CHECKBOX})} - /> - configureFilter({type: types.RADIO})} - /> -
    ); + const configMenuItems = ( +
    + configureAllOptions({ mode: modes.SELECT_ALWAYS })} + /> + configureAllOptions({ mode: modes.SELECT_NEVER })} + /> + configureAllOptions({ mode: modes.USER_DEFINED })} + /> + + configureFilter({ enabled: true })} + /> + configureFilter({ enabled: false })} + /> + + configureFilter({ type: types.CHECKBOX })} + /> + configureFilter({ type: types.RADIO })} + /> +
    ); - return ( -
    - expandFilter(!filter.expanded)} - > -

    - {' '} - {!configurable && filter.type == types.CHECKBOX && renderCheckedCount()} -

    -
    - -
    ); + return ( +
    + expandFilter(!filter.expanded)} + > +

    + {' '} + {!configurable && filter.type == types.CHECKBOX && renderCheckedCount()} +

    +
    + +
    ); }; FilterConfigHeader.propTypes = { - filter: PropTypes.instanceOf(Filter).isRequired, - configurable: PropTypes.bool, - configureAllOptions: PropTypes.func, - configureFilter: PropTypes.func, - expandFilter: PropTypes.func, - selectAllOptions: PropTypes.func + filter: PropTypes.instanceOf(Filter).isRequired, + configurable: PropTypes.bool, + configureAllOptions: PropTypes.func, + configureFilter: PropTypes.func, + expandFilter: PropTypes.func, + selectAllOptions: PropTypes.func }; export default FilterConfigHeader; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/GoogleMapsCircles.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/GoogleMapsCircles.js index 06cb02e8..70670fb9 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/GoogleMapsCircles.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/GoogleMapsCircles.js @@ -1,226 +1,226 @@ -import React, {Component, PropTypes} from "react"; -import {connect, Provider} from "react-redux"; -import {Map as ImmutableMap, Set as ImmutableSet} from "immutable"; -import {Circle, InfoWindow} from "react-google-maps"; -import GoogleMap from "../../../../components/GoogleMap"; -import {mapStateSelector, updateMapState} from "../ducks/mapState"; -import {toggledMarkersSelector, toggleMarker} from "../ducks/toggledMarkers"; -import {coordinatesSelector} from "../ducks/coordinates"; -import MapMarker from "./MapMarkerInfoWindow"; -import {MapState} from "../models"; -import {createStructuredSelector} from "reselect"; -import {placesSelector} from "../ducks/places"; -import {quantifiedThingsSelector} from "../ducks/quantifiedThings"; -import {quantifiedPlacesSelector} from "../ducks/quantifiedPlaces"; -import {colorsSelector, setColors, setColorsReset} from "../ducks/colors"; +import React, { Component, PropTypes } from 'react' +import { connect, Provider } from 'react-redux' +import { Map as ImmutableMap, Set as ImmutableSet } from 'immutable' +import { Circle, InfoWindow } from 'react-google-maps' +import GoogleMap from '../../../../components/GoogleMap' +import { mapStateSelector, updateMapState } from '../ducks/mapState' +import { toggledMarkersSelector, toggleMarker } from '../ducks/toggledMarkers' +import { coordinatesSelector } from '../ducks/coordinates' +import MapMarker from './MapMarkerInfoWindow' +import { MapState } from '../models' +import { createStructuredSelector } from 'reselect' +import { placesSelector } from '../ducks/places' +import { quantifiedThingsSelector } from '../ducks/quantifiedThings' +import { quantifiedPlacesSelector } from '../ducks/quantifiedPlaces' +import { colorsSelector, setColors, setColorsReset } from '../ducks/colors' class GoogleMapsMarkers extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, + static propTypes = { + dispatch: PropTypes.func.isRequired, - coordinates: PropTypes.instanceOf(Array).isRequired, - places: PropTypes.array.isRequired, - quantifiedThings: PropTypes.array.isRequired, - quantifiedPlaces: PropTypes.array.isRequired, + coordinates: PropTypes.instanceOf(Array).isRequired, + places: PropTypes.array.isRequired, + quantifiedThings: PropTypes.array.isRequired, + quantifiedPlaces: PropTypes.array.isRequired, - mapState: PropTypes.instanceOf(MapState).isRequired, - toggledMarkers: PropTypes.instanceOf(ImmutableSet).isRequired, + mapState: PropTypes.instanceOf(MapState).isRequired, + toggledMarkers: PropTypes.instanceOf(ImmutableSet).isRequired, - colors: PropTypes.instanceOf(ImmutableMap).isRequired - }; + colors: PropTypes.instanceOf(ImmutableMap).isRequired + }; - static contextTypes = { - store: PropTypes.object.isRequired - }; + static contextTypes = { + store: PropTypes.object.isRequired + }; - getColor(url) { - if (this.colors.has(url)) { - return this.colors.get(url); - } - else { - var color = '#' + (0x1000000 + (Math.random()) * 0xffffff).toString(16).substr(1, 6); - this.colors = this.colors.set(url, color); - return color; - } + getColor(url) { + if (this.colors.has(url)) { + return this.colors.get(url); + } + else { + var color = '#' + (0x1000000 + (Math.random()) * 0xffffff).toString(16).substr(1, 6); + this.colors = this.colors.set(url, color); + return color; } + } - // === MARKERS === - infoWindow(coors) { - const {toggledMarkers, dispatch} = this.props; - - const position = { - lat: parseFloat(coors.latitude.toFixed(5)), - lng: parseFloat(coors.longitude.toFixed(5)) - }; - - if (toggledMarkers.contains(coors.url)) { - return ( - dispatch(toggleMarker(coors.url))} - position={position} - > - - - - - ); - } + // === MARKERS === + infoWindow(coors) { + const { toggledMarkers, dispatch } = this.props; - return ""; - } + const position = { + lat: parseFloat(coors.latitude.toFixed(5)), + lng: parseFloat(coors.longitude.toFixed(5)) + }; - getQuantifiedThingConnection(url) { - const {places, quantifiedThings} = this.props; - - for (const place of places) { - if (place.coordinates == url) { - for (const thing of quantifiedThings) { - if (thing.place == place.url) { - return {thing: thing, place: place}; - } - } - } - } - return null; + if (toggledMarkers.contains(coors.url)) { + return ( + dispatch(toggleMarker(coors.url))} + position={position} + > + + + + + ); } - getQuantifiedPlaceConnection(url) { - const {quantifiedPlaces} = this.props; + return ''; + } - for (const place of quantifiedPlaces) { - if (place.coordinates == url) { - return {quantifiedPlace: place}; - } + getQuantifiedThingConnection(url) { + const { places, quantifiedThings } = this.props; + + for (const place of places) { + if (place.coordinates == url) { + for (const thing of quantifiedThings) { + if (thing.place == place.url) { + return { thing: thing, place: place }; + } } - return null; + } } + return null; + } - // === CIRCLES === - getMaxOfAllValues() { - const {quantifiedPlaces, quantifiedThings} = this.props; - - var qpvMax = Math.max.apply(null, quantifiedPlaces.map(p => p.value)); - var qtvMax = Math.max.apply(null, quantifiedThings.map(t => t.value)); + getQuantifiedPlaceConnection(url) { + const { quantifiedPlaces } = this.props; - return (qtvMax > qpvMax) ? qtvMax : qpvMax; + for (const place of quantifiedPlaces) { + if (place.coordinates == url) { + return { quantifiedPlace: place }; + } } + return null; + } - circle(coordinates, maxValue) { - const {dispatch, mapState} = this.props; + // === CIRCLES === + getMaxOfAllValues() { + const { quantifiedPlaces, quantifiedThings } = this.props; - // Adjusting radius & stroke to zoom levels - const nonZeroZoom = 1 + mapState.zoomLevel; + var qpvMax = Math.max.apply(null, quantifiedPlaces.map(p => p.value)); + var qtvMax = Math.max.apply(null, quantifiedThings.map(t => t.value)); - const MAX_RADIUS = (1000 / (nonZeroZoom * nonZeroZoom)) * 1000; // Radius is in meters... - const MAX_STROKE_W = nonZeroZoom; + return (qtvMax > qpvMax) ? qtvMax : qpvMax; + } - var value = 0; - var placeType = "default_place_type"; - var valuePredicate = "default_value_predicate"; + circle(coordinates, maxValue) { + const { dispatch, mapState } = this.props; - // Values for radius, Place type & Value predicate for colors + // Adjusting radius & stroke to zoom levels + const nonZeroZoom = 1 + mapState.zoomLevel; - // From quantified thing - var qt = this.getQuantifiedThingConnection(coordinates.url); + const MAX_RADIUS = (1000 / (nonZeroZoom * nonZeroZoom)) * 1000; // Radius is in meters... + const MAX_STROKE_W = nonZeroZoom; - if (qt != null) { - value = qt.thing.value; - placeType = qt.place.placeType; - valuePredicate = qt.thing.valuePredicate; - } + var value = 0; + var placeType = 'default_place_type'; + var valuePredicate = 'default_value_predicate'; - // From quantifiedPlace - var qp = this.getQuantifiedPlaceConnection(coordinates.url); - if (qp != null) { - value = qp.quantifiedPlace.value; - placeType = qp.quantifiedPlace.placeType; - valuePredicate = qp.quantifiedPlace.valuePredicate; - } + // Values for radius, Place type & Value predicate for colors - // Map radius to (0,maxRadius) - const radius = (value / maxValue) * MAX_RADIUS; - - // Stroke - const strokeWidth = 1 + parseInt((value / maxValue) * MAX_STROKE_W); - - // Colors - const strokeColor = this.getColor(valuePredicate); - const fillColor = this.getColor(placeType); - - // Render the circle. - const position = { - lat: parseFloat(coordinates.latitude.toFixed(5)), - lng: parseFloat(coordinates.longitude.toFixed(5)) - }; - return ( - dispatch(toggleMarker(coordinates.url))} - options={{ - strokeColor: strokeColor, - strokeOpacity: 1, - strokeWeight: strokeWidth, - fillColor: fillColor, - fillOpacity: 0.5 - }} - /> - ); - } + // From quantified thing + var qt = this.getQuantifiedThingConnection(coordinates.url); - // === RENDER === - componentDidMount() { - this.colors = this.props.colors; + if (qt != null) { + value = qt.thing.value; + placeType = qt.place.placeType; + valuePredicate = qt.thing.valuePredicate; } - componentWillReceiveProps(nextProps) { - if (nextProps.colors != this.props.colors) { - this.colors = nextProps.colors; - } + // From quantifiedPlace + var qp = this.getQuantifiedPlaceConnection(coordinates.url); + if (qp != null) { + value = qp.quantifiedPlace.value; + placeType = qp.quantifiedPlace.placeType; + valuePredicate = qp.quantifiedPlace.valuePredicate; } - componentDidUpdate() { - const {dispatch} = this.props; - if (this.props.colors != this.colors) { - dispatch(setColors(this.colors)); - } - } + // Map radius to (0,maxRadius) + const radius = (value / maxValue) * MAX_RADIUS; - componentWillUnmount() { - const {dispatch} = this.props; - dispatch(setColorsReset()); - } + // Stroke + const strokeWidth = 1 + parseInt((value / maxValue) * MAX_STROKE_W); + + // Colors + const strokeColor = this.getColor(valuePredicate); + const fillColor = this.getColor(placeType); - render() { - const {dispatch, coordinates, mapState} = this.props; - - var maxValue = this.getMaxOfAllValues(); - return ( - dispatch(updateMapState({zoomLevel}))} - onCenterChanged={center => dispatch(updateMapState({center}))} - defaultZoom={mapState.zoomLevel} - defaultCenter={mapState.center.toJS()} - > - {coordinates.map(c => this.infoWindow(c))} - {coordinates.map(c => this.circle(c, maxValue))} - - ); + // Render the circle. + const position = { + lat: parseFloat(coordinates.latitude.toFixed(5)), + lng: parseFloat(coordinates.longitude.toFixed(5)) }; + return ( + dispatch(toggleMarker(coordinates.url))} + options={{ + strokeColor: strokeColor, + strokeOpacity: 1, + strokeWeight: strokeWidth, + fillColor: fillColor, + fillOpacity: 0.5 + }} + /> + ); + } + + // === RENDER === + componentDidMount() { + this.colors = this.props.colors; + } + + componentWillReceiveProps(nextProps) { + if (nextProps.colors != this.props.colors) { + this.colors = nextProps.colors; + } + } + + componentDidUpdate() { + const { dispatch } = this.props; + if (this.props.colors != this.colors) { + dispatch(setColors(this.colors)); + } + } + + componentWillUnmount() { + const { dispatch } = this.props; + dispatch(setColorsReset()); + } + + render() { + const { dispatch, coordinates, mapState } = this.props; + + var maxValue = this.getMaxOfAllValues(); + return ( + dispatch(updateMapState({ zoomLevel }))} + onCenterChanged={center => dispatch(updateMapState({ center }))} + defaultZoom={mapState.zoomLevel} + defaultCenter={mapState.center.toJS()} + > + {coordinates.map(c => this.infoWindow(c))} + {coordinates.map(c => this.circle(c, maxValue))} + + ); + }; } const selector = createStructuredSelector({ - coordinates: coordinatesSelector, + coordinates: coordinatesSelector, - places: placesSelector, - quantifiedThings: quantifiedThingsSelector, - quantifiedPlaces: quantifiedPlacesSelector, + places: placesSelector, + quantifiedThings: quantifiedThingsSelector, + quantifiedPlaces: quantifiedPlacesSelector, - toggledMarkers: toggledMarkersSelector, - mapState: mapStateSelector, + toggledMarkers: toggledMarkersSelector, + mapState: mapStateSelector, - colors: colorsSelector + colors: colorsSelector }); export default connect(selector)(GoogleMapsMarkers); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/GoogleMapsMarkers.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/GoogleMapsMarkers.js index 89504301..8e705785 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/GoogleMapsMarkers.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/GoogleMapsMarkers.js @@ -1,88 +1,88 @@ -import React, {Component, PropTypes} from "react"; -import {connect, Provider} from "react-redux"; -import {Set as ImmutableSet} from "immutable"; -import {InfoWindow, Marker} from "react-google-maps"; -import MarkerClusterer from "react-google-maps/lib/addons/MarkerClusterer"; -import GoogleMap from "../../../../components/GoogleMap"; -import {mapStateSelector, updateMapState} from "../ducks/mapState"; -import {toggledMarkersSelector, toggleMarker} from "../ducks/toggledMarkers"; -import {coordinatesSelector} from "../ducks/coordinates"; -import MapMarker from "./MapMarkerInfoWindow"; -import {MapState} from "../models"; -import {createStructuredSelector} from "reselect"; +import React, { Component, PropTypes } from 'react' +import { connect, Provider } from 'react-redux' +import { Set as ImmutableSet } from 'immutable' +import { InfoWindow, Marker } from 'react-google-maps' +import MarkerClusterer from 'react-google-maps/lib/addons/MarkerClusterer' +import GoogleMap from '../../../../components/GoogleMap' +import { mapStateSelector, updateMapState } from '../ducks/mapState' +import { toggledMarkersSelector, toggleMarker } from '../ducks/toggledMarkers' +import { coordinatesSelector } from '../ducks/coordinates' +import MapMarker from './MapMarkerInfoWindow' +import { MapState } from '../models' +import { createStructuredSelector } from 'reselect' class GoogleMapsMarkers extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, + static propTypes = { + dispatch: PropTypes.func.isRequired, - coordinates: PropTypes.instanceOf(Array).isRequired, + coordinates: PropTypes.instanceOf(Array).isRequired, - mapState: PropTypes.instanceOf(MapState).isRequired, - toggledMarkers: PropTypes.instanceOf(ImmutableSet).isRequired - }; + mapState: PropTypes.instanceOf(MapState).isRequired, + toggledMarkers: PropTypes.instanceOf(ImmutableSet).isRequired + }; - static contextTypes = { - store: PropTypes.object.isRequired - }; + static contextTypes = { + store: PropTypes.object.isRequired + }; - infoWindow(url) { - const {toggledMarkers, dispatch} = this.props; - if (toggledMarkers.contains(url)) { - return ( - dispatch(toggleMarker(url))}> + infoWindow(url) { + const { toggledMarkers, dispatch } = this.props; + if (toggledMarkers.contains(url)) { + return ( + dispatch(toggleMarker(url))}> - - - - - ); - } - return ""; + + + + + ); } + return ''; + } - marker(coors) { - const {dispatch} = this.props; + marker(coors) { + const { dispatch } = this.props; - const position = { - lat: parseFloat(coors.latitude.toFixed(5)), - lng: parseFloat(coors.longitude.toFixed(5)) - }; + const position = { + lat: parseFloat(coors.latitude.toFixed(5)), + lng: parseFloat(coors.longitude.toFixed(5)) + }; - return ( - dispatch(toggleMarker(coors.url))} - defaultAnimation={null}> - {this.infoWindow(coors.url)} - - ) - } + return ( + dispatch(toggleMarker(coors.url))} + defaultAnimation={null}> + {this.infoWindow(coors.url)} + + ) + } - render() { - const {dispatch, coordinates, mapState} = this.props; - return ( - dispatch(updateMapState({zoomLevel}))} - onCenterChanged={center => dispatch(updateMapState({center}))} - defaultZoom={mapState.zoomLevel} - defaultCenter={mapState.center.toJS()}> + render() { + const { dispatch, coordinates, mapState } = this.props; + return ( + dispatch(updateMapState({ zoomLevel }))} + onCenterChanged={center => dispatch(updateMapState({ center }))} + defaultZoom={mapState.zoomLevel} + defaultCenter={mapState.center.toJS()}> - - {coordinates.map(c => this.marker(c))} - - - ); - }; + + {coordinates.map(c => this.marker(c))} + + + ); + }; } const selector = createStructuredSelector({ - coordinates: coordinatesSelector, - toggledMarkers: toggledMarkersSelector, - mapState: mapStateSelector + coordinates: coordinatesSelector, + toggledMarkers: toggledMarkersSelector, + mapState: mapStateSelector }); export default connect(selector)(GoogleMapsMarkers); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/Layout.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/Layout.js index 1dc6abaf..4f109e3b 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/Layout.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/Layout.js @@ -1,79 +1,80 @@ -import React, {PropTypes} from "react"; -import Paper from "material-ui/Paper"; -import FillInScreen from "../../../../components/FillInScreen"; -import BodyPadding from "../../../../components/BodyPadding"; -import MapContainer from "../containers/MapContainer"; +import React, { PropTypes } from 'react' +import { Row, Col } from 'react-flexbox-grid' +import Paper from 'material-ui/Paper'; +import FillInScreen from '../../../../components/FillInScreen' +import BodyPadding from '../../../../components/BodyPadding' +import MapContainer from '../containers/MapContainer' const wrapperStyle = { - position: 'relative', - width: '100%' + position: 'relative', + width: '100%' }; const sidebarStyle = { - width: '450px', - position: 'absolute', - zIndex: 3 + width: '450px', + position: 'absolute', + zIndex: 3 }; const toolbarStyle = { - position: 'absolute', - right: 0, - zIndex: 3 + position: 'absolute', + right: 0, + zIndex: 3 }; const mapStyle = { - width: '100%', - position: 'absolute', - zIndex: 2 + width: '100%', + position: 'absolute', + zIndex: 2 }; const insetShadowWrapperStyle = { - width: '100%', - height: '10px', - position: 'absolute', - top: 0, - left: 0, - zIndex: 3, - overflow: 'hidden' + width: '100%', + height: '10px', + position: 'absolute', + top: 0, + left: 0, + zIndex: 3, + overflow: 'hidden' }; const insetShadowStyle = { - width: '100%', - height: '20px', - position: 'relative', - top: '-20px', - left: 0, - zIndex: 3 + width: '100%', + height: '20px', + position: 'relative', + top: '-20px', + left: 0, + zIndex: 3 }; -const Layout = ({sidebar, toolbar, insetShadow}) => { - return
    +const Layout = ({ sidebar, toolbar, insetShadow }) => { + return
    - {insetShadow &&
    - -
    } + {insetShadow &&
    + +
    } - {sidebar &&
    - - {sidebar} - -
    } + {sidebar &&
    + + {sidebar} + +
    } - {toolbar &&
    - {toolbar} -
    } + {toolbar &&
    + {toolbar} +
    } -
    - - - -
    -
    ; +
    + + + +
    +
    ; }; Layout.propTypes = { - sidebar: PropTypes.node, - toolbar: PropTypes.node, - insetShadow: PropTypes.bool + sidebar: PropTypes.node, + toolbar: PropTypes.node, + insetShadow: PropTypes.bool }; export default Layout; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/MapMarkerInfoWindow.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/MapMarkerInfoWindow.js index 320e214e..2cad96eb 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/MapMarkerInfoWindow.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/MapMarkerInfoWindow.js @@ -1,116 +1,116 @@ -import React, {Component, PropTypes} from "react"; -import {connect} from "react-redux"; -import {createStructuredSelector} from "reselect"; -import {coordinatesSelector} from "../ducks/coordinates"; -import {placesSelector} from "../ducks/places"; -import {quantifiedThingsSelector} from "../ducks/quantifiedThings"; -import makePureRender from "../../../../misc/makePureRender"; -import {quantifiedPlacesSelector} from "../ducks/quantifiedPlaces"; -import ObjectInfo from "../../../app/containers/ObjectInfo"; +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from 'reselect' +import { coordinatesSelector } from '../ducks/coordinates' +import { placesSelector } from '../ducks/places' +import { quantifiedThingsSelector } from '../ducks/quantifiedThings' +import makePureRender from '../../../../misc/makePureRender' +import { quantifiedPlacesSelector } from '../ducks/quantifiedPlaces' +import ObjectInfo from '../../../app/containers/ObjectInfo' class MapMarkerInfoWindow extends Component { - static propTypes = { - url: PropTypes.string.isRequired, - coordinates: PropTypes.array.isRequired, - places: PropTypes.array.isRequired, - quantifiedThings: PropTypes.array.isRequired, - quantifiedPlaces: PropTypes.array.isRequired, - }; + static propTypes = { + url: PropTypes.string.isRequired, + coordinates: PropTypes.array.isRequired, + places: PropTypes.array.isRequired, + quantifiedThings: PropTypes.array.isRequired, + quantifiedPlaces: PropTypes.array.isRequired, + }; - coordinate() { - const {url, coordinates} = this.props; - for (const c of coordinates) { - if (c.url == url) { - return
    - -
    - Latitude: - {c.latitude}
    - Longitude: - {c.longitude}
    -
    -
    - } - } - return
    + coordinate() { + const { url, coordinates } = this.props; + for (const c of coordinates) { + if (c.url == url) { + return
    + +
    + Latitude: + {c.latitude}
    + Longitude: + {c.longitude}
    +
    +
    + } } + return
    + } - // Places connected to the coordinates - connectPlaces() { - const {places, quantifiedPlaces, url} = this.props; - - // Places + Quantified Things connected to them - var connectedPlaces = []; - for (const p of places) { - if (p.coordinates == url) { - connectedPlaces.push( -
    - -
    - {this.connectQuantifiedThings(p.url)} -
    - ); - } - } + // Places connected to the coordinates + connectPlaces() { + const { places, quantifiedPlaces, url } = this.props; - // Quantified places - for (const p of quantifiedPlaces) { - if (p.coordinates == url) { - connectedPlaces.push( -
    - -
    - Value: - {p.value}
    -
    - -
    -
    - ); - } - } - return connectedPlaces; + // Places + Quantified Things connected to them + var connectedPlaces = []; + for (const p of places) { + if (p.coordinates == url) { + connectedPlaces.push( +
    + +
    + {this.connectQuantifiedThings(p.url)} +
    + ); + } } - // Quantified things connected to the place - connectQuantifiedThings(placeUrl) { - const {quantifiedThings} = this.props; - - var connectedQuantifiedThings = []; - for (const t of quantifiedThings) { - if (t.place == placeUrl) { - connectedQuantifiedThings.push( -
    - -
    - -
    - Value: - {t.value}
    -
    - -
    -
    - ); - } - } - return connectedQuantifiedThings; + // Quantified places + for (const p of quantifiedPlaces) { + if (p.coordinates == url) { + connectedPlaces.push( +
    + +
    + Value: + {p.value}
    +
    + +
    +
    + ); + } } + return connectedPlaces; + } - render() { - return
    + // Quantified things connected to the place + connectQuantifiedThings(placeUrl) { + const { quantifiedThings } = this.props; + + var connectedQuantifiedThings = []; + for (const t of quantifiedThings) { + if (t.place == placeUrl) { + connectedQuantifiedThings.push( +
    + +
    + +
    + Value: + {t.value}
    +
    +
    - {this.coordinate()} - {this.connectPlaces()} -
    +
    + ); + } } + return connectedQuantifiedThings; + } + + render() { + return
    +
    + {this.coordinate()} + {this.connectPlaces()} +
    + } } const selector = createStructuredSelector({ - coordinates: coordinatesSelector, - places: placesSelector, - quantifiedThings: quantifiedThingsSelector, - quantifiedPlaces: quantifiedPlacesSelector + coordinates: coordinatesSelector, + places: placesSelector, + quantifiedThings: quantifiedThingsSelector, + quantifiedPlaces: quantifiedPlacesSelector }); export default connect(selector)(makePureRender(MapMarkerInfoWindow)); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/NoFiltersAvailable.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/NoFiltersAvailable.js index 33578064..7b7f5b2a 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/NoFiltersAvailable.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/NoFiltersAvailable.js @@ -1,13 +1,13 @@ -import React from "react"; -import CenteredMessage from "../../../../components/CenteredMessage"; -import Padding from "../../../../components/Padding"; +import React, { PropTypes } from 'react' +import CenteredMessage from '../../../../components/CenteredMessage' +import Padding from '../../../../components/Padding' const NoFiltersAvailable = () => ( - - - Filters are not available as no filtering properties were discovered. - - + + + Filters are not available as no filtering properties were discovered. + + ); export default NoFiltersAvailable; diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/OpenEmbedAppDialogButton.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/OpenEmbedAppDialogButton.js index 57aa0e3a..b5e7670a 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/OpenEmbedAppDialogButton.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/components/OpenEmbedAppDialogButton.js @@ -1,19 +1,19 @@ -import React, {PropTypes} from "react"; -import Button from "../../../../components/Button"; -import withDialogControls from "../../../core/containers/withDialogControls"; -import {dialogName} from "./../containers/EmbedAppDialog"; +import React, { PropTypes } from 'react' +import Button from '../../../../components/Button' +import withDialogControls from '../../../core/containers/withDialogControls' +import { dialogName } from './../containers/EmbedAppDialog' const OpenEmbedAppDialogButton = props => ( -
    + render() { + const { status, places, quantifiedPlaces } = this.props; + + if (!status.done) { + return } + + return
    + +
    +
    + } } const selector = createStructuredSelector({ - coordinates: coordinatesSelector, - status: coordinatesStatusSelector, + coordinates: coordinatesSelector, + status: coordinatesStatusSelector, - places: placesSelector, - quantifiedPlaces: quantifiedPlacesSelector, + places: placesSelector, + quantifiedPlaces: quantifiedPlacesSelector, - limit: limitSelector + limit: limitSelector }); export default connect(selector)(CoordinatesLoader); \ No newline at end of file diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountCoordinatesContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountCoordinatesContainer.js index d3aab9f9..45aa7186 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountCoordinatesContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountCoordinatesContainer.js @@ -1,49 +1,50 @@ -import React, {Component, PropTypes} from "react"; -import {connect} from "react-redux"; -import {createStructuredSelector} from "reselect"; -import {PromiseStatus} from "../../../core/models"; -import {coordinatesCountSelector, coordinatesCountStatusSelector} from "../ducks/counts"; -import {coordinatesSelector, coordinatesStatusSelector} from "../ducks/coordinates" -import PromiseResult from "../../../core/components/PromiseResult"; -import CenteredMessage from "../../../../components/CenteredMessage"; -import {getDistinctCount} from "../../../common/utils/arrayUtils" +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from 'reselect' +import { PromiseStatus } from '../../../core/models' +import { coordinatesCountSelector, coordinatesCountStatusSelector } from '../ducks/counts' +import { coordinatesSelector, coordinatesStatusSelector } from '../ducks/coordinates' +import PromiseResult from '../../../core/components/PromiseResult' +import CenteredMessage from '../../../../components/CenteredMessage' +import { getDistinctCount } from '../../../common/utils/arrayUtils' class CountCoordinatesContainer extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, + static propTypes = { + dispatch: PropTypes.func.isRequired, - coordinates: PropTypes.array.isRequired, - coordinatesStatus: PropTypes.instanceOf(PromiseStatus).isRequired, + coordinates: PropTypes.array.isRequired, + coordinatesStatus: PropTypes.instanceOf(PromiseStatus).isRequired, - count: PropTypes.number.isRequired, - countStatus: PropTypes.instanceOf(PromiseStatus).isRequired - }; + count: PropTypes.number.isRequired, + countStatus: PropTypes.instanceOf(PromiseStatus).isRequired + }; - render() { - const {count, countStatus, coordinates, coordinatesStatus} = this.props; + render() { + const { count, countStatus, coordinates, coordinatesStatus } = this.props; - if (!countStatus.done) { - return - } - - if (!coordinatesStatus.done) { - return - } + if (!countStatus.done) { + return + } - var loaded = getDistinctCount(t=>t.url,coordinates); - return - Loaded {loaded} records out of {count} available. Increase limit to load more. - + if (!coordinatesStatus.done) { + return } + + var loaded = getDistinctCount(t => t.url, coordinates); + return + Loaded {loaded} records out of {count} available. Increase limit to load more. + + } } const selector = createStructuredSelector({ - coordinates: coordinatesSelector, - coordinatesStatus: coordinatesStatusSelector, + coordinates: coordinatesSelector, + coordinatesStatus: coordinatesStatusSelector, - count: coordinatesCountSelector, - countStatus: coordinatesCountStatusSelector + count: coordinatesCountSelector, + countStatus: coordinatesCountStatusSelector }); export default connect(selector)(CountCoordinatesContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountPlacesContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountPlacesContainer.js index 533e9ab2..b68250e4 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountPlacesContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountPlacesContainer.js @@ -1,50 +1,50 @@ -import React, {Component, PropTypes} from "react"; -import {connect} from "react-redux"; -import {createStructuredSelector} from "reselect"; -import {PromiseStatus} from "../../../core/models"; -import {placesCountSelector, placesCountStatusSelector} from "../ducks/counts"; -import PromiseResult from "../../../core/components/PromiseResult"; -import CenteredMessage from "../../../../components/CenteredMessage"; -import {getDistinctCount} from "../../../common/utils/arrayUtils"; -import {placesSelector, placesStatusSelector} from "../ducks/places"; +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from 'reselect' +import { PromiseStatus } from '../../../core/models' +import { placesCountSelector, placesCountStatusSelector } from '../ducks/counts' +import PromiseResult from '../../../core/components/PromiseResult' +import CenteredMessage from '../../../../components/CenteredMessage' +import { getDistinctCount } from '../../../common/utils/arrayUtils' +import { placesSelector, placesStatusSelector } from '../ducks/places' class CountPlacesContainer extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, + static propTypes = { + dispatch: PropTypes.func.isRequired, - places: PropTypes.array.isRequired, - placesStatus: PropTypes.instanceOf(PromiseStatus).isRequired, + places: PropTypes.array.isRequired, + placesStatus: PropTypes.instanceOf(PromiseStatus).isRequired, - count: PropTypes.number.isRequired, - countStatus: PropTypes.instanceOf(PromiseStatus).isRequired - }; + count: PropTypes.number.isRequired, + countStatus: PropTypes.instanceOf(PromiseStatus).isRequired + }; - render() { - const {count, countStatus, places, placesStatus} = this.props; + render() { + const { count, countStatus, places, placesStatus } = this.props; - if (!countStatus.done) { - return - } - - if (!placesStatus.done) { - return - } + if (!countStatus.done) { + return + } - var loaded = getDistinctCount(t => t.url, places); - return - Loaded {loaded} records out of {count} available. Increase limit to load more. - + if (!placesStatus.done) { + return } + + var loaded = getDistinctCount(t => t.url, places); + return + Loaded {loaded} records out of {count} available. Increase limit to load more. + + } } const selector = createStructuredSelector({ - places: placesSelector, - placesStatus: placesStatusSelector, + places: placesSelector, + placesStatus: placesStatusSelector, - count: placesCountSelector, - countStatus: placesCountStatusSelector, + count: placesCountSelector, + countStatus: placesCountStatusSelector, }); export default connect(selector)(CountPlacesContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountQuantifiedPlacesContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountQuantifiedPlacesContainer.js index 63159d7c..d41add63 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountQuantifiedPlacesContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountQuantifiedPlacesContainer.js @@ -1,50 +1,50 @@ -import React, {Component, PropTypes} from "react"; -import {connect} from "react-redux"; -import {createStructuredSelector} from "reselect"; -import {PromiseStatus} from "../../../core/models"; -import {quantifiedPlacesCountSelector, quantifiedPlacesCountStatusSelector} from "../ducks/counts"; -import PromiseResult from "../../../core/components/PromiseResult"; -import CenteredMessage from "../../../../components/CenteredMessage"; -import {getDistinctCount} from "../../../common/utils/arrayUtils"; -import {quantifiedPlacesSelector, quantifiedPlacesStatusSelector} from "../ducks/quantifiedPlaces"; +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from 'reselect' +import { PromiseStatus } from '../../../core/models' +import { quantifiedPlacesCountSelector, quantifiedPlacesCountStatusSelector } from '../ducks/counts' +import PromiseResult from '../../../core/components/PromiseResult' +import CenteredMessage from '../../../../components/CenteredMessage' +import { getDistinctCount } from '../../../common/utils/arrayUtils' +import { quantifiedPlacesSelector, quantifiedPlacesStatusSelector } from '../ducks/quantifiedPlaces' class CountQuantifiersContainer extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, + static propTypes = { + dispatch: PropTypes.func.isRequired, - quantifiedPlaces: PropTypes.array.isRequired, - quantifiedPlacesStatus: PropTypes.instanceOf(PromiseStatus).isRequired, + quantifiedPlaces: PropTypes.array.isRequired, + quantifiedPlacesStatus: PropTypes.instanceOf(PromiseStatus).isRequired, - count: PropTypes.number.isRequired, - countStatus: PropTypes.instanceOf(PromiseStatus).isRequired - }; + count: PropTypes.number.isRequired, + countStatus: PropTypes.instanceOf(PromiseStatus).isRequired + }; - render() { - const {count, countStatus, quantifiedPlaces, quantifiedPlacesStatus} = this.props; + render() { + const { count, countStatus, quantifiedPlaces, quantifiedPlacesStatus } = this.props; - if (!countStatus.done) { - return - } - - if (!quantifiedPlacesStatus.done) { - return - } + if (!countStatus.done) { + return + } - var loaded = getDistinctCount(t => t.url, quantifiedPlaces); - return - Loaded {loaded} records out of {count} available. Increase limit to load more. - + if (!quantifiedPlacesStatus.done) { + return } + + var loaded = getDistinctCount(t => t.url, quantifiedPlaces); + return + Loaded {loaded} records out of {count} available. Increase limit to load more. + + } } const selector = createStructuredSelector({ - quantifiedPlaces: quantifiedPlacesSelector, - quantifiedPlacesStatus: quantifiedPlacesStatusSelector, + quantifiedPlaces: quantifiedPlacesSelector, + quantifiedPlacesStatus: quantifiedPlacesStatusSelector, - count: quantifiedPlacesCountSelector, - countStatus: quantifiedPlacesCountStatusSelector + count: quantifiedPlacesCountSelector, + countStatus: quantifiedPlacesCountStatusSelector }); export default connect(selector)(CountQuantifiersContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountQuantifiedThingsContainer.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountQuantifiedThingsContainer.js index a59fa80f..aed08c0f 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountQuantifiedThingsContainer.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/CountQuantifiedThingsContainer.js @@ -1,50 +1,50 @@ -import React, {Component, PropTypes} from "react"; -import {connect} from "react-redux"; -import {createStructuredSelector} from "reselect"; -import {PromiseStatus} from "../../../core/models"; -import {quantifiedThingsCountSelector, quantifiedThingsCountStatusSelector} from "../ducks/counts"; -import PromiseResult from "../../../core/components/PromiseResult"; -import CenteredMessage from "../../../../components/CenteredMessage"; -import {getDistinctCount} from "../../../common/utils/arrayUtils"; -import {quantifiedThingsSelector, quantifiedThingsStatusSelector} from "../ducks/quantifiedThings"; +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from 'reselect' +import { PromiseStatus } from '../../../core/models' +import { quantifiedThingsCountSelector, quantifiedThingsCountStatusSelector } from '../ducks/counts' +import PromiseResult from '../../../core/components/PromiseResult' +import CenteredMessage from '../../../../components/CenteredMessage' +import { getDistinctCount } from '../../../common/utils/arrayUtils' +import { quantifiedThingsSelector, quantifiedThingsStatusSelector } from '../ducks/quantifiedThings' class CountThingsContainer extends Component { - static propTypes = { - dispatch: PropTypes.func.isRequired, + static propTypes = { + dispatch: PropTypes.func.isRequired, - quantifiedThings: PropTypes.array.isRequired, - quantifiedThingsStatus: PropTypes.instanceOf(PromiseStatus).isRequired, + quantifiedThings: PropTypes.array.isRequired, + quantifiedThingsStatus: PropTypes.instanceOf(PromiseStatus).isRequired, - count: PropTypes.number.isRequired, - countStatus: PropTypes.instanceOf(PromiseStatus).isRequired - }; + count: PropTypes.number.isRequired, + countStatus: PropTypes.instanceOf(PromiseStatus).isRequired + }; - render() { - const {count, countStatus, quantifiedThings, quantifiedThingsStatus} = this.props; + render() { + const { count, countStatus, quantifiedThings, quantifiedThingsStatus } = this.props; - if (!countStatus.done) { - return - } - - if (!quantifiedThingsStatus.done) { - return - } + if (!countStatus.done) { + return + } - var loaded = getDistinctCount(t => t.url, quantifiedThings); - return - Loaded {loaded} records out of {count} available. Increase limit to load more. - + if (!quantifiedThingsStatus.done) { + return } + + var loaded = getDistinctCount(t => t.url, quantifiedThings); + return + Loaded {loaded} records out of {count} available. Increase limit to load more. + + } } const selector = createStructuredSelector({ - quantifiedThings: quantifiedThingsSelector, - quantifiedThingsStatus: quantifiedThingsStatusSelector, + quantifiedThings: quantifiedThingsSelector, + quantifiedThingsStatus: quantifiedThingsStatusSelector, - count: quantifiedThingsCountSelector, - countStatus: quantifiedThingsCountStatusSelector, + count: quantifiedThingsCountSelector, + countStatus: quantifiedThingsCountStatusSelector, }); export default connect(selector)(CountThingsContainer); diff --git a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/EmbedAppDialog.js b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/EmbedAppDialog.js index 6517c70a..20907c43 100644 --- a/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/EmbedAppDialog.js +++ b/src/app/assets_webpack/assistant/javascripts/modules/visualizers/googleMaps/containers/EmbedAppDialog.js @@ -1,50 +1,50 @@ -import React, {Component, PropTypes} from "react"; -import {connect} from "react-redux"; -import {createStructuredSelector} from "reselect"; -import Button from "../../../../components/Button"; -import Dialog from "../../../core/containers/Dialog"; -import prefix from "../prefix"; -import withDialogControls from "../../../core/containers/withDialogControls"; -import EmbedCodeGenerator from "../../../app/components/EmbedCodeGenerator"; -import {applicationUrl} from "../../../app/applicationRoutes"; -import {applicationSelector} from "../../../app/ducks/application"; -import {Application} from "../../../app/models"; -import locationOrigin from "../../../../misc/locationOrigin"; +import React, { Component, PropTypes } from 'react' +import { connect } from 'react-redux' +import { createStructuredSelector } from 'reselect' +import Button from '../../../../components/Button' +import Dialog from '../../../core/containers/Dialog' +import prefix from '../prefix' +import withDialogControls from '../../../core/containers/withDialogControls' +import EmbedCodeGenerator from '../../../app/components/EmbedCodeGenerator' +import { applicationUrl } from '../../../app/applicationRoutes' +import { applicationSelector } from '../../../app/ducks/application' +import { Application } from '../../../app/models' +import locationOrigin from '../../../../misc/locationOrigin' export const dialogName = prefix('EMBED_APP_DIALOG'); function generateUrl(application) { - return locationOrigin() + applicationUrl(application) + '/embed'; + return locationOrigin() + applicationUrl(application) + '/embed'; } class EmbedAppDialog extends Component { - static propTypes = { - application: PropTypes.instanceOf(Application).isRequired, - dialogClose: PropTypes.func.isRequired - }; - - constructor(props) { - super(props); - } - - render() { - const {application, dialogClose} = this.props; - - const actions = [ -
    - } - - var buttonsEnabled = selectedFirstLevelTypes.size > 0 || selectedFirstLevelPredicates.size > 0; - - return - t.outerType} - selectedKeys={selectedFirstLevelTypes} - onKeySelect={k => dispatch(setSelectFirstLevelType(k))} - /> - t.predicate} - selectedKeys={selectedFirstLevelPredicates} - onKeySelect={k => dispatch(setSelectFirstLevelPredicate(k))} - /> -
    } + + var buttonsEnabled = selectedFirstLevelTypes.size > 0 || selectedFirstLevelPredicates.size > 0; + + return + t.outerType} + selectedKeys={selectedFirstLevelTypes} + onKeySelect={k => dispatch(setSelectFirstLevelType(k))} + /> + t.predicate} + selectedKeys={selectedFirstLevelPredicates} + onKeySelect={k => dispatch(setSelectFirstLevelPredicate(k))} + /> +
    - } - - var buttonsEnabled = selectedSecondLevelThings.size > 0 || selectedSecondLevelPredicates.size > 0; - - return - t.outer} - selectedKeys={selectedSecondLevelThings} - onKeySelect={k => dispatch(setSelectThingSL(k))} - /> - t.predicate} - selectedKeys={selectedSecondLevelPredicates} - onKeySelect={k => dispatch(setSelectSecondLevelPredicate(k))} - /> -
    } + + var buttonsEnabled = selectedSecondLevelThings.size > 0 || selectedSecondLevelPredicates.size > 0; + + return + t.outer} + selectedKeys={selectedSecondLevelThings} + onKeySelect={k => dispatch(setSelectThingSL(k))} + /> + t.predicate} + selectedKeys={selectedSecondLevelPredicates} + onKeySelect={k => dispatch(setSelectSecondLevelPredicate(k))} + /> +