Module:T-CountryHub: Difference between revisions
// via Wikitext Extension for VSCode |
Maintenance update // via Wikitext Extension for VSCode |
||
| (37 intermediate revisions by the same user not shown) | |||
| Line 21: | Line 21: | ||
local CountryData = safeRequire('Module:CountryData') | local CountryData = safeRequire('Module:CountryData') | ||
local TemplateHelpers = safeRequire('Module:TemplateHelpers') | local TemplateHelpers = safeRequire('Module:TemplateHelpers') | ||
local LinkParser = safeRequire('Module:LinkParser') | |||
local NormalizationText = safeRequire('Module:NormalizationText') | local NormalizationText = safeRequire('Module:NormalizationText') | ||
local NormalizationDiacritic = safeRequire('Module:NormalizationDiacritic') | local NormalizationDiacritic = safeRequire('Module:NormalizationDiacritic') | ||
local MasonryLayout = safeRequire('Module:MasonryLayout') | |||
local mw = mw | local mw = mw | ||
local html = mw.html | local html = mw.html | ||
| Line 69: | Line 71: | ||
end | end | ||
-- | -- renderSection: A wrapper function that performs a cached SMW query and renders a table only if results are found. | ||
-- | -- @param key string: The base cache key for the query. | ||
-- @param params table: The parameters for the smw.ask query. | |||
-- | -- @param columns table: A list of column headers for the table. | ||
-- @return string: An HTML table if data is found, otherwise an empty string. | |||
local function renderSection(key, params, columns) | |||
-- | local data = askCached(key, params) | ||
if not data or #data == 0 then | |||
return '' | |||
end | |||
-- | return renderTable(data, columns) | ||
end | |||
local errorContext = ErrorHandling.createContext("T-CountryHub") | local errorContext = ErrorHandling.createContext("T-CountryHub") | ||
| Line 110: | Line 101: | ||
people = true, | people = true, | ||
laws = true, | laws = true, | ||
documents = | documents = false, | ||
geoTlds = true, | geoTlds = true, | ||
meetings = true, | meetings = true, | ||
nra = true, | nra = true, | ||
resources = | resources = false, | ||
semanticProperties = true, | semanticProperties = true, | ||
categories = true, | categories = true, | ||
| Line 130: | Line 121: | ||
template.config.blockSequence = { | template.config.blockSequence = { | ||
'wrapperOpen', | 'wrapperOpen', | ||
' | 'featureBanner', | ||
'overview', | 'overview', | ||
' | 'intelligentMasonry', | ||
'wrapperClose', | 'wrapperClose', | ||
'categories', | 'categories', | ||
'errors' | 'errors' | ||
} | |||
-- MASONRY LAYOUT CONFIGURATION | |||
local cardDefinitions = { | |||
{blockId = 'intro', feature = 'intro', title = 'Welcome'}, | |||
{blockId = 'organizations', feature = 'organizations', title = 'Organizations'}, | |||
{blockId = 'people', feature = 'people', title = 'People'}, | |||
{blockId = 'geoTlds', feature = 'geoTlds', title = 'GeoTLDs'}, | |||
{blockId = 'meetings', feature = 'meetings', title = 'Internet Governance Events'}, | |||
{blockId = 'nra', feature = 'nra', title = 'National Authorities'}, | |||
{blockId = 'laws', feature = 'laws', title = 'Laws and Regulations'}, | |||
{blockId = 'documents', feature = 'documents', title = 'Key Documents'}, | |||
{blockId = 'resources', feature = 'resources', title = 'Resources'}, | |||
{blockId = 'infoBox', feature = 'infoBox', title = 'Country Info'} | |||
} | |||
local masonryOptions = { | |||
columns = 3, | |||
mobileColumns = 1, | |||
containerClass = 'country-hub-masonry-container', | |||
columnClass = 'country-hub-masonry-column', | |||
cardClass = 'country-hub-masonry-card', | |||
-- Note: We cannot detect mobile server-side in MediaWiki | |||
-- The MasonryLayout will output both desktop and mobile HTML | |||
-- CSS media queries will handle the actual display | |||
mobileMode = false -- Always use desktop mode in Lua, CSS handles responsive | |||
} | } | ||
| Line 170: | Line 179: | ||
return '<div class="country-hub-wrapper">' -- .. flagImageWikitext -- Appended flag | return '<div class="country-hub-wrapper">' -- .. flagImageWikitext -- Appended flag | ||
end | |||
} | |||
-- Feature Preview Banner | |||
template.config.blocks.featureBanner = { | |||
feature = 'fullPage', | |||
render = function(template, args) | |||
return '<div class="country-hub-feature-banner">' .. | |||
'<strong>Country Hubs</strong> have been enabled as a feature preview and are still under testing.' .. | |||
' Contribute more knowledge to our database so that they can keep growing!' .. | |||
'</div>' | |||
end | end | ||
} | } | ||
| Line 198: | Line 218: | ||
local regionData = askCached('infoBox:region:' .. args.has_country, regionParams) | local regionData = askCached('infoBox:region:' .. args.has_country, regionParams) | ||
local regionText = regionData[1] and regionData[1]['Has ICANN region'] or '' | local regionText = regionData[1] and regionData[1]['Has ICANN region'] or '' | ||
regionText = | regionText = LinkParser.processWikiLink(regionText, 'strip') | ||
-- Check for an ISOC chapter in the country using fuzzy matching | -- Check for an ISOC chapter in the country using fuzzy matching | ||
| Line 251: | Line 271: | ||
if not foundMatch then | if not foundMatch then | ||
ISOCText = string.format('[[Internet Society %s Chapter]]', args.has_country) | ISOCText = string.format('[[Internet Society %s Chapter]]', args.has_country) | ||
end | end | ||
| Line 312: | Line 319: | ||
:tag('th'):wikitext('ISOC chapter'):done() | :tag('th'):wikitext('ISOC chapter'):done() | ||
:tag('td'):wikitext(ISOCText):done() | :tag('td'):wikitext(ISOCText):done() | ||
:done() | :done() | ||
| Line 339: | Line 340: | ||
-- ANCHOR: OVERVIEW | -- ANCHOR: OVERVIEW | ||
template.config.blocks.overview = { | |||
feature = 'overview', | |||
render = function(template, args) | |||
local displayCountry = (args.country or mw.title.getCurrentTitle().text or ""):gsub('_',' ') | |||
local queryCountryName = args.has_country | |||
local params = { | |||
string.format('[[Has country::%s]]', queryCountryName), | |||
'[[Category:Country]]', | |||
'?Has description', | |||
format = 'plain', | |||
limit = 1 | |||
} | |||
local data = askCached('overview:' .. queryCountryName, params) | |||
local desc = (data[1] and data[1]['Has description']) or '' | |||
if desc == '' then | |||
desc = 'No overview description found for ' .. displayCountry .. '.' | |||
end | |||
return '== Overview ==\n' .. desc | |||
end | |||
} | |||
-- ANCHOR: ORGANIZATIONS | -- ANCHOR: ORGANIZATIONS | ||
| Line 364: | Line 365: | ||
feature = 'organizations', | feature = 'organizations', | ||
render = function(template, args) | render = function(template, args) | ||
local params = { | local params = { | ||
string.format('[[Has country::%s]] [[Has entity type::Organization]]', args.has_country), | string.format('[[Has country::%s]] [[Has entity type::Organization]]', args.has_country), | ||
limit = | limit = 20 | ||
} | } | ||
local data = askCached('organizations:' .. args.has_country, params) | local data = askCached('organizations:' .. args.has_country, params) | ||
-- Store the raw count for masonry layout | |||
-- | template._rawDataCounts = template._rawDataCounts or {} | ||
template._rawDataCounts.organizations = #data | |||
-- Only render if we have data | |||
if #data == 0 then | |||
return '' | |||
-- | end | ||
return renderTable(data, {'Organizations'}) | |||
end | end | ||
} | } | ||
| Line 389: | Line 385: | ||
feature = 'people', | feature = 'people', | ||
render = function(template, args) | render = function(template, args) | ||
local params = { | local params = { | ||
string.format('[[Has country::%s]] [[Has entity type::Person]]', | string.format('[[Has country::%s]] [[Has entity type::Person]]', | ||
| Line 396: | Line 391: | ||
} | } | ||
local data = askCached('people:' .. args.has_country, params) | local data = askCached('people:' .. args.has_country, params) | ||
-- Store the raw count for masonry layout | |||
-- | template._rawDataCounts = template._rawDataCounts or {} | ||
template._rawDataCounts.people = #data | |||
-- Only render if we have data | |||
if #data == 0 then | |||
return '' | |||
-- | end | ||
return renderTable(data, {'People'}) | |||
end, | end, | ||
} | } | ||
| Line 417: | Line 406: | ||
feature = 'laws', | feature = 'laws', | ||
render = function(template, args) | render = function(template, args) | ||
local params = { | local params = { | ||
string.format('[[Has country::%s]] | string.format('[[Has country::%s]] [[Has entity type::Norm]]', args.has_country), | ||
limit = 20 | |||
limit = | |||
} | } | ||
local data = askCached('laws:' .. args.has_country, params) | local data = askCached('laws:' .. args.has_country, params) | ||
-- Store the raw count for masonry layout | |||
-- | template._rawDataCounts = template._rawDataCounts or {} | ||
template._rawDataCounts.laws = #data | |||
-- Only render if we have data | |||
-- | if #data == 0 then | ||
return '' | |||
end | |||
return renderTable(data, {'Laws and Regulations'}) | |||
return | |||
end, | end, | ||
} | } | ||
| Line 441: | Line 426: | ||
feature = 'documents', | feature = 'documents', | ||
render = function(template, args) | render = function(template, args) | ||
local params = { | local params = { | ||
string.format('[[Has country::%s]]', args.has_country), | string.format('[[Has country::%s]]', args.has_country), | ||
'[[Category:Document]]', | '[[Category:Document]]', | ||
mainlabel = 'Document', sort = 'Has date', order = 'desc', | mainlabel = 'Document', sort = 'Has date', order = 'desc', | ||
limit = | limit = 20 | ||
} | } | ||
return renderSection('documents:' .. args.has_country, params, {'Key Documents'}) | |||
end, | end, | ||
} | } | ||
| Line 465: | Line 440: | ||
feature = 'geoTlds', | feature = 'geoTlds', | ||
render = function(template, args) | render = function(template, args) | ||
local params = { | local params = { | ||
string.format('[[Has country::%s]] [[Has entity type::TLD]] [[Has TLD subtype::geoTLD]]', args.has_country), | string.format('[[Has country::%s]] [[Has entity type::TLD]] [[Has TLD subtype::geoTLD]]', args.has_country), | ||
limit = | limit = 20 | ||
} | } | ||
local data = askCached('geoTlds:' .. args.has_country, params) | local data = askCached('geoTlds:' .. args.has_country, params) | ||
-- Store the raw count for masonry layout | |||
-- | template._rawDataCounts = template._rawDataCounts or {} | ||
template._rawDataCounts.geoTlds = #data | |||
-- Only render if we have data | |||
-- | if #data == 0 then | ||
return '' | |||
end | |||
return renderTable(data, {'GeoTLDs'}) | |||
return | |||
end, | end, | ||
} | } | ||
| Line 487: | Line 460: | ||
feature = 'meetings', | feature = 'meetings', | ||
render = function(template, args) | render = function(template, args) | ||
local params = { | local params = { | ||
string.format('[[Has country::%s]]', args.has_country), | string.format('[[Has country::%s]]', args.has_country), | ||
'[[Has entity type::Event]]', | '[[Has entity type::Event]]', | ||
limit = | limit = 20 | ||
} | } | ||
local data = askCached('events:' .. args.has_country, params) | local data = askCached('events:' .. args.has_country, params) | ||
-- Store the raw count for masonry layout | |||
if | template._rawDataCounts = template._rawDataCounts or {} | ||
template._rawDataCounts.meetings = #data | |||
-- Only render if we have data | |||
if #data == 0 then | |||
return '' | return '' | ||
end | end | ||
return renderTable(data, {'Internet Governance Events'}) | |||
end, | end, | ||
} | } | ||
| Line 518: | Line 481: | ||
feature = 'nra', | feature = 'nra', | ||
render = function(template, args) | render = function(template, args) | ||
local params = { | local params = { | ||
string.format('[[Has country::%s]] [[Has entity type::Organization]] [[Has organization type::Government agency]]', args.has_country), | string.format('[[Has country::%s]] [[Has entity type::Organization]] [[Has organization type::Government agency]]', args.has_country), | ||
limit = | limit = 20 | ||
} | } | ||
local data = askCached('nra:' .. args.has_country, params) | local data = askCached('nra:' .. args.has_country, params) | ||
-- Store the raw count for masonry layout | |||
template._rawDataCounts = template._rawDataCounts or {} | |||
template._rawDataCounts.nra = #data | |||
-- Only render if we have data | |||
if #data == 0 then | |||
return '' | |||
end | |||
return renderTable(data, {'National Authorities'}) | |||
end, | end, | ||
} | } | ||
-- -- REVIEW: CONNECTED COUNTRIES | -- -- REVIEW: CONNECTED COUNTRIES (COLONIES) | ||
-- ANCHOR: RESOURCES | -- ANCHOR: RESOURCES | ||
| Line 535: | Line 503: | ||
feature = 'resources', | feature = 'resources', | ||
render = function(template, args) | render = function(template, args) | ||
local params = { | local params = { | ||
string.format('[[Has country::%s]]', args.has_country), | string.format('[[Has country::%s]]', args.has_country), | ||
'[[Category:Resource]]', | '[[Category:Resource]]', | ||
mainlabel = 'Resource', | mainlabel = 'Resource', | ||
limit = | limit = 20 | ||
} | } | ||
return renderSection('resources:' .. args.has_country, params, {'Resources'}) | |||
end, | end, | ||
} | |||
-- Data wrapper blocks | |||
template.config.blocks.dataWrapperOpen = { | |||
feature = 'fullPage', | |||
render = function() return '<div class="country-hub-data-container">' end | |||
} | |||
template.config.blocks.dataWrapperClose = { | |||
feature = 'fullPage', | |||
render = function() return '</div>' end | |||
} | } | ||
| Line 552: | Line 527: | ||
feature = 'countryWrapper', | feature = 'countryWrapper', | ||
render = function() return '</div>' end | render = function() return '</div>' end | ||
} | |||
-- INTELLIGENT MASONRY LAYOUT INTEGRATION | |||
-- Single block that handles all masonry logic at render-time (Blueprint pattern) | |||
template.config.blocks.intelligentMasonry = { | |||
feature = 'fullPage', | |||
render = function(template, args) | |||
return MasonryLayout.renderIntelligentLayout(template, args, { | |||
cardDefinitions = cardDefinitions, | |||
options = masonryOptions, | |||
blockRenderers = { | |||
intro = template.config.blocks.intro, | |||
organizations = template.config.blocks.organizations, | |||
people = template.config.blocks.people, | |||
geoTlds = template.config.blocks.geoTlds, | |||
meetings = template.config.blocks.meetings, | |||
nra = template.config.blocks.nra, | |||
laws = template.config.blocks.laws, | |||
documents = template.config.blocks.documents, | |||
resources = template.config.blocks.resources, | |||
infoBox = template.config.blocks.infoBox | |||
} | |||
}) | |||
end | |||
} | } | ||