Skip to content

Allow admin to upload and manage program videos with optional PDF handouts#473

Merged
JoeProgrammer88 merged 7 commits intomainfrom
copilot/allow-admin-upload-videos
Mar 12, 2026
Merged

Allow admin to upload and manage program videos with optional PDF handouts#473
JoeProgrammer88 merged 7 commits intomainfrom
copilot/allow-admin-upload-videos

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 28, 2026

Enables admins to manage program videos (YouTube-hosted) via a full CRUD interface, replacing hardcoded video IDs in the view. Admins can also attach optional PDF handouts to each video, stored in Azure Blob Storage.

Data Layer

  • ProgramVideo model: Title, YouTubeVideoId, required; PdfLocation, PdfName, nullable
  • ProgramVideoDB: static CRUD helpers (AddAsync, GetAllAsync, GetVideoAsync, UpdateAsync, DeleteAsync)
  • EF migration: creates ProgramVideos table

Controller

  • ProgramVideosController is authorized at the class level with [Authorize(Roles = IdentityHelper.Admin)]; the public Index() action uses [AllowAnonymous] to remain accessible to all users
  • PDF upload on create/edit; replaces existing blob if a new file is provided; blob deleted on video delete

Views

  • Public Index.cshtml renders YouTube players and PDF attachments dynamically from DB (replaces hardcoded player IDs/video IDs); PDF handouts are styled as cards matching the Focus Newsletters page (Bootstrap icon, filename, and "Download PDF" button)
  • New admin views: ManageVideos, CreateVideo, EditVideo, DeleteVideo
  • CreateVideo and EditVideo forms auto-extract the YouTube video ID when a full YouTube URL is pasted (supports youtube.com/watch?v=, youtu.be/, /embed/, and /v/ formats); extraction logic and PDF file-size validation live in the shared wwwroot/js/program-videos.js file, referenced by both views
  • Admin nav: "Program Videos" added under the Members dropdown

Tests

  • ProgramVideoDBTests covers all CRUD operations

Copilot Summary

This PR adds a database-driven program video management system. Previously, videos were hardcoded into the Razor view. Admins can now add, edit, and delete YouTube videos with optional PDF attachments through a standard CRUD interface consistent with other admin features (newsletters, staff, board members). Authorization is enforced at the controller level, the public video listing page is open to all users, PDF handouts match the Focus Newsletters card style for consistency, and admin forms automatically extract a YouTube video ID from a pasted full URL for ease of use. Shared client-side logic (extractYouTubeId and checkFileSize) is consolidated in wwwroot/js/program-videos.js and referenced by both the Create and Edit views, eliminating duplication.

Original prompt

This section details on the original issue you should resolve

<issue_title>Allow admin to upload program videos</issue_title>
<issue_description>The client may upload more videos in the future and they should be allowed to upload videos as an admin. For now, we will assume YouTube hosting will continue to be used moving forward

Client would also like the ability to add a PDF attachment to the video (related handouts)</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits March 1, 2026 00:06
Co-authored-by: JoeProgrammer88 <7156063+JoeProgrammer88@users.noreply.github.com>
Co-authored-by: JoeProgrammer88 <7156063+JoeProgrammer88@users.noreply.github.com>
Copilot AI changed the title [WIP] Add feature to allow admin to upload program videos Allow admin to upload and manage program videos with optional PDF handouts Mar 1, 2026
@JoeProgrammer88 JoeProgrammer88 marked this pull request as ready for review March 12, 2026 14:42
@JoeProgrammer88 JoeProgrammer88 self-requested a review as a code owner March 12, 2026 14:42
Copy link
Copy Markdown
Member

@JoeProgrammer88 JoeProgrammer88 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user enters a full YouTube video URL, we should extract the id for them. This will be better for our non-tech savvy users

return View();
}

[Authorize(Roles = IdentityHelper.Admin)]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of authorizing Admin on these actions, let's do it at the controller level but then use AllowAnonymous on the Index action since it doesn't need authorization

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in ef0abcb. [Authorize(Roles = IdentityHelper.Admin)] is now on the controller class, and [AllowAnonymous] is applied to the Index action. All per-action [Authorize] attributes have been removed.

<h1>@video.Title</h1>
</div>
<div class="player" id="player-@video.ProgramVideoId"></div>
@if (!string.IsNullOrEmpty(video.PdfLocation))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's style the PDF's like we do on the Focus Newsletters view for consistency

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in ef0abcb. PDF attachments now render as Bootstrap cards matching the Focus Newsletters style — red PDF icon, filename as the card title, "PDF Handout" subtitle, and a full-width "Download PDF" button.

… URL extraction

Co-authored-by: JoeProgrammer88 <7156063+JoeProgrammer88@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 12, 2026

If the user enters a full YouTube video URL, we should extract the id for them. This will be better for our non-tech savvy users

Done in ef0abcb. Both the Create and Edit video forms now auto-extract the video ID when the user pastes a full YouTube URL (supports youtube.com/watch?v=, youtu.be/, /embed/, and /v/ formats). The extraction fires on field blur, so the ID is cleaned up before the form is submitted.

Copy link
Copy Markdown
Member

@JoeProgrammer88 JoeProgrammer88 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the JS script for extractYouTubeId is duplicated on the CreateVideo and EditVideo pages. Let's move that into a .js file and just reference it twice

Co-authored-by: JoeProgrammer88 <7156063+JoeProgrammer88@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 12, 2026

It looks like the JS script for extractYouTubeId is duplicated on the CreateVideo and EditVideo pages. Let's move that into a .js file and just reference it twice

Done in 4d47f8a. The shared logic is now in wwwroot/js/youtube-id-extractor.js and both CreateVideo.cshtml and EditVideo.cshtml reference it via <script src="~/js/youtube-id-extractor.js"></script>. The DOMContentLoaded listener in the file handles attaching the blur event to the input, so neither view needs any inline extraction code anymore.

Copy link
Copy Markdown
Member

@JoeProgrammer88 JoeProgrammer88 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On CreateVideo and EditVideo there is also a checkFileSize function that is duplicated. Let's name the youtube-id-extractor.js something more generic and move the checkFileSize() function to that file as well

…heckFileSize

Co-authored-by: JoeProgrammer88 <7156063+JoeProgrammer88@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 12, 2026

On CreateVideo and EditVideo there is also a checkFileSize function that is duplicated. Let's name the youtube-id-extractor.js something more generic and move the checkFileSize() function to that file...

Done in 807481a. youtube-id-extractor.js has been renamed to program-videos.js and now contains both extractYouTubeId and checkFileSize. Both CreateVideo.cshtml and EditVideo.cshtml reference it with a single <script src="~/js/program-videos.js"></script> — no inline script blocks remain in either view.

@JoeProgrammer88 JoeProgrammer88 merged commit 51528f8 into main Mar 12, 2026
1 check passed
@JoeProgrammer88 JoeProgrammer88 deleted the copilot/allow-admin-upload-videos branch March 12, 2026 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow admin to upload program videos

2 participants