Module:User:Kai/sandbox

From The Deadlock Wiki
Revision as of 20:58, 27 August 2026 by Kai (talk | contribs)
Jump to navigation Jump to search

Documentation for this module may be created at Module:User:Kai/sandbox/doc

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