Add new slug property for videos.
These will in the future hold pre-generated slugs since some runs can have the same title and slugs are generated based on those titles. This also implements a default for when no slugs are set (as is the case for all videos right now) where the slug is still generated based on the title but a counter suffix is added for dupe titles.master
							parent
							
								
									5781966b91
								
							
						
					
					
						commit
						40cbd2ed6e
					
				|  | @ -89,6 +89,7 @@ class VideoList extends React.Component<VideoListProps, VideoListState> { | |||
|                 duration, | ||||
|                 fileName, | ||||
|                 title, | ||||
|                 slug, | ||||
|                 sourceVideoStart, | ||||
|                 sourceVideoEnd, | ||||
|               }, | ||||
|  | @ -100,6 +101,7 @@ class VideoList extends React.Component<VideoListProps, VideoListState> { | |||
|                 id={id} | ||||
|                 thumbnailServerURL={thumbnailServerURL} | ||||
|                 fileName={fileName} | ||||
|                 slug={slug} | ||||
|                 title={title} | ||||
|                 sourceVideoStart={sourceVideoStart} | ||||
|                 sourceVideoEnd={sourceVideoEnd} | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ export default function VideoListItem({ | |||
|   duration, | ||||
|   id, | ||||
|   fileName, | ||||
|   slug, | ||||
|   title, | ||||
|   sourceVideoStart, | ||||
|   sourceVideoEnd, | ||||
|  | @ -47,6 +48,7 @@ export default function VideoListItem({ | |||
|   duration: number | string, | ||||
|   id: string, | ||||
|   fileName: string, | ||||
|   slug: string, | ||||
|   title: string, | ||||
|   sourceVideoStart: number | string, | ||||
|   sourceVideoEnd: number | string, | ||||
|  | @ -77,7 +79,6 @@ export default function VideoListItem({ | |||
|     } | ||||
|     displayDuration = videoEnd - videoStart; | ||||
|   } | ||||
|   const titleUrlSlug = sanitizeTitle(title); | ||||
|   const listGroupItem = ( | ||||
|     <ListGroup.Item action> | ||||
|       <Media> | ||||
|  | @ -131,7 +132,7 @@ export default function VideoListItem({ | |||
|   ); | ||||
|   if (fileName) { | ||||
|     return ( | ||||
|       <Link passHref href="/[id]/[vslug]" as={`/${id}/${titleUrlSlug}`}> | ||||
|       <Link passHref href="/[id]/[vslug]" as={`/${id}/${slug}`}> | ||||
|         {listGroupItem} | ||||
|       </Link> | ||||
|     ); | ||||
|  |  | |||
|  | @ -115,7 +115,7 @@ const getProps = withSession(async (req, _res, { id, vslug }: VideoPlayerPagePar | |||
|         redirect: true, | ||||
|         id, | ||||
|         video, | ||||
|         vslug: sanitizeTitle(video.title), | ||||
|         vslug: video.slug, | ||||
|       }, | ||||
|     }; | ||||
|   } | ||||
|  | @ -132,13 +132,13 @@ const getProps = withSession(async (req, _res, { id, vslug }: VideoPlayerPagePar | |||
|         redirect: true, | ||||
|         id, | ||||
|         video: realVIndex, | ||||
|         vslug: sanitizeTitle(video.title), | ||||
|         vslug: video.slug, | ||||
|       }, | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   // Check if we can find any video with matching vslug
 | ||||
|   const video = videos.find(({ title }: { title: string }) => sanitizeTitle(title) === vslug); | ||||
|   const video = videos.find(({ slug }: VideoEntry) => slug === vslug); | ||||
|   if (!video) { | ||||
|     return { props: {} }; | ||||
|   } | ||||
|  |  | |||
|  | @ -15,8 +15,9 @@ | |||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
| 
 | ||||
| import { VideoList } from './datatypes/VideoList'; | ||||
| import { VideoEntry, VideoList } from './datatypes/VideoList'; | ||||
| import { VideoOnDemandIndex } from './datatypes/VideoOnDemandIdentifier'; | ||||
| import sanitizeTitle from './sanitizeTitle'; | ||||
| 
 | ||||
| const upstreamURL = process.env.UPSTREAM_URL; | ||||
| const upstreamDirectURL = process.env.UPSTREAM_DIRECT_URL || upstreamURL; | ||||
|  | @ -73,7 +74,26 @@ export async function getIndex(): Promise<VideoOnDemandIndex> { | |||
| } | ||||
| 
 | ||||
| export async function getVideos(id: string): Promise<VideoList> { | ||||
|   return getDirect(`videos/${id}.json`); | ||||
|   const result: VideoList = await getDirect(`videos/${id}.json`); | ||||
|   result.videos = result.videos.reduce((all: Array<VideoEntry>, { | ||||
|     slug, | ||||
|     title, | ||||
|     ...video | ||||
|   }: VideoEntry) => [ | ||||
|     ...all, | ||||
|     { | ||||
|       ...video, | ||||
|       title, | ||||
|       slug: typeof slug === 'string' | ||||
|         ? slug | ||||
|         : sanitizeTitle(title + ( | ||||
|           all.find(v => v.title === title) | ||||
|             ? ` ${all.filter(v => v.title === title).length + 1}` | ||||
|             : '' | ||||
|         )), | ||||
|     }, | ||||
|   ], []) | ||||
|   return result; | ||||
| } | ||||
| 
 | ||||
| export function getDownloadURL(id: string, fileName: string): string { | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ export interface VideoEntry { | |||
|   fileName:string | ||||
|   title: string | ||||
|   duration?: number | string, | ||||
|   slug: string, | ||||
|   sourceVideoURL: string | ||||
|   sourceVideoStart: number | string | ||||
|   sourceVideoEnd: number | string | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue