1038 lines
39 KiB
YAML
1038 lines
39 KiB
YAML
# Glance Dashboard for Orsi
|
||
# Namespace: glance-system
|
||
# Domain: orsi.dooplex.hu
|
||
# Version: v0.8.4
|
||
#
|
||
# Features:
|
||
# - Custom background image (purple theme matching Homepage)
|
||
# - Custom logo
|
||
# - Weather widget (Budapest)
|
||
# - YouTube subscriptions
|
||
# - RSS feeds
|
||
# - To-do list
|
||
# - iFrames for Cal.com, Google Calendar, Outline
|
||
# - Bookmarks/Links to all apps
|
||
# - Calendar widget
|
||
#
|
||
# Authentik Integration:
|
||
# 1. Create Application: "Glance Orsi"
|
||
# 2. Create Provider: Proxy Provider with external host https://orsi.dooplex.hu
|
||
# 3. Create Outpost: glance-outpost
|
||
# 4. Update auth-url annotation with actual outpost service name
|
||
---
|
||
apiVersion: v1
|
||
kind: Namespace
|
||
metadata:
|
||
name: glance-system
|
||
labels:
|
||
app.kubernetes.io/name: glance-orsi
|
||
app.kubernetes.io/instance: glance-orsi
|
||
---
|
||
apiVersion: v1
|
||
kind: ConfigMap
|
||
metadata:
|
||
name: glance-config
|
||
namespace: glance-system
|
||
labels:
|
||
app.kubernetes.io/name: glance-orsi
|
||
app.kubernetes.io/instance: glance-orsi
|
||
data:
|
||
glance.yml: |
|
||
# Glance Configuration
|
||
# Documentation: https://github.com/glanceapp/glance/blob/main/docs/configuration.md
|
||
|
||
server:
|
||
host: 0.0.0.0
|
||
port: 8080
|
||
assets-path: /app/config/assets
|
||
|
||
branding:
|
||
logo-url: https://web.dooplex.hu/static/dooplex_logo_orsi_3.png
|
||
favicon-url: https://web.dooplex.hu/static/dooplex_favicon_orsi.png
|
||
app-name: "Orsi's Home"
|
||
app-icon-url: https://web.dooplex.hu/static/dooplex_favicon_orsi.png
|
||
app-background-color: "#2d1f3d"
|
||
hide-footer: true
|
||
|
||
theme:
|
||
disable-picker: true
|
||
background-color: 280 30 15
|
||
primary-color: 280 60 70
|
||
positive-color: 120 50 50
|
||
negative-color: 0 70 60
|
||
contrast-multiplier: 1.2
|
||
text-saturation-multiplier: 0.8
|
||
custom-css-file: /assets/custom.css
|
||
|
||
pages:
|
||
# ==================== HOME PAGE ====================
|
||
- name: Home
|
||
slug: home
|
||
width: wide
|
||
columns:
|
||
# ---------- LEFT COLUMN ----------
|
||
- size: small
|
||
widgets:
|
||
- type: custom-api
|
||
title: Meal for the Day
|
||
cache: 5m
|
||
|
||
url: http://glance-helper.glance-system.svc.cluster.local:8000/tandoor/daily
|
||
parameters:
|
||
count: 3
|
||
cooldown: 14
|
||
|
||
options:
|
||
tandoor_url: https://tandoor.dooplex.hu
|
||
|
||
template: |
|
||
{{ $tandoor := .Options.StringOr "tandoor_url" "https://tandoor.dooplex.hu" }}
|
||
{{ $items := .JSON.Array "items" }}
|
||
{{ $count := len $items }}
|
||
{{ $last := sub $count 1 }}
|
||
|
||
<style>
|
||
.mw { display:flex; flex-direction:column; gap:6px; }
|
||
.mw-meta { opacity:.65; font-size:12px; display:flex; justify-content:space-between; align-items:center; }
|
||
.mw-box { position:relative; border-radius:14px; background:rgba(255,255,255,0.04); box-shadow:0 0 0 1px rgba(255,255,255,0.06) inset; overflow:hidden; width:100%; }
|
||
.mw-box input { display:none; }
|
||
.mw-track { display:flex; transition:transform 0.3s ease; }
|
||
.mw-s { min-width:100%; width:100%; flex-shrink:0; box-sizing:border-box; }
|
||
.mw-img { height:150px; background:rgba(0,0,0,0.15); overflow:hidden; }
|
||
.mw-img img { width:100%; height:100%; object-fit:cover; display:block; }
|
||
.mw-noimg { height:150px; display:flex; align-items:center; justify-content:center; opacity:.5; font-size:12px; }
|
||
.mw-name { padding:10px 12px 4px; font-weight:700; opacity:.95; line-height:1.3; overflow-wrap:break-word; word-break:break-word; }
|
||
.mw-stats { padding:0 12px 6px; font-size:11px; opacity:.5; }
|
||
.mw-acts { padding:0 12px 10px; display:flex; gap:10px; opacity:.8; font-size:12px; }
|
||
.mw-acts a, .mw-link { text-decoration:none; color:inherit; display:block; }
|
||
.mw-p, .mw-n { position:absolute; top:75px; transform:translateY(-50%); width:26px; height:26px; border-radius:50%; background:rgba(0,0,0,0.6); color:#fff; align-items:center; justify-content:center; font-size:11px; cursor:pointer; z-index:5; display:none; }
|
||
.mw-p { left:6px; }
|
||
.mw-n { right:6px; }
|
||
.mw-p:hover, .mw-n:hover { background:rgba(0,0,0,0.85); }
|
||
.mw-dots { display:flex; justify-content:center; gap:5px; padding:3px 0 1px; }
|
||
.mw-dot { width:6px; height:6px; border-radius:50%; background:rgba(255,255,255,0.2); cursor:pointer; }
|
||
.mw-dot:hover { background:rgba(255,255,255,0.4); }
|
||
{{ range $i, $_ := $items }}
|
||
#mr{{ $i }}:checked ~ .mw-track { transform:translateX(-{{ mul $i 100 }}%); }
|
||
#mr{{ $i }}:checked ~ .mw-dots .mw-dot:nth-child({{ add $i 1 }}) { background:rgba(255,255,255,0.85); }
|
||
{{ if gt $i 0 }}.mw-box:hover #mr{{ $i }}:checked ~ .mw-p[data-t="{{ sub $i 1 }}"] { display:flex; }{{ end }}
|
||
{{ if lt $i $last }}.mw-box:hover #mr{{ $i }}:checked ~ .mw-n[data-t="{{ add $i 1 }}"] { display:flex; }{{ end }}
|
||
{{ end }}
|
||
</style>
|
||
|
||
<div class="mw">
|
||
<div class="mw-meta">
|
||
<span>Today's picks ({{ $count }} total)</span>
|
||
<a href="{{ $tandoor }}" target="_blank" rel="noreferrer">Open Tandoor</a>
|
||
</div>
|
||
{{ if lt $count 1 }}<div class="color-negative">No recipes.</div>{{ else }}
|
||
<div class="mw-box">
|
||
{{ range $i, $_ := $items }}<input type="radio" name="mr" id="mr{{ $i }}"{{ if eq $i 0 }} checked{{ end }}>{{ end }}
|
||
<div class="mw-track">
|
||
{{ range $r := $items }}{{ $img := $r.String "image" }}{{ $url := $r.String "url" }}{{ $cook := $r.String "cook_url" }}{{ $cooked := $r.Int "cooked_count" }}
|
||
<div class="mw-s">
|
||
<a class="mw-link" href="{{ $url }}" target="_blank">
|
||
<div class="mw-img">{{ if $img }}<img src="{{ $img }}" alt="">{{ else }}<div class="mw-noimg">No image</div>{{ end }}</div>
|
||
<div class="mw-name">{{ $r.String "name" }}</div>
|
||
</a>
|
||
{{ if gt $cooked 0 }}<div class="mw-stats">Cooked {{ $cooked }}× before</div>{{ end }}
|
||
<div class="mw-acts"><a href="{{ $url }}" target="_blank">Open</a> <a href="{{ $cook }}" target="_blank">Cooked today ✔</a></div>
|
||
</div>
|
||
{{ end }}
|
||
</div>
|
||
{{ if gt $count 1 }}
|
||
{{ range $i, $_ := $items }}{{ if gt $i 0 }}<label class="mw-p" for="mr{{ sub $i 1 }}" data-t="{{ sub $i 1 }}">◀</label>{{ end }}{{ if lt $i $last }}<label class="mw-n" for="mr{{ add $i 1 }}" data-t="{{ add $i 1 }}">▶</label>{{ end }}{{ end }}
|
||
<div class="mw-dots">{{ range $i, $_ := $items }}<label class="mw-dot" for="mr{{ $i }}"></label>{{ end }}</div>
|
||
{{ end }}
|
||
</div>
|
||
{{ end }}
|
||
</div>
|
||
|
||
# Quick Links - Productivity
|
||
- type: bookmarks
|
||
title: Productivity
|
||
groups:
|
||
- title: ""
|
||
links:
|
||
- title: Nextcloud
|
||
url: https://nextcloud.dooplex.hu
|
||
icon: si:nextcloud
|
||
- title: Outline
|
||
url: https://outline.dooplex.hu
|
||
icon: si:outline
|
||
- title: Paperless
|
||
url: https://paperless.dooplex.hu
|
||
icon: si:paperlessngx
|
||
- title: Vaultwarden
|
||
url: https://vaultwarden.dooplex.hu
|
||
icon: si:bitwarden
|
||
- title: Actual Budget
|
||
url: https://actualbudget.dooplex.hu
|
||
icon: si:actualbudget
|
||
- title: Tandoor
|
||
url: https://tandoor.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/tandoor.png
|
||
- title: Bookstack
|
||
url: https://bookstack.dooplex.hu
|
||
icon: si:bookstack
|
||
|
||
# Quick Links - File Sharing
|
||
- type: bookmarks
|
||
title: File Sharing
|
||
groups:
|
||
- title: ""
|
||
links:
|
||
- title: Fileshare
|
||
url: https://fileshare.dooplex.hu
|
||
icon: si:files
|
||
- title: Privatebin
|
||
url: https://privatebin.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/privatebin.png
|
||
- title: Pastes (OpenGist)
|
||
url: https://paste.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/opengist.png
|
||
- title: Zipline
|
||
url: https://zipline.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/zipline.png
|
||
|
||
# ---------- CENTER COLUMN ----------
|
||
- size: full
|
||
widgets:
|
||
- type: split-column
|
||
max-columns: 3
|
||
widgets:
|
||
# Weather Widget (Időkép)
|
||
- type: custom-api
|
||
title: "Időkép – Budapest VII."
|
||
url: "http://idokep-scraper.glance-system.svc.cluster.local:8000/api?v=2"
|
||
cache: 30s
|
||
template: |
|
||
{{ $loc := .JSON.String "location.name" }}
|
||
{{ if eq $loc "" }}{{ $loc = .JSON.String "place" }}{{ end }}
|
||
{{ $curTemp := .JSON.Float "current.temp_c" }}
|
||
{{ $curIcon := .JSON.String "current.icon_url" }}
|
||
{{ $daily := .JSON.Array "daily" }}
|
||
{{ $hourly := .JSON.Array "hourly" }}
|
||
|
||
<div class="idokep">
|
||
<div class="idokep-top">
|
||
<div class="idokep-top-left">
|
||
{{ if $curIcon }}<img class="idokep-icon" src="{{ $curIcon }}" alt="" />{{ end }}
|
||
<div class="idokep-temp">{{ printf "%.0f" $curTemp }}°C</div>
|
||
</div>
|
||
<div class="idokep-top-right">
|
||
<div class="idokep-loc">{{ $loc }}</div>
|
||
<div class="idokep-src">Forrás: <a href="{{ .JSON.String "source.url" }}" target="_blank">Időkép</a></div>
|
||
</div>
|
||
</div>
|
||
|
||
{{ if gt (len $hourly) 0 }}
|
||
<div class="idokep-hourly">
|
||
{{ range $i, $h := $hourly }}
|
||
<div class="idokep-hour">
|
||
<div class="idokep-hour-time">{{ $h.String "time" }}</div>
|
||
{{ if $h.String "icon_url" }}<img class="idokep-hour-icon" src="{{ $h.String "icon_url" }}" title="{{ $h.String "condition" }}" alt="{{ $h.String "condition" }}" />{{ end }}
|
||
<div class="idokep-hour-temp">{{ printf "%.0f" ($h.Float "temp_c") }}°</div>
|
||
</div>
|
||
{{ end }}
|
||
</div>
|
||
{{ end }}
|
||
|
||
{{ if gt (len $daily) 0 }}
|
||
<div class="idokep-daily">
|
||
{{ range $daily }}
|
||
<div class="idokep-row">
|
||
<div class="idokep-dow">
|
||
<span class="idokep-downame">{{ .String "dow" }}</span>
|
||
<span class="idokep-daynum">{{ .String "daynum" }}</span>
|
||
</div>
|
||
<div class="idokep-dayicon">
|
||
{{ if .String "icon_url" }}<img src="{{ .String "icon_url" }}" title="{{ .String "condition" }}" alt="{{ .String "condition" }}" />{{ end }}
|
||
</div>
|
||
<div class="idokep-min">{{ printf "%.0f" (.Float "tmin_c") }}°</div>
|
||
|
||
<div class="idokep-bar">
|
||
<div class="idokep-bar-track"></div>
|
||
|
||
{{/* We construct the style manually to bypass Go security sanitization */}}
|
||
<div class="idokep-bar-fill" style="
|
||
--l: {{ printf "%.1f" (.Float "c_l") }}%;
|
||
--w: {{ printf "%.1f" (.Float "c_w") }}%;
|
||
--gw: {{ printf "%.1f" (.Float "c_gw") }}%;
|
||
--ml: {{ printf "%.1f" (.Float "c_ml") }}%;
|
||
--s-wht: {{ printf "%.1f" (.Float "c_s1") }}%;
|
||
--s-blu: {{ printf "%.1f" (.Float "c_s2") }}%;
|
||
--s-pur: {{ printf "%.1f" (.Float "c_s3") }}%;
|
||
--s-pnk: {{ printf "%.1f" (.Float "c_s4") }}%;
|
||
--s-red: {{ printf "%.1f" (.Float "c_s5") }}%;
|
||
">
|
||
<div class="idokep-bar-gradient"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="idokep-max">{{ printf "%.0f" (.Float "tmax_c") }}°</div>
|
||
</div>
|
||
{{ end }}
|
||
</div>
|
||
{{ end }}
|
||
</div>
|
||
# Calendar Widget
|
||
- type: calendar
|
||
first-day-of-week: monday
|
||
# To-Do List
|
||
- type: to-do
|
||
title: Tasks
|
||
|
||
# Outline Notes iframe
|
||
- type: iframe
|
||
source: https://outline.dooplex.hu/collection/notes-VVby8kTDMn/recent
|
||
height: 500
|
||
title: Recent Notes
|
||
|
||
# ---------- RIGHT COLUMN ----------
|
||
- size: small
|
||
widgets:
|
||
- type: rss
|
||
title: News & Feeds
|
||
limit: 15
|
||
collapse-after: 8
|
||
feeds:
|
||
- url: https://telex.hu/rss
|
||
title: telex.hu
|
||
limit: 3
|
||
- url: https://444.hu/feed
|
||
title: 444.hu
|
||
limit: 3
|
||
- url: https://444.hu/feed
|
||
title: 444.hu
|
||
limit: 3
|
||
- url: https://hvg.hu/rss
|
||
title: hvg.hu
|
||
limit: 3
|
||
- url: http://www.socialpsychology.org/headlines.rss
|
||
title: socialpsychology.org
|
||
limit: 3
|
||
- url: https://youarenotsosmart.com/feed/
|
||
title: youarenotsosmart.com
|
||
limit: 3
|
||
|
||
# ==================== TEACHING/LEARNING PAGE ====================
|
||
- name: Teaching & Learning
|
||
slug: teaching
|
||
width: wide
|
||
columns:
|
||
- size: small
|
||
widgets:
|
||
- type: bookmarks
|
||
title: Links for Teaching
|
||
groups:
|
||
- links:
|
||
- title: Plex
|
||
url: https://plex.dooplex.hu
|
||
icon: si:plex
|
||
- type: bookmarks
|
||
title: Links for Learning
|
||
groups:
|
||
- links:
|
||
- title: Plex
|
||
url: https://plex.dooplex.hu
|
||
icon: si:plex
|
||
|
||
# ---------- CENTER COLUMN ----------
|
||
- size: full
|
||
widgets:
|
||
# Cal.com Booking iframe
|
||
- type: iframe
|
||
source: https://booking.dooplex.hu/bookings/upcoming
|
||
height: 500
|
||
title: Upcoming Bookings
|
||
|
||
# Google Calendar iframe
|
||
- type: iframe
|
||
source: https://calendar.google.com/calendar/embed?src=b2884faf3db792ac082a6206057552c79080716efd5f966e169a41fc500e1c1c%40group.calendar.google.com&ctz=Europe%2FBudapest
|
||
height: 500
|
||
title: Calendar
|
||
|
||
# ==================== MEDIA PAGE ====================
|
||
- name: Media
|
||
slug: media
|
||
width: wide
|
||
columns:
|
||
- size: small
|
||
widgets:
|
||
- type: bookmarks
|
||
title: Entertainment
|
||
groups:
|
||
- links:
|
||
- title: Plex
|
||
url: https://plex.dooplex.hu
|
||
icon: si:plex
|
||
- title: Immich (Photos)
|
||
url: https://photos.dooplex.hu
|
||
icon: si:immich
|
||
- title: AudioBookshelf
|
||
url: https://audiobookshelf.dooplex.hu
|
||
icon: si:audiobookshelf
|
||
- title: Calibre-Web (eBooks)
|
||
url: https://books.dooplex.hu
|
||
icon: si:calibreweb
|
||
- title: Arcade (Retro Games)
|
||
url: https://arcade.dooplex.hu
|
||
icon: si:retroarch
|
||
|
||
- type: bookmarks
|
||
title: Media Management
|
||
groups:
|
||
- links:
|
||
- title: Sonarr (TV Shows)
|
||
url: https://sonarr.dooplex.hu
|
||
icon: si:sonarr
|
||
- title: Radarr (Movies)
|
||
url: https://radarr.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/radarr.png
|
||
- title: RadarrKids
|
||
url: https://radarrkids.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/radarrkids.png
|
||
- title: Prowlarr (Indexers)
|
||
url: https://prowlarr.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/prowlarr.png
|
||
- title: Seerr (Requests)
|
||
url: https://seerr.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/seerr.png
|
||
|
||
- size: full
|
||
widgets:
|
||
# YouTube Videos
|
||
- type: videos
|
||
title: YouTube
|
||
channels:
|
||
- UCir93b_ftqInEaDpsWYbo_g #Practical Psychology - @practicalpsychologytips
|
||
- UCEwsbtepqts935wXykReKxg #CounsellingTutor - @Counsellingtutor1
|
||
- UCUdettijNYvLAm4AixZv4RA #SciShow Psych - @SciShowPsych
|
||
- UClHVl2N3jPEbkNJVx-ItQIQ #HealthyGamerGG - @HealthyGamerGG
|
||
- UCAvfZQ3r24F-V1JYqn2pfXg #The Psychology Podcast - @ThePsychologyPodcast
|
||
- UC6Unpcb3T4QijIBs8hPfeyA #Psych Explained - @PsychExplained
|
||
- UCl8TEoIOnMq_5ntJOYMq-Zg #DrJulie - @DrJulie
|
||
limit: 12
|
||
collapse-after: 6
|
||
|
||
# Reddit
|
||
- type: group
|
||
title: Reddit
|
||
widgets:
|
||
- type: reddit
|
||
subreddit: psychology
|
||
show-thumbnails: true
|
||
- type: reddit
|
||
subreddit: psychologystudents
|
||
show-thumbnails: true
|
||
- type: reddit
|
||
subreddit: psychologytalk
|
||
show-thumbnails: true
|
||
- type: reddit
|
||
subreddit: psychologists
|
||
show-thumbnails: true
|
||
- type: reddit
|
||
subreddit: psychologyresearch
|
||
show-thumbnails: true
|
||
- type: reddit
|
||
subreddit: academicpsychology
|
||
show-thumbnails: true
|
||
- type: reddit
|
||
subreddit: social_psychology
|
||
show-thumbnails: true
|
||
|
||
- size: small
|
||
widgets:
|
||
- type: bookmarks
|
||
title: Other Apps
|
||
groups:
|
||
- links:
|
||
- title: AdventureLog
|
||
url: https://adventures.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/adventurelog.png
|
||
- title: Wanderer
|
||
url: https://wanderer.dooplex.hu
|
||
icon: sh:wanderer
|
||
- title: Plant-it
|
||
url: https://plantit.dooplex.hu
|
||
icon: si:leaflet
|
||
- title: Workout (wger)
|
||
url: https://workout.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/wger.png
|
||
- title: Fileshare
|
||
url: https://fileshare.dooplex.hu
|
||
icon: si:files
|
||
- title: Privatebin
|
||
url: https://privatebin.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/privatebin.png
|
||
- title: Pastes (OpenGist)
|
||
url: https://paste.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/opengist.png
|
||
- title: Zipline
|
||
url: https://zipline.dooplex.hu
|
||
icon: https://web.dooplex.hu/static/white-icons/zipline.png
|
||
|
||
# ==================== NECTCLOUD PAGE ====================
|
||
- name: NextCloud
|
||
slug: nextcloud
|
||
width: wide
|
||
columns:
|
||
- size: full
|
||
widgets:
|
||
# Nextcloud iframe
|
||
- type: iframe
|
||
css-class: iframe-no-tint
|
||
source: https://nextcloud.dooplex.hu/apps/files/files
|
||
height: 1200
|
||
title: NextCloud
|
||
|
||
custom.css: |
|
||
/* Custom CSS for Orsi's Glance Dashboard */
|
||
/* Purple theme with background image matching Homepage */
|
||
|
||
/* ===== Wallpaper visible ===== */
|
||
html, body { height: 100%; }
|
||
|
||
html {
|
||
background: url("https://web.dooplex.hu/static/wallpaper-orsi.jpg") center / cover no-repeat fixed !important;
|
||
}
|
||
|
||
/* Glance containers that tend to paint over the wallpaper */
|
||
body,
|
||
.page,
|
||
#page-content,
|
||
.page-content,
|
||
.content-bounds,
|
||
.page-columns,
|
||
.page-column {
|
||
background: transparent !important;
|
||
}
|
||
|
||
/* Optional readability veil (Homepage-like) */
|
||
body::before {
|
||
content: "";
|
||
position: fixed;
|
||
inset: 0;
|
||
background: rgba(20, 10, 30, 0.25);
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
}
|
||
body > * { position: relative; z-index: 1; }
|
||
|
||
/* ===== Glassy widgets like Homepage ===== */
|
||
.widget {
|
||
background: rgba(45, 31, 61, 0.55) !important;
|
||
border: 1px solid rgba(255,255,255,0.08) !important;
|
||
border-radius: 10px !important;
|
||
backdrop-filter: blur(6px) !important;
|
||
-webkit-backdrop-filter: blur(6px) !important;
|
||
}
|
||
|
||
/* ===== Header + bigger logo ===== */
|
||
.header-container {
|
||
background: rgba(45, 31, 61, 0.55) !important;
|
||
backdrop-filter: blur(10px) !important;
|
||
-webkit-backdrop-filter: blur(10px) !important;
|
||
border-bottom: 1px solid rgba(255,255,255,0.08) !important;
|
||
}
|
||
|
||
.header {
|
||
min-height: 150px !important;
|
||
align-items: flex-end !important;
|
||
padding: 16px 18px !important;
|
||
}
|
||
|
||
/* This matches your DOM: <div class="logo"> <img ...> */
|
||
.logo img {
|
||
max-height: 170px !important;
|
||
height: auto !important;
|
||
width: auto !important;
|
||
object-fit: contain !important;
|
||
}
|
||
|
||
/* ===== iFrame purple tint + visible overlay ===== */
|
||
.widget.widget-type-iframe {
|
||
position: relative !important;
|
||
overflow: hidden !important;
|
||
border-radius: 12px !important;
|
||
}
|
||
|
||
.widget.widget-type-iframe iframe {
|
||
border-radius: 12px !important;
|
||
width: 100% !important;
|
||
border: 0 !important;
|
||
filter: sepia(0.25) saturate(3) hue-rotate(250deg) brightness(1.02) !important;
|
||
position: relative !important;
|
||
z-index: 1 !important;
|
||
}
|
||
|
||
/* Overlay ON TOP of iframe (you can’t style inside cross-origin iframes) */
|
||
.widget.widget-type-iframe::after {
|
||
content: "";
|
||
position: absolute;
|
||
inset: 0;
|
||
z-index: 2;
|
||
pointer-events: none;
|
||
border-radius: 12px;
|
||
background: rgba(226, 146, 255, 0.16);
|
||
}
|
||
|
||
/* Widget content area */
|
||
.widget-content {
|
||
background-color: transparent !important;
|
||
}
|
||
|
||
/* Header fully transparent */
|
||
.header-container,
|
||
.header,
|
||
.page-header,
|
||
.nav,
|
||
.navigation {
|
||
background-color: transparent !important;
|
||
background: transparent !important;
|
||
backdrop-filter: none !important;
|
||
-webkit-backdrop-filter: none !important;
|
||
box-shadow: none !important;
|
||
border: 0 !important;
|
||
}
|
||
|
||
/* --- Header: align tabs to bottom + larger font --- */
|
||
.header {
|
||
display: flex !important;
|
||
align-items: flex-end !important; /* bottom-align children */
|
||
gap: 18px !important;
|
||
}
|
||
|
||
/* Push the nav to the bottom edge */
|
||
.header .nav {
|
||
align-self: flex-end !important;
|
||
padding-bottom: 10px !important; /* tweak this value if you want it lower/higher */
|
||
}
|
||
|
||
/* Bigger, cleaner tab text */
|
||
.header .nav .nav-item {
|
||
font-size: 18px !important; /* increase */
|
||
line-height: 1.1 !important;
|
||
padding: 10px 14px !important; /* makes it feel less “floaty” */
|
||
letter-spacing: 0.2px !important;
|
||
}
|
||
|
||
/* Optional: make current tab underline sit nicely at the bottom */
|
||
.header .nav .nav-item-current::after,
|
||
.header .nav .nav-item[aria-current="page"]::after {
|
||
bottom: -6px !important;
|
||
}
|
||
|
||
.content-bounds,
|
||
.body-content,
|
||
.page,
|
||
#page-content {
|
||
background: transparent !important;
|
||
}
|
||
|
||
/* Column containers */
|
||
.page-column, .page-columns {
|
||
background-color: transparent !important;
|
||
}
|
||
|
||
/* Links styling - purple accent */
|
||
a {
|
||
color: #e292ff !important;
|
||
}
|
||
|
||
a:hover {
|
||
color: #f0b8ff !important;
|
||
}
|
||
|
||
/* Bookmark items */
|
||
.bookmark-link {
|
||
background-color: rgba(60, 40, 80, 0.6) !important;
|
||
border-radius: 8px !important;
|
||
transition: background-color 0.2s ease !important;
|
||
}
|
||
|
||
.bookmark-link:hover {
|
||
background-color: rgba(80, 50, 110, 0.8) !important;
|
||
}
|
||
|
||
.widget-type-calendar,
|
||
.widget-type-weather,
|
||
.widget-type-to-do {
|
||
background-color: rgba(45, 31, 61, 0.55) !important;
|
||
}
|
||
|
||
/* RSS feed items */
|
||
.rss-item, .feed-item {
|
||
background-color: rgba(60, 40, 80, 0.5) !important;
|
||
border-radius: 6px !important;
|
||
margin-bottom: 4px !important;
|
||
}
|
||
|
||
/* Video thumbnails */
|
||
.video-item, .videos-item {
|
||
background-color: rgba(60, 40, 80, 0.5) !important;
|
||
border-radius: 8px !important;
|
||
}
|
||
|
||
/* Widget titles */
|
||
.widget-header, .widget-title {
|
||
color: #e292ff !important;
|
||
font-weight: 600 !important;
|
||
}
|
||
|
||
/* Scrollbar styling */
|
||
::-webkit-scrollbar {
|
||
width: 8px;
|
||
}
|
||
|
||
::-webkit-scrollbar-track {
|
||
background: rgba(45, 31, 61, 0.5);
|
||
}
|
||
|
||
::-webkit-scrollbar-thumb {
|
||
background: rgba(226, 146, 255, 0.5);
|
||
border-radius: 4px;
|
||
}
|
||
|
||
::-webkit-scrollbar-thumb:hover {
|
||
background: rgba(226, 146, 255, 0.7);
|
||
}
|
||
|
||
/* Fix "Show more" bar background in RSS widget */
|
||
.widget-type-rss .expand-toggle-button {
|
||
background: transparent !important;
|
||
box-shadow: none !important;
|
||
border: 0 !important;
|
||
}
|
||
|
||
/* Glance often draws that ugly bar via a pseudo-element */
|
||
.widget-type-rss .expand-toggle-button::before,
|
||
.widget-type-rss .expand-toggle-button::after,
|
||
.widget-type-rss .expand-toggle-button-icon::before,
|
||
.widget-type-rss .expand-toggle-button-icon::after {
|
||
background: transparent !important;
|
||
box-shadow: none !important;
|
||
border: 0 !important;
|
||
}
|
||
|
||
/* Optional: make it feel "intentional" instead of floating */
|
||
.widget-type-rss .expand-toggle-button {
|
||
margin-top: 8px !important;
|
||
padding: 10px 12px !important;
|
||
border-top: 1px solid rgba(255,255,255,0.08) !important;
|
||
color: rgba(255,255,255,0.75) !important;
|
||
}
|
||
.widget-type-rss .expand-toggle-button:hover {
|
||
color: rgba(255,255,255,0.95) !important;
|
||
}
|
||
|
||
/* --- Force header nav to sit at the bottom (override utility classes) --- */
|
||
.header.flex {
|
||
align-items: flex-end !important;
|
||
}
|
||
|
||
/* Make the nav fill the header height and align its items to the bottom */
|
||
.header.flex > .nav.flex {
|
||
height: 100% !important;
|
||
align-items: flex-end !important;
|
||
padding-bottom: 14px !important; /* increase/decrease to taste */
|
||
}
|
||
|
||
/* Bigger tab text */
|
||
.header.flex > .nav.flex > .nav-item {
|
||
font-size: 20px !important;
|
||
line-height: 1.1 !important;
|
||
padding: 10px 14px !important;
|
||
}
|
||
|
||
/* Tabs: bottom-align text inside full-height .nav-item */
|
||
.header.flex > .nav.flex > .nav-item {
|
||
display: flex !important;
|
||
align-items: flex-end !important;
|
||
|
||
/* keep them full-height, but move the text down */
|
||
height: 100% !important;
|
||
padding: 0 14px 18px 14px !important; /* bottom padding controls “how low” */
|
||
|
||
/* kill Glance's vertical centering */
|
||
line-height: 1 !important;
|
||
|
||
font-size: 20px !important;
|
||
}
|
||
|
||
/* Expand buttons: force transparent everywhere (RSS, Reddit, etc) */
|
||
.expand-toggle-button,
|
||
.expand-toggle-button.container-expanded {
|
||
background: transparent !important;
|
||
background-color: transparent !important;
|
||
box-shadow: none !important;
|
||
border: 0 !important;
|
||
}
|
||
|
||
/* Some themes draw the bar via pseudo elements */
|
||
.expand-toggle-button::before,
|
||
.expand-toggle-button::after,
|
||
.expand-toggle-button-icon::before,
|
||
.expand-toggle-button-icon::after {
|
||
background: transparent !important;
|
||
background-color: transparent !important;
|
||
box-shadow: none !important;
|
||
}
|
||
|
||
/* If the purple comes from a wrapper around the button, kill that too */
|
||
.widget-content > button.expand-toggle-button,
|
||
.widget-content > .expand-toggle-button,
|
||
.widget-content .expand-toggle-button {
|
||
background: transparent !important;
|
||
background-color: transparent !important;
|
||
}
|
||
|
||
/* If it’s "sticking" to bottom and picking up background from parent */
|
||
.expand-toggle-button.container-expanded {
|
||
backdrop-filter: none !important;
|
||
-webkit-backdrop-filter: none !important;
|
||
}
|
||
|
||
.widget.iframe-no-tint iframe {
|
||
filter: none !important;
|
||
}
|
||
|
||
.widget.iframe-no-tint::after {
|
||
content: none !important;
|
||
display: none !important;
|
||
}
|
||
/* =========================================================================
|
||
Időkép custom-api widget
|
||
========================================================================= */
|
||
.idokep { display: flex; flex-direction: column; gap: 10px; }
|
||
|
||
.idokep-top { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
|
||
.idokep-top-left { display: flex; align-items: center; gap: 10px; }
|
||
.idokep-icon { width: 42px; height: 42px; opacity: 0.95; }
|
||
.idokep-temp { font-size: 42px; font-weight: 700; letter-spacing: 0.5px; line-height: 1; }
|
||
|
||
.idokep-top-right { text-align: right; }
|
||
.idokep-loc { opacity: 0.85; font-weight: 600; }
|
||
.idokep-src { opacity: 0.6; font-size: 12px; margin-top: 2px; }
|
||
.idokep-src a { opacity: 0.9; }
|
||
|
||
.idokep-hourly { display: flex; gap: 10px; padding-top: 4px; }
|
||
.idokep-hour { width: 54px; display: flex; flex-direction: column; align-items: center; gap: 6px; opacity: 0.9; }
|
||
.idokep-hour-time { font-size: 12px; opacity: 0.65; }
|
||
.idokep-hour-icon { width: 26px; height: 26px; }
|
||
.idokep-hour-temp { font-weight: 700; }
|
||
|
||
.idokep-muted { opacity: 0.6; font-size: 12px; padding: 4px 0; }
|
||
|
||
.idokep-daily { display: flex; flex-direction: column; gap: 8px; margin-top: 2px; }
|
||
.idokep-row {
|
||
display: grid;
|
||
grid-template-columns: 44px 26px 36px 1fr 36px; /* day+date, icon, min, bar, max */
|
||
gap: 10px;
|
||
align-items: center;
|
||
}
|
||
.idokep-dow { opacity: 0.7; font-weight: 700; }
|
||
.idokep-dayicon img { width: 22px; height: 22px; opacity: 0.95; }
|
||
.idokep-min, .idokep-max { text-align: right; font-weight: 700; opacity: 0.8; }
|
||
.idokep-dow {
|
||
display: grid;
|
||
grid-template-columns: 22px 1fr; /* dow then daynum */
|
||
column-gap: 6px;
|
||
align-items: center;
|
||
opacity: 0.8;
|
||
font-weight: 700;
|
||
}
|
||
.idokep-daynum {
|
||
text-align: right;
|
||
opacity: 0.75;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.idokep-bar {
|
||
position: relative;
|
||
height: 10px;
|
||
}
|
||
.idokep-bar-track {
|
||
position: absolute;
|
||
inset: 0;
|
||
border-radius: 999px;
|
||
background: rgba(255,255,255,0.10);
|
||
}
|
||
.idokep-bar-fill {
|
||
position: absolute;
|
||
top: 0;
|
||
bottom: 0;
|
||
border-radius: 999px;
|
||
overflow: hidden;
|
||
box-shadow: 0 0 0 1px rgba(0,0,0,0.08) inset;
|
||
|
||
/* Position controlled by Python variables */
|
||
left: var(--l, 0%);
|
||
width: var(--w, 0%);
|
||
}
|
||
/* This element holds the gradient */
|
||
.idokep-bar-gradient {
|
||
position: absolute;
|
||
top: 0;
|
||
bottom: 0;
|
||
|
||
/* Compensation geometry controlled by Python variables */
|
||
width: var(--gw, 100%);
|
||
margin-left: var(--ml, 0%);
|
||
|
||
/* The Dynamic Gradient */
|
||
background: linear-gradient(90deg,
|
||
#ffffff var(--s-wht),
|
||
#60a5fa var(--s-blu),
|
||
#a78bfa var(--s-pur),
|
||
#fb7185 var(--s-pnk),
|
||
#ef4444 var(--s-red)
|
||
);
|
||
}
|
||
---
|
||
apiVersion: apps/v1
|
||
kind: Deployment
|
||
metadata:
|
||
name: glance-orsi
|
||
namespace: glance-system
|
||
labels:
|
||
app.kubernetes.io/name: glance-orsi
|
||
app.kubernetes.io/instance: glance-orsi
|
||
app.kubernetes.io/version: "v0.8.4"
|
||
annotations:
|
||
reloader.stakater.com/auto: "true"
|
||
spec:
|
||
replicas: 1
|
||
strategy:
|
||
type: Recreate
|
||
selector:
|
||
matchLabels:
|
||
app.kubernetes.io/name: glance-orsi
|
||
app.kubernetes.io/instance: glance-orsi
|
||
template:
|
||
metadata:
|
||
labels:
|
||
app.kubernetes.io/name: glance-orsi
|
||
app.kubernetes.io/instance: glance-orsi
|
||
app.kubernetes.io/version: "v0.8.4"
|
||
spec:
|
||
securityContext:
|
||
runAsUser: 1000
|
||
runAsGroup: 1000
|
||
fsGroup: 1000
|
||
containers:
|
||
- name: glance
|
||
image: glanceapp/glance:v0.8.4
|
||
imagePullPolicy: IfNotPresent
|
||
env:
|
||
- name: TZ
|
||
value: "Europe/Budapest"
|
||
ports:
|
||
- name: http
|
||
containerPort: 8080
|
||
protocol: TCP
|
||
livenessProbe:
|
||
httpGet:
|
||
path: /
|
||
port: http
|
||
initialDelaySeconds: 10
|
||
periodSeconds: 30
|
||
timeoutSeconds: 5
|
||
failureThreshold: 3
|
||
readinessProbe:
|
||
httpGet:
|
||
path: /
|
||
port: http
|
||
initialDelaySeconds: 5
|
||
periodSeconds: 10
|
||
timeoutSeconds: 5
|
||
failureThreshold: 3
|
||
resources:
|
||
requests:
|
||
cpu: 10m
|
||
memory: 32Mi
|
||
limits:
|
||
cpu: 200m
|
||
memory: 128Mi
|
||
volumeMounts:
|
||
- name: config
|
||
mountPath: /app/config/glance.yml
|
||
subPath: glance.yml
|
||
- name: config
|
||
mountPath: /app/config/assets/custom.css
|
||
subPath: custom.css
|
||
volumes:
|
||
- name: config
|
||
configMap:
|
||
name: glance-config
|
||
---
|
||
apiVersion: v1
|
||
kind: Service
|
||
metadata:
|
||
name: glance-orsi
|
||
namespace: glance-system
|
||
labels:
|
||
app.kubernetes.io/name: glance-orsi
|
||
app.kubernetes.io/instance: glance-orsi
|
||
spec:
|
||
type: ClusterIP
|
||
ports:
|
||
- name: http
|
||
port: 8080
|
||
targetPort: http
|
||
protocol: TCP
|
||
selector:
|
||
app.kubernetes.io/name: glance-orsi
|
||
app.kubernetes.io/instance: glance-orsi
|
||
---
|
||
# Ingress WITH Authentik proxy authentication
|
||
# Update the auth-url annotation with your actual outpost service name after creating in Authentik
|
||
apiVersion: networking.k8s.io/v1
|
||
kind: Ingress
|
||
metadata:
|
||
name: glance-orsi
|
||
namespace: glance-system
|
||
labels:
|
||
app.kubernetes.io/name: glance-orsi
|
||
app.kubernetes.io/instance: glance-orsi
|
||
annotations:
|
||
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||
external-dns.alpha.kubernetes.io/hostname: orsi.dooplex.hu
|
||
nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
||
nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"
|
||
nginx.ingress.kubernetes.io/proxy-buffers-number: "4"
|
||
nginx.ingress.kubernetes.io/proxy-busy-buffers-size: "32k"
|
||
# Authentik Forward Auth annotations
|
||
# TODO: Update 'glance-home-outpost' with your actual outpost name after creating in Authentik
|
||
nginx.ingress.kubernetes.io/auth-url: http://ak-outpost-glance-orsi-outpost.auth-system.svc.cluster.local:9000/outpost.goauthentik.io/auth/nginx
|
||
nginx.ingress.kubernetes.io/auth-signin: https://orsi.dooplex.hu/outpost.goauthentik.io/start?rd=$escaped_request_uri
|
||
nginx.ingress.kubernetes.io/auth-response-headers: Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email
|
||
nginx.ingress.kubernetes.io/auth-snippet: |
|
||
proxy_set_header X-Forwarded-Host $http_host;
|
||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||
set $geo_allowed 0;
|
||
if ($remote_addr ~ "^192\.168\.") { set $geo_allowed 1; }
|
||
if ($remote_addr ~ "^10\.") { set $geo_allowed 1; }
|
||
if ($geoip2_country_code = "HU") { set $geo_allowed 1; }
|
||
if ($geo_allowed = 0) {
|
||
return 403 "Access restricted to Hungary";
|
||
}
|
||
spec:
|
||
ingressClassName: nginx-internal
|
||
rules:
|
||
- host: orsi.dooplex.hu
|
||
http:
|
||
paths:
|
||
- path: /
|
||
pathType: Prefix
|
||
backend:
|
||
service:
|
||
name: glance-orsi
|
||
port:
|
||
number: 8080
|
||
tls:
|
||
- hosts:
|
||
- orsi.dooplex.hu
|
||
secretName: glance-orsi-tls
|
||
---
|