|
|
| 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
| |
|
| |
| local function renderCard(entry, showInstruction)
| |
| local resolved = (entry.status == 'resolved')
| |
| local user = entry.user or "Anonymous"
| |
| local feedback = entry.feedback or "No feedback provided"
| |
| local page = entry.page
| |
|
| |
| 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 page and page ~= '' then
| |
| meta:tag('span')
| |
| :addClass('feedback-page')
| |
| :wikitext(string.format('[[%s]]', page))
| |
|
| |
| 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 showInstruction and not resolved 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
| |
|
| |
| 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
| |
|
| |
| -- Write directly to the Bucket database
| |
| if mw.ext and mw.ext.bucket then
| |
| mw.ext.bucket('feedback').put({
| |
| page = currentPage,
| |
| user = user,
| |
| status = statusStr,
| |
| feedback = feedback
| |
| })
| |
| end
| |
|
| |
| local card = renderCard({
| |
| page = nil,
| |
| user = user,
| |
| status = statusStr,
| |
| feedback = feedback
| |
| }, true)
| |
|
| |
| local category = resolved and '[[Category:Resolved Feedback]]' or '[[Category:Unresolved Feedback]]'
| |
|
| |
| return card .. category
| |
| end
| |
|
| |
| local function renderFeedbackList(results)
| |
| if not results or #results == 0 then
| |
| return "<em>No feedback entries found.</em>"
| |
| end
| |
|
| |
| local list = {}
| |
| for _, row in ipairs(results) do
| |
| table.insert(list, renderCard(row, false))
| |
| end
| |
| return table.concat(list, "\n")
| |
| end
| |
|
| |
| function p.view(frame)
| |
| local parent = frame:getParent()
| |
| local args = parent and parent.args or frame.args
| |
| 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
| |
|
| |
| frame = frame or mw.getCurrentFrame()
| |
| local filterStatus = mw.text.trim(args.status or args[1] or 'tabber'):lower()
| |
|
| |
| if filterStatus == 'resolved' or filterStatus == 'unresolved' then
| |
| local query = mw.ext.bucket('feedback')
| |
| query.select('page', 'user', 'status', 'feedback')
| |
| query.where('status', filterStatus)
| |
| return renderFeedbackList(query.run())
| |
| elseif filterStatus == 'all' then
| |
| local query = mw.ext.bucket('feedback')
| |
| query.select('page', 'user', 'status', 'feedback')
| |
| return renderFeedbackList(query.run())
| |
| end
| |
|
| |
| -- Tabber mode (default): queries all, unresolved, and resolved tabs
| |
| local qAll = mw.ext.bucket('feedback')
| |
| qAll.select('page', 'user', 'status', 'feedback')
| |
| local allEntries = qAll.run()
| |
|
| |
| local allList = {}
| |
| local unresolvedList = {}
| |
| local resolvedList = {}
| |
|
| |
| if allEntries and #allEntries > 0 then
| |
| 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
| |
|
| |
| local allContent = (#allList > 0) and table.concat(allList, "\n") or "<em>No feedback entries found.</em>"
| |
| local unresolvedContent = (#unresolvedList > 0) and table.concat(unresolvedList, "\n") or "<em>No unresolved feedback entries found.</em>"
| |
| local resolvedContent = (#resolvedList > 0) and table.concat(resolvedList, "\n") or "<em>No resolved feedback entries found.</em>"
| |
|
| |
| 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
| |
|
| |
| return p
| |