Module:CRTModel: Difference between revisions
Remove random timestamp targets from Add Part and Add Accessory buttons — let users name pages themselves (via update-page on MediaWiki MCP Server) |
Change "Add accessory" button to link to Create_an_accessory with crt_models parameter (via update-page on MediaWiki MCP Server) |
||
| (10 intermediate revisions by the same user not shown) | |||
| Line 228: | Line 228: | ||
local model_code = trim(args.model_code) | local model_code = trim(args.model_code) | ||
local variants = trim(args.variants) | local variants = trim(args.variants) | ||
local market = trim(args.market) | |||
local series = trim(args.series) | local series = trim(args.series) | ||
local image_main = trim(args.image_main) | local image_main = trim(args.image_main) | ||
| Line 296: | Line 297: | ||
'infobox-title' | 'infobox-title' | ||
) | ) | ||
-- Type badge (breadcrumb) — plainlinks hides external icon, $wgNoFollowDomainExceptions handles nofollow | |||
local badgeWikitext = '[[CRT Search|CRT]]' | |||
if crt_type then | |||
local typeUrl = mw.title.new('CRT Search'):fullUrl({crt_type = crt_type}) | |||
badgeWikitext = badgeWikitext .. ' › <span class="plainlinks">[' .. typeUrl .. ' ' .. crt_type .. ']</span>' | |||
end | |||
addFullRow(container, badgeWikitext, '', false, 'infobox-type-badge') | |||
if image_main then | if image_main then | ||
| Line 341: | Line 350: | ||
if variants then | if variants then | ||
addRow(container, 'Variants', variants, false) | addRow(container, 'Variants', variants, false) | ||
end | |||
-- Market row | |||
if market then | |||
addRow(container, 'Market', market, false) | |||
end | end | ||
| Line 559: | Line 573: | ||
if range.min and range.max then | if range.min and range.max then | ||
if range.min == range.max then | if range.min == range.max then | ||
rangeStr = range.min .. 'V' | rangeStr = range.min .. 'V' | ||
else | else | ||
rangeStr = range.min .. '–' .. range.max .. 'V' | rangeStr = range.min .. '–' .. range.max .. 'V' | ||
end | end | ||
| Line 576: | Line 588: | ||
if #rangeStrings > 0 then | if #rangeStrings > 0 then | ||
addRow(container, 'Voltage', table.concat(rangeStrings, ' / '), false) | addRow(container, 'Voltage', table.concat(rangeStrings, ' / '), false) | ||
end | end | ||
| Line 604: | Line 615: | ||
addSectionRow(container, 'TV Systems') | addSectionRow(container, 'TV Systems') | ||
if av_system then | if av_system then | ||
local systems = {} | local systems = {} | ||
for system in av_system:gmatch('[^,]+') do | for system in av_system:gmatch('[^,]+') do | ||
| Line 619: | Line 628: | ||
end | end | ||
if tuner_system then | if tuner_system then | ||
local systems = {} | local systems = {} | ||
for system in tuner_system:gmatch('[^,]+') do | for system in tuner_system:gmatch('[^,]+') do | ||
| Line 635: | Line 642: | ||
end | end | ||
-- Scan Range section | -- Scan Range section | ||
if h_scan_min or h_scan_max or v_scan_min or v_scan_max then | if h_scan_min or h_scan_max or v_scan_min or v_scan_max then | ||
addSectionRow(container, 'Scan Range') | addSectionRow(container, 'Scan Range') | ||
if h_scan_min or h_scan_max then | if h_scan_min or h_scan_max then | ||
local hDisplay | local hDisplay | ||
if h_scan_min and h_scan_max then | if h_scan_min and h_scan_max then | ||
if h_scan_min == h_scan_max then | if h_scan_min == h_scan_max then | ||
hDisplay = h_scan_min .. ' kHz' | hDisplay = h_scan_min .. ' kHz' | ||
else | else | ||
hDisplay = h_scan_min .. '–' .. h_scan_max .. ' kHz' | hDisplay = h_scan_min .. '–' .. h_scan_max .. ' kHz' | ||
end | end | ||
| Line 658: | Line 662: | ||
end | end | ||
if v_scan_min or v_scan_max then | if v_scan_min or v_scan_max then | ||
local vDisplay | local vDisplay | ||
if v_scan_min and v_scan_max then | if v_scan_min and v_scan_max then | ||
if v_scan_min == v_scan_max then | if v_scan_min == v_scan_max then | ||
vDisplay = v_scan_min .. ' Hz' | vDisplay = v_scan_min .. ' Hz' | ||
else | else | ||
vDisplay = v_scan_min .. '–' .. v_scan_max .. ' Hz' | vDisplay = v_scan_min .. '–' .. v_scan_max .. ' Hz' | ||
end | end | ||
| Line 679: | Line 680: | ||
-- Inputs, Outputs, and Control Ports sections | -- Inputs, Outputs, and Control Ports sections | ||
local function renderIOSection(sectionTitle, ioType) | local function renderIOSection(sectionTitle, ioType) | ||
local locations = discoverLocations(frame, fullPageName, ioType) | local locations = discoverLocations(frame, fullPageName, ioType) | ||
| Line 713: | Line 711: | ||
renderIOSection('Control Ports', 'control') | renderIOSection('Control Ports', 'control') | ||
-- Accessories section | -- Accessories section | ||
addSectionRow(container, 'Accessories') | addSectionRow(container, 'Accessories') | ||
local addAccessoryUrl = mw.uri.fullUrl( | local addAccessoryUrl = mw.uri.fullUrl( | ||
" | "Create an accessory", | ||
{ | { | ||
crt_models = pageName | |||
} | } | ||
) | ) | ||
local accessoriesCountWikitext = | local accessoriesCountWikitext = | ||
'{{#ask:\n' .. | '{{#ask:\n' .. | ||
| Line 740: | Line 735: | ||
if hasAccessories then | if hasAccessories then | ||
local accessoriesQueryWikitext = | local accessoriesQueryWikitext = | ||
'{{#ask:\n' .. | '{{#ask:\n' .. | ||
| Line 754: | Line 748: | ||
local accessoriesResult = frame:preprocess(accessoriesQueryWikitext) | local accessoriesResult = frame:preprocess(accessoriesQueryWikitext) | ||
local accessoriesByType = {} | local accessoriesByType = {} | ||
local typeOrder = {} | local typeOrder = {} | ||
| Line 766: | Line 759: | ||
end | end | ||
if #cells >= 2 then | if #cells >= 2 then | ||
local accPageName = cells[1] | local accPageName = cells[1] | ||
| Line 772: | Line 764: | ||
if accPageName then | if accPageName then | ||
if not accessoriesByType[accType] then | if not accessoriesByType[accType] then | ||
accessoriesByType[accType] = {} | accessoriesByType[accType] = {} | ||
| Line 786: | Line 777: | ||
end | end | ||
local accGrid = accDiv:tag('div') | local accGrid = accDiv:tag('div') | ||
css(accGrid, 'display:grid; grid-template-columns:auto 1fr; gap:3px;') | css(accGrid, 'display:grid; grid-template-columns:auto 1fr; gap:3px;') | ||
for _, accType in ipairs(typeOrder) do | for _, accType in ipairs(typeOrder) do | ||
local accs = accessoriesByType[accType] | local accs = accessoriesByType[accType] | ||
| Line 811: | Line 800: | ||
end | end | ||
local addAccDiv = mw.html.create('div') | local addAccDiv = mw.html.create('div') | ||
addAccDiv:css('margin-top', '0.5em'):css('text-align', 'center') | addAccDiv:css('margin-top', '0.5em'):css('text-align', 'center') | ||
| Line 817: | Line 805: | ||
accDiv:node(addAccDiv) | accDiv:node(addAccDiv) | ||
else | else | ||
local addAccDiv = mw.html.create('div') | local addAccDiv = mw.html.create('div') | ||
addAccDiv:css('text-align', 'center') | addAccDiv:css('text-align', 'center') | ||
| Line 827: | Line 814: | ||
addSectionRow(container, 'Parts') | addSectionRow(container, 'Parts') | ||
local addPartUrl = mw.uri.fullUrl( | local addPartUrl = mw.uri.fullUrl( | ||
" | "Create a part", | ||
{ | { | ||
crt_models = pageName | |||
} | } | ||
) | ) | ||
local partsCountWikitext = | local partsCountWikitext = | ||
'{{#ask:\n' .. | '{{#ask:\n' .. | ||
| Line 850: | Line 834: | ||
if hasParts then | if hasParts then | ||
local partsQueryWikitext = | local partsQueryWikitext = | ||
'{{#ask:\n' .. | '{{#ask:\n' .. | ||
| Line 864: | Line 847: | ||
local partsResult = frame:preprocess(partsQueryWikitext) | local partsResult = frame:preprocess(partsQueryWikitext) | ||
local partsByType = {} | local partsByType = {} | ||
local partTypeOrder = {} | local partTypeOrder = {} | ||
| Line 876: | Line 858: | ||
end | end | ||
if #cells >= 2 then | if #cells >= 2 then | ||
local partPageName = cells[1] | local partPageName = cells[1] | ||
| Line 882: | Line 863: | ||
local partSubtype = cells[3] | local partSubtype = cells[3] | ||
local groupKey = partType | local groupKey = partType | ||
if partSubtype and partSubtype ~= '' then | if partSubtype and partSubtype ~= '' then | ||
| Line 890: | Line 869: | ||
if partPageName then | if partPageName then | ||
if not partsByType[groupKey] then | if not partsByType[groupKey] then | ||
partsByType[groupKey] = {} | partsByType[groupKey] = {} | ||
| Line 904: | Line 882: | ||
end | end | ||
local partsGrid = partsDiv:tag('div') | local partsGrid = partsDiv:tag('div') | ||
css(partsGrid, 'display:grid; grid-template-columns:auto 1fr; gap:3px;') | css(partsGrid, 'display:grid; grid-template-columns:auto 1fr; gap:3px;') | ||
for _, partType in ipairs(partTypeOrder) do | for _, partType in ipairs(partTypeOrder) do | ||
local parts = partsByType[partType] | local parts = partsByType[partType] | ||
| Line 914: | Line 890: | ||
local partLinks = {} | local partLinks = {} | ||
for _, part in ipairs(parts) do | for _, part in ipairs(parts) do | ||
table.insert(partLinks, '[[' .. part.page .. ']]') | table.insert(partLinks, '[[' .. part.page .. ']]') | ||
end | end | ||
| Line 930: | Line 905: | ||
end | end | ||
local addPartDiv = mw.html.create('div') | local addPartDiv = mw.html.create('div') | ||
addPartDiv:css('margin-top', '0.5em'):css('text-align', 'center') | addPartDiv:css('margin-top', '0.5em'):css('text-align', 'center') | ||
| Line 936: | Line 910: | ||
partsDiv:node(addPartDiv) | partsDiv:node(addPartDiv) | ||
else | else | ||
local addPartDiv = mw.html.create('div') | local addPartDiv = mw.html.create('div') | ||
addPartDiv:css('text-align', 'center') | addPartDiv:css('text-align', 'center') | ||
| Line 943: | Line 916: | ||
end | end | ||
-- Mods section | -- Mods section | ||
local modsQueryWikitext = | local modsQueryWikitext = | ||
'{{#ask:\n' .. | '{{#ask:\n' .. | ||
| Line 958: | Line 931: | ||
local modsResult = frame:preprocess(modsQueryWikitext) | local modsResult = frame:preprocess(modsQueryWikitext) | ||
local mods = {} | local mods = {} | ||
| Line 999: | Line 971: | ||
end | end | ||
if #mods > 0 then | if #mods > 0 then | ||
addSectionRow(container, 'Mods') | addSectionRow(container, 'Mods') | ||
| Line 1,012: | Line 983: | ||
local li = ul:tag('li') | local li = ul:tag('li') | ||
local displayText = mod.description or mod.type | local displayText = mod.description or mod.type | ||
local isFeasible = mod.feasible ~= 'No' | local isFeasible = mod.feasible ~= 'No' | ||
if isFeasible then | if isFeasible then | ||
li:wikitext('[' .. mod.url .. ' ' .. displayText .. ']') | li:wikitext('[' .. mod.url .. ' ' .. displayText .. ']') | ||
else | else | ||
local wrapper = li:tag('span') | local wrapper = li:tag('span') | ||
wrapper:addClass('mod-not-feasible') | wrapper:addClass('mod-not-feasible') | ||
| Line 1,036: | Line 1,002: | ||
addSectionRow(container, 'Documents') | addSectionRow(container, 'Documents') | ||
local timestamp = os.time() | local timestamp = os.time() | ||
math.randomseed(timestamp + pageId) | math.randomseed(timestamp + pageId) | ||
local random = math.random(1000, 9999) | local random = math.random(1000, 9999) | ||
local target = "Document:" .. timestamp .. "-" .. random | local target = "Document:" .. timestamp .. "-" .. random | ||
| Line 1,050: | Line 1,015: | ||
) | ) | ||
local documentsCountWikitext = | local documentsCountWikitext = | ||
'{{#ask:\n' .. | '{{#ask:\n' .. | ||
| Line 1,060: | Line 1,024: | ||
local hasDocuments = documentCount and tonumber(trim(documentCount)) and tonumber(trim(documentCount)) > 0 | local hasDocuments = documentCount and tonumber(trim(documentCount)) and tonumber(trim(documentCount)) > 0 | ||
local docsDiv = container:tag('div') | local docsDiv = container:tag('div') | ||
css(docsDiv, 'grid-column: 1 / -1; padding:0.2em 0.4em;') | css(docsDiv, 'grid-column: 1 / -1; padding:0.2em 0.4em;') | ||
if hasDocuments then | if hasDocuments then | ||
local docsQueryWikitext = | local docsQueryWikitext = | ||
'{{#ask:\n' .. | '{{#ask:\n' .. | ||
| Line 1,080: | Line 1,042: | ||
local docsResult = frame:preprocess(docsQueryWikitext) | local docsResult = frame:preprocess(docsQueryWikitext) | ||
local ul = mw.html.create('ul') | local ul = mw.html.create('ul') | ||
ul:css('margin', '0'):css('padding-left', '1.5em') | ul:css('margin', '0'):css('padding-left', '1.5em') | ||
if docsResult then | if docsResult then | ||
for rowContent in docsResult:gmatch('<tr[^>]*>(.-)</tr>') do | for rowContent in docsResult:gmatch('<tr[^>]*>(.-)</tr>') do | ||
local cells = {} | local cells = {} | ||
for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do | for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do | ||
local cleanContent = cellContent:gsub('<[^>]+>', '') | local cleanContent = cellContent:gsub('<[^>]+>', '') | ||
table.insert(cells, cleanContent) | table.insert(cells, cleanContent) | ||
end | end | ||
if #cells >= 2 then | if #cells >= 2 then | ||
local docType = trim(cells[2]) | local docType = trim(cells[2]) | ||
| Line 1,103: | Line 1,059: | ||
local docTitle = trim(cells[5]) | local docTitle = trim(cells[5]) | ||
local linkTarget = nil | local linkTarget = nil | ||
if docUrl then | if docUrl then | ||
linkTarget = docUrl | linkTarget = docUrl | ||
elseif docFile then | elseif docFile then | ||
local filename = docFile:match('File:(.+)') or docFile | local filename = docFile:match('File:(.+)') or docFile | ||
linkTarget = tostring(mw.uri.fullUrl('File:' .. filename)) | linkTarget = tostring(mw.uri.fullUrl('File:' .. filename)) | ||
end | end | ||
local docPageName = trim(cells[1]) | local docPageName = trim(cells[1]) | ||
if docPageName then | if docPageName then | ||
local displayText = 'Document' | local displayText = 'Document' | ||
if docTitle then | if docTitle then | ||
| Line 1,125: | Line 1,077: | ||
end | end | ||
local li = ul:tag('li') | local li = ul:tag('li') | ||
li:wikitext('[[' .. docPageName .. '|' .. displayText .. ']]') | li:wikitext('[[' .. docPageName .. '|' .. displayText .. ']]') | ||
| Line 1,135: | Line 1,086: | ||
docsDiv:node(ul) | docsDiv:node(ul) | ||
local uploadDiv = mw.html.create('div') | local uploadDiv = mw.html.create('div') | ||
uploadDiv:css('margin-top', '0.5em'):css('text-align', 'center') | uploadDiv:css('margin-top', '0.5em'):css('text-align', 'center') | ||
| Line 1,142: | Line 1,092: | ||
docsDiv:node(uploadDiv) | docsDiv:node(uploadDiv) | ||
else | else | ||
local uploadDiv = mw.html.create('div') | local uploadDiv = mw.html.create('div') | ||
uploadDiv:css('text-align', 'center') | uploadDiv:css('text-align', 'center') | ||
| Line 1,150: | Line 1,099: | ||
end | end | ||
-- Links section | -- Links section | ||
local linksQueryWikitext = | local linksQueryWikitext = | ||
'{{#ask:\n' .. | '{{#ask:\n' .. | ||
| Line 1,163: | Line 1,112: | ||
local linksResult = frame:preprocess(linksQueryWikitext) | local linksResult = frame:preprocess(linksQueryWikitext) | ||
local linksByType = { | local linksByType = { | ||
Manufacturer = {}, | Manufacturer = {}, | ||
| Line 1,172: | Line 1,120: | ||
if linksResult then | if linksResult then | ||
for rowContent in linksResult:gmatch('<tr[^>]*>(.-)</tr>') do | for rowContent in linksResult:gmatch('<tr[^>]*>(.-)</tr>') do | ||
local cells = {} | local cells = {} | ||
for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do | for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do | ||
local cleanContent = cellContent:gsub('<[^>]+>', '') | local cleanContent = cellContent:gsub('<[^>]+>', '') | ||
table.insert(cells, trim(cleanContent)) | table.insert(cells, trim(cleanContent)) | ||
end | end | ||
if #cells >= 4 then | if #cells >= 4 then | ||
local linkType = cells[2] | local linkType = cells[2] | ||
| Line 1,198: | Line 1,142: | ||
end | end | ||
if hasLinks then | if hasLinks then | ||
addSectionRow(container, 'Archival Links') | addSectionRow(container, 'Archival Links') | ||
local linkTypeOrder = {'Database', 'Manufacturer', 'Retailer'} | local linkTypeOrder = {'Database', 'Manufacturer', 'Retailer'} | ||
for _, linkType in ipairs(linkTypeOrder) do | for _, linkType in ipairs(linkTypeOrder) do | ||
if #linksByType[linkType] > 0 then | if #linksByType[linkType] > 0 then | ||
local linksHtml = {} | local linksHtml = {} | ||
for _, link in ipairs(linksByType[linkType]) do | for _, link in ipairs(linksByType[linkType]) do | ||
| Line 1,219: | Line 1,160: | ||
addSectionRow(container, 'Contribute') | addSectionRow(container, 'Contribute') | ||
local editUrl = mw.uri.fullUrl( | local editUrl = mw.uri.fullUrl( | ||
"Special:FormStart", | "Special:FormStart", | ||
| Line 1,228: | Line 1,168: | ||
) | ) | ||
local editDiv = container:tag('div') | local editDiv = container:tag('div') | ||
css(editDiv, 'grid-column: 1 / -1; padding:0.2em 0.4em; text-align:center;') | css(editDiv, 'grid-column: 1 / -1; padding:0.2em 0.4em; text-align:center;') | ||
editDiv:wikitext('[' .. tostring(editUrl) .. ' <span class="infobox-button infobox-button-primary">Edit this data</span>]') | editDiv:wikitext('[' .. tostring(editUrl) .. ' <span class="infobox-button infobox-button-primary">Edit this data</span>]') | ||
return styleTag .. tostring(container) | return styleTag .. tostring(container) | ||
end | end | ||
return p | return p | ||