Module:Timeline: Difference between revisions

From aquila
Jump to navigation Jump to search
mNo edit summary
Tag: Reverted
mNo edit summary
Tag: Reverted
Line 13: Line 13:
     local categoryUpper = string.upper(category)
     local categoryUpper = string.upper(category)
      
      
     -- Fetch data from Cargo
     -- Query Cargo using preprocess to avoid argument table errors
     local cargoQuery = frame:callParserFunction('#cargo_query', {
     local query = string.format(
        tables = 'NewsPosts',
        '<div>{{#cargo_query:tables=NewsPosts|fields=Page_Name,Title,Author,Publisher,DayNum|where=YearNum=%d AND Type="%s News"|order by=RealDate ASC}}</div>',
        fields = 'Page_Name,Title,Type,RealDate,Author,Publisher,DayNum',
         year, categoryUpper
        where = 'YearNum=' .. tostring(year) .. ' AND Type="' .. categoryUpper .. ' News"',
    )
         order_by = 'DayNum ASC, RealDate ASC'
     local cargoHTML = frame:preprocess(query)
     })
      
      
    -- Parse Cargo results
     local events = {}
     local events = {}
     for i = 1, 14 do events[i] = {} end
     for i = 1, 14 do events[i] = {} end
      
      
     -- Simple parser for Cargo's template output
     -- Extract rows from the raw HTML Cargo outputs
    local rows = {}
     for row in string.gmatch(cargoHTML, "<tr>(.-)</tr>") do
     for row in string.gmatch(cargoQuery, "<tr>(.-)</tr>") do
        -- Matches the 5 columns we requested
         local title, page, author, publisher, day = string.match(row, "<td>(.-)</td><td>(.-)</td><td>(.-)</td><td>(.-)</td><td>(.-)</td>")
         local page, title, author, publisher, day = string.match(row, "<td>(.-)</td>%s*<td>(.-)</td>%s*<td>(.-)</td>%s*<td>(.-)</td>%s*<td>(.-)</td>")
         if day then
         if day then
             local d = tonumber(day)
             local d = tonumber(day)
             if d and d >= 1 and d <= 14 then
             if d and d >= 1 and d <= 14 then
                -- If Author is empty, use Publisher
                local charName = (author ~= "" and author) or publisher
                 table.insert(events[d], {
                 table.insert(events[d], {
                     Post = title,
                     Post = title,
                     Page = page,
                     Page = page,
                     Char = author ~= "" and author or publisher,
                     Char = charName,
                     Date = "Auto" -- Handled by Cargo real date if needed
                     Date = "Auto" -- Handled by Lua calculation below
                 })
                 })
             end
             end
Line 42: Line 42:
     end
     end
      
      
     -- Add manual events from Day1...Day14 parameters
     -- Add manual events from Day1...Day14 parameters (for events without wiki pages)
     for i = 1, 14 do
     for i = 1, 14 do
         local manualData = frame.args["Day" .. i]
         local manualData = frame.args["Day" .. i]
Line 57: Line 57:
     end
     end


     -- Build the HTML table
     -- Build the beautiful HTML table
     local html = {}
     local html = {}
      
      
Line 65: Line 65:
      
      
     table.insert(html, '<div class="aquila-timeline-custom" style="border: 1px solid #d1d5db; border-radius: 12px; overflow: hidden; margin-bottom: 2em; box-shadow: 0 4px 12px rgba(0,0,0,0.05);">')
     table.insert(html, '<div class="aquila-timeline-custom" style="border: 1px solid #d1d5db; border-radius: 12px; overflow: hidden; margin-bottom: 2em; box-shadow: 0 4px 12px rgba(0,0,0,0.05);">')
    table.insert(html, '<table style="width: 100%; border-collapse: collapse; background: #ffffff; margin: 0;">')
      
      
     -- Table Header
     -- Table Header
    table.insert(html, '<table style="width: 100%; border-collapse: collapse; background: #ffffff; margin: 0;">')
     table.insert(html, '<tr>')
     table.insert(html, '<tr>')
     table.insert(html, '<th colspan="4" style="background: ' .. headerBg .. '; color: #ffffff; font-family: \'Georgia\', serif; font-size: 1.1em; letter-spacing: 0.1em; text-align: center; padding: 12px; border-bottom: 3px solid #e0a96d;">' .. categoryUpper .. ' NEWS</th>')
     table.insert(html, '<th colspan="4" style="background: ' .. headerBg .. '; color: #ffffff; font-family: \'Georgia\', serif; font-size: 1.1em; letter-spacing: 0.1em; text-align: center; padding: 12px; border-bottom: 3px solid #e0a96d;">' .. categoryUpper .. ' NEWS</th>')
Line 89: Line 89:
              
              
             if eventCount == 0 then
             if eventCount == 0 then
                 -- Empty Day Logic
                 -- Empty Day Logic (merges consecutive empty days)
                 local emptySpan = 1
                 local emptySpan = 1
                 for j = i + 1, 14 do
                 for j = i + 1, 14 do
Line 119: Line 119:
                  
                  
                 for idx, event in ipairs(events[i]) do
                 for idx, event in ipairs(events[i]) do
                     table.insert(html, '<tr style="background: #ffffff; transition: background 0.2s;">')
                     table.insert(html, '<tr style="background: #ffffff;">')
                      
                      
                     -- Date Column (Only on first row of the day)
                     -- Date Column (Only on first row of the day)
Line 142: Line 142:
                     table.insert(html, '<td style="padding: 12px 10px; border-bottom: 1px solid #e2e8f0; border-right: 1px solid #e2e8f0; vertical-align: top;">' .. charText .. '</td>')
                     table.insert(html, '<td style="padding: 12px 10px; border-bottom: 1px solid #e2e8f0; border-right: 1px solid #e2e8f0; vertical-align: top;">' .. charText .. '</td>')
                      
                      
                     -- Date Column
                     -- Real Date Column
                     local realDate = event.Date or ""
                     local realDate = event.Date or ""
                     if realDate == "Auto" then
                     if realDate == "Auto" then
                        -- Year 1, Day 1 is 2026-07-28. Every year is 14 days.
                         local daysOffset = ((year - 1) * 14) + (i - 1)
                         local daysOffset = ((year - 1) * 14) + (i - 1)
                         local timestamp = os.time({year=2026, month=07, day=28, hour=12}) + (daysOffset * 86400)
                         local timestamp = os.time({year=2026, month=07, day=28, hour=12}) + (daysOffset * 86400)

Revision as of 10:42, 24 October 2026

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

local p = {}

local dayLabels = {
    "Early January", "January--February", "February--March", "March--April", 
    "April--May", "May--June", "June", "June--July", "July--August", 
    "August--September", "September--October", "October--November", 
    "November--December", "Late December"
}

function p.render(frame)
    local year = tonumber(frame.args["Year"])
    local category = frame.args["Category"]
    local categoryUpper = string.upper(category)
    
    -- Query Cargo using preprocess to avoid argument table errors
    local query = string.format(
        '<div>{{#cargo_query:tables=NewsPosts|fields=Page_Name,Title,Author,Publisher,DayNum|where=YearNum=%d AND Type="%s News"|order by=RealDate ASC}}</div>',
        year, categoryUpper
    )
    local cargoHTML = frame:preprocess(query)
    
    local events = {}
    for i = 1, 14 do events[i] = {} end
    
    -- Extract rows from the raw HTML Cargo outputs
    for row in string.gmatch(cargoHTML, "<tr>(.-)</tr>") do
        -- Matches the 5 columns we requested
        local page, title, author, publisher, day = string.match(row, "<td>(.-)</td>%s*<td>(.-)</td>%s*<td>(.-)</td>%s*<td>(.-)</td>%s*<td>(.-)</td>")
        if day then
            local d = tonumber(day)
            if d and d >= 1 and d <= 14 then
                -- If Author is empty, use Publisher
                local charName = (author ~= "" and author) or publisher
                table.insert(events[d], {
                    Post = title,
                    Page = page,
                    Char = charName,
                    Date = "Auto" -- Handled by Lua calculation below
                })
            end
        end
    end
    
    -- Add manual events from Day1...Day14 parameters (for events without wiki pages)
    for i = 1, 14 do
        local manualData = frame.args["Day" .. i]
        if manualData and manualData ~= "" then
            for line in string.gmatch(manualData, "[^\r\n]+") do
                local post, char = string.match(line, "^%s*(.-)%s*;%s*(.-)%s*$")
                if post and post ~= "" then
                    table.insert(events[i], { Post = post, Char = char or "" })
                elseif post == nil and line ~= "" then
                    table.insert(events[i], { Post = line, Char = "" })
                end
            end
        end
    end

    -- Build the beautiful HTML table
    local html = {}
    
    -- Determine accent color based on category
    local headerBg = "#3a506b" -- Default slate
    if categoryUpper == "CHARACTER" then headerBg = "#6e473b" end
    
    table.insert(html, '<div class="aquila-timeline-custom" style="border: 1px solid #d1d5db; border-radius: 12px; overflow: hidden; margin-bottom: 2em; box-shadow: 0 4px 12px rgba(0,0,0,0.05);">')
    table.insert(html, '<table style="width: 100%; border-collapse: collapse; background: #ffffff; margin: 0;">')
    
    -- Table Header
    table.insert(html, '<tr>')
    table.insert(html, '<th colspan="4" style="background: ' .. headerBg .. '; color: #ffffff; font-family: \'Georgia\', serif; font-size: 1.1em; letter-spacing: 0.1em; text-align: center; padding: 12px; border-bottom: 3px solid #e0a96d;">' .. categoryUpper .. ' NEWS</th>')
    table.insert(html, '</tr>')
    
    -- Column Headers
    table.insert(html, '<tr>')
    table.insert(html, '<th style="background: #f8fafc; color: #1e293b; font-family: \'Georgia\', serif; padding: 10px; text-align: left; border-bottom: 2px solid #e2e8f0; width: 20%;">In-universe date</th>')
    table.insert(html, '<th style="background: #f8fafc; color: #1e293b; font-family: \'Georgia\', serif; padding: 10px; text-align: left; border-bottom: 2px solid #e2e8f0; width: 35%;">Post</th>')
    table.insert(html, '<th style="background: #f8fafc; color: #1e293b; font-family: \'Georgia\', serif; padding: 10px; text-align: left; border-bottom: 2px solid #e2e8f0; width: 25%;">Character / nation</th>')
    table.insert(html, '<th style="background: #f8fafc; color: #1e293b; font-family: \'Georgia\', serif; padding: 10px; text-align: left; border-bottom: 2px solid #e2e8f0; width: 20%;">Real-world date</th>')
    table.insert(html, '</tr>')

    -- Loop through days
    local skipRows = 0
    for i = 1, 14 do
        if skipRows > 0 then
            skipRows = skipRows - 1
        else
            local eventCount = #events[i]
            
            if eventCount == 0 then
                -- Empty Day Logic (merges consecutive empty days)
                local emptySpan = 1
                for j = i + 1, 14 do
                    if #events[j] == 0 then
                        emptySpan = emptySpan + 1
                    else
                        break
                    end
                end
                
                local dateLabel = dayLabels[i]
                if emptySpan > 1 then
                    dateLabel = dayLabels[i] .. " to " .. dayLabels[i + emptySpan - 1]
                end
                dateLabel = dateLabel .. ", Year " .. year
                
                table.insert(html, '<tr style="background: #fcfcfd;">')
                table.insert(html, '<td style="padding: 12px 10px; border-bottom: 1px solid #e2e8f0; color: #64748b; font-style: italic; font-size: 0.9em;">' .. dateLabel .. '</td>')
                table.insert(html, '<td colspan="3" style="padding: 12px 10px; border-bottom: 1px solid #e2e8f0; color: #94a3b8; font-style: italic;">No news</td>')
                table.insert(html, '</tr>')
                
                skipRows = emptySpan - 1
            else
                -- Event Logic
                local rowspanAttr = ''
                if eventCount > 1 then
                    rowspanAttr = ' rowspan="' .. eventCount .. '" '
                end
                
                for idx, event in ipairs(events[i]) do
                    table.insert(html, '<tr style="background: #ffffff;">')
                    
                    -- Date Column (Only on first row of the day)
                    if idx == 1 then
                        table.insert(html, '<td' .. rowspanAttr .. 'style="padding: 12px 10px; border-bottom: 1px solid #e2e8f0; border-right: 1px solid #e2e8f0; font-weight: bold; color: #1e293b; vertical-align: top;">' .. dayLabels[i] .. ', Year ' .. year .. '</td>')
                    end
                    
                    -- Post Column
                    local postText = event.Post
                    if event.Page and event.Page ~= "" then
                        postText = '[[' .. event.Page .. '|' .. event.Post .. ']]'
                    elseif not string.find(postText, "%[%[") and not string.find(postText, "<span>") then
                        postText = '[[' .. postText .. ']]'
                    end
                    table.insert(html, '<td style="padding: 12px 10px; border-bottom: 1px solid #e2e8f0; border-right: 1px solid #e2e8f0; vertical-align: top;">' .. postText .. '</td>')
                    
                    -- Character Column
                    local charText = event.Char or ""
                    if charText ~= "" and not string.find(charText, "%[%[") and not string.find(charText, "<span>") then
                        charText = '[[' .. charText .. ']]'
                    end
                    table.insert(html, '<td style="padding: 12px 10px; border-bottom: 1px solid #e2e8f0; border-right: 1px solid #e2e8f0; vertical-align: top;">' .. charText .. '</td>')
                    
                    -- Real Date Column
                    local realDate = event.Date or ""
                    if realDate == "Auto" then
                        -- Year 1, Day 1 is 2026-07-28. Every year is 14 days.
                        local daysOffset = ((year - 1) * 14) + (i - 1)
                        local timestamp = os.time({year=2026, month=07, day=28, hour=12}) + (daysOffset * 86400)
                        realDate = os.date("%Y-%m-%d", timestamp)
                    end
                    table.insert(html, '<td style="padding: 12px 10px; border-bottom: 1px solid #e2e8f0; vertical-align: top; color: #64748b; font-size: 0.9em; white-space: nowrap;">' .. realDate .. '</td>')
                    
                    table.insert(html, '</tr>')
                end
            end
        end
    end

    table.insert(html, '</table>')
    table.insert(html, '</div>')
    
    return table.concat(html, "\n")
end

return p