Skip to content

Commit

Permalink
copy author edges with their times but executing user in automation
Browse files Browse the repository at this point in the history
  • Loading branch information
cornerman committed Mar 10, 2019
1 parent e0b930a commit f7a9e28
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 15 deletions.
9 changes: 6 additions & 3 deletions graph/src/main/scala/GraphChanges.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ case class GraphChanges(
// we do not really need a connection for deleting (ConnectionId instead), but we want to revert it again.
delEdges: collection.Set[Edge] = Set.empty
) {
def withAuthor(userId: UserId, timestamp: EpochMilli = EpochMilli.now): GraphChanges =
def withAuthor(userId: UserId, timestamp: EpochMilli = EpochMilli.now): GraphChanges = {
val existingAuthors: Set[NodeId] = addEdges.collect { case edge: Edge.Author => edge.nodeId }(breakOut)
copy(
addEdges = addEdges ++
addNodes.map(node => Edge.Author(node.id, EdgeData.Author(timestamp), userId))
addEdges = addEdges ++ addNodes.flatMap { node =>
(if (existingAuthors(node.id)) Set.empty[Edge] else Set[Edge](Edge.Author(node.id, EdgeData.Author(timestamp), userId)))
}
)
}

def merge(other: GraphChanges): GraphChanges = {
GraphChanges.from(
Expand Down
10 changes: 5 additions & 5 deletions sdk/shared/src/main/scala/EventProcessor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import monix.reactive.{Observable, OverflowStrategy}
import monix.reactive.subjects.{PublishSubject, PublishToOneSubject}
import wust.api.ApiEvent._
import wust.api._
import wust.ids.NodeId
import wust.ids.{NodeId, UserId}
import wust.graph._

import scala.concurrent.Future
Expand Down Expand Up @@ -36,7 +36,7 @@ object EventProcessor {
//TODO factory and constructor shared responsibility
def apply(
eventStream: Observable[Seq[ApiEvent]],
enrichChanges: (GraphChanges, Graph) => GraphChanges,
enrichChanges: (GraphChanges, UserId, Graph) => GraphChanges,
sendChange: List[GraphChanges] => Future[Boolean],
initialAuth: Authentication
)(implicit scheduler: Scheduler): EventProcessor = {
Expand All @@ -62,7 +62,7 @@ object EventProcessor {
class EventProcessor private (
eventStream: Observable[Seq[ApiEvent.GraphContent]],
authEventStream: Observable[Seq[ApiEvent.AuthContent]],
enrichChanges: (GraphChanges, Graph) => GraphChanges,
enrichChanges: (GraphChanges, UserId, Graph) => GraphChanges,
sendChange: List[GraphChanges] => Future[Boolean],
val initialAuth: Authentication
)(implicit scheduler: Scheduler) {
Expand Down Expand Up @@ -92,8 +92,8 @@ class EventProcessor private (
val sharedRawGraph = rawGraph.share
val rawGraphWithInit = sharedRawGraph.startWith(Seq(Graph.empty))

val enrichedChanges = changes.withLatestFrom(rawGraphWithInit) { (changes, graph) =>
val newChanges = enrichChanges(changes, graph)
val enrichedChanges = changes.withLatestFrom2(currentUser, rawGraphWithInit) { (changes, user, graph) =>
val newChanges = enrichChanges(changes, user.id, graph)
scribe.info(s"Local Graphchanges: ${newChanges.toPrettyString(graph)}")
newChanges
}
Expand Down
2 changes: 1 addition & 1 deletion webApp/src/main/scala/state/GlobalStateFactory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ object GlobalStateFactory {

val eventProcessor = EventProcessor(
Client.observable.event,
(changes, graph) => GraphChangesAutomation.enrich(graph, urlConfig, EmojiReplacer.replaceChangesToColons(changes)).consistent,
(changes, userId, graph) => GraphChangesAutomation.enrich(userId, graph, urlConfig, EmojiReplacer.replaceChangesToColons(changes)).consistent,
Client.api.changeGraph,
Client.currentAuth
)
Expand Down
13 changes: 9 additions & 4 deletions webApp/src/main/scala/state/GraphChangesAutomation.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ object GraphChangesAutomation {

// copy the whole subgraph of the templateNode and append it to newNode.
// templateNode is a placeholder and we want make changes such newNode looks like a copy of templateNode.
def copySubGraphOfNode(graph: Graph, newNode: Node, templateNode: Node, newId: NodeId => NodeId = _ => NodeId.fresh, copyTime: EpochMilli = EpochMilli.now): GraphChanges = {
def copySubGraphOfNode(userId: UserId, graph: Graph, newNode: Node, templateNode: Node, newId: NodeId => NodeId = _ => NodeId.fresh, copyTime: EpochMilli = EpochMilli.now): GraphChanges = {
scribe.info(s"Copying sub graph of node $newNode with template $templateNode")

val templateNodeIdx = graph.idToIdxOrThrow(templateNode.id)
Expand Down Expand Up @@ -100,10 +100,15 @@ object GraphChangesAutomation {
// Go through all edges and create new edges pointing to the replacedNodes, so
// that we copy the edge structure that the template node had.
graph.edges.foreach {
case _: Edge.Author => () // do not copy authors, we want the new authors of the one who triggered this change.
case _: Edge.DerivedFromTemplate => () // do not copy derived info, we get new derive infos for new nodes
case edge: Edge.Automated if edge.templateNodeId == templateNode.id => () // do not copy automation edges of template, otherwise the newNode would become a template.
case edge: Edge.Child if edge.data.deletedAt.exists(EpochMilli.now.isAfter) => () // do not copy deleted parent edges
case edge: Edge.Author => // need to keep date of authorship, but change author. We will have an author edge for every change that was done to this node
// replace node ids to point to our copied nodes
replacedNodes.get(edge.nodeId) match {
case Some(newSource) => addEdges += edge.copy(nodeId = newSource.id, userId = userId)
case None => ()
}
case edge =>
// replace node ids to point to our copied nodes
(replacedNodes.get(edge.sourceId), replacedNodes.get(edge.targetId)) match {
Expand All @@ -121,7 +126,7 @@ object GraphChangesAutomation {
// We get the current graph + the new graph change. For each new parent edge in the graph change,
// we check if the parent has a template node. If the parent has a template node, we want to
// append the subgraph (which is spanned from the template node) to the newly inserted child of the parent.
def enrich(graph: Graph, viewConfig: Var[UrlConfig], changes: GraphChanges): GraphChanges = {
def enrich(userId: UserId, graph: Graph, viewConfig: Var[UrlConfig], changes: GraphChanges): GraphChanges = {
scribe.info("Check for automation enrichment of graphchanges: " + changes.toPrettyString(graph))

val addNodes = mutable.HashSet.newBuilder[Node]
Expand Down Expand Up @@ -153,7 +158,7 @@ object GraphChangesAutomation {
val templateNode = graph.nodes(templateNodeIdx)
if (templateNode.role == childNode.role) {
scribe.info(s"Found fitting template '$templateNode' for '$childNode'")
val changes = copySubGraphOfNode(graph, newNode = childNode, templateNode = templateNode)
val changes = copySubGraphOfNode(userId, graph, newNode = childNode, templateNode = templateNode)
// if the automated changes re-add the same child edge were are currently replacing, then we want to take the ordering from the new child edge.
// so an automated node can be drag/dropped to the correct position.
addEdges ++= changes.addEdges.map {
Expand Down
2 changes: 1 addition & 1 deletion webApp/src/main/scala/views/TableView.scala
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ object TableView {
// now we add these changes with the template node to a temporary graph, because ChangesAutomation needs the template node in the graph
val tmpGraph = state.rawGraph.now applyChanges changes
// run automation of this template for each row
propertyGroup.infos.foldLeft[GraphChanges](changes)((changes, info) => changes merge GraphChangesAutomation.copySubGraphOfNode(tmpGraph, info.node, templateNode = templateNode))
propertyGroup.infos.foldLeft[GraphChanges](changes)((changes, info) => changes merge GraphChangesAutomation.copySubGraphOfNode(state.user.now.id, tmpGraph, info.node, templateNode = templateNode))
} else propertyGroup.infos.foldLeft[GraphChanges](GraphChanges.empty)((changes, info) => changes merge changesf(info.node.id))
}, keepPropertyAsDefault),
dropdownModifier = cls := "top right",
Expand Down
2 changes: 1 addition & 1 deletion webApp/src/test/scala/GraphChangesAutomationSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class GraphChangesAutomationSpec extends FreeSpec with MustMatchers {
val copyTime = EpochMilli.now

def copySubGraphOfNode(graph: Graph, newNode: Node, templateNode: Node) = GraphChangesAutomation.copySubGraphOfNode(
graph, newNode, templateNode, copyNodeId(_), copyTime
freshNodeId(), graph, newNode, templateNode, copyNodeId(_), copyTime
)

"empty template node" in {
Expand Down

0 comments on commit f7a9e28

Please sign in to comment.