Fixing searching in library movies

Added nuke option to blow away all stored data
This commit is contained in:
jhouse
2020-02-12 15:17:27 +09:00
parent 7d895dd695
commit f898008069
13 changed files with 201 additions and 82 deletions

View File

@@ -36,4 +36,9 @@ public interface GapsService {
* @param plexSearch The object to copy into the plex search singleton
*/
void updatePlexSearch(PlexSearch plexSearch);
/**
* Resets the plex search object itself to the singleton object
*/
void nukePlexSearch();
}

View File

@@ -19,7 +19,11 @@ public enum Payload {
TMDB_KEY_INVALID(21, "TMDB Key invalid"),
TMDB_CONNECTION_ERROR(22, "Error connecting to TMDB with url"),
TMDB_KEY_SAVE_SUCCESSFUL(23, "TMDB key saved."),
TMDB_KEY_SAVE_UNSUCCESSFUL(24, "TMDB key not saved.");
TMDB_KEY_SAVE_UNSUCCESSFUL(24, "TMDB key not saved."),
NUKE_SUCCESSFUL(30, "Nuke successful. All files deleted."),
NUKE_UNSUCCESSFUL(31, "Nuke unsuccessful. Manually delete files."),
PLEX_LIBRARY_MOVIE_FOUND(40, "Plex's library movies found."),
PLEX_LIBRARY_MOVIE_NOT_FOUND(41, "Plex's library movies not found.");
final private int code;
final private String reason;

View File

@@ -10,6 +10,7 @@
package com.jasonhhouse.gaps.controller;
import com.jasonhhouse.gaps.GapsService;
import com.jasonhhouse.gaps.Payload;
import com.jasonhhouse.gaps.PlexSearch;
import com.jasonhhouse.gaps.service.IoService;
import java.io.IOException;
@@ -17,10 +18,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
@@ -56,6 +60,20 @@ public class GapsController {
return modelAndView;
}
@RequestMapping(method = RequestMethod.PUT,
value = "/nuke/{username}",
produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ResponseEntity<Payload> putNuke(@PathVariable("username") final String username) {
LOGGER.info("putNuke( " + username + " )");
LOGGER.info("Deleting all local files");
Payload payload = ioService.nuke();
if (payload.getCode() == Payload.NUKE_SUCCESSFUL.getCode()) {
gapsService.nukePlexSearch();
}
return ResponseEntity.ok().body(payload);
}
@InitBinder
public void initBinder(WebDataBinder binder) {
LOGGER.info("initBinder()");

View File

@@ -1,10 +1,8 @@
package com.jasonhhouse.gaps.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.jasonhhouse.gaps.GapsService;
import com.jasonhhouse.gaps.Movie;
import com.jasonhhouse.gaps.Payload;
import com.jasonhhouse.gaps.PlexLibrary;
import com.jasonhhouse.gaps.PlexSearch;
import com.jasonhhouse.gaps.PlexServer;
@@ -31,7 +29,6 @@ import org.springframework.web.servlet.ModelAndView;
public class LibraryController {
private static final Logger LOGGER = LoggerFactory.getLogger(LibraryController.class);
private static final ObjectMapper objectMapper = new ObjectMapper();
private final IoService ioService;
private final GapsService gapsService;
@@ -96,31 +93,22 @@ public class LibraryController {
@RequestMapping(method = RequestMethod.GET,
path = "/libraries/{machineIdentifier}/{key}")
@ResponseBody
public ResponseEntity<String> getLibraries(@PathVariable("machineIdentifier") final String machineIdentifier, @PathVariable("key") final Integer key) {
public ResponseEntity<Payload> getLibraries(@PathVariable("machineIdentifier") final String machineIdentifier, @PathVariable("key") final Integer key) {
LOGGER.info("getLibraries( " + machineIdentifier + ", " + key + " )");
List<Movie> movies = ioService.readOwnedMovies(machineIdentifier, key);
ObjectNode objectNode = objectMapper.createObjectNode();
Payload payload;
if (CollectionUtils.isEmpty(movies)) {
objectNode.put("success", false);
LOGGER.warn("Could not find Plex Library movies");
payload = Payload.PLEX_LIBRARY_MOVIE_NOT_FOUND;
LOGGER.warn(payload.getReason());
} else {
String output;
try {
output = objectMapper.writeValueAsString(movies);
objectNode.put("success", true);
} catch (JsonProcessingException e) {
LOGGER.error("Failed to turn PlexLibrary Movies to JSON", e);
objectNode.put("success", false);
output = "";
}
objectNode.put("movies", output);
payload = Payload.PLEX_LIBRARY_MOVIE_FOUND;
}
return ResponseEntity.ok().body(objectNode.toString());
payload.setExtras(movies);
return ResponseEntity.ok().body(payload);
}
}

View File

@@ -73,4 +73,10 @@ public class GapsServiceImpl implements GapsService {
this.plexSearch.setMovieDbApiKey(plexSearch.getMovieDbApiKey());
}
}
@Override
public void nukePlexSearch() {
plexSearch.setMovieDbApiKey("");
plexSearch.getPlexServers().clear();
}
}

View File

@@ -13,6 +13,7 @@ package com.jasonhhouse.gaps.service;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jasonhhouse.gaps.Movie;
import com.jasonhhouse.gaps.Payload;
import com.jasonhhouse.gaps.PlexLibrary;
import com.jasonhhouse.gaps.PlexSearch;
import com.jasonhhouse.gaps.PlexServer;
@@ -429,4 +430,27 @@ public class IoService {
return plexSearch;
}
public Payload nuke() {
LOGGER.info("nuke()");
File folder = new File(STORAGE_FOLDER);
try {
nuke(folder);
return Payload.NUKE_SUCCESSFUL;
} catch (Exception e) {
LOGGER.error(Payload.NUKE_UNSUCCESSFUL.getReason(), e);
return Payload.NUKE_UNSUCCESSFUL;
}
}
private void nuke(File file) {
LOGGER.info("nuke( " + file + " )");
if (!file.isFile()) {
for (File children : file.listFiles()) {
nuke(children);
}
} else {
file.delete();
}
}
}

View File

@@ -15,10 +15,10 @@ export function getMoviesForTable(url, movieContainer, noMovieContainer, moviesT
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (result) {
if (result.success) {
if (result.code = 40) {
movieContainer.show(100);
noMovieContainer.css({'display': 'none'});
moviesTable.rows.add(JSON.parse(result.movies)).draw();
moviesTable.rows.add(result.extras).draw();
} else {
movieContainer.css({'display': 'none'});
noMovieContainer.show(100);

View File

@@ -30,14 +30,20 @@ jQuery(function ($) {
libraryKey = $('#libraryKey').val();
moviesTable = $('#movies').DataTable({
initComplete: function () {
getMoviesForTable(`/libraries/${plexServer.machineIdentifier}/${libraryKey}`, movieContainer, noMovieContainer, moviesTable);
},
deferRender: true,
search: true,
ordering: false,
columns: [
{data: 'imdbId'},
{data: 'name'},
{data: 'year'},
{data: 'language'},
{data: 'overview'}
],
columnDefs: [
{
data: "card",
targets: [0],
type: 'html',
searchable: false,
render: function (data, type, row) {
if (type === 'display') {
row.address = plexServer.address;
@@ -52,52 +58,17 @@ jQuery(function ($) {
}
},
{
data: "title",
searchable: true,
visible: false,
render: function (data, type, row) {
if (type === 'display' && row.name) {
return row.name;
}
return "";
}
},
{
data: "year",
searchable: true,
visible: false,
render: function (data, type, row) {
if (type === 'display' && row.year) {
return row.year;
}
return "";
}
},
{
data: "language",
searchable: true,
visible: false,
render: function (data, type, row) {
if (type === 'display' && row.language) {
return row.language;
}
return "";
}
},
{
data: "summary",
searchable: true,
visible: false,
render: function (data, type, row) {
if (type === 'display' && row.overview) {
return row.overview;
}
return "";
}
},
targets: [1, 2, 3, 4],
visible: false
}
]
});
getMoviesForTable(`/libraries/${plexServer.machineIdentifier}/${libraryKey}`, movieContainer, noMovieContainer, moviesTable);
//Exposing function for onClick()
window.searchForMovies = searchForMovies;
window.switchPlexLibrary = switchPlexLibrary;
});
function switchPlexLibrary(machineIdentifier, key) {
@@ -112,7 +83,6 @@ function switchPlexLibrary(machineIdentifier, key) {
getMoviesForTable(`/libraries/${machineIdentifier}/${libraryKey}`, movieContainer, noMovieContainer, moviesTable);
}
function searchForMovies() {
movieSearchingContainer.show();
noMovieContainer.css({'display': 'none'});

View File

@@ -63,7 +63,7 @@
th:data-key="*{plexLibrary.key}"
th:data-machineIdentifier="*{instance.value.machineIdentifier}"
th:each="plexLibrary : *{instance.value.plexLibraries}"
th:onclick="switchPlexLibrary(this.getAttribute('data-machineIdentifier'), this.getAttribute('data-key'))"
onclick="switchPlexLibrary(this.getAttribute('data-machineIdentifier'), this.getAttribute('data-key'))"
th:text="(*{instance.value.friendlyName} + ' - ' + *{plexLibrary.title})"></a>
</div>
</div>
@@ -95,11 +95,11 @@
<table class="display" id="movies" style="width:100%">
<thead>
<tr>
<th>Movie</th>
<th hidden>Title</th>
<th hidden>Year</th>
<th hidden>Language</th>
<th hidden>Summary</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
</table>

View File

@@ -35,4 +35,9 @@ public class GapsServiceTest implements GapsService {
public void updatePlexSearch(PlexSearch plexSearch) {
}
@Override
public void nukePlexSearch() {
}
}

View File

@@ -14,3 +14,71 @@ export function spyOnAddEventListener(win) {
return addListener.apply(this, arguments);
};
}
export function libraryBefore() {
cy.request('PUT', '/nuke/jhouse')
.then((response) => {
expect(response.body).to.have.property('code', 30);
expect(response.body).to.have.property('reason', 'Nuke successful. All files deleted.');
});
cy.visit('/configuration', {onBeforeLoad: spyOnAddEventListener});
cy.get('#plexTab')
.click();
cy.get('#address')
.clear()
.type('174.58.64.67')
.should('have.value', '174.58.64.67');
cy.get('#port')
.clear()
.type('32400')
.should('have.value', '32400');
cy.get('#plexToken')
.clear()
.type('xPUCxLh4cTz8pcgorQQs')
.should('have.value', 'xPUCxLh4cTz8pcgorQQs');
cy.get('#addPlexServer')
.click();
cy.get('#plexSpinner')
.should('not.be.visible');
cy.get('#plexTestError')
.should('not.be.visible');
cy.get('#plexTestSuccess')
.should('not.be.visible');
cy.get('#plexSaveError')
.should('not.be.visible');
cy.get('#plexSaveSuccess')
.should('be.visible');
cy.get('#plexDeleteError')
.should('not.be.visible');
cy.get('#plexDeleteSuccess')
.should('not.be.visible');
cy.get('#plexDuplicateError')
.should('not.be.visible');
//Define card here
cy.get('.card-header')
.should('have.text', 'KnoxServer');
cy.get('.list-group > :nth-child(1)')
.should('have.text', 'Disney Classic Movies');
cy.get('.list-group > :nth-child(2)')
.should('have.text', 'Movies');
cy.visit('/libraries', {onBeforeLoad: spyOnAddEventListener});
}

View File

@@ -1,9 +1,9 @@
import {spyOnAddEventListener} from '../common.js';
import {libraryBefore} from '../common.js';
describe('Not Searched Yet Library Tests', function () {
it('Clean configuration page load', () => {
cy.visit('/libraries', {onBeforeLoad: spyOnAddEventListener});
before(libraryBefore);
it('Clean configuration page load', () => {
cy.get('#libraryTitle')
.contains('KnoxServer');

View File

@@ -0,0 +1,31 @@
import {libraryBefore} from '../common.js';
describe('Find owned movies', function () {
before(libraryBefore);
it('Find Disney Movies', () => {
cy.get('#dropdownMenuLink')
.click();
cy.get('[data-key="2"]')
.click();
cy.get('.card-body > .btn')
.click();
cy.get(':nth-child(1) > .sorting_1 > .card > .row > .col-md-10 > .card-body > .card-title')
.should('have.text', '101 Dalmatians II Patch\'s London Adventure (2003)');
cy.get('#dropdownMenuLink')
.click();
cy.get('[data-key="1"]')
.click();
cy.get('#dropdownMenuLink')
.click();
cy.get('[data-key="2"]')
.click();
});
});