Module:CapacityExchange
Appearance
| This module is rated as beta, and is ready for widespread use. It is still new and should be used with some caution to ensure the results are as expected. |
This Lua module is part of the Capacity Exchange platform. It is designed to display user capacities on their user pages. The module retrieves user data and capacity information from toolforge:capx, process and generates the HTML content to present the user's known and wanted capacities.
Usage
[edit]{{CapacityExchange}}
local users = mw.ext.data.get("CapacityExchange/users.tab").data
local lang = mw.getCurrentFrame():preprocess("{{Int:Lang}}")
local capacities = mw.ext.data.get("CapacityExchange/capacities.tab", lang).data
local badgesData = mw.ext.data.get("CapacityExchange/badges.tab").data
local tmb = require 'mw.ext.translate.messageBundle'
local mb = tmb.new( "Module:CapacityExchange/locale.json", lang )
local is_rtl = require( 'Module:Is rtl' )
local p = {}
-- Get the text direction
function get_dir()
if is_rtl[lang] then
return "rtl"
else
return "ltr"
end
end
-- Create a mapping of capacity IDs to their names and descriptions.
-- Export rows: [id:number, name:string, description:string, wikidata_item:string]
local capacityMap = {}
for _, capacity in ipairs(capacities) do
local id = tostring(capacity[1])
local nameVal = capacity[2] or ''
local descVal = capacity[3] or ''
local key = capacity[4] -- wikidata_item / QID
capacityMap[id] = { key = key, label = nameVal, description = descVal }
end
-- Create a mapping of badge IDs to their names and images
local badgeMap = {}
for _, badge in ipairs(badgesData) do
-- badge schema: [id:number, name:string, image:string, base_url:string]
local id = tostring(badge[1])
badgeMap[id] = { name = badge[2], image = badge[3], base_url = badge[4] }
end
-- Function to get user data by username
local function getUserData(username)
for _, userData in ipairs(users) do
if userData[1] == username then
return {
username = userData[1],
skills_known = userData[2],
skills_available = userData[3],
badges = userData[4]
}
end
end
return nil
end
-- Helper function to replace capacity IDs with names and descriptions
local function replaceCapacities(capacityList, sectionPrefix)
local result = {}
-- Remove [] and split by comma
capacityList = mw.ustring.gsub(capacityList, "%[", "")
capacityList = mw.ustring.gsub(capacityList, "%]", "")
for _, capacityId in ipairs(mw.text.split(capacityList, ",")) do
local trimmedId = mw.text.trim(capacityId)
if trimmedId ~= "" then
local meta = capacityMap[trimmedId]
if meta then
local toggleId = sectionPrefix .. "-" .. meta.key
table.insert(result,
"<div class='capx-capacity'>" ..
"<div class='capx-name mw-customtoggle-" .. toggleId .. "'>" .. meta.label .. "</div>" ..
"<div class='capx-desc mw-collapsible mw-collapsed' id='mw-customcollapsible-" .. toggleId .. "'>" .. meta.description .. "</div>" ..
"</div>"
)
else
table.insert(result, "<div class='capx-unknown'>" .. trimmedId .. "</div>")
end
end
end
return result
end
-- Helper function to load badges
local function loadBadges(badgeList)
local result = {}
-- Remove [] and split by comma
badgeList = mw.ustring.gsub(badgeList, "%[", "")
badgeList = mw.ustring.gsub(badgeList, "%]", "")
for _, badge in ipairs(mw.text.split(badgeList, ",")) do
local parts = mw.text.split(mw.text.trim(badge), "§")
local id = mw.text.trim(parts[1] or "")
if id ~= "" then
local meta = badgeMap[id]
if meta then
local hashCode = parts[2]
local badgeUrl = nil
if hashCode and hashCode ~= "" and meta.base_url and meta.base_url ~= "" then
badgeUrl = meta.base_url .. hashCode
end
if not badgeUrl or badgeUrl == "" then
badgeUrl = "https://meta.wikimedia.org/wiki/Capacity_Exchange/User_Guide#Badges"
end
table.insert(result, "<div class='capx-badge'>")
table.insert(result, "<table role='presentation'>")
table.insert(result, "<tr>")
table.insert(result, "<td>[[File:" .. meta.image .. "|45px]]</td>")
table.insert(result, "<td>" .. mw.getCurrentFrame():preprocess(mb:t( "badge" ):params( badgeUrl, meta.name, '{{PAGENAME}}' ):plain()) .. "</td>")
table.insert(result, "</tr>")
table.insert(result, "</table>")
table.insert(result, "</div>")
else
-- Unknown badge id
table.insert(result, "<div class='capx-badge capx-unknown'>" .. mb:t( "unknown-badge" ):params( id ):plain() .. "</div>")
end
end
end
return result
end
-- Return the constructed table
local function constructCapacitiesTable(knownCapacities, availableCapacities, badges)
local capacitiesTable = {}
local localeLink = 'https://meta.wikimedia.org/w/index.php?title=Special%3ATranslate&group=messagebundle-Module%3ACapacityExchange%2Flocale.json'
local capacitiesLink = 'https://meta.wikimedia.org/w/index.php?title=Special%3ATranslate&group=messagebundle-Module%3ACapacityExchange%2Fcapacities.json'
table.insert(capacitiesTable, "<div class='capx-main' style='direction: " .. get_dir() .. ";'>")
table.insert(capacitiesTable, "<div class='capx-logo'>")
table.insert(capacitiesTable, mb:t( "help-translate-plus" ):params( localeLink, capacitiesLink ):plain())
table.insert(capacitiesTable, "</div>")
if #availableCapacities > 0 then
table.insert(capacitiesTable, "<div class='capx-available'>")
table.insert(capacitiesTable, "<div class='capx-title-" .. get_dir() .. "'>" .. mb:t( "available" ):plain() .. "</div>")
for _, capacity in ipairs(availableCapacities) do
table.insert(capacitiesTable, capacity)
end
table.insert(capacitiesTable, "<div class='capx-message'>" .. mw.getCurrentFrame():preprocess(mb:t( "you-available" ):params( '{{PAGENAME}}' ):plain()) .. "</div>")
table.insert(capacitiesTable, "</div>")
end
if #knownCapacities > 0 then
table.insert(capacitiesTable, "<div class='capx-known'>")
table.insert(capacitiesTable, "<div class='capx-title-" .. get_dir() .. "'>" .. mb:t( "known" ):plain() .. "</div>")
for _, capacity in ipairs(knownCapacities) do
table.insert(capacitiesTable, capacity)
end
table.insert(capacitiesTable, "<div class='capx-message'>" .. mw.getCurrentFrame():preprocess(mb:t( "you-have" ):params( '{{PAGENAME}}' ):plain()) .. "</div>")
table.insert(capacitiesTable, "</div>")
end
table.insert(capacitiesTable, "<div class='capx-button'>[[:toolforge:capx|" .. mb:t( "access-capx" ):plain() .. "]]</div>")
table.insert(capacitiesTable, "<div class='capx-badges'>")
table.insert(capacitiesTable, "<div class='capx-title-" .. get_dir() .. "'>" .. mb:t( "recognition" ):plain() .. "</div>")
for _, badge in ipairs(badges) do
table.insert(capacitiesTable, badge)
end
table.insert(capacitiesTable, "</div>")
table.insert(capacitiesTable, "</div>")
return table.concat(capacitiesTable, "\n")
end
function p.main(frame)
-- Check if namespace is 2, else return a message
if mw.title.getCurrentTitle().namespace ~= 2 then
return "<div class='capx-error'>" .. mb:t( "wrong-namespace" ):plain() .. "</div>"
end
-- Get the title of the page and remove the namespace
local user = mw.ustring.gsub(mw.title.getCurrentTitle().text, "User:", "")
-- Get the specific user data
local userData = getUserData(user)
if not userData then
return "<div class='capx-error'>" .. mb:t( "not-found" ):plain() .. "</div>"
end
-- Replace capacity IDs with names and descriptions (use unique section prefixes)
local knownCapacities = replaceCapacities(userData.skills_known, "known")
local availableCapacities = replaceCapacities(userData.skills_available, "available")
local badges = loadBadges(userData.badges)
return constructCapacitiesTable(knownCapacities, availableCapacities, badges)
end
return p