feat(config): add media column to consolidate media content sources

This commit is contained in:
Prad Nukala
2026-06-29 13:32:44 -04:00
parent 643c142b06
commit 9706abe9ad
6 changed files with 305 additions and 995 deletions
+293
View File
@@ -0,0 +1,293 @@
# Media — single column: Continue Watching, then Latest Movies, then Latest Shows.
# One Jellyfin template shared across all three via the &jellyfin-tpl anchor.
- size: full
widgets:
- type: custom-api
title: Continue Watching
frameless: true
cache: 5m
options:
base-url: ${JELLYFIN_URL}
api-key: ${JELLYFIN_KEY}
user-name: "prad"
mode: "resume"
item-count: "12"
small-column: false
show-thumbnail: true
thumbnail-aspect-ratio: "landscape"
template: &jellyfin-tpl |
{{/* Required config options */}}
{{ $baseURL := .Options.StringOr "base-url" "" }}
{{ $apiKey := .Options.StringOr "api-key" "" }}
{{ $userName := .Options.StringOr "user-name" "" }}
{{/* Required config options for "latest" mode */}}
{{ $libraryName := .Options.StringOr "library-name" "" }}
{{/* Optional config options */}}
{{ $mode := .Options.StringOr "mode" "latest" }}
{{ $itemCount := .Options.StringOr "item-count" "10" }}
{{ $mediaTypes := .Options.StringOr "media-types" "Movie,Episode,MusicAlbum" }}
{{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
{{ $isSmallColumn:= .Options.BoolOr "small-column" false }}
{{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
{{ $showProgressBar := .Options.BoolOr "progress-bar" true }}
{{/* Error message template */}}
{{ define "errorMsg" }}
<div class="widget-error-header">
<div class="color-negative size-h3">ERROR</div>
<svg class="widget-error-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"></path>
</svg>
</div>
<p class="break-all">{{ . }}</p>
{{ end }}
{{/* Check required fields */}}
{{ if or (eq $baseURL "") (eq $apiKey "") (eq $userName "") (eq $mode "") (and (eq $mode "latest") (eq $libraryName "")) }}
{{ template "errorMsg" "Some required options are not set." }}
{{ else }}
{{/* Fetch user ID */}}
{{ $userID := "" }}
{{ $usersCall := newRequest (print $baseURL "/Users")
| withParameter "api_key" $apiKey
| withHeader "Accept" "application/json"
| getResponse }}
{{ range $i, $user := $usersCall.JSON.Array "" }}
{{ if eq ($user.String "Name") $userName }}
{{ $userID = $user.String "Id" }}
{{ break }}
{{ end }}
{{ end }}
{{ if eq $userID "" }}
{{ template "errorMsg" (printf "User '%s' not found." $userName) }}
{{ else }}
{{ $items := "" }}
{{ if eq $mode "latest" }}
{{/* Fetch library ID */}}
{{ $libraryID := "" }}
{{ $userViewsCall := newRequest (print $baseURL "/UserViews")
| withParameter "api_key" $apiKey
| withParameter "userId" $userID
| withHeader "Accept" "application/json"
| getResponse }}
{{ range $i, $item := $userViewsCall.JSON.Array "Items" }}
{{ if eq ($item.String "Name") $libraryName }}
{{ $libraryID = $item.String "Id" }}
{{ break }}
{{ end }}
{{ end }}
{{ if eq $libraryID "" }}
{{ template "errorMsg" (printf "Library '%s' not found." $libraryName) }}
{{ else }}
{{/* Fetch latest items */}}
{{ $latestCall := newRequest (print $baseURL "/Users/" $userID "/Items/Latest")
| withParameter "api_key" $apiKey
| withParameter "Limit" $itemCount
| withParameter "ParentId" $libraryID
| withParameter "IncludeItemTypes" $mediaTypes
| withParameter "GroupItems" "true"
| withHeader "Accept" "application/json"
| getResponse }}
{{ $items = $latestCall.JSON.Array "" }}
{{ end }}
{{ else if eq $mode "nextup" }}
{{/* Fetch next up items */}}
{{ $nextUpCall := newRequest (print $baseURL "/Shows/NextUp")
| withParameter "api_key" $apiKey
| withParameter "UserId" $userID
| withParameter "Limit" $itemCount
| withParameter "EnableResumable" "true"
| withHeader "Accept" "application/json"
| getResponse }}
{{ $items = $nextUpCall.JSON.Array "Items" }}
{{ else if eq $mode "resume" }}
{{/* Fetch in-progress (continue watching) items — movies and episodes */}}
{{ $resumeCall := newRequest (print $baseURL "/Users/" $userID "/Items/Resume")
| withParameter "api_key" $apiKey
| withParameter "Limit" $itemCount
| withParameter "MediaTypes" "Video"
| withHeader "Accept" "application/json"
| getResponse }}
{{ $items = $resumeCall.JSON.Array "Items" }}
{{ else }}
{{ template "errorMsg" "Unknown mode, expected 'latest', 'nextup' or 'resume'" }}
{{ end }}
{{ if eq (len $items) 0 }}
<p>No items found, start streaming something!</p>
{{ else }}
{{/* Display the item carousel */}}
<div class="carousel-container show-right-cutoff">
<div class="cards-horizontal carousel-items-container">
{{ range $n, $item := $items }}
{{/* Common item variables */}}
{{ $mediaType := $item.String "Type" }}
{{ $title := $item.String "Name" }}
{{ $itemID := $item.String "Id" }}
{{/* Media type specific variables */}}
{{ $seriesTitle := "" }}
{{ $artist := "" }}
{{ $seriesID := "" }}
{{ $season := "" }}
{{ $episode := "" }}
{{ $playPercentage := "" }}
{{ $unwatchedEpisodeCount := "" }}
{{ if eq $mediaType "Movie" }}
{{ if $item.Exists "UserData.PlayedPercentage" }}
{{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
{{ end }}
{{ else if eq $mediaType "Series" }}
{{ $unwatchedEpisodeCount = $item.Int "UserData.UnplayedItemCount" }}
{{ else if eq $mediaType "Episode" }}
{{ $unwatchedEpisodeCount = 1 }}
{{ $seriesTitle = $item.String "SeriesName" }}
{{ $seriesID = $item.String "SeriesId" }}
{{ $season = $item.Int "ParentIndexNumber" }}
{{ $episode = $item.Int "IndexNumber" }}
{{ if $item.Exists "UserData.PlayedPercentage" }}
{{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
{{ end }}
{{/* For latest always refer to the series not individual episodes */}}
{{ if eq $mode "latest" }}
{{ $itemID = $seriesID }}
{{ $title = $seriesTitle }}
{{ end }}
{{ else if eq $mediaType "MusicAlbum" }}
{{ $artist = $item.String "AlbumArtist" }}
{{ end }}
{{ $linkURL := print $baseURL "/web/#/details?id=" $itemID }}
{{ $thumbURL := concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
<a class="card widget-content-frame" href="{{ $linkURL | safeURL }}">
{{ if $showThumbnail }}
<div style="position: relative;">
<img src="{{ $thumbURL | safeURL }}"
alt="{{ $title }} thumbnail"
loading="lazy"
class="media-server-thumbnail shrink-0"
style="
object-fit: cover;
border-radius: var(--border-radius) var(--border-radius) 0 0;
width: 100%;
display: block;
{{ if eq $thumbAspectRatio "square" }}aspect-ratio: 1;
{{ else if eq $thumbAspectRatio "portrait" }}aspect-ratio: 2/3;
{{ else if eq $thumbAspectRatio "landscape" }}aspect-ratio: 16/9;
{{ else }}aspect-ratio: initial;
{{ end }}
"
/>
{{ if and ($showProgressBar) (not (eq $playPercentage "")) }}
<div style="
position: absolute;
bottom: 8px;
left: 8px;
right: 8px;
height: 6px;
border-radius: var(--border-radius);
overflow: hidden;
background-color: rgba(255, 255, 255, 0.2);
">
<div style="
width: {{ print $playPercentage "%" }};
height: 100%;
border-radius: var(--border-radius) 0 0 var(--border-radius);
background-color: var(--color-primary)
"></div>
</div>
{{ end }}
</div>
{{ end }}
<div class="grow padding-inline-widget margin-top-10 margin-bottom-10">
<ul class="flex flex-column justify-evenly margin-bottom-3 {{ if $isSmallColumn }}size-h6{{ end }}" style="height: 100%;">
{{ if eq $mode "latest" }}
{{ if or (eq $mediaType "Series") (eq $mediaType "Episode") }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary shrink-0">{{ $unwatchedEpisodeCount }}</li>
<li class="text-truncate">{{ $title }}</li>
</ul>
{{ else if eq $mediaType "MusicAlbum" }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary text-truncate">{{ $artist }}</li>
<li class="text-truncate">{{ $title }}</li>
</ul>
{{ else }}
<li class="text-truncate">{{ $title }}</li>
{{ end }}
{{ else }}
{{/* nextup + resume: show S/E for episodes, plain title for movies */}}
{{ if eq $mediaType "Episode" }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary shrink-0">S{{ $season }}E{{ $episode }}</li>
<li class="text-truncate">{{ $seriesTitle }}</li>
</ul>
<li class="text-truncate">{{ $title }}</li>
{{ else }}
<li class="text-truncate">{{ $title }}</li>
{{ end }}
{{ end }}
</ul>
</div>
</a>
{{ end }}
</div>
</div>
{{ end }}
{{ end }}
{{ end }}
- type: custom-api
title: Latest Movies
frameless: true
cache: 5m
options:
base-url: ${JELLYFIN_URL}
api-key: ${JELLYFIN_KEY}
user-name: "prad"
library-name: "Movies"
mode: "latest"
item-count: "12"
small-column: false
show-thumbnail: true
thumbnail-aspect-ratio: "portrait"
template: *jellyfin-tpl
- type: custom-api
title: Latest Shows
frameless: true
cache: 5m
options:
base-url: ${JELLYFIN_URL}
api-key: ${JELLYFIN_KEY}
user-name: "prad"
library-name: "TV"
mode: "latest"
item-count: "12"
small-column: false
show-thumbnail: true
thumbnail-aspect-ratio: "portrait"
template: *jellyfin-tpl
-492
View File
@@ -1,492 +0,0 @@
- size: full
widgets:
- type: custom-api
title: Latest Movies
frameless: true
cache: 5m
options:
base-url: http://nukala.local:8096
api-key: df9e869fec0b460bb6577302f5efd049
user-name: "prad"
library-name: "Movies"
mode: "latest"
item-count: "10"
small-column: false
show-thumbnail: true
thumbnail-aspect-ratio: "default"
template: |
{{/* Required config options */}}
{{ $baseURL := .Options.StringOr "base-url" "" }}
{{ $apiKey := .Options.StringOr "api-key" "" }}
{{ $userName := .Options.StringOr "user-name" "" }}
{{/* Required config options for "latest" mode */}}
{{ $libraryName := .Options.StringOr "library-name" "" }}
{{/* Optional config options */}}
{{ $mode := .Options.StringOr "mode" "latest" }}
{{ $itemCount := .Options.StringOr "item-count" "10" }}
{{ $mediaTypes := .Options.StringOr "media-types" "Movie,Episode,MusicAlbum" }}
{{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
{{ $isSmallColumn:= .Options.BoolOr "small-column" false }}
{{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
{{ $showProgressBar := .Options.BoolOr "progress-bar" true }}
{{/* Error message template */}}
{{ define "errorMsg" }}
<div class="widget-error-header">
<div class="color-negative size-h3">ERROR</div>
<svg class="widget-error-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"></path>
</svg>
</div>
<p class="break-all">{{ . }}</p>
{{ end }}
{{/* Check required fields */}}
{{ if or (eq $baseURL "") (eq $apiKey "") (eq $userName "") (eq $mode "") (and (eq $mode "latest") (eq $libraryName "")) }}
{{ template "errorMsg" "Some required options are not set." }}
{{ else }}
{{/* Fetch user ID */}}
{{ $userID := "" }}
{{ $usersCall := newRequest (print $baseURL "/Users")
| withParameter "api_key" $apiKey
| withHeader "Accept" "application/json"
| getResponse }}
{{ range $i, $user := $usersCall.JSON.Array "" }}
{{ if eq ($user.String "Name") $userName }}
{{ $userID = $user.String "Id" }}
{{ break }}
{{ end }}
{{ end }}
{{ if eq $userID "" }}
{{ template "errorMsg" (printf "User '%s' not found." $userName) }}
{{ else }}
{{ $items := "" }}
{{ if eq $mode "latest" }}
{{/* Fetch library ID */}}
{{ $libraryID := "" }}
{{ $userViewsCall := newRequest (print $baseURL "/UserViews")
| withParameter "api_key" $apiKey
| withParameter "userId" $userID
| withHeader "Accept" "application/json"
| getResponse }}
{{ range $i, $item := $userViewsCall.JSON.Array "Items" }}
{{ if eq ($item.String "Name") $libraryName }}
{{ $libraryID = $item.String "Id" }}
{{ break }}
{{ end }}
{{ end }}
{{ if eq $libraryID "" }}
{{ template "errorMsg" (printf "Library '%s' not found." $libraryName) }}
{{ else }}
{{/* Fetch latest items */}}
{{ $latestCall := newRequest (print $baseURL "/Users/" $userID "/Items/Latest")
| withParameter "api_key" $apiKey
| withParameter "Limit" $itemCount
| withParameter "ParentId" $libraryID
| withParameter "IncludeItemTypes" $mediaTypes
| withParameter "GroupItems" "true"
| withHeader "Accept" "application/json"
| getResponse }}
{{ $items = $latestCall.JSON.Array "" }}
{{ end }}
{{ else if eq $mode "nextup" }}
{{/* Fetch next up items */}}
{{ $nextUpCall := newRequest (print $baseURL "/Shows/NextUp")
| withParameter "api_key" $apiKey
| withParameter "UserId" $userID
| withParameter "Limit" $itemCount
| withParameter "EnableResumable" "true"
| withHeader "Accept" "application/json"
| getResponse }}
{{ $items = $nextUpCall.JSON.Array "Items" }}
{{ else }}
{{ template "errorMsg" "Unknown mode, expected 'latest' or 'nextup'" }}
{{ end }}
{{ if eq (len $items) 0 }}
<p>No items found, start streaming something!</p>
{{ else }}
{{/* Display the item carousel */}}
<div class="carousel-container show-right-cutoff">
<div class="cards-horizontal carousel-items-container">
{{ range $n, $item := $items }}
{{/* Common item variables */}}
{{ $mediaType := $item.String "Type" }}
{{ $title := $item.String "Name" }}
{{ $itemID := $item.String "Id" }}
{{/* Media type specific variables */}}
{{ $seriesTitle := "" }}
{{ $artist := "" }}
{{ $seriesID := "" }}
{{ $season := "" }}
{{ $episode := "" }}
{{ $playPercentage := "" }}
{{ $unwatchedEpisodeCount := "" }}
{{ if eq $mediaType "Movie" }}
{{ else if eq $mediaType "Series" }}
{{ $unwatchedEpisodeCount = $item.Int "UserData.UnplayedItemCount" }}
{{ else if eq $mediaType "Episode" }}
{{ $unwatchedEpisodeCount = 1 }}
{{ $seriesTitle = $item.String "SeriesName" }}
{{ $seriesID = $item.String "SeriesId" }}
{{ $season = $item.Int "ParentIndexNumber" }}
{{ $episode = $item.Int "IndexNumber" }}
{{ if $item.Exists "UserData.PlayedPercentage" }}
{{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
{{ end }}
{{/* For latest always refer to the series not individual episodes */}}
{{ if eq $mode "latest" }}
{{ $itemID = $seriesID }}
{{ $title = $seriesTitle }}
{{ end }}
{{ else if eq $mediaType "MusicAlbum" }}
{{ $artist = $item.String "AlbumArtist" }}
{{ end }}
{{ $linkURL := print $baseURL "/web/#/details?id=" $itemID }}
{{ $thumbURL := "" }}
{{ if not (eq $playPercentage "") }}
{{/* $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey "&percentPlayed=" $playPercentage */}}
{{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
{{ else }}
{{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
{{ end }}
<a class="card widget-content-frame" href="{{ $linkURL | safeURL }}">
{{ if $showThumbnail }}
<div style="position: relative;">
<img src="{{ $thumbURL | safeURL }}"
alt="{{ $title }} thumbnail"
loading="lazy"
class="media-server-thumbnail shrink-0"
style="
object-fit: fill;
border-radius: var(--border-radius) var(--border-radius) 0 0;
width: 100%;
display: block;
{{ if eq $thumbAspectRatio "square" }}aspect-ratio: 1;
{{ else if eq $thumbAspectRatio "portrait" }}aspect-ratio: 2/3;
{{ else if eq $thumbAspectRatio "landscape" }}aspect-ratio: 16/9;
{{ else }}aspect-ratio: initial;
{{ end }}
"
/>
{{ if and ($showProgressBar) (not (eq $playPercentage "")) }}
<div style="
position: absolute;
bottom: 8px;
left: 8px;
right: 8px;
height: 6px;
border-radius: var(--border-radius);
overflow: hidden;
background-color: rgba(255, 255, 255, 0.2);
">
<div style="
width: {{ print $playPercentage "%" }};
height: 100%;
border-radius: var(--border-radius) 0 0 var(--border-radius);
background-color: var(--color-primary)
"></div>
</div>
{{ end }}
</div>
{{ end }}
<div class="grow padding-inline-widget margin-top-10 margin-bottom-10">
<ul class="flex flex-column justify-evenly margin-bottom-3 {{ if $isSmallColumn }}size-h6{{ end }}" style="height: 100%;">
{{ if eq $mode "latest" }}
{{ if or (eq $mediaType "Series") (eq $mediaType "Episode") }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary shrink-0">{{ $unwatchedEpisodeCount }}</li>
<li class="text-truncate">{{ $title }}</li>
</ul>
{{ else if eq $mediaType "MusicAlbum" }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary text-truncate">{{ $artist }}</li>
<li class="text-truncate">{{ $title }}</li>
</ul>
{{ else }}
<li class="text-truncate">{{ $title }}</li>
{{ end }}
{{ else if eq $mode "nextup" }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary shrink-0">S{{ $season }}E{{ $episode }}</li>
<li class="text-truncate">{{ $seriesTitle }}</li>
</ul>
<li class="text-truncate">{{ $title }}</li>
{{ end }}
</ul>
</div>
</a>
{{ end }}
</div>
</div>
{{ end }}
{{ end }}
{{ end }}
- type: custom-api
title: Up Next Movies
frameless: true
cache: 5m
options:
base-url: http://nukala.local:8096
api-key: df9e869fec0b460bb6577302f5efd049
user-name: "prad"
library-name: "Movies"
mode: "nextup"
item-count: "10"
small-column: false
show-thumbnail: true
thumbnail-aspect-ratio: "default"
template: |
{{/* Required config options */}}
{{ $baseURL := .Options.StringOr "base-url" "" }}
{{ $apiKey := .Options.StringOr "api-key" "" }}
{{ $userName := .Options.StringOr "user-name" "" }}
{{/* Required config options for "latest" mode */}}
{{ $libraryName := .Options.StringOr "library-name" "" }}
{{/* Optional config options */}}
{{ $mode := .Options.StringOr "mode" "latest" }}
{{ $itemCount := .Options.StringOr "item-count" "10" }}
{{ $mediaTypes := .Options.StringOr "media-types" "Movie,Episode,MusicAlbum" }}
{{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
{{ $isSmallColumn:= .Options.BoolOr "small-column" false }}
{{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
{{ $showProgressBar := .Options.BoolOr "progress-bar" true }}
{{/* Error message template */}}
{{ define "errorMsg" }}
<div class="widget-error-header">
<div class="color-negative size-h3">ERROR</div>
<svg class="widget-error-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"></path>
</svg>
</div>
<p class="break-all">{{ . }}</p>
{{ end }}
{{/* Check required fields */}}
{{ if or (eq $baseURL "") (eq $apiKey "") (eq $userName "") (eq $mode "") (and (eq $mode "latest") (eq $libraryName "")) }}
{{ template "errorMsg" "Some required options are not set." }}
{{ else }}
{{/* Fetch user ID */}}
{{ $userID := "" }}
{{ $usersCall := newRequest (print $baseURL "/Users")
| withParameter "api_key" $apiKey
| withHeader "Accept" "application/json"
| getResponse }}
{{ range $i, $user := $usersCall.JSON.Array "" }}
{{ if eq ($user.String "Name") $userName }}
{{ $userID = $user.String "Id" }}
{{ break }}
{{ end }}
{{ end }}
{{ if eq $userID "" }}
{{ template "errorMsg" (printf "User '%s' not found." $userName) }}
{{ else }}
{{ $items := "" }}
{{ if eq $mode "latest" }}
{{/* Fetch library ID */}}
{{ $libraryID := "" }}
{{ $userViewsCall := newRequest (print $baseURL "/UserViews")
| withParameter "api_key" $apiKey
| withParameter "userId" $userID
| withHeader "Accept" "application/json"
| getResponse }}
{{ range $i, $item := $userViewsCall.JSON.Array "Items" }}
{{ if eq ($item.String "Name") $libraryName }}
{{ $libraryID = $item.String "Id" }}
{{ break }}
{{ end }}
{{ end }}
{{ if eq $libraryID "" }}
{{ template "errorMsg" (printf "Library '%s' not found." $libraryName) }}
{{ else }}
{{/* Fetch latest items */}}
{{ $latestCall := newRequest (print $baseURL "/Users/" $userID "/Items/Latest")
| withParameter "api_key" $apiKey
| withParameter "Limit" $itemCount
| withParameter "ParentId" $libraryID
| withParameter "IncludeItemTypes" $mediaTypes
| withParameter "GroupItems" "true"
| withHeader "Accept" "application/json"
| getResponse }}
{{ $items = $latestCall.JSON.Array "" }}
{{ end }}
{{ else if eq $mode "nextup" }}
{{/* Fetch next up items */}}
{{ $nextUpCall := newRequest (print $baseURL "/Shows/NextUp")
| withParameter "api_key" $apiKey
| withParameter "UserId" $userID
| withParameter "Limit" $itemCount
| withParameter "EnableResumable" "true"
| withHeader "Accept" "application/json"
| getResponse }}
{{ $items = $nextUpCall.JSON.Array "Items" }}
{{ else }}
{{ template "errorMsg" "Unknown mode, expected 'latest' or 'nextup'" }}
{{ end }}
{{ if eq (len $items) 0 }}
<p>No items found, start streaming something!</p>
{{ else }}
{{/* Display the item carousel */}}
<div class="carousel-container show-right-cutoff">
<div class="cards-horizontal carousel-items-container">
{{ range $n, $item := $items }}
{{/* Common item variables */}}
{{ $mediaType := $item.String "Type" }}
{{ $title := $item.String "Name" }}
{{ $itemID := $item.String "Id" }}
{{/* Media type specific variables */}}
{{ $seriesTitle := "" }}
{{ $artist := "" }}
{{ $seriesID := "" }}
{{ $season := "" }}
{{ $episode := "" }}
{{ $playPercentage := "" }}
{{ $unwatchedEpisodeCount := "" }}
{{ if eq $mediaType "Movie" }}
{{ else if eq $mediaType "Series" }}
{{ $unwatchedEpisodeCount = $item.Int "UserData.UnplayedItemCount" }}
{{ else if eq $mediaType "Episode" }}
{{ $unwatchedEpisodeCount = 1 }}
{{ $seriesTitle = $item.String "SeriesName" }}
{{ $seriesID = $item.String "SeriesId" }}
{{ $season = $item.Int "ParentIndexNumber" }}
{{ $episode = $item.Int "IndexNumber" }}
{{ if $item.Exists "UserData.PlayedPercentage" }}
{{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
{{ end }}
{{/* For latest always refer to the series not individual episodes */}}
{{ if eq $mode "latest" }}
{{ $itemID = $seriesID }}
{{ $title = $seriesTitle }}
{{ end }}
{{ else if eq $mediaType "MusicAlbum" }}
{{ $artist = $item.String "AlbumArtist" }}
{{ end }}
{{ $linkURL := print $baseURL "/web/#/details?id=" $itemID }}
{{ $thumbURL := "" }}
{{ if not (eq $playPercentage "") }}
{{/* $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey "&percentPlayed=" $playPercentage */}}
{{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
{{ else }}
{{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
{{ end }}
<a class="card widget-content-frame" href="{{ $linkURL | safeURL }}">
{{ if $showThumbnail }}
<div style="position: relative;">
<img src="{{ $thumbURL | safeURL }}"
alt="{{ $title }} thumbnail"
loading="lazy"
class="media-server-thumbnail shrink-0"
style="
object-fit: fill;
border-radius: var(--border-radius) var(--border-radius) 0 0;
width: 100%;
display: block;
{{ if eq $thumbAspectRatio "square" }}aspect-ratio: 1;
{{ else if eq $thumbAspectRatio "portrait" }}aspect-ratio: 2/3;
{{ else if eq $thumbAspectRatio "landscape" }}aspect-ratio: 16/9;
{{ else }}aspect-ratio: initial;
{{ end }}
"
/>
{{ if and ($showProgressBar) (not (eq $playPercentage "")) }}
<div style="
position: absolute;
bottom: 8px;
left: 8px;
right: 8px;
height: 6px;
border-radius: var(--border-radius);
overflow: hidden;
background-color: rgba(255, 255, 255, 0.2);
">
<div style="
width: {{ print $playPercentage "%" }};
height: 100%;
border-radius: var(--border-radius) 0 0 var(--border-radius);
background-color: var(--color-primary)
"></div>
</div>
{{ end }}
</div>
{{ end }}
<div class="grow padding-inline-widget margin-top-10 margin-bottom-10">
<ul class="flex flex-column justify-evenly margin-bottom-3 {{ if $isSmallColumn }}size-h6{{ end }}" style="height: 100%;">
{{ if eq $mode "latest" }}
{{ if or (eq $mediaType "Series") (eq $mediaType "Episode") }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary shrink-0">{{ $unwatchedEpisodeCount }}</li>
<li class="text-truncate">{{ $title }}</li>
</ul>
{{ else if eq $mediaType "MusicAlbum" }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary text-truncate">{{ $artist }}</li>
<li class="text-truncate">{{ $title }}</li>
</ul>
{{ else }}
<li class="text-truncate">{{ $title }}</li>
{{ end }}
{{ else if eq $mode "nextup" }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary shrink-0">S{{ $season }}E{{ $episode }}</li>
<li class="text-truncate">{{ $seriesTitle }}</li>
</ul>
<li class="text-truncate">{{ $title }}</li>
{{ end }}
</ul>
</div>
</a>
{{ end }}
</div>
</div>
{{ end }}
{{ end }}
{{ end }}
-492
View File
@@ -1,492 +0,0 @@
- size: full
widgets:
- type: custom-api
title: Latest TV
frameless: true
cache: 5m
options:
base-url: http://nukala.local:8096
api-key: df9e869fec0b460bb6577302f5efd049
user-name: "prad"
library-name: "TV"
mode: "latest"
item-count: "10"
small-column: false
show-thumbnail: true
thumbnail-aspect-ratio: "default"
template: |
{{/* Required config options */}}
{{ $baseURL := .Options.StringOr "base-url" "" }}
{{ $apiKey := .Options.StringOr "api-key" "" }}
{{ $userName := .Options.StringOr "user-name" "" }}
{{/* Required config options for "latest" mode */}}
{{ $libraryName := .Options.StringOr "library-name" "" }}
{{/* Optional config options */}}
{{ $mode := .Options.StringOr "mode" "latest" }}
{{ $itemCount := .Options.StringOr "item-count" "10" }}
{{ $mediaTypes := .Options.StringOr "media-types" "Movie,Episode,MusicAlbum" }}
{{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
{{ $isSmallColumn:= .Options.BoolOr "small-column" false }}
{{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
{{ $showProgressBar := .Options.BoolOr "progress-bar" true }}
{{/* Error message template */}}
{{ define "errorMsg" }}
<div class="widget-error-header">
<div class="color-negative size-h3">ERROR</div>
<svg class="widget-error-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"></path>
</svg>
</div>
<p class="break-all">{{ . }}</p>
{{ end }}
{{/* Check required fields */}}
{{ if or (eq $baseURL "") (eq $apiKey "") (eq $userName "") (eq $mode "") (and (eq $mode "latest") (eq $libraryName "")) }}
{{ template "errorMsg" "Some required options are not set." }}
{{ else }}
{{/* Fetch user ID */}}
{{ $userID := "" }}
{{ $usersCall := newRequest (print $baseURL "/Users")
| withParameter "api_key" $apiKey
| withHeader "Accept" "application/json"
| getResponse }}
{{ range $i, $user := $usersCall.JSON.Array "" }}
{{ if eq ($user.String "Name") $userName }}
{{ $userID = $user.String "Id" }}
{{ break }}
{{ end }}
{{ end }}
{{ if eq $userID "" }}
{{ template "errorMsg" (printf "User '%s' not found." $userName) }}
{{ else }}
{{ $items := "" }}
{{ if eq $mode "latest" }}
{{/* Fetch library ID */}}
{{ $libraryID := "" }}
{{ $userViewsCall := newRequest (print $baseURL "/UserViews")
| withParameter "api_key" $apiKey
| withParameter "userId" $userID
| withHeader "Accept" "application/json"
| getResponse }}
{{ range $i, $item := $userViewsCall.JSON.Array "Items" }}
{{ if eq ($item.String "Name") $libraryName }}
{{ $libraryID = $item.String "Id" }}
{{ break }}
{{ end }}
{{ end }}
{{ if eq $libraryID "" }}
{{ template "errorMsg" (printf "Library '%s' not found." $libraryName) }}
{{ else }}
{{/* Fetch latest items */}}
{{ $latestCall := newRequest (print $baseURL "/Users/" $userID "/Items/Latest")
| withParameter "api_key" $apiKey
| withParameter "Limit" $itemCount
| withParameter "ParentId" $libraryID
| withParameter "IncludeItemTypes" $mediaTypes
| withParameter "GroupItems" "true"
| withHeader "Accept" "application/json"
| getResponse }}
{{ $items = $latestCall.JSON.Array "" }}
{{ end }}
{{ else if eq $mode "nextup" }}
{{/* Fetch next up items */}}
{{ $nextUpCall := newRequest (print $baseURL "/Shows/NextUp")
| withParameter "api_key" $apiKey
| withParameter "UserId" $userID
| withParameter "Limit" $itemCount
| withParameter "EnableResumable" "true"
| withHeader "Accept" "application/json"
| getResponse }}
{{ $items = $nextUpCall.JSON.Array "Items" }}
{{ else }}
{{ template "errorMsg" "Unknown mode, expected 'latest' or 'nextup'" }}
{{ end }}
{{ if eq (len $items) 0 }}
<p>No items found, start streaming something!</p>
{{ else }}
{{/* Display the item carousel */}}
<div class="carousel-container show-right-cutoff">
<div class="cards-horizontal carousel-items-container">
{{ range $n, $item := $items }}
{{/* Common item variables */}}
{{ $mediaType := $item.String "Type" }}
{{ $title := $item.String "Name" }}
{{ $itemID := $item.String "Id" }}
{{/* Media type specific variables */}}
{{ $seriesTitle := "" }}
{{ $artist := "" }}
{{ $seriesID := "" }}
{{ $season := "" }}
{{ $episode := "" }}
{{ $playPercentage := "" }}
{{ $unwatchedEpisodeCount := "" }}
{{ if eq $mediaType "Movie" }}
{{ else if eq $mediaType "Series" }}
{{ $unwatchedEpisodeCount = $item.Int "UserData.UnplayedItemCount" }}
{{ else if eq $mediaType "Episode" }}
{{ $unwatchedEpisodeCount = 1 }}
{{ $seriesTitle = $item.String "SeriesName" }}
{{ $seriesID = $item.String "SeriesId" }}
{{ $season = $item.Int "ParentIndexNumber" }}
{{ $episode = $item.Int "IndexNumber" }}
{{ if $item.Exists "UserData.PlayedPercentage" }}
{{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
{{ end }}
{{/* For latest always refer to the series not individual episodes */}}
{{ if eq $mode "latest" }}
{{ $itemID = $seriesID }}
{{ $title = $seriesTitle }}
{{ end }}
{{ else if eq $mediaType "MusicAlbum" }}
{{ $artist = $item.String "AlbumArtist" }}
{{ end }}
{{ $linkURL := print $baseURL "/web/#/details?id=" $itemID }}
{{ $thumbURL := "" }}
{{ if not (eq $playPercentage "") }}
{{/* $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey "&percentPlayed=" $playPercentage */}}
{{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
{{ else }}
{{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
{{ end }}
<a class="card widget-content-frame" href="{{ $linkURL | safeURL }}">
{{ if $showThumbnail }}
<div style="position: relative;">
<img src="{{ $thumbURL | safeURL }}"
alt="{{ $title }} thumbnail"
loading="lazy"
class="media-server-thumbnail shrink-0"
style="
object-fit: fill;
border-radius: var(--border-radius) var(--border-radius) 0 0;
width: 100%;
display: block;
{{ if eq $thumbAspectRatio "square" }}aspect-ratio: 1;
{{ else if eq $thumbAspectRatio "portrait" }}aspect-ratio: 2/3;
{{ else if eq $thumbAspectRatio "landscape" }}aspect-ratio: 16/9;
{{ else }}aspect-ratio: initial;
{{ end }}
"
/>
{{ if and ($showProgressBar) (not (eq $playPercentage "")) }}
<div style="
position: absolute;
bottom: 8px;
left: 8px;
right: 8px;
height: 6px;
border-radius: var(--border-radius);
overflow: hidden;
background-color: rgba(255, 255, 255, 0.2);
">
<div style="
width: {{ print $playPercentage "%" }};
height: 100%;
border-radius: var(--border-radius) 0 0 var(--border-radius);
background-color: var(--color-primary)
"></div>
</div>
{{ end }}
</div>
{{ end }}
<div class="grow padding-inline-widget margin-top-10 margin-bottom-10">
<ul class="flex flex-column justify-evenly margin-bottom-3 {{ if $isSmallColumn }}size-h6{{ end }}" style="height: 100%;">
{{ if eq $mode "latest" }}
{{ if or (eq $mediaType "Series") (eq $mediaType "Episode") }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary shrink-0">{{ $unwatchedEpisodeCount }}</li>
<li class="text-truncate">{{ $title }}</li>
</ul>
{{ else if eq $mediaType "MusicAlbum" }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary text-truncate">{{ $artist }}</li>
<li class="text-truncate">{{ $title }}</li>
</ul>
{{ else }}
<li class="text-truncate">{{ $title }}</li>
{{ end }}
{{ else if eq $mode "nextup" }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary shrink-0">S{{ $season }}E{{ $episode }}</li>
<li class="text-truncate">{{ $seriesTitle }}</li>
</ul>
<li class="text-truncate">{{ $title }}</li>
{{ end }}
</ul>
</div>
</a>
{{ end }}
</div>
</div>
{{ end }}
{{ end }}
{{ end }}
- type: custom-api
title: Up Next TV
frameless: true
cache: 5m
options:
base-url: http://nukala.local:8096
api-key: df9e869fec0b460bb6577302f5efd049
user-name: "prad"
library-name: "TV"
mode: "nextup"
item-count: "10"
small-column: false
show-thumbnail: true
thumbnail-aspect-ratio: "default"
template: |
{{/* Required config options */}}
{{ $baseURL := .Options.StringOr "base-url" "" }}
{{ $apiKey := .Options.StringOr "api-key" "" }}
{{ $userName := .Options.StringOr "user-name" "" }}
{{/* Required config options for "latest" mode */}}
{{ $libraryName := .Options.StringOr "library-name" "" }}
{{/* Optional config options */}}
{{ $mode := .Options.StringOr "mode" "latest" }}
{{ $itemCount := .Options.StringOr "item-count" "10" }}
{{ $mediaTypes := .Options.StringOr "media-types" "Movie,Episode,MusicAlbum" }}
{{ $thumbAspectRatio := .Options.StringOr "thumbnail-aspect-ratio" "" }}
{{ $isSmallColumn:= .Options.BoolOr "small-column" false }}
{{ $showThumbnail := .Options.BoolOr "show-thumbnail" false }}
{{ $showProgressBar := .Options.BoolOr "progress-bar" true }}
{{/* Error message template */}}
{{ define "errorMsg" }}
<div class="widget-error-header">
<div class="color-negative size-h3">ERROR</div>
<svg class="widget-error-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"></path>
</svg>
</div>
<p class="break-all">{{ . }}</p>
{{ end }}
{{/* Check required fields */}}
{{ if or (eq $baseURL "") (eq $apiKey "") (eq $userName "") (eq $mode "") (and (eq $mode "latest") (eq $libraryName "")) }}
{{ template "errorMsg" "Some required options are not set." }}
{{ else }}
{{/* Fetch user ID */}}
{{ $userID := "" }}
{{ $usersCall := newRequest (print $baseURL "/Users")
| withParameter "api_key" $apiKey
| withHeader "Accept" "application/json"
| getResponse }}
{{ range $i, $user := $usersCall.JSON.Array "" }}
{{ if eq ($user.String "Name") $userName }}
{{ $userID = $user.String "Id" }}
{{ break }}
{{ end }}
{{ end }}
{{ if eq $userID "" }}
{{ template "errorMsg" (printf "User '%s' not found." $userName) }}
{{ else }}
{{ $items := "" }}
{{ if eq $mode "latest" }}
{{/* Fetch library ID */}}
{{ $libraryID := "" }}
{{ $userViewsCall := newRequest (print $baseURL "/UserViews")
| withParameter "api_key" $apiKey
| withParameter "userId" $userID
| withHeader "Accept" "application/json"
| getResponse }}
{{ range $i, $item := $userViewsCall.JSON.Array "Items" }}
{{ if eq ($item.String "Name") $libraryName }}
{{ $libraryID = $item.String "Id" }}
{{ break }}
{{ end }}
{{ end }}
{{ if eq $libraryID "" }}
{{ template "errorMsg" (printf "Library '%s' not found." $libraryName) }}
{{ else }}
{{/* Fetch latest items */}}
{{ $latestCall := newRequest (print $baseURL "/Users/" $userID "/Items/Latest")
| withParameter "api_key" $apiKey
| withParameter "Limit" $itemCount
| withParameter "ParentId" $libraryID
| withParameter "IncludeItemTypes" $mediaTypes
| withParameter "GroupItems" "true"
| withHeader "Accept" "application/json"
| getResponse }}
{{ $items = $latestCall.JSON.Array "" }}
{{ end }}
{{ else if eq $mode "nextup" }}
{{/* Fetch next up items */}}
{{ $nextUpCall := newRequest (print $baseURL "/Shows/NextUp")
| withParameter "api_key" $apiKey
| withParameter "UserId" $userID
| withParameter "Limit" $itemCount
| withParameter "EnableResumable" "true"
| withHeader "Accept" "application/json"
| getResponse }}
{{ $items = $nextUpCall.JSON.Array "Items" }}
{{ else }}
{{ template "errorMsg" "Unknown mode, expected 'latest' or 'nextup'" }}
{{ end }}
{{ if eq (len $items) 0 }}
<p>No items found, start streaming something!</p>
{{ else }}
{{/* Display the item carousel */}}
<div class="carousel-container show-right-cutoff">
<div class="cards-horizontal carousel-items-container">
{{ range $n, $item := $items }}
{{/* Common item variables */}}
{{ $mediaType := $item.String "Type" }}
{{ $title := $item.String "Name" }}
{{ $itemID := $item.String "Id" }}
{{/* Media type specific variables */}}
{{ $seriesTitle := "" }}
{{ $artist := "" }}
{{ $seriesID := "" }}
{{ $season := "" }}
{{ $episode := "" }}
{{ $playPercentage := "" }}
{{ $unwatchedEpisodeCount := "" }}
{{ if eq $mediaType "Movie" }}
{{ else if eq $mediaType "Series" }}
{{ $unwatchedEpisodeCount = $item.Int "UserData.UnplayedItemCount" }}
{{ else if eq $mediaType "Episode" }}
{{ $unwatchedEpisodeCount = 1 }}
{{ $seriesTitle = $item.String "SeriesName" }}
{{ $seriesID = $item.String "SeriesId" }}
{{ $season = $item.Int "ParentIndexNumber" }}
{{ $episode = $item.Int "IndexNumber" }}
{{ if $item.Exists "UserData.PlayedPercentage" }}
{{ $playPercentage = $item.String "UserData.PlayedPercentage" }}
{{ end }}
{{/* For latest always refer to the series not individual episodes */}}
{{ if eq $mode "latest" }}
{{ $itemID = $seriesID }}
{{ $title = $seriesTitle }}
{{ end }}
{{ else if eq $mediaType "MusicAlbum" }}
{{ $artist = $item.String "AlbumArtist" }}
{{ end }}
{{ $linkURL := print $baseURL "/web/#/details?id=" $itemID }}
{{ $thumbURL := "" }}
{{ if not (eq $playPercentage "") }}
{{/* $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey "&percentPlayed=" $playPercentage */}}
{{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
{{ else }}
{{ $thumbURL = concat $baseURL "/Items/" $itemID "/Images/Primary?api_key=" $apiKey }}
{{ end }}
<a class="card widget-content-frame" href="{{ $linkURL | safeURL }}">
{{ if $showThumbnail }}
<div style="position: relative;">
<img src="{{ $thumbURL | safeURL }}"
alt="{{ $title }} thumbnail"
loading="lazy"
class="media-server-thumbnail shrink-0"
style="
object-fit: fill;
border-radius: var(--border-radius) var(--border-radius) 0 0;
width: 100%;
display: block;
{{ if eq $thumbAspectRatio "square" }}aspect-ratio: 1;
{{ else if eq $thumbAspectRatio "portrait" }}aspect-ratio: 2/3;
{{ else if eq $thumbAspectRatio "landscape" }}aspect-ratio: 16/9;
{{ else }}aspect-ratio: initial;
{{ end }}
"
/>
{{ if and ($showProgressBar) (not (eq $playPercentage "")) }}
<div style="
position: absolute;
bottom: 8px;
left: 8px;
right: 8px;
height: 6px;
border-radius: var(--border-radius);
overflow: hidden;
background-color: rgba(255, 255, 255, 0.2);
">
<div style="
width: {{ print $playPercentage "%" }};
height: 100%;
border-radius: var(--border-radius) 0 0 var(--border-radius);
background-color: var(--color-primary)
"></div>
</div>
{{ end }}
</div>
{{ end }}
<div class="grow padding-inline-widget margin-top-10 margin-bottom-10">
<ul class="flex flex-column justify-evenly margin-bottom-3 {{ if $isSmallColumn }}size-h6{{ end }}" style="height: 100%;">
{{ if eq $mode "latest" }}
{{ if or (eq $mediaType "Series") (eq $mediaType "Episode") }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary shrink-0">{{ $unwatchedEpisodeCount }}</li>
<li class="text-truncate">{{ $title }}</li>
</ul>
{{ else if eq $mediaType "MusicAlbum" }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary text-truncate">{{ $artist }}</li>
<li class="text-truncate">{{ $title }}</li>
</ul>
{{ else }}
<li class="text-truncate">{{ $title }}</li>
{{ end }}
{{ else if eq $mode "nextup" }}
<ul class="list-horizontal-text flex-nowrap">
<li class="color-primary shrink-0">S{{ $season }}E{{ $episode }}</li>
<li class="text-truncate">{{ $seriesTitle }}</li>
</ul>
<li class="text-truncate">{{ $title }}</li>
{{ end }}
</ul>
</div>
</a>
{{ end }}
</div>
</div>
{{ end }}
{{ end }}
{{ end }}
+4 -2
View File
@@ -20,6 +20,7 @@ pages:
- $include: ./headlines/right.yml - $include: ./headlines/right.yml
- name: Finance - name: Finance
width: wide
columns: columns:
- $include: ./markets/left.yml - $include: ./markets/left.yml
- $include: ./markets/main.yml - $include: ./markets/main.yml
@@ -39,6 +40,7 @@ pages:
- $include: ./schedule/right.yml - $include: ./schedule/right.yml
- name: Movies & TV - name: Movies & TV
slug: movies
columns: columns:
- $include: ./entertainment/movies.yml - $include: ./entertainment/side.yml
- $include: ./entertainment/tv.yml - $include: ./entertainment/media.yml
-9
View File
@@ -1,13 +1,4 @@
# Masthead + markets ticker — the newspaper banner # Masthead + markets ticker — the newspaper banner
- type: html
source: |
<div class="masthead">
<div class="masthead-rule"></div>
<div class="masthead-title">The Daily Glance</div>
<div class="masthead-sub">Tech · Markets · Crypto</div>
<div class="masthead-rule"></div>
</div>
- type: markets - type: markets
hide-header: true hide-header: true
markets: markets:
+8
View File
@@ -7,3 +7,11 @@
- type: to-do - type: to-do
title: Projects title: Projects
id: projects id: projects
- type: rss
title: X Bookmarks
style: detailed-list
limit: 20
collapse-after: 8
feeds:
- url: https://x-bookmarks-rss.wltbs.workers.dev/feed.xml
title: X Bookmarks