diff --git a/bruno/VoD-System/Media/Clip Stream.bru b/bruno/VoD-System/Media/Clip Stream.bru index 1010702..7b9ba79 100644 --- a/bruno/VoD-System/Media/Clip Stream.bru +++ b/bruno/VoD-System/Media/Clip Stream.bru @@ -12,7 +12,9 @@ post { body:json { { - "duration": 60.0 + "duration": 60.0, + "title": "Hello", + "description": "my clip" } } diff --git a/bruno/VoD-System/Media/Save Stream Section.bru b/bruno/VoD-System/Media/Save Stream Section.bru index ef727ae..e3823a8 100644 --- a/bruno/VoD-System/Media/Save Stream Section.bru +++ b/bruno/VoD-System/Media/Save Stream Section.bru @@ -12,8 +12,10 @@ post { body:json { { - "startTime": "2026-06-21T17:27:00Z", - "endTime": "2026-06-21T17:28:00Z" + "startTime": "2026-07-01T21:09:00Z", + "endTime": "2026-07-01T21:12:00Z", + "title": "Hello", + "description": "my clip" } } diff --git a/bruno/VoD-System/VoDs/Delete VoD.bru b/bruno/VoD-System/VoDs/Delete VoD.bru new file mode 100644 index 0000000..5f50cfe --- /dev/null +++ b/bruno/VoD-System/VoDs/Delete VoD.bru @@ -0,0 +1,16 @@ +meta { + name: Delete VoD + type: http + seq: 4 +} + +delete { + url: {{base_url}}/vods/1 + body: none + auth: inherit +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/bruno/VoD-System/VoDs/Downloads/Get VoD Media.bru b/bruno/VoD-System/VoDs/Downloads/Get VoD Media.bru new file mode 100644 index 0000000..e775d54 --- /dev/null +++ b/bruno/VoD-System/VoDs/Downloads/Get VoD Media.bru @@ -0,0 +1,16 @@ +meta { + name: Get VoD Media + type: http + seq: 1 +} + +get { + url: {{base_url}}/vods/1/media + body: none + auth: inherit +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/bruno/VoD-System/VoDs/Downloads/Get VoD Thumbnail.bru b/bruno/VoD-System/VoDs/Downloads/Get VoD Thumbnail.bru new file mode 100644 index 0000000..f18a340 --- /dev/null +++ b/bruno/VoD-System/VoDs/Downloads/Get VoD Thumbnail.bru @@ -0,0 +1,15 @@ +meta { + name: Get VoD Thumbnail + type: http + seq: 2 +} + +get { + url: {{base_url}}/vods/1/thumbnail + body: none + auth: inherit +} + +settings { + encodeUrl: true +} diff --git a/bruno/VoD-System/VoDs/Downloads/folder.bru b/bruno/VoD-System/VoDs/Downloads/folder.bru new file mode 100644 index 0000000..343da03 --- /dev/null +++ b/bruno/VoD-System/VoDs/Downloads/folder.bru @@ -0,0 +1,8 @@ +meta { + name: Downloads + seq: 5 +} + +auth { + mode: inherit +} diff --git a/bruno/VoD-System/VoDs/Get VoD.bru b/bruno/VoD-System/VoDs/Get VoD.bru new file mode 100644 index 0000000..efea9df --- /dev/null +++ b/bruno/VoD-System/VoDs/Get VoD.bru @@ -0,0 +1,16 @@ +meta { + name: Get VoD + type: http + seq: 2 +} + +get { + url: {{base_url}}/vods/1 + body: none + auth: inherit +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/bruno/VoD-System/VoDs/Get all vods.bru b/bruno/VoD-System/VoDs/Get all vods.bru new file mode 100644 index 0000000..9a6bd97 --- /dev/null +++ b/bruno/VoD-System/VoDs/Get all vods.bru @@ -0,0 +1,11 @@ +meta { + name: Get all vods + type: http + seq: 1 +} + +get { + url: {{base_url}}/vods + body: none + auth: inherit +} diff --git a/bruno/VoD-System/VoDs/Update VoD.bru b/bruno/VoD-System/VoDs/Update VoD.bru new file mode 100644 index 0000000..64bd430 --- /dev/null +++ b/bruno/VoD-System/VoDs/Update VoD.bru @@ -0,0 +1,23 @@ +meta { + name: Update VoD + type: http + seq: 3 +} + +patch { + url: {{base_url}}/vods/1 + body: json + auth: inherit +} + +body:json { + { + "title": "My VoD", + "description": "" + } +} + +settings { + encodeUrl: true + timeout: 0 +} diff --git a/bruno/VoD-System/VoDs/folder.bru b/bruno/VoD-System/VoDs/folder.bru new file mode 100644 index 0000000..a320686 --- /dev/null +++ b/bruno/VoD-System/VoDs/folder.bru @@ -0,0 +1,8 @@ +meta { + name: VoDs + seq: 2 +} + +auth { + mode: inherit +} diff --git a/bruno/VoD-System/environments/dev.bru b/bruno/VoD-System/environments/dev.bru new file mode 100644 index 0000000..0b7d47d --- /dev/null +++ b/bruno/VoD-System/environments/dev.bru @@ -0,0 +1,8 @@ +vars { + base_url: http://http://server.tail3cd897.ts.net:8087/api/v1 + uuid: +} +vars:secret [ + google_client_id, + google_secret +] diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 3dd46ba..5ffc1d3 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -6,8 +6,11 @@ import ClipEdit from './pages/ClipEdit'; import Home from './pages/Home'; import {useEffect} from "react"; import MyClips from './pages/MyClips'; +import MyVods from './pages/MyVods'; import VideoPlayer from "./pages/VideoPlayer.tsx"; +import VodPlayer from "./pages/VodPlayer.tsx"; import EditClip from "./pages/EditClip.tsx"; +import EditVod from "./pages/EditVod.tsx"; import Profile from "./pages/Profile.tsx"; import { GoogleOAuthProvider } from '@react-oauth/google'; @@ -26,8 +29,11 @@ function App() { } /> } /> } /> + } /> } /> + } /> } /> + } /> } /> diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index ca409d6..bd3ecd2 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -1,6 +1,6 @@ import clsx from "clsx"; import SidebarButton from "./buttons/SidebarButton.tsx"; -import { Plus, Film, Home, User as UserIcon } from 'lucide-react'; +import { Plus, Film, Home, User as UserIcon, Video } from 'lucide-react'; import type {User} from "../utils/types.ts"; type props = { @@ -31,6 +31,7 @@ const Sidebar = ({user, className}: props) => {
} label="Clips" /> + } label="VoDs" />
)} diff --git a/frontend/src/components/video/VideoCard.tsx b/frontend/src/components/video/VideoCard.tsx index 084aafc..1561ceb 100644 --- a/frontend/src/components/video/VideoCard.tsx +++ b/frontend/src/components/video/VideoCard.tsx @@ -13,17 +13,21 @@ type VideoCardProps = { onEdit?: () => void, onDelete?: () => void, className?: string, + mediaApiPath?: string, + playerPath?: string, + itemLabel?: string, } const fallbackThumbnail = "../../../public/default_thumbnail.png"; const API_URL = import.meta.env.VITE_API_URL; -const VideoCard = ({ id, title, duration, createdAt, onEdit, onDelete, className }: VideoCardProps) => { +const VideoCard = ({ id, title, duration, createdAt, onEdit, onDelete, className, mediaApiPath = '/api/v1/clips', playerPath = '/video', itemLabel = 'clip' }: VideoCardProps) => { const [timeAgo, setTimeAgo] = useState(dateToTimeAgo(stringToDate(createdAt))); const [thumbnailAvailable, setThumbnailAvailable] = useState(true); const [menuOpen, setMenuOpen] = useState(false); const [confirmDelete, setConfirmDelete] = useState(false); const menuRef = useRef(null); + const thumbnailUrl = `${API_URL}${mediaApiPath}/${id}/thumbnail`; useEffect(() => { const interval = setInterval(() => { @@ -33,10 +37,10 @@ const VideoCard = ({ id, title, duration, createdAt, onEdit, onDelete, className }, [createdAt]); useEffect(() => { - isThumbnailAvailable(id) + isThumbnailAvailable(thumbnailUrl) .then(setThumbnailAvailable) .catch(() => setThumbnailAvailable(false)); - }, []); + }, [thumbnailUrl]); useEffect(() => { if (!menuOpen) return; @@ -57,11 +61,11 @@ const VideoCard = ({ id, title, duration, createdAt, onEdit, onDelete, className }; return ( - +
Video Thumbnail @@ -105,7 +109,7 @@ const VideoCard = ({ id, title, duration, createdAt, onEdit, onDelete, className )} {confirmDelete && (
-

Delete this clip?

+

Delete this {itemLabel}?

+ +

Edit VoD

+ + {loading ? ( +
Loading...
+ ) : ( + +
+ + setTitle(e.target.value)} + placeholder="Enter title" + className={inputClass} + /> +
+ +
+ +