Module:RenderData

From Nano World Order - Wiki
Jump to navigation Jump to search

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

-- The RenderData module.
-- Params: 
--  +name = the name of the json without the namespace and extension. Create as a wikipage in the Data namespace: "Data:${name}.json", 
--  +template = Name of the mediawiki template without the namespace so "Template:${template}". 
--  +sort
--  +filters - any number of filters pairs separated by pipe. prefix with underscore. e.g: "name=john*,type=customer"
local p = {}

-- Function to load JSON data from a given page name
local function loadJSONData(pageName)
    local title = mw.title.new("Data:" .. pageName .. ".json")
    if not title or not title.exists then
        return nil, "Data page not found: Data:" .. pageName .. ".json"
    end

    local content = title:getContent()
    local success, dataOrError = pcall(mw.text.jsonDecode, content)
    if not success then
        return nil, "Failed to parse JSON data on page: Data:" .. pageName .. ".json. Error: " .. tostring(dataOrError)
    end

    return dataOrError, nil
end

-- Function to filter data based on key-value pairs
local function filterData(data, filters)
    if not filters or next(filters) == nil then
        return data -- Return all data if no filters are provided
    end

    local filtered = {}
    for _, item in ipairs(data) do
        local match = true
        for key, value in pairs(filters) do
            local itemValue = tostring(item[key] or "")
            local pattern = value:gsub("%*", ".*") -- Convert '*' to a Lua regex pattern
            if not mw.ustring.match(itemValue, "^" .. pattern .. "$") then
                match = false
                break
            end
        end
        if match then
            table.insert(filtered, item)
        end
    end
    return filtered
end

-- Function to sort data
local function sortData(data, sortKey)
    if not sortKey or sortKey == "" then
        return data -- Return data as-is if no sort key is provided
    end

    table.sort(data, function(a, b)
        return (a[sortKey] or "") < (b[sortKey] or "")
    end)
    return data
end

function parseFilterString(filterString)
    local filters = {}
    for key, value in string.gmatch(filterString, "([^,=]+)=([^,=]+)") do
        filters[key] = value
    end
    return filters
end

-- Main render function
function p.render(frame)
    local args = frame.args
    local parentArgs = frame:getParent().args
    local dataPageName = args.name
    local templateName = args.template
    local sortKey = args.sort

    if not dataPageName or dataPageName == "" then
        return "Error: 'name' parameter is required to specify the data source."
    end

    -- Load JSON data
    local data, err = loadJSONData(dataPageName)
    if not data then
        return err
    end

    -- Parse filter parameters (in keyval pairs format "n1=v1,n2=v2")
    local filters = parseFilterString(args.filter)

    mw.log("name:" .. args.name)
    mw.log("templateName:" .. args.template)
    mw.log("filter:" .. args.filter)


    -- Filter and sort data
    local filteredData = filterData(data, filters)
    local sortedData = sortData(filteredData, sortKey)

    -- Render each item using the specified template
    local result = ""
    for _, item in ipairs(sortedData) do
        result = result .. frame:expandTemplate{ title = templateName, args = item } .. "\n"
    end

    return result
end

return p