Module:Arbcom election banner
Yi palo
Documentation for this module may be created at Module:Arbcom election banner/doc
local messageBox = require('Module:Message box')
local navbarModule = require('Module:Navbar')
local horizontal = require('Module:List').horizontal
local p = {}
-- Get constants.
local lang = mw.language.getContentLanguage()
local currentUnixDate = tonumber(lang:formatDate('U'))
local function err(msg)
return mw.ustring.format('<strong class="error">%s</strong>', msg)
end
local function getUnixDate(date)
local success, unixDate = pcall(lang.formatDate, lang, 'U', date)
if success then
return tonumber(unixDate)
end
end
local function unixDateError(date)
return err(tostring(date) .. ' is not a valid date.')
end
local function makeOmbox(oargs)
return messageBox.main('ombox', oargs)
end
local function makeNavbar(name)
return navbarModule.navbar{name, mini = '1'}
end
local function randomizeArray(t)
-- Iterate through the array backwards, each time swapping the entry "i" with a random entry.
-- Courtesy of Xinhuan at http://forums.wowace.com/showthread.php?p=279756
math.randomseed(mw.site.stats.edits)
for i = #t, 2, -1 do
local r = math.random(i)
t[i], t[r] = t[r], t[i]
end
return t
end
local function getArgNums(args, prefix)
-- Returns a table containing the numbers of the arguments that exist for the specified prefix. For example, if the prefix
-- was 'data', and 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}.
local nums = {}
for k, v in pairs(args) do
k = tostring(k)
local num = mw.ustring.match(k, '^' .. prefix .. '([1-9]%d*)$')
if num then
table.insert(nums, tonumber(num))
end
end
table.sort(nums)
return nums
end
local function showBeforeDate(datePairs)
-- Shows a value if it is before a given date.
for i, datePair in ipairs(datePairs) do
local date = datePair.date
local val = datePair.val
if not date then -- No date specified, so assume we have no more dates to process.
return val
end
local unixDate = getUnixDate(date)
if not unixDate then return unixDateError(date) end
if currentUnixDate < unixDate then -- The specified date is in the future.
return val
end
end
end
local function countdown(date, event)
if type(event) ~= 'string' then return err('No event name provided.') end
-- Get the current date unix timestamp.
local unixDate = getUnixDate(date)
if not unixDate then return unixDateError(date) end
unixDate = tonumber(unixDate)
-- Subtract the timestamp from the current unix timestamp to find the time left, and output that in a readable way.
local secondsLeft = unixDate - currentUnixDate
if secondsLeft <= 0 then return end
local timeLeft = lang:formatDuration(secondsLeft, {'weeks', 'days', 'hours'})
-- Find whether we are plural or not.
local isOrAre
if mw.ustring.match(timeLeft, '^%d+') == '1' then
isOrAre = 'is'
else
isOrAre = 'are'
end
local timeLeft = mw.ustring.gsub(timeLeft, '(%d+)', '<span class="ace-banner-timeleft">%1</span>')
-- Make the refresh link, and join it all together.
local refreshLink = mw.title.getCurrentTitle():fullUrl{action = 'purge'}
refreshLink = mw.ustring.format('<span class="ace-banner-refresh plainlinks">([%s refresh])</span>', refreshLink)
return mw.ustring.format('There %s %s until %s. %s', isOrAre, timeLeft, event, refreshLink)
end
local function format_guides(args)
local guideNums = getArgNums(args, 'guide')
local guides = {}
for _, num in ipairs(guideNums) do
table.insert(guides, args['guide' .. tostring(num)])
end
local guide_text = '\nThese [[:Category:Wikipedia Arbitration Committee Elections 2022 voter guides|guides]] represent the thoughts of their authors. All individually written voter guides are eligible for inclusion. Guides to other guides are ineligible.\n'
guides = randomizeArray(guides)
guides = horizontal(guides)
local ret = [=[
<div class="mw-collapsible mw-collapsed">
<div class="ace-banner-guides-title"><div>Personal voter guides</div></div>
<div class="mw-collapsible-content">%s%s</div>
</div>]=]
return mw.ustring.format(ret, guide_text, guides)
end
function p._main(args)
-- Get data for the box, plus the box title.
local year = lang:formatDate('Y')
local name = args.name or 'ACE' .. year
local navbar = makeNavbar(name)
local electionpage = args.electionpage or mw.ustring.format(
'[[Wikipedia:Arbitration Committee Elections December %s|%s Arbitration Committee Elections]]',
year, year
)
-- Get nomination or voting link, depending on the date.
local beforenomlink = args.beforenomlink or mw.ustring.format('[[Wikipedia:Requests for comment/Arbitration Committee Elections December %s/Electoral Commission|Electoral Commission RFC]]', year)
local nomstart = args.nomstart or error('No nomstart date supplied')
local nomlink = args.nomlink or mw.ustring.format('[[Wikipedia:Arbitration Committee Elections December %s/Candidates|Nominate]]', year)
local nomend = args.nomend or error('No nomend date supplied')
local votestart = args.votestart or error('No votestart date supplied')
local votepage = args.votepage or '[[Special:SecurePoll|Cast your vote]]'
local votelink = args.votelink or mw.ustring.format('<span class="ace-banner-votelink">%s</span>', votepage)
local votelog = args.votelog or mw.ustring.format('[[Wikipedia:Arbitration Committee Elections December %s/Log|Voter log]]', year)
local voteend = args.voteend or error('No voteend date supplied')
local voteendlink = args.voteendlink or votelog
local scheduleText = showBeforeDate{
{val = beforenomlink, date = nomstart},
{val = nomlink, date = nomend},
{val = countdown(votestart, 'voting begins'), date = votestart},
{val = votelink, date = voteend},
{val = voteendlink}
}
-- support votelog as its own element. must be done after we have scheduleText
if scheduleText ~= votelink then
votelog = nil
end
-- Get other links.
local contact = args.contact or mw.ustring.format('[[WT:COORD%s|Contact the coordinators]]', mw.ustring.sub(year, 3, 4))
local discuss = args.discuss or mw.ustring.format('[[WT:ACE%s|Discuss the elections]]', year)
local cguide = args.cguide or mw.ustring.format('[[Wikipedia:Arbitration Committee Elections December %s/Candidates/Guide|Candidate guide]]', year)
local cstatements = args.cstatements or mw.ustring.format('[[Wikipedia:Arbitration Committee Elections December %s/Candidates|Candidate statements]]', year)
local cquestions = args.cquestions or mw.ustring.format('[[Wikipedia:Arbitration Committee Elections December %s/Questions|Questions for the candidates]]', year)
local cdiscuss = args.cdiscuss or mw.ustring.format('[[Wikipedia:Arbitration Committee Elections December %s/Candidates/Discussion|Discuss the candidates]]', year)
local guides = format_guides(args)
-- Get the text field of ombox.
local lead_links = horizontal({
class = 'ace-banner-lead-links',
'<span class="ace-banner-mainpage">' .. electionpage .. '</span>',
scheduleText,
votelog,
contact,
discuss,
'[[Wikipedia:5-minute guide to ArbCom elections|Quick guide]]'
})
local candidate_links = horizontal({
class = 'ace-banner-candidates-links inline',
cguide,
cstatements,
cquestions,
cdiscuss,
})
return makeOmbox({
image = args.image or '[[File:Judges cupola.svg|50px|ArbCom|link=]]',
style = args.style or nil,
text = mw.ustring.format(
'<div class="ace-banner-navbar">%s</div>%s<span class="ace-banner-candidates">Candidates: </span>%s%s',
navbar,
lead_links,
candidate_links,
guides
),
templatestyles = 'Module:Arbcom election banner/styles.css',
class = 'ace-banner'
})
end
function p.main(frame)
-- If called via #invoke, use the args passed into the invoking template, or the args passed to #invoke if any exist.
-- Otherwise assume args are being passed directly in from the debug console or from another Lua module.
local origArgs
if frame == mw.getCurrentFrame() then
origArgs = frame:getParent().args
for k, v in pairs(frame.args) do
origArgs = frame.args
break
end
else
origArgs = frame
end
-- Trim whitespace and remove blank arguments.
local args = {}
for k, v in pairs(origArgs) do
if type(v) == 'string' then
v = mw.text.trim(v)
end
if v ~= '' then
args[k] = v
end
end
return p._main(args)
end
return p