Editing Module:User:Kai/sandboxGive feedback
Jump to navigation
Jump to search
The edit can be undone.
Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
| Latest revision | Your text | ||
| Line 1: | Line 1: | ||
local p = {} | |||
local function isTruthy(v) | |||
if v == nil then | |||
return false | |||
end | |||
v = mw.text.trim(tostring(v)):lower() | |||
return v ~= '' and v ~= '0' and v ~= 'false' and v ~= 'no' and v ~= 'off' | |||
end | |||
local function formatUser(user) | |||
user = mw.text.trim(tostring(user or '')) | |||
if user == '' or user:lower() == 'anonymous' then | |||
return 'Anonymous' | |||
end | |||
return string.format('[[User:%s|%s]]', user, user) | |||
end | |||
-- Renders the individual feedback visual card | |||
local function renderCard(user, feedback, resolved, pageName) | |||
local root = mw.html.create('div') | |||
:addClass('feedback-box') | |||
:addClass(resolved and 'feedback-box--resolved' or 'feedback-box--unresolved') | |||
local meta = root:tag('div') | |||
:addClass('feedback-meta') | |||
if pageName and pageName ~= '' then | |||
meta:tag('span') | |||
:addClass('feedback-page') | |||
:wikitext(string.format("'''[[%s]]'''", pageName)) | |||
meta:tag('span') | |||
:addClass('feedback-separator') | |||
:wikitext(' • ') | |||
end | |||
meta:tag('span') | |||
:addClass('feedback-user') | |||
:wikitext(formatUser(user)) | |||
meta:tag('span') | |||
:addClass('feedback-separator') | |||
:wikitext(' • ') | |||
meta:tag('span') | |||
:addClass('feedback-status') | |||
:addClass(resolved and 'feedback-status--resolved' or 'feedback-status--unresolved') | |||
:wikitext(resolved and 'Resolved' or 'Unresolved') | |||
root:tag('div') | |||
:addClass('feedback-body') | |||
:wikitext(feedback) | |||
if not resolved and (not pageName or pageName == '') then | |||
root:tag('div') | |||
:addClass('feedback-instruction') | |||
:wikitext('If this feedback has been resolved, edit this page and set <code>|resolved=true</code>.') | |||
end | |||
return tostring(root) | |||
end | |||
-- ========================================================================= | |||
-- 1. ARTICLE INGESTION & DISPLAY: {{#invoke:Feedback|main|...}} | |||
-- ========================================================================= | |||
function p.main(frame) | |||
local parent = frame:getParent() | |||
local args = parent and parent.args or frame.args | |||
return p._main(args) | |||
end | |||
function p._main(args) | |||
local feedback = args.feedback or "No feedback provided" | |||
local user = args.user or "Anonymous" | |||
local resolved = isTruthy(args.resolved) | |||
local statusStr = resolved and 'resolved' or 'unresolved' | |||
local currentPage = mw.title.getCurrentTitle().fullText | |||
-- Ingest to Bucket | |||
if mw.ext and mw.ext.bucket and mw.ext.bucket.put then | |||
mw.ext.bucket.put('feedback', { | |||
page = currentPage, | |||
user = user, | |||
status = statusStr, | |||
feedback = feedback | |||
}) | |||
elseif mw.ext and mw.ext.bucket then | |||
pcall(function() | |||
mw.ext.bucket('feedback').put({ | |||
page = currentPage, | |||
user = user, | |||
status = statusStr, | |||
feedback = feedback | |||
}) | |||
end) | |||
end | |||
local card = renderCard(user, feedback, resolved, nil) | |||
local category = resolved and '[[Category:Resolved Feedback]]' or '[[Category:Unresolved Feedback]]' | |||
return card .. category | |||
end | |||
-- ========================================================================= | |||
-- 2. DASHBOARD QUERY WITH TABBER: {{#invoke:Feedback|dashboard}} | |||
-- ========================================================================= | |||
function p.dashboard(frame) | |||
local rows = {} | |||
if mw.ext and mw.ext.bucket and mw.ext.bucket.query then | |||
rows = mw.ext.bucket.query('feedback', { | |||
fields = { 'page', 'user', 'status', 'feedback' } | |||
}) or {} | |||
end | |||
local allCards = {} | |||
local unresolvedCards = {} | |||
local resolvedCards = {} | |||
for _, row in ipairs(rows) do | |||
local isResolved = (row.status or ''):lower() == 'resolved' | |||
local card = renderCard(row.user or 'Anonymous', row.feedback or '', isResolved, row.page) | |||
table.insert(allCards, card) | |||
if isResolved then | |||
table.insert(resolvedCards, card) | |||
else | |||
table.insert(unresolvedCards, card) | |||
end | |||
end | |||
local function getListHtml(cards, emptyMsg) | |||
if #cards == 0 then | |||
return string.format('<div class="feedback-empty" style="padding: 12px; color: #72777d; font-style: italic;">%s</div>', emptyMsg) | |||
end | |||
return table.concat(cards, '\n\n') | |||
end | |||
-- Construct the raw wikitext for the <tabber> extension | |||
local tabberWikitext = string.format( | |||
'<tabber>\n' .. | |||
'Unresolved (%d)=\n%s\n' .. | |||
'|-|\n' .. | |||
'Resolved (%d)=\n%s\n' .. | |||
'|-|\n' .. | |||
'All (%d)=\n%s\n' .. | |||
'</tabber>', | |||
#unresolvedCards, getListHtml(unresolvedCards, 'No unresolved feedback found.'), | |||
#resolvedCards, getListHtml(resolvedCards, 'No resolved feedback found.'), | |||
#allCards, getListHtml(allCards, 'No feedback records found.') | |||
) | |||
-- Preprocess the wikitext so the tabber tags evaluate correctly | |||
return frame:preprocess(tabberWikitext) | |||
end | |||
return p | |||