Initial commit
This commit is contained in:
commit
6ad6ebd1c1
1 changed files with 242 additions and 0 deletions
242
Library/Widgets/Calendar.md
Normal file
242
Library/Widgets/Calendar.md
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
```space-lua
|
||||
|
||||
function generate_calendar(calendarID, year, month)
|
||||
local month_names = {
|
||||
"Januari", "Februari", "Mars", "April",
|
||||
"Maj", "Juni", "Juli", "Augusti",
|
||||
"September", "Oktober", "November", "December"
|
||||
}
|
||||
local day_names = {"Mån", "Tis", "Ons", "Tor", "Fre", "Lör", "Sön"}
|
||||
|
||||
-- A specified year and month will always display that calendar.
|
||||
if year == 0 and month == 0 then
|
||||
local wantedMonth = clientStore.get("calendar:" .. calendarID)
|
||||
-- Calculate year and month from the current date plus a month offset.
|
||||
if wantedMonth == nil then
|
||||
wantedMonth = tonumber(os.date("%Y")) * 12 + tonumber(os.date("%m"))
|
||||
end
|
||||
year = (wantedMonth - (wantedMonth % 12)) / 12
|
||||
month = wantedMonth % 12
|
||||
if month == 0 then
|
||||
month = 1
|
||||
end
|
||||
end
|
||||
|
||||
local events = query[[
|
||||
from index.tag "event"
|
||||
where
|
||||
_.at.match(string.format("^%d-%02d-", year, month))
|
||||
order by _.at
|
||||
]]
|
||||
|
||||
local days = get_days_in_month(year, month)
|
||||
|
||||
-- Get the first day of the month (1 = Sunday, 2 = Monday, ..., 7 = Saturday)
|
||||
local first_day = tonumber(os.date("%w", os.time{year=year, month=month, day=1})) + 1
|
||||
|
||||
-- Adjust the first day based on the week start setting
|
||||
if week_start_on_monday then
|
||||
first_day = first_day - 1
|
||||
if first_day == 0 then
|
||||
first_day = 7
|
||||
end
|
||||
end
|
||||
|
||||
local html = [[
|
||||
<table border='1'>
|
||||
<tr>
|
||||
<th colspan='7'>
|
||||
<span class="month-prev"><</span>
|
||||
<span class="month-now">Idag</span>
|
||||
<span class="month-next">></span>
|
||||
]] .. month_names[month] .. " " .. year .. [[
|
||||
</th>
|
||||
</tr>
|
||||
]]
|
||||
|
||||
html = html .. "<tr>"
|
||||
for _, day_name in ipairs(day_names) do
|
||||
html = html .. "<th>" .. day_name .. "</th>"
|
||||
end
|
||||
html = html .. "</tr>\n"
|
||||
|
||||
local day = 1
|
||||
local started = false
|
||||
for week = 1, 6 do
|
||||
html = html .. "<tr>"
|
||||
for weekday = 1, 7 do
|
||||
if not started and weekday == first_day then
|
||||
started = true
|
||||
end
|
||||
if started and day <= days then
|
||||
local cellcontent = ""
|
||||
cellcontent = day
|
||||
|
||||
for _, e in pairs(events) do
|
||||
local datematch = e.at.match(
|
||||
string.format("^%d-%02d-%02d( +[0-9]+:[0-9]+)?", year, month, day))
|
||||
if #datematch >= 2 and not datematch[2] then
|
||||
cellcontent = cellcontent .. string.format(
|
||||
[[<a href="%s"><div class="event all-day">%s</div></a>]],
|
||||
e.ref, e.name
|
||||
)
|
||||
elseif #datematch >= 2 and datematch[2] then
|
||||
cellcontent = cellcontent .. string.format(
|
||||
[[
|
||||
<a href="%s">
|
||||
<div class="event">
|
||||
<div class="time">%s</div>
|
||||
<div>%s</div>
|
||||
</div>
|
||||
</a>
|
||||
]],
|
||||
e.ref,
|
||||
datematch[2],
|
||||
e.name
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
-- Mark today's date
|
||||
if day == tonumber(os.date("%d")) and month == tonumber(os.date("%m")) and year == tonumber(os.date("%Y")) then
|
||||
html = html .. string.format([[<td class="today">%s</td>]], cellcontent)
|
||||
else
|
||||
html = html .. string.format([[<td>%s</td>]], cellcontent)
|
||||
end
|
||||
|
||||
day = day + 1
|
||||
else
|
||||
html = html .. "<td></td>"
|
||||
end
|
||||
end
|
||||
html = html .. "</tr>"
|
||||
if day > days then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
html = html .. "</table>"
|
||||
|
||||
local tmpl = js.window.document.createElement("template")
|
||||
tmpl.innerHTML = html
|
||||
|
||||
tmpl.content.querySelector('.month-prev').addEventListener('click', function()
|
||||
storeMonth(calendarID, year, month, -1)
|
||||
codeWidget.refreshAll()
|
||||
end)
|
||||
|
||||
tmpl.content.querySelector('.month-next').addEventListener('click', function()
|
||||
storeMonth(calendarID, year, month, 1)
|
||||
codeWidget.refreshAll()
|
||||
end)
|
||||
|
||||
tmpl.content.querySelector('.month-now').addEventListener('click', function()
|
||||
clientStore.delete("calendar:" .. calendarID)
|
||||
storeMonth(calendarID, tonumber(os.date("%Y")), tonumber(os.date("%m")), 0)
|
||||
codeWidget.refreshAll()
|
||||
end)
|
||||
|
||||
return widget.new{
|
||||
html = tmpl.content,
|
||||
display = "block",
|
||||
cssClasses = {"calendartable"}
|
||||
}
|
||||
end
|
||||
|
||||
function storeMonth(calendarID, year, month, offset)
|
||||
local storedMonth = clientStore.get("calendar:" .. calendarID)
|
||||
if storedMonth == nil then
|
||||
storedMonth = year * 12 + month
|
||||
end
|
||||
clientStore.set("calendar:" .. calendarID, storedMonth + offset)
|
||||
codeWidget.refreshAll()
|
||||
end
|
||||
|
||||
-- Local function to get the correct number of days in a month (handles leap years)
|
||||
local function get_days_in_month(year, month)
|
||||
local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
|
||||
|
||||
-- Check for leap year and adjust February
|
||||
if month == 2 and ((year % 4 == 0 and year % 100 ~= 0) or (year % 400 == 0)) then
|
||||
return 29
|
||||
end
|
||||
|
||||
return days_in_month[month]
|
||||
end
|
||||
```
|
||||
|
||||
```space-style
|
||||
.calendartable {
|
||||
border-collapse: collapse;
|
||||
/* width: 500px; */
|
||||
}
|
||||
|
||||
.calendartable table {
|
||||
border-color: var(--panel-border-color);
|
||||
border: 2px solid #444;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.calendartable th {
|
||||
width: 14%;
|
||||
padding: 3px;
|
||||
text-align: left;
|
||||
background-color: var(--panel-background-color);
|
||||
color: #852624;
|
||||
border: 1px solid #aaa;
|
||||
}
|
||||
|
||||
|
||||
.calendartable td {
|
||||
width: 14%;
|
||||
padding: 3px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
border: 1px solid #aaa;
|
||||
}
|
||||
|
||||
.calendartable td.today {
|
||||
background-color: #f6f3c2;
|
||||
}
|
||||
|
||||
.calendartable a {
|
||||
text-decoration-line: none;
|
||||
color: var(--root-color);
|
||||
}
|
||||
|
||||
.calendartable a.mark {
|
||||
text-decoration-line: none;
|
||||
color: var(--ui-accent-text-color);
|
||||
}
|
||||
|
||||
.calendartable span.extramarker {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.calendartable .event {
|
||||
background-color: #2ca05a;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 4px 8px;
|
||||
margin-top: 8px;
|
||||
max-width: 200px;
|
||||
white-space: normal;
|
||||
overflow-wrap: normal !important;
|
||||
word-break: normal !important;
|
||||
}
|
||||
|
||||
.calendartable .event.all-day {
|
||||
background-color: #852624;
|
||||
}
|
||||
|
||||
.calendartable .event .time {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.calendartable .month-prev,
|
||||
.calendartable .month-next,
|
||||
.calendartable .month-now {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue