Allow adding items to anime collection that are in the anime list
This commit is contained in:
parent
fe8b769cf2
commit
ecf09b5641
@ -9,7 +9,7 @@
|
||||
<div class="cssload-inner cssload-two"></div>
|
||||
<div class="cssload-inner cssload-three"></div>
|
||||
</div>
|
||||
<label for="search">Search for <?= $collection_type ?> by name: <input type="search" id="search" name="search" /></label>
|
||||
<label for="search-anime-collection">Search for <?= $collection_type ?> by name: <input type="search" id="search-anime-collection" name="search" /></label>
|
||||
<section id="series-list" class="media-wrap">
|
||||
</section>
|
||||
</section>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import _ from './anime-client.js'
|
||||
import { renderSearchResults } from './template-helpers.js'
|
||||
|
||||
const search = (query) => {
|
||||
const search = (query, isCollection = false) => {
|
||||
// Show the loader
|
||||
_.show('.cssload-loader');
|
||||
|
||||
@ -13,10 +13,11 @@ const search = (query) => {
|
||||
_.hide('.cssload-loader');
|
||||
|
||||
// Show the results
|
||||
_.$('#series-list')[ 0 ].innerHTML = renderSearchResults('anime', searchResults);
|
||||
_.$('#series-list')[ 0 ].innerHTML = renderSearchResults('anime', searchResults, isCollection);
|
||||
});
|
||||
};
|
||||
|
||||
// Anime list search
|
||||
if (_.hasElement('.anime #search')) {
|
||||
let prevRequest = null;
|
||||
|
||||
@ -34,6 +35,24 @@ if (_.hasElement('.anime #search')) {
|
||||
}));
|
||||
}
|
||||
|
||||
// Anime collection search
|
||||
if (_.hasElement('#search-anime-collection')) {
|
||||
let prevRequest = null;
|
||||
|
||||
_.on('#search-anime-collection', 'input', _.throttle(250, (e) => {
|
||||
const query = encodeURIComponent(e.target.value);
|
||||
if (query === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (prevRequest !== null) {
|
||||
prevRequest.abort();
|
||||
}
|
||||
|
||||
prevRequest = search(query, true);
|
||||
}));
|
||||
}
|
||||
|
||||
// Action to increment episode count
|
||||
_.on('body.anime.list', 'click', '.plus-one', (e) => {
|
||||
let parentSel = _.closestParent(e.target, 'article');
|
||||
|
@ -13,10 +13,11 @@ _.on('main', 'change', '.big-check', (e) => {
|
||||
*
|
||||
* @param {'anime'|'manga'} type
|
||||
* @param {Object} item
|
||||
* @param isCollection
|
||||
* @returns {String}
|
||||
*/
|
||||
function renderEditLink (type, item) {
|
||||
if (item.libraryEntry === null) {
|
||||
function renderEditLink (type, item, isCollection = false) {
|
||||
if (isCollection || item.libraryEntry === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
@ -38,13 +39,18 @@ function renderEditLink (type, item) {
|
||||
*
|
||||
* @param {'anime'|'manga'} type
|
||||
* @param {Object} data
|
||||
* @param {boolean} isCollection
|
||||
* @returns {String}
|
||||
*/
|
||||
export function renderSearchResults (type, data) {
|
||||
export function renderSearchResults (type, data, isCollection = false) {
|
||||
return data.map(item => {
|
||||
const titles = item.titles.join('<br />');
|
||||
const disabled = item.libraryEntry !== null ? 'disabled' : '';
|
||||
const editLink = renderEditLink(type, item);
|
||||
let disabled = item.libraryEntry !== null ? 'disabled' : '';
|
||||
const editLink = renderEditLink(type, item, isCollection);
|
||||
|
||||
if (isCollection) {
|
||||
disabled = '';
|
||||
}
|
||||
|
||||
return `
|
||||
<article class="media search ${disabled}">
|
||||
|
2
public/js/scripts.min.js
vendored
2
public/js/scripts.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
public/js/tables.min.js
vendored
2
public/js/tables.min.js
vendored
@ -1 +1 @@
|
||||
var LightTableSorter=function(){var th=null;var cellIndex=null;var order='';var text=function(row){return row.cells.item(cellIndex).textContent.toLowerCase();};var sort=function(a,b){var textA=text(a);var textB=text(b);var n=parseInt(textA,10);if(n){textA=n;textB=parseInt(textB,10);}if(textA>textB)return 1;if(textA<textB)return -1;return 0;};var toggle=function(){var c=order!=='sorting-asc'?'sorting-asc':'sorting-desc';th.className=(th.className.replace(order,'')+' '+c).trim();return order=c;};var reset=function(){th.classList.remove('sorting-asc','sorting-desc');th.classList.add('sorting');return order='';};var onClickEvent=function(e){if(th&&cellIndex!==e.target.cellIndex)reset();th=e.target;if(th.nodeName.toLowerCase()==='th'){cellIndex=th.cellIndex;var tbody=th.offsetParent.getElementsByTagName('tbody')[0];var rows=Array.from(tbody.rows);if(rows){rows.sort(sort);if(order==='sorting-asc')rows.reverse();toggle();tbody.innerHtml='';rows.forEach(function(row){tbody.appendChild(row);});}}};return {init:function(){var ths=document.getElementsByTagName('th');var results=[];for(var i=0,len=ths.length;i<len;i++){var th1=ths[i];th1.classList.add('sorting');results.push(th1.onclick=onClickEvent);}return results;}};}();LightTableSorter.init();
|
||||
var LightTableSorter=function(){var th=null;var cellIndex=null;var order='';var text=function(row){return row.cells.item(cellIndex).textContent.toLowerCase()};var sort=function(a,b){var textA=text(a);var textB=text(b);var n=parseInt(textA,10);if(n){textA=n;textB=parseInt(textB,10)}if(textA>textB)return 1;if(textA<textB)return -1;return 0};var toggle=function(){var c=order!=='sorting-asc'?'sorting-asc':'sorting-desc';th.className=(th.className.replace(order,'')+' '+c).trim();return order=c};var reset=function(){th.classList.remove('sorting-asc','sorting-desc');th.classList.add('sorting');return order=''};var onClickEvent=function(e){if(th&&cellIndex!==e.target.cellIndex)reset();th=e.target;if(th.nodeName.toLowerCase()==='th'){cellIndex=th.cellIndex;var tbody=th.offsetParent.getElementsByTagName('tbody')[0];var rows=Array.from(tbody.rows);if(rows){rows.sort(sort);if(order==='sorting-asc')rows.reverse();toggle();tbody.innerHtml='';rows.forEach(function(row){tbody.appendChild(row)})}}};return{init:function(){var ths=document.getElementsByTagName('th');var results=[];for(var i=0,len=ths.length;i<len;i++){var th=ths[i];th.classList.add('sorting');results.push(th.onclick=onClickEvent)}return results}}}();LightTableSorter.init()
|
@ -1 +1 @@
|
||||
{"version":3,"sources":["/var/www/htdocs/github.timshomepage.net/animeclient/frontEndSrc/js/base/sort-tables.js"],"sourcesContent":["const LightTableSorter = (() => {\n\tlet th = null;\n\tlet cellIndex = null;\n\tlet order = '';\n\tconst text = (row) => row.cells.item(cellIndex).textContent.toLowerCase();\n\tconst sort = (a, b) => {\n\t\tlet textA = text(a);\n\t\tlet textB = text(b);\n\t\tconst n = parseInt(textA, 10);\n\t\tif (n) {\n\t\t\ttextA = n;\n\t\t\ttextB = parseInt(textB, 10);\n\t\t}\n\t\tif (textA > textB) {\n\t\t\treturn 1;\n\t\t}\n\t\tif (textA < textB) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn 0;\n\t};\n\tconst toggle = () => {\n\t\tconst c = order !== 'sorting-asc' ? 'sorting-asc' : 'sorting-desc';\n\t\tth.className = (th.className.replace(order, '') + ' ' + c).trim();\n\t\treturn order = c;\n\t};\n\tconst reset = () => {\n\t\tth.classList.remove('sorting-asc', 'sorting-desc');\n\t\tth.classList.add('sorting');\n\t\treturn order = '';\n\t};\n\tconst onClickEvent = (e) => {\n\t\tif (th && (cellIndex !== e.target.cellIndex)) {\n\t\t\treset();\n\t\t}\n\t\tth = e.target;\n\t\tif (th.nodeName.toLowerCase() === 'th') {\n\t\t\tcellIndex = th.cellIndex;\n\t\t\tconst tbody = th.offsetParent.getElementsByTagName('tbody')[0];\n\t\t\tlet rows = Array.from(tbody.rows);\n\t\t\tif (rows) {\n\t\t\t\trows.sort(sort);\n\t\t\t\tif (order === 'sorting-asc') {\n\t\t\t\t\trows.reverse();\n\t\t\t\t}\n\t\t\t\ttoggle();\n\t\t\t\ttbody.innerHtml = '';\n\n\t\t\t\trows.forEach(row => {\n\t\t\t\t\ttbody.appendChild(row);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\treturn {\n\t\tinit: () => {\n\t\t\tlet ths = document.getElementsByTagName('th');\n\t\t\tlet results = [];\n\t\t\tfor (let i = 0, len = ths.length; i < len; i++) {\n\t\t\t\tlet th = ths[i];\n\t\t\t\tth.classList.add('sorting');\n\t\t\t\tresults.push(th.onclick = onClickEvent);\n\t\t\t}\n\t\t\treturn results;\n\t\t}\n\t};\n})();\n\nLightTableSorter.init();"],"names":[],"mappings":"IAAM,gBAAgB,gBACjB,EAAE,CAAG,IAAI,KACT,SAAS,CAAG,IAAI,KAChB,KAAK,QACH,IAAI,UAAI,GAAG,SAAK,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,WAAW,SACjE,IAAI,UAAI,CAAC,CAAE,CAAC,MACb,KAAK,CAAG,IAAI,CAAC,CAAC,MACd,KAAK,CAAG,IAAI,CAAC,CAAC,MACZ,CAAC,CAAG,QAAQ,CAAC,KAAK,CAAE,EAAE,KACxB,CAAC,EACJ,KAAK,CAAG,CAAC,CACT,KAAK,CAAG,QAAQ,CAAC,KAAK,CAAE,EAAE,MAEvB,KAAK,CAAG,KAAK,QACT,CAAC,IAEL,KAAK,CAAG,KAAK,QACT,EAAE,QAEH,CAAC,OAEH,MAAM,gBACL,CAAC,CAAG,KAAK,IAAK,WAAa,GAAG,WAAa,GAAG,YAAc,EAClE,EAAE,CAAC,SAAS,EAAI,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,MAAQ,CAAG,EAAG,CAAC,EAAE,IAAI,UACxD,KAAK,CAAG,CAAC,OAEX,KAAK,YACV,EAAE,CAAC,SAAS,CAAC,MAAM,EAAC,WAAa,GAAE,YAAc,GACjD,EAAE,CAAC,SAAS,CAAC,GAAG,EAAC,OAAS,UACnB,KAAK,UAEP,YAAY,UAAI,CAAC,KAClB,EAAE,EAAK,SAAS,GAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAC1C,KAAK,GAEN,EAAE,CAAG,CAAC,CAAC,MAAM,IACT,EAAE,CAAC,QAAQ,CAAC,WAAW,MAAO,EAAI,GACrC,SAAS,CAAG,EAAE,CAAC,SAAS,KAClB,KAAK,CAAG,EAAE,CAAC,YAAY,CAAC,oBAAoB,EAAC,KAAO,GAAE,CAAC,MACzD,IAAI,CAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAC5B,IAAI,EACP,IAAI,CAAC,IAAI,CAAC,IAAI,KACV,KAAK,IAAK,WAAa,EAC1B,IAAI,CAAC,OAAO,GAEb,MAAM,GACN,KAAK,CAAC,SAAS,IAEf,IAAI,CAAC,OAAO,UAAC,GAAG,EACf,KAAK,CAAC,WAAW,CAAC,GAAG,iBAMxB,IAAI,gBACC,GAAG,CAAG,QAAQ,CAAC,oBAAoB,EAAC,EAAI,OACxC,OAAO,YACF,CAAC,CAAG,CAAC,CAAE,GAAG,CAAG,GAAG,CAAC,MAAM,CAAE,CAAC,CAAG,GAAG,CAAE,CAAC,QACvC,GAAE,CAAG,GAAG,CAAC,CAAC,EACd,GAAE,CAAC,SAAS,CAAC,GAAG,EAAC,OAAS,GAC1B,OAAO,CAAC,IAAI,CAAC,GAAE,CAAC,OAAO,CAAG,YAAY,UAEhC,OAAO,QAKjB,gBAAgB,CAAC,IAAI"}
|
||||
{"version":3,"sources":["/var/www/htdocs/github.timshomepage.net/animeclient/frontEndSrc/js/base/sort-tables.js"],"sourcesContent":["const LightTableSorter = (() => {\n\tlet th = null;\n\tlet cellIndex = null;\n\tlet order = '';\n\tconst text = (row) => row.cells.item(cellIndex).textContent.toLowerCase();\n\tconst sort = (a, b) => {\n\t\tlet textA = text(a);\n\t\tlet textB = text(b);\n\t\tconst n = parseInt(textA, 10);\n\t\tif (n) {\n\t\t\ttextA = n;\n\t\t\ttextB = parseInt(textB, 10);\n\t\t}\n\t\tif (textA > textB) {\n\t\t\treturn 1;\n\t\t}\n\t\tif (textA < textB) {\n\t\t\treturn -1;\n\t\t}\n\t\treturn 0;\n\t};\n\tconst toggle = () => {\n\t\tconst c = order !== 'sorting-asc' ? 'sorting-asc' : 'sorting-desc';\n\t\tth.className = (th.className.replace(order, '') + ' ' + c).trim();\n\t\treturn order = c;\n\t};\n\tconst reset = () => {\n\t\tth.classList.remove('sorting-asc', 'sorting-desc');\n\t\tth.classList.add('sorting');\n\t\treturn order = '';\n\t};\n\tconst onClickEvent = (e) => {\n\t\tif (th && (cellIndex !== e.target.cellIndex)) {\n\t\t\treset();\n\t\t}\n\t\tth = e.target;\n\t\tif (th.nodeName.toLowerCase() === 'th') {\n\t\t\tcellIndex = th.cellIndex;\n\t\t\tconst tbody = th.offsetParent.getElementsByTagName('tbody')[0];\n\t\t\tlet rows = Array.from(tbody.rows);\n\t\t\tif (rows) {\n\t\t\t\trows.sort(sort);\n\t\t\t\tif (order === 'sorting-asc') {\n\t\t\t\t\trows.reverse();\n\t\t\t\t}\n\t\t\t\ttoggle();\n\t\t\t\ttbody.innerHtml = '';\n\n\t\t\t\trows.forEach(row => {\n\t\t\t\t\ttbody.appendChild(row);\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n\treturn {\n\t\tinit: () => {\n\t\t\tlet ths = document.getElementsByTagName('th');\n\t\t\tlet results = [];\n\t\t\tfor (let i = 0, len = ths.length; i < len; i++) {\n\t\t\t\tlet th = ths[i];\n\t\t\t\tth.classList.add('sorting');\n\t\t\t\tresults.push(th.onclick = onClickEvent);\n\t\t\t}\n\t\t\treturn results;\n\t\t}\n\t};\n})();\n\nLightTableSorter.init();"],"names":[],"mappings":"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"}
|
@ -82,7 +82,7 @@ final class AnimeCollection extends BaseController {
|
||||
{
|
||||
$queryParams = $this->request->getQueryParams();
|
||||
$query = $queryParams['query'];
|
||||
$this->outputJSON($this->animeModel->search($query), 200);
|
||||
$this->outputJSON($this->animeModel->search($query, inCollection: TRUE), 200);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,11 +71,19 @@ trait MediaTrait {
|
||||
* Search for anime by name
|
||||
*
|
||||
* @param string $name
|
||||
* @param bool $inCollection
|
||||
* @return array
|
||||
*/
|
||||
public function search(string $name): array
|
||||
public function search(string $name, bool $inCollection = false): array
|
||||
{
|
||||
return $this->kitsuModel->search($this->type, urldecode($name));
|
||||
$data = $this->kitsuModel->search($this->type, urldecode($name));
|
||||
|
||||
if ($inCollection)
|
||||
{
|
||||
// @TODO: allow filtering collection search by existing items
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user