Module:CRTModel: Difference between revisions

Add market row to infobox Overview section (after variants) (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)
 
(9 intermediate revisions by the same user not shown)
Line 297: 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 565: 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
-- Single voltage (e.g., "120V")
rangeStr = range.min .. 'V'
rangeStr = range.min .. 'V'
else
else
-- Range (e.g., "100–120V")
rangeStr = range.min .. '–' .. range.max .. 'V'
rangeStr = range.min .. '–' .. range.max .. 'V'
end
end
Line 582: Line 588:
if #rangeStrings > 0 then
if #rangeStrings > 0 then
-- Join multiple ranges with " / " (e.g., "100–120V / 220–240V")
addRow(container, 'Voltage', table.concat(rangeStrings, ' / '), false)
addRow(container, 'Voltage', table.concat(rangeStrings, ' / '), false)
end
end
Line 610: Line 615:
addSectionRow(container, 'TV Systems')
addSectionRow(container, 'TV Systems')
-- AV system row (baseband video color support)
if av_system then
if av_system then
-- Link each system to its wiki page
local systems = {}
local systems = {}
for system in av_system:gmatch('[^,]+') do
for system in av_system:gmatch('[^,]+') do
Line 625: Line 628:
end
end
-- Tuner system row (RF broadcast standards)
if tuner_system then
if tuner_system then
-- Link each system to its wiki page
local systems = {}
local systems = {}
for system in tuner_system:gmatch('[^,]+') do
for system in tuner_system:gmatch('[^,]+') do
Line 641: Line 642:
end
end


-- Scan Range section: show if we have any scan range specs
-- 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')
-- Horizontal scan row
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
-- Single frequency (e.g., "15.7 kHz")
hDisplay = h_scan_min .. ' kHz'
hDisplay = h_scan_min .. ' kHz'
else
else
-- Range (e.g., "15–100 kHz")
hDisplay = h_scan_min .. '–' .. h_scan_max .. ' kHz'
hDisplay = h_scan_min .. '–' .. h_scan_max .. ' kHz'
end
end
Line 664: Line 662:
end
end
-- Vertical scan row
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
-- Single frequency (e.g., "60 Hz")
vDisplay = v_scan_min .. ' Hz'
vDisplay = v_scan_min .. ' Hz'
else
else
-- Range (e.g., "50–160 Hz")
vDisplay = v_scan_min .. '–' .. v_scan_max .. ' Hz'
vDisplay = v_scan_min .. '–' .. v_scan_max .. ' Hz'
end
end
Line 685: Line 680:


-- Inputs, Outputs, and Control Ports sections
-- Inputs, Outputs, and Control Ports sections
-- Dynamically discover locations from semantic data instead of hardcoding
-- Helper closure to render an I/O section with dynamically discovered location-based rows
local function renderIOSection(sectionTitle, ioType)
local function renderIOSection(sectionTitle, ioType)
local locations = discoverLocations(frame, fullPageName, ioType)
local locations = discoverLocations(frame, fullPageName, ioType)
Line 719: Line 711:
renderIOSection('Control Ports', 'control')
renderIOSection('Control Ports', 'control')


-- Accessories section: Always show (like Parts/Documents), with "Add accessory" button
-- Accessories section
addSectionRow(container, 'Accessories')
addSectionRow(container, 'Accessories')


-- Build the add accessory link with prefilled CRT model
local addAccessoryUrl = mw.uri.fullUrl(
local addAccessoryUrl = mw.uri.fullUrl(
"Special:FormEdit",
"Create an accessory",
{
{
form = "Accessory",
crt_models = pageName
["Accessory[crt_models]"] = pageName
}
}
)
)


-- Query for non-remote accessories linked via Has related CRT model
local accessoriesCountWikitext =
local accessoriesCountWikitext =
'{{#ask:\n' ..
'{{#ask:\n' ..
Line 746: Line 735:


if hasAccessories then
if hasAccessories then
-- Query accessories and display grouped by type
local accessoriesQueryWikitext =
local accessoriesQueryWikitext =
'{{#ask:\n' ..
'{{#ask:\n' ..
Line 760: Line 748:
local accessoriesResult = frame:preprocess(accessoriesQueryWikitext)
local accessoriesResult = frame:preprocess(accessoriesQueryWikitext)


-- Parse accessories from broadtable result and group by type
local accessoriesByType = {}
local accessoriesByType = {}
local typeOrder = {}
local typeOrder = {}
Line 772: Line 759:
end
end


-- cells[1] = page name, cells[2] = type, cells[3] = model code
if #cells >= 2 then
if #cells >= 2 then
local accPageName = cells[1]
local accPageName = cells[1]
Line 778: Line 764:


if accPageName then
if accPageName then
-- Track type order for consistent display
if not accessoriesByType[accType] then
if not accessoriesByType[accType] then
accessoriesByType[accType] = {}
accessoriesByType[accType] = {}
Line 792: Line 777:
end
end


-- Create a nested grid for accessory rows
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;')


-- Display as label/value rows grouped by type (like Parts)
for _, accType in ipairs(typeOrder) do
for _, accType in ipairs(typeOrder) do
local accs = accessoriesByType[accType]
local accs = accessoriesByType[accType]
Line 817: Line 800:
end
end


-- Add "Add accessory" button
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 823: Line 805:
accDiv:node(addAccDiv)
accDiv:node(addAccDiv)
else
else
-- Just show the add accessory link as a button
local addAccDiv = mw.html.create('div')
local addAccDiv = mw.html.create('div')
addAccDiv:css('text-align', 'center')
addAccDiv:css('text-align', 'center')
Line 833: Line 814:
addSectionRow(container, 'Parts')
addSectionRow(container, 'Parts')
-- Build the add part link with prefilled CRT model
local addPartUrl = mw.uri.fullUrl(
local addPartUrl = mw.uri.fullUrl(
"Special:FormEdit",
"Create a part",
{
{
form = "Part",
crt_models = pageName
["Part[crt_models]"] = pageName
}
}
)
)
-- Query for parts linked via Has related CRT model
local partsCountWikitext =
local partsCountWikitext =
'{{#ask:\n' ..
'{{#ask:\n' ..
Line 856: Line 834:
if hasParts then
if hasParts then
-- Query parts and display grouped by type/subtype
local partsQueryWikitext =
local partsQueryWikitext =
'{{#ask:\n' ..
'{{#ask:\n' ..
Line 870: Line 847:
local partsResult = frame:preprocess(partsQueryWikitext)
local partsResult = frame:preprocess(partsQueryWikitext)
-- Parse parts from broadtable result and group by type
local partsByType = {}
local partsByType = {}
local partTypeOrder = {}
local partTypeOrder = {}
Line 882: Line 858:
end
end
-- cells[1] = page name, cells[2] = type, cells[3] = subtype, cells[4] = model code
if #cells >= 2 then
if #cells >= 2 then
local partPageName = cells[1]
local partPageName = cells[1]
Line 888: Line 863:
local partSubtype = cells[3]
local partSubtype = cells[3]
-- Use subtype + type as the grouping key if subtype exists
-- Keep proper capitalization (e.g., "Frame synchronizer IC" not "Frame synchronizer ic")
local groupKey = partType
local groupKey = partType
if partSubtype and partSubtype ~= '' then
if partSubtype and partSubtype ~= '' then
Line 896: Line 869:
if partPageName then
if partPageName then
-- Track type order for consistent display
if not partsByType[groupKey] then
if not partsByType[groupKey] then
partsByType[groupKey] = {}
partsByType[groupKey] = {}
Line 910: Line 882:
end
end
-- Create a nested grid for part rows
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;')
-- Display as label/value rows grouped by type
for _, partType in ipairs(partTypeOrder) do
for _, partType in ipairs(partTypeOrder) do
local parts = partsByType[partType]
local parts = partsByType[partType]
Line 920: Line 890:
local partLinks = {}
local partLinks = {}
for _, part in ipairs(parts) do
for _, part in ipairs(parts) do
-- Just show the page name (which is "Brand Model"), no description
table.insert(partLinks, '[[' .. part.page .. ']]')
table.insert(partLinks, '[[' .. part.page .. ']]')
end
end
Line 936: Line 905:
end
end
-- Add "Add part" button
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 942: Line 910:
partsDiv:node(addPartDiv)
partsDiv:node(addPartDiv)
else
else
-- Just show the add part link as a button
local addPartDiv = mw.html.create('div')
local addPartDiv = mw.html.create('div')
addPartDiv:css('text-align', 'center')
addPartDiv:css('text-align', 'center')
Line 949: Line 916:
end
end


-- Mods section: Query for mod subobjects and display
-- Mods section
local modsQueryWikitext =
local modsQueryWikitext =
'{{#ask:\n' ..
'{{#ask:\n' ..
Line 964: Line 931:
local modsResult = frame:preprocess(modsQueryWikitext)
local modsResult = frame:preprocess(modsQueryWikitext)
-- Parse mods from broadtable result
local mods = {}
local mods = {}
Line 1,005: Line 971:
end
end
-- Display mods section if there are any
if #mods > 0 then
if #mods > 0 then
addSectionRow(container, 'Mods')
addSectionRow(container, 'Mods')
Line 1,018: Line 983:
local li = ul:tag('li')
local li = ul:tag('li')
-- Determine display text: use description if available, otherwise type
local displayText = mod.description or mod.type
local displayText = mod.description or mod.type
-- Check if mod is not feasible
local isFeasible = mod.feasible ~= 'No'
local isFeasible = mod.feasible ~= 'No'
if isFeasible then
if isFeasible then
-- Normal link for feasible mods using wikitext external link
li:wikitext('[' .. mod.url .. ' ' .. displayText .. ']')
li:wikitext('[' .. mod.url .. ' ' .. displayText .. ']')
else
else
-- Red styling with X for impossible mods
local wrapper = li:tag('span')
local wrapper = li:tag('span')
wrapper:addClass('mod-not-feasible')
wrapper:addClass('mod-not-feasible')
Line 1,042: Line 1,002:
addSectionRow(container, 'Documents')
addSectionRow(container, 'Documents')
-- Build the upload link with pseudorandom unique identifier
local timestamp = os.time()
local timestamp = os.time()
math.randomseed(timestamp + pageId) -- Seed with timestamp + page ID for better randomness
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,056: Line 1,015:
)
)
-- Query for document count
local documentsCountWikitext =
local documentsCountWikitext =
'{{#ask:\n' ..
'{{#ask:\n' ..
Line 1,066: 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
-- Create the content div
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
-- Use #ask to get documents
local docsQueryWikitext =
local docsQueryWikitext =
'{{#ask:\n' ..
'{{#ask:\n' ..
Line 1,086: Line 1,042:
local docsResult = frame:preprocess(docsQueryWikitext)
local docsResult = frame:preprocess(docsQueryWikitext)
-- Create UL element
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')
-- Parse the HTML table - extract data from <td> tags
if docsResult then
if docsResult then
-- Match each table row
for rowContent in docsResult:gmatch('<tr[^>]*>(.-)</tr>') do
for rowContent in docsResult:gmatch('<tr[^>]*>(.-)</tr>') do
local cells = {}
local cells = {}
-- Extract content from each <td>
for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do
for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do
-- Strip any remaining HTML tags and get just the text
local cleanContent = cellContent:gsub('<[^>]+>', '')
local cleanContent = cellContent:gsub('<[^>]+>', '')
table.insert(cells, cleanContent)
table.insert(cells, cleanContent)
end
end
-- cells[1] = page name, cells[2] = type, cells[3] = URL, cells[4] = file, cells[5] = title
if #cells >= 2 then
if #cells >= 2 then
local docType = trim(cells[2])
local docType = trim(cells[2])
Line 1,109: Line 1,059:
local docTitle = trim(cells[5])
local docTitle = trim(cells[5])
-- Determine what to link to (URL or file)
local linkTarget = nil
local linkTarget = nil
if docUrl then
if docUrl then
linkTarget = docUrl
linkTarget = docUrl
elseif docFile then
elseif docFile then
-- Extract filename from "File:..." format if present
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


-- Always link to the wiki page
local docPageName = trim(cells[1])
local docPageName = trim(cells[1])
if docPageName then
if docPageName then
-- Determine display text priority: custom title > type > default
local displayText = 'Document'
local displayText = 'Document'
if docTitle then
if docTitle then
Line 1,131: Line 1,077:
end
end
-- Create list item with link to wiki page
local li = ul:tag('li')
local li = ul:tag('li')
li:wikitext('[[' .. docPageName .. '|' .. displayText .. ']]')
li:wikitext('[[' .. docPageName .. '|' .. displayText .. ']]')
Line 1,141: Line 1,086:
docsDiv:node(ul)
docsDiv:node(ul)
-- Add upload link as a button
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,148: Line 1,092:
docsDiv:node(uploadDiv)
docsDiv:node(uploadDiv)
else
else
-- Just show the upload link as a button
local uploadDiv = mw.html.create('div')
local uploadDiv = mw.html.create('div')
uploadDiv:css('text-align', 'center')
uploadDiv:css('text-align', 'center')
Line 1,156: Line 1,099:
end
end


-- Links section: Query for link subobjects and display by type
-- Links section
local linksQueryWikitext =
local linksQueryWikitext =
'{{#ask:\n' ..
'{{#ask:\n' ..
Line 1,169: Line 1,112:
local linksResult = frame:preprocess(linksQueryWikitext)
local linksResult = frame:preprocess(linksQueryWikitext)
-- Parse links and organize by type
local linksByType = {
local linksByType = {
Manufacturer = {},
Manufacturer = {},
Line 1,178: Line 1,120:
if linksResult then
if linksResult then
-- Match each table row
for rowContent in linksResult:gmatch('<tr[^>]*>(.-)</tr>') do
for rowContent in linksResult:gmatch('<tr[^>]*>(.-)</tr>') do
local cells = {}
local cells = {}
-- Extract content from each <td>
for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do
for cellContent in rowContent:gmatch('<td[^>]*>(.-)</td>') do
-- Strip any remaining HTML tags and get just the text
local cleanContent = cellContent:gsub('<[^>]+>', '')
local cleanContent = cellContent:gsub('<[^>]+>', '')
table.insert(cells, trim(cleanContent))
table.insert(cells, trim(cleanContent))
end
end
-- cells[1] = page/subobject, cells[2] = type, cells[3] = source, cells[4] = URL
if #cells >= 4 then
if #cells >= 4 then
local linkType = cells[2]
local linkType = cells[2]
Line 1,204: Line 1,142:
end
end
-- Display links section if there are any links
if hasLinks then
if hasLinks then
addSectionRow(container, 'Archival Links')
addSectionRow(container, 'Archival Links')
-- Add links in order: Database, Manufacturer, Retailer
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
-- If multiple links of the same type, combine them in one row
local linksHtml = {}
local linksHtml = {}
for _, link in ipairs(linksByType[linkType]) do
for _, link in ipairs(linksByType[linkType]) do
Line 1,225: Line 1,160:
addSectionRow(container, 'Contribute')
addSectionRow(container, 'Contribute')
-- Build the edit link URL
local editUrl = mw.uri.fullUrl(
local editUrl = mw.uri.fullUrl(
"Special:FormStart",
"Special:FormStart",
Line 1,234: Line 1,168:
)
)
-- Create the edit button div
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;')
-- Add edit button with primary action styling (using class for night mode compatibility)
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 templatestyles tag + container HTML
return styleTag .. tostring(container)
return styleTag .. tostring(container)
end
end


return p
return p
MediaWiki Appliance - Powered by TurnKey Linux