Skip to content

Commit fa4c772

Browse files
author
Mark Robinson
committed
Add /workflows endpoint to list all workflows with pagination
1 parent 68179a7 commit fa4c772

File tree

8 files changed

+177
-26
lines changed

8 files changed

+177
-26
lines changed

src/main/java/org/commonwl/viewer/domain/GithubDetails.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ public class GithubDetails implements Serializable {
2828

2929
private String owner;
3030
private String repoName;
31-
private String sha;
3231
private String branch;
3332
private String path;
3433

src/main/java/org/commonwl/viewer/services/DotWriter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public void writeGraph(Workflow workflow) throws IOException {
5757

5858
// Overall graph style
5959
writeLine(" graph [");
60-
writeLine(" bgcolor = \"#EEEEEE\"");
60+
writeLine(" bgcolor = \"transparent\"");
6161
writeLine(" color = \"black\"");
6262
writeLine(" fontsize = \"10\"");
6363
writeLine(" labeljust = \"left\"");

src/main/java/org/commonwl/viewer/services/WorkflowRepository.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,19 @@
2121

2222
import org.commonwl.viewer.domain.GithubDetails;
2323
import org.commonwl.viewer.domain.Workflow;
24-
import org.springframework.data.mongodb.repository.MongoRepository;
24+
import org.springframework.data.domain.Page;
25+
import org.springframework.data.domain.Pageable;
26+
import org.springframework.data.repository.PagingAndSortingRepository;
2527

2628
/**
2729
* Stores workflow objects in the database
2830
*/
29-
public interface WorkflowRepository extends MongoRepository<Workflow, String> {
31+
public interface WorkflowRepository extends PagingAndSortingRepository<Workflow, String> {
3032

3133
// Finds a workflow model in the database based on where it was retrieved from
3234
Workflow findByRetrievedFrom(GithubDetails retrievedFrom);
3335

36+
// Get the first 10 workflows
37+
Page<Workflow> findAllByOrderByRetrievedOnDesc(Pageable pageable);
38+
3439
}

src/main/java/org/commonwl/viewer/web/WorkflowController.java

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import com.github.jabbalaci.graphviz.GraphViz;
2323
import org.apache.commons.lang.StringUtils;
24+
import org.apache.jena.ext.com.google.common.collect.Lists;
2425
import org.commonwl.viewer.domain.GithubDetails;
2526
import org.commonwl.viewer.domain.Workflow;
2627
import org.commonwl.viewer.domain.WorkflowForm;
@@ -32,7 +33,13 @@
3233
import org.springframework.beans.factory.annotation.Autowired;
3334
import org.springframework.beans.factory.annotation.Value;
3435
import org.springframework.core.io.FileSystemResource;
36+
import org.springframework.data.domain.Page;
37+
import org.springframework.data.domain.PageRequest;
38+
import org.springframework.data.domain.Pageable;
39+
import org.springframework.data.web.PageableDefault;
3540
import org.springframework.stereotype.Controller;
41+
import org.springframework.ui.Model;
42+
import org.springframework.ui.ModelMap;
3643
import org.springframework.validation.BindingResult;
3744
import org.springframework.web.bind.annotation.*;
3845
import org.springframework.web.servlet.HandlerMapping;
@@ -67,6 +74,19 @@ public WorkflowController(WorkflowFormValidator workflowFormValidator,
6774
this.workflowRepository = workflowRepository;
6875
}
6976

77+
/**
78+
* List all the workflows in the database, paginated
79+
* @param model The model for the page
80+
* @param pageable Pagination for the list of workflows
81+
* @return The workflows view
82+
*/
83+
@RequestMapping(value="/workflows")
84+
public String listWorkflows(Model model, Pageable pageable) {
85+
model.addAttribute("workflows", workflowRepository.findAllByOrderByRetrievedOnDesc(pageable));
86+
model.addAttribute("pages", pageable);
87+
return "workflows";
88+
}
89+
7090
/**
7191
* Create a new workflow from the given github URL in the form
7292
* @param workflowForm The data submitted from the form
@@ -113,27 +133,6 @@ public ModelAndView newWorkflowFromGithubURL(@Valid WorkflowForm workflowForm, B
113133
}
114134
}
115135

116-
/**
117-
* Display a page for a particular workflow
118-
* @param workflowID The ID of the workflow to be retrieved
119-
* @return The workflow view with the workflow as a model
120-
*/
121-
@RequestMapping(value="/workflows/{workflowID}")
122-
public ModelAndView getWorkflowByID(@PathVariable String workflowID){
123-
124-
// Get workflow from database
125-
Workflow workflowModel = workflowRepository.findOne(workflowID);
126-
127-
// 404 error if workflow does not exist
128-
if (workflowModel == null) {
129-
throw new WorkflowNotFoundException();
130-
}
131-
132-
// Display this model along with the view
133-
return new ModelAndView("workflow", "workflow", workflowModel);
134-
135-
}
136-
137136
/**
138137
* Display a page for a particular workflow from Github details
139138
* @param owner The owner of the Github repository

src/main/resources/static/css/main.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ body {
102102
margin-bottom: 5px;
103103
}
104104

105+
.icon-view {
106+
font-size: 20px;
107+
}
108+
105109
#visualisation {
106110
overflow: hidden;
107111
padding: 0;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<!DOCTYPE html>
2+
<!--
3+
~ Licensed to the Apache Software Foundation (ASF) under one
4+
~ or more contributor license agreements. See the NOTICE file
5+
~ distributed with this work for additional information
6+
~ regarding copyright ownership. The ASF licenses this file
7+
~ to you under the Apache License, Version 2.0 (the
8+
~ "License"); you may not use this file except in compliance
9+
~ with the License. You may obtain a copy of the License at
10+
~
11+
~ http://www.apache.org/licenses/LICENSE-2.0
12+
~
13+
~ Unless required by applicable law or agreed to in writing,
14+
~ software distributed under the License is distributed on an
15+
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
~ KIND, either express or implied. See the License for the
17+
~ specific language governing permissions and limitations
18+
~ under the License.
19+
-->
20+
21+
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
22+
<head>
23+
<link rel="stylesheet" type="text/css" href="../../static/css/main.css" />
24+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" />
25+
</head>
26+
<body>
27+
<nav th:fragment="workflowControl" class="text-center">
28+
<ul class="pagination">
29+
<li th:class="${pages.getPageNumber() == 0}? 'disabled' : ''">
30+
<span th:if="${pages.getPageNumber() == 0}? 'disabled' : ''" aria-hidden="true">First</span>
31+
<a th:unless="${pages.getPageNumber() == 0}? 'disabled' : ''" aria-label="Previous">
32+
<span aria-hidden="true">First</span>
33+
</a>
34+
</li>
35+
<li th:class="${workflows.hasPrevious()} ? '' : 'disabled'">
36+
<span th:unless="${workflows.hasPrevious()}">&laquo;</span>
37+
<a href="#" th:if="${workflows.hasPrevious()}" th:href="@{'?page=' + ${pages.getPageNumber() - 1} + '&amp;size=' + ${pages.getPageSize()}}">&laquo;</a>
38+
</li>
39+
<li th:if="${pages.getPageNumber() - 2 &gt; 0}">
40+
<a href="#" th:text="${pages.getPageNumber() - 2}" th:href="@{'?page=' + ${pages.getPageNumber() - 3} + '&amp;size=' + ${pages.getPageSize()}}">1</a>
41+
</li>
42+
<li th:if="${pages.getPageNumber() - 1 &gt; 0}">
43+
<a href="#" th:text="${pages.getPageNumber() - 1}" th:href="@{'?page=' + ${pages.getPageNumber() - 2} + '&amp;size=' + ${pages.getPageSize()}}">2</a>
44+
</li>
45+
<li th:if="${workflows.hasPrevious()}">
46+
<a href="#" th:text="${pages.getPageNumber()}" th:href="@{'?page=' + ${pages.getPageNumber() - 1} + '&amp;size=' + ${pages.getPageSize()}}">3</a>
47+
</li>
48+
<li th:class="active">
49+
<span th:text="${pages.getPageNumber() + 1}">4</span>
50+
</li>
51+
<li th:if="${workflows.hasNext()}">
52+
<a href="#" th:text="${pages.getPageNumber() + 2}" th:href="@{'?page=' + ${pages.getPageNumber() + 1} + '&amp;size=' + ${pages.getPageSize()}}">5</a>
53+
</li>
54+
<li th:if="${pages.getPageNumber() + 2 &lt; workflows.getTotalPages()}">
55+
<a href="#" th:text="${pages.getPageNumber() + 3}" th:href="@{'?page=' + ${pages.getPageNumber() + 2} + '&amp;size=' + ${pages.getPageSize()}}">6</a>
56+
</li>
57+
<li th:if="${pages.getPageNumber() + 3 &lt; workflows.getTotalPages()}">
58+
<a href="#" th:text="${pages.getPageNumber() + 4}" th:href="@{'?page=' + ${pages.getPageNumber() + 3} + '&amp;size=' + ${pages.getPageSize()}}">7</a>
59+
</li>
60+
<li th:class="${workflows.hasNext()}? '' : 'disabled'">
61+
<span th:if="${workflows.hasNext()}">&raquo;</span>
62+
<a th:unless="${workflows.hasNext()}" th:href="@{'?page=' + ${pages.getPageNumber() + 1} + '&amp;size=' + ${pages.getPageSize()}}" title="Go to next page">&raquo;</a>
63+
</li>
64+
<li th:class="${workflows.getTotalPages() == pages.getPageNumber() + 1} ? 'disabled' : ''">
65+
<span th:if="${workflows.getTotalPages() == pages.getPageNumber() + 1}">Last</span>
66+
<a th:unless="${workflows.getTotalPages() == pages.getPageNumber() + 1}" th:href="@{'?page=' + ${workflows.getTotalPages() - 1} + '&amp;size=' + ${pages.getPageSize()}}">Last</a>
67+
</li>
68+
</ul>
69+
</nav>
70+
</body>
71+
</html>

src/main/resources/templates/workflow.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ <h2>Workflow: <span th:text="${workflow.label}">Workflow Name</span></h2>
153153
</div>
154154
<div th:if="${workflow.dockerLink != null}">
155155
<h2 style="float:left;">Requires: </h2>
156-
<a th:unless="${workflow.dockerLink == 'true'}" th:href="${workflow.dockerLink}">
156+
<a th:unless="${workflow.dockerLink == 'true'}" th:href="${workflow.dockerLink}" rel="noopener" target="_blank">
157157
<img id="dockerLogo" src="/img/Docker-logo.png" alt="docker logo" />
158158
</a>
159159
<img th:if="${workflow.dockerLink == 'true'}" id="dockerLogo" src="/img/Docker-logo.png" alt="docker logo" />
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<!DOCTYPE html>
2+
<!--
3+
~ Licensed to the Apache Software Foundation (ASF) under one
4+
~ or more contributor license agreements. See the NOTICE file
5+
~ distributed with this work for additional information
6+
~ regarding copyright ownership. The ASF licenses this file
7+
~ to you under the Apache License, Version 2.0 (the
8+
~ "License"); you may not use this file except in compliance
9+
~ with the License. You may obtain a copy of the License at
10+
~
11+
~ http://www.apache.org/licenses/LICENSE-2.0
12+
~
13+
~ Unless required by applicable law or agreed to in writing,
14+
~ software distributed under the License is distributed on an
15+
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
~ KIND, either express or implied. See the License for the
17+
~ specific language governing permissions and limitations
18+
~ under the License.
19+
-->
20+
21+
<html xmlns:th="http://www.thymeleaf.org">
22+
<head>
23+
<meta charset="UTF-8" />
24+
<meta name="viewport" content="width=device-width, initial-scale=1" />
25+
<title>Common Workflow Language Viewer</title>
26+
<link rel="stylesheet" type="text/css" th:href="@{/css/main.css}" href="../static/css/main.css" />
27+
<link rel="stylesheet" th:href="@{/bower_components/bootstrap/dist/css/bootstrap.min.css}" href="../static/bower_components/bootstrap/dist/css/bootstrap.min.css" />
28+
</head>
29+
<body>
30+
31+
<nav th:replace="fragments/header :: navbar"></nav>
32+
33+
<div class="container">
34+
<div class="row">
35+
<div class="col-md-12" role="main" id="main">
36+
<h1>All Workflows</h1>
37+
38+
<nav th:replace="fragments/pagination :: workflowControl"></nav>
39+
40+
<table class="table table-striped">
41+
<tr>
42+
<th>Graph</th>
43+
<th>Name</th>
44+
<th>Retrieved From</th>
45+
<th>View</th>
46+
</tr>
47+
<tr th:each="workflow : ${workflows}" th:with="workflowURL=@{'/workflows/github.com/' + ${workflow.retrievedFrom.owner} + '/' + ${workflow.retrievedFrom.repoName} + '/tree/' + ${workflow.retrievedFrom.branch} + '/' + ${workflow.retrievedFrom.path}}">
48+
<td>
49+
<a th:href="${workflowURL}">
50+
<img th:src="@{'/workflows/' + ${workflow.id} + '/graph/svg'}" alt="workflow graph" />
51+
</a>
52+
</td>
53+
<td th:text="${workflow.label}"></td>
54+
<td>
55+
<a th:href="@{'https://github.com/' + ${workflow.retrievedFrom.owner} + '/' + ${workflow.retrievedFrom.repoName} + '/tree/' + ${workflow.lastCommit} + '/' + ${workflow.retrievedFrom.path}}" rel="noopener" target="_blank">
56+
<img id="githubLogo" src="../static/img/GitHub-Mark-32px.png" th:src="@{/img/GitHub-Mark-32px.png}" width="20" height="20" />
57+
<span th:text="@{${workflow.retrievedFrom.owner} + '/' + ${workflow.retrievedFrom.repoName} + '/' + ${workflow.retrievedFrom.path}}"></span>
58+
</a>
59+
</td>
60+
<td><a th:href="${workflowURL}"><span class="icon-view glyphicon glyphicon-chevron-right"></span></a></td>
61+
</tr>
62+
</table>
63+
64+
<nav th:replace="fragments/pagination :: workflowControl"></nav>
65+
66+
</div>
67+
</div>
68+
</div>
69+
70+
<div th:replace="fragments/footer :: copy"></div>
71+
72+
</body>
73+
</html>

0 commit comments

Comments
 (0)