Browse Source

Merge master changes

Arkadiusz Ryś 1 year ago
parent
commit
21180f3ad5

+ 18 - 0
.editorconfig

@@ -0,0 +1,18 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.{css,html,yml,yaml,js,xml}]
+indent_size = 2
+
+[{*.log,LICENSE}]
+insert_final_newline = false
+
+[*.rst]
+indent_size = 3

+ 13 - 58
flake.lock

@@ -5,11 +5,11 @@
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1681202837,
-        "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
+        "lastModified": 1689068808,
+        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
+        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
         "type": "github"
       },
       "original": {
@@ -20,8 +20,12 @@
     },
     "mvn2nix": {
       "inputs": {
-        "nixpkgs": "nixpkgs",
-        "utils": "utils"
+        "nixpkgs": [
+          "nixpkgs"
+        ],
+        "utils": [
+          "flake-utils"
+        ]
       },
       "locked": {
         "lastModified": 1629170129,
@@ -39,27 +43,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1684215771,
-        "narHash": "sha256-fsum28z+g18yreNa1Y7MPo9dtps5h1VkHfZbYQ+YPbk=",
+        "lastModified": 1692084312,
+        "narHash": "sha256-Za++qKVK6ovjNL9poQZtLKRM/re663pxzbJ+9M4Pgwg=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "963006aab35e3e8ebbf6052b6bf4ea712fdd3c28",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixos-21.05",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
-    "nixpkgs_2": {
-      "locked": {
-        "lastModified": 1684215771,
-        "narHash": "sha256-fsum28z+g18yreNa1Y7MPo9dtps5h1VkHfZbYQ+YPbk=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "963006aab35e3e8ebbf6052b6bf4ea712fdd3c28",
+        "rev": "8353344d3236d3fda429bb471c1ee008857d3b7c",
         "type": "github"
       },
       "original": {
@@ -73,7 +61,7 @@
       "inputs": {
         "flake-utils": "flake-utils",
         "mvn2nix": "mvn2nix",
-        "nixpkgs": "nixpkgs_2"
+        "nixpkgs": "nixpkgs"
       }
     },
     "systems": {
@@ -90,39 +78,6 @@
         "repo": "default",
         "type": "github"
       }
-    },
-    "systems_2": {
-      "locked": {
-        "lastModified": 1681028828,
-        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-        "owner": "nix-systems",
-        "repo": "default",
-        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "nix-systems",
-        "repo": "default",
-        "type": "github"
-      }
-    },
-    "utils": {
-      "inputs": {
-        "systems": "systems_2"
-      },
-      "locked": {
-        "lastModified": 1681202837,
-        "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
-        "type": "github"
-      },
-      "original": {
-        "owner": "numtide",
-        "repo": "flake-utils",
-        "type": "github"
-      }
     }
   },
   "root": "root",

+ 6 - 2
flake.nix

@@ -2,8 +2,12 @@
   inputs = rec {
     nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
     flake-utils.url = "github:numtide/flake-utils";
-    mvn2nix.url = "github:fzakaria/mvn2nix";
-    mvn2nix.inputs = { inherit nixpkgs; utils = flake-utils; };
+
+    mvn2nix = {
+      url = "github:fzakaria/mvn2nix";
+      inputs.nixpkgs.follows = "nixpkgs";
+      inputs.utils.follows = "flake-utils";
+    };
   };
 
   outputs = { nixpkgs, mvn2nix, flake-utils, ... }:

+ 4 - 10
src/main/java/ua/be/wee/WeeApplication.java

@@ -5,14 +5,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 
 @SpringBootApplication
 public class WeeApplication {
-
-	
-	public static void main(String[] args) {
-		System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
-
-		
-		SpringApplication.run(WeeApplication.class, args);
-		
-	}
-
+    public static void main(String[] args) {
+        System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
+        SpringApplication.run(WeeApplication.class, args);
+    }
 }

+ 36 - 39
src/main/java/ua/be/wee/controller/EnactmentControllerMVC.java

@@ -46,13 +46,13 @@ import ua.be.wee.model.util.Pair;
 public class EnactmentControllerMVC {
 
 	@Autowired private EnactmentController controller;
-	
+
 	@Autowired
 	private PTController ptController;
-  
+
 	@Autowired
 	private Environment env;
-	
+
     @Value("${base_url}")
     private String baseUrl;
 
@@ -86,7 +86,7 @@ public class EnactmentControllerMVC {
 			return "index";
 		}
     }
-    
+
     @RequestMapping("/gettraces")
     public String getTraces(Model model, @RequestParam String iri, HttpServletRequest request) throws Exception {
     	List<StartTraceEvent> activeTraces = ptController.getActiveTraces(iri);
@@ -100,8 +100,8 @@ public class EnactmentControllerMVC {
 		model.addAttribute("current", iri);
         return "pms";
     }
-    
-    
+
+
     @RequestMapping(value="/enactpm", method=RequestMethod.POST, params="action=new")
     public String getPMtoEnact(Model model, @RequestParam String pmiri, HttpServletRequest request) throws Exception {
     	if ((pmiri.equals("select PM"))) {
@@ -111,7 +111,7 @@ public class EnactmentControllerMVC {
     		model.addAttribute("current", "1");
 			return "pms";
 		} else {
-			PM pm = controller.getPM(pmiri);			
+			PM pm = controller.getPM(pmiri);
 			PT trace = controller.createTrace(pm);
 			List<Pair<String,String>> iris = controller.findNextNodes(pm.getInitial().getIri(), trace.getIri());
 			List<PMTrigger> acts = findElements(pm, iris);
@@ -126,17 +126,17 @@ public class EnactmentControllerMVC {
 	        return "enact";
 		}
     }
-    
+
     @RequestMapping(value="/enactpm", method=RequestMethod.POST, params="action=continue")
     public String continueEnact(Model model, @RequestParam String pmiri, @RequestParam String contTrace, HttpServletRequest request) throws Exception {
-    	if ((pmiri.equals("select PM")) || contTrace != null && contTrace.equals("Select Trace")) {
-			model.addAttribute("error", true);
+        if ((pmiri.equals("select PM")) || contTrace != null && contTrace.equals("Select Trace")) {
+            model.addAttribute("error", true);
 			model.addAttribute("pms", controller.getAllPMs());
 			model.addAttribute("traces",null);
     		model.addAttribute("current", "1");
 			return "pms";
 		} else {
-			PM pm = controller.getPM(pmiri);			
+            PM pm = controller.getPM(pmiri);
 			List<Event> events = ptController.getEvents(contTrace);
 			PT trace = new PT();
 			trace.setEvents(events);
@@ -147,7 +147,6 @@ public class EnactmentControllerMVC {
 				List<Pair<String,String>> iris = controller.findNextNodes(pm.getInitial().getIri(), trace.getIri());
 				List<PMTrigger> acts = findElements(pm, iris);
 				request.getSession().setAttribute("acts",acts);
-				
 			} else {
 				endActs = findEndActs(events);
 				List<PMTrigger> acts = findStartActs(trace);
@@ -156,10 +155,8 @@ public class EnactmentControllerMVC {
 					List<Pair<String,String>> iris = controller.findNextNodes(last.getRelatesTo().getIri(), trace.getIri());
 					acts.addAll(findElements(pm, iris));
 				}
-				
 				request.getSession().setAttribute("acts",acts);
-				
-			}			
+			}
 			model.addAttribute("error", false);
 			request.getSession().setAttribute("pm", pm);
 			request.getSession().setAttribute("trace", trace);
@@ -170,7 +167,7 @@ public class EnactmentControllerMVC {
 	        return "enact";
 		}
     }
-    
+
 
 	private List<PMTrigger> findStartActs(PT trace) throws Exception {
 		PM pmEnacted = trace.getPmEnacted();
@@ -188,10 +185,10 @@ public class EnactmentControllerMVC {
 						}
 					}
 					List<String> consider = checkTrace(trace,actIris);
-						
+
 					for (Iterator<Pair<String,String>> iterator = findNextNodes.iterator(); iterator.hasNext();) {
 						Pair<String,String> pair = iterator.next();
-						
+
 						if (pair.getSnd() == null) {
 							findNextNodes.remove(pair);
 						} else {
@@ -207,9 +204,9 @@ public class EnactmentControllerMVC {
 							}
 						}
 					}
-					
+
 					result.addAll(findElements(trace.getPmEnacted(), findNextNodes));
-					
+
 				}
 			}
 		}
@@ -232,7 +229,7 @@ public class EnactmentControllerMVC {
 			}
 			pairs.add(new Pair<String, Integer>(iri, count));
 		}
-		
+
 		List<String> result = new ArrayList<String>();
 		for (Pair<String, Integer> pair : pairs) {
 			if (pair.getSnd() < max) {
@@ -240,7 +237,7 @@ public class EnactmentControllerMVC {
 			}
 		}
 		return result;
-		
+
 	}
 
 	private List<Node> findEndActs(List<Event> events) {
@@ -297,8 +294,8 @@ public class EnactmentControllerMVC {
 			return "error";
 		}
     }
-    
-    
+
+
 
     @PostMapping("/endAct")
     public String endActivityWithArtifacts(Model model, @RequestParam String port, @RequestParam String activity, HttpServletRequest request) throws Exception {
@@ -315,7 +312,7 @@ public class EnactmentControllerMVC {
 				break;
 			}
 		}
-    	
+
     	List<Artifact> arts = act.getOutputs();
     	List<TraceArtifact> traceArts = new ArrayList<TraceArtifact>();
     	for (Artifact artifact : arts) {
@@ -328,16 +325,16 @@ public class EnactmentControllerMVC {
 					traceArts.add(tArt);
 					controller.uploadArtifact(part.getInputStream(),part.getSubmittedFileName());
 				}
-			}  
+			}
 		}
-    	
+
     	controller.addEndEvent(pt,traceArts,p);
     	for (Node activ : endacts) {
 			if (activ.getIri().equals(act.getIri())) {
 				endacts.remove(activ);
 				break;
 			}
-		}	
+		}
 
     	List<Pair<String,String>> iris = controller.findNextNodes(p.getIri(), pt.getIri());
         acts.addAll(findElements(pm, iris));
@@ -348,7 +345,7 @@ public class EnactmentControllerMVC {
 		model.addAttribute("current", "1");
     	return "enact";
     }
-    
+
     @RequestMapping("/endselect")
     public String selectActivityToEnd(Model model, @RequestParam String iri, HttpServletRequest request) throws Exception {
     	PM pm = (PM)request.getSession().getAttribute("pm");
@@ -357,17 +354,17 @@ public class EnactmentControllerMVC {
         		Activity act = (Activity)pm.getNode(iri);
             	model.addAttribute("act", pm.getNode(iri));
             	model.addAttribute("arts", act.getOutputs());
-			} else { 
+			} else {
 				model.addAttribute("endBool", true);
 			}
-        	
+
 		} else {
 			model.addAttribute("arts", null);
 		}
 
     	return "enactEnd";
     }
-    
+
     @RequestMapping("/inarts")
     public String selectActivity(Model model, @RequestParam String iri, HttpServletRequest request) throws Exception {
     	PT pt = (PT)request.getSession().getAttribute("trace");
@@ -398,21 +395,21 @@ public class EnactmentControllerMVC {
             	//model.addAttribute("arts", arts);
             	request.getSession().setAttribute("arts", arts);
             	model.addAttribute("storageURL", env.getProperty("storageURL"));
-			} else { 
+			} else {
 				model.addAttribute("endBool", true);
 			}
-        	
+
 		} else {
 			request.getSession().setAttribute("arts", null);
 		}
     	model.addAttribute("current", iri);
     	return "enact";
     }
-    
+
 
     // Helper methods
-    
-    
+
+
     private List<PMTrigger> findElements(PM pm, List<Pair<String, String>> iris) {
 		List<PMTrigger> acts = new ArrayList<PMTrigger>();
 		for (Pair<String,String> pair : iris) {
@@ -435,7 +432,7 @@ public class EnactmentControllerMVC {
 		}
 		return acts;
 	}
-    
+
     private PMTrigger findPMTrigger(List<PMTrigger> acts, String iri) {
 		for (PMTrigger pmTrigger : acts) {
 			if (pmTrigger.getIri().equals(iri)) {
@@ -455,5 +452,5 @@ public class EnactmentControllerMVC {
 
 	}
 
-	
+
 }

+ 2 - 4
src/main/resources/application.properties

@@ -3,9 +3,7 @@ base_url=http://localhost:8081/
 spring.application.name=wee
 endpoint=http://localhost:3030/SystemDesignOntology2Layers
 storageURL=http://localhost:5000
-# Max file size.
 spring.servlet.multipart.max-file-size=500MB
-# Max request size.
 spring.servlet.multipart.max-request-size=500MB
-
-server.tomcat.max-http-post-size=629145600000
+server.tomcat.max-http-post-size=629145600000
+#server.contextPath=/wee

+ 6 - 6
src/main/resources/static/favicon.svg

@@ -6,19 +6,19 @@
     </defs>
     <g fill="none" fill-rule="evenodd" transform="translate(2 1)">
         <g transform="translate(3 3)">
-            <mask id="share-b" fill="#ffffff">
+            <mask id="share-b" fill="#00c4a7">
                 <use xlink:href="#share-a"/>
             </mask>
-            <use fill="#fff" xlink:href="#share-a"/>
-            <g fill="#fff" mask="url(#share-b)">
+            <use fill="#00c4a7" xlink:href="#share-a"/>
+            <g fill="#00c4a7" mask="url(#share-b)">
                 <rect width="24" height="24" transform="translate(-5 -4)"/>
             </g>
         </g>
-        <mask id="share-d" fill="#ffffff">
+        <mask id="share-d" fill="#00c4a7">
             <use xlink:href="#share-c"/>
         </mask>
-        <use fill="#000000" fill-rule="nonzero" xlink:href="#share-c"/>
-        <g fill="#fff" mask="url(#share-d)">
+        <use fill="#00c4a7" fill-rule="nonzero" xlink:href="#share-c"/>
+        <g fill="#000" mask="url(#share-d)">
             <rect width="24" height="24" transform="translate(-2 -1)"/>
         </g>
     </g>

+ 100 - 50
src/main/resources/static/main.js

@@ -1,27 +1,27 @@
-function showDiv(select){
-    let hiddenDiv = document.getElementById('hidden_div');
-    if (select.value != 1) {
-        hiddenDiv.classList.remove('is-hidden');
-    } else{
-        hiddenDiv.classList.add('is-hidden');
-    }
+function showDiv(select) {
+  let hiddenDiv = document.getElementById('hidden_div');
+  if (select.value != 1) {
+    hiddenDiv.classList.remove('is-hidden');
+  } else {
+    hiddenDiv.classList.add('is-hidden');
+  }
 }
 
 function play() {
-           var audio = document.getElementById("audio");
-    		var img = document.getElementById("img");
-    
-    		function play() {
-    			  audio.play();
-    		}
-    
-    		function stop() {
-      			audio.pause();
-    		}
-    
-    		img.addEventListener('click', play);
-    		img.addEventListener('mouseover', play);
-    		img.addEventListener('mouseout', stop);
+  const audio = document.getElementById("audio");
+  const img = document.getElementById("img");
+
+  function play() {
+    audio.play();
+  }
+
+  function stop() {
+    audio.pause();
+  }
+
+  img.addEventListener('click', play);
+  img.addEventListener('mouseover', play);
+  img.addEventListener('mouseout', stop);
 }
 
 // document.addEventListener('DOMContentLoaded', () => {
@@ -33,49 +33,99 @@ function play() {
 // });
 
 document.addEventListener('DOMContentLoaded', () => {
-    // Get all "navbar-burger" elements
-    const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
+  // Get all "navbar-burger" elements
+  const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
 
-    // Add a click event on each of them
-    $navbarBurgers.forEach( el => {
-        el.addEventListener('click', () => {
+  // Add a click event on each of them
+  $navbarBurgers.forEach(el => {
+    el.addEventListener('click', () => {
 
-            // Get the target from the "data-target" attribute
-            const target = el.dataset.target;
-            const $target = document.getElementById(target);
+      // Get the target from the "data-target" attribute
+      const target = el.dataset.target;
+      const $target = document.getElementById(target);
 
-            // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
-            el.classList.toggle('is-active');
-            $target.classList.toggle('is-active');
-        });
+      // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
+      el.classList.toggle('is-active');
+      $target.classList.toggle('is-active');
     });
+  });
 });
 
 document.addEventListener('DOMContentLoaded', () => {
-    (document.querySelectorAll('.notification .delete') || []).forEach(($delete) => {
-        const $notification = $delete.parentNode;
-        $delete.addEventListener('click', () => {
-            $notification.parentNode.removeChild($notification);
-        });
+  (document.querySelectorAll('.notification .delete') || []).forEach(($delete) => {
+    const $notification = $delete.parentNode;
+    $delete.addEventListener('click', () => {
+      $notification.parentNode.removeChild($notification);
     });
+  });
 });
 
 document.addEventListener('DOMContentLoaded', () => {
-    (document.querySelectorAll('#endpointURL') || []).forEach(($urlInput) => {
-        $urlInput.addEventListener('input', (e) => {
-            window.localStorage.setItem("uri", e.target.value);
-            console.log('Storing uri input ' + e.target.value);
-        });
+  (document.querySelectorAll('#endpointURL') || []).forEach(($urlInput) => {
+    $urlInput.addEventListener('input', (e) => {
+      window.localStorage.setItem("uri", e.target.value);
+      console.log('Storing uri input ' + e.target.value);
     });
+  });
 });
 
 document.addEventListener('DOMContentLoaded', () => {
-    let data = window.localStorage.getItem("uri");
-    if (data) {
-        (document.querySelectorAll('#endpointURL') || []).forEach(($urlInput) => {
-            $urlInput.setAttribute('value', data);
-            console.log('Setting uri input to ' + data);
-        });
-    }
+  let data = window.localStorage.getItem("uri");
+  if (data) {
+    (document.querySelectorAll('#endpointURL') || []).forEach(($urlInput) => {
+      $urlInput.setAttribute('value', data);
+      console.log('Setting uri input to ' + data);
+    });
+  }
 });
 
+function sendFormData(uri, pm_iri, pt_iri) {
+  console.log(pm_iri);
+  console.log(pt_iri);
+  // Get value of dropDownList in pm.html
+  let formData = new FormData();
+  formData.append('action', 'continue');
+  formData.append('pmiri', pm_iri);
+  formData.append('contTrace', pt_iri);
+  fetch(uri, {method: 'POST', body: formData, redirect: "follow"}).then(r => console.log(r));
+}
+
+function sendHiddenForm(uri, pm_iri, pt_iri) {
+  const hidden_form = document.createElement('form');
+  hidden_form.method = 'post';
+  hidden_form.action = uri;
+
+  const hidden_pm_input = document.createElement('input');
+  hidden_pm_input.type = 'hidden';
+  hidden_pm_input.name = 'pmiri';
+  hidden_pm_input.value = pm_iri;
+
+  const hidden_pt_input = document.createElement('input');
+  hidden_pt_input.type = 'hidden';
+  hidden_pt_input.name = 'contTrace';
+  hidden_pt_input.value = pt_iri;
+
+  const action_input = document.createElement('input');
+  action_input.type = 'hidden';
+  action_input.name = 'action';
+  action_input.value = 'continue';
+
+  hidden_form.appendChild(hidden_pm_input);
+  hidden_form.appendChild(hidden_pt_input);
+  hidden_form.appendChild(action_input);
+
+  document.body.appendChild(hidden_form);
+  hidden_form.submit();
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+  (document.querySelectorAll('.trace-continuation-row') || []).forEach(($row) => {
+    console.log($row);
+    const pm_dropdown_value = document.getElementById('dropDownList').value;
+    const button = $row.getElementsByTagName('button')[0];
+    button.addEventListener('click', (e) => {
+      // sendFormData($row.dataset.action, pm_dropdown_value, $row.dataset.iri)
+      sendHiddenForm($row.dataset.action, pm_dropdown_value, $row.dataset.iri)
+    });
+  });
+});

+ 10 - 11
src/main/resources/templates/base.html

@@ -1,6 +1,5 @@
 <!DOCTYPE html>
 <html lang="en" xmlns:th="http://www.thymeleaf.org" th:fragment="layout(title, main)">
-<!--<html lang="en" xmlns:th="http://www.thymeleaf.org" th:fragment="layout">-->
 <head>
   <meta charset="UTF-8"/>
   <title th:replace="${title}"></title>
@@ -9,14 +8,14 @@
   <link href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css" rel="stylesheet">
   <link rel="stylesheet" type="text/css" href="../static/reset.css" th:href="@{/reset.css}"/>
   <link rel="stylesheet" type="text/css" href="../static/style.css" th:href="@{/style.css}"/>
-  <link rel="icon" href="../static/favicon.svg" th:href="@{/favicon.svg}"/>
+  <link rel="icon" href="../static/favicon.svg" th:href="@{/icon.svg}"/>
 </head>
 <body>
 <header>
   <nav class="navbar" role="navigation" aria-label="main navigation">
     <div class="navbar-brand">
       <a class="navbar-item" href="/">
-<!--        <img src="https://bulma.io/images/bulma-logo.png" width="112" height="28">-->
+        <img th:src="@{/icon.svg}" width="28" height="28">
         <h1 class="is-size-3">Workflow Enactment Engine</h1>
       </a>
       <a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navigation-menu">
@@ -28,11 +27,12 @@
 
     <div id="navigation-menu" class="navbar-menu">
       <div class="navbar-start">
-        <a class="navbar-item" href="/" >Home</a>
+        <!--        <a class="navbar-item" href="/" >Home</a>-->
         <div class="navbar-item has-dropdown is-hoverable">
           <a class="navbar-link">Enactment</a>
           <div class="navbar-dropdown">
-            <a href="https://msdl.uantwerpen.be/git/lucasalbertins/wee/src/master/README.md" class="navbar-item">About</a>
+            <a href="https://msdl.uantwerpen.be/git/lucasalbertins/wee/src/master/README.md"
+               class="navbar-item">About</a>
             <hr class="navbar-divider">
             <a href="https://msdl.uantwerpen.be/git/lucasalbertins/wee/issues" class="navbar-item">Report an issue</a>
           </div>
@@ -42,25 +42,24 @@
       <div class="navbar-end">
         <div class="navbar-item">
           <div class="buttons">
-            <a href="https://msdl.uantwerpen.be/git/lucasalbertins/wee" class="button is-primary">
+            <a href="https://msdl.uantwerpen.be/git/lucasalbertins/wee/wiki" class="button is-primary">
               <strong>?</strong>
             </a>
           </div>
         </div>
       </div>
     </div>
-    <!--  <button id="toggle">Theme</button>-->
   </nav>
 </header>
 <main th:replace="${main}"></main>
 <footer>
   <section>
-<!--  https://stackoverflow.com/questions/30574093/how-to-implement-breadcrumbs-in-spring-mvc-thymeleaf  -->
     <nav class="breadcrumb pl-5 pr-5" aria-label="breadcrumbs">
       <ul>
-        <li><a href="#">WEE</a></li>
-        <li><a href="#">PM</a></li>
-        <li class="is-active"><a href="#" aria-current="page">Index</a></li>
+        <li th:each="entry : ${breadcrumbs}" th:classappend="${entry.isCurrent} ? 'is-active' : ''">
+          <a th:href="${entry.href}" th:unless="${entry.isCurrent}" th:text="${entry.label}"></a>
+          <span th:if="${entry.isCurrent}" th:text="${entry.label}"></span>
+        </li>
       </ul>
     </nav>
   </section>

+ 89 - 76
src/main/resources/templates/enact.html

@@ -1,94 +1,107 @@
 <!DOCTYPE html>
 <html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="base::layout(~{::title}, ~{::main})">
 <head>
-  <title>Wee! Workflow Enactment Engine</title>
+  <title>[[${session.trace.name}]] Enactment</title>
 </head>
 <body>
 <main>
   <section class="pt-6 pb-6 pl-5 pr-5">
-    <h2 class="is-size-3 is-capitalized">Workflow Enactment Engine</h2>
-    <div class="level-left">
-      <p th:inline="text">Enacting the Process Model:</p>
-      <div class="tags has-addons">
-        <span class="tag">PM</span>
-        <span class="tag is-primary">[[${session.pm.name}]]</span>
-      </div>
-    </div>
-
-    <div class="enactment pt-3">
-      <form class="form" th:action="@{/startAct}" method="post">
-        <th:block th:if="${session.acts != null && session.acts.size > 0}">
-          <!--  Options shown only when starting an activity  -->
-          <label for="activities">Select activity to start:</label>
-          <div class="field has-addons">
-            <div class="control is-expanded">
-              <div class="select is-fullwidth">
-                <select id="activities" name="iri" th:onchange="'window.location.href = \'' + @{/inarts} + '?iri=\' + encodeURIComponent(this.value) ' ">
-                  <option th:value="1">Select Activity</option>
-                  <option th:each="act: ${session.acts}" th:selected="${act.iri == current}" th:value="${act.iri}" th:text="${act.name}"></option>
-                </select>
+    <div class="columns">
+      <div class="column is-two-thirds">
+        <div class="tags are-large has-addons">
+          <span class="tag">PM</span>
+          <span class="tag is-primary">[[${session.pm.name}]]</span>
+        </div>
+        <div class="enactment pt-3">
+          <form class="form" th:action="@{/startAct}" method="post">
+            <th:block th:if="${session.acts != null && session.acts.size > 0}">
+              <!--  Options shown only when starting an activity  -->
+              <p>The selected Process Model supports the following activities. Choose the activity you want to start.</p>
+              <div class="field has-addons">
+                <div class="control is-expanded">
+                  <div class="select is-fullwidth">
+                    <select id="activities" name="iri"
+                            th:onchange="'window.location.href = \'' + @{/inarts} + '?iri=\' + encodeURIComponent(this.value) ' ">
+                      <option th:value="1">Select Activity</option>
+                      <option th:each="act: ${session.acts}" th:selected="${act.iri == current}" th:value="${act.iri}"
+                              th:text="${act.name}"></option>
+                    </select>
+                  </div>
+                </div>
+                <div class="control" th:unless="${session.arts != null}"><button id="startActivity" type="submit" class="button is-primary" disabled>Start Activity</button></div>
+                <div class="control" th:if="${session.arts != null}"><button id="startActivity" type="submit" class="button is-primary">Start Activity</button></div>
               </div>
-            </div>
-            <div class="control">
-              <button th:unless="${session.arts != null}" id="startActivity" type="submit" class="button is-primary" disabled>Start Activity</button>
-              <button th:if="${session.arts != null}" id="startActivity" type="submit" class="button is-primary">Start Activity</button>
-            </div>
-          </div>
-        </th:block>
-        <th:block th:if="${session.endacts != null && session.endacts.size > 0}">
-          <!--  Options shown only when ending an activity  -->
-          <label for="activitiesend">Select activity to end:</label>
-          <div class="field has-addons">
-            <div class="control is-expanded">
-              <div class="select is-fullwidth">
-                <select id="activitiesend" name="activityend" th:onchange="'window.location.href = \'' + @{/endselect} + '?iri=\' + encodeURIComponent(this.value) ' ">
-                  <option th:value="1">Select Activity</option>
-                  <option th:each="actend: ${session.endacts}" th:selected="${actend.iri == currentend}" th:value="${actend.iri}" th:text="${actend.name}"></option>
-                </select>
+            </th:block>
+            <th:block th:if="${session.endacts != null && session.endacts.size > 0}">
+              <!--  Options shown only when ending an activity  -->
+              <p>The selected Process Model supports the following activities. Choose the activity you want to end.</p>
+              <div class="field has-addons">
+                <div class="control is-expanded">
+                  <div class="select is-fullwidth">
+                    <select id="activitiesend" name="activityend"
+                            th:onchange="'window.location.href = \'' + @{/endselect} + '?iri=\' + encodeURIComponent(this.value) ' ">
+                      <option th:value="1">Select Activity</option>
+                      <option th:each="actend: ${session.endacts}" th:selected="${actend.iri == currentend}"
+                              th:value="${actend.iri}" th:text="${actend.name}"></option>
+                    </select>
+                  </div>
+                </div>
               </div>
+            </th:block>
+            <div class="control">
+              <button type="submit" class="button is-primary" id="endEnactment" th:if="${endBool}">End Enactment</button>
             </div>
+          </form>
+
+          <div class="artifacts pt-6" th:if="${session.arts != null && session.arts.size > 0}">
+            <p class="is-size-4 is-capitalized">Artifacts</p>
+            <th:block th:each="art : ${session.arts}">
+              <article class="media">
+                <figure class="media-left">
+                  <p class="image is-64x64">
+                    <img src="https://bulma.io/images/placeholders/128x128.png" alt="Download arrow">
+                  </p>
+                </figure>
+                <div class="media-content">
+                  <div class="content">
+                    <p>
+                      <strong th:text="${art.relatesTo.name}"></strong> <small th:text="${art.relatesTo.type}"></small>
+                      <br>
+                      <a
+                        th:if="${art.fileExtension == 'xopp' || art.fileExtension == 'csv' || art.fileExtension == 'drawio'}"
+                        th:href="@{|${storageURL}/files/${art.fileExtension}/${art.location}|}">Download</a>
+                      <a
+                        th:if="${art.fileExtension != null && art.fileExtension != 'xopp' && art.fileExtension != 'csv' && art.fileExtension != 'drawio'}"
+                        th:href="@{|${storageURL}/files/file/${art.location}|}">Download</a>
+                    </p>
+                  </div>
+                </div>
+              </article>
+            </th:block>
           </div>
-        </th:block>
-        <div class="control">
-          <button type="submit" class="button is-primary" id="endEnactment" th:if="${endBool}">End Enactment</button>
         </div>
-      </form>
-
-      <div class="details">
-        <p th:inline="text"><strong>Trace: </strong><span class="accent">[[${session.trace.name}]]</span></p>
-        <p th:inline="text"><strong>Started at: </strong><span class="accent">[[${session.trace.events[0].timestampF}]]</span></p>
-        <th:block th:each="ev : ${session.trace.events}">
-          <p th:if="${ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}"><strong>Begin: </strong><span class="accent" th:text="${ev.relatesTo.activity.name}"></span></p>
-          <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent'}"><strong>End: </strong><span class="accent" th:text="${ev.relatesTo.activity.name}"></span></p>
-          <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent' || ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}"><strong>Port: </strong><span class="accent">[[${ev.relatesTo.name}]]</span></p>
-        </th:block>
       </div>
-
-      <div class="artifacts pt-6" th:if="${session.arts != null && session.arts.size > 0}">
-        <p class="is-size-4 is-capitalized">Artifacts</p>
-        <th:block th:each="art : ${session.arts}">
-        <article class="media">
-          <figure class="media-left">
-            <p class="image is-64x64">
-              <img src="https://bulma.io/images/placeholders/128x128.png" alt="Download arrow">
-            </p>
-          </figure>
-          <div class="media-content">
-            <div class="content">
-              <p>
-                <strong th:text="${art.relatesTo.name}"></strong> <small th:text="${art.relatesTo.type}"></small>
-                <br>                
-                <a th:if="${art.fileExtension == 'xopp' || art.fileExtension == 'csv' || art.fileExtension == 'drawio'}" th:href="@{|${storageURL}/files/${art.fileExtension}/${art.location}|}">Download</a>
-                <a th:if="${art.fileExtension != null && art.fileExtension != 'xopp' && art.fileExtension != 'csv' && art.fileExtension != 'drawio'}" th:href="@{|${storageURL}/files/file/${art.location}|}">Download</a>                
-              </p>
-            </div>
-          </div>
-        </article>
-        </th:block>
+      <div class="column">
+        <div class="tags are-large has-addons">
+          <span class="tag">PT</span>
+          <span class="tag is-primary">[[${session.trace.name}]]</span>
+        </div>
+        <div class="details">
+          <p th:inline="text"><strong>Started at: </strong><span
+            class="accent">[[${session.trace.events[0].timestampF}]]</span></p>
+          <th:block th:each="ev : ${session.trace.events}">
+            <p th:if="${ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}"><strong>Begin: </strong><span
+              class="accent" th:text="${ev.relatesTo.activity.name}"></span></p>
+            <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent'}"><strong>End: </strong><span
+              class="accent" th:text="${ev.relatesTo.activity.name}"></span></p>
+            <p
+              th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent' || ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}">
+              <strong>Port: </strong><span class="accent">[[${ev.relatesTo.name}]]</span></p>
+          </th:block>
+        </div>
       </div>
     </div>
-
   </section>
 </main>
 </body>
-</html>
+</html>

+ 61 - 52
src/main/resources/templates/enactEnd.html

@@ -1,71 +1,80 @@
 <!DOCTYPE html>
 <html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="base::layout(~{::title}, ~{::main})">
 <head>
-  <title>Wee! Workflow Enactment Engine</title>
+  <title>[[${session.trace.name}]] Enactment</title>
 </head>
 <body>
 <main>
   <section class="pt-6 pb-6 pl-5 pr-5">
-    <h2 class="is-size-3 is-capitalized">Workflow Enactment Engine</h2>
-    <div class="level-left">
-      <p th:inline="text">Enacting the Process Model:</p>
-      <div class="tags has-addons">
-        <span class="tag">PM</span>
-        <span class="tag is-primary">[[${session.pm.name}]]</span>
-      </div>
-    </div>
-
-    <div class="enactment pt-3">
-      <form class="form" id="form" th:action="@{/endAct}" method="post" enctype="multipart/form-data">
-        <div class="level-left">
-          <p th:inline="text">Select output port of Activity:</p>
-          <div class="tags has-addons">
-            <span class="tag">ACTIVITY</span>
-            <span class="tag is-primary">[[${act.name}]]</span>
-          </div>
+    <div class="columns">
+      <div class="column is-two-thirds">
+        <div class="tags are-large has-addons">
+          <span class="tag">PM</span>
+          <span class="tag is-primary">[[${session.pm.name}]]</span>
         </div>
-        <div class="select">
-          <select id="portSelect" name="port" th:onchange="showDiv(this)">
-            <option th:value="1">select port</option>
-            <option th:each="port: ${act.ctrlOutPorts}" th:value="${port.iri}" th:text="${port.name}"></option>
-          </select>
-        </div>
-        <input type="hidden" th:value="${act.iri}" name="activity"/>
+        <div class="enactment pt-3">
+          <form class="form" id="form" th:action="@{/endAct}" method="post" enctype="multipart/form-data">
+            <div class="tags are-large has-addons">
+              <span class="tag">ACTIVITY</span>
+              <span class="tag is-primary">[[${act.name}]]</span>
+            </div>
+            <p>Choose the output port for the selected Process Model and Activity.</p>
+
+            <div class="select">
+              <select id="portSelect" name="port" th:onchange="showDiv(this)">
+                <option th:value="1">select port</option>
+                <option th:each="port: ${act.ctrlOutPorts}" th:value="${port.iri}" th:text="${port.name}"></option>
+              </select>
+            </div>
+            <input type="hidden" th:value="${act.iri}" name="activity"/>
 
-        <div id="hidden_div" class="is-hidden">
-          <div th:if="${arts != null && arts.size > 0}">
-            <p class="is-size-4 pt-4">Artifacts</p>
-            <th:block th:each="art : ${arts}">
-              <p th:inline="text"><strong>Name: </strong><span class="accent">[[${art.name}]]</span></p>
-              <p th:inline="text"><strong>Type: </strong><span class="accent">[[${art.type}]]</span></p>
-              <div class="file has-name">
-                <label class="file-label">
-                  <input class="file-input" type="file" th:name="${art.name}" id="input-file-${art.name}">
-                    <span class="file-cta">
+            <div id="hidden_div" class="is-hidden">
+              <div th:if="${arts != null && arts.size > 0}">
+                <p class="is-size-4 pt-4">Artifacts</p>
+                <p>The selected action requires you to upload the artifact created by the Activity.</p>
+                <th:block th:each="art : ${arts}">
+                  <p th:inline="text"><strong>Name: </strong><span class="accent">[[${art.name}]]</span></p>
+                  <p th:inline="text"><strong>Type: </strong><span class="accent">[[${art.type}]]</span></p>
+                  <div class="file has-name">
+                    <label class="file-label">
+                      <input class="file-input" type="file" th:name="${art.name}" id="input-file-${art.name}">
+                      <span class="file-cta">
                       <span class="file-icon">
                         <i class="fas fa-upload"></i>
                       </span>
                     <span class="file-label">Choose a file…</span>
                   </span>
-                  <span class="file-name">file.extension</span>
-                </label>
+                      <span class="file-name">[[${art.type}]]</span>
+                    </label>
+                  </div>
+                </th:block>
               </div>
-            </th:block>
-          </div>
-          <div class="control pt-4">
-            <button type="submit" class="button is-primary">End Activity</button>
-          </div>
+              <div class="control pt-4">
+                <button type="submit" class="button is-primary">End Activity</button>
+              </div>
+            </div>
+          </form>
+        </div>
+      </div>
+      <div class="column">
+        <div class="tags are-large has-addons">
+          <span class="tag">PT</span>
+          <span class="tag is-primary">[[${session.trace.name}]]</span>
+        </div>
+        <div class="details">
+          <p th:inline="text"><strong>Trace: </strong><span class="accent">[[${session.trace.name}]]</span></p>
+          <p th:inline="text"><strong>Started at: </strong><span class="accent">[[${session.trace.events[0].timestampF}]]</span>
+          </p>
+          <th:block th:each="ev : ${session.trace.events}">
+            <p th:if="${ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}"><strong>Begin: </strong><span
+              class="accent" th:text="${ev.relatesTo.activity.name}"></span></p>
+            <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent'}"><strong>End: </strong><span
+              class="accent" th:text="${ev.relatesTo.activity.name}"></span></p>
+            <p
+              th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent' || ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}">
+              <strong>Port: </strong><span class="accent">[[${ev.relatesTo.name}]]</span></p>
+          </th:block>
         </div>
-      </form>
-
-      <div class="details">
-        <p th:inline="text"><strong>Trace: </strong><span class="accent">[[${session.trace.name}]]</span></p>
-        <p th:inline="text"><strong>Started at: </strong><span class="accent">[[${session.trace.events[0].timestampF}]]</span></p>
-        <th:block th:each="ev : ${session.trace.events}">
-          <p th:if="${ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}"><strong>Begin: </strong><span class="accent" th:text="${ev.relatesTo.activity.name}"></span></p>
-          <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent'}"><strong>End: </strong><span class="accent" th:text="${ev.relatesTo.activity.name}"></span></p>
-          <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent' || ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}"><strong>Port: </strong><span class="accent">[[${ev.relatesTo.name}]]</span></p>
-        </th:block>
       </div>
     </div>
   </section>

+ 12 - 11
src/main/resources/templates/endEnactment.html

@@ -1,25 +1,26 @@
 <!DOCTYPE html>
 <html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="base::layout(~{::title}, ~{::main})">
 <head>
-  <title>Wee! Workflow Enactment Engine</title>
+  <title>[[${session.trace.name}]] Enactment End</title>
 </head>
 <body>
 <main>
   <section class="pt-6 pb-6 pl-5 pr-5">
-    <h2 class="is-size-3 is-capitalized">Workflow Enactment Engine</h2>
-    <p th:inline="text">Enactment of the Process Model: [[${session.pm.name}]] has ended!</p>
-    <a th:href="@{/}">HOME</a>
-    <p th:inline="text">Trace: [[${session.trace.name}]]</p>
-    <p th:inline="text">Started at: [[${session.trace.events[0].timestampF}]]</p>
+    <p th:inline="text">Enactment of the Process Model: <span class="accent">[[${session.pm.name}]]</span> has ended!</p>
+    <p>You can review the details about the Process Trace.</p>
+    <div class="tags are-large has-addons">
+      <span class="tag">PT</span>
+      <span class="tag is-primary">[[${session.trace.name}]]</span>
+    </div>
+    <p th:inline="text"><strong>Started at: </strong><span class="accent">[[${session.trace.events[0].timestampF}]]</span></p>
     <th:block th:each="ev : ${session.trace.events}">
-      <p th:if="${ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}">Begin:</p>
-      <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent'}">End:</p>
+      <p th:if="${ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}"><strong>Begin: </strong></p>
+      <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent'}"><strong>End: </strong></p>
       <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent' || ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}" th:text="${ev.relatesTo.activity.name}"></p>
-      <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndTraceEvent'}">End of Trace at:</p>
-      <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndTraceEvent'}" th:text="${ev.timestampF}"></p>
       <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndActivityEvent' || ev.class.name == 'ua.be.wee.model.pt.StartActivityEvent'}">port: [[${ev.relatesTo.name}]]</p>
+      <p th:if="${ev.class.name == 'ua.be.wee.model.pt.EndTraceEvent'}"><strong>Ended at: </strong><span class="accent">[[${ev.timestampF}]]</span></p>
     </th:block>
   </section>
 </main>
 </body>
-</html>
+</html>

+ 13 - 10
src/main/resources/templates/error.html

@@ -1,13 +1,16 @@
 <!DOCTYPE html>
-<html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="base::layout(~{::title}, ~{::main})">
+<head>
+  <title>Enactment Error</title>
+</head>
 <body>
-<center>
-<h1>Sorry, WEE have weeed and something went wrong </h1>
-<img id="img" class="wee-meme-image" src="../static/img/slip-and-fall.png" th:src="@{/img/slip-and-fall.png}" alt="Logo of person slipping">
-<h2>Let us know about it and we will try to fix ASAP </h2>
-<a href="/" >
-<img id="home" src="../static/img/home-button.png" th:src="@{/img/home-button.png}" alt="Home icon"> 
-</a>
-</center>
+<main>
+  <section class="pt-6 pb-6 pl-5 pr-5">
+    <h1>Sorry, WEE have weeed and something went wrong </h1>
+    <img id="img" class="wee-meme-image" src="../static/img/slip-and-fall.png" th:src="@{/img/slip-and-fall.png}" alt="Logo of person slipping">
+    <h2>Let us know about it and we will try to fix ASAP</h2>
+    <a href="/"><img src="../static/img/home-button.png" th:src="@{/img/home-button.png}" alt="Home icon"></a>
+  </section>
+</main>
 </body>
-</html>
+</html>

+ 30 - 22
src/main/resources/templates/pms.html

@@ -1,44 +1,52 @@
 <!DOCTYPE html>
 <html lang="en" xmlns:th="http://www.thymeleaf.org" th:replace="base::layout(~{::title}, ~{::main})">
 <head>
-  <title>Process Model Enactment</title>
+  <title>Process Model Choice</title>
 </head>
 <body>
 <main>
   <section class="pt-6 pb-6 pl-5 pr-5">
-    <h2 class="is-size-3 is-capitalized">Wee: Workflow Enactment Engine</h2>
     <form class="pt-3" th:action="@{/enactpm}" method="post">
-      <p class="is-size-4">Choose the Process Model to be enacted:</p>
+      <p class="is-size-4">Choose the Process Model to be enacted</p>
+
       <div class="field has-addons">
         <div class="control is-expanded">
           <div class="select is-fullwidth">
-            <select id="dropDownList" name="pmiri" th:onchange="'window.location.href = \'' + @{/gettraces} + '?iri=\' + encodeURIComponent(this.value) ' ">
+            <select id="dropDownList" name="pmiri"
+                    th:onchange="'window.location.href = \'' + @{/gettraces} + '?iri=\' + encodeURIComponent(this.value) ' ">
               <option th:value="1">select PM</option>
-              <option th:each="pm: ${pms}" th:value="${pm.iri}" th:text="${pm}" th:selected="${pm.iri == current}"></option>
+              <option th:each="pm: ${pms}" th:value="${pm.iri}" th:text="${pm}"
+                      th:selected="${pm.iri == current}"></option>
             </select>
           </div>
         </div>
         <div class="control">
-          <button type="submit" class="button is-primary" name="action" value="new" >New Enactment</button>
+          <button type="submit" class="button is-primary" name="action" value="new">Start New Enactment</button>
         </div>
-        
       </div>
-      
-       <div class="field has-addons" th:if="${traces != null}">
-          <p class="is-size-6">Continue enactment:</p>
-           <div class="select is-fullwidth">
-          <select id="dropDownList" name="contTrace">
-              <option value="Select Trace">select trace</option>
-              <option th:each="trace: ${traces}" th:value="${trace.iri}" th:text="${trace.name} + ' started at ' + ${trace.timestampF}"></option>
-          </select>
-          </div>
-          <div class="control">
-          	<button type="submit" class="button is-primary" name="action" value="continue">Continue Enactment</button>
-      	  </div>    
-       </div>
-      
     </form>
+    <section th:if="${traces != null}">
+      <p>This Process Model has ongoing enactments. Do you wish to continue with a previously started enactment?</p>
+      <table class="table is-striped is-hoverable is-fullwidth">
+        <thead>
+        <tr>
+          <th>Name</th>
+          <th><abbr title="Internationalized Resource Identifier">IRI</abbr></th>
+          <th>Start Time</th>
+          <th></th>
+        </tr>
+        </thead>
+        <tbody>
+        <tr th:each="trace: ${traces}" class="trace-continuation-row" th:attr="data-name=${trace.name},data-iri=${trace.iri},data-timestamp=${trace.timestampF},data-action=@{/enactpm}">
+          <th th:text="${trace.name}"></th>
+          <td th:text="${trace.iri}"></td>
+          <td th:text="${trace.timestampF}"></td>
+          <td><button class="button is-primary is-small">Continue Enactment</button></td>
+        </tr>
+        </tbody>
+      </table>
+    </section>
   </section>
 </main>
 </body>
-</html>
+</html>