diff --git a/lua/wikis/ageofempires/Infobox/Person/Player/Custom.lua b/lua/wikis/ageofempires/Infobox/Person/Player/Custom.lua index 98003bbbb6b..52c003fb12b 100644 --- a/lua/wikis/ageofempires/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/ageofempires/Infobox/Person/Player/Custom.lua @@ -182,7 +182,7 @@ function CustomInjector:parse(id, widgets) return widgets end ----@return Html? +---@return Renderable? function CustomPlayer:createBottomContent() return MatchTicker.recent{player = self.pagename} end diff --git a/lua/wikis/brawlstars/Infobox/Person/Player/Custom.lua b/lua/wikis/brawlstars/Infobox/Person/Player/Custom.lua index 867d066ee13..94c3a70119b 100644 --- a/lua/wikis/brawlstars/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/brawlstars/Infobox/Person/Player/Custom.lua @@ -113,7 +113,7 @@ function CustomPlayer:adjustLPDB(lpdbData, args) return lpdbData end ----@return Widget? +---@return Renderable? function CustomPlayer:createBottomContent() if self:shouldStoreData(self.args) and String.isNotEmpty(self.args.team) then local teamPage = TeamTemplate.getPageName(self.args.team) diff --git a/lua/wikis/commons/HiddenDataBox.lua b/lua/wikis/commons/HiddenDataBox.lua index 6a231531051..d774584a987 100644 --- a/lua/wikis/commons/HiddenDataBox.lua +++ b/lua/wikis/commons/HiddenDataBox.lua @@ -13,7 +13,7 @@ local Logic = Lua.import('Module:Logic') local Game = Lua.import('Module:Game') local I18n = Lua.import('Module:I18n') local Info = Lua.import('Module:Info', {loadData = true}) -local MatchTicker = Lua.import('Module:MatchTicker') +local MatchTicker = Lua.import('Module:MatchTicker/Controller') local Namespace = Lua.import('Module:Namespace') local ReferenceCleaner = Lua.import('Module:ReferenceCleaner') local String = Lua.import('Module:StringUtils') @@ -230,7 +230,7 @@ function HiddenDataBox._matchTicker(supressMatchTicker) return Logic.tryCatch( function() - local matchTicker = MatchTicker{ + return MatchTicker.makeMatchTicker{ tournament = mw.title.getCurrentTitle().prefixedText, limit = 5, upcoming = true, @@ -239,7 +239,6 @@ function HiddenDataBox._matchTicker(supressMatchTicker) queryByParent = false, entityStyle = true, } - return matchTicker:query():create() end, function() return nil diff --git a/lua/wikis/commons/Infobox/League.lua b/lua/wikis/commons/Infobox/League.lua index d891cbc5b4b..bea9764584a 100644 --- a/lua/wikis/commons/Infobox/League.lua +++ b/lua/wikis/commons/Infobox/League.lua @@ -22,7 +22,7 @@ local Links = Lua.import('Module:Links') local Locale = Lua.import('Module:Locale') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') -local MatchTicker = Lua.import('Module:MatchTicker') +local MatchTicker = Lua.import('Module:MatchTicker/Controller') local MetadataGenerator = Lua.import('Module:MetadataGenerator') local Namespace = Lua.import('Module:Namespace') local Page = Lua.import('Module:Page') @@ -357,7 +357,7 @@ function League:_createUpcomingMatches() return Logic.tryCatch( function() - local matchTicker = MatchTicker{ + return MatchTicker.makeMatchTicker{ tournament = self.pagename, limit = 5, upcoming = true, @@ -366,7 +366,6 @@ function League:_createUpcomingMatches() queryByParent = true, entityStyle = true, } - return matchTicker:query():create() end, function() return nil diff --git a/lua/wikis/commons/Infobox/Person.lua b/lua/wikis/commons/Infobox/Person.lua index 5730bc24795..79031567489 100644 --- a/lua/wikis/commons/Infobox/Person.lua +++ b/lua/wikis/commons/Infobox/Person.lua @@ -25,7 +25,7 @@ local BasicInfobox = Lua.import('Module:Infobox/Basic') local Earnings = Lua.import('Module:Earnings') local Flags = Lua.import('Module:Flags') local Links = Lua.import('Module:Links') -local MatchTicker = Lua.import('Module:MatchTicker') +local MatchTicker = Lua.import('Module:MatchTicker/Controller') local PlayerIntroduction = Lua.import('Module:PlayerIntroduction/Custom') local Region = Lua.import('Module:Region') @@ -212,7 +212,7 @@ function Person:_createUpcomingMatches() return Logic.tryCatch( function() - local matchTicker = MatchTicker{ + return MatchTicker.makeMatchTicker{ player = self.pagename, limit = 5, upcoming = true, @@ -220,7 +220,6 @@ function Person:_createUpcomingMatches() hideTournament = false, entityStyle = true, } - return matchTicker:query():create() end, function() return nil diff --git a/lua/wikis/commons/Infobox/Team.lua b/lua/wikis/commons/Infobox/Team.lua index 53c6793059d..032764dae61 100644 --- a/lua/wikis/commons/Infobox/Team.lua +++ b/lua/wikis/commons/Infobox/Team.lua @@ -18,7 +18,7 @@ local Json = Lua.import('Module:Json') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') local Namespace = Lua.import('Module:Namespace') -local MatchTicker = Lua.import('Module:MatchTicker') +local MatchTicker = Lua.import('Module:MatchTicker/Controller') local String = Lua.import('Module:StringUtils') local Table = Lua.import('Module:Table') local TeamTemplate = Lua.import('Module:TeamTemplate') @@ -310,7 +310,7 @@ function Team:_createUpcomingMatches() return Logic.tryCatch( function() - local matchTicker = MatchTicker{ + return MatchTicker.makeMatchTicker{ team = self.pagename, limit = 5, upcoming = true, @@ -318,7 +318,6 @@ function Team:_createUpcomingMatches() hideTournament = false, entityStyle = true, } - return matchTicker:query():create() end, function() return nil diff --git a/lua/wikis/commons/Infobox/UnofficialWorldChampion.lua b/lua/wikis/commons/Infobox/UnofficialWorldChampion.lua index c8a6243f999..7bf45a43f8a 100644 --- a/lua/wikis/commons/Infobox/UnofficialWorldChampion.lua +++ b/lua/wikis/commons/Infobox/UnofficialWorldChampion.lua @@ -13,7 +13,7 @@ local Info = Lua.import('Module:Info', {loadData = true}) local Json = Lua.import('Module:Json') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') -local MatchTicker = Lua.import('Module:MatchTicker') +local MatchTicker = Lua.import('Module:MatchTicker/Controller') local Namespace = Lua.import('Module:Namespace') local String = Lua.import('Module:StringUtils') local Table = Lua.import('Module:Table') @@ -216,7 +216,7 @@ function UnofficialWorldChampion:_createUpcomingMatches() return Logic.tryCatch( function() - local matchTicker = MatchTicker{ + return MatchTicker.makeMatchTicker{ team = currentChampion.template, limit = 5, upcoming = true, @@ -224,7 +224,6 @@ function UnofficialWorldChampion:_createUpcomingMatches() hideTournament = false, entityStyle = true, } - return matchTicker:query():create() end, function() return nil diff --git a/lua/wikis/commons/MatchTicker.lua b/lua/wikis/commons/MatchTicker/Controller.lua similarity index 72% rename from lua/wikis/commons/MatchTicker.lua rename to lua/wikis/commons/MatchTicker/Controller.lua index dcdeb7f6fbd..be91a88a53d 100644 --- a/lua/wikis/commons/MatchTicker.lua +++ b/lua/wikis/commons/MatchTicker/Controller.lua @@ -8,10 +8,8 @@ local Lua = require('Module:Lua') local Array = Lua.import('Module:Array') -local Class = Lua.import('Module:Class') local FnUtil = Lua.import('Module:FnUtil') local Game = Lua.import('Module:Game') -local I18n = Lua.import('Module:I18n') local Logic = Lua.import('Module:Logic') local Lpdb = Lua.import('Module:Lpdb') local Operator = Lua.import('Module:Operator') @@ -25,10 +23,7 @@ local MatchUtil = Lua.import('Module:Match/Util') local MatchGroupUtil = Lua.import('Module:MatchGroup/Util/Custom') local Tournament = Lua.import('Module:Tournament') -local Html = Lua.import('Module:Widget/Html/All') -local MatchCard = Lua.import('Module:Widget/Match/Card') -local Carousel = Lua.import('Module:Widget/Basic/Carousel') -local Switch = Lua.import('Module:Widget/Switch') +local MatchTickerWrapper = Lua.import('Module:Widget/Match/Ticker/Wrapper') local Condition = Lua.import('Module:Condition') local ConditionTree = Condition.Tree @@ -69,7 +64,6 @@ local DEFAULT_LIMIT = 20 local DEFAULT_ORDER = 'date asc, liquipediatier asc, tournament asc' local DEFAULT_RECENT_ORDER = 'date desc, liquipediatier asc, tournament asc' local NOW = os.date('%Y-%m-%d %H:%M', os.time(os.date('!*t') --[[@as osdateparam]])) -local TABLE_OF_CONTENTS = '__TOC__' ---@class MatchTickerConfig ---@field tournaments string[] @@ -97,6 +91,7 @@ local TABLE_OF_CONTENTS = '__TOC__' ---@field variant 'vertical' | 'horizontal' ---@field featuredOnly boolean? ---@field displayGameIcons boolean? +---@field header Renderable? ---@class MatchTickerGameData ---@field asGame boolean? @@ -104,19 +99,29 @@ local TABLE_OF_CONTENTS = '__TOC__' ---@field map string? ---@field mapDisplayName string? ----@class MatchTicker ----@operator call(table): MatchTicker ----@field args table ----@field config MatchTickerConfig ----@field matches table[]? -local MatchTicker = Class.new(function(self, args) self:init(args) end) +local MatchTickerController = {} ---@param args table? ----@return table -function MatchTicker:init(args) - args = args or {} - self.args = args +---@return Renderable? +function MatchTickerController.makeMatchTicker(args) + local config = MatchTickerController.parseConfig(args or {}) + local matches = MatchTickerController.fetchMatches(config) + return MatchTickerWrapper{ + matches = matches, + header = config.header, + showInfoForEmptyResults = config.showInfoForEmptyResults, + wrapperClasses = config.wrapperClasses, + hideTournament = config.hideTournament, + displayGameIcons = config.displayGameIcons, + onlyHighlightOnValue = config.onlyHighlightOnValue, + variant = config.variant + } +end +---@private +---@param args table +---@return MatchTickerConfig +function MatchTickerController.parseConfig(args) local hasOpponent = Logic.isNotEmpty(args.player or args.team) local config = { @@ -153,6 +158,7 @@ function MatchTicker:init(args) featuredOnly = Logic.readBool(args.featuredOnly), displayGameIcons = Logic.readBool(args.displayGameIcons), variant = Logic.readBool(args.entityStyle) and 'horizontal' or 'vertical', + header = args.header, } --min 1 of them has to be set; recent can not be set while any of the others is set @@ -196,53 +202,52 @@ function MatchTicker:init(args) end config.wrapperClasses = wrapperClasses - self.config = config - - return self + return config end ---queries the matches and filters them for unwanted ones ----@param matches table? ----@return MatchTicker -function MatchTicker:query(matches) - if not matches then - matches = {} - Lpdb.executeMassQuery('match2', - { - conditions = self:buildQueryConditions(), - order = self.config.order, - query = table.concat(self.config.queryColumns, ','), - limit = DEFAULT_LIMIT, - }, - function(record) - record = self:parseMatch(record) - if not self:keepMatch(record) then - return - end - for _, match in ipairs(self:expandGamesOfMatch(record)) do - table.insert(matches, match) - end - if #matches >= self.config.limit then - return false - end - end, - DEFAULT_LIMIT * 20 - ) - end +---@private +---@param config MatchTickerConfig +---@return table[] +function MatchTickerController.fetchMatches(config) + local matches = {} + Lpdb.executeMassQuery('match2', + { + conditions = MatchTickerController.buildQueryConditions(config), + order = config.order, + query = table.concat(config.queryColumns, ','), + limit = DEFAULT_LIMIT, + }, + function(record) + record = MatchTickerController.parseMatch(record, config) + if not MatchTickerController.keepMatch(record, config) then + return + end + for _, match in ipairs(MatchTickerController.expandGamesOfMatch(record, config)) do + table.insert(matches, match) + end + if #matches >= config.limit then + return false + end + end, + DEFAULT_LIMIT * 20 + ) - if type(matches[1]) == 'table' then - matches = self:sortMatches(matches) - matches = Array.sub(matches, 1, self.config.limit) - self.matches = Array.map(matches, function(match) return self:adjustMatch(match) end) - return self + if type(matches[1]) ~= 'table' then + return {} end - return self + matches = MatchTickerController.sortMatches(matches, config) + matches = Array.sub(matches, 1, config.limit) + matches = Array.map(matches, function(match) return MatchTickerController.adjustMatch(match, config) end) + + return matches end +---@private +---@param config MatchTickerConfig ---@return string -function MatchTicker:buildQueryConditions() - local config = self.config +function MatchTickerController.buildQueryConditions(config) local conditions = ConditionTree(BooleanOperator.all) if Table.isNotEmpty(config.tournaments) then @@ -313,15 +318,15 @@ function MatchTicker:buildQueryConditions() conditions:add(tierConditions) end - conditions:add(self:dateConditions()) + conditions:add(MatchTickerController.dateConditions(config)) return conditions:toString() .. config.additionalConditions end +---@private +---@param config MatchTickerConfig ---@return ConditionTree -function MatchTicker:dateConditions() - local config = self.config - +function MatchTickerController.dateConditions(config) local dateConditions = ConditionTree(BooleanOperator.all) if config.onlyExact then @@ -353,38 +358,40 @@ function MatchTicker:dateConditions() return dateConditions:add{ConditionNode(ColumnName('date'), Comparator.gt, NOW)} end ----Overwritable per wiki decision +---@private ---@param match table +---@param config MatchTickerConfig ---@return table -function MatchTicker:parseMatch(match) +function MatchTickerController.parseMatch(match, config) match.opponents = Array.map(match.match2opponents, function(opponent, opponentIndex) return MatchGroupUtil.opponentFromRecord(match, opponent, opponentIndex) end) - if self.config.regions or self.config.featuredOnly then - match.tournamentData = MatchTicker.fetchTournament(match.parent) + if config.regions or config.featuredOnly then + match.tournamentData = MatchTickerController.fetchTournament(match.parent) end return match end -local previousMatchWasTbd ----Overwritable per wiki decision +local previousMatchWasTbd = false +---@private ---@param match table +---@param config MatchTickerConfig ---@return boolean -function MatchTicker:keepMatch(match) +function MatchTickerController.keepMatch(match, config) if match.extradata and match.extradata.hidden then return false end -- Remove matches with wrong region - if self.config.regions then + if config.regions then if not match.tournamentData then return false end - if not Table.includes(self.config.regions, match.tournamentData.region) then + if not Table.includes(config.regions, match.tournamentData.region) then return false end end - if self.config.featuredOnly then + if config.featuredOnly then local matchIsInFeaturedTournament = match.tournamentData and match.tournamentData.featured local matchIsFeatured = match.extradata and match.extradata.featured if not matchIsInFeaturedTournament and not matchIsFeatured then @@ -397,30 +404,24 @@ function MatchTicker:keepMatch(match) return false end - if not self.config.showAllTbdMatches then + if not config.showAllTbdMatches then local isTbdMatch = Array.all(match.opponents, function(opponent) return Opponent.isEmpty(opponent) or Opponent.isTbd(opponent) end) - local toss = isTbdMatch and previousMatchWasTbd - if isTbdMatch then - previousMatchWasTbd = true - else - previousMatchWasTbd = false - end + local throwAway = isTbdMatch and previousMatchWasTbd + previousMatchWasTbd = isTbdMatch - if toss == true then - return false - end + return not throwAway end return true end ----Overwritable per wiki decision +---@private ---@param match table +---@param config MatchTickerConfig ---@return table[] -function MatchTicker:expandGamesOfMatch(match) - local config = self.config +function MatchTickerController.expandGamesOfMatch(match, config) if not match.match2games or #match.match2games < 2 then return {match} end @@ -473,11 +474,12 @@ function MatchTicker:expandGamesOfMatch(match) end) end ----Overwritable per wiki decision +---@private ---@param matches table[] +---@param config MatchTickerConfig ---@return table[] -function MatchTicker:sortMatches(matches) - local reverse = self.config.recent and true or false +function MatchTickerController.sortMatches(matches, config) + local reverse = config.recent and true or false return Array.sortBy(matches, FnUtil.identity, function (a, b) if a.date ~= b.date then if reverse then @@ -493,31 +495,34 @@ function MatchTicker:sortMatches(matches) end --- Will only switch if enteredOpponentOnLeft is enabled AND there are exactly 2 opponents +---@private ---@param match table +---@param config MatchTickerConfig ---@return table -function MatchTicker:adjustMatch(match) - if not self.config.enteredOpponentOnLeft or #match.opponents ~= 2 then +function MatchTickerController.adjustMatch(match, config) + if not config.enteredOpponentOnLeft or #match.opponents ~= 2 then return match end - local opponentNames = Array.extend({self.config.player}, self.config.teamPages) + local opponentNames = Array.extend({config.player}, config.teamPages) if --check for the name value Table.includes(opponentNames, ((match.opponents[2].name or ''):gsub(' ', '_'))) --check inside match2players too for the player value - or self.config.player and Table.any(match.opponents[2].players, function(_, playerData) - return (playerData.pageName or ''):gsub(' ', '_') == self.config.player end) + or config.player and Table.any(match.opponents[2].players, function(_, playerData) + return (playerData.pageName or ''):gsub(' ', '_') == config.player end) then - return MatchTicker.switchOpponents(match) + return MatchTickerController.switchOpponents(match) end return match end --- Will only switch if there are exactly 2 opponents +---@private ---@param match table ---@return table -function MatchTicker.switchOpponents(match) +function MatchTickerController.switchOpponents(match) if #match.opponents ~= 2 then return match end @@ -533,91 +538,11 @@ function MatchTicker.switchOpponents(match) end --- Fetches region of a tournament +---@private ---@param tournamentPage string ---@return StandardTournament? -MatchTicker.fetchTournament = FnUtil.memoize(function(tournamentPage) +MatchTickerController.fetchTournament = FnUtil.memoize(function(tournamentPage) return Tournament.getTournament(tournamentPage) end) -local function HorizontalLayout(matchCards, config) - local carousel = Carousel{ - children = matchCards, - itemWidth = '12.5rem', - gap = '0.5rem', - } - - return Html.Div{ - css = {['margin-bottom'] = '1rem'}, - children = { - Html.Div{ - classes = {'mw-heading', 'mw-heading2'}, - children = { - Html.H2{ - css = {border = 'unset'}, - children = I18n.translate('matchticker-upcoming-matches'), - }, - }, - }, - Switch{ - label = 'Show countdown', - switchGroup = 'countdown', - storeValue = true, - defaultActive = true, - css = {margin = '0.75rem 0 1rem'}, - content = carousel, - }, - Html.Div{ - css = {['margin-top'] = '1rem'}, - children = { - TABLE_OF_CONTENTS, - }, - }, - }, - } -end - ----@param header Renderable? ----@return Renderable? -function MatchTicker:create(header) - if not self.matches and not self.config.showInfoForEmptyResults then - return - end - - if not self.matches or #self.matches == 0 then - return Html.Div{ - classes = self.config.wrapperClasses, - css = {['text-align'] = 'center'}, - children = Array.extend({header}, {'No Results found.'}), - } - end - - local matchCards = Array.map(self.matches, function(match) - return MatchCard{ - match = MatchGroupUtil.matchFromRecord(match), - hideTournament = self.config.hideTournament, - displayGameIcons = self.config.displayGameIcons, - onlyHighlightOnValue = self.config.onlyHighlightOnValue, - variant = self.config.variant == 'horizontal' and 'vertical' or nil, - gameData = { - asGame = match.asGame, - gameIds = match.asGameIndexes, - map = match.map, - mapDisplayName = match.extradata and match.extradata.displayname or nil - } - } - end) - - if self.config.variant == 'vertical' then - return Html.Div{ - classes = self.config.wrapperClasses, - children = Array.extend({header}, matchCards), - } - end - - return Html.Div{ - classes = self.config.wrapperClasses, - children = Array.extend({header}, HorizontalLayout(matchCards, self.config)), - } -end - -return MatchTicker +return MatchTickerController diff --git a/lua/wikis/commons/MatchTicker/Custom.lua b/lua/wikis/commons/MatchTicker/Custom.lua index d2cf23b5f5e..b2f089ed833 100644 --- a/lua/wikis/commons/MatchTicker/Custom.lua +++ b/lua/wikis/commons/MatchTicker/Custom.lua @@ -11,7 +11,7 @@ local Arguments = Lua.import('Module:Arguments') local Logic = Lua.import('Module:Logic') local Table = Lua.import('Module:Table') -local MatchTicker = Lua.import('Module:MatchTicker') +local MatchTicker = Lua.import('Module:MatchTicker/Controller') local InfoboxHeader = Lua.import('Module:Widget/Infobox/Header') local CustomMatchTicker = {} @@ -33,9 +33,9 @@ function CustomMatchTicker.mainPage(frame) args.games = args['filterbuttons-game'] if args.type == 'upcoming' then - return MatchTicker(Table.merge(args, {ongoing = true, upcoming = true})):query():create() + return MatchTicker.makeMatchTicker(Table.merge(args, {ongoing = true, upcoming = true})) elseif args.type == 'recent' then - return MatchTicker(Table.merge(args, {recent = true})):query():create() + return MatchTicker.makeMatchTicker(Table.merge(args, {recent = true})) end end @@ -51,19 +51,15 @@ end ---Displays recent matches for a player or team. ---@param args table ----@param matches {recent: table?}? ---@return Renderable? -function CustomMatchTicker.recent(args, matches) - matches = matches or {} - +function CustomMatchTicker.recent(args) --adjusting args args.infoboxClass = Logic.nilOr(Logic.readBoolOrNil(args.infoboxClass), true) args.recent = true args.limit = args.limit or args.recentLimit or 5 + args.header = InfoboxHeader{name = 'Recent Matches'} - return MatchTicker(args):query(matches.recent):create( - InfoboxHeader{name = 'Recent Matches'} - ) + return MatchTicker.makeMatchTicker(args) end return CustomMatchTicker diff --git a/lua/wikis/commons/Widget/MainPage/MatchTicker.lua b/lua/wikis/commons/Widget/MainPage/MatchTicker.lua index 76bdd72adf3..ae5e97409a4 100644 --- a/lua/wikis/commons/Widget/MainPage/MatchTicker.lua +++ b/lua/wikis/commons/Widget/MainPage/MatchTicker.lua @@ -7,7 +7,7 @@ local Lua = require('Module:Lua') -local MatchTickerContainer = Lua.import('Module:Widget/Match/Ticker/Container') +local MatchTickerContainer = Lua.import('Module:Widget/Match/Ticker/FilterableContainer') local Component = Lua.import('Module:Widget/Component') local Html = Lua.import('Module:Widget/Html') diff --git a/lua/wikis/commons/Widget/Match/Ticker/Container.lua b/lua/wikis/commons/Widget/Match/Ticker/Container.lua index 43a8dd2b7a3..5773146af1d 100644 --- a/lua/wikis/commons/Widget/Match/Ticker/Container.lua +++ b/lua/wikis/commons/Widget/Match/Ticker/Container.lua @@ -7,125 +7,5 @@ local Lua = require('Module:Lua') -local Array = Lua.import('Module:Array') -local Class = Lua.import('Module:Class') -local FeatureFlag = Lua.import('Module:FeatureFlag') -local Operator = Lua.import('Module:Operator') -local String = Lua.import('Module:StringUtils') -local Table = Lua.import('Module:Table') - -local Widget = Lua.import('Module:Widget') -local ContentSwitch = Lua.import('Module:Widget/ContentSwitch') -local HtmlWidgets = Lua.import('Module:Widget/Html/All') -local Switch = Lua.import('Module:Widget/Switch') -local FilterConfig = Lua.import('Module:FilterButtons/Config') - ----@class MatchTickerContainer: Widget ----@operator call(table): MatchTickerContainer -local MatchTickerContainer = Class.new(Widget) -MatchTickerContainer.defaultProps = { - limit = 10, - module = 'MatchTicker/Custom', - fn = 'mainPage', -} - ----@return Widget -function MatchTickerContainer:render() - local function filterName(filter) - return 'filterbuttons-' .. filter - end - - local filters = Array.map(FilterConfig.categories, Operator.property('name')) or {} - local filterText = table.concat(Array.map(filters, filterName), ',') - - local defaultFilterParams = Table.map(FilterConfig.categories, function (_, category) - return filterName(category.name), table.concat(category.defaultItems or {}, ',') - end) - - local matchTickerArgs = { - limit = self.props.limit, - displayGameIcons = self.props.displayGameIcons - } - - local devFlag = FeatureFlag.get('dev') - - ---@param type 'upcoming' | 'recent' - ---@return string - local function buildTemplateExpansionString(type) - return String.interpolate( - '#invoke:Lua|invoke|module=${module}|fn=${fn}${args}', - { - module = self.defaultProps.module, - fn = self.defaultProps.fn, - args = table.concat(Array.extractValues(Table.map( - Table.merge(matchTickerArgs, {type=type, dev=devFlag}), - function (key, value) - return key, String.interpolate('|${key}=${value}', {key = key, value = tostring(value)}) - end - )), '') - } - ) - end - - ---@param type 'upcoming' |'recent' - ---@return Renderable - local function callTemplate(type) - local ticker = Lua.import('Module:' .. self.defaultProps.module) - return ticker[self.defaultProps.fn]( - Table.merge( - {type=type}, - matchTickerArgs, - defaultFilterParams - ) - ) - end - - return HtmlWidgets.Div{ - classes = {'match-section-header'}, - css = {['padding-top'] = '0.75rem'}, - children = { - ContentSwitch{ - css = {margin = '0 0.75rem 0.75rem'}, - tabs = { - { - label = 'Upcoming', - value = 'upcoming', - content = { - Switch{ - label = 'Show Countdown', - switchGroup = 'countdown', - storeValue = true, - defaultActive = true, - css = {margin = '1rem 0', ['justify-content'] = 'center'}, - content = HtmlWidgets.Div{ - attributes = { - ['data-filter-expansion-template'] = buildTemplateExpansionString('upcoming'), - ['data-filter-groups'] = filterText, - }, - children = callTemplate('upcoming'), - } - } - } - }, - { - label = 'Completed', - value = 'completed', - content = { - HtmlWidgets.Div{ - attributes = { - ['data-filter-expansion-template'] = buildTemplateExpansionString('recent'), - ['data-filter-groups'] = filterText, - }, - children = callTemplate('recent'), - } - } - } - }, - switchGroup = 'matchFiler', - defaultActive = 1, - } - }, - } -end - -return MatchTickerContainer +---@deprecated +return Lua.import('Module:Widget/Match/Ticker/FilterableContainer') diff --git a/lua/wikis/commons/Widget/Match/Ticker/FilterableContainer.lua b/lua/wikis/commons/Widget/Match/Ticker/FilterableContainer.lua new file mode 100644 index 00000000000..670fe6217a0 --- /dev/null +++ b/lua/wikis/commons/Widget/Match/Ticker/FilterableContainer.lua @@ -0,0 +1,131 @@ +--- +-- @Liquipedia +-- page=Module:Widget/Match/Ticker/FilterableContainer +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local Lua = require('Module:Lua') + +local Array = Lua.import('Module:Array') +local Class = Lua.import('Module:Class') +local FeatureFlag = Lua.import('Module:FeatureFlag') +local Operator = Lua.import('Module:Operator') +local String = Lua.import('Module:StringUtils') +local Table = Lua.import('Module:Table') + +local Widget = Lua.import('Module:Widget') +local ContentSwitch = Lua.import('Module:Widget/ContentSwitch') +local HtmlWidgets = Lua.import('Module:Widget/Html') +local Switch = Lua.import('Module:Widget/Switch') +local FilterConfig = Lua.import('Module:FilterButtons/Config') + +---@class FilterableMatchTickerContainer: Widget +---@operator call(table): FilterableMatchTickerContainer +local FilterableMatchTickerContainer = Class.new(Widget) +FilterableMatchTickerContainer.defaultProps = { + limit = 10, + module = 'MatchTicker/Custom', + fn = 'mainPage', +} + +---@return Widget +function FilterableMatchTickerContainer:render() + local function filterName(filter) + return 'filterbuttons-' .. filter + end + + local filters = Array.map(FilterConfig.categories, Operator.property('name')) or {} + local filterText = table.concat(Array.map(filters, filterName), ',') + + local defaultFilterParams = Table.map(FilterConfig.categories, function (_, category) + return filterName(category.name), table.concat(category.defaultItems or {}, ',') + end) + + local matchTickerArgs = { + limit = self.props.limit, + displayGameIcons = self.props.displayGameIcons + } + + local devFlag = FeatureFlag.get('dev') + + ---@param type 'upcoming' | 'recent' + ---@return string + local function buildTemplateExpansionString(type) + return String.interpolate( + '#invoke:Lua|invoke|module=${module}|fn=${fn}${args}', + { + module = self.defaultProps.module, + fn = self.defaultProps.fn, + args = table.concat(Array.extractValues(Table.map( + Table.merge(matchTickerArgs, {type=type, dev=devFlag}), + function (key, value) + return key, String.interpolate('|${key}=${value}', {key = key, value = tostring(value)}) + end + )), '') + } + ) + end + + ---@param type 'upcoming' |'recent' + ---@return Renderable + local function callTemplate(type) + local ticker = Lua.import('Module:' .. self.defaultProps.module) + return ticker[self.defaultProps.fn]( + Table.merge( + {type=type}, + matchTickerArgs, + defaultFilterParams + ) + ) + end + + return HtmlWidgets.Div{ + classes = {'match-section-header'}, + css = {['padding-top'] = '0.75rem'}, + children = { + ContentSwitch{ + css = {margin = '0 0.75rem 0.75rem'}, + tabs = { + { + label = 'Upcoming', + value = 'upcoming', + content = { + Switch{ + label = 'Show Countdown', + switchGroup = 'countdown', + storeValue = true, + defaultActive = true, + css = {margin = '1rem 0', ['justify-content'] = 'center'}, + content = HtmlWidgets.Div{ + attributes = { + ['data-filter-expansion-template'] = buildTemplateExpansionString('upcoming'), + ['data-filter-groups'] = filterText, + }, + children = callTemplate('upcoming'), + } + } + } + }, + { + label = 'Completed', + value = 'completed', + content = { + HtmlWidgets.Div{ + attributes = { + ['data-filter-expansion-template'] = buildTemplateExpansionString('recent'), + ['data-filter-groups'] = filterText, + }, + children = callTemplate('recent'), + } + } + } + }, + switchGroup = 'matchFiler', + defaultActive = 1, + } + }, + } +end + +return FilterableMatchTickerContainer diff --git a/lua/wikis/commons/Widget/Match/Ticker/HorizontalContainer.lua b/lua/wikis/commons/Widget/Match/Ticker/HorizontalContainer.lua new file mode 100644 index 00000000000..8d3bfd22adb --- /dev/null +++ b/lua/wikis/commons/Widget/Match/Ticker/HorizontalContainer.lua @@ -0,0 +1,58 @@ +--- +-- @Liquipedia +-- page=Module:Widget/Match/Ticker/HorizontalContainer +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local Lua = require('Module:Lua') + +local Component = Lua.import('Module:Widget/Component') +local I18n = Lua.import('Module:I18n') + +local Carousel = Lua.import('Module:Widget/Basic/Carousel') +local Switch = Lua.import('Module:Widget/Switch') +local Html = Lua.import('Module:Widget/Html') + +local TABLE_OF_CONTENTS = '__TOC__' + +---@param props {children: Renderable[]} +---@return Renderable +local function HorizontalContainer(props) + local carousel = Carousel{ + children = props.children, + itemWidth = '12.5rem', + gap = '0.5rem', + } + + return Html.Div{ + css = {['margin-bottom'] = '1rem'}, + children = { + Html.Div{ + classes = {'mw-heading', 'mw-heading2'}, + children = { + Html.H2{ + css = {border = 'unset'}, + children = I18n.translate('matchticker-upcoming-matches'), + }, + }, + }, + Switch{ + label = 'Show countdown', + switchGroup = 'countdown', + storeValue = true, + defaultActive = true, + css = {margin = '0.75rem 0 1rem'}, + content = carousel, + }, + Html.Div{ + css = {['margin-top'] = '1rem'}, + children = { + TABLE_OF_CONTENTS, + }, + }, + }, + } +end + +return Component.component(HorizontalContainer) diff --git a/lua/wikis/commons/Widget/Match/Ticker/Wrapper.lua b/lua/wikis/commons/Widget/Match/Ticker/Wrapper.lua new file mode 100644 index 00000000000..1ba57f2b8d4 --- /dev/null +++ b/lua/wikis/commons/Widget/Match/Ticker/Wrapper.lua @@ -0,0 +1,65 @@ +--- +-- @Liquipedia +-- page=Module:Widget/Match/Ticker/Wrapper +-- +-- Please see https://github.com/Liquipedia/Lua-Modules to contribute +-- + +local Lua = require('Module:Lua') + +local Array = Lua.import('Module:Array') +local Component = Lua.import('Module:Widget/Component') +local MatchGroupUtil = Lua.import('Module:MatchGroup/Util/Custom') + +local Html = Lua.import('Module:Widget/Html') +local MatchCard = Lua.import('Module:Widget/Match/Card') +local HorizontalContainer = Lua.import('Module:Widget/Match/Ticker/HorizontalContainer') + +---@param props {matches: table[], header: Renderable?, showInfoForEmptyResults: boolean, wrapperClasses: string[], +---hideTournament: boolean, displayGameIcons: boolean, onlyHighlightOnValue: string?, variant: 'vertical'|'horizontal'} +---@return Renderable? +local function MatchTickerWrapper(props) + local matches = props.matches + if not matches and not props.showInfoForEmptyResults then + return + end + local header = props.header + + if not matches or #matches == 0 then + return Html.Div{ + classes = props.wrapperClasses, + css = {['text-align'] = 'center'}, + children = Array.extend({header}, {'No Results found.'}), + } + end + + local matchCards = Array.map(matches, function(match) + return MatchCard{ + match = MatchGroupUtil.matchFromRecord(match), + hideTournament = props.hideTournament, + displayGameIcons = props.displayGameIcons, + onlyHighlightOnValue = props.onlyHighlightOnValue, + variant = props.variant == 'horizontal' and 'vertical' or nil, + gameData = { + asGame = match.asGame, + gameIds = match.asGameIndexes, + map = match.map, + mapDisplayName = match.extradata and match.extradata.displayname or nil + } + } + end) + + if props.variant == 'vertical' then + return Html.Div{ + classes = props.wrapperClasses, + children = Array.extend({header}, matchCards), + } + end + + return Html.Div{ + classes = props.wrapperClasses, + children = Array.extend({header}, HorizontalContainer{children = matchCards}), + } +end + +return Component.component(MatchTickerWrapper) diff --git a/lua/wikis/dota2/Infobox/Person/Player/Custom.lua b/lua/wikis/dota2/Infobox/Person/Player/Custom.lua index 1b51838eb11..ad7ed3a1c9e 100644 --- a/lua/wikis/dota2/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/dota2/Infobox/Person/Player/Custom.lua @@ -139,7 +139,7 @@ function CustomPlayer:adjustLPDB(lpdbData, args, personType) return lpdbData end ----@return Widget? +---@return Renderable? function CustomPlayer:createBottomContent() if not Namespace.isMain() then return diff --git a/lua/wikis/geoguessr/Infobox/Person/Player/Custom.lua b/lua/wikis/geoguessr/Infobox/Person/Player/Custom.lua index d42a461de62..6bc318cf9bf 100644 --- a/lua/wikis/geoguessr/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/geoguessr/Infobox/Person/Player/Custom.lua @@ -38,7 +38,7 @@ function CustomPlayer:_getStatusContents() return {Page.makeInternalLink({onlyIfExists = true}, self.args.status) or self.args.status} end ----@return Html? +---@return Renderable? function CustomPlayer:createBottomContent() if self:shouldStoreData(self.args) then return MatchTicker.recent{player = self.pagename} diff --git a/lua/wikis/leagueoflegends/Infobox/Person/Player/Custom.lua b/lua/wikis/leagueoflegends/Infobox/Person/Player/Custom.lua index 1abe77722f1..ef82cb3e585 100644 --- a/lua/wikis/leagueoflegends/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/leagueoflegends/Infobox/Person/Player/Custom.lua @@ -118,7 +118,7 @@ function CustomPlayer:adjustLPDB(lpdbData, args) return lpdbData end ----@return Widget? +---@return Renderable? function CustomPlayer:createBottomContent() if self:shouldStoreData(self.args) and String.isNotEmpty(self.args.team) then local teamPage = TeamTemplate.getPageName(self.args.team) diff --git a/lua/wikis/marvelrivals/Infobox/Person/Player/Custom.lua b/lua/wikis/marvelrivals/Infobox/Person/Player/Custom.lua index 1a3ff405f17..345fc561143 100644 --- a/lua/wikis/marvelrivals/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/marvelrivals/Infobox/Person/Player/Custom.lua @@ -89,7 +89,7 @@ function CustomPlayer:adjustLPDB(lpdbData, args, personType) return lpdbData end ----@return Widget? +---@return Renderable? function CustomPlayer:createBottomContent() if String.isEmpty(self.args.team) or not self:shouldStoreData(self.args) then return diff --git a/lua/wikis/overwatch/Infobox/Person/Player/Custom.lua b/lua/wikis/overwatch/Infobox/Person/Player/Custom.lua index 3c23b89b52a..4d12ae2a5a0 100644 --- a/lua/wikis/overwatch/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/overwatch/Infobox/Person/Player/Custom.lua @@ -100,7 +100,7 @@ function CustomPlayer:adjustLPDB(lpdbData, args) return lpdbData end ----@return Widget? +---@return Renderable? function CustomPlayer:createBottomContent() if self:shouldStoreData(self.args) and String.isNotEmpty(self.args.team) then local teamPage = TeamTemplate.getPageName(self.args.team) diff --git a/lua/wikis/rainbowsix/Infobox/Person/Player/Custom.lua b/lua/wikis/rainbowsix/Infobox/Person/Player/Custom.lua index 918b7d046e8..2faf96495b4 100644 --- a/lua/wikis/rainbowsix/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/rainbowsix/Infobox/Person/Player/Custom.lua @@ -124,7 +124,7 @@ function CustomPlayer:adjustLPDB(lpdbData, args) return lpdbData end ----@return Widget? +---@return Renderable? function CustomPlayer:createBottomContent() if self:shouldStoreData(self.args) and String.isNotEmpty(self.args.team) then local teamPage = TeamTemplate.getPageName(self.args.team) diff --git a/lua/wikis/starcraft2/Infobox/Person/Player/Custom.lua b/lua/wikis/starcraft2/Infobox/Person/Player/Custom.lua index 2f66cd74bce..c9ac80bd88f 100644 --- a/lua/wikis/starcraft2/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/starcraft2/Infobox/Person/Player/Custom.lua @@ -157,7 +157,7 @@ function CustomPlayer:_getActiveCasterYears() return YearsActive.displayYears(years:toArray()) end ----@return Html? +---@return Renderable? function CustomPlayer:createBottomContent() if self.shouldQueryData then return MatchTicker.recent({ diff --git a/lua/wikis/stormgate/Infobox/Person/Player/Custom.lua b/lua/wikis/stormgate/Infobox/Person/Player/Custom.lua index 68001f58aa9..17473d32e8a 100644 --- a/lua/wikis/stormgate/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/stormgate/Infobox/Person/Player/Custom.lua @@ -112,7 +112,7 @@ function CustomPlayer:_getActiveCasterYears() return YearsActive.displayYears(years:toArray()) end ----@return Html? +---@return Renderable? function CustomPlayer:createBottomContent() if self:shouldStoreData(self.args) then return MatchTicker.recent({player = self.pagename}) diff --git a/lua/wikis/valorant/Infobox/Person/Player/Custom.lua b/lua/wikis/valorant/Infobox/Person/Player/Custom.lua index cfa5c52fa66..826fa495030 100644 --- a/lua/wikis/valorant/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/valorant/Infobox/Person/Player/Custom.lua @@ -126,7 +126,7 @@ function CustomPlayer:adjustLPDB(lpdbData, args, personType) return lpdbData end ----@return Widget? +---@return Renderable? function CustomPlayer:createBottomContent() if self:shouldStoreData(self.args) and String.isNotEmpty(self.args.team) then local teamPage = TeamTemplate.getPageName(self.args.team) diff --git a/lua/wikis/wildrift/Infobox/Person/Player/Custom.lua b/lua/wikis/wildrift/Infobox/Person/Player/Custom.lua index eb079900655..c50fcfae255 100644 --- a/lua/wikis/wildrift/Infobox/Person/Player/Custom.lua +++ b/lua/wikis/wildrift/Infobox/Person/Player/Custom.lua @@ -124,7 +124,7 @@ function CustomPlayer:adjustLPDB(lpdbData, args, personType) return lpdbData end ----@return Widget? +---@return Renderable? function CustomPlayer:createBottomContent() if self:shouldStoreData(self.args) and String.isNotEmpty(self.args.team) then local teamPage = TeamTemplate.getPageName(self.args.team)