diff --git a/lua/wikis/commons/HiddenDataBox.lua b/lua/wikis/commons/HiddenDataBox.lua index 2054230a6aa..6a231531051 100644 --- a/lua/wikis/commons/HiddenDataBox.lua +++ b/lua/wikis/commons/HiddenDataBox.lua @@ -14,7 +14,6 @@ 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 MatchTickerEntityDisplay = Lua.import('Module:MatchTicker/DisplayComponents/Entity') local Namespace = Lua.import('Module:Namespace') local ReferenceCleaner = Lua.import('Module:ReferenceCleaner') local String = Lua.import('Module:StringUtils') @@ -229,7 +228,7 @@ function HiddenDataBox._matchTicker(supressMatchTicker) return nil end - local result = Logic.tryCatch( + return Logic.tryCatch( function() local matchTicker = MatchTicker{ tournament = mw.title.getCurrentTitle().prefixedText, @@ -238,23 +237,14 @@ function HiddenDataBox._matchTicker(supressMatchTicker) ongoing = true, hideTournament = true, queryByParent = false, + entityStyle = true, } - matchTicker:query() - return matchTicker + return matchTicker:query():create() end, function() return nil end ) - - if not result or not result.matches or #result.matches == 0 then - return nil - end - - return MatchTickerEntityDisplay.Container{ - config = result.config, - matches = result.matches, - }:create() end return Class.export(HiddenDataBox, {exports = {'run'}}) diff --git a/lua/wikis/commons/Infobox/League.lua b/lua/wikis/commons/Infobox/League.lua index 6d81974b88c..d891cbc5b4b 100644 --- a/lua/wikis/commons/Infobox/League.lua +++ b/lua/wikis/commons/Infobox/League.lua @@ -355,7 +355,7 @@ function League:_createUpcomingMatches() return nil end - local result = Logic.tryCatch( + return Logic.tryCatch( function() local matchTicker = MatchTicker{ tournament = self.pagename, @@ -364,24 +364,14 @@ function League:_createUpcomingMatches() ongoing = true, hideTournament = true, queryByParent = true, + entityStyle = true, } - matchTicker:query() - return matchTicker + return matchTicker:query():create() end, function() return nil end ) - - if not result or not result.matches or #result.matches == 0 then - return nil - end - - local EntityDisplay = Lua.import('Module:MatchTicker/DisplayComponents/Entity') - return EntityDisplay.Container{ - config = result.config, - matches = result.matches, - }:create() end ---@param args table diff --git a/lua/wikis/commons/Infobox/Person.lua b/lua/wikis/commons/Infobox/Person.lua index bc3c370b7a1..5730bc24795 100644 --- a/lua/wikis/commons/Infobox/Person.lua +++ b/lua/wikis/commons/Infobox/Person.lua @@ -210,7 +210,7 @@ function Person:_createUpcomingMatches() return nil end - local result = Logic.tryCatch( + return Logic.tryCatch( function() local matchTicker = MatchTicker{ player = self.pagename, @@ -218,24 +218,14 @@ function Person:_createUpcomingMatches() upcoming = true, ongoing = true, hideTournament = false, + entityStyle = true, } - matchTicker:query() - return matchTicker + return matchTicker:query():create() end, function() return nil end ) - - if not result or not result.matches or #result.matches == 0 then - return nil - end - - local EntityDisplay = Lua.import('Module:MatchTicker/DisplayComponents/Entity') - return EntityDisplay.Container{ - config = result.config, - matches = result.matches, - }:create() end function Person:_parseArgs() diff --git a/lua/wikis/commons/Infobox/Team.lua b/lua/wikis/commons/Infobox/Team.lua index d38395f05b8..53c6793059d 100644 --- a/lua/wikis/commons/Infobox/Team.lua +++ b/lua/wikis/commons/Infobox/Team.lua @@ -308,7 +308,7 @@ function Team:_createUpcomingMatches() return nil end - local result = Logic.tryCatch( + return Logic.tryCatch( function() local matchTicker = MatchTicker{ team = self.pagename, @@ -316,24 +316,14 @@ function Team:_createUpcomingMatches() upcoming = true, ongoing = true, hideTournament = false, + entityStyle = true, } - matchTicker:query() - return matchTicker + return matchTicker:query():create() end, function() return nil end ) - - if not result or not result.matches or #result.matches == 0 then - return nil - end - - local EntityDisplay = Lua.import('Module:MatchTicker/DisplayComponents/Entity') - return EntityDisplay.Container{ - config = result.config, - matches = result.matches, - }:create() end ---@param location string? diff --git a/lua/wikis/commons/Infobox/UnofficialWorldChampion.lua b/lua/wikis/commons/Infobox/UnofficialWorldChampion.lua index 1319654f174..c8a6243f999 100644 --- a/lua/wikis/commons/Infobox/UnofficialWorldChampion.lua +++ b/lua/wikis/commons/Infobox/UnofficialWorldChampion.lua @@ -214,7 +214,7 @@ function UnofficialWorldChampion:_createUpcomingMatches() return nil end - local result = Logic.tryCatch( + return Logic.tryCatch( function() local matchTicker = MatchTicker{ team = currentChampion.template, @@ -222,24 +222,14 @@ function UnofficialWorldChampion:_createUpcomingMatches() upcoming = true, ongoing = true, hideTournament = false, + entityStyle = true, } - matchTicker:query() - return matchTicker + return matchTicker:query():create() end, function() return nil end ) - - if not result or not result.matches or #result.matches == 0 then - return nil - end - - local EntityDisplay = Lua.import('Module:MatchTicker/DisplayComponents/Entity') - return EntityDisplay.Container{ - config = result.config, - matches = result.matches, - }:create() end ---@param args table diff --git a/lua/wikis/commons/MatchTicker.lua b/lua/wikis/commons/MatchTicker.lua index c5090e097a0..7910f2a4834 100644 --- a/lua/wikis/commons/MatchTicker.lua +++ b/lua/wikis/commons/MatchTicker.lua @@ -11,6 +11,7 @@ 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') @@ -24,6 +25,11 @@ 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') +local MatchCard = Lua.import('Module:Widget/Match/Card') +local Carousel = Lua.import('Module:Widget/Basic/Carousel') +local Switch = Lua.import('Module:Widget/Switch') + local Condition = Lua.import('Module:Condition') local ConditionTree = Condition.Tree local ConditionNode = Condition.Node @@ -63,36 +69,7 @@ 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]])) - ----@class MatchTickerMatchInterface ----@operator call({config: MatchTickerConfig, match: table}): MatchTickerMatchInterface ----@field config MatchTickerConfig ----@field match table ----@field create fun(self: MatchTickerMatchInterface): Widget|Html? - ----@class MatchTickerContainerInterface ----@operator call({config: MatchTickerConfig, matches: table[]}): MatchTickerContainerInterface ----@field config MatchTickerConfig ----@field matches table[] ----@field create fun(self: MatchTickerContainerInterface): Widget|Html? - ---- Extract externally if it grows ----@param matchTickerConfig MatchTickerConfig ----@return {Container?: MatchTickerContainerInterface, Match: MatchTickerMatchInterface} -local MatchTickerDisplayFactory = function (matchTickerConfig) - assert(not (matchTickerConfig.entityStyle and matchTickerConfig.newStyle), - "Invalid MatchTicker configuration: 'entityStyle' and 'newStyle' are mutually exclusive. " .. - "Choose one display mode: use 'entityStyle' for carousel-based entity display, " .. - "'newStyle' for new-style match cards, or neither for legacy display.") - - if matchTickerConfig.entityStyle then - return Lua.import('Module:MatchTicker/DisplayComponents/Entity') - elseif matchTickerConfig.newStyle then - return Lua.import('Module:MatchTicker/DisplayComponents/New') - else - return Lua.import('Module:MatchTicker/DisplayComponents') - end -end +local TABLE_OF_CONTENTS = '__TOC__' ---@class MatchTickerConfig ---@field tournaments string[] @@ -117,8 +94,7 @@ end ---@field tierTypes string[]? ---@field regions string[]? ---@field games string[]? ----@field newStyle boolean? ----@field entityStyle boolean? +---@field variant 'vertical' | 'horizontal' ---@field featuredOnly boolean? ---@field displayGameIcons boolean? @@ -174,9 +150,9 @@ function MatchTicker:init(args) games = args.games and Array.map(Array.parseCommaSeparatedString(args.games), function (game) return Game.toIdentifier{game=game} end) or nil, - newStyle = Logic.readBool(args.newStyle), featuredOnly = Logic.readBool(args.featuredOnly), - displayGameIcons = Logic.readBool(args.displayGameIcons) + displayGameIcons = Logic.readBool(args.displayGameIcons), + variant = Logic.readBool(args.entityStyle) and 'horizontal' or 'vertical', } --min 1 of them has to be set; recent can not be set while any of the others is set @@ -220,8 +196,6 @@ function MatchTicker:init(args) end config.wrapperClasses = wrapperClasses - MatchTicker.DisplayComponents = MatchTickerDisplayFactory(config) - self.config = config return self @@ -565,43 +539,85 @@ MatchTicker.fetchTournament = FnUtil.memoize(function(tournamentPage) return Tournament.getTournament(tournamentPage) end) ----@param header MatchTickerHeader? ----@return Html -function MatchTicker:create(header) - if not self.matches and not self.config.showInfoForEmptyResults then - return mw.html.create() - end - - local wrapper = mw.html.create('div') +local function HorizontalLayout(matchCards, config) + local carousel = Carousel{ + children = matchCards, + itemWidth = '12.5rem', + gap = '0.5rem', + } - for _, class in pairs(self.config.wrapperClasses) do - wrapper:addClass(class) - end + 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 - if header then - wrapper:node(header:create()) +---@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 then - return wrapper:css('text-align', 'center'):wikitext('No Results found.') + 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 - if MatchTicker.DisplayComponents.Container then - local container = MatchTicker.DisplayComponents.Container{ - config = self.config, - matches = self.matches - }:create() + 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 container then - wrapper:node(container) - end - else - Array.forEach(self.matches or {}, function(match) - wrapper:node(MatchTicker.DisplayComponents.Match{config = self.config, match = match}:create()) - end) + if self.config.variant == 'vertical' then + return Html.Div{ + classes = self.config.wrapperClasses, + children = Array.extend({header}, matchCards), + } end - return wrapper + return Html.Div{ + classes = self.config.wrapperClasses, + children = Array.extend({header}, HorizontalLayout(matchCards, self.config)), + } end return MatchTicker diff --git a/lua/wikis/commons/MatchTicker/Custom.lua b/lua/wikis/commons/MatchTicker/Custom.lua index 562111bbae3..3522091e544 100644 --- a/lua/wikis/commons/MatchTicker/Custom.lua +++ b/lua/wikis/commons/MatchTicker/Custom.lua @@ -12,23 +12,15 @@ local Logic = Lua.import('Module:Logic') local Table = Lua.import('Module:Table') local MatchTicker = Lua.import('Module:MatchTicker') +local InfoboxHeader = Lua.import('Module:Widget/Infobox/Header') local CustomMatchTicker = {} ---Entry point for display on the main page ---@param frame Frame|table|nil ----@return Html +---@return Renderable? function CustomMatchTicker.mainPage(frame) local args = Arguments.getArgs(frame) - return MatchTicker(args):query():create() -end - ----Entry point for display on the main page with the new style ----@param frame Frame|table|nil ----@return Html? -function CustomMatchTicker.newMainPage(frame) - local args = Arguments.getArgs(frame) - args.newStyle = true args.tiers = args['filterbuttons-liquipediatier'] if args.tiers == 'curated' then @@ -41,16 +33,16 @@ function CustomMatchTicker.newMainPage(frame) args.games = args['filterbuttons-game'] if args.type == 'upcoming' then - return MatchTicker(Table.merge(args, {ongoing = true, upcoming = true})):query():create():addClass('new-match-style') + return MatchTicker(Table.merge(args, {ongoing = true, upcoming = true})):query():create() elseif args.type == 'recent' then - return MatchTicker(Table.merge(args, {recent = true})):query():create():addClass('new-match-style') + return MatchTicker(Table.merge(args, {recent = true})):query():create() end end ---Entry point for display on player pages ---Upcoming and ongoing matches are now automatically displayed via the entity match ticker ---@param frame Frame|table|nil ----@return Html +---@return Renderable? function CustomMatchTicker.player(frame) local args = Arguments.getArgs(frame) args.player = args.player or mw.title.getCurrentTitle().text @@ -60,7 +52,7 @@ end ---Displays recent matches for a player or team. ---@param args table ---@param matches {recent: table?}? ----@return Html +---@return Renderable? function CustomMatchTicker.recent(args, matches) matches = matches or {} @@ -70,16 +62,8 @@ function CustomMatchTicker.recent(args, matches) args.limit = args.limit or args.recentLimit or 5 return MatchTicker(args):query(matches.recent):create( - MatchTicker.DisplayComponents.Header('Recent Matches') + InfoboxHeader{name = 'Recent Matches', displayButtons = false} ) end ----@deprecated Use CustomMatchTicker.recent() instead. This function only displays recent matches. ----@param args table ----@param matches {recent: table?}? ----@return Html -function CustomMatchTicker.participant(args, matches) - return CustomMatchTicker.recent(args, matches) -end - return CustomMatchTicker diff --git a/lua/wikis/commons/MatchTicker/DisplayComponents.lua b/lua/wikis/commons/MatchTicker/DisplayComponents.lua deleted file mode 100644 index 869655bc2ab..00000000000 --- a/lua/wikis/commons/MatchTicker/DisplayComponents.lua +++ /dev/null @@ -1,473 +0,0 @@ ---- --- @Liquipedia --- page=Module:MatchTicker/DisplayComponents --- --- Please see https://github.com/Liquipedia/Lua-Modules to contribute --- - --- Holds DisplayComponents for the MatchTicker module - -local Lua = require('Module:Lua') - -local Abbreviation = Lua.import('Module:Abbreviation') -local Array = Lua.import('Module:Array') -local Class = Lua.import('Module:Class') -local Countdown = Lua.import('Module:Countdown') -local DateExt = Lua.import('Module:Date/Ext') -local I18n = Lua.import('Module:I18n') -local Icon = Lua.import('Module:Icon') -local LeagueIcon = Lua.import('Module:LeagueIcon') -local Logic = Lua.import('Module:Logic') -local Page = Lua.import('Module:Page') -local Operator = Lua.import('Module:Operator') -local String = Lua.import('Module:StringUtils') -local Table = Lua.import('Module:Table') -local Timezone = Lua.import('Module:Timezone') -local VodLink = Lua.import('Module:VodLink') - -local HighlightConditions = Lua.import('Module:HighlightConditions') -local DisplayHelper = Lua.import('Module:MatchGroup/Display/Helper') - -local Opponent = Lua.import('Module:Opponent/Custom') -local OpponentDisplay = Lua.import('Module:OpponentDisplay/Custom') - -local VS = 'vs' -local SCORE_STATUS = 'S' -local CURRENT_PAGE = mw.title.getCurrentTitle().text -local DEFAULT_BR_MATCH_TEXT = 'Unknown Round' -local HIGHLIGHT_CLASS = 'tournament-highlighted-bg' -local WINNER_TO_BG_CLASS = { - [0] = 'recent-matches-draw', - 'recent-matches-left', - 'recent-matches-right', -} -local TOURNAMENT_DEFAULT_ICON = 'Generic_Tournament_icon.png' -local NOW = os.date('%Y-%m-%d %H:%M', os.time(os.date('!*t') --[[@as osdateparam]])) -local UTC = Timezone.getTimezoneString{timezone = 'UTC'} - ----Display class for the header of a match ticker ----@class MatchTickerHeader ----@operator call(string|number|nil): MatchTickerHeader ----@field root Html -local Header = Class.new( - function(self, text) - self.root = mw.html.create('div') - :addClass('infobox-header') - :wikitext(text) - end -) - ----@param class string? ----@return MatchTickerHeader -function Header:addClass(class) - self.root:addClass(class) - return self -end - ----@return Html -function Header:create() - return mw.html.create('div'):node(self.root) -end - ----Display class for matches shown within a match ticker ----@class MatchTickerVersus ----@operator call(table): MatchTickerVersus ----@field root Html ----@field match table -local Versus = Class.new( - function(self, match) - self.root = mw.html.create('div') - self.match = match - end -) - ----@return Html -function Versus:create() - local bestof = self.match.asGame and self:gameTitle() or self:bestof() - local scores, scores2 = self:scores() - local upperText, lowerText - if #self.match.opponents > 2 then - -- brackets always have an inherited header matchlists might lack them, - -- hence use matchIndex to generate a generic one for those cases - local headerRaw = self.match.match2bracketdata.inheritedheader - or ('Match ' .. self.match.match2bracketdata.matchIndex) - upperText = DisplayHelper.expandHeader(headerRaw)[1] - if self.match.asGame then - upperText = upperText .. ' - ' .. self:gameTitle() .. self:mapTitle() - end - elseif String.isNotEmpty(scores2) then - upperText = scores2 - lowerText = scores - elseif bestof then - upperText = scores or VS - lowerText = bestof - elseif scores then - upperText = scores - lowerText = VS - end - upperText = upperText or VS - - if not lowerText then - return self.root:wikitext(upperText) - end - - return self.root - :node(mw.html.create('div') - :addClass('versus-upper'):node(upperText) - ):node(mw.html.create('div') - :addClass('versus-lower'):wikitext('(' .. lowerText .. ')') - ) -end - ----@return string? -function Versus:bestof() - local bestof = tonumber(self.match.bestof) or 0 - if bestof > 0 then - return Abbreviation.make{text = 'Bo' .. bestof, title = 'Best of ' .. bestof} - end -end - ----@return string -function Versus:gameTitle() - if not self.match.asGameIndexes then - return '' - end - return 'Game #' .. (table.concat(self.match.asGameIndexes, '-')) -end - ----@return string -function Versus:mapTitle() - local mapName = Logic.nilIfEmpty(self.match.map) - if not mapName then - return '' - end - return ' on ' .. mapName -end - ----@return string? ----@return string? -function Versus:scores() - if self.match.date > NOW then - return - end - - local winner = tonumber(self.match.winner) - - local scores, scores2 = {}, {} - local hasSecondScore - local delimiter = ':' - - local setWinner = function(score, opponentIndex) - if winner == opponentIndex then - return '' .. score .. '' - end - return score - end - - Array.forEach(self.match.opponents or {}, function(opponent, opponentIndex) - local score = Logic.isNotEmpty(opponent.status) and opponent.status ~= SCORE_STATUS and opponent.status - or tonumber(opponent.score) or -1 - - table.insert(scores, '' .. setWinner(score ~= -1 and score or 0, opponentIndex) .. '' ) - - local score2 = tonumber((opponent.extradata or {}).score2) or 0 - table.insert(scores2, '' .. setWinner(score2, opponentIndex) .. '' ) - if score2 > 0 then - hasSecondScore = true - end - end) - - if hasSecondScore then - return table.concat(scores, delimiter), table.concat(scores2, delimiter) - end - - return table.concat(scores, delimiter) -end - ----Display class for matches shown within a match ticker ----@class MatchTickerScoreBoard ----@operator call(table): MatchTickerScoreBoard ----@field root Html ----@field match table -local ScoreBoard = Class.new( - function(self, match) - self.root = mw.html.create('tr') - self.match = match - end -) - ----@return Html -function ScoreBoard:create() - local match = self.match - local winner = tonumber(match.winner) - - return self.root - :node(self:opponent(match.opponents[1], winner == 1, true):addClass('team-left')) - :node(self:versus()) - :node(self:opponent(match.opponents[2], winner == 2):addClass('team-right')) -end - ----@param opponent table ----@param isWinner boolean ----@param flip boolean? ----@return Html -function ScoreBoard:opponent(opponent, isWinner, flip) - if Opponent.isEmpty(opponent) or Opponent.isTbd(opponent) and opponent.type ~= Opponent.literal then - opponent = Opponent.tbd(Opponent.literal) - end - - local opponentName = Opponent.toName(opponent) - if not opponentName then - mw.logObject(opponent, 'Invalid Opponent, Opponent.toName returns nil') - opponentName = '' - end - - local opponentDispaly = mw.html.create('td') - :node(OpponentDisplay.InlineOpponent{ - opponent = opponent, - teamStyle = 'short', - flip = flip, - showLink = opponentName:gsub('_', ' ') ~= CURRENT_PAGE - }) - - if isWinner then - opponentDispaly:css('font-weight', 'bold') - end - - return opponentDispaly -end - ----@return Html -function ScoreBoard:versus() - return mw.html.create('td') - :addClass('versus') - :node(Versus(self.match):create()) -end - ----Display class for matches shown within a match ticker ----@class MatchTickerDetails ----@operator call(table): MatchTickerDetails ----@field root Html ----@field hideTournament boolean ----@field isBrMatch boolean ----@field onlyHighlightOnValue string? ----@field match table -local Details = Class.new( - function(self, args) - assert(args.match, 'No Match passed to MatchTickerDetails class') - self.root = mw.html.create('tr') - self.hideTournament = args.hideTournament - self.isBrMatch = args.isBrMatch - self.onlyHighlightOnValue = args.onlyHighlightOnValue - self.match = args.match - end -) - ----@return Html -function Details:create() - local matchPageIcon = self:_matchPageIcon() - local td = mw.html.create('td') - :addClass('match-filler') - :node(mw.html.create('div') - :addClass(matchPageIcon and 'has-matchpage' or nil) - :node(self:countdown(matchPageIcon)) - :node(self:tournament()) - ) - - if not self.isBrMatch then - td:attr('colspan', 3) - end - - local highlightCondition = HighlightConditions.match or HighlightConditions.tournament - - if highlightCondition(self.match, {onlyHighlightOnValue = self.onlyHighlightOnValue}) then - self.root:addClass(HIGHLIGHT_CLASS) - end - - return self.root:node(td) -end - ----@return string? -function Details:_matchPageIcon() - local matchPage = (self.match.match2bracketdata or {}).matchpage - if Logic.isEmpty(matchPage) then return end - - local display = mw.html.create('div') - :addClass('btn-secondary btn btn-extrasmall') - :wikitext(Icon.makeIcon{iconName = 'matchpopup'}) - - return Page.makeInternalLink(tostring(display), matchPage) -end - ----@param matchPageIcon string? ----@return Html -function Details:countdown(matchPageIcon) - local match = self.match - - local dateString - if Logic.readBool(match.dateexact) then - local timestamp = DateExt.readTimestamp(match.date) + (Timezone.getOffset{timezone = match.extradata.timezoneid} or 0) - dateString = DateExt.formatTimestamp('F j, Y - H:i', timestamp) .. ' ' - .. (Timezone.getTimezoneString{timezone = match.extradata.timezoneid} or UTC) - else - dateString = mw.getContentLanguage():formatDate('F j, Y', match.date) .. UTC - end - - local countdownArgs = Table.merge(match.stream or {}, { - rawcountdown = not Logic.readBool(match.finished), - rawdatetime = Logic.readBool(match.finished), - date = dateString, - finished = match.finished - }) - - local countdownDisplay = mw.html.create('span') - :addClass('match-countdown') - :node(Countdown.create(countdownArgs)) - - if Logic.readBool(match.finished) then - local function makeVod(vod, num) - if Logic.isEmpty(vod) then - return nil - end - return VodLink.display{ - vod = vod, - gamenum = num, - } - end - - local gameVods = Array.map(Array.map(match.match2games or {}, Operator.property('vod')), makeVod) - - countdownDisplay:node(makeVod(match.vod)) - Array.forEach(gameVods, function(vod) - countdownDisplay:node(vod) - end) - end - - return mw.html.create('div') - :addClass('match-countdown-wrapper') - :node(countdownDisplay) - :node(matchPageIcon) -end - ----@return Html? -function Details:tournament() - if self.hideTournament then - return - end - - local match = self.match - - local icon = LeagueIcon.display{ - icon = Logic.emptyOr(match.icon, TOURNAMENT_DEFAULT_ICON), - iconDark = match.icondark, - link = match.pagename, - name = match.tournament, - options = {noTemplate = true}, - } - - local displayName = Logic.emptyOr( - match.tickername, - match.tournament, - match.parent:gsub('_', ' ') - ) - - return mw.html.create('div') - :addClass('tournament-flex') - :node(mw.html.create('div') - :addClass('tournament-text-flex') - :wikitext('[[' .. match.pagename .. '|' .. displayName .. ']]') - ) - :node(mw.html.create('span') - :node(icon) - ) -end - ----Display class for matches shown within a match ticker ----@class MatchTickerMatch: MatchTickerMatchInterface ----@operator call({config: MatchTickerConfig, match: table}): MatchTickerMatch ----@field root Html -local Match = Class.new( - function(self, args) - self.root = mw.html.create('table') - :addClass('wikitable wikitable-striped infobox_matches_content') - self.config = args.config - self.match = args.match - end -) - ----@return Html -function Match:create() - local matchDisplay = mw.html.create('table') - :addClass('wikitable wikitable-striped infobox_matches_content') - - local isBrMatch = #self.match.opponents ~= 2 - if isBrMatch then - matchDisplay:node(self:brMatchRow()) - else - matchDisplay - :addClass(WINNER_TO_BG_CLASS[tonumber(self.match.winner)]) - :node(self:standardMatchRow()) - end - - matchDisplay:node(self:detailsRow(isBrMatch)) - - return matchDisplay -end - ----@param inheritedHeader string? ----@return string? -function Match:_expandHeader(inheritedHeader) - if not inheritedHeader then - return - end - - local headerArray = mw.text.split(inheritedHeader, '!') - - local index = 1 - if String.isEmpty(headerArray[1]) then - index = 2 - end - - local headerInput = 'brkts-header-' .. headerArray[index] - local expandedHeader = I18n.translate('brkts-header-' .. headerArray[index], {round = headerArray[index + 1]}) - local failedExpandedHeader = '⧼' .. headerInput .. '⧽' - if Logic.isEmpty(expandedHeader) or failedExpandedHeader == expandedHeader then - return inheritedHeader - end - - return expandedHeader -end - ----@return Html -function Match:brMatchRow() - local displayText = self:_expandHeader(self.match.match2bracketdata.inheritedheader) - or self.match.match2bracketdata.sectionheader or DEFAULT_BR_MATCH_TEXT - - return mw.html.create('tr') - :addClass('versus') - :tag('td'):wikitext(displayText):done() -end - ----@return Html -function Match:standardMatchRow() - return ScoreBoard(self.match):create() -end - ----@param isBrMatch boolean ----@return Html -function Match:detailsRow(isBrMatch) - return Details{ - match = self.match, - hideTournament = self.config.hideTournament, - isBrMatch = isBrMatch, - onlyHighlightOnValue = self.config.onlyHighlightOnValue - }:create() -end - -return { - Header = Header, - Match = Match, - Details = Details, - ScoreBoard = ScoreBoard, - Versus = Versus, -} diff --git a/lua/wikis/commons/MatchTicker/DisplayComponents/Entity.lua b/lua/wikis/commons/MatchTicker/DisplayComponents/Entity.lua deleted file mode 100644 index 2342b042762..00000000000 --- a/lua/wikis/commons/MatchTicker/DisplayComponents/Entity.lua +++ /dev/null @@ -1,104 +0,0 @@ ---- --- @Liquipedia --- page=Module:MatchTicker/DisplayComponents/Entity --- --- 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 I18n = Lua.import('Module:I18n') -local MatchGroupUtil = Lua.import('Module:MatchGroup/Util/Custom') - -local Carousel = Lua.import('Module:Widget/Basic/Carousel') -local HtmlWidgets = Lua.import('Module:Widget/Html/All') -local MatchCard = Lua.import('Module:Widget/Match/Card') -local Switch = Lua.import('Module:Widget/Switch') - -local TABLE_OF_CONTENTS = '__TOC__' - ----@class EntityMatchTickerMatch: MatchTickerMatchInterface ----@operator call({config: MatchTickerConfig, match: table}): EntityMatchTickerMatch -local MatchCardEntity = Class.new( - function(self, args) - self.config = args.config - self.match = args.match - end -) - ----@return Widget -function MatchCardEntity:create() - return MatchCard{ - match = MatchGroupUtil.matchFromRecord(self.match), - hideTournament = self.config.hideTournament, - displayGameIcons = self.config.displayGameIcons, - onlyHighlightOnValue = self.config.onlyHighlightOnValue, - variant = 'vertical', - gameData = { - asGame = self.match.asGame, - gameIds = self.match.asGameIndexes, - map = self.match.map, - mapDisplayName = self.match.extradata and self.match.extradata.displayname - } - } -end - ----@class EntityMatchTickerContainer: MatchTickerContainerInterface ----@operator call({config: MatchTickerConfig, matches: table[]}): EntityMatchTickerContainer -local Container = Class.new( - function(self, args) - self.config = args.config - self.matches = args.matches - end -) - ----@return Widget? -function Container:create() - if not self.matches or #self.matches == 0 then - return nil - end - - local carousel = Carousel{ - children = Array.map(self.matches, function(match) - return MatchCardEntity{config = self.config, match = match}:create() - end), - itemWidth = '12.5rem', - gap = '0.5rem', - } - - return HtmlWidgets.Div{ - css = {['margin-bottom'] = '1rem'}, - children = { - HtmlWidgets.Div{ - classes = {'mw-heading', 'mw-heading2'}, - children = { - HtmlWidgets.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, - }, - HtmlWidgets.Div{ - css = {['margin-top'] = '1rem'}, - children = { - TABLE_OF_CONTENTS, - }, - }, - }, - } -end - -return { - Match = MatchCardEntity, - Container = Container, -} diff --git a/lua/wikis/commons/MatchTicker/DisplayComponents/New.lua b/lua/wikis/commons/MatchTicker/DisplayComponents/New.lua deleted file mode 100644 index ec953484cb4..00000000000 --- a/lua/wikis/commons/MatchTicker/DisplayComponents/New.lua +++ /dev/null @@ -1,43 +0,0 @@ ---- --- @Liquipedia --- page=Module:MatchTicker/DisplayComponents/New --- --- Please see https://github.com/Liquipedia/Lua-Modules to contribute --- - -local Lua = require('Module:Lua') - -local Class = Lua.import('Module:Class') -local MatchGroupUtil = Lua.import('Module:MatchGroup/Util/Custom') - -local MatchCard = Lua.import('Module:Widget/Match/Card') - ----@class NewMatchTickerMatch: MatchTickerMatchInterface ----@operator call({config: MatchTickerConfig, match: table}): NewMatchTickerMatch -local Match = Class.new( - function(self, args) - self.config = args.config - self.match = args.match - end -) - ----@return Widget -function Match:create() - return MatchCard{ - match = MatchGroupUtil.matchFromRecord(self.match), - hideTournament = self.config.hideTournament, - displayGameIcons = self.config.displayGameIcons, - onlyHighlightOnValue = self.config.onlyHighlightOnValue, - -- TODO: This is bad, and needs to be refactored, but it's not realistic right now, so works for now - gameData = { - asGame = self.match.asGame, - gameIds = self.match.asGameIndexes, - map = self.match.map, - mapDisplayName = self.match.extradata.displayname - } - } -end - -return { - Match = Match, -} diff --git a/lua/wikis/commons/Widget/Infobox/Header.lua b/lua/wikis/commons/Widget/Infobox/Header.lua index bb89a166491..9206e151ce0 100644 --- a/lua/wikis/commons/Widget/Infobox/Header.lua +++ b/lua/wikis/commons/Widget/Infobox/Header.lua @@ -24,10 +24,12 @@ local Link = Lua.import('Module:Widget/Basic/Link') ---@field imageText Renderable? ---@field name Renderable? ---@field subHeader Renderable? +---@field displayButtons boolean? local Header = {} -Header.defaultProps = { +local defaultProps = { name = mw.title.getCurrentTitle().text, + displayButtons = true, } ---@param props InfoboxHeaderProps @@ -56,10 +58,10 @@ end function Header._name(props) return Div{children = {Div{ classes = {'infobox-header', 'wiki-backgroundcolor-light'}, - children = { - Header._createInfoboxButtons(), - props.name, - } + children = WidgetUtil.collect( + Header._createInfoboxButtons(props), + props.name + ) }}} end @@ -138,8 +140,11 @@ function Header._makeSizedImage(imageName, size, mode) } end ----@return VNode -function Header._createInfoboxButtons() +---@return VNode? +function Header._createInfoboxButtons(props) + if not props.displayButtons then + return + end local rootFrame local currentFrame = mw.getCurrentFrame() while currentFrame ~= nil do @@ -188,4 +193,4 @@ function Header._makeImageText(text) return Div{classes = {'infobox-image-text'}, children = {text}} end -return Component.component(Header.render, Header.defaultProps) +return Component.component(Header.render, defaultProps) diff --git a/lua/wikis/commons/Widget/Match/Ticker/Container.lua b/lua/wikis/commons/Widget/Match/Ticker/Container.lua index c6bd3614e0b..43a8dd2b7a3 100644 --- a/lua/wikis/commons/Widget/Match/Ticker/Container.lua +++ b/lua/wikis/commons/Widget/Match/Ticker/Container.lua @@ -26,7 +26,7 @@ local MatchTickerContainer = Class.new(Widget) MatchTickerContainer.defaultProps = { limit = 10, module = 'MatchTicker/Custom', - fn = 'newMainPage', + fn = 'mainPage', } ---@return Widget