use picocss

This commit is contained in:
steven 2025-04-10 01:17:42 -04:00
parent eaae9de31c
commit 9bab0c69af
4 changed files with 155 additions and 146 deletions

View file

@ -17,11 +17,13 @@
{%- endif %} {%- endif %}
<meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" href="clock.svg" type="image/svg+xml"> <link rel="icon" href="clock.svg" type="image/svg+xml">
<style>*{font-family:monospace;}</style> <meta name="color-scheme" content="dark light">
<link rel="stylesheet" href="https://static.stevenalexander.org/picocss/css/pico.min.css">
</head> </head>
<body> <body>
<h1><a href="https://25live.collegenet.com/pro/louisville#!/home/event/{{ data.event_id }}/details">{{ data.event_name }}</a>{{ " ("+data.event_title+")" if data.event_title }}</h1> <main class="container">
<h2> <h2><a href="https://25live.collegenet.com/pro/louisville#!/home/event/{{ data.event_id }}/details">{{ data.event_name }}</a>{{ " ("+data.event_title+")" if data.event_title }}</h2>
<h3>
{%- if "Rsrv" in data.profile.profile_name %} {%- if "Rsrv" in data.profile.profile_name %}
{%- if data.profile.reservation.append is defined %} {%- if data.profile.reservation.append is defined %}
Start: {{ data.profile.reservation[0].event_start_dt }}<br> Start: {{ data.profile.reservation[0].event_start_dt }}<br>
@ -33,9 +35,9 @@
{%- else %} {%- else %}
{{ data.profile.profile_name }} {{ data.profile.profile_name }}
{%- endif %} {%- endif %}
</h2> </h3>
{%- if data.profile.append is not defined %} {%- if data.profile.append is not defined %}
<h2> <h3>
{%- if data.profile.reservation.append is defined %} {%- if data.profile.reservation.append is defined %}
{%- if data.profile.reservation[0].space_reservation.append is defined %} {%- if data.profile.reservation[0].space_reservation.append is defined %}
{%- for space in data.profile.reservation[0].space_reservation %} {%- for space in data.profile.reservation[0].space_reservation %}
@ -53,23 +55,23 @@
<a href="{{ data.profile.reservation.space_reservation.space_id }}">{{ data.profile.reservation.space_reservation.space.formal_name }}</a> <a href="{{ data.profile.reservation.space_reservation.space_id }}">{{ data.profile.reservation.space_reservation.space.formal_name }}</a>
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
</h2> </h3>
{%- endif %} {%- endif %}
{%- if data.event_text %} {%- if data.event_text %}
<h2>Description</h2> <h3>Description</h3>
{%- if data.event_text.append is defined %} {%- if data.event_text.append is defined %}
{%- for i in data.event_text %} {%- for i in data.event_text %}
{%- if i.text_type_id == 1 %} {%- if i.text_type_id == 1 %}
<h3>{{ i.text | safe }}</h3> <h4>{{ i.text | safe }}</h4>
{%- endif %} {%- endif %}
{%- endfor %} {%- endfor %}
{%- elif data.event_text.text_type_id == 1 %} {%- elif data.event_text.text_type_id == 1 %}
<h3>{{ data.event_text.text | safe }}</h3> <h4>{{ data.event_text.text | safe }}</h4>
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
<h2>Contact(s)</h2> <h3>Contact(s)</h3>
{%- for i in data.role %} {%- for i in data.role %}
<h3>{{ i.role_name }}: {{ i.contact.contact_first_name }} {{ i.contact.contact_middle_name }} {{ i.contact.contact_last_name }}</h3> <h4>{{ i.role_name }}: {{ i.contact.contact_first_name }} {{ i.contact.contact_middle_name }} {{ i.contact.contact_last_name }}</h4>
{%- if i.contact.email %} {%- if i.contact.email %}
<p>Email: {{ i.contact.email }}</p> <p>Email: {{ i.contact.email }}</p>
{%- endif %} {%- endif %}
@ -81,17 +83,18 @@
{%- endif %} {%- endif %}
{%- endfor %} {%- endfor %}
{%- if data.custom_attribute %} {%- if data.custom_attribute %}
<h2>Custom Attribute(s)</h2> <h3>Custom Attribute(s)</h3>
{%- if data.custom_attribute.append is defined %} {%- if data.custom_attribute.append is defined %}
{%- for i in data.custom_attribute %} {%- for i in data.custom_attribute %}
<h3>{{ i.attribute_name }}</h3> <h4>{{ i.attribute_name }}</h4>
<p>{{ i.attribute_value }}</p> <p>{{ i.attribute_value }}</p>
{%- endfor %} {%- endfor %}
{%- else %} {%- else %}
<h3>{{ data.custom_attribute.attribute_name }}</h3> <h4>{{ data.custom_attribute.attribute_name }}</h4>
<p>{{ data.custom_attribute.attribute_value }}</p> <p>{{ data.custom_attribute.attribute_value }}</p>
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
<h2>Last modified at {{ data.last_mod_dt }} by {{ data.last_mod_user }}</h2> </main>
<footer class=container>Last modified at {{ data.last_mod_dt }} by {{ data.last_mod_user }}</footer>
</body> </body>
</html> </html>

View file

@ -7,37 +7,47 @@
<meta name="description" content="Find events at the University of Louisville"> <meta name="description" content="Find events at the University of Louisville">
<meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" href="calendar.svg" type="image/svg+xml"> <link rel="icon" href="calendar.svg" type="image/svg+xml">
<style>*{font-family:monospace;font-size:0.8cm;}input[type="checkbox"],input[type="radio"]{width:0.7cm;height:0.7cm;}</style> <meta name="color-scheme" content="dark light">
<link rel="stylesheet" href="https://static.stevenalexander.org/picocss/css/pico.jade.min.css">
</head> </head>
<body> <body>
<h1>Choose a day:</h1> <header class="container">
<input id="today" type="radio" name="date" checked> <h2>UofL Events</h2>
<label for="today">today</label><br> </header>
<input id="tomorrow" type="radio" name="date"> <main class="container">
<label for="tomorrow">tomorrow</label><br> <fieldset>
<input id="custom" type="radio" name="date"> <legend><strong>Date to display</strong></legend>
<label for="custom"><input id="date" type="date" min="{{today}}" max="{{later}}" value="{{dayafter}}" onchange="noClear(event)"></label> <input id="today" type="radio" name="date" checked>
<h1>[Optional] Select types of events to find:</h1> <label for="today">today</label><br>
{%- for i in ["available","class","exam","booked","food"] %} <input id="tomorrow" type="radio" name="date">
<input id="{{i}}" type="checkbox"> <label for="tomorrow">tomorrow</label><br>
<label for="{{i}}">{{i}}</label><br> <input id="custom" type="radio" name="date">
{%- endfor %} <label for="custom"><input id="date" type="date" min="{{today}}" max="{{later}}" value="{{dayafter}}" onchange="noClear(event)"></label>
<p><button onclick="changeURL()">Show me the events!</button></p> </fieldset>
<fieldset>
<legend><strong>Filter rooms by event type</strong></legend>
{%- for i in ["closed","available","class","exam","booked","food"] %}
<input id="{{i}}" type="checkbox">
<label for="{{i}}">{{i}}</label><br>
{%- endfor %}
</fieldset>
<fieldset>
<button class="outline" onclick="doFilters()">Show the events!</button>
</fieldset>
<script> <script>
function noClear(e) { function noClear(e){
val=e.target.value val=e.target.value
if(val===""||val<"{{today}}"||val>"{{later}}"){e.target.value="{{dayafter}}"} if(!val||val<"{{today}}"||val>"{{later}}"){e.target.value="{{dayafter}}"}
document.getElementById("custom").click() document.getElementById("custom").click()
} }
function changeURL(){ function doFilters(){
has=[] d=document.querySelector('input[type="radio"]:checked').id;
document.querySelectorAll('input[type="checkbox"]:checked').forEach(i=>has.push(i.id)) if(d=="custom"){document.querySelector('input[type="date"]').value}
if(has.length>0){has="?has="+has.join(",") f=Array.from(document.querySelectorAll('input[type="checkbox"]:checked')).map(c=>c.id);
}else{has=""} f=f.length?"?"+f.join(","):"";
date=document.querySelector('input[type="radio"]:checked').id document.location.href=d+f
if(date=="custom"){date=document.querySelector('input[type="date"]').value}
document.location.href=date+has
} }
</script> </script>
</main>
</body> </body>
</html> </html>

View file

@ -6,76 +6,64 @@
<title>{{ day }} - 44live</title> <title>{{ day }} - 44live</title>
<meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" href="calendar.svg" type="image/svg+xml"> <link rel="icon" href="calendar.svg" type="image/svg+xml">
<link rel="stylesheet" href="https://static.stevenalexander.org/picocss/css/pico.min.css">
<base target="_blank"> <base target="_blank">
<style>*{margin:0;padding:0;scrollbar-width:none;} <style>
body,html{ html,body{
-webkit-text-size-adjust:100%; font-family:monospace;
font:12px monospace; font-size:12px;
width:100%;
height:100%; height:100%;
width:100%;
overflow:auto; overflow:auto;
} }
table{ table{
background-color:black;
min-width:100%; min-width:100%;
width:1600px; width:1600px;
max-width:400%; max-width:400%;
border-collapse:separate; border-collapse:separate;
border-spacing:0;
table-layout:fixed; table-layout:fixed;
overflow-x:clip; overflow:hidden;
margin:0;
} }
th,td{ th,td{
background-color:white;
box-sizing:border-box;
border-bottom:2px solid black; border-bottom:2px solid black;
border-right:2px solid black; border-right:2px solid black;
overflow:hidden; padding:0;
text-overflow:ellipsis;
} }
th,td:first-child{ th,td:first-child{
position:sticky; position:sticky;
} }
th:first-child,td:first-child{ th:first-child,td:first-child{
left:0; left:0;
} }
th{ th{
top:0; color:black;
background-color:white;
text-align:center; text-align:center;
font-weight:bold; font-weight:bold;
top:0;
} }
th:first-child{ th:first-child{
z-index:1; z-index:1;
} }
a,span{ a,span{
white-space:nowrap; color:black;
padding:2px; padding:2px;
display:block;
white-space:nowrap;
overflow:hidden; overflow:hidden;
text-overflow:ellipsis; text-overflow:ellipsis;
}
a{
display:block;
text-decoration:none; text-decoration:none;
color:black;
} }
.closed>a{color:white;}
a:hover{background-color:lightgray;color:black;} a:hover{background-color:lightgray;color:black;}
.closed{background-color:black;color:white;} [class="closed"],[class="closed"]>*{background-color:#13171f;color:white;}
.available{background-color:lightgreen;} .available{background-color:lightgreen;}
.other{background-color:white;} .other{background-color:white;}
.class{background-color:darkgray;} .class{background-color:darkgray;}
.exam{background-color:gray;} .exam{background-color:gray;}
.booked{background-color:coral;} .booked{background-color:coral;}
.food{background-color:mediumpurple;} .food{background-color:mediumpurple;}
</style> </style>
</head> </head>
<body> <body>
<table> <table>
@ -85,98 +73,103 @@ a:hover{background-color:lightgray;color:black;}
<tbody></tbody> <tbody></tbody>
</table> </table>
<script> <script>
const headRow = document.querySelector("tr"); const headRow=document.querySelector("tr");
const bookBtn = headRow.querySelector("a"); const bookBtn=headRow.querySelector("a");
const tbody = document.querySelector("tbody"); const tbody=document.querySelector("tbody");
for (let hour = 8; hour < 23; hour++) { for(let hour=8;hour<23;hour++){
const th = document.createElement("th"); const th=document.createElement("th");
th.setAttribute("colspan", 60); th.setAttribute("colspan",60);
th.textContent = hour; th.textContent=hour;
headRow.appendChild(th) headRow.appendChild(th)
} }
let json=localStorage.getItem("{{ day }}"); let json=localStorage.getItem("{{day}}");
if (json) displayEvents(JSON.parse(json)) if(json)displayEvents(JSON.parse(json))
fetch("{{ day }}.json").then(r => { fetch("{{day}}.json").then(r=>{
bookBtn.innerText = "Book a Space"; bookBtn.innerText="Book a Space";
return r.json() return r.json()
}).then(json => { }).then(json=>{
tbody.innerHTML=""; tbody.innerHTML="";
displayEvents(json); displayEvents(json);
try { try{
localStorage.setItem("{{ day }}",JSON.stringify(json)) localStorage.setItem("{{day}}",JSON.stringify(json))
} catch { }catch{
localStorage.clear(); localStorage.clear();
localStorage.setItem("{{ day }}",JSON.stringify(json)) localStorage.setItem("{{day}}",JSON.stringify(json))
} }
}) })
function createBox(row, length, type, name, link) { function createBox(row,length,name=null,link=null,type=null){
const td = document.createElement("td"); const td=document.createElement("td");
if (link) { td.setAttribute("colspan",length);
var e = document.createElement("a"); let e;
e.href = link if(link){
e=document.createElement("a");
e.href=link
}else if(name){
e=document.createElement("span")
} }
if (name) { if(name&&e){
if (!e) var e = document.createElement("span") e.textContent=name;
e.textContent = name; e.title=name;
e.title = name;
td.appendChild(e) td.appendChild(e)
} }
if (type) { if(type){
if (type != "closed" || length == 900) {row.firstChild.classList.add(type)} row.firstChild?.classList.add(type);
td.classList.add(type); td.classList.add(type)
} }
td.setAttribute("colspan", length); row.appendChild(td)
row.appendChild(td);
} }
function displayEvents(json) { function displayEvents(json){
if (window.location.search) var has=new Set(new URLSearchParams(window.location.search).get("has").split(",")) const filterClasses=new Set(window.location.search.substring(1).split(",").filter(Boolean));
for (space in json) {
const row = document.createElement("tr"); for(const space in json){
let link = json[space].i; const row=document.createElement("tr");
let defaultEmpty = "available"; const info=json[space];
let defaultType = null; let link=`https://louisville.campusdish.com/LocationsAndMenus/Belknap/${space}`;
if (!json[space].i) { let defaultType="closed";
link = "https://louisville.campusdish.com/LocationsAndMenus/Belknap/"+space; if(info.i){
defaultEmpty = "closed"; link=info.i;
defaultType = "food" defaultType="available"
} }
createBox(row, 60, null, space, link); createBox(row,60,space,link);
let now = 0; let time=0;
if (json[space].l) { if(Array.isArray(info.l)){
for (e of json[space].l) { for(const event of info.l){
start=e.s const {s:start,e:end,n:name,t:type="other",i:id}=event;
end=e.e if(time<start){
if (now < start) { createBox(row,start-time,null,null,defaultType);
createBox(row, start-now, defaultEmpty); time=start;
now = start
} }
if (now <= start && now < end) { if(time<=start&&time<end){
type = defaultType ? defaultType : (e.i ? (e.t ? e.t : "other") : "closed"); const eventType=defaultType==="closed"?"food":(id===undefined?"closed":type);
link = e.i ? "event/" + e.i : null; const eventLink=id?`event/${id}`:null;
createBox(row, end-start, type, e.n, link) createBox(row,end-start,name,eventLink,eventType);
now = end time=end;
} }
} }
} }
if (now < 900) {
createBox(row, 900-now, defaultEmpty) if (time<900){
createBox(row,900-time,null,null,defaultType);
} }
if (typeof has === "undefined") {
tbody.appendChild(row) const firstCell=row.firstChild;
} else { if(!firstCell)continue;
for (let i of row.firstChild.className.split(" ")) {
if (has.has(i)) { if(filterClasses.size>0){
tbody.appendChild(row) if(firstCell.className.split(" ").some(cls=>filterClasses.has(cls))){
} tbody.appendChild(row);
} }
}else{
tbody.appendChild(row);
} }
} }
}; }
document.querySelector("script").remove(); document.querySelector("script").remove();
</script> </script>
</body> </body>

View file

@ -6,38 +6,41 @@
<title>{{ data.space_name }}{{ " ("+data.building_name+")" if data.building_name }}</title> <title>{{ data.space_name }}{{ " ("+data.building_name+")" if data.building_name }}</title>
<meta name="viewport" content="width=device-width,initial-scale=1"> <meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" href="location.svg" type="image/svg+xml"> <link rel="icon" href="location.svg" type="image/svg+xml">
<style>*{font-family:monospace;}b{white-space:pre-wrap;}img{max-width:100%;}</style> <meta name="color-scheme" content="dark light">
<link rel="stylesheet" href="https://static.stevenalexander.org/picocss/css/pico.min.css">
</head> </head>
<body> <body>
<h1><a href="https://25live.collegenet.com/pro/louisville#!/home/location/{{ data.space_id }}/availability/daily">{{ data.space_name }}</a>{{ " ("+data.building_name+")" if data.building_name }}</h1> <main class="container">
<h2>Hours</h2> <h2><a href="https://25live.collegenet.com/pro/louisville#!/home/location/{{ data.space_id }}/availability/daily">{{ data.space_name }}</a>{{ " ("+data.building_name+")" if data.building_name }}</h2>
<h3> <h3>Hours</h3>
<h4>
{%- for i in data.hours %} {%- for i in data.hours %}
{{ i.day_name[:3] }}: {{ i.open }} - {{ i.close }}<br> {{ i.day_name[:3] }}: {{ i.open }} - {{ i.close }}<br>
{%- endfor %} {%- endfor %}
</h3> </h4>
{% if data.instructions %} {% if data.instructions %}
<h2>Instructions</h2> <h3>Instructions</h3>
<h3>{{ data.instructions|safe }}</h3> <h4>{{ data.instructions|safe }}</h4>
{% endif %} {% endif %}
{%- if data.comments %} {%- if data.comments %}
<h2>Comments</h2> <h3>Comments</h3>
<h3>{{ data.comments|safe }}</h3> <h4>{{ data.comments|safe }}</h4>
{%- endif %} {%- endif %}
<h2>Layout(s)</h2> <h3>Layout(s)</h3>
{%- if data.layout %} {%- if data.layout %}
{%- if data.layout.append is defined %} {%- if data.layout.append is defined %}
{%- for i in data.layout %} {%- for i in data.layout %}
{%- if i.layout_photo_id %} {%- if i.layout_photo_id %}
<h3>{{ i.layout_name }} ({{ i.layout_capacity }} capacity)</h3> <h4>{{ i.layout_name }} ({{ i.layout_capacity }} capacity)</h4>
<img src="https://25live.collegenet.com/25live/data/louisville/run/image?image_id={{ i.layout_photo_id }}"> <img src="https://25live.collegenet.com/25live/data/louisville/run/image?image_id={{ i.layout_photo_id }}">
{%- endif %} {%- endif %}
{%- endfor %} {%- endfor %}
{%- elif data.layout.layout_photo_id %} {%- elif data.layout.layout_photo_id %}
<h3>{{ data.layout.layout_name }} ({{ data.layout.layout_capacity }} capacity)</h3> <h4>{{ data.layout.layout_name }} ({{ data.layout.layout_capacity }} capacity)</h4>
<img src="https://25live.collegenet.com/25live/data/louisville/run/image?image_id={{ data.layout.layout_photo_id }}"> <img src="https://25live.collegenet.com/25live/data/louisville/run/image?image_id={{ data.layout.layout_photo_id }}">
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
<h2>Last modified at {{ data.last_mod_dt }} by {{ data.last_mod_user }}</h2> </main>
<footer class="container">Last modified at {{ data.last_mod_dt }} by {{ data.last_mod_user }}</footer>
</body> </body>
</html> </html>