Module:ResourceList: Difference between revisions
From PC Gaming Shelter
No edit summary |
No edit summary |
||
| (26 intermediate revisions by the same user not shown) | |||
| Line 4: | Line 4: | ||
{ | { | ||
key = "resources", | key = "resources", | ||
title = " | title = "Type", | ||
property = "Has resource type", | property = "Has resource type", | ||
}, | }, | ||
{ | { | ||
key = "types", | key = "types", | ||
title = " | title = "Content", | ||
property = "Has content type", | property = "Has content type", | ||
}, | }, | ||
{ | { | ||
key = "langs", | key = "langs", | ||
title = " | title = "Language", | ||
property = "Has language", | property = "Has language", | ||
}, | }, | ||
{ | { | ||
key = "years", | key = "years", | ||
title = " | title = "Year", | ||
property = "Has date", | property = "Has date", | ||
}, | }, | ||
| Line 121: | Line 121: | ||
local function renderList(frame, field, bucket, game, showCounts) | local function renderList(frame, field, bucket, game, showCounts) | ||
local | local html = mw.html.create() | ||
local resItem = html:tag('div'):addClass('card bg-transparent flex-md-row mb-2') | |||
} | |||
resItem:tag('div'):addClass('resources-header'):wikitext(field.title) | |||
local cardBody = resItem:tag('div'):addClass('d-flex flex-wrap px-3 text-muted'):css({ | |||
['gap'] = '0 .5rem' | |||
}) | |||
local keys = sortedKeys(bucket) | local keys = sortedKeys(bucket) | ||
if #keys == 0 then | if #keys == 0 then | ||
cardBody:tag('div'):wikitext("None found.") | |||
return | return html | ||
end | end | ||
| Line 137: | Line 141: | ||
if showCounts then | if showCounts then | ||
cardBody:tag('div'):wikitext(link .. " (" .. bucket.counts[key] .. ")") | |||
else | else | ||
cardBody:tag('div'):wikitext(link) | |||
end | end | ||
end | end | ||
return | return html | ||
end | end | ||
local function askRows(args) | local function askRows(args) | ||
local game = args.game | local game = args.game | ||
if not game then | |||
return | |||
end | |||
local limit = args.limit or "5000" | local limit = args.limit or "5000" | ||
| Line 163: | Line 171: | ||
function p.render(frame) | function p.render(frame) | ||
local args = | local args = frame.args or {} | ||
local game = args.game | local game = args.game | ||
local showCounts = args.counts ~= "no" | local showCounts = args.counts ~= "no" | ||
local rows = askRows(args) | local rows = askRows(args) | ||
local buckets = collect(rows) | local buckets = collect(rows) | ||
local header = args.header or 'External Resources' | |||
local | local html = mw.html.create() | ||
local res = html:tag('div'):attr('id', 'more-resources') | |||
res:tag('h2'):wikitext(header) | |||
for _, field in ipairs(FIELDS) do | for _, field in ipairs(FIELDS) do | ||
res:node(renderList(frame, field, buckets[field.key], game, showCounts)) | |||
end | end | ||
return | return html | ||
end | end | ||
| Line 192: | Line 202: | ||
local filter = args['Has filter'] | local filter = args['Has filter'] | ||
local query = frame:callParserFunction( | local query = frame:callParserFunction("#ask", { | ||
"[[Resource:+]][[Related game::" .. game .. "]][[" .. filter .. "::~" .. item .. "]]", | |||
"format=embedded", | |||
"embedformat=h5", | |||
"limit=5000", | |||
}) | }) | ||
Latest revision as of 14:07, 12 July 2026
Documentation for this module may be created at Module:ResourceList/doc
local p = {}
local FIELDS = {
{
key = "resources",
title = "Type",
property = "Has resource type",
},
{
key = "types",
title = "Content",
property = "Has content type",
},
{
key = "langs",
title = "Language",
property = "Has language",
},
{
key = "years",
title = "Year",
property = "Has date",
},
}
local function trim(value)
return mw.text.trim(tostring(value or ""))
end
local function valueText(value)
if type(value) ~= "table" then
return trim(value)
end
return trim(
value.fulltext
or value.fullText
or value.label
or value.text
or value.displaytitle
or value[1]
or ""
)
end
local function addValue(bucket, rawValue)
local value = valueText(rawValue)
if value == "" then
return
end
local key = mw.ustring.lower(value)
if bucket.counts[key] == nil then
bucket.counts[key] = 0
bucket.labels[key] = value
end
bucket.counts[key] = bucket.counts[key] + 1
end
local function collect(rows)
local buckets = {}
for _, field in ipairs(FIELDS) do
buckets[field.key] = {
counts = {},
labels = {},
}
end
for _, row in ipairs(rows) do
for _, field in ipairs(FIELDS) do
local values = row[field.key]
local bucket = buckets[field.key]
if type(values) == "table" then
for _, value in ipairs(values) do
addValue(bucket, value)
end
else
addValue(bucket, values)
end
end
end
return buckets
end
local function sortedKeys(bucket)
local keys = {}
for key in pairs(bucket.counts) do
table.insert(keys, key)
end
table.sort(keys, function(a, b)
return mw.ustring.lower(bucket.labels[a]) < mw.ustring.lower(bucket.labels[b])
end)
return keys
end
local function queryFormLink(frame, game, propertyName, item)
return frame:preprocess(string.format(
"{{#queryformlink: form=Resource filter" ..
"|link text=%s" ..
"|Resource filter[Related game]=%s" ..
"|Resource filter[%s]=%s" ..
"|Resource filter[Has filter]=%s" ..
"|_run=1" ..
"}}",
item,
game,
propertyName,
item,
propertyName
))
end
local function renderList(frame, field, bucket, game, showCounts)
local html = mw.html.create()
local resItem = html:tag('div'):addClass('card bg-transparent flex-md-row mb-2')
resItem:tag('div'):addClass('resources-header'):wikitext(field.title)
local cardBody = resItem:tag('div'):addClass('d-flex flex-wrap px-3 text-muted'):css({
['gap'] = '0 .5rem'
})
local keys = sortedKeys(bucket)
if #keys == 0 then
cardBody:tag('div'):wikitext("None found.")
return html
end
for _, key in ipairs(keys) do
local label = bucket.labels[key]
local link = queryFormLink(frame, game, field.property, label)
if showCounts then
cardBody:tag('div'):wikitext(link .. " (" .. bucket.counts[key] .. ")")
else
cardBody:tag('div'):wikitext(link)
end
end
return html
end
local function askRows(args)
local game = args.game
if not game then
return
end
local limit = args.limit or "5000"
return mw.smw.ask({
"[[Resource:+]]",
"[[Related game::" .. game .. "]]",
"?Has resource type=resources",
"?Has content type=types",
"?Has language=langs",
"?Has date#-F[Y]=years",
"limit=" .. limit,
"mainlabel=-",
}) or {}
end
function p.render(frame)
local args = frame.args or {}
local game = args.game
local showCounts = args.counts ~= "no"
local rows = askRows(args)
local buckets = collect(rows)
local header = args.header or 'External Resources'
local html = mw.html.create()
local res = html:tag('div'):attr('id', 'more-resources')
res:tag('h2'):wikitext(header)
for _, field in ipairs(FIELDS) do
res:node(renderList(frame, field, buckets[field.key], game, showCounts))
end
return html
end
function p.filtered(frame)
local item = frame.args['item']
local parent = frame:getParent()
local args = setmetatable(frame.args, {
__index = parent and parent.args or {},
})
local game = args['Related game']
local filter = args['Has filter']
local query = frame:callParserFunction("#ask", {
"[[Resource:+]][[Related game::" .. game .. "]][[" .. filter .. "::~" .. item .. "]]",
"format=embedded",
"embedformat=h5",
"limit=5000",
})
return query
end
p.main = p.render
return p
