Module:Organization

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

local p = {}

-- Helper function to check if a value exists in the tabs_table
local function tabExists(tabName, tabTable)
	for _, tab in ipairs(tabTable) do
		if tab:gsub("^%s*(.-)%s*$", "%1") == tabName then
			return true
		end
	end
    return false
end

-- Helper function to split a string by a delimiter
local function splitString(input, delimiter)
    local result = {}
    for value in string.gmatch(input, "([^" .. delimiter .. "]+)") do
        table.insert(result, value)
    end
    return result
end

-- Helper function to trim whitespace
local function trimString(s)
    return (s:gsub("^%s*(.-)%s*$", "%1"))
end

-- Helper message extractor
local function getMessage(msg)
    return mw.message.new(msg):plain()
end

function p.main(frame)

local page = tostring(mw.title.getCurrentTitle())
local args = frame.args
local template = frame:getParent().args

local display_title = template['Display title'] or ''
local sort_as = template['Sort as'] or display_title or page
local cover_image_caption = template['Cover image caption'] or ''
local orgtabs = template['Tabs'] or ''
local tabs_table = splitString(orgtabs, ",")

local has_photo = template['Photo'] or 'Johndoe.png'
local filename = frame:preprocess('{{PAGENAME:' .. has_photo .. '}}')
local photo = string.format('File:%s', filename )

local homepage = template['Homepage'] or ''
local category = '[[Category:Organizations]]'
	
-- Remove title
local notitle = args.notitle or ''
if notitle ~= '' then
    local widget_notitle = frame:callParserFunction( '#widget', 'notitle' )
end

-- Get Areas
local areas_add = template['Areas'] or ''
local areas_pre = mw.smw.ask( '[[Category:Articles]][[Modification date::+]][[Area::+]][[Source::' .. page .. ']]|mainlabel=-|?Area|limit=500|searchlabel=|valuesep=;' )

-- Function to join and deduplicate areas
local function joinAndMakeUnique(existing, inputTable)
    local seen = {}
    local all_areas = {}

    -- Start with the existing areas string
    if existing ~= "" then
        for _, area in ipairs(splitString(existing, ";")) do
            area = trimString(area)
            if area ~= "" and not seen[area] then
                seen[area] = true
                table.insert(all_areas, area)
            end
        end
    end

    -- Add areas from the input table
    if inputTable ~= nil then
    for _, v in ipairs(inputTable) do
        if v.Area then
            local area = trimString(v.Area)
            if area ~= "" and not seen[area] then
                seen[area] = true
                table.insert(all_areas, area)
            end
        end
    end
    end

    -- Return the unique, concatenated string
    return table.concat(all_areas, ";")
end

-- Combine areas_add and areas_pre, making the result unique
areas_add = joinAndMakeUnique(areas_add, areas_pre)

-- Set properties
local page_properties = frame:callParserFunction(
	'#set',
	'Area=' .. areas_add,
	'+sep=;',
	'Cover image caption=' .. cover_image_caption,
	'Has photo=' ..	photo,
	'Homepage=' .. homepage
)
    
if display_title ~= '' then
	frame:preprocess('{{DISPLAYTITLE:' .. display_title .. '|noerror}}')
end

if sort_as ~= '' then
	frame:preprocess('{{DEFAULTSORT:' .. sort_as .. '}}')
end

-- Assemble

local output = {}
local html = mw.html.create()

local properties = html:tag('div')
	:addClass('d-none')
	:wikitext(page_properties)

-- MAIN CONTENT
local maincontent = html:tag('div')
	:addClass('card w-100 border-0 mb-3')
	
local mainbody = maincontent:tag('div')
	:addClass('card-body px-0')
	:css('flex', '0 0 auto')

local organization_bio = mainbody:tag('div')
	:addClass('author-biography mb-3')
	:wikitext(cover_image_caption)

-- TABS
if #orgtabs > 0 then

	local orgtabs_list = mainbody:tag('ul')
		:attr('id', 'author-tabs')
		:addClass('nav nav-tabs pl-0')
		
    -- Add tabs dynamically
    if tabExists("Articles", tabs_table) then
        orgtabs_list:tag('li')
            :addClass('nav-item')
            :wikitext(frame:callParserFunction('#widget',
            	'a',
            	'id=observatory-articles-show',
            	'class=nav-link interface active',
    			'toggle=tab',
    			'href=#observatory-articles',
    			'linktext=Observatory Articles'
              ))
    end

    if tabExists("Full Bio", tabs_table) then
        orgtabs_list:tag('li')
            :addClass('nav-item')
            :wikitext(frame:callParserFunction('#widget',
            	'a',
            	'id=fullbio-show',
            	'class=nav-link interface',
    			'toggle=tab',
    			'href=#fullbio',
    			'linktext=Full Bio'
              ))
    end

    if tabExists("Authors", tabs_table) then
        orgtabs_list:tag('li')
            :addClass('nav-item')
            :wikitext(frame:callParserFunction('#widget',
            	'a',
            	'id=authors-show',
            	'class=nav-link interface',
    			'toggle=tab',
    			'href=#authors',
    			'linktext=Authors'
              ))
    end

    -- Check if there are guides related to the current page
    local guides = mw.smw.ask('[[Category:Guides]][[Source::' .. page .. ']]')
    if guides and #guides > 0 then
        orgtabs_list:tag('li')
            :addClass('nav-item')
            :wikitext(frame:callParserFunction('#widget',
            	'a',
            	'id=paths-show',
            	'class=nav-link interface',
    			'toggle=tab',
    			'href=#paths',
    			'linktext=Guides'
              ))
    end

    if tabExists("Commentary", tabs_table) then
        orgtabs_list:tag('li')
            :addClass('nav-item')
            :wikitext(frame:callParserFunction('#widget',
            	'a',
            	'id=commentary-show',
            	'class=nav-link interface',
    			'toggle=tab',
    			'href=#commentary',
    			'linktext=Commentary'
              ))
    end

    if tabExists("Books and Research", tabs_table) then
        orgtabs_list:tag('li')
            :addClass('nav-item')
            :wikitext(frame:callParserFunction('#widget',
            	'a',
            	'id=books-research-show',
            	'class=nav-link interface',
    			'toggle=tab',
    			'href=#books-research',
    			'linktext=Books & Research'
              ))
    end

    if tabExists("Multimedia", tabs_table) then
        orgtabs_list:tag('li')
            :addClass('nav-item')
            :wikitext(frame:callParserFunction('#widget',
            	'a',
            	'id=multimedia-show',
            	'class=nav-link interface',
    			'toggle=tab',
    			'href=#multimedia',
    			'linktext=Multimedia'
              ))
    end

    if tabExists("Events", tabs_table) then
        orgtabs_list:tag('li')
            :addClass('nav-item')
            :wikitext(frame:callParserFunction('#widget',
            	'a',
            	'id=events-show',
            	'class=nav-link interface',
    			'toggle=tab',
    			'href=#events',
    			'linktext=Events'
              ))
    end
    
end

-- TAB PANES
local tab_panes = mainbody:tag('div')
	:attr('id', 'author-tab-content')
	:addClass('tab-content')

if tabExists("Articles", tabs_table) then

	local tab_pane = tab_panes:tag('div')
		:addClass('tab-pane container active')
		:attr('id', 'observatory-articles')

	local tab_heading = tab_pane:tag('div')
		:addClass('h3 my-4')
		:wikitext('Latest from this source')
		
	local smw_query = frame:callParserFunction('#ask', {
		'[[Category:Articles]][[Source::' .. page .. '||Secondary source::' .. page .. ']] OR ' ..
		'[[Category:Work in progress]][[Secondary source::' .. page .. '||Source::' .. page .. ']]',
		'format=plainlist',
		'template=Article item',
		'sort=Date published',
		'order=desc', 
		'mainlabel=Article',
		'?Subtitle',
		'?Source',
		'?Credit line',
		'?Teaser',
		'?Modification date',
		'?Display date', 
		'?Area',
		'?Is featured',
		'?Is collaborative research',
		'?Has map label',
		'?Text author=Author',
		'named args=yes',
		'headers=hide',
		'link=none',
		'limit=200',
		'valuesep=;'
		}
	)
	
	local tab_result = tab_pane:tag('div')
		:wikitext(smw_query)

end

if tabExists("Full Bio", tabs_table) then
	
	local about = template['About']
	
	local tab_pane = tab_panes:tag('div')
		:addClass('tab-pane container py-4')
		:attr('id', 'fullbio')
        :newline()
		:wikitext(about)	
end

if tabExists("Authors", tabs_table) then

	local tab_pane = tab_panes:tag('div')
		:addClass('tab-pane container')
		:attr('id', 'authors')
		
	local tab_heading = tab_pane:tag('div')
		:addClass('h3 my-4')
		:wikitext('Associated Authors')

	local smw_query = frame:callParserFunction('#ask', {
		'[[Category:Authors]][[Source::' .. page .. ']]',
		'format=plainlist',
		'template=Source author box',
		'named args=yes',
		'mainlabel=page',
		'?Has photo=image',
		'?Biography=info',
		'order=random',
		'limit=100',
		'searchlabel=',
		'link=none'
		}
	)
	
	local tab_result = tab_pane:tag('div')
		:wikitext(smw_query)
end

-- GUIDES
	local tab_pane = tab_panes:tag('div')
		:addClass('tab-pane container py-4')
		:attr('id', 'paths')
		
	local smw_query = frame:callParserFunction('#ask', {
		'[[Category:Guides]][[Source::' .. page .. ']]',
		'mainlabel=Path',
		'named args=yes',
		'link=none',
		'format=plainlist',
		'template=Path record'
	})

	tab_heading = tab_pane:tag('div')
		:addClass('h3 mb-4')
		:wikitext('The Observatory Guides')

	local tab_result = tab_pane:tag('div')
		:wikitext(smw_query)


-- COMMENTARY
if tabExists("Commentary", tabs_table) then

	local commentary = template['Commentary']
	
	local tab_pane = tab_panes:tag('div')
		:addClass('tab-pane container pt-4')
		:attr('id', 'commentary')
		:wikitext(commentary)
end

if tabExists("Books and Research", tabs_table) then

	local tab_pane = tab_panes:tag('div')
		:addClass('tab-pane container')
		:attr('id', 'books-research')
		
	local tab_heading = tab_pane:tag('div')
		:addClass('h3 my-4')
		:wikitext('Publications by this organization')
		
	local books = template['Books and Research']	

end

if tabExists("Multimedia", tabs_table) then

	local tab_pane = tab_panes:tag('div')
		:addClass('tab-pane container')
		:attr('id', 'multimedia')
		
	local tab_heading = tab_pane:tag('div')
		:addClass('h3 my-4')
		:wikitext('Videos by this organization')
		
	local multimedia = template['Multimedia']	
	local tab_content = tab_pane:tag('div')
        :wikitext('\n' .. multimedia)

end

if tabExists("Events", tabs_table) then

	local tab_pane = tab_panes:tag('div')
		:addClass('tab-pane container')
		:attr('id', 'events')
		
	local tab_heading = tab_pane:tag('div')
		:addClass('h3 my-4')
		:wikitext('Events with this organization')
	
	local events = template['Events']
	local tab_content = tab_pane:tag('div')
        :wikitext('\n' .. events)
        
	local display_calendar = template['Display calendar'] or ''
	local calendar_id = template['Calendar ID'] or ''
	
	if display_calendar == 'Yes' then
		if calendar_id ~= '' then
			frame:callParserFunction('#widget',
				'id=' .. calendar_id,
				'style=border: 0 !important;'
			)
		end
	end
end

-- Initialize the sideblock
local sideblock = html:tag('div')
    :attr('id', 'article-sources')
    :css('flex', '0 0 280px')
    :wikitext('[[' .. photo .. '|class=w-100 h-auto object-fit-contain|300px|link=' .. homepage .. ']]')

-- Create the area tabs container
local area_tabs = sideblock:tag('div')
    :addClass('author-research-areas mt-3 d-none d-md-block')

-- Add tabs if `area_add` is defined
if areas_add and areas_add ~= "" then
    local tabs = area_tabs:tag('ul')
        :addClass('nav nav-tabs mt-3')
        :attr('id', 'coverage-tabs')
        
    local tab = tabs:tag('li')
    	:addClass('nav-item')
    	:attr('role', 'presentation')
    	
    local tab_label = tab:tag('div')
    	:addClass('nav-link interface border-0 w-100')
    	:wikitext('Coverage')
	
	-- Check and process areas_add
	if areas_add and areas_add ~= "" then
		
		local tiles = area_tabs:tag('div')
			:addClass('observatory-tile-deck')

    	local areas_table = splitString(areas_add, ";")
    	for _, area in ipairs(areas_table) do
        	local item = tiles:tag('div')
            	:addClass('tile d-flex align-items-center gap-3')
            	
            local item_label = item:tag('div')
            	:addClass('tile-caption w-100')
            	:wikitext('[[' .. area .. ']]')
    	end
	end
end

local organization = tostring(maincontent) .. category .. tostring(sideblock)

return organization 

end

return p