mirror of
https://github.com/linuxserver/davos.git
synced 2026-04-20 00:01:51 +08:00
Bug fixes and additions to schedule page. Ready for alpha
This commit is contained in:
parent
7636800e4f
commit
7bc79ff181
@ -1,5 +1,8 @@
|
||||
package io.linuxserver.davos.dto;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
public class ActionDTO {
|
||||
|
||||
public Long id;
|
||||
@ -9,4 +12,8 @@ public class ActionDTO {
|
||||
public String f2;
|
||||
public String f3;
|
||||
public String f4;
|
||||
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
package io.linuxserver.davos.dto;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
public class FilterDTO {
|
||||
|
||||
public Long id;
|
||||
public String value;
|
||||
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,9 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import io.linuxserver.davos.transfer.ftp.FileTransferType;
|
||||
import io.linuxserver.davos.transfer.ftp.TransferProtocol;
|
||||
|
||||
@ -24,4 +27,8 @@ public class ScheduleConfigurationDTO {
|
||||
public FileTransferType transferType;
|
||||
public List<FilterDTO> filters = new ArrayList<FilterDTO>();
|
||||
public List<ActionDTO> actions = new ArrayList<ActionDTO>();
|
||||
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,8 +5,6 @@ import java.util.List;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import io.linuxserver.davos.persistence.model.ScheduleConfigurationModel;
|
||||
@ -15,8 +13,6 @@ import io.linuxserver.davos.persistence.repository.ScheduleConfigurationReposito
|
||||
@Component
|
||||
public class DefaultScheduleConfigurationDAO implements ScheduleConfigurationDAO {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultScheduleConfigurationDAO.class);
|
||||
|
||||
@Resource
|
||||
private ScheduleConfigurationRepository configRepository;
|
||||
|
||||
@ -38,9 +34,7 @@ public class DefaultScheduleConfigurationDAO implements ScheduleConfigurationDAO
|
||||
@Override
|
||||
public void updateLastRun(Long configId, DateTime lastRun) {
|
||||
|
||||
LOGGER.debug("Updating model with new lastRun of {}", lastRun);
|
||||
ScheduleConfigurationModel model = configRepository.findOne(configId);
|
||||
LOGGER.debug("Got existing model, {}", model);
|
||||
|
||||
model.lastRun = lastRun.toDate();
|
||||
configRepository.save(model);
|
||||
|
||||
@ -10,11 +10,7 @@ import javax.persistence.ManyToOne;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||
|
||||
@Entity
|
||||
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
|
||||
public class ActionModel {
|
||||
|
||||
@Id
|
||||
@ -37,7 +33,7 @@ public class ActionModel {
|
||||
public String f4;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "schedule_id")
|
||||
@JoinColumn(name = "action_schedule_id")
|
||||
public ScheduleConfigurationModel schedule;
|
||||
|
||||
@Override
|
||||
|
||||
@ -10,11 +10,7 @@ import javax.persistence.ManyToOne;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
|
||||
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
|
||||
|
||||
@Entity
|
||||
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
|
||||
public class FilterModel {
|
||||
|
||||
@Id
|
||||
@ -25,7 +21,7 @@ public class FilterModel {
|
||||
public String value;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "schedule_id")
|
||||
@JoinColumn(name = "filter_schedule_id")
|
||||
public ScheduleConfigurationModel schedule;
|
||||
|
||||
@Override
|
||||
|
||||
@ -7,13 +7,14 @@ import java.util.List;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.hibernate.annotations.LazyCollection;
|
||||
import org.hibernate.annotations.LazyCollectionOption;
|
||||
|
||||
import io.linuxserver.davos.transfer.ftp.FileTransferType;
|
||||
import io.linuxserver.davos.transfer.ftp.TransferProtocol;
|
||||
@ -61,10 +62,12 @@ public class ScheduleConfigurationModel {
|
||||
@Column
|
||||
public FileTransferType transferType;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = "schedule", cascade = CascadeType.ALL)
|
||||
@OneToMany(orphanRemoval = true, mappedBy = "schedule", cascade = CascadeType.ALL)
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
public List<FilterModel> filters = new ArrayList<FilterModel>();
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = "schedule", cascade = CascadeType.ALL)
|
||||
@OneToMany(orphanRemoval = true, mappedBy = "schedule", cascade = CascadeType.ALL)
|
||||
@LazyCollection(LazyCollectionOption.FALSE)
|
||||
public List<ActionModel> actions = new ArrayList<ActionModel>();
|
||||
|
||||
@Override
|
||||
|
||||
@ -26,6 +26,7 @@ public class RunnableSchedule implements Runnable {
|
||||
LOGGER.info("Starting schedule {}", scheduleId);
|
||||
|
||||
ScheduleConfigurationModel model = configurationDAO.getConfig(scheduleId);
|
||||
|
||||
ScheduleConfiguration config = ScheduleConfigurationFactory.createConfig(model);
|
||||
ScheduleWorkflow scheduleWorkflow = new ScheduleWorkflow(config);
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ public class HttpAPICallAction implements PostDownloadAction {
|
||||
headers.add("Content-Type", contentType);
|
||||
|
||||
LOGGER.info("Sending message to generic API for {}", execution.fileName);
|
||||
HttpEntity<String> httpEntity = new HttpEntity<String>(body, headers);
|
||||
HttpEntity<String> httpEntity = new HttpEntity<String>(body.replaceAll("$filename", execution.fileName), headers);
|
||||
LOGGER.debug("Sending message {} to generic API: {}", httpEntity, url);
|
||||
restTemplate.exchange(url, method, httpEntity, Object.class);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#spring.datasource.url=jdbc:h2:file:~/testdb
|
||||
#spring.datasource.username=sa
|
||||
#spring.datasource.password=sa
|
||||
#spring.datasource.driverClassName=org.h2.Driver
|
||||
#spring.jpa.hibernate.ddl-auto=update
|
||||
spring.datasource.url=jdbc:h2:file:/config/db/davos
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=sa
|
||||
spring.datasource.driverClassName=org.h2.Driver
|
||||
spring.jpa.hibernate.ddl-auto=update
|
||||
@ -8,7 +8,7 @@
|
||||
</Console>
|
||||
|
||||
<RollingFile name="File" fileName="davos.log"
|
||||
filePattern="logs/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log">
|
||||
filePattern="/config/logs/$${date:yyyy-MM}/app-%d{yyyy-MM-dd-HH}-%i.log">
|
||||
<PatternLayout>
|
||||
<Pattern>
|
||||
%d{yyyy-MM-dd HH:mm:ss.SSS} - $5p - [%c{1}] - %msg%n
|
||||
|
||||
@ -111,4 +111,8 @@ a.collection-item.schedule {
|
||||
|
||||
.chip {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.action_type {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
@ -32,11 +32,49 @@ var action = (function ($) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var initialise;
|
||||
var initialise, addMove, addPushbullet, addApi;
|
||||
|
||||
initialise = function () {
|
||||
|
||||
$('#select_download_action').on('change', function () {
|
||||
|
||||
var action = $(this).find('option:selected').val();
|
||||
$(this).val('choose');
|
||||
|
||||
if (action === 'pushbullet') {
|
||||
addPushbullet();
|
||||
}
|
||||
|
||||
if (action === 'move') {
|
||||
addMove();
|
||||
}
|
||||
|
||||
if (action === 'api') {
|
||||
addApi();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
addMove = function () {
|
||||
|
||||
var newAction = $('<div class="row action action_move"><div class="input-field col s3 action_type">move</div><div class="input-field col s8"><input type="text" placeholder="Move To.." class="f1" /></div></div>');
|
||||
$('#download_actions').append(newAction);
|
||||
};
|
||||
|
||||
addPushbullet = function () {
|
||||
|
||||
var newAction = $('<div class="row action action_pushbullet"><div class="input-field col s3 action_type">pushbullet</div><div class="input-field col s8"><input type="text" placeholder="API Key" class="f1" /></div></div>');
|
||||
$('#download_actions').append(newAction);
|
||||
};
|
||||
|
||||
addApi = function () {
|
||||
|
||||
|
||||
var newAction = $('<div class="row action action_api"><div class="input-field col s3 action_type">api</div><div class="input-field col s8"><input type="text" placeholder="URL" class="f1" /><br />' +
|
||||
'<input type="text" placeholder="Method (e.g. POST, GET)" class="f2" /><br /><input type="text" placeholder="Content Type (e.g. application/json)" class="f3" /><br /><input type="text"' +
|
||||
' placeholder="Message body" class="f4" /><br /></div></div>');
|
||||
|
||||
$('#download_actions').append(newAction);
|
||||
};
|
||||
|
||||
return {
|
||||
@ -49,13 +87,13 @@ var schedule = (function ($) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var initialise, save, onSuccess, onError, cleanId, startSchedule, stopSchedule, startResponse, stopResponse;
|
||||
var initialise, save, onSuccess, onError, cleanId, startSchedule, stopSchedule, startResponse, stopResponse, cleanActionFunction;
|
||||
|
||||
initialise = function () {
|
||||
|
||||
$('#start_schedule').on('click', startSchedule);
|
||||
$('#stop_schedule').on('click', stopSchedule);
|
||||
|
||||
|
||||
$('#save_schedule').on('click', function () {
|
||||
|
||||
var postData = {
|
||||
@ -87,6 +125,21 @@ var schedule = (function ($) {
|
||||
postData.filters.push(filter);
|
||||
});
|
||||
|
||||
$('#download_actions .action').each(function () {
|
||||
|
||||
var action = {
|
||||
|
||||
id: cleanId($(this).attr('data-action-id')),
|
||||
actionType: $(this).find('.action_type').text(),
|
||||
f1: cleanActionFunction($(this).find('.f1')),
|
||||
f2: cleanActionFunction($(this).find('.f2')),
|
||||
f3: cleanActionFunction($(this).find('.f3')),
|
||||
f4: cleanActionFunction($(this).find('.f4'))
|
||||
};
|
||||
|
||||
postData.actions.push(action);
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
|
||||
method: "POST",
|
||||
@ -100,6 +153,14 @@ var schedule = (function ($) {
|
||||
});
|
||||
};
|
||||
|
||||
cleanActionFunction = function (action) {
|
||||
|
||||
if (action)
|
||||
return action.val();
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
cleanId = function (id) {
|
||||
|
||||
if ($.trim(id).length === 0) {
|
||||
@ -116,7 +177,7 @@ var schedule = (function ($) {
|
||||
url: "/api/v1/schedule/" + cleanId($('#schedule_id').val()) + "/start"
|
||||
}).done(startResponse).fail(startResponse);
|
||||
};
|
||||
|
||||
|
||||
stopSchedule = function () {
|
||||
|
||||
$.ajax({
|
||||
@ -128,7 +189,7 @@ var schedule = (function ($) {
|
||||
startResponse = function (msg) {
|
||||
Materialize.toast(msg.message, 3000, 'rounded');
|
||||
};
|
||||
|
||||
|
||||
stopResponse = function (msg) {
|
||||
Materialize.toast(msg.message, 3000, 'rounded');
|
||||
};
|
||||
|
||||
@ -234,7 +234,7 @@
|
||||
</li>
|
||||
<li>
|
||||
<div class="collapsible-header active"><i class="material-icons">code</i>Post-download Actions</div>
|
||||
<div class="collapsible-body">
|
||||
<div class="collapsible-body" id="download_actions">
|
||||
<div class="row">
|
||||
<div class="col s12">
|
||||
<p class="subtext">
|
||||
@ -246,22 +246,41 @@
|
||||
<div class="row">
|
||||
|
||||
<div class="input-field col s4">
|
||||
<select class="browser-default">
|
||||
<option value="" disabled="disabled" selected="selected">Add action...</option>
|
||||
<select id="select_download_action" class="browser-default">
|
||||
<option value="choose" disabled="disabled" selected="selected">Add action...</option>
|
||||
<option value="pushbullet">Pushbullet Notification</option>
|
||||
<option value="move">Move downloaded file</option>
|
||||
<option value="move">Move Downloaded File</option>
|
||||
<option value="api">Generic HTTP API Call</option>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="download_actions">
|
||||
<div th:each="action : ${schedule.actions}" th:switch="${action.actionType}" th:attr="data-action-id=${action.id}, class='row action action_' + ${action.actionType}">
|
||||
|
||||
<div class="input-field col s3 action_type" th:text="${action.actionType}"></div>
|
||||
|
||||
<div class="row download_action">
|
||||
<div th:case="'move'" class="action_name input-field col s8">
|
||||
<input type="text" placeholder="Move To..." class="f1" th:attr="value=${action.f1}" />
|
||||
</div>
|
||||
|
||||
<div th:case="'pushbullet'" class="action_name input-field col s8">
|
||||
<input type="text" placeholder="API Key" class="f1" th:attr="value=${action.f1}" />
|
||||
</div>
|
||||
|
||||
<div th:case="'api'" class="action_name input-field col s8">
|
||||
<input type="text" placeholder="URL" class="f1" th:attr="value=${action.f1}" />
|
||||
<br />
|
||||
<input type="text" placeholder="Method (e.g. POST, GET)" class="f2" th:attr="value=${action.f2}" />
|
||||
<br />
|
||||
<input type="text" placeholder="Content Type (e.g. application/json)" class="f3" th:attr="value=${action.f3}" />
|
||||
<br />
|
||||
<input type="text" placeholder="Message body" class="f4" th:attr="value=${action.f4}" />
|
||||
<br />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
@ -285,9 +304,10 @@
|
||||
<script type="text/javascript" th:src="@{/js/jquery-2.1.4.min.js}"></script>
|
||||
<script type="text/javascript" th:src="@{/js/materialize.min.js}"></script>
|
||||
<script type="text/javascript" th:src="@{/js/davos.js}"></script>
|
||||
|
||||
|
||||
<script type="text/javascript" th:inline="text">
|
||||
var base = "[[@{/}]]"
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
@ -35,7 +35,7 @@ public class HttpAPICallActionTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
httpAPICallAction = new HttpAPICallAction("http://url", HttpMethod.POST, "application/json", "{\"hello\":\"world\"}");
|
||||
httpAPICallAction = new HttpAPICallAction("http://url", HttpMethod.POST, "application/json", "{\"hello\":\"$filename\"}");
|
||||
|
||||
initMocks(this);
|
||||
}
|
||||
@ -52,7 +52,7 @@ public class HttpAPICallActionTest {
|
||||
|
||||
String body = entityCaptor.getValue().getBody();
|
||||
|
||||
assertThat(body).isEqualTo("{\"hello\":\"world\"}");
|
||||
assertThat(body).isEqualTo("{\"hello\":\"file.txt\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -73,18 +73,24 @@ public class HttpAPICallActionTest {
|
||||
@Test
|
||||
public void ifRestTemplateFailsThenDoNothing() {
|
||||
|
||||
PostDownloadExecution execution = new PostDownloadExecution();
|
||||
execution.fileName = "filename";
|
||||
|
||||
when(mockRestTemplate.exchange(eq("http://url"), eq(HttpMethod.POST), any(HttpEntity.class), eq(Object.class)))
|
||||
.thenThrow(new RestClientException(""));
|
||||
|
||||
httpAPICallAction.execute(new PostDownloadExecution());
|
||||
httpAPICallAction.execute(execution);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ifRestTemplateFailsBecauseMessageIsUnreadbleThenDoNothing() {
|
||||
|
||||
PostDownloadExecution execution = new PostDownloadExecution();
|
||||
execution.fileName = "filename";
|
||||
|
||||
when(mockRestTemplate.exchange(eq("http://url"), eq(HttpMethod.POST), any(HttpEntity.class), eq(Object.class)))
|
||||
.thenThrow(new HttpMessageConversionException(""));
|
||||
|
||||
httpAPICallAction.execute(new PostDownloadExecution());
|
||||
httpAPICallAction.execute(execution);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user