Toggle menu
83
56
34
2.9K
Landrace.Wiki - The Landrace Cannabis Wiki
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:CurrentEventsCalendar

From Landrace.Wiki - The Landrace Cannabis Wiki

Documentation for this module may be created at Module:CurrentEventsCalendar/doc

local p = {}

local function pad2(n)
  n = tonumber(n) or 0
  if n < 10 then return "0" .. tostring(n) end
  return tostring(n)
end

local function ymd(y, m, d)
  return string.format("%04d-%02d-%02d", y, m, d)
end

local function month_name(m)
  local names = {
    "January","February","March","April","May","June",
    "July","August","September","October","November","December"
  }
  return names[m] or tostring(m)
end

local function days_in_month(y, m)
  local t = os.time({ year = y, month = m + 1, day = 0 })
  return tonumber(os.date("%d", t))
end

local function weekday_of_first(y, m)
  local t = os.time({ year = y, month = m, day = 1 })
  -- Lua: 1=Sunday .. 7=Saturday
  return tonumber(os.date("*t", t).wday)
end

local function next_month(y, m)
  m = m + 1
  if m == 13 then return y + 1, 1 end
  return y, m
end

local function prev_month(y, m)
  m = m - 1
  if m == 0 then return y - 1, 12 end
  return y, m
end

local function get_today()
  -- Force UTC time
  local t = os.date("!*t")
  return t.year, t.month, t.day
end

local function smw_available()
  return mw and mw.smw and type(mw.smw.ask) == "function"
end

local function collect_event_days(y, m, category)
  local days = {}

  if not smw_available() then
    return days
  end

  local start = ymd(y, m, 1)
  local ny, nm = next_month(y, m)
  local finish = ymd(ny, nm, 1)

  local query = {
    string.format("[[Category:%s]]", category),
    string.format("[[Has event date::>=%s]]", start),
    string.format("[[Has event date::<%s]]", finish),
    "?Has event date=eventdate",
    "limit=500"
  }

  local res = mw.smw.ask(query) or {}

  for _, row in ipairs(res) do
    local po = row.printouts or {}
    local vals = po.eventdate or {}

    for _, v in ipairs(vals) do
      local s = v
      if type(v) == "table" then
        if v.value then s = v.value
        elseif v.raw then s = v.raw
        elseif v.timestamp then
          s = os.date("%Y-%m-%d", tonumber(v.timestamp))
        end
      end

      if type(s) == "string" then
        local yy, mm, dd = s:match("^(%d%d%d%d)%-(%d%d)%-(%d%d)")
        if yy and mm and dd then
          local daynum = tonumber(dd)
          if daynum then days[daynum] = true end
        end
      end
    end
  end

  return days
end

-- Build PrefixIndex links from a base like "Special:PrefixIndex/News:"
local function prefix_month_link(base, y, m, label)
  local target = string.format("%s%04d-%02d-", base, y, m)
  return string.format("[[%s|%s]]", target, label)
end

local function prefix_day_link(base, y, m, d)
  local target = string.format("%s%04d-%02d-%02d/", base, y, m, d)
  return string.format("[[%s|%d]]", target, d)
end

local function normalize_base(base)
  base = tostring(base or "")
  base = mw.text.trim(base)
  -- Ensure it ends with ":" for PrefixIndex/News:
  -- If someone passes "Special:PrefixIndex/News", fix it.
  if base:sub(-1) ~= ":" then
    if base:sub(-1) == "/" then
      base = base:sub(1, -2)
    end
    if base:sub(-1) ~= ":" then
      base = base .. ":"
    end
  end
  return base
end

function p.render(frame)
  local args = frame.args or {}

  local nowY, nowM, nowD = get_today()

  local y = tonumber(args.year) or nowY
  local m = tonumber(args.month) or nowM

  -- Expect: base = "Special:PrefixIndex/News:"
  local base = normalize_base(args.base or "Special:PrefixIndex/News:")
  local category = args.category or "News Item"

  local py, pm = prev_month(y, m)
  local ny, nm = next_month(y, m)

  local firstWday = weekday_of_first(y, m) -- 1..7 (Sun..Sat)
  local dim = days_in_month(y, m)
  local hasEvents = collect_event_days(y, m, category)

  local html = mw.html.create("div"):addClass("portal-events-calendar")

  local nav = mw.html.create("div"):addClass("calendar-month-nav")

  nav:tag("span")
    :addClass("calendar-nav-link")
    :wikitext(prefix_month_link(base, py, pm, "‹ " .. month_name(pm)))

  nav:tag("span")
    :addClass("calendar-current-month")
    :wikitext(string.format("%s %04d", month_name(m), y))

  nav:tag("span")
    :addClass("calendar-nav-link")
    :wikitext(prefix_month_link(base, ny, nm, month_name(nm) .. " ›"))

  html:node(nav)

  local headers = mw.html.create("div"):addClass("calendar-week-headers")
  local names = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}
  for i = 1, 7 do
    headers:tag("div"):addClass("calendar-weekday"):wikitext(names[i])
  end
  html:node(headers)

  local grid = mw.html.create("div"):addClass("calendar-month-grid")

  local leading = firstWday - 1
  for _ = 1, leading do
    grid:tag("div"):addClass("calendar-day"):addClass("empty")
  end

  for d = 1, dim do
    local cell = grid:tag("div"):addClass("calendar-day")

    if hasEvents[d] then cell:addClass("has-events") end
    if y == nowY and m == nowM and d == nowD then cell:addClass("today") end

    cell:wikitext(prefix_day_link(base, y, m, d))
  end

  html:node(grid)

  return tostring(html)
end

return p