Module:T-Person: Difference between revisions

// via Wikitext Extension for VSCode
 
// via Wikitext Extension for VSCode
Line 1: Line 1:
-- Module:T-Person
-- Module:T-Person
-- Blueprint migration of Person template (Phase 1)
-- Makes use of ICANNWiki's "Template Blueprint Framework" to render the "Person" template


local p = {}
local p = {}


-- ==================== Required modules ====================
-- ==================== Required modules ====================
local Blueprint       = require('Module:LuaTemplateBlueprint')
local Blueprint = require('Module:LuaTemplateBlueprint')
local TemplateHelpers = require('Module:TemplateHelpers')
local TemplateHelpers = require('Module:TemplateHelpers')
local ErrorHandling   = require('Module:ErrorHandling')
local ErrorHandling = require('Module:ErrorHandling')
local ConfigRepository = require('Module:ConfigRepository')
local ConfigRepository = require('Module:ConfigRepository')
local LinkParser       = require('Module:LinkParser')
local LinkParser = require('Module:LinkParser')
local Achievements = require('Module:AchievementSystem')


-- Blueprint default: Module-level cache for lazy-loaded modules
-- Blueprint default: Module-level cache for lazy-loaded modules
Line 25: Line 26:


-- Blueprint default: Modules to lazy load
-- Blueprint default: Modules to lazy load
local CanonicalForms            = lazyRequire('Module:CanonicalForms')
     -- local getTemplateHelpers = lazyRequire('')
local CountryData              = lazyRequire('Module:CountryData')
local SemanticCategoryHelpers  = lazyRequire('Module:SemanticCategoryHelpers')
local LanguageNormalization     = lazyRequire('Module:NormalizationLanguage')
local socialFooter              = lazyRequire('Module:SocialMedia')
local Achievements              = lazyRequire('Module:AchievementSystem')


-- ==================== Helper Functions ====================
-- ==================== Helper Functions ====================
local errorContext = ErrorHandling.createContext('T-Person')
-- Blueprint default: Create error context for the module
local errorContext = ErrorHandling.createContext("T-Person")


-- Blueprint default: Helper for extracting semantic values from wiki links
local function extractSemanticValue(fieldValue, fieldName)
local function extractSemanticValue(fieldValue, fieldName)
     return TemplateHelpers.extractSemanticValue(fieldValue, fieldName, errorContext)
     return TemplateHelpers.extractSemanticValue(fieldValue, fieldName, errorContext)
Line 42: Line 40:


-- IMPORTANT! TEMPLATE BLUEPRINT FRAMEWORK INSTRUCTIONS
-- IMPORTANT! TEMPLATE BLUEPRINT FRAMEWORK INSTRUCTIONS
local template = Blueprint.registerTemplate('Person', {
-- CONTROL OF TEMPLATE FEATURES: THIS LIST SPECIFIES IN AN EXPLICIT MANNER WHAT FEATURES ARE TO BE CALLED/RENDERED BY THE TEMPLATE.
local template = Blueprint.registerTemplate('Person2', {
     features = {
     features = {
         title             = true,
         title = true,
         logo               = false,
         logo = true,
         fields             = true,
         fields = true,
         socialMedia       = true,
         socialMedia = true,
         semanticProperties = true,
         semanticProperties = true,
         categories         = true,
         categories = true,
         errorReporting     = true,
         errorReporting = true,
     }
     }
})
})
Line 57: Line 56:
Blueprint.initializeConfig(template)
Blueprint.initializeConfig(template)


-- CONTROL THE VISUAL ORDER OF BLOCKS
-- CONTROL THE VISUAL ORDER THAT EACH ASPECT IS RENDERED IN
template.config.blockSequence = {
template.config.blockSequence = {
     'title',
     'title',
     'achievementHeader',
     'logo',
    'portraitCarousel',
     'fields',
     'fields',
     'achievementBadges',
     'socialMedia',
     'socialMedia'
    'semanticProperties',
    'categories',
     'errors'
}
}


-- ================================================================================
-- ================================================================================


-- Block: Title
-- TEMPLATE-SPECIFIC CALLS AND CODE
local function renderTitleBlock(args, frame)
    local pageId = mw.title.getCurrentTitle().id
    local cls, name = Achievements().getTitleClass(pageId, frame)
    local aid = ''
    if cls and cls ~= '' then
        aid = cls:gsub('^achievement%-', '')
    end
    return TemplateHelpers.renderTitleBlock(
        args,
        'template-title template-title-person person-template',
        'Person',
        {
            achievementSupport = true,
            achievementClass  = cls or '',
            achievementId      = aid,
            achievementName    = name or ''
        }
    )
end


-- Block: Achievement header
-- ELEMENTS GO HERE
local function renderAchievementHeaderBlock(args, frame)
-- Safely load element modules with ErrorHandling.safeRequire, then register them via Blueprint.addElementToTemplate(template, 'example')
    local pageId = mw.title.getCurrentTitle().id
    local css, display, aid = Achievements().getTitleAchievement(pageId, frame)
    if css ~= '' and display ~= '' and aid ~= '' then
        return string.format(
            '|-\n! colspan="2" class="achievement-header %s" data-achievement-id="%s" data-achievement-name="%s" | %s',
            aid, aid, display, display
        )
    end
    return ''
end


-- Block: Portrait carousel
-- if template.features.navigation then
local function renderPortraitCarousel(args)
--     local ElementExample = ErrorHandling.safeRequire(errorContext, 'Module:ElementNavigation', false)
    if not args.portrait or args.portrait == '' then
--    if ElementExample and ElementExample.elementName then
        return ''
--         Blueprint.registerElement(ElementExample.elementName, ElementExample)
    end
--        Blueprint.addElementToTemplate(template, 'example')
     local images = SemanticCategoryHelpers().splitMultiValueString(
--     end
        args.portrait,
-- end
        SemanticCategoryHelpers().SEMICOLON_PATTERN
    )
    if #images == 0 then
        return ''
    elseif #images == 1 then
        return string.format(
            '|-\n| colspan="2" class="person-portrait" | [[Image:%s|220px|center]]',
            images[1]
        )
    end
    local out = '|-\n| colspan="2" class="person-portrait-carousel" |'
     out = out .. '<div class="carousel-container">'
    out = out .. '<div class="carousel-nav carousel-prev">&#9664;</div>'
    out = out .. '<div class="carousel-images">'
    for i, img in ipairs(images) do
        local vis  = (i == 1) and 'carousel-visible' or 'carousel-hidden'
        local pos  = ''
        if #images == 2 then
            pos = (i == 1) and 'carousel-orbital-1' or 'carousel-orbital-2'
        else
            if i == 2 then pos = 'carousel-right' end
            if i == #images then pos = 'carousel-left' end
         end
        out = out .. string.format(
            '<div class="carousel-item %s %s" data-index="%d">[[Image:%s|220px|center]]</div>',
            vis, pos, i, img
        )
     end
    out = out .. '</div>'
    out = out .. '<div class="carousel-nav carousel-next">&#9654;</div>'
    out = out .. '</div>'
    return out
end


-- Block: Fields
-- SPECIAL SEMANTIC MAPPINGS GO HERE
local function renderFieldsBlock(args, frame)
    local processors = {
        community = function(val)
            return select(1, CanonicalForms().normalize(val, template.config.mappings.community)) or val
        end,
        languages = function(val)
            return LanguageNormalization().formatLanguages(val)
        end,
        country  = TemplateHelpers.normalizeCountries,
        website  = TemplateHelpers.normalizeWebsites,
        soi      = function(val)
            local formatted = string.format('[%s Here]', val)
            return {
                isCompleteHtml = true,
                html          = string.format(TemplateHelpers.FIELD_FORMAT, 'SOI', formatted)
            }
        end,
        userbox  = function(val)
            local pid = mw.title.getCurrentTitle().id
            local ok, box = pcall(function()
                return Achievements().renderAchievementBox(pid, frame)
            end)
            if ok and box and box ~= '' then
                return box
            end
            return val
        end
    }
    return TemplateHelpers.renderFieldsBlock(args, template.config.fields, processors)
end


-- Block: Achievement badges
-- ================================================================================
local function renderAchievementBadgesBlock(args, frame)
    local pid = mw.title.getCurrentTitle().id
    local ok, achmod = pcall(Achievements)
    local parts = { '|-\n| colspan="2" |' }
    if not ok then
        table.insert(parts, '<div class="achievement-badges"></div>')
        return table.concat(parts)
    end
    local types = achmod.loadTypes(frame)
    local defs  = {}
    for _, t in ipairs(types) do defs[t.id] = t end
    local badges = {}
    for _, a in ipairs(achmod.getUserAchievements(pid)) do
        local td = defs[a.type]
        if td and td.type == 'badge' then
            table.insert(badges, { id = a.type, name = td.name or a.type })
        end
    end
    if #badges > 0 then
        table.insert(parts, '<div class="achievement-badges">')
        for _, b in ipairs(badges) do
            table.insert(parts, string.format(
                '<div class="achievement-badge %s" data-achievement-id="%s" data-achievement-name="%s" title="%s"></div>',
                b.id, b.id, b.name, b.name
            ))
        end
        table.insert(parts, '</div>')
    else
        table.insert(parts, '<div class="achievement-badges"></div>')
    end
    return table.concat(parts)
end
 
-- Register blocks with Blueprint
Blueprint.addBlock(template, 'title', renderTitleBlock)
Blueprint.addBlock(template, 'achievementHeader', renderAchievementHeaderBlock)
Blueprint.addBlock(template, 'portraitCarousel', renderPortraitCarousel)
Blueprint.addBlock(template, 'fields', renderFieldsBlock)
Blueprint.addBlock(template, 'achievementBadges', renderAchievementBadgesBlock)
Blueprint.addBlock(template, 'socialMedia', socialFooter().render)


-- ==================== Preprocessors ====================
-- ==================== Preprocessors ====================
Blueprint.addPreprocessor(template, 'setPageIdField')
-- Basic preprocessors
Blueprint.addPreprocessor(template, 'setPageIdField')  -- Blueprint default
Blueprint.addPreprocessor(template, 'deriveRegionFromCountry')


-- ==================== Main Render Function ====================
-- ==================== Main Render Function ====================
-- Blueprint default: Render
function p.render(frame)
function p.render(frame)
     return ErrorHandling.protect(
     return ErrorHandling.protect(
         errorContext,
         errorContext,
         'render',
         "render",
         function()
         function()
             return template.render(frame)
             return template.render(frame)
         end,
         end,
         ErrorHandling.getMessage('TEMPLATE_RENDER_ERROR'),
         ErrorHandling.getMessage("TEMPLATE_RENDER_ERROR"),
         frame
         frame
     )
     )