Module:AVDevice: Difference between revisions
Remove infobox-label-top from connectivity labels - let gray bg stretch full row height naturally (via update-page on MediaWiki MCP Server) |
Add Parts section to AV device infobox (queries parts linked via Has related AV device) (via update-page on MediaWiki MCP Server) |
||
| Line 56: | Line 56: | ||
fullDiv:wikitext(valueHtmlOrWikitext) | fullDiv:wikitext(valueHtmlOrWikitext) | ||
end | end | ||
end | |||
-- Helper function to strip brand prefix from item name if it matches device brand | |||
local function getDisplayTextWithoutBrand(itemName, deviceBrand) | |||
if not itemName then return nil end | |||
if not deviceBrand then return itemName end | |||
local brandPrefix = deviceBrand .. ' ' | |||
if itemName:sub(1, #brandPrefix) == brandPrefix then | |||
return itemName:sub(#brandPrefix + 1) | |||
end | |||
return itemName | |||
end | end | ||
| Line 507: | Line 520: | ||
end | end | ||
end | end | ||
end | |||
end | |||
end | |||
-- Parts section: Query for parts linked via Has related AV device | |||
local partsCountWikitext = | |||
'{{#ask:\n' .. | |||
' [[Category:Parts]]\n' .. | |||
' [[Has related AV device::' .. fullPageName .. ']]\n' .. | |||
' |format=count\n' .. | |||
'}}' | |||
local partsCount = frame:preprocess(partsCountWikitext) | |||
local hasParts = partsCount and tonumber(trim(partsCount)) and tonumber(trim(partsCount)) > 0 | |||
if hasParts then | |||
addSectionRow(container, 'Parts') | |||
-- Query parts and display grouped by type/subtype | |||
local partsQueryWikitext = | |||
'{{#ask:\n' .. | |||
' [[Category:Parts]]\n' .. | |||
' [[Has related AV device::' .. fullPageName .. ']]\n' .. | |||
' |?Has part type=type\n' .. | |||
' |?Has part subtype=subtype\n' .. | |||
' |?Has model code=model\n' .. | |||
' |?Has description=desc\n' .. | |||
' |format=broadtable\n' .. | |||
' |headers=hide\n' .. | |||
' |link=none\n' .. | |||
'}}' | |||
local partsResult = frame:preprocess(partsQueryWikitext) | |||
-- Parse parts from broadtable result and group by type | |||
local partsByType = {} | |||
local partTypeOrder = {} | |||
if partsResult then | |||
for rowContent in partsResult:gmatch('<tr[^>]*>(.-)</tr>') do | |||
local cells = {} | |||
for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do | |||
local cleanContent = cellContent:gsub('<[^>]+>', '') | |||
table.insert(cells, trim(cleanContent)) | |||
end | |||
-- cells[1] = page name, cells[2] = type, cells[3] = subtype, cells[4] = model code, cells[5] = description | |||
if #cells >= 2 then | |||
local partPageName = cells[1] | |||
local partType = cells[2] or 'Part' | |||
local partSubtype = cells[3] | |||
local partDesc = cells[5] | |||
-- Use subtype + type as the grouping key if subtype exists (e.g., "Frame synchronizer IC") | |||
local groupKey = partType | |||
if partSubtype and partSubtype ~= '' then | |||
groupKey = partSubtype .. ' ' .. partType:lower() | |||
end | |||
if partPageName then | |||
-- Track type order for consistent display | |||
if not partsByType[groupKey] then | |||
partsByType[groupKey] = {} | |||
table.insert(partTypeOrder, groupKey) | |||
end | |||
table.insert(partsByType[groupKey], { | |||
page = partPageName, | |||
desc = partDesc | |||
}) | |||
end | |||
end | |||
end | |||
end | |||
-- Display as label/value rows grouped by type | |||
for _, partType in ipairs(partTypeOrder) do | |||
local parts = partsByType[partType] | |||
if parts and #parts > 0 then | |||
local partLinks = {} | |||
for _, part in ipairs(parts) do | |||
local displayText = getDisplayTextWithoutBrand(part.page, brand) | |||
local linkText = displayText | |||
if part.desc and part.desc ~= '' then | |||
linkText = displayText .. ' – ' .. part.desc | |||
end | |||
table.insert(partLinks, '[[' .. part.page .. '|' .. linkText .. ']]') | |||
end | |||
addRow(container, partType, table.concat(partLinks, '<br>'), true) | |||
end | end | ||
end | end | ||