Editing Module:Feedback
From The Petit Planet Wiki
More actions
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 2: | Line 2: | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
-- | -- Helpers | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
local function isTruthy( | local function isTruthy(v) | ||
if | if v == nil then | ||
return false | return false | ||
end | end | ||
v = mw.text.trim(tostring(v)):lower() | |||
return | return v ~= '' | ||
and v ~= '0' | |||
and v ~= 'false' | |||
and v ~= 'no' | |||
and v ~= 'off' | |||
end | end | ||
local function formatUser(user) | local function formatUser(user) | ||
user = trim(user) | user = mw.text.trim(tostring(user or '')) | ||
if user == '' then | if user == '' or user:lower() == 'anonymous' then | ||
return 'Anonymous' | return 'Anonymous' | ||
end | end | ||
| Line 43: | Line 35: | ||
------------------------------------------------------------ | |||
-- Feedback card | |||
------------------------------------------------------------ | |||
local function renderCard(entry, showInstruction) | |||
local resolved = (entry.status == 'resolved') | |||
local user = | |||
entry.user | |||
or 'Anonymous' | |||
local | local feedback = | ||
entry.feedback | |||
or 'No feedback provided' | |||
local page = | |||
entry.page | |||
local id = | |||
mw.text.trim( | |||
tostring(entry.id or '') | |||
local | |||
mw. | |||
) | ) | ||
local resolvedBy = | |||
mw.text.trim( | |||
tostring(entry.resolvedby or '') | |||
) | ) | ||
local resolvedDate = | |||
mw.text.trim( | |||
tostring(entry.resolveddate or '') | |||
) | ) | ||
local root = mw.html.create('div') | |||
:addClass('feedback-box') | |||
' | :addClass( | ||
resolved | |||
and 'feedback-box--resolved' | |||
or 'feedback-box--unresolved' | |||
) | ) | ||
-------------------------------------------------------- | |||
-- Meta | |||
-------------------------------------------------------- | |||
local meta = root:tag('div') | |||
:addClass('feedback-meta') | |||
- | |||
if page and page ~= '' then | |||
page | |||
meta:tag('span') | |||
:addClass('feedback-page') | |||
:wikitext( | |||
string.format( | |||
'[[%s]]', | |||
page | |||
:addClass('feedback- | ) | ||
: | |||
) | ) | ||
meta:tag('span') | |||
:addClass('feedback-separator') | |||
:wikitext(' • ') | |||
: | |||
:wikitext(' | |||
end | end | ||
meta:tag('span') | |||
:addClass('feedback-user') | |||
:wikitext( | |||
formatUser(user) | |||
) | |||
) | ) | ||
meta:tag('span') | |||
:addClass('feedback-separator') | |||
:wikitext(' • ') | |||
meta:tag('span') | |||
:addClass('feedback-status') | :addClass('feedback-status') | ||
:addClass( | :addClass( | ||
| Line 331: | Line 124: | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- Feedback | -- Feedback | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
root:tag('div') | |||
:addClass('feedback- | :addClass('feedback-body') | ||
:wikitext( | :wikitext(feedback) | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- | -- Resolution information | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
if resolved and resolvedBy ~= '' then | |||
local resolution = | |||
root:tag('div') | |||
' | :addClass('feedback-resolution') | ||
resolution:wikitext( | |||
'Resolved by ' | |||
.. formatUser(resolvedBy) | |||
) | ) | ||
if resolvedDate ~= '' then | |||
resolution:wikitext( | |||
' on ' | |||
.. mw.text.nowiki(resolvedDate) | |||
) | |||
end | |||
end | end | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- | -- Resolve instruction | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
if showInstruction and not resolved then | |||
local instruction = | |||
root:tag('div') | |||
:addClass('feedback-instruction') | |||
if id ~= '' then | |||
instruction:wikitext( | |||
'If this feedback has been resolved, click the button below. ' | |||
:wikitext( | |||
' | |||
) | ) | ||
-- Use an <a> instead of <button>. | |||
-- MediaWiki sanitizes <button> when returned from wikitext. | |||
instruction:tag('a') | |||
:addClass('feedback-resolve-button') | |||
:attr('href', '#') | |||
:attr('role', 'button') | |||
:attr('data-feedback-id', id) | |||
:wikitext('Resolve') | |||
else | |||
instruction:wikitext( | |||
'Add an ID to this feedback to enable the Resolve button.' | |||
) | |||
end | |||
end | end | ||
| Line 413: | Line 193: | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
-- | -- Save feedback | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
local function | local function saveFeedback(data) | ||
if not (mw.ext and mw.ext.bucket) then | |||
return false, 'Bucket extension is not available' | |||
end | |||
local bucket = | |||
mw.ext.bucket('feedback') | |||
local bucket = | |||
if not bucket then | if not bucket then | ||
return false, ' | return false, 'Feedback bucket could not be opened' | ||
end | end | ||
local success, err = pcall(function() | local success, err = pcall(function() | ||
bucket.put({ | bucket.put({ | ||
page = data.page, | page = data.page, | ||
| Line 439: | Line 217: | ||
feedback = data.feedback, | feedback = data.feedback, | ||
id = data.id, | id = data.id, | ||
resolvedby = data.resolvedby, | resolvedby = data.resolvedby, | ||
resolveddate = data.resolveddate | resolveddate = data.resolveddate | ||
}) | }) | ||
end) | end) | ||
| Line 456: | Line 232: | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
-- | -- Main | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
function p.main(frame) | function p.main(frame) | ||
local parent = frame:getParent() | |||
local parent = | |||
frame:getParent() | |||
local args = | local args = | ||
| Line 471: | Line 247: | ||
if parent and parent.getTitle then | if parent and parent.getTitle then | ||
local title = parent:getTitle() | |||
local title = | |||
parent:getTitle() | |||
if title | if title | ||
| Line 489: | Line 267: | ||
function p._main(args, pageTitle) | function p._main(args, pageTitle) | ||
local feedback = | local feedback = | ||
args.feedback | |||
or 'No feedback provided' | |||
local user = | |||
args.user | |||
or 'Anonymous' | |||
local id = | |||
args.id | |||
or '' | |||
local | local resolvedBy = | ||
args.resolvedby | |||
or '' | |||
local resolvedDate = | |||
args.resolveddate | |||
or '' | |||
local resolved = | local resolved = | ||
| Line 512: | Line 297: | ||
local currentPage = | local currentPage = | ||
pageTitle | |||
or mw.title.getCurrentTitle().fullText | |||
-------------------------------------------------------- | -------------------------------------------------------- | ||
| Line 548: | Line 311: | ||
feedback = feedback, | feedback = feedback, | ||
id = id, | id = id, | ||
resolvedby = resolvedBy, | |||
resolveddate = resolvedDate | |||
resolvedby = | |||
resolveddate = | |||
}) | }) | ||
if not saved then | if not saved then | ||
return | return '<strong style="color:red;">Feedback bucket error: ' | ||
.. mw.text.nowiki( | .. mw.text.nowiki( | ||
saveError or 'Unknown error' | saveError or 'Unknown error' | ||
| Line 565: | Line 324: | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- Render | -- Render card | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
local card = | local card = | ||
renderCard({ | |||
page = | page = nil, | ||
user = user, | user = user, | ||
status = status, | status = status, | ||
feedback = feedback, | feedback = feedback, | ||
id = id, | id = id, | ||
resolvedby = resolvedBy, | |||
resolveddate = resolvedDate | |||
}, true) | |||
resolvedby = | |||
resolveddate = | |||
}) | |||
-------------------------------------------------------- | -------------------------------------------------------- | ||
| Line 586: | Line 342: | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
local | local categories = {} | ||
if resolved then | if resolved then | ||
table.insert( | |||
categories, | |||
'[[Category:Resolved Feedback]]' | '[[Category:Resolved Feedback]]' | ||
) | |||
else | else | ||
table.insert( | |||
categories, | |||
'[[Category:Unresolved Feedback]]' | '[[Category:Unresolved Feedback]]' | ||
) | |||
end | end | ||
if id == '' then | if mw.text.trim( | ||
tostring(id) | |||
) == '' then | |||
table.insert( | |||
categories, | |||
'[[Category:Feedbacks Missing ID]]' | '[[Category:Feedbacks Missing ID]]' | ||
) | |||
end | end | ||
return card .. | return card | ||
.. table.concat(categories) | |||
end | end | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
-- | -- Render feedback list | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
local function renderFeedbackList(results) | local function renderFeedbackList(results) | ||
if not results or #results == 0 then | if not results or #results == 0 then | ||
return '<em>No feedback entries found.</em>' | return '<em>No feedback entries found.</em>' | ||
| Line 618: | Line 389: | ||
for _, row in ipairs(results) do | for _, row in ipairs(results) do | ||
table.insert( | table.insert( | ||
list, | list, | ||
renderCard( | |||
row, | |||
false | |||
) | |||
) | ) | ||
end | end | ||
| Line 632: | Line 408: | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
-- | -- View feedback | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
function p. | function p.view(frame) | ||
local | |||
local parent = | |||
frame:getParent() | |||
local args | |||
if frame | |||
and frame.args | |||
and frame.args.status | |||
then | |||
args = | |||
frame.args | |||
elseif parent | |||
and parent.args | |||
and parent.args.status | |||
then | |||
args = | |||
parent.args | |||
elseif frame | |||
and frame.args | |||
then | |||
args = | |||
frame.args | |||
elseif parent | |||
and parent.args | |||
then | |||
args = | |||
parent.args | |||
else | |||
args = {} | |||
end | |||
return p._view( | |||
args, | |||
frame | |||
) | ) | ||
end | |||
function p._view(args, frame) | |||
if not (mw.ext and mw.ext.bucket) then | |||
return '<em>Bucket extension is not available.</em>' | |||
end | end | ||
frame = | |||
frame | |||
or mw.getCurrentFrame() | |||
local rawStatus = | |||
args.status | |||
or args[1] | |||
local filterStatus = | |||
rawStatus | |||
and mw.text.trim(rawStatus):lower() | |||
or nil | |||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- | -- Filtered views | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
if filterStatus == 'resolved' | |||
or filterStatus == 'unresolved' | |||
then | |||
local query = | |||
mw.ext.bucket('feedback') | |||
query.select( | |||
'page', | |||
'user', | |||
'status', | |||
'feedback', | |||
'id', | |||
'resolvedby', | |||
'resolveddate' | |||
) | |||
query.where( | |||
'status', | |||
filterStatus | |||
) | |||
return renderFeedbackList( | |||
query.run() | |||
) | |||
end | end | ||
| Line 787: | Line 515: | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
if filterStatus == 'all' then | |||
local query = | |||
mw.ext.bucket('feedback') | |||
query.select( | |||
'page', | |||
'user', | |||
'status', | |||
'feedback', | |||
'id', | |||
'resolvedby', | |||
'resolveddate' | |||
) | |||
return renderFeedbackList( | |||
query.run() | |||
) | ) | ||
end | |||
-------------------------------------------------------- | |||
-- Default tabbed view | |||
-------------------------------------------------------- | |||
local qAll = | |||
mw.ext.bucket('feedback') | |||
qAll.select( | |||
'page', | |||
'user', | |||
'status', | |||
'feedback', | |||
'id', | |||
'resolvedby', | |||
'resolveddate' | |||
) | ) | ||
local allEntries = | |||
qAll.run() | |||
local allList = {} | |||
local unresolvedList = {} | |||
local resolvedList = {} | |||
if allEntries and #allEntries > 0 then | |||
if | |||
for _, row in ipairs(allEntries) do | |||
local card = | |||
renderCard( | |||
row, | |||
false | |||
) | |||
table.insert( | |||
allList, | |||
card | |||
) | |||
if row.status == 'resolved' then | |||
table.insert( | |||
resolvedList, | |||
card | |||
) | |||
else | |||
table.insert( | |||
unresolvedList, | |||
card | |||
) | |||
end | |||
end | |||
end | |||
-------------------------------------------------------- | |||
-- All content | |||
-------------------------------------------------------- | |||
local allContent | |||
if #allList > 0 then | |||
allContent = | |||
table.concat( | |||
allList, | |||
'\n' | |||
) | ) | ||
else | |||
allContent = | |||
'<em>No feedback entries found.</em>' | |||
end | end | ||
-------------------------------------------------------- | |||
-- Unresolved content | |||
-------------------------------------------------------- | |||
local unresolvedContent | |||
if #unresolvedList > 0 then | |||
unresolvedContent = | |||
table.concat( | |||
unresolvedList, | |||
'\n' | |||
) | |||
else | else | ||
unresolvedContent = | |||
'<em>No unresolved feedback entries found.</em>' | |||
end | end | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- | -- Resolved content | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
local | local resolvedContent | ||
if #resolvedList > 0 then | |||
resolvedContent = | |||
table.concat( | |||
resolvedList, | |||
'\n' | |||
) | |||
else | |||
resolvedContent = | |||
'<em>No resolved feedback entries found.</em>' | |||
end | end | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- | -- Tabber | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
local tabberBody = | |||
string.format( | |||
'All=\n%s\n|-|Unresolved=\n%s\n|-|Resolved=\n%s', | |||
allContent, | |||
unresolvedContent, | |||
resolvedContent | |||
) | ) | ||
return frame:callParserFunction( | |||
'#tag', | |||
{ | |||
'tabber', | |||
tabberBody | |||
} | |||
) | |||
end | end | ||
return p | return p | ||