Compare commits
11 commits
b42c9f1833
...
e04f567586
Author | SHA1 | Date | |
---|---|---|---|
e04f567586 | |||
e24dd3bc55 | |||
493372633c | |||
9be03784d2 | |||
843ef1395d | |||
41f12db8f0 | |||
84ed033a8d | |||
cfad242ab8 | |||
616646c0d9 | |||
9f6a7d38b5 | |||
d08b54d14a |
|
@ -3,9 +3,16 @@ import bodyParser from "body-parser";
|
|||
|
||||
const app: Express = express();
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
|
||||
next();
|
||||
});
|
||||
|
||||
app.use(bodyParser.urlencoded({
|
||||
extended: true
|
||||
}));
|
||||
app.use(bodyParser.json());
|
||||
|
||||
export { app };
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import fetch from "node-fetch";
|
|||
|
||||
import { API_BASE, API_TOKEN } from "../config.ts";
|
||||
|
||||
const API_ENDPOINT_WITH_PARAMS = "/Items?isMovie=true&isSeries=true&recursive=true&fields=ProviderIds&filters=&mediaTypes=Video&enableTotalRecordCount=true&enableImages=false";
|
||||
const API_ENDPOINT_WITH_PARAMS = "/Items?isMovie=true&isSeries=true&recursive=true&fields=ProviderIds&filters=&enableTotalRecordCount=true&enableImages=false";
|
||||
const API_URL = API_BASE + API_ENDPOINT_WITH_PARAMS;
|
||||
|
||||
export const fetchFromJellyfinApi = async () => {
|
||||
|
|
|
@ -99,7 +99,7 @@ h1:hover {
|
|||
flex-direction: column;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
max-width: calc(50% + 15px);
|
||||
max-width: calc(50% + 20px);
|
||||
|
||||
input {
|
||||
font-size: 17px;
|
||||
|
@ -116,22 +116,42 @@ h1:hover {
|
|||
|
||||
section {
|
||||
flex: 1;
|
||||
padding: 8px 0 0 8px;
|
||||
margin-left: 8px;
|
||||
display: flex;
|
||||
justify-content: space-evenly;text-align: left;
|
||||
justify-content: space-evenly;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.search-result-item-interaction {
|
||||
min-width: 20px;
|
||||
.search-result-item-icons {
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.search-result-item-text {
|
||||
flex: 1;
|
||||
.search-result-item-year {
|
||||
padding-left: 5px;
|
||||
|
||||
&:after {
|
||||
margin-left: 4px;
|
||||
content: "-";
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.search-result-item-title {
|
||||
flex: 1;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.search-result-item-action {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
width: 50px;
|
||||
height: 48px;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
background: linear-gradient(310deg, var(--jf-gradient-color-primary-dark), var(--jf-gradient-color-secondary-dark));
|
||||
padding: 0 6px;
|
||||
color: white;
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
|
59
fe/src/components/item/ItemStatusInLibrary.tsx
Normal file
59
fe/src/components/item/ItemStatusInLibrary.tsx
Normal file
|
@ -0,0 +1,59 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { getItemStatusInLibrary } from "../../helper/internalApiHelper";
|
||||
|
||||
const LIBRARY_STATUS_AVAILABLE = "ON_JF";
|
||||
const LIBRARY_STATUS_REQUESTED= "ON_WISHLIST";
|
||||
const LIBRARY_STATUS_MISSING = "NO_MATCH";
|
||||
|
||||
const statusIcons: { [key: string]: string } = {
|
||||
loading: "⏳",
|
||||
[LIBRARY_STATUS_AVAILABLE]: "✅",
|
||||
[LIBRARY_STATUS_REQUESTED]: "📋",
|
||||
[LIBRARY_STATUS_MISSING]: " ",
|
||||
};
|
||||
|
||||
interface ItemStatusInLibraryProps {
|
||||
imdbId: string,
|
||||
};
|
||||
|
||||
const FETCH_STATUS_DEFAULT = "FETCH_STATUS_DEFAULT";
|
||||
const FETCH_STATUS_STARTED_FETCHING = "FETCH_STATUS_STARTED_FETCHING";
|
||||
const FETCH_STATUS_DONE_FETCHING = "FETCH_STATUS_DONE_FETCHING";
|
||||
|
||||
const ItemStatusInLibrary = ({
|
||||
imdbId,
|
||||
}: ItemStatusInLibraryProps) => {
|
||||
const [fetchStatus , setFetchStatus] = useState(FETCH_STATUS_DEFAULT);
|
||||
const [libraryState, setLibraryState] = useState<string | null>(null);
|
||||
|
||||
console.log(`libraryState: ${imdbId}: `, libraryState);
|
||||
|
||||
const callBackFunc = (status: string) => {
|
||||
console.log("status", status)
|
||||
setFetchStatus(FETCH_STATUS_DONE_FETCHING);
|
||||
setLibraryState(status);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// begin fetching
|
||||
if (fetchStatus === FETCH_STATUS_DEFAULT) {
|
||||
setFetchStatus(FETCH_STATUS_STARTED_FETCHING)
|
||||
getItemStatusInLibrary(
|
||||
imdbId,
|
||||
callBackFunc,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
{fetchStatus === FETCH_STATUS_STARTED_FETCHING && statusIcons.loading}
|
||||
{fetchStatus === FETCH_STATUS_DONE_FETCHING
|
||||
&& !!libraryState
|
||||
&& Object.keys(statusIcons).includes(libraryState)
|
||||
&& statusIcons[libraryState]}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ItemStatusInLibrary
|
|
@ -1,16 +1,17 @@
|
|||
import ItemStatusInLibrary from "../item/ItemStatusInLibrary";
|
||||
|
||||
interface SearchResultItemProps {
|
||||
title: string,
|
||||
image: string,
|
||||
imdbId: string,
|
||||
year: string,
|
||||
type: string,
|
||||
type: "series" | "movie",
|
||||
clickHandler?: Function,
|
||||
}
|
||||
|
||||
const itemStatusInLibrary = {
|
||||
available: "✅",
|
||||
requested: "⏳",
|
||||
missing: " ",
|
||||
const itemTypeIcons = {
|
||||
movie: "📽",
|
||||
series: "📺",
|
||||
}
|
||||
|
||||
// todo add link to movie if available
|
||||
|
@ -32,15 +33,21 @@ const SearchResultItem = ({
|
|||
>
|
||||
<img src={image} alt={title} />
|
||||
<section>
|
||||
<div className="search-result-item-interaction">
|
||||
{Object.values(itemStatusInLibrary)[Math.floor(Math.random() * Object.values(itemStatusInLibrary).length)]}
|
||||
<div className="search-result-item-icons">
|
||||
<div>
|
||||
{itemTypeIcons[type]}
|
||||
</div>
|
||||
<ItemStatusInLibrary imdbId={imdbId} />
|
||||
</div>
|
||||
<span className="search-result-item-text">
|
||||
{year.substring(0, 4)} - {title}
|
||||
</span>
|
||||
<div className="search-result-item-action">
|
||||
🔗
|
||||
<div className="search-result-item-year">
|
||||
{year.substring(0, 4)}
|
||||
</div>
|
||||
<div className="search-result-item-title">
|
||||
{title.length > 40 ? `${title.substring(0, 40)}...` : title}
|
||||
</div>
|
||||
<button className="search-result-item-action">
|
||||
Wish
|
||||
</button>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
|
|
15
fe/src/helper/internalApiHelper.ts
Normal file
15
fe/src/helper/internalApiHelper.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
const buildApiUrl = (imdbId: string) => `http://localhost:1312/check/${imdbId}`;
|
||||
|
||||
|
||||
export const getItemStatusInLibrary = async (
|
||||
imdbId: string,
|
||||
callback: Function,
|
||||
) => {
|
||||
if (imdbId.length > 0) {
|
||||
fetch(buildApiUrl(imdbId))
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
callback(data.status);
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue