Module:MaintenanceDashboard

Revision as of 22:34, 4 February 2026 by Arclight-MCP-Bot (talk | contribs) (Create module for maintenance dashboard status checks (via create-page on MediaWiki MCP Server))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Documentation for this module may be created at Module:MaintenanceDashboard/doc

-- Module:MaintenanceDashboard
-- Generates status cards for various maintenance checks across the wiki

local p = {}

local function trim(s)
	if s == nil then return nil end
	s = tostring(s)
	s = s:gsub('^%s+', ''):gsub('%s+$', '')
	if s == '' then return nil end
	return s
end

-- Get count from an SMW query
local function getCount(frame, query)
	local result = frame:preprocess('{{#ask:' .. query .. '|format=count}}')
	return tonumber(trim(result)) or 0
end

-- Generate a single status card
local function statusCard(label, count, link, threshold_warning, threshold_error)
	threshold_warning = threshold_warning or 1
	threshold_error = threshold_error or 10
	
	local status = 'ok'
	if count >= threshold_error then
		status = 'error'
	elseif count >= threshold_warning then
		status = 'warning'
	end
	
	local linkAttr = ''
	if link then
		linkAttr = '|link=' .. link
	end
	
	return '{{Maintenance status card|label=' .. label .. '|count=' .. count .. '|status=' .. status .. linkAttr .. '}}'
end

-- Category maintenance status grid
function p.categoryStatus(frame)
	-- Count missing category pages using the audit logic
	local missingCRTBrands = 0
	local missingCRTTypes = 0
	local missingAVBrands = 0
	local missingAVTypes = 0
	
	-- Get used CRT brands
	local usedCRTBrands = {}
	local brandQuery = frame:preprocess('{{#ask:[[Category:CRT models]][[Has brand::+]]|?Has brand|format=broadtable|headers=hide|link=none|mainlabel=-|limit=500|searchlabel=}}')
	if brandQuery then
		for cell in brandQuery:gmatch('<td[^>]*>(.-)</td>') do
			local brand = trim(cell:gsub('<[^>]+>', ''))
			if brand and brand ~= '' then
				usedCRTBrands[brand] = true
			end
		end
	end
	
	-- Get registered CRT brand categories
	local registeredCRTBrands = {}
	local regQuery = frame:preprocess('{{#ask:[[Is CRT brand category::Yes]]|?Brand name|format=broadtable|headers=hide|link=none|mainlabel=-|limit=500|searchlabel=}}')
	if regQuery then
		for cell in regQuery:gmatch('<td[^>]*>(.-)</td>') do
			local brand = trim(cell:gsub('<[^>]+>', ''))
			if brand and brand ~= '' then
				registeredCRTBrands[brand] = true
			end
		end
	end
	
	for brand, _ in pairs(usedCRTBrands) do
		if not registeredCRTBrands[brand] then
			missingCRTBrands = missingCRTBrands + 1
		end
	end
	
	-- Get used CRT types
	local usedCRTTypes = {}
	local typeQuery = frame:preprocess('{{#ask:[[Category:CRT models]][[Has CRT type::+]]|?Has CRT type|format=broadtable|headers=hide|link=none|mainlabel=-|limit=500|searchlabel=}}')
	if typeQuery then
		for cell in typeQuery:gmatch('<td[^>]*>(.-)</td>') do
			local crtType = trim(cell:gsub('<[^>]+>', ''))
			if crtType and crtType ~= '' then
				usedCRTTypes[crtType] = true
			end
		end
	end
	
	-- Get registered CRT type categories
	local registeredCRTTypes = {}
	local regTypeQuery = frame:preprocess('{{#ask:[[Is CRT type category::Yes]]|?CRT type name|format=broadtable|headers=hide|link=none|mainlabel=-|limit=500|searchlabel=}}')
	if regTypeQuery then
		for cell in regTypeQuery:gmatch('<td[^>]*>(.-)</td>') do
			local crtType = trim(cell:gsub('<[^>]+>', ''))
			if crtType and crtType ~= '' then
				registeredCRTTypes[crtType] = true
			end
		end
	end
	
	for crtType, _ in pairs(usedCRTTypes) do
		if not registeredCRTTypes[crtType] then
			missingCRTTypes = missingCRTTypes + 1
		end
	end
	
	-- Get used AV brands
	local usedAVBrands = {}
	local avBrandQuery = frame:preprocess('{{#ask:[[Category:AV devices]][[Has brand::+]]|?Has brand|format=broadtable|headers=hide|link=none|mainlabel=-|limit=500|searchlabel=}}')
	if avBrandQuery then
		for cell in avBrandQuery:gmatch('<td[^>]*>(.-)</td>') do
			local brand = trim(cell:gsub('<[^>]+>', ''))
			if brand and brand ~= '' then
				usedAVBrands[brand] = true
			end
		end
	end
	
	-- Get registered AV brand categories
	local registeredAVBrands = {}
	local regAVQuery = frame:preprocess('{{#ask:[[Is AV brand category::Yes]]|?Brand name|format=broadtable|headers=hide|link=none|mainlabel=-|limit=500|searchlabel=}}')
	if regAVQuery then
		for cell in regAVQuery:gmatch('<td[^>]*>(.-)</td>') do
			local brand = trim(cell:gsub('<[^>]+>', ''))
			if brand and brand ~= '' then
				registeredAVBrands[brand] = true
			end
		end
	end
	
	for brand, _ in pairs(usedAVBrands) do
		if not registeredAVBrands[brand] then
			missingAVBrands = missingAVBrands + 1
		end
	end
	
	-- Get used AV types
	local usedAVTypes = {}
	local avTypeQuery = frame:preprocess('{{#ask:[[Category:AV devices]][[Has device type::+]]|?Has device type|format=broadtable|headers=hide|link=none|mainlabel=-|limit=500|searchlabel=}}')
	if avTypeQuery then
		for cell in avTypeQuery:gmatch('<td[^>]*>(.-)</td>') do
			local deviceType = trim(cell:gsub('<[^>]+>', ''))
			if deviceType and deviceType ~= '' then
				usedAVTypes[deviceType] = true
			end
		end
	end
	
	-- Get registered AV type categories
	local registeredAVTypes = {}
	local regAVTypeQuery = frame:preprocess('{{#ask:[[Is AV device type category::Yes]]|?Device type name|format=broadtable|headers=hide|link=none|mainlabel=-|limit=500|searchlabel=}}')
	if regAVTypeQuery then
		for cell in regAVTypeQuery:gmatch('<td[^>]*>(.-)</td>') do
			local deviceType = trim(cell:gsub('<[^>]+>', ''))
			if deviceType and deviceType ~= '' then
				registeredAVTypes[deviceType] = true
			end
		end
	end
	
	for deviceType, _ in pairs(usedAVTypes) do
		if not registeredAVTypes[deviceType] then
			missingAVTypes = missingAVTypes + 1
		end
	end
	
	-- Build output
	local cards = {}
	table.insert(cards, statusCard('CRT Brand Categories', missingCRTBrands, 'EveryCRT:Category maintenance#CRT Brands Missing Category Pages', 1, 5))
	table.insert(cards, statusCard('CRT Type Categories', missingCRTTypes, 'EveryCRT:Category maintenance#CRT Types Missing Category Pages', 1, 3))
	table.insert(cards, statusCard('AV Brand Categories', missingAVBrands, 'EveryCRT:Category maintenance#AV Brands Missing Category Pages', 1, 5))
	table.insert(cards, statusCard('AV Type Categories', missingAVTypes, 'EveryCRT:Category maintenance#AV Device Types Missing Category Pages', 1, 3))
	
	local output = '<div class="maintenance-status-grid">\n'
	for _, card in ipairs(cards) do
		output = output .. frame:preprocess(card) .. '\n'
	end
	output = output .. '</div>'
	
	return output
end

-- Data quality status grid
function p.dataQualityStatus(frame)
	local crtStubs = getCount(frame, '[[Category:CRT stubs]]')
	local crtNoImage = getCount(frame, '[[Category:CRT models needing images]]')
	local crtNoType = getCount(frame, '[[Category:CRTs missing type]]')
	local crtNoSeries = getCount(frame, '[[Category:CRTs without series]]')
	local avStubs = getCount(frame, '[[Category:AV device stubs]]')
	
	local cards = {}
	table.insert(cards, statusCard('CRT Stubs', crtStubs, 'Category:CRT stubs', 50, 200))
	table.insert(cards, statusCard('CRTs Need Images', crtNoImage, 'Category:CRT models needing images', 50, 200))
	table.insert(cards, statusCard('CRTs Missing Type', crtNoType, 'Category:CRTs missing type', 10, 50))
	table.insert(cards, statusCard('CRTs No Series', crtNoSeries, 'Category:CRTs without series', 100, 500))
	table.insert(cards, statusCard('AV Device Stubs', avStubs, 'Category:AV device stubs', 10, 50))
	
	local output = '<div class="maintenance-status-grid">\n'
	for _, card in ipairs(cards) do
		output = output .. frame:preprocess(card) .. '\n'
	end
	output = output .. '</div>'
	
	return output
end

-- Full dashboard combining all checks
function p.fullDashboard(frame)
	local output = ''
	
	output = output .. '=== Category System ===\n'
	output = output .. p.categoryStatus(frame) .. '\n\n'
	
	output = output .. '=== Data Quality ===\n'
	output = output .. p.dataQualityStatus(frame) .. '\n'
	
	return output
end

-- Summary counts for the main dashboard
function p.summaryCounts(frame)
	-- Category issues
	local categoryIssues = 0
	
	-- Quick check for missing categories (simplified)
	local usedBrands = {}
	local brandQuery = frame:preprocess('{{#ask:[[Category:CRT models]][[Has brand::+]]|?Has brand|format=broadtable|headers=hide|link=none|mainlabel=-|limit=500|searchlabel=}}')
	if brandQuery then
		for cell in brandQuery:gmatch('<td[^>]*>(.-)</td>') do
			local brand = trim(cell:gsub('<[^>]+>', ''))
			if brand and brand ~= '' then usedBrands[brand] = true end
		end
	end
	
	local registeredBrands = {}
	local regQuery = frame:preprocess('{{#ask:[[Is CRT brand category::Yes]]|?Brand name|format=broadtable|headers=hide|link=none|mainlabel=-|limit=500|searchlabel=}}')
	if regQuery then
		for cell in regQuery:gmatch('<td[^>]*>(.-)</td>') do
			local brand = trim(cell:gsub('<[^>]+>', ''))
			if brand and brand ~= '' then registeredBrands[brand] = true end
		end
	end
	
	for brand, _ in pairs(usedBrands) do
		if not registeredBrands[brand] then categoryIssues = categoryIssues + 1 end
	end
	
	-- Data quality
	local crtStubs = getCount(frame, '[[Category:CRT stubs]]')
	local crtNoImage = getCount(frame, '[[Category:CRT models needing images]]')
	
	-- Totals
	local totalIssues = categoryIssues + crtStubs + crtNoImage
	
	return tostring(totalIssues)
end

return p
MediaWiki Appliance - Powered by TurnKey Linux