Module:Feedback: Difference between revisions
From The Petit Planet Wiki
More actions
ReisuDesign (talk | contribs) No edit summary |
ReisuDesign (talk | contribs) No edit summary |
||
| Line 5: | Line 5: | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
local function isTruthy( | local function isTruthy(value) | ||
if | if value == nil then | ||
return false | return false | ||
end | end | ||
value = mw.text.trim(tostring(value)):lower() | |||
return | return value ~= '' | ||
and | and value ~= '0' | ||
and | and value ~= 'false' | ||
and | and value ~= 'no' | ||
and | and value ~= 'off' | ||
end | |||
local function trim(value) | |||
return mw.text.trim( | |||
tostring(value or '') | |||
) | |||
end | end | ||
local function formatUser(user) | local function formatUser(user) | ||
user = | user = trim(user) | ||
if user == '' or user:lower() == 'anonymous' then | if user == '' or user:lower() == 'anonymous' then | ||
| Line 32: | Line 39: | ||
user | user | ||
) | ) | ||
end | |||
local function currentSubjectPage() | |||
local title = | |||
mw.title.getCurrentTitle() | |||
return title.subjectPageTitle.fullText | |||
end | |||
local function getBucket() | |||
if not (mw.ext and mw.ext.bucket) then | |||
return nil, 'Bucket extension is not available' | |||
end | |||
local bucket = | |||
mw.ext.bucket('feedback') | |||
if not bucket then | |||
return nil, 'Feedback bucket could not be opened' | |||
end | |||
return bucket | |||
end | |||
local function sortNewestFirst(results) | |||
if not results then | |||
return {} | |||
end | |||
table.sort( | |||
results, | |||
function(a, b) | |||
local aDate = | |||
trim(a.createddate) | |||
local bDate = | |||
trim(b.createddate) | |||
-- Entries without a date go last. | |||
if aDate == '' and bDate ~= '' then | |||
return false | |||
end | |||
if aDate ~= '' and bDate == '' then | |||
return true | |||
end | |||
if aDate ~= bDate then | |||
return aDate > bDate | |||
end | |||
-- Stable-ish fallback. | |||
return trim(a.id) > trim(b.id) | |||
end | |||
) | |||
return results | |||
end | |||
local function queryFeedback(page, status) | |||
local bucket, err = | |||
getBucket() | |||
if not bucket then | |||
return nil, err | |||
end | |||
local query = | |||
bucket.select( | |||
'page', | |||
'user', | |||
'status', | |||
'feedback', | |||
'id', | |||
'createddate', | |||
'link', | |||
'image', | |||
'resolvedby', | |||
'resolveddate' | |||
) | |||
if page and page ~= '' then | |||
query.where( | |||
'page', | |||
page | |||
) | |||
end | |||
if status | |||
and status ~= '' | |||
and status ~= 'all' | |||
then | |||
query.where( | |||
'status', | |||
status | |||
) | |||
end | |||
local success, results = | |||
pcall(function() | |||
return query.run() | |||
end) | |||
if not success then | |||
return nil, tostring(results) | |||
end | |||
return sortNewestFirst( | |||
results or {} | |||
) | |||
end | |||
------------------------------------------------------------ | |||
-- Save feedback | |||
------------------------------------------------------------ | |||
local function saveFeedback(data) | |||
local bucket, err = | |||
getBucket() | |||
if not bucket then | |||
return false, err | |||
end | |||
local success, saveError = | |||
pcall(function() | |||
bucket.put({ | |||
page = data.page, | |||
user = data.user, | |||
status = data.status, | |||
feedback = data.feedback, | |||
id = data.id, | |||
createddate = data.createddate, | |||
link = data.link, | |||
image = data.image, | |||
resolvedby = data.resolvedby, | |||
resolveddate = data.resolveddate | |||
}) | |||
end) | |||
if not success then | |||
return false, tostring(saveError) | |||
end | |||
return true | |||
end | end | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
-- | -- Shared metadata | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
local function | local function renderMetadata(root, entry) | ||
local | local meta = | ||
(entry. | root:tag('div') | ||
:addClass('feedback-meta') | |||
if entry.user and entry.user ~= '' then | |||
meta:tag('span') | |||
:addClass('feedback-user') | |||
:wikitext( | |||
formatUser(entry.user) | |||
) | |||
end | |||
if entry.createddate | |||
and entry.createddate ~= '' | |||
then | |||
meta:tag('span') | |||
:addClass('feedback-meta-date') | |||
:wikitext( | |||
' · ' | |||
.. mw.text.nowiki( | |||
entry.createddate | |||
) | |||
) | |||
end | |||
end | |||
------------------------------------------------------------ | |||
-- Attachments | |||
------------------------------------------------------------ | |||
local function renderAttachments(root, entry) | |||
local link = | |||
trim(entry.link) | |||
local image = | |||
trim(entry.image) | |||
if link == '' | |||
and image == '' | |||
then | |||
return | |||
end | |||
local attachments = | |||
root:tag('div') | |||
:addClass('feedback-attachments') | |||
if link ~= '' then | |||
attachments:tag('span') | |||
:addClass('feedback-attachment') | |||
:wikitext( | |||
'🔗 ' | |||
.. '[' | |||
.. link | |||
.. ' Link]' | |||
) | |||
end | |||
if image ~= '' then | |||
attachments:tag('span') | |||
:addClass('feedback-attachment') | |||
attachments:tag('span') | |||
:addClass('feedback-image-icon') | |||
:wikitext('▣') | |||
attachments:tag('span') | |||
:addClass('feedback-image-link') | |||
:wikitext( | |||
'[[Media:' | |||
.. image | |||
.. '|Picture]]' | |||
) | |||
end | |||
end | |||
------------------------------------------------------------ | |||
-- Resolution information | |||
------------------------------------------------------------ | |||
local function renderResolution(root, entry) | |||
local resolvedBy = | local resolvedBy = | ||
trim(entry.resolvedby) | |||
local resolvedDate = | |||
trim(entry.resolveddate) | |||
if resolvedBy == '' | |||
and resolvedDate == '' | |||
then | |||
return | |||
end | |||
local resolution = | |||
root:tag('div') | |||
:addClass('feedback-resolution') | |||
resolution:wikitext('↳ Resolved by ') | |||
if resolvedBy ~= '' then | |||
resolution:wikitext( | |||
formatUser(resolvedBy) | |||
) | ) | ||
else | |||
resolution:wikitext('Unknown') | |||
end | |||
if resolvedDate ~= '' then | |||
mw.text. | resolution:wikitext( | ||
' on ' | |||
.. mw.text.nowiki(resolvedDate) | |||
) | ) | ||
end | |||
end | |||
------------------------------------------------------------ | |||
-- Resolve control | |||
------------------------------------------------------------ | |||
local function renderResolveControl( | |||
parent, | |||
id, | |||
compact | |||
) | |||
if not id or id == '' then | |||
return | |||
end | |||
local control = | |||
parent:tag('span') | |||
:addClass('feedback-resolve-button') | |||
if compact then | |||
control | |||
:addClass('feedback-resolve-button--compact') | |||
:attr('aria-label', 'Resolve feedback') | |||
:attr('title', 'Resolve feedback') | |||
:wikitext('✓') | |||
else | |||
control | |||
:attr('role', 'button') | |||
:attr('tabindex', '0') | |||
:attr('aria-label', 'Resolve feedback') | |||
:wikitext('Resolve') | |||
end | |||
control:attr( | |||
'data-feedback-id', | |||
id | |||
) | |||
end | |||
------------------------------------------------------------ | |||
-- Full feedback card | |||
------------------------------------------------------------ | |||
local function renderFullCard(entry) | |||
local resolved = | |||
entry.status == 'resolved' | |||
local id = | |||
trim(entry.id) | |||
local root = | local root = | ||
| Line 78: | Line 395: | ||
or 'feedback-box--unresolved' | or 'feedback-box--unresolved' | ||
) | ) | ||
if id ~= '' then | |||
root:attr( | |||
'data-feedback-id', | |||
id | |||
) | |||
end | |||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- | -- Main line | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
local | local main = | ||
root:tag('div') | root:tag('div') | ||
:addClass('feedback-meta') | :addClass('feedback-main-line') | ||
main:tag('span') | |||
:addClass('feedback-status') | |||
:addClass( | |||
resolved | |||
and 'feedback-status--resolved' | |||
or 'feedback-status--unresolved' | |||
) | |||
:wikitext( | |||
resolved | |||
and 'RESOLVED' | |||
or 'UNRESOLVED' | |||
) | |||
main:tag('span') | |||
:addClass('feedback-text') | |||
:wikitext( | |||
entry.feedback | |||
or 'No feedback provided' | |||
) | |||
-------------------------------------------------------- | |||
-- Metadata | |||
-------------------------------------------------------- | |||
local metadata = | |||
main:tag('span') | |||
:addClass('feedback-inline-meta') | |||
if entry.user | |||
and entry.user ~= '' | |||
then | |||
metadata:wikitext( | |||
' · ' | |||
.. formatUser(entry.user) | |||
) | |||
end | |||
if entry.createddate | |||
and entry.createddate ~= '' | |||
then | |||
metadata:wikitext( | |||
' ' | |||
.. mw.text.nowiki( | |||
entry.createddate | |||
) | |||
) | |||
end | |||
-------------------------------------------------------- | |||
-- Resolve button | |||
-------------------------------------------------------- | |||
if not resolved | |||
and id ~= '' | |||
then | |||
renderResolveControl( | |||
main, | |||
id, | |||
false | |||
) | |||
end | |||
-------------------------------------------------------- | |||
-- Attachments | |||
-------------------------------------------------------- | |||
renderAttachments( | |||
root, | |||
entry | |||
) | |||
-------------------------------------------------------- | |||
-- Resolution | |||
-------------------------------------------------------- | |||
if resolved then | |||
renderResolution( | |||
root, | |||
entry | |||
) | |||
end | |||
-------------------------------------------------------- | |||
-- Missing ID warning | |||
-------------------------------------------------------- | |||
if | if not resolved | ||
and id == '' | |||
then | |||
root:tag('div') | |||
:addClass('feedback- | :addClass('feedback-missing-id') | ||
:wikitext( | :wikitext( | ||
'Add an ID to enable the Resolve button.' | |||
) | ) | ||
end | |||
:addClass('feedback- | |||
: | return tostring(root) | ||
end | |||
------------------------------------------------------------ | |||
-- Compact article card | |||
------------------------------------------------------------ | |||
local function renderCompactCard(entry) | |||
local resolved = | |||
entry.status == 'resolved' | |||
local id = | |||
trim(entry.id) | |||
local root = | |||
mw.html.create('div') | |||
:addClass('feedback-page-card') | |||
:addClass( | |||
resolved | |||
and 'feedback-page-card--resolved' | |||
or 'feedback-page-card--unresolved' | |||
) | |||
if id ~= '' then | |||
root:attr( | |||
'data-feedback-id', | |||
id | |||
) | |||
end | end | ||
local content = | |||
root:tag('div') | |||
:addClass('feedback-page-card-content') | |||
local firstLine = | |||
content:tag('div') | |||
:addClass('feedback-page-card-line') | |||
firstLine:tag('span') | |||
:addClass('feedback-status') | :addClass('feedback-status') | ||
:addClass( | :addClass( | ||
| Line 123: | Line 564: | ||
:wikitext( | :wikitext( | ||
resolved | resolved | ||
and ' | and 'RESOLVED' | ||
or ' | or 'UNRESOLVED' | ||
) | ) | ||
firstLine:tag('span') | |||
:addClass('feedback-page-card-text') | |||
:wikitext( | |||
entry.feedback | |||
or 'No feedback provided' | |||
) | |||
local meta = | |||
content:tag('div') | |||
:addClass('feedback-page-card-meta') | |||
if entry.user | |||
and entry.user ~= '' | |||
then | |||
meta:wikitext( | |||
formatUser(entry.user) | |||
) | |||
end | |||
if entry.createddate | |||
and entry.createddate ~= '' | |||
then | |||
meta:wikitext( | |||
' · ' | |||
.. mw.text.nowiki( | |||
entry.createddate | |||
) | |||
) | |||
end | |||
if resolved then | |||
local resolvedBy = | |||
trim(entry.resolvedby) | |||
local resolvedDate = | |||
trim(entry.resolveddate) | |||
if resolvedBy ~= '' | |||
or resolvedDate ~= '' | |||
then | |||
local resolution = | |||
content:tag('div') | |||
:addClass( | |||
'feedback-page-card-resolution' | |||
) | |||
resolution:wikitext( | |||
'↳ Resolved by ' | |||
) | |||
if resolvedBy ~= '' then | |||
resolution:wikitext( | |||
formatUser(resolvedBy) | |||
) | |||
else | |||
resolution:wikitext( | |||
'Unknown' | |||
) | |||
end | |||
if resolvedDate ~= '' then | |||
resolution:wikitext( | |||
' · ' | |||
.. mw.text.nowiki( | |||
resolvedDate | |||
) | |||
) | |||
end | |||
end | |||
else | |||
if id ~= '' then | |||
renderResolveControl( | |||
root, | |||
id, | |||
true | |||
) | |||
end | |||
end | |||
renderAttachments( | |||
content, | |||
entry | |||
) | |||
return tostring(root) | |||
end | |||
------------------------------------------------------------ | |||
-- Page feedback section | |||
------------------------------------------------------------ | |||
function p.page(frame) | |||
local page = | |||
currentSubjectPage() | |||
local allEntries, err = | |||
queryFeedback(page) | |||
if not allEntries then | |||
return '' | |||
end | |||
if #allEntries == 0 then | |||
return '' | |||
end | |||
local unresolved = {} | |||
local resolved = {} | |||
for _, row in ipairs(allEntries) do | |||
if row.status == 'resolved' then | |||
table.insert( | |||
resolved, | |||
row | |||
) | |||
else | |||
table.insert( | |||
unresolved, | |||
row | |||
) | |||
end | |||
end | |||
local root = | |||
mw.html.create('section') | |||
:addClass('feedback-page-section') | |||
:attr('id', 'feedback-section') | |||
:attr( | |||
'data-unresolved-count', | |||
#unresolved | |||
) | |||
:attr( | |||
'data-resolved-count', | |||
#resolved | |||
) | |||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- | -- Heading | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
root:tag(' | root:tag('h2') | ||
:addClass('feedback- | :addClass('feedback-page-heading') | ||
:wikitext( | :wikitext('Feedbacks') | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- | -- Filter controls | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
local filters = | |||
root:tag('div') | |||
:addClass('feedback-page-filters') | |||
local unresolvedFilter = | |||
filters:tag('span') | |||
: | :addClass('feedback-page-filter') | ||
:addClass( | |||
'feedback-page-filter--active' | |||
) | |||
:attr( | |||
'role', | |||
'button' | |||
) | |||
:attr( | |||
'tabindex', | |||
'0' | |||
) | |||
:attr( | |||
'data-feedback-filter', | |||
'unresolved' | |||
) | |||
unresolvedFilter:wikitext( | |||
'Unresolved ' | |||
) | |||
unresolvedFilter:tag('span') | |||
:addClass('feedback-page-filter-count') | |||
:wikitext( | |||
tostring(#unresolved) | |||
) | ) | ||
if #resolved > 0 then | |||
local resolvedFilter = | |||
filters:tag('span') | |||
:addClass('feedback-page-filter') | |||
:attr( | |||
'role', | |||
'button' | |||
) | |||
:attr( | |||
'tabindex', | |||
'0' | |||
) | |||
:attr( | |||
'data-feedback-filter', | |||
'resolved' | |||
) | |||
resolvedFilter:wikitext( | |||
'Resolved ' | |||
) | |||
resolvedFilter:tag('span') | |||
:addClass('feedback-page-filter-count') | |||
:wikitext( | |||
tostring(#resolved) | |||
) | ) | ||
end | end | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- | -- Unresolved list | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
if | local unresolvedList = | ||
root:tag('div') | |||
:addClass( | |||
'feedback-page-list' | |||
) | |||
:addClass( | |||
'feedback-page-list--unresolved' | |||
) | |||
if #unresolved > 0 then | |||
for _, row in ipairs(unresolved) do | |||
unresolvedList:node( | |||
renderCompactCard(row) | |||
) | |||
end | |||
else | |||
unresolvedList:tag('div') | |||
' | :addClass( | ||
'feedback-page-empty' | |||
) | |||
:wikitext( | |||
'No unresolved feedback.' | |||
) | ) | ||
end | |||
-------------------------------------------------------- | |||
-- Resolved list | |||
-------------------------------------------------------- | |||
if #resolved > 0 then | |||
local resolvedList = | |||
root:tag('div') | |||
:addClass( | |||
'feedback-page-list' | |||
) | |||
:addClass( | |||
'feedback-page-list--resolved' | |||
) | |||
for _, row in ipairs(resolved) do | |||
resolvedList:node( | |||
renderCompactCard(row) | |||
) | ) | ||
end | |||
end | end | ||
| Line 197: | Line 858: | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
-- | -- Feedback counts | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
function p.counts(frame) | |||
local page = | |||
currentSubjectPage() | |||
local | local entries = | ||
queryFeedback(page) | |||
if not | if not entries then | ||
return | return '' | ||
end | end | ||
local | local unresolved = 0 | ||
local resolved = 0 | |||
for _, row in ipairs(entries) do | |||
end | if row.status == 'resolved' then | ||
resolved = resolved + 1 | |||
else | |||
unresolved = unresolved + 1 | |||
end | |||
end | end | ||
return | return tostring( | ||
mw.html.create('span') | |||
:addClass('feedback-count-data') | |||
:attr( | |||
'data-unresolved', | |||
unresolved | |||
) | |||
:attr( | |||
'data-resolved', | |||
resolved | |||
) | |||
) | |||
end | end | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
-- Main | -- Main / individual feedback | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
| Line 248: | Line 913: | ||
parent and parent.args | parent and parent.args | ||
or frame.args | or frame.args | ||
local feedback = | local feedback = | ||
| Line 284: | Line 923: | ||
local id = | local id = | ||
args.id | trim(args.id) | ||
local createdDate = | |||
trim(args.createddate) | |||
local link = | |||
trim(args.link) | |||
local image = | |||
trim(args.image) | |||
local resolvedBy = | local resolvedBy = | ||
args.resolvedby | trim(args.resolvedby) | ||
local resolvedDate = | local resolvedDate = | ||
args.resolveddate | trim(args.resolveddate) | ||
local resolved = | local resolved = | ||
| Line 303: | Line 948: | ||
or 'unresolved' | or 'unresolved' | ||
local | local page = | ||
currentSubjectPage() | |||
local saved, saveError = | local saved, saveError = | ||
saveFeedback({ | saveFeedback({ | ||
page = | page = page, | ||
user = user, | user = user, | ||
status = status, | status = status, | ||
feedback = feedback, | feedback = feedback, | ||
id = id, | id = id, | ||
createddate = createdDate, | |||
link = link, | |||
image = image, | |||
resolvedby = resolvedBy, | resolvedby = resolvedBy, | ||
resolveddate = resolvedDate | resolveddate = resolvedDate | ||
| Line 324: | Line 967: | ||
if not saved then | if not saved then | ||
return '<strong style="color:red;">Feedback bucket error: ' | return | ||
'<strong style="color:red;">' | |||
.. 'Feedback bucket error: ' | |||
.. mw.text.nowiki( | .. mw.text.nowiki( | ||
saveError or 'Unknown error' | saveError or 'Unknown error' | ||
| Line 331: | Line 976: | ||
end | end | ||
local card = | local card = | ||
renderFullCard({ | |||
page = | page = page, | ||
user = user, | user = user, | ||
status = status, | status = status, | ||
feedback = feedback, | feedback = feedback, | ||
id = id, | id = id, | ||
createddate = createdDate, | |||
link = link, | |||
image = image, | |||
resolvedby = resolvedBy, | resolvedby = resolvedBy, | ||
resolveddate = resolvedDate | resolveddate = resolvedDate | ||
} | }) | ||
local categories = {} | local categories = {} | ||
| Line 369: | Line 1,009: | ||
end | end | ||
if | if id == '' then | ||
table.insert( | table.insert( | ||
| Line 386: | Line 1,024: | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
-- | -- Feedback table | ||
------------------------------------------------------------ | ------------------------------------------------------------ | ||
local function | local function renderTable(entries, includeResolved) | ||
local tableRoot = | |||
mw.html.create('table') | |||
:addClass('feedback-table') | |||
local | local header = | ||
tableRoot:tag('tr') | |||
if includeResolved then | |||
header:tag('th') | |||
:wikitext('Status') | |||
end | end | ||
header:tag('th') | |||
:wikitext('Page') | |||
header:tag('th') | |||
:wikitext('Username') | |||
header:tag('th') | |||
:wikitext('Date') | |||
header:tag('th') | |||
:wikitext('Feedback') | |||
if includeResolved then | |||
header:tag('th') | |||
:wikitext('Resolved by') | |||
header:tag('th') | |||
:wikitext('Resolved date') | |||
end | end | ||
if #entries == 0 then | |||
local row = | |||
tableRoot:tag('tr') | |||
local colspan = | |||
includeResolved | |||
and '7' | |||
or '4' | |||
row:tag('td') | |||
:attr( | |||
'colspan', | |||
colspan | |||
) | |||
:addClass( | |||
'feedback-table-empty' | |||
) | |||
:wikitext( | |||
'No feedback entries found.' | |||
) | |||
return tostring(tableRoot) | |||
return | |||
end | end | ||
for _, entry in ipairs(entries) do | |||
local row = | |||
tableRoot:tag('tr') | |||
:addClass( | |||
entry.status == 'resolved' | |||
and 'feedback-table-row--resolved' | |||
or 'feedback-table-row--unresolved' | |||
) | |||
if includeResolved then | |||
row:tag('td') | |||
:addClass('feedback-table-status') | |||
:wikitext( | |||
entry.status == 'resolved' | |||
and 'Resolved' | |||
or 'Unresolved' | |||
) | |||
end | |||
row:tag('td') | |||
:addClass('feedback-table-page') | |||
:wikitext( | |||
'[[' | |||
.. entry.page | |||
.. ']]' | |||
) | |||
row:tag('td') | |||
:addClass('feedback-table-user') | |||
:wikitext( | |||
formatUser(entry.user) | |||
) | |||
row:tag('td') | |||
:addClass('feedback-table-date') | |||
:wikitext( | |||
mw.text.nowiki( | |||
entry.createddate | |||
or '—' | |||
) | ) | ||
) | |||
table | row:tag('td') | ||
:addClass('feedback-table-feedback') | |||
:wikitext( | |||
entry.feedback | |||
or '' | |||
) | ) | ||
if includeResolved then | |||
table. | row:tag('td') | ||
:addClass( | |||
'feedback-table-resolved-by' | |||
) | |||
:wikitext( | |||
entry.resolvedby | |||
and formatUser( | |||
entry.resolvedby | |||
) | |||
or '—' | |||
) | ) | ||
row:tag('td') | |||
:addClass( | |||
'feedback-table-resolved-date' | |||
) | |||
:wikitext( | |||
entry.resolveddate | |||
and mw.text.nowiki( | |||
entry.resolveddate | |||
) | |||
or '—' | |||
) | ) | ||
end | end | ||
end | end | ||
return tostring(tableRoot) | |||
end | |||
------------------------------------------------------------ | |||
-- Global feedback page | |||
------------------------------------------------------------ | |||
function p.view(frame) | |||
local parent = | |||
frame:getParent() | |||
local args = | |||
parent and parent.args | |||
or frame.args | |||
local status = | |||
trim( | |||
args.status | |||
or '' | |||
):lower() | |||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- | -- Specific table | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
if status == 'resolved' | |||
or status == 'unresolved' | |||
then | |||
local entries = | |||
queryFeedback( | |||
nil, | |||
status | |||
) | ) | ||
if not entries then | |||
return '' | |||
end | |||
' | |||
return renderTable( | |||
entries, | |||
false | |||
) | |||
end | end | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
-- | -- Dashboard | ||
-------------------------------------------------------- | -------------------------------------------------------- | ||
local | local unresolved = | ||
queryFeedback( | |||
nil, | |||
'unresolved' | |||
) | |||
local all = | |||
queryFeedback( | |||
nil, | |||
'all' | |||
) | |||
if | if not unresolved then | ||
unresolved = {} | |||
end | |||
if not all then | |||
all = {} | |||
end | |||
local root = | |||
mw.html.create('div') | |||
:addClass('feedback-dashboard') | |||
root:tag('h2') | |||
:addClass('feedback-dashboard-heading') | |||
:wikitext('Unresolved Feedback') | |||
root:node( | |||
renderTable( | |||
unresolved, | |||
false | |||
) | |||
) | |||
root:tag('h2') | |||
:addClass('feedback-dashboard-heading') | |||
:wikitext('All Feedback') | |||
root:node( | |||
renderTable( | |||
all, | |||
true | |||
) | ) | ||
) | |||
return | return tostring(root) | ||
end | end | ||
------------------------------------------------------------ | |||
-- Aliases | |||
------------------------------------------------------------ | |||
p.table = p.view | |||
return p | return p | ||