|
|
| Line 17: |
Line 17: |
| end | | end |
|
| |
|
| -- Renders the individual feedback visual card | | function p.main(frame) |
| local function renderCard(user, feedback, resolved, pageName)
| | 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 |
| | |
| | -- Build HTML display |
| local root = mw.html.create('div') | | local root = mw.html.create('div') |
| :addClass('feedback-box') | | :addClass('feedback-box') |
| Line 25: |
Line 47: |
| local meta = root:tag('div') | | local meta = root:tag('div') |
| :addClass('feedback-meta') | | :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') | | meta:tag('span') |
| Line 52: |
Line 65: |
| :wikitext(feedback) | | :wikitext(feedback) |
|
| |
|
| if not resolved and (not pageName or pageName == '') then | | if not resolved then |
| root:tag('div') | | root:tag('div') |
| :addClass('feedback-instruction') | | :addClass('feedback-instruction') |
| Line 58: |
Line 71: |
| end | | 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]]' | | 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 = nil
| |
|
| |
| -- Method 1: mw.ext.bucket:select() syntax (common Scribunto Bucket API)
| |
| if not rows and mw.ext and mw.ext.bucket and type(mw.ext.bucket) == 'function' then
| |
| pcall(function()
| |
| rows = mw.ext.bucket('feedback'):select('page', 'user', 'status', 'feedback'):run()
| |
| end)
| |
| end
| |
|
| |
| -- Method 2: mw.ext.bucket.query() or mw.ext.bucket.select() direct table syntax
| |
| if not rows and mw.ext and mw.ext.bucket then
| |
| if type(mw.ext.bucket.query) == 'function' then
| |
| pcall(function()
| |
| rows = mw.ext.bucket.query('feedback', {
| |
| fields = { 'page', 'user', 'status', 'feedback' }
| |
| })
| |
| end)
| |
| elseif type(mw.ext.bucket.select) == 'function' then
| |
| pcall(function()
| |
| rows = mw.ext.bucket.select('feedback', { 'page', 'user', 'status', 'feedback' })
| |
| end)
| |
| end
| |
| end
| |
|
| |
| -- Method 3: Global mw.bucket syntax
| |
| if not rows and mw.bucket then
| |
| pcall(function()
| |
| if type(mw.bucket) == 'function' then
| |
| rows = mw.bucket('feedback'):select('page', 'user', 'status', 'feedback'):run()
| |
| elseif type(mw.bucket.query) == 'function' then
| |
| rows = mw.bucket.query('feedback', {
| |
| fields = { 'page', 'user', 'status', 'feedback' }
| |
| })
| |
| end
| |
| end)
| |
| end
| |
|
| |
| rows = rows or {}
| |
|
| |
| local allCards = {}
| |
| local unresolvedCards = {}
| |
| local resolvedCards = {}
| |
|
| |
| for _, row in ipairs(rows) do
| |
| -- Support both string keys and positional keys
| |
| local pageName = row.page or row[1] or ''
| |
| local user = row.user or row[2] or 'Anonymous'
| |
| local status = tostring(row.status or row[3] or 'unresolved'):lower()
| |
| local feedbackText = row.feedback or row[4] or ''
| |
| local isResolved = status == 'resolved' or status == 'true' or status == '1'
| |
|
| |
| local card = renderCard(user, feedbackText, isResolved, pageName)
| |
|
| |
| 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.')
| |
| )
| |
|
| |
|
| return frame:preprocess(tabberWikitext) | | return tostring(root) .. category |
| end | | end |
|
| |
|
| return p | | return p |