Module:SongsTable

From Angelina Jordan Wiki
Revision as of 06:47, 28 August 2024 by Most2dot0 (talk | contribs) (start with hidden details)
The code for this module can be found below its documentation. You can edit the code, edit the documentation, or purge the cache.

Work in Progress!!

This module is supposed to provide access to the list of song titles Angelina did. To (most of) the song titles also a selection of videos was attached (now removed). This list is stored in JSON format in the Data:Songs.json page.

The song data has initially be derived from the listing on the Songs page. The intention is, that listing can be instead genereated by this module. But in addition, it should be possible to use the data on other pages.

For example, a page for a song could use it to list the most relevant example renditions of that song.

The idea is not, that all details of the songs data, like the song info box on the songs page, is stored in this list.

In the past, the videos were stored in the Data:SongsToVideos.json JSON data together with the songs listing, which is assumed to be alphabetic. That was not the long term solution, and in the meantime the videos were removed and the page renamed to Data:Songs.json. It's envisioned, that this will later be generated from more generic tables. See User:Most2dot0/Ideas for more ideas on this.

ToDo

  • Add more representations of data, e.g. like on the "Songs" page.
  • Consider to have a seperate reference field ( or a list of references )
  • Either integrate AtoZ bar in table section headers, or a link to jump to it above
  • Add access with filters, e.g.
- for song title
- for orginals
  • Don't rely on videos included, but generate by using a seperate performances table, which links performances to songs, events, locations and videos.
  • Present some sort of "quality" indication

Examples

Complete Table

A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z

Error: Failed to load content for page: Data:SongsToVideos.json

A · B · C · D · E · F · G · H · I · J · K · L · M · N · O · P · Q · R · S · T · U · V · W · X · Y · Z

Code

[Edit module code]


local p = {}

-- Function to load JSON content from a page
function p.loadJsonContent(jsonPage)
    -- Check if jsonPage is a valid string
    if type(jsonPage) ~= 'string' then
        return nil, "Invalid argument: JSON page name must be a string."
    end
    
    -- Try to load the page content
    local title = mw.title.new(jsonPage)
    if not title then
        return nil, "Failed to create title object for page: " .. jsonPage
    end

    local content = title:getContent()
    if not content then
        return nil, "Failed to load content for page: " .. jsonPage
    end

    -- Try to decode the JSON content
    local data = mw.text.jsonDecode(content)
    if type(data) ~= 'table' then
        return nil, "Invalid JSON data in page: " .. jsonPage
    end

    return data, nil
end

local function fetchData()
    local data, err = p.loadJsonContent('Data:SongsToVideos.json')
    if err then
        return nil, err
    end
    return data
end

local function generateCollapsibleTableRow(song, index, count)
    local title = song.title
    local linkTarget = title
    local displayTitle = title
    local wpTarget = title

    if song.wpext then
        wpTarget = title .. " (" .. song.wpext .. ")"
    else 
    	if song.disambiguation then
        	wpTarget = title .. " (" .. song.disambiguation .. ")"
       end
    end

    if song.type == "redirect" and song.actual then
        displayTitle = "    ''" .. title .. "'' → ''' [[#" .. song.actual .. "|" .. song.actual .. "]] '''"
    else
        displayTitle = '<span id="' .. title .. '">' ..count .. ". '''[[" .. linkTarget .. "|" .. title .. "]]'''</span>"

        if song.type == "original" then
            displayTitle = displayTitle .. " ''★ (Angelina original)''"
        else 
	        if song.disambiguation then
    	        displayTitle = displayTitle .. " ''(" .. song.disambiguation .. ")''"
        	end
        end
        displayTitle = displayTitle .. " - {{w|" .. wpTarget .. "|Wikipedia}}"
    end

    local button = ""
    local videosSection = ""
    if song.videos and #song.videos > 0 or song.comment then
        local buttonLabel = ""
        if song.comment then
            buttonLabel = "Comment"
        end
        if song.videos and #song.videos > 0 then
            if buttonLabel ~= "" then
                buttonLabel = buttonLabel .. " + "
            end
            buttonLabel = buttonLabel .. #song.videos .. " Video" .. (#song.videos > 1 and "s" or "")
        end
        button = ' <span class="mw-customtoggle-' .. index .. '" style="cursor:pointer; color:blue;"> [' .. buttonLabel .. ']</span>'
        local comment = song.comment and "''" .. song.comment .. "''<br/>" or ""
        local placeholderDiv = '<div class="youtube-player-placeholder">\n'
        videosSection = '<tr class="mw-collapsible mw-collapsed" id="mw-customcollapsible-' .. index .. '" style="display: none">\n'
        videosSection = videosSection .. '<td colspan="1" style="padding-left: 1em;">' .. comment .. placeholderDiv .. '<ul>\n'
        if song.videos and #song.videos > 0 then
            for _, video in ipairs(song.videos) do
                videosSection = videosSection .. '<li>[' .. video.url .. ' ' .. video.title .. '] (' .. video.user .. ', accessed ' .. video.accessed .. ')</li>\n'
            end
        end
        videosSection = videosSection .. '</ul>\n</div></td></tr>\n'
    end

    local row = "|-\n| style=\"background-color:#f2f2f2;\" | " .. displayTitle .. button .. "\n"
    row = row .. videosSection

    return row
end

function p.renderCollapsibleTable(frame)
    local data, err = fetchData()
    if not data then
        return '<div class="error">Error: ' .. err .. '</div>'
    end

    local wikitable = '{| class="wikitable" style="width: 100%" \n|-\n! Song Title\n'

    local count = 0
    local currentLetter = ""
    local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    local alphabetIndex = 1
    local lastRelevantLetter = ""

    for index, song in ipairs(data) do
        local firstLetter = mw.ustring.upper(mw.ustring.gsub(mw.ustring.sub(song.title, 1, 1), "%W", ""))
        local relevantLetter = mw.ustring.match(song.title, "%w") or ""
        relevantLetter = mw.ustring.upper(relevantLetter)

        -- Skip titles starting with a digit
        if not mw.ustring.match(firstLetter, "%d") then
            while alphabetIndex <= #alphabet and alphabet:sub(alphabetIndex, alphabetIndex) < firstLetter do
                wikitable = wikitable .. '|-\n| colspan="1" style="text-align:center;" | {{a|' .. alphabet:sub(alphabetIndex, alphabetIndex) .. '|}}\n'
                alphabetIndex = alphabetIndex + 1
            end

            if relevantLetter ~= lastRelevantLetter and mw.ustring.match(relevantLetter, "%a") then
                currentLetter = relevantLetter
                wikitable = wikitable .. '|-\n| colspan="1" style="text-align:center;" | {{a|' .. currentLetter .. '}}\n'
                lastRelevantLetter = relevantLetter
                alphabetIndex = alphabetIndex + 1
            end
        end

        if song.type ~= "redirect" then
            count = count + 1
        end
        
        wikitable = wikitable .. generateCollapsibleTableRow(song, index, count)
    end
    
    while alphabetIndex <= #alphabet do
        wikitable = wikitable .. '|-\n| colspan="1" style="text-align:center;" | {{a|' .. alphabet:sub(alphabetIndex, alphabetIndex) .. '|}}\n'
        alphabetIndex = alphabetIndex + 1
    end

    wikitable = wikitable .. "|}"

    return frame:preprocess(wikitable)
end

return p