Skip to content

Commit 8a9777b

Browse files
committed
feat: playlist order
1 parent 5c23d3f commit 8a9777b

File tree

6 files changed

+135
-26
lines changed

6 files changed

+135
-26
lines changed

prisma/schema.prisma

+11
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,24 @@ model Video {
239239
shows ShowVideo[]
240240
}
241241

242+
enum PlaylistOrder {
243+
// Use playlist order as it is on YouTube
244+
YouTubeAsc
245+
// Reverse playlist order as it is on YouTube
246+
YouTubeDesc
247+
// Order playlist by video publish date accordingly
248+
VideoPublishedAtAsc
249+
VideoPublishedAtDesc
250+
}
251+
242252
model Playlist {
243253
id String @id @default(uuid())
244254
title String
245255
description String? @db.Text
246256
created_at DateTime @default(now())
247257
slug String @unique
248258
unlisted Boolean? @default(false)
259+
order PlaylistOrder @default(YouTubeAsc)
249260
videos PlaylistOnVideo[]
250261
}
251262

src/lib/videos/playlistOrderBy.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { PlaylistOrder } from '@prisma/client';
2+
3+
export default {
4+
[PlaylistOrder.YouTubeAsc]: {
5+
order: 'asc'
6+
},
7+
[PlaylistOrder.YouTubeDesc]: {
8+
order: 'desc'
9+
},
10+
[PlaylistOrder.VideoPublishedAtDesc]: {
11+
video: {
12+
published_at: 'desc'
13+
}
14+
},
15+
[PlaylistOrder.VideoPublishedAtAsc]: {
16+
video: {
17+
published_at: 'asc'
18+
}
19+
}
20+
} as const;

src/routes/(site)/admin/videos/[playlist_id]/+page.server.ts

+31-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { PlaylistOrder } from '@prisma/client';
2+
import type { Actions } from '@sveltejs/kit';
3+
14
export const load = async ({ params, locals }) => {
25
const { playlist_id } = params;
36

@@ -29,9 +32,12 @@ export const load = async ({ params, locals }) => {
2932
const videos = playlist.videos.map((item) => item.video);
3033
console.log('videos', videos);
3134

35+
const playlistOrderTypes = Object.keys(PlaylistOrder);
36+
3237
return {
3338
playlist,
34-
videos
39+
videos,
40+
playlistOrderTypes
3541
};
3642
} catch (error) {
3743
console.error('Error fetching playlist videos:', error);
@@ -41,3 +47,27 @@ export const load = async ({ params, locals }) => {
4147
};
4248
}
4349
};
50+
51+
export const actions: Actions = {
52+
updatePlaylist: async function updatePlaylist({ locals, params }) {
53+
const { playlist_id } = params;
54+
const { playlistOrder } = locals.form_data;
55+
if (!playlist_id || !playlistOrder) {
56+
return {
57+
error: 'Missing data',
58+
status: 500
59+
};
60+
}
61+
await locals.prisma.playlist.update({
62+
where: {
63+
id: playlist_id
64+
},
65+
data: {
66+
order: locals.form_data.playlistOrder as PlaylistOrder
67+
}
68+
});
69+
return {
70+
message: 'Updated'
71+
};
72+
}
73+
};

src/routes/(site)/admin/videos/[playlist_id]/+page.svelte

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
<!-- src/routes/playlists/[playlist_id]/+page.svelte -->
22
<script lang="ts">
33
import AdminSearch from '$/lib/AdminSearch.svelte';
4+
import { enhance } from '$app/forms';
5+
import { form_action } from '$lib/form_action';
46
import type { PageData } from './$types';
57
68
export let data: PageData;
7-
const { playlist, videos } = data;
9+
const { playlist, videos, playlistOrderTypes } = data;
810
911
let search_text = '';
1012
@@ -13,6 +15,20 @@
1315

1416
<h1>{playlist?.title}</h1>
1517

18+
{#if playlistOrderTypes}
19+
<form use:enhance={form_action({ message: 'Update Playlist Order' })} action="?/updatePlaylist" method="POST">
20+
<label>
21+
Order Playlist
22+
<select name="playlistOrder" value={playlist?.order}>
23+
{#each playlistOrderTypes as orderType}
24+
<option>{orderType}</option
25+
{/each}
26+
</select>
27+
</label>
28+
<button>Update</button>
29+
</form>
30+
{/if}
31+
1632
<div>
1733
<AdminSearch bind:text={search_text} />
1834

@@ -42,3 +58,9 @@
4258
</table>
4359
</div>
4460
</div>
61+
62+
<style>
63+
form {
64+
margin: 1rem;
65+
}
66+
</style>

src/routes/(site)/videos/+page.server.ts

+29-16
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,42 @@
1+
import playListOrderBy from '$lib/videos/playlistOrderBy';
2+
13
export const load = async function ({ locals }) {
2-
const playlists = await locals.prisma.playlist.findMany({
4+
const playlistMeta = await locals.prisma.playlist.findMany({
35
orderBy: {
46
created_at: 'desc'
57
},
6-
include: {
7-
videos: {
8-
take: 3,
9-
orderBy: {
10-
order: 'asc'
8+
select: {
9+
id: true,
10+
order: true
11+
}
12+
});
13+
const playlists = await Promise.all(
14+
playlistMeta.map(async (playlist) => {
15+
return locals.prisma.playlist.findFirst({
16+
where: {
17+
id: playlist.id
1118
},
1219
include: {
13-
video: true
20+
videos: {
21+
take: 3,
22+
orderBy: playListOrderBy[playlist.order],
23+
include: {
24+
video: true
25+
}
26+
},
27+
_count: {
28+
select: {
29+
videos: true
30+
}
31+
}
1432
}
15-
},
16-
_count: {
17-
select: {
18-
videos: true
19-
}
20-
}
21-
}
22-
});
33+
});
34+
})
35+
);
2336

2437
const playlists_with_item_count = playlists.map((playlist) => ({
2538
...playlist,
26-
item_count: playlist._count.videos
39+
item_count: playlist!._count.videos
2740
}));
2841
return {
2942
playlists: playlists_with_item_count

src/routes/(site)/videos/[p_slug]/+page.server.ts

+21-8
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,37 @@
1+
import playlistOrderBy from '$/lib/videos/playlistOrderBy.js';
2+
13
export const load = async function ({ locals, params }) {
24
const { p_slug } = params;
3-
const playlist = await locals.prisma.playlist.findUnique({
5+
const playlistMeta = await locals.prisma.playlist.findUnique({
46
where: { slug: p_slug },
5-
include: {
6-
videos: {
7-
include: {
8-
video: true
9-
}
10-
}
7+
select: {
8+
id: true,
9+
order: true
1110
}
1211
});
1312

14-
if (!playlist) {
13+
if (!playlistMeta) {
1514
// Playlist not found
1615
return {
1716
status: 404,
1817
error: 'Playlist not found'
1918
};
2019
}
2120

21+
const playlist = await locals.prisma.playlist.findUnique({
22+
where: {
23+
id: playlistMeta.id
24+
},
25+
include: {
26+
videos: {
27+
include: {
28+
video: true
29+
},
30+
orderBy: playlistOrderBy[playlistMeta.order]
31+
}
32+
}
33+
});
34+
2235
return {
2336
playlist
2437
};

0 commit comments

Comments
 (0)