Skip to content

Commit b86056c

Browse files
committed
Combine Discog/Vinyl API request.
1 parent 6e827a1 commit b86056c

File tree

10 files changed

+92
-90
lines changed

10 files changed

+92
-90
lines changed

frontend/public/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
{
2222
"src": "logo-mask-512.png",
2323
"type": "image/png",
24-
"sizes": "512x512",
24+
"sizes": "512x512"
2525
},
2626
{
2727
"src": "logo-mask-512.png",

frontend/src/api/discogs.ts

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ICollections, IIdentify, IProfile, IReleases } from "./interface"
1+
import { ICollections, IIdentify, IProfile, IReleases, VinylAPIImageMap } from "./interface"
22

33
const API_URL = "https://api.discogs.com"
44

@@ -35,6 +35,7 @@ export const getCollectionWants = async (
3535
): Promise<IReleases[]> => {
3636
let allReleases: IReleases[] = []
3737
let url: string | undefined = `${API_URL}/users/${username}/wants?per_page=100`
38+
const vinylURL = import.meta.env.VITE_VINYL_API_URL
3839

3940
while (url) {
4041
const response = await fetch(url, {
@@ -50,13 +51,44 @@ export const getCollectionWants = async (
5051

5152
const data: ICollections = await response.json()
5253

53-
const transformedData = {
54-
...data,
55-
// @ts-expect-error Cheating a bit - converting the reference to keep the same models.
56-
releases: data.wants,
54+
let imageMap: Record<number, VinylAPIImageMap> = {}
55+
if (vinylURL && vinylURL !== "") {
56+
try {
57+
const secondaryResponse = await fetch(`${vinylURL}/api/queue`, {
58+
method: "POST",
59+
headers: {
60+
"Content-Type": "application/json",
61+
},
62+
// @ts-expect-error Cheating a bit - converting the reference to keep the same models.
63+
body: JSON.stringify(data.wants.map((item) => item.basic_information.id) ?? []),
64+
})
65+
66+
if (secondaryResponse.ok) {
67+
const imageData = await secondaryResponse.json()
68+
69+
imageMap = imageData.available.reduce((acc: Record<number, VinylAPIImageMap>, record: any) => {
70+
acc[record.recordID] = { image: record.image, barcode: record.barcode }
71+
return acc
72+
}, {})
73+
} else {
74+
console.warn("Vinyl API response was not ok, skipping.")
75+
}
76+
} catch (error) {
77+
console.error("Vinyl API response hit an error, skipping.", error)
78+
}
5779
}
5880

59-
allReleases = [...allReleases, ...transformedData.releases]
81+
// @ts-expect-error Cheating a bit - converting the reference to keep the same models.
82+
const releasesExtraData = data.wants.map((release) => {
83+
const imageRecord = imageMap[release.basic_information.id] || { image: null, barcode: null }
84+
return {
85+
...release,
86+
image_base64: imageRecord.image,
87+
barcode: imageRecord.barcode,
88+
}
89+
})
90+
91+
allReleases = [...allReleases, ...releasesExtraData]
6092

6193
if (onProgress) {
6294
onProgress(data.pagination.page, data.pagination.pages)
@@ -76,6 +108,7 @@ export const getCollectionReleases = async (
76108
): Promise<IReleases[]> => {
77109
let allReleases: IReleases[] = []
78110
let url: string | undefined = `${API_URL}/users/${username}/collection/folders/0/releases?per_page=100`
111+
const vinylURL = import.meta.env.VITE_VINYL_API_URL
79112

80113
while (url) {
81114
const response = await fetch(url, {
@@ -90,7 +123,43 @@ export const getCollectionReleases = async (
90123
}
91124

92125
const data: ICollections = await response.json()
93-
allReleases = [...allReleases, ...data.releases]
126+
127+
let imageMap: Record<number, VinylAPIImageMap> = {}
128+
if (vinylURL && vinylURL !== "") {
129+
try {
130+
const secondaryResponse = await fetch(`${vinylURL}/api/queue`, {
131+
method: "POST",
132+
headers: {
133+
"Content-Type": "application/json",
134+
},
135+
body: JSON.stringify(data.releases.map((item) => item.basic_information.id) ?? []),
136+
})
137+
138+
if (secondaryResponse.ok) {
139+
const imageData = await secondaryResponse.json()
140+
141+
imageMap = imageData.available.reduce((acc: Record<number, VinylAPIImageMap>, record: any) => {
142+
acc[record.recordID] = { image: record.image, barcode: record.barcode }
143+
return acc
144+
}, {})
145+
} else {
146+
console.warn("Vinyl API response was not ok, skipping.")
147+
}
148+
} catch (error) {
149+
console.error("Vinyl API response hit an error, skipping.", error)
150+
}
151+
}
152+
153+
const releasesExtraData = data.releases.map((release) => {
154+
const imageRecord = imageMap[release.basic_information.id] || { image: null, barcode: null }
155+
return {
156+
...release,
157+
image_base64: imageRecord.image,
158+
barcode: imageRecord.barcode,
159+
}
160+
})
161+
162+
allReleases = [...allReleases, ...(releasesExtraData as IReleases[])]
94163

95164
if (onProgress) {
96165
onProgress(data.pagination.page, data.pagination.pages)

frontend/src/api/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export { getCollectionReleases, getCollectionWants, getMe, getProfile } from "./discogs"
2-
export { postVinylQueue } from "./vinyl"
32
export type {
43
ICollections,
54
IWants,
@@ -9,4 +8,5 @@ export type {
98
IReleases,
109
IVinylResponse,
1110
IAvailableItem,
11+
VinylAPIImageMap,
1212
} from "./interface"

frontend/src/api/interface.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ export interface IReleases {
5757
genres: string[]
5858
styles: string[]
5959
}
60+
image_base64?: string
61+
barcode?: string
6062
}
6163

6264
export interface ICollections {
@@ -113,3 +115,8 @@ export interface IVinylResponse {
113115
available: IAvailableItem[]
114116
queued: number[]
115117
}
118+
119+
export interface VinylAPIImageMap {
120+
image?: string
121+
barcode?: string
122+
}

frontend/src/api/vinyl.ts

Lines changed: 0 additions & 23 deletions
This file was deleted.

frontend/src/components/AlbumGrid.tsx

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { IonCol, IonGrid, IonRow, IonText } from "@ionic/react"
2-
import { useQuery } from "@tanstack/react-query"
3-
import { IReleases, IVinylResponse, postVinylQueue } from "../api"
4-
import { findLocalImageById, splitRecordsByArtist, splitRecordsByLabel, splitRecordsByYear } from "../utils"
2+
import { IReleases } from "../api"
3+
import { splitRecordsByArtist, splitRecordsByLabel, splitRecordsByYear } from "../utils"
54
import "./AlbumGrid.css"
65

76
interface AlbumProps {
@@ -33,13 +32,6 @@ interface CollectionProps {
3332
}
3433

3534
const AlbumGrid: React.FC<CollectionProps> = ({ data, sort = "none", type, username = "", onClickAlbum }) => {
36-
const imageData = useQuery<IVinylResponse | undefined>({
37-
queryKey: [`${username}${type}images`],
38-
queryFn: () => postVinylQueue(data?.map((item) => item.basic_information.id) ?? []),
39-
staleTime: 1000 * 60 * 60 * 24, // 24 hours
40-
enabled: data !== undefined,
41-
})
42-
4335
let displayData: [string, IReleases[]][] = []
4436
let labelText = ""
4537

@@ -60,10 +52,6 @@ const AlbumGrid: React.FC<CollectionProps> = ({ data, sort = "none", type, usern
6052
break
6153
}
6254

63-
if (imageData.isLoading) {
64-
return <></>
65-
}
66-
6755
return (
6856
<>
6957
{displayData.map((options, index) => (
@@ -72,16 +60,11 @@ const AlbumGrid: React.FC<CollectionProps> = ({ data, sort = "none", type, usern
7260
<IonGrid>
7361
<IonRow>
7462
{options[1].map((album, index) => {
75-
let image = undefined
76-
if (imageData.data) {
77-
image = findLocalImageById(imageData.data?.available, album.basic_information.id)
78-
}
79-
8063
return (
8164
<AlbumGridEntry
8265
key={index}
8366
album={album}
84-
staticImage={image}
67+
staticImage={album.image_base64}
8568
index={index}
8669
onClickAlbum={onClickAlbum}
8770
/>

frontend/src/components/AlbumList.tsx

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { IonAvatar, IonChip, IonIcon, IonItem, IonLabel, IonList, IonListHeader, IonText } from "@ionic/react"
22
import { disc } from "ionicons/icons"
3-
import { useQuery } from "@tanstack/react-query"
4-
import { IReleases, IVinylResponse, postVinylQueue } from "../api"
5-
import { findLocalImageById } from "../utils"
3+
import { IReleases } from "../api"
64
import "./AlbumList.css"
75

86
interface Props {
@@ -14,13 +12,6 @@ interface Props {
1412
}
1513

1614
const AlbumList: React.FC<Props> = ({ data, username = "", title = undefined, type, onClickAlbum }) => {
17-
const imageData = useQuery<IVinylResponse | undefined>({
18-
queryKey: [`${username}${type}images`],
19-
queryFn: () => postVinylQueue(data?.map((item) => item.basic_information.id) ?? []),
20-
staleTime: 1000 * 60 * 60 * 24, // 24 hours
21-
enabled: data !== undefined,
22-
})
23-
2415
return (
2516
<IonList lines="full">
2617
{title && (
@@ -29,15 +20,10 @@ const AlbumList: React.FC<Props> = ({ data, username = "", title = undefined, ty
2920
</IonListHeader>
3021
)}
3122
{data.map((album, index) => {
32-
let image = undefined
33-
if (imageData.data) {
34-
image = findLocalImageById(imageData.data?.available, album.basic_information.id)
35-
}
36-
3723
return (
3824
<IonItem key={index} className="album-list-item" onClick={() => onClickAlbum(album)}>
3925
<IonAvatar aria-hidden="true" slot="start">
40-
<img alt="" src={image ? image : album.basic_information.thumb} />
26+
<img alt="" src={album.image_base64 ? album.image_base64 : album.basic_information.thumb} />
4127
</IonAvatar>
4228
<IonLabel>
4329
<strong>{album.basic_information.title}</strong>

frontend/src/modal/ViewAlbumDetails.tsx

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ import {
1010
IonLabel,
1111
IonList,
1212
} from "@ionic/react"
13-
import { useQuery } from "@tanstack/react-query"
14-
import { IReleases, IVinylResponse } from "../api"
15-
import { findLocalImageById } from "../utils"
13+
import { IReleases } from "../api"
1614

1715
interface DisplayProps {
1816
album: IReleases
@@ -23,17 +21,6 @@ interface DisplayProps {
2321
}
2422

2523
const ViewAlbumDetails: React.FC<DisplayProps> = ({ album, username = "", type, open, onClose }) => {
26-
const imageData = useQuery<IVinylResponse | undefined>({
27-
queryKey: [`${username}${type}images`],
28-
staleTime: 1000 * 60 * 60 * 24, // 24 hours
29-
enabled: false,
30-
})
31-
32-
let image = undefined
33-
if (imageData.data) {
34-
image = findLocalImageById(imageData.data?.available, album.basic_information.id)
35-
}
36-
3724
return (
3825
<IonModal isOpen={open}>
3926
<IonHeader>
@@ -46,7 +33,7 @@ const ViewAlbumDetails: React.FC<DisplayProps> = ({ album, username = "", type,
4633
</IonHeader>
4734
<IonContent className="ion-padding">
4835
<div style={{ display: "flex", justifyContent: "center" }}>
49-
<img src={image ? image : album.basic_information.thumb} alt="" />
36+
<img src={album.image_base64 ? album.image_base64 : album.basic_information.thumb} alt="" />
5037
</div>
5138
<IonList inset>
5239
<IonItem>

frontend/src/utils/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
export { splitRecordsByYear, splitRecordsByLabel, splitRecordsByArtist } from "./collectionSort"
2-
export { findLocalImageById } from "./search"
32

43
/**
54
* Formats a number of bytes as a human-readable string, with the size unit automatically selected based on the size of the number.

frontend/src/utils/search.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)