Module:USASpending-spending-over-time

From Defense Knowledge

Documentation for this module may be created at Module:USASpending-spending-over-time/doc

local p = {}

-- Function to create a tab button dynamically
local function createTabButton(id, label, isActive)
    local activeClass = isActive and 'active' or ''
    local selected = isActive and 'true' or 'false'
    return string.format(
        '<li class="nav-item" role="presentation">' ..
            '<div class="nav-link rounded-0 %s" id="%s-tab" data-bs-toggle="tab" data-bs-target="#%s" type="button" role="tab" aria-controls="%s" aria-selected="%s">%s</div>' ..
        '</li>',
        activeClass, id, id, id, selected, label
    )
end

-- Helper function to generate graph data (comma-separated values)
local function generateSpendingGraph(data, field)
    local values = {}

    for _, entry in ipairs(data) do
        local value

        if field == 'quarter' then
            local year = entry['fiscal_year']
            local period = entry[field]
        
            if year and period then
                value = "'" .. year .. " Q" .. period .. "'"
            end
        else
            value = entry[field]
        end

        -- Insert the value into the list if it exists
        if value then
            table.insert(values, value)
        end
    end

    return table.concat(values, ',')
end

-- Main function to fetch data and generate output
function p.aggregatedByYear(uei, queryUrl)
    -- Define API URLs
    local baseUrl = 'https://api.usaspending.gov'
    local queryUrl = queryUrl or '/api/v2/search/spending_over_time/'
    local apiUrl = baseUrl .. queryUrl

    -- Helper function to fetch data
    local function fetchData(postData)
        return mw.ext.externalData.getWebData {
            url = apiUrl,
            format = 'JSON',
            ['use jsonpath'] = true,
            ['post data'] = postData,
            data = { aggregated_amount = '$..aggregated_amount', quarter = '$..quarter', fiscal_year = '$..fiscal_year' },
            ['cache seconds'] = 86400
        } or {}
    end

    -- Prepare output
    local output = {}
    local frame = mw.getCurrentFrame()

    -- Generate the tab buttons
    table.insert(output, '<ul class="nav nav-tabs m-0 mt-3 pb-0" id="transactionGraphs" role="tablist">')
    table.insert(output, createTabButton('quarter', 'By Quarter', true))
    table.insert(output, createTabButton('year', 'By Year', false))
    table.insert(output, '</ul>')

    table.insert(output, '<div class="tab-content" id="transactionGraphsContent">')

    -- Generate "Quarters" tab content
    local quartersData = fetchData(string.format('{"group":"quarter","filters":{"recipient_search_text":["%s"]}}', uei))
    table.insert(output, '<div class="tab-pane active pt-3" id="quarter" role="tabpanel" aria-labelledby="quarter-tab">')
    table.insert(output, '<div id="quarter-graph" style="width:100%;height:280px;max-width:900px"></div>') -- Graph wrapper
    local x = generateSpendingGraph(quartersData, 'quarter') -- X-axis data
    local y = generateSpendingGraph(quartersData, 'aggregated_amount') -- Y-axis data
    -- Build the graph using the #widget parser function
    local graphQuarter = frame:callParserFunction(
       '#widget', 
       'SpendingOverTimeGraph', 
       'xAxis=' .. x, 
       'yAxis=' .. y, 
       'target=quarter-graph', 
       'name=Obligations' 
    )

    -- Return the graph output
    table.insert(output, '<div>' .. graphQuarter .. '</div>')
    table.insert(output, '</div>')

-- Generate "Years" tab content
    local yearsData = fetchData(string.format('{"group":"fiscal_year","filters":{"recipient_search_text":["%s"]}}', uei))
    table.insert(output, '<div class="tab-pane active pt-3" id="year" role="tabpanel" aria-labelledby="year-tab">')
    table.insert(output, '<div id="year-graph" style="width:100%;height:280px;max-width:900px"></div>') -- Graph wrapper
    local x = generateSpendingGraph(yearsData, 'fiscal_year') -- X-axis data
    local y = generateSpendingGraph(yearsData, 'aggregated_amount') -- Y-axis data

    -- Build the graph using the #widget parser function
    local graphYear = frame:callParserFunction(
       '#widget', 
       'SpendingOverTimeGraph', 
       'xAxis=' .. x, 
       'yAxis=' .. y, 
       'target=year-graph', 
       'name=Obligations'
    )

    -- Return the graph output
    table.insert(output, '<div>' .. graphYear .. '</div>')
    table.insert(output, '</div>')

    table.insert(output, '</div>')

    return table.concat(output, "\n")
end

return p