Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ public interface GroupSyncJobRepository extends PagingAndSortingRepository<Group
public List<GroupSyncJob> findByGroupIdIn(List<String> groupIds, Pageable page);

public long countByGroupIdIn(List<String> groupIds);

public long deleteByGroupIdInAndCreatedOnBefore(List<String> groupIds, java.time.OffsetDateTime threshold);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package edu.asu.diging.citesphere.core.service.jobs;

import java.util.List;
import java.time.OffsetDateTime;

import org.springframework.data.domain.Pageable;

Expand All @@ -18,5 +19,7 @@ public interface ISyncJobManager {
long getJobsCount(IUser user);

void cancelJob(String jobId);

long pruneJobs(IUser user, OffsetDateTime before);

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
import java.util.stream.Collectors;

import javax.annotation.PostConstruct;
import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import edu.asu.diging.citesphere.core.model.jobs.IJob;
import edu.asu.diging.citesphere.core.model.jobs.JobStatus;
import edu.asu.diging.citesphere.core.model.jobs.impl.GroupSyncJob;
import edu.asu.diging.citesphere.core.repository.jobs.GroupSyncJobRepository;
Expand Down Expand Up @@ -89,4 +89,15 @@ public void cancelJob(String jobId) {
jobRepo.save(job);
}
}

@Override
@Transactional
public long pruneJobs(IUser user, OffsetDateTime before) {
List<ICitationGroup> groups = citationManager.getGroups(user);
if (groups == null || groups.isEmpty()) {
return 0;
}
List<String> groupIds = groups.stream().map(g -> g.getGroupId() + "").collect(Collectors.toList());
return jobRepo.deleteByGroupIdInAndCreatedOnBefore(groupIds, before);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package edu.asu.diging.citesphere.web.user.jobs;

import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
Expand All @@ -8,6 +12,10 @@
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.format.annotation.DateTimeFormat;

import edu.asu.diging.citesphere.core.service.jobs.ISyncJobManager;
import edu.asu.diging.citesphere.user.IUser;
Expand All @@ -26,8 +34,23 @@ public String list(Model model, @PageableDefault(sort = { "createdOn" }, directi
return "redirect:/";
}
model.addAttribute("jobs", jobManager.getJobs((IUser) authentication.getPrincipal(), page));
model.addAttribute("total", Math.ceil(total/page.getPageSize()));
model.addAttribute("page", page.getPageNumber() + 1);
long totalPages = total > 0 ? (long) Math.ceil((double) total / page.getPageSize()) : 1;
model.addAttribute("total", totalPages);
model.addAttribute("page", Math.max(1, Math.min(page.getPageNumber() + 1, totalPages)));
return "auth/jobs/list";
}

@RequestMapping(value = "/auth/jobs/sync/prune", method = RequestMethod.POST)
public String prune(@RequestParam("pruneDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate pruneDate, Authentication authentication,
RedirectAttributes redirectAttributes) {
OffsetDateTime pruneBefore = pruneDate.plusDays(1).atStartOfDay().atOffset(ZoneOffset.UTC);
long deleted = jobManager.pruneJobs((IUser) authentication.getPrincipal(), pruneBefore);

redirectAttributes.addFlashAttribute("show_alert", true);
redirectAttributes.addFlashAttribute("alert_type", "success");
redirectAttributes.addFlashAttribute("alert_msg",
String.format("%d job(s) deleted up to and including %s.", deleted, pruneDate));

return "redirect:/auth/jobs/sync/list";
}
}
106 changes: 96 additions & 10 deletions citesphere/src/main/webapp/WEB-INF/views/auth/jobs/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,110 @@
<script th:inline="javascript">
//# sourceURL=page.js
$(function() {
$('#pagination-top').twbsPagination({
totalPages: [(${total})],
startPage: [(${page})],
prev: "«",
next: "»",
visiblePages: 10,
initiateStartPageClick: false,
onPageClick: function (event, page) {
window.location.href = "[(@{|/auth/jobs/sync/list|})]?page=" + (page - 1);
var totalPages = [(${total})];
var startPage = [(${page})];
if (totalPages > 0 && startPage > 0 && startPage <= totalPages) {
$('#pagination-top').twbsPagination({
totalPages: totalPages,
startPage: startPage,
prev: "«",
next: "»",
visiblePages: 10,
initiateStartPageClick: false,
onPageClick: function (event, page) {
window.location.href = "[(@{|/auth/jobs/sync/list|})]?page=" + (page - 1);
}
});
}

$('#openPruneModal').on('click', function() {
$('#pruneModal').modal('show');
});

$('#pruneForm').on('submit', function(e) {
var date = $('#pruneDate').val();
if (!date) {
e.preventDefault();
alert('Please select a date.');
return;
}
e.preventDefault();
$('#confirmDate').text(date);
$('#pruneModal').modal('hide');
$('#confirmDeleteModal').modal('show');
});

$('#confirmDelete').on('click', function() {
$('#pruneForm')[0].submit();
});

$('#cancelConfirm').on('click', function() {
$('#confirmDeleteModal').modal('hide');
$('#pruneModal').modal('show');
});
});
</script>
</head>

<body>
<div layout:fragment="content">
<h1>Jobs</h1>
<div class="row" style="margin-bottom: 15px;">
<div class="col-md-6">
<h1 style="margin: 0;">Jobs</h1>
</div>
<div class="col-md-6 text-right" style="padding-top: 10px;">
<button id="openPruneModal" class="btn btn-danger btn-sm">Prune Jobs</button>
</div>
</div>

<div class="modal fade" id="pruneModal" tabindex="-1" role="dialog" aria-labelledby="pruneModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form id="pruneForm" th:action="@{/auth/jobs/sync/prune}" method="post">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="pruneModalLabel">Prune jobs</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="pruneDate">Delete jobs created on or before</label>
<input type="date" id="pruneDate" name="pruneDate" class="form-control" required />
</div>
<div class="alert alert-warning" role="alert">
This will permanently delete all jobs up to and including the selected date. This cannot be undone.
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-danger">Delete jobs</button>
</div>
</form>
</div>
</div>
</div>

<div class="modal fade" id="confirmDeleteModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span>&times;</span></button>
<h4 class="modal-title">Confirm Deletion</h4>
</div>
<div class="modal-body">
<div class="alert alert-danger">
<strong>Warning!</strong> This is an irreversible action. All jobs up to and including
<span id="confirmDate"></span> will be permanently deleted.
</div>
<p>Are you sure you want to continue?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" id="cancelConfirm">Cancel</button>
<button type="button" class="btn btn-danger" id="confirmDelete">Delete Jobs</button>
</div>
</div>
</div>
</div>

<ul id="pagination-top" class="pagination-sm"></ul>

Expand Down