|
|
| Line 1: |
Line 1: |
| local p = {}
| |
|
| |
| ------------------------------------------------------------
| |
| -- Helpers
| |
| ------------------------------------------------------------
| |
|
| |
| local function isTruthy(value)
| |
| if value == nil then
| |
| return false
| |
| end
| |
|
| |
| value = mw.text.trim(tostring(value)):lower()
| |
|
| |
| return value ~= ''
| |
| and value ~= '0'
| |
| and value ~= 'false'
| |
| and value ~= 'no'
| |
| and value ~= 'off'
| |
| end
| |
|
| |
|
| |
| local function trim(value)
| |
| return mw.text.trim(
| |
| tostring(value or '')
| |
| )
| |
| end
| |
|
| |
|
| |
| local function formatUser(user)
| |
| user = trim(user)
| |
|
| |
| if user == '' or user:lower() == 'anonymous' then
| |
| return 'Anonymous'
| |
| end
| |
|
| |
| return string.format(
| |
| '[[User:%s|%s]]',
| |
| 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
| |
|
| |
|
| |
| ------------------------------------------------------------
| |
| -- Shared metadata
| |
| ------------------------------------------------------------
| |
|
| |
| local function renderMetadata(root, entry)
| |
|
| |
| local meta =
| |
| 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 =
| |
| 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
| |
| resolution:wikitext(
| |
| ' on '
| |
| .. mw.text.nowiki(resolvedDate)
| |
| )
| |
| end
| |
| end
| |
|
| |
|
| |
| ------------------------------------------------------------ | | ------------------------------------------------------------ |
| -- Resolve control | | -- Resolve control |
| Line 339: |
Line 6: |
| parent, | | parent, |
| id, | | id, |
| compact | | compact, |
| | page |
| ) | | ) |
|
| |
|
| Line 349: |
Line 17: |
| parent:tag('span') | | parent:tag('span') |
| :addClass('feedback-resolve-button') | | :addClass('feedback-resolve-button') |
| | :attr( |
| | 'data-feedback-id', |
| | id |
| | ) |
| | |
| | if page and page ~= '' then |
| | control:attr( |
| | 'data-feedback-page', |
| | page |
| | ) |
| | end |
|
| |
|
| if compact then | | if compact then |
| Line 367: |
Line 46: |
|
| |
|
| end | | 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 =
| |
| mw.html.create('div')
| |
| :addClass('feedback-box')
| |
| :addClass(
| |
| resolved
| |
| and 'feedback-box--resolved'
| |
| or 'feedback-box--unresolved'
| |
| )
| |
|
| |
| if id ~= '' then
| |
| root:attr(
| |
| 'data-feedback-id',
| |
| id
| |
| )
| |
| end
| |
|
| |
| --------------------------------------------------------
| |
| -- Main line
| |
| --------------------------------------------------------
| |
|
| |
| local main =
| |
| root:tag('div')
| |
| :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 not resolved
| |
| and id == ''
| |
| then
| |
|
| |
| root:tag('div')
| |
| :addClass('feedback-missing-id')
| |
| :wikitext(
| |
| 'Add an ID to enable the Resolve button.'
| |
| )
| |
|
| |
| end
| |
|
| |
| 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
| |
|
| |
| 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(
| |
| resolved
| |
| and 'feedback-status--resolved'
| |
| or 'feedback-status--unresolved'
| |
| )
| |
| :wikitext(
| |
| resolved
| |
| and 'RESOLVED'
| |
| 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('h2')
| |
| :addClass('feedback-page-heading')
| |
| :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
| |
|
| |
| --------------------------------------------------------
| |
| -- Unresolved list
| |
| --------------------------------------------------------
| |
|
| |
| 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
| |
|
| |
| return tostring(root)
| |
| end
| |
|
| |
|
| |
| ------------------------------------------------------------
| |
| -- Feedback counts
| |
| ------------------------------------------------------------
| |
|
| |
| function p.counts(frame)
| |
|
| |
| local page =
| |
| currentSubjectPage()
| |
|
| |
| local entries =
| |
| queryFeedback(page)
| |
|
| |
| if not entries then
| |
| return ''
| |
| end
| |
|
| |
| local unresolved = 0
| |
| local resolved = 0
| |
|
| |
| for _, row in ipairs(entries) do
| |
|
| |
| if row.status == 'resolved' then
| |
| resolved = resolved + 1
| |
| else
| |
| unresolved = unresolved + 1
| |
| end
| |
|
| |
| end
| |
|
| |
| return tostring(
| |
| mw.html.create('span')
| |
| :addClass('feedback-count-data')
| |
| :attr(
| |
| 'data-unresolved',
| |
| unresolved
| |
| )
| |
| :attr(
| |
| 'data-resolved',
| |
| resolved
| |
| )
| |
| )
| |
| end
| |
|
| |
|
| |
| ------------------------------------------------------------
| |
| -- Main / individual feedback
| |
| ------------------------------------------------------------
| |
|
| |
| function p.main(frame)
| |
|
| |
| local parent =
| |
| frame:getParent()
| |
|
| |
| local args =
| |
| parent and parent.args
| |
| or frame.args
| |
|
| |
| local feedback =
| |
| args.feedback
| |
| or 'No feedback provided'
| |
|
| |
| local user =
| |
| args.user
| |
| or 'Anonymous'
| |
|
| |
| local id =
| |
| trim(args.id)
| |
|
| |
| local createdDate =
| |
| trim(args.createddate)
| |
|
| |
| local link =
| |
| trim(args.link)
| |
|
| |
| local image =
| |
| trim(args.image)
| |
|
| |
| local resolvedBy =
| |
| trim(args.resolvedby)
| |
|
| |
| local resolvedDate =
| |
| trim(args.resolveddate)
| |
|
| |
| local resolved =
| |
| isTruthy(args.resolved)
| |
|
| |
| local status =
| |
| resolved
| |
| and 'resolved'
| |
| or 'unresolved'
| |
|
| |
| local page =
| |
| currentSubjectPage()
| |
|
| |
| local saved, saveError =
| |
| saveFeedback({
| |
| page = page,
| |
| user = user,
| |
| status = status,
| |
| feedback = feedback,
| |
| id = id,
| |
| createddate = createdDate,
| |
| link = link,
| |
| image = image,
| |
| resolvedby = resolvedBy,
| |
| resolveddate = resolvedDate
| |
| })
| |
|
| |
| if not saved then
| |
|
| |
| return
| |
| '<strong style="color:red;">'
| |
| .. 'Feedback bucket error: '
| |
| .. mw.text.nowiki(
| |
| saveError or 'Unknown error'
| |
| )
| |
| .. '</strong>'
| |
|
| |
| end
| |
|
| |
| local card =
| |
| renderFullCard({
| |
| page = page,
| |
| user = user,
| |
| status = status,
| |
| feedback = feedback,
| |
| id = id,
| |
| createddate = createdDate,
| |
| link = link,
| |
| image = image,
| |
| resolvedby = resolvedBy,
| |
| resolveddate = resolvedDate
| |
| })
| |
|
| |
| local categories = {}
| |
|
| |
| if resolved then
| |
|
| |
| table.insert(
| |
| categories,
| |
| '[[Category:Resolved Feedback]]'
| |
| )
| |
|
| |
| else
| |
|
| |
| table.insert(
| |
| categories,
| |
| '[[Category:Unresolved Feedback]]'
| |
| )
| |
|
| |
| end
| |
|
| |
| if id == '' then
| |
|
| |
| table.insert(
| |
| categories,
| |
| '[[Category:Feedbacks Missing ID]]'
| |
| )
| |
|
| |
| end
| |
|
| |
| return card
| |
| .. table.concat(categories)
| |
| end | | end |
|
| |
|
| |
| ------------------------------------------------------------
| |
| -- Feedback table
| |
| ------------------------------------------------------------
| |
|
| |
| local function renderTable(entries, includeResolved)
| |
|
| |
| local tableRoot =
| |
| mw.html.create('table')
| |
| :addClass('feedback-table')
| |
|
| |
| local header =
| |
| tableRoot:tag('tr')
| |
|
| |
| if includeResolved then
| |
|
| |
| header:tag('th')
| |
| :wikitext('Status')
| |
|
| |
| 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
| |
|
| |
| 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)
| |
| 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 '—'
| |
| )
| |
| )
| |
|
| |
| row:tag('td')
| |
| :addClass('feedback-table-feedback')
| |
| :wikitext(
| |
| entry.feedback
| |
| or ''
| |
| )
| |
|
| |
| if includeResolved then
| |
|
| |
| 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
| |
|
| |
| 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
| |
|
| |
| --------------------------------------------------------
| |
| -- Dashboard
| |
| --------------------------------------------------------
| |
|
| |
| local unresolved =
| |
| queryFeedback(
| |
| nil,
| |
| 'unresolved'
| |
| )
| |
|
| |
| local all =
| |
| queryFeedback(
| |
| nil,
| |
| 'all'
| |
| )
| |
|
| |
| 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 tostring(root)
| |
| end
| |
|
| |
|
| |
| ------------------------------------------------------------
| |
| -- Aliases
| |
| ------------------------------------------------------------
| |
|
| |
| p.table = p.view
| |
|
| |
| return p
| |