From 7db290fef0c20b33c5ee595187d37a31eb5bbac3 Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Tue, 7 Jan 2025 17:52:50 +0100 Subject: [PATCH 1/9] create rankings table --- app/views/results/rankings.html.erb | 12 +-- .../components/Results/Rankings/index.jsx | 97 +++++++++++++++++++ config/i18n.yml | 1 + 3 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 app/webpacker/components/Results/Rankings/index.jsx diff --git a/app/views/results/rankings.html.erb b/app/views/results/rankings.html.erb index eea83d9a46..4018626940 100644 --- a/app/views/results/rankings.html.erb +++ b/app/views/results/rankings.html.erb @@ -16,14 +16,8 @@ comp_ids = @rows.map { |r| r["competitionId"] }.uniq @competitions_by_id = Hash[Competition.where(id: comp_ids).map { |c| [c.id, c] }] %> -
-
- <% if @is_by_region %> - <%= render 'rankings_by_region_table' %> - <% else %> - <%= render 'rankings_table' %> - <% end %> -
-
+ <%= react_component("Results/Rankings", { + rows: @rows.as_json, competitionsById: @competitions_by_id.as_json({ methods: %w[country name id], includes: [] }), isAverage: @is_average, isByRegion: @is_by_region, + }) %> <% end %> diff --git a/app/webpacker/components/Results/Rankings/index.jsx b/app/webpacker/components/Results/Rankings/index.jsx new file mode 100644 index 0000000000..5a2f90f508 --- /dev/null +++ b/app/webpacker/components/Results/Rankings/index.jsx @@ -0,0 +1,97 @@ +import React, { useMemo } from 'react'; +import { Container, Table } from 'semantic-ui-react'; +import _ from 'lodash'; +import I18n from '../../../lib/i18n'; +import { formatAttemptResult } from '../../../lib/wca-live/attempts'; +import CountryFlag from '../../wca/CountryFlag'; +import { countries, events } from '../../../lib/wca-data.js.erb'; + +function ResultRow({ + result, competition, rank, isAverage, +}) { + const attempts = [result.value1, result.value2, result.value3, result.value4, result.value5]; + const bestResult = _.max(attempts); + const worstResult = _.min(attempts); + const bestResultIndex = attempts.findIndex((a) => a === bestResult); + const worstResultIndex = attempts.findIndex((a) => a === worstResult); + return ( + + {rank} + + {result.personName} + + + {formatAttemptResult(result.value, result.eventId)} + + + c.id === result.countryId).iso2} /> + + + + {' '} + {competition.name} + + {isAverage && (attempts.map((a, i) => ( + + { events.byId[result.eventId].format.expectedSolveCount === 5 + && (i === bestResultIndex || i === worstResultIndex) + ? `(${formatAttemptResult(a, result.eventId)})` : formatAttemptResult(a, result.eventId)} + + )) + )} + + ); +} + +export default function Rankings({ rows, competitionsById, isAverage }) { + const r = useMemo(() => { + let previousValue = 0; + let previousRank = 0; + return rows.map((result, index) => { + const competition = competitionsById[result.competitionId]; + const { value } = result; + const rank = value === previousValue ? previousRank : index + 1; + const tiedPrevious = rank === previousRank; + + previousValue = value; + previousRank = rank; + + return ( + + ); + }); + }, [competitionsById, isAverage, rows]); + + return ( + + + + # + {I18n.t('results.table_elements.name')} + {I18n.t('results.table_elements.result')} + {I18n.t('results.table_elements.representing')} + {I18n.t('results.table_elements.competition')} + {isAverage && ( + <> + {I18n.t('results.table_elements.solves')} + + + + + + )} + + + {r} + +
+
+ ); +} diff --git a/config/i18n.yml b/config/i18n.yml index 5f2ebbbc48..61ec2172ea 100644 --- a/config/i18n.yml +++ b/config/i18n.yml @@ -75,3 +75,4 @@ translations: - "*.time_limit.*" - "*.users.edit.*" - "*.persons.index.*" + - "*.results.table_elements.*" From e0d12caf85f12ded021f0acf24f78a0480583ad3 Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Wed, 8 Jan 2025 14:25:18 +0100 Subject: [PATCH 2/9] create seperate index for filters --- .../Results/Rankings/RankingsTable.jsx | 97 +++++++++++++++++++ .../components/Results/Rankings/index.jsx | 97 ------------------- 2 files changed, 97 insertions(+), 97 deletions(-) create mode 100644 app/webpacker/components/Results/Rankings/RankingsTable.jsx diff --git a/app/webpacker/components/Results/Rankings/RankingsTable.jsx b/app/webpacker/components/Results/Rankings/RankingsTable.jsx new file mode 100644 index 0000000000..c66f3018cb --- /dev/null +++ b/app/webpacker/components/Results/Rankings/RankingsTable.jsx @@ -0,0 +1,97 @@ +import React, { useMemo } from 'react'; +import { Container, Table } from 'semantic-ui-react'; +import _ from 'lodash'; +import I18n from '../../../lib/i18n'; +import { formatAttemptResult } from '../../../lib/wca-live/attempts'; +import CountryFlag from '../../wca/CountryFlag'; +import { countries, events } from '../../../lib/wca-data.js.erb'; + +function ResultRow({ + result, competition, rank, isAverage, +}) { + const attempts = [result.value1, result.value2, result.value3, result.value4, result.value5]; + const bestResult = _.max(attempts); + const worstResult = _.min(attempts); + const bestResultIndex = attempts.findIndex((a) => a === bestResult); + const worstResultIndex = attempts.findIndex((a) => a === worstResult); + return ( + + {rank} + + {result.personName} + + + {formatAttemptResult(result.value, result.eventId)} + + + c.id === result.countryId).iso2} /> + + + + {' '} + {competition.name} + + {isAverage && (attempts.map((a, i) => ( + + { events.byId[result.eventId].format.expectedSolveCount === 5 + && (i === bestResultIndex || i === worstResultIndex) + ? `(${formatAttemptResult(a, result.eventId)})` : formatAttemptResult(a, result.eventId)} + + )) + )} + + ); +} + +export default function RankingsTable({ rows, competitionsById, isAverage }) { + const r = useMemo(() => { + let previousValue = 0; + let previousRank = 0; + return rows.map((result, index) => { + const competition = competitionsById[result.competitionId]; + const { value } = result; + const rank = value === previousValue ? previousRank : index + 1; + const tiedPrevious = rank === previousRank; + + previousValue = value; + previousRank = rank; + + return ( + + ); + }); + }, [competitionsById, isAverage, rows]); + + return ( + + + + # + {I18n.t('results.table_elements.name')} + {I18n.t('results.table_elements.result')} + {I18n.t('results.table_elements.representing')} + {I18n.t('results.table_elements.competition')} + {isAverage && ( + <> + {I18n.t('results.table_elements.solves')} + + + + + + )} + + + {r} + +
+
+ ); +} diff --git a/app/webpacker/components/Results/Rankings/index.jsx b/app/webpacker/components/Results/Rankings/index.jsx index 5a2f90f508..e69de29bb2 100644 --- a/app/webpacker/components/Results/Rankings/index.jsx +++ b/app/webpacker/components/Results/Rankings/index.jsx @@ -1,97 +0,0 @@ -import React, { useMemo } from 'react'; -import { Container, Table } from 'semantic-ui-react'; -import _ from 'lodash'; -import I18n from '../../../lib/i18n'; -import { formatAttemptResult } from '../../../lib/wca-live/attempts'; -import CountryFlag from '../../wca/CountryFlag'; -import { countries, events } from '../../../lib/wca-data.js.erb'; - -function ResultRow({ - result, competition, rank, isAverage, -}) { - const attempts = [result.value1, result.value2, result.value3, result.value4, result.value5]; - const bestResult = _.max(attempts); - const worstResult = _.min(attempts); - const bestResultIndex = attempts.findIndex((a) => a === bestResult); - const worstResultIndex = attempts.findIndex((a) => a === worstResult); - return ( - - {rank} - - {result.personName} - - - {formatAttemptResult(result.value, result.eventId)} - - - c.id === result.countryId).iso2} /> - - - - {' '} - {competition.name} - - {isAverage && (attempts.map((a, i) => ( - - { events.byId[result.eventId].format.expectedSolveCount === 5 - && (i === bestResultIndex || i === worstResultIndex) - ? `(${formatAttemptResult(a, result.eventId)})` : formatAttemptResult(a, result.eventId)} - - )) - )} - - ); -} - -export default function Rankings({ rows, competitionsById, isAverage }) { - const r = useMemo(() => { - let previousValue = 0; - let previousRank = 0; - return rows.map((result, index) => { - const competition = competitionsById[result.competitionId]; - const { value } = result; - const rank = value === previousValue ? previousRank : index + 1; - const tiedPrevious = rank === previousRank; - - previousValue = value; - previousRank = rank; - - return ( - - ); - }); - }, [competitionsById, isAverage, rows]); - - return ( - - - - # - {I18n.t('results.table_elements.name')} - {I18n.t('results.table_elements.result')} - {I18n.t('results.table_elements.representing')} - {I18n.t('results.table_elements.competition')} - {isAverage && ( - <> - {I18n.t('results.table_elements.solves')} - - - - - - )} - - - {r} - -
-
- ); -} From 8b8c66ea41a04bae088131286d9e6174a9ca31d2 Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Wed, 8 Jan 2025 17:17:21 +0100 Subject: [PATCH 3/9] implement backend loading and filters --- app/controllers/results_controller.rb | 19 +++- app/views/results/rankings.html.erb | 20 +--- .../Results/Rankings/RankingsTable.jsx | 43 +++++---- .../components/Results/Rankings/index.jsx | 95 +++++++++++++++++++ .../components/Results/api/rankings.js | 8 ++ .../components/wca/EventSelector.jsx | 37 ++++---- app/webpacker/lib/requests/routes.js.erb | 2 + 7 files changed, 169 insertions(+), 55 deletions(-) create mode 100644 app/webpacker/components/Results/api/rankings.js diff --git a/app/controllers/results_controller.rb b/app/controllers/results_controller.rb index 48d5f85fcf..f95d4b7079 100644 --- a/app/controllers/results_controller.rb +++ b/app/controllers/results_controller.rb @@ -156,7 +156,24 @@ def rankings else flash[:danger] = t(".unknown_show") - redirect_to rankings_path + return redirect_to rankings_path + end + + @ranking_timestamp = ComputeAuxiliaryData.successful_start_date || Date.current + + respond_to do |format| + format.html + format.json do + cached_data = Rails.cache.fetch [*@cache_params, @ranking_timestamp] do + rows = DbHelper.execute_cached_query(@cache_params, @ranking_timestamp, @query) + comp_ids = rows.map { |r| r["competitionId"] }.uniq + competitions_by_id = Hash[Competition.where(id: comp_ids).map { |c| [c.id, c] }] + { + rows: rows.as_json, competitionsById: competitions_by_id.as_json({ methods: %w[country cellName id], includes: [] }), + } + end + render json: cached_data + end end end diff --git a/app/views/results/rankings.html.erb b/app/views/results/rankings.html.erb index 4018626940..1d367d83cb 100644 --- a/app/views/results/rankings.html.erb +++ b/app/views/results/rankings.html.erb @@ -1,23 +1,11 @@ <% provide(:title, t(".title")) %> -<% ranking_timestamp = ComputeAuxiliaryData.successful_start_date || Date.current %> -<% @rows = DbHelper.execute_cached_query(@cache_params, ranking_timestamp, @query) %> -

<%= yield(:title) %>

-

<%= t("results.last_updated_html", timestamp: wca_local_time(ranking_timestamp)) %>

+

<%= t("results.last_updated_html", timestamp: wca_local_time(@ranking_timestamp)) %>

<%= t('results.filters_fixes_underway') %>

-
- <%= render 'results_selector', show_rankings_options: true %> -
- <% cache [*@cache_params, ranking_timestamp, I18n.locale] do %> - <% - comp_ids = @rows.map { |r| r["competitionId"] }.uniq - @competitions_by_id = Hash[Competition.where(id: comp_ids).map { |c| [c.id, c] }] - %> - <%= react_component("Results/Rankings", { - rows: @rows.as_json, competitionsById: @competitions_by_id.as_json({ methods: %w[country name id], includes: [] }), isAverage: @is_average, isByRegion: @is_by_region, - }) %> - <% end %> + <%= react_component("Results/Rankings", { + event: params[:event_id], region: params[:region], rankingType: params[:type], year: params[:year], gender: params[:gender], + }) %>
diff --git a/app/webpacker/components/Results/Rankings/RankingsTable.jsx b/app/webpacker/components/Results/Rankings/RankingsTable.jsx index c66f3018cb..e2811ac430 100644 --- a/app/webpacker/components/Results/Rankings/RankingsTable.jsx +++ b/app/webpacker/components/Results/Rankings/RankingsTable.jsx @@ -1,10 +1,10 @@ import React, { useMemo } from 'react'; -import { Container, Table } from 'semantic-ui-react'; +import { Table } from 'semantic-ui-react'; import _ from 'lodash'; import I18n from '../../../lib/i18n'; import { formatAttemptResult } from '../../../lib/wca-live/attempts'; import CountryFlag from '../../wca/CountryFlag'; -import { countries, events } from '../../../lib/wca-data.js.erb'; +import { countries } from '../../../lib/wca-data.js.erb'; function ResultRow({ result, competition, rank, isAverage, @@ -14,6 +14,7 @@ function ResultRow({ const worstResult = _.min(attempts); const bestResultIndex = attempts.findIndex((a) => a === bestResult); const worstResultIndex = attempts.findIndex((a) => a === worstResult); + const country = countries.real.find((c) => c.id === result.countryId); return ( {rank} @@ -24,16 +25,18 @@ function ResultRow({ {formatAttemptResult(result.value, result.eventId)} - c.id === result.countryId).iso2} /> + + {' '} + {country.name} {' '} - {competition.name} + {competition.cellName} {isAverage && (attempts.map((a, i) => ( - { events.byId[result.eventId].format.expectedSolveCount === 5 + { attempts.length === 5 && (i === bestResultIndex || i === worstResultIndex) ? `(${formatAttemptResult(a, result.eventId)})` : formatAttemptResult(a, result.eventId)} @@ -70,15 +73,14 @@ export default function RankingsTable({ rows, competitionsById, isAverage }) { }, [competitionsById, isAverage, rows]); return ( - - - - # - {I18n.t('results.table_elements.name')} - {I18n.t('results.table_elements.result')} - {I18n.t('results.table_elements.representing')} - {I18n.t('results.table_elements.competition')} - {isAverage && ( +
+ + # + {I18n.t('results.table_elements.name')} + {I18n.t('results.table_elements.result')} + {I18n.t('results.table_elements.representing')} + {I18n.t('results.table_elements.competition')} + {isAverage && ( <> {I18n.t('results.table_elements.solves')} @@ -86,12 +88,11 @@ export default function RankingsTable({ rows, competitionsById, isAverage }) { - )} - - - {r} - -
-
+ )} + + + {r} + + ); } diff --git a/app/webpacker/components/Results/Rankings/index.jsx b/app/webpacker/components/Results/Rankings/index.jsx index e69de29bb2..8d99ba19f7 100644 --- a/app/webpacker/components/Results/Rankings/index.jsx +++ b/app/webpacker/components/Results/Rankings/index.jsx @@ -0,0 +1,95 @@ +import React, { useEffect, useState } from 'react'; +import { + Button, ButtonGroup, Container, Grid, Segment, +} from 'semantic-ui-react'; +import { useQuery } from '@tanstack/react-query'; +import RankingsTable from './RankingsTable'; +import WCAQueryClientProvider from '../../../lib/providers/WCAQueryClientProvider'; +import { getRankings } from '../api/rankings'; +import { EventSelector } from '../../wca/EventSelector'; +import { RegionSelector } from '../../CompetitionsOverview/CompetitionsFilters'; +import Loading from '../../Requests/Loading'; +import { rankingsUrl } from '../../../lib/requests/routes.js.erb'; + +export default function Wrapper({ + event, region, year, rankingType, gender, +}) { + return ( + + + + ); +} + +export function Rankings({ + initialEvent, initialRegion, initialYear, initialRankingType, initialGender, +}) { + const [event, setEvent] = useState(initialEvent); + const [region, setRegion] = useState(initialRegion ?? 'all'); + const [year, setYear] = useState(initialYear); + const [rankingType, setRankingType] = useState(initialRankingType); + const [gender, setGender] = useState(initialGender); + + const { data, isFetching } = useQuery({ + queryKey: ['rankings', event, region, year, rankingType], + queryFn: () => getRankings(event, rankingType, year, region), + }); + + useEffect(() => { + const queryParams = new URLSearchParams(); + + if (region !== 'all') { + queryParams.append('region', region); + } + if (year) { + queryParams.append('years', `only ${year}`); + } + if (rankingType === 'average') { + queryParams.append('gender', gender); // Replace with dynamic values if needed + } + + const newUrl = `${rankingsUrl(event, rankingType)}?${queryParams.toString()}`; + window.history.replaceState(null, '', newUrl); + }, [event, region, year, rankingType, gender]); + + if (isFetching) { + return ; + } + + return ( + + + + + setEvent(eventId)} showLabels={false} /> + setRegion(r)} /> + + + + + + + + + + + + + + + + + + + + + + + + + ); +} diff --git a/app/webpacker/components/Results/api/rankings.js b/app/webpacker/components/Results/api/rankings.js new file mode 100644 index 0000000000..f55d720a70 --- /dev/null +++ b/app/webpacker/components/Results/api/rankings.js @@ -0,0 +1,8 @@ +import { fetchJsonOrError } from '../../../lib/requests/fetchWithAuthenticityToken'; +import { rankingsUrl } from '../../../lib/requests/routes.js.erb'; + +// eslint-disable-next-line import/prefer-default-export +export async function getRankings(eventId, rankingType, year, region) { + const { data } = await fetchJsonOrError(rankingsUrl(eventId, rankingType, year, region), { headers: { Accept: 'application/json' } }); + return data; +} diff --git a/app/webpacker/components/wca/EventSelector.jsx b/app/webpacker/components/wca/EventSelector.jsx index 095540658b..6252e85917 100644 --- a/app/webpacker/components/wca/EventSelector.jsx +++ b/app/webpacker/components/wca/EventSelector.jsx @@ -22,26 +22,29 @@ export function EventSelector({ // Listing event as an argument here to indicate to developers that it's needed // eslint-disable-next-line no-unused-vars disabledText = (event) => {}, + showLabels = true, }) { return ( <> - + {showLabels && ( + + )} `; export const paymentTicketUrl = (competitionId, donationIso) => `<%= CGI.unescape(Rails.application.routes.url_helpers.api_v1_registrations_payment_ticket_path(competition_id: "${competitionId}", donation_iso: "${donationIso}")) %>`; + +export const rankingsUrl = (eventId, rankingType, year, region) => `<%= CGI.unescape(Rails.application.routes.url_helpers.rankings_path(event_id: "${eventId}", type: "${rankingType}")) %>`; From 4e1cb69b9fefa86d19f3b681ee5c7cd86b1d7854 Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Wed, 8 Jan 2025 17:21:32 +0100 Subject: [PATCH 4/9] remove segment --- app/controllers/results_controller.rb | 4 +- .../components/Results/Rankings/index.jsx | 62 +++++++++---------- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/app/controllers/results_controller.rb b/app/controllers/results_controller.rb index f95d4b7079..ee16eb2d4b 100644 --- a/app/controllers/results_controller.rb +++ b/app/controllers/results_controller.rb @@ -167,9 +167,9 @@ def rankings cached_data = Rails.cache.fetch [*@cache_params, @ranking_timestamp] do rows = DbHelper.execute_cached_query(@cache_params, @ranking_timestamp, @query) comp_ids = rows.map { |r| r["competitionId"] }.uniq - competitions_by_id = Hash[Competition.where(id: comp_ids).map { |c| [c.id, c] }] + competitions_by_id = Competition.where(id: comp_ids).to_h { |c| [c.id, c] } { - rows: rows.as_json, competitionsById: competitions_by_id.as_json({ methods: %w[country cellName id], includes: [] }), + rows: rows.as_json, competitionsById: competitions_by_id.as_json({ methods: %w[country cellName id], includes: [] }) } end render json: cached_data diff --git a/app/webpacker/components/Results/Rankings/index.jsx b/app/webpacker/components/Results/Rankings/index.jsx index 8d99ba19f7..dd290b67a9 100644 --- a/app/webpacker/components/Results/Rankings/index.jsx +++ b/app/webpacker/components/Results/Rankings/index.jsx @@ -58,38 +58,36 @@ export function Rankings({ return ( - - - - setEvent(eventId)} showLabels={false} /> - setRegion(r)} /> - - - - - - - - - - - - - - - - - - - - - - - + + + setEvent(eventId)} showLabels={false} /> + setRegion(r)} /> + + + + + + + + + + + + + + + + + + + + + + ); } From f6f0d47c57ee068ea70d90b886a5bb5715645c58 Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Fri, 10 Jan 2025 14:57:50 +0100 Subject: [PATCH 5/9] fix stylings in filters --- .../components/Results/Rankings/index.jsx | 63 +++++++------------ .../components/Results/resultsFilter.jsx | 61 ++++++++++++++++++ .../components/wca/EventSelector.jsx | 35 +++++------ 3 files changed, 101 insertions(+), 58 deletions(-) create mode 100644 app/webpacker/components/Results/resultsFilter.jsx diff --git a/app/webpacker/components/Results/Rankings/index.jsx b/app/webpacker/components/Results/Rankings/index.jsx index dd290b67a9..73afe0f77c 100644 --- a/app/webpacker/components/Results/Rankings/index.jsx +++ b/app/webpacker/components/Results/Rankings/index.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { Button, ButtonGroup, Container, Grid, Segment, } from 'semantic-ui-react'; @@ -6,10 +6,9 @@ import { useQuery } from '@tanstack/react-query'; import RankingsTable from './RankingsTable'; import WCAQueryClientProvider from '../../../lib/providers/WCAQueryClientProvider'; import { getRankings } from '../api/rankings'; -import { EventSelector } from '../../wca/EventSelector'; -import { RegionSelector } from '../../CompetitionsOverview/CompetitionsFilters'; import Loading from '../../Requests/Loading'; import { rankingsUrl } from '../../../lib/requests/routes.js.erb'; +import ResultsFilter from '../resultsFilter'; export default function Wrapper({ event, region, year, rankingType, gender, @@ -22,35 +21,45 @@ export default function Wrapper({ } export function Rankings({ - initialEvent, initialRegion, initialYear, initialRankingType, initialGender, + initialEvent, initialRegion, initialRankingType, initialGender, }) { const [event, setEvent] = useState(initialEvent); const [region, setRegion] = useState(initialRegion ?? 'all'); - const [year, setYear] = useState(initialYear); const [rankingType, setRankingType] = useState(initialRankingType); const [gender, setGender] = useState(initialGender); + const filterState = useMemo(() => ({ + event, + setEvent, + region, + setRegion, + rankingType, + setRankingType, + gender, + setGender, + }), [event, gender, rankingType, region]); + const { data, isFetching } = useQuery({ - queryKey: ['rankings', event, region, year, rankingType], - queryFn: () => getRankings(event, rankingType, year, region), + queryKey: ['rankings', event, region, rankingType], + queryFn: () => getRankings(event, rankingType, region), }); useEffect(() => { const queryParams = new URLSearchParams(); - if (region !== 'all') { + if (region !== 'world') { queryParams.append('region', region); } - if (year) { - queryParams.append('years', `only ${year}`); - } - if (rankingType === 'average') { - queryParams.append('gender', gender); // Replace with dynamic values if needed + // if (year) { + // queryParams.append('years', `only ${year}`); + // } + if (gender !== 'All') { + queryParams.append('gender', gender); } const newUrl = `${rankingsUrl(event, rankingType)}?${queryParams.toString()}`; window.history.replaceState(null, '', newUrl); - }, [event, region, year, rankingType, gender]); + }, [event, region, rankingType, gender]); if (isFetching) { return ; @@ -58,31 +67,7 @@ export function Rankings({ return ( - - - setEvent(eventId)} showLabels={false} /> - setRegion(r)} /> - - - - - - - - - - - - - - - - - - - - - + +
+ + setEvent(eventId)} + hideAllButton + hideClearButton + /> + setRegion(r)} /> + + + + + + + + + + {/* */} + {/* */} + {/* */} + {/* */} + {/* */} + + + + + + + + + + + + + + + + +
+ + ); +} diff --git a/app/webpacker/components/wca/EventSelector.jsx b/app/webpacker/components/wca/EventSelector.jsx index 6252e85917..40377338e8 100644 --- a/app/webpacker/components/wca/EventSelector.jsx +++ b/app/webpacker/components/wca/EventSelector.jsx @@ -22,29 +22,26 @@ export function EventSelector({ // Listing event as an argument here to indicate to developers that it's needed // eslint-disable-next-line no-unused-vars disabledText = (event) => {}, - showLabels = true, }) { return ( <> - {showLabels && ( - Date: Fri, 10 Jan 2025 15:31:37 +0100 Subject: [PATCH 6/9] fix gender and region not being filtered --- app/controllers/results_controller.rb | 2 +- .../Results/Rankings/RankingsTable.jsx | 7 ++++--- .../components/Results/Rankings/index.jsx | 19 +++---------------- .../components/Results/api/rankings.js | 4 ++-- .../components/Results/resultsFilter.jsx | 7 ++++++- app/webpacker/lib/requests/routes.js.erb | 15 ++++++++++++++- 6 files changed, 30 insertions(+), 24 deletions(-) diff --git a/app/controllers/results_controller.rb b/app/controllers/results_controller.rb index ee16eb2d4b..d2f98807b7 100644 --- a/app/controllers/results_controller.rb +++ b/app/controllers/results_controller.rb @@ -32,7 +32,7 @@ def rankings support_old_links! # Default params - params[:region] ||= REGION_WORLD + params[:region] ||= "all" params[:years] = YEARS_ALL # FIXME: this is disabling years filters for now params[:show] ||= SHOW_100_PERSONS params[:gender] ||= GENDER_ALL diff --git a/app/webpacker/components/Results/Rankings/RankingsTable.jsx b/app/webpacker/components/Results/Rankings/RankingsTable.jsx index e2811ac430..ac0ec51a29 100644 --- a/app/webpacker/components/Results/Rankings/RankingsTable.jsx +++ b/app/webpacker/components/Results/Rankings/RankingsTable.jsx @@ -5,6 +5,7 @@ import I18n from '../../../lib/i18n'; import { formatAttemptResult } from '../../../lib/wca-live/attempts'; import CountryFlag from '../../wca/CountryFlag'; import { countries } from '../../../lib/wca-data.js.erb'; +import { personUrl } from '../../../lib/requests/routes.js.erb'; function ResultRow({ result, competition, rank, isAverage, @@ -17,9 +18,9 @@ function ResultRow({ const country = countries.real.find((c) => c.id === result.countryId); return ( - {rank} + {rank} - {result.personName} + {result.personName} {formatAttemptResult(result.value, result.eventId)} @@ -75,7 +76,7 @@ export default function RankingsTable({ rows, competitionsById, isAverage }) { return ( - # + # {I18n.t('results.table_elements.name')} {I18n.t('results.table_elements.result')} {I18n.t('results.table_elements.representing')} diff --git a/app/webpacker/components/Results/Rankings/index.jsx b/app/webpacker/components/Results/Rankings/index.jsx index 73afe0f77c..a5a0b5dda8 100644 --- a/app/webpacker/components/Results/Rankings/index.jsx +++ b/app/webpacker/components/Results/Rankings/index.jsx @@ -40,25 +40,12 @@ export function Rankings({ }), [event, gender, rankingType, region]); const { data, isFetching } = useQuery({ - queryKey: ['rankings', event, region, rankingType], - queryFn: () => getRankings(event, rankingType, region), + queryKey: ['rankings', event, region, rankingType, gender], + queryFn: () => getRankings(event, rankingType, region, gender), }); useEffect(() => { - const queryParams = new URLSearchParams(); - - if (region !== 'world') { - queryParams.append('region', region); - } - // if (year) { - // queryParams.append('years', `only ${year}`); - // } - if (gender !== 'All') { - queryParams.append('gender', gender); - } - - const newUrl = `${rankingsUrl(event, rankingType)}?${queryParams.toString()}`; - window.history.replaceState(null, '', newUrl); + window.history.replaceState(null, '', rankingsUrl(event, rankingType, region, gender)); }, [event, region, rankingType, gender]); if (isFetching) { diff --git a/app/webpacker/components/Results/api/rankings.js b/app/webpacker/components/Results/api/rankings.js index f55d720a70..8040cd5a87 100644 --- a/app/webpacker/components/Results/api/rankings.js +++ b/app/webpacker/components/Results/api/rankings.js @@ -2,7 +2,7 @@ import { fetchJsonOrError } from '../../../lib/requests/fetchWithAuthenticityTok import { rankingsUrl } from '../../../lib/requests/routes.js.erb'; // eslint-disable-next-line import/prefer-default-export -export async function getRankings(eventId, rankingType, year, region) { - const { data } = await fetchJsonOrError(rankingsUrl(eventId, rankingType, year, region), { headers: { Accept: 'application/json' } }); +export async function getRankings(eventId, rankingType, region, gender) { + const { data } = await fetchJsonOrError(rankingsUrl(eventId, rankingType, region, gender), { headers: { Accept: 'application/json' } }); return data; } diff --git a/app/webpacker/components/Results/resultsFilter.jsx b/app/webpacker/components/Results/resultsFilter.jsx index e7e9743698..35ae0a7a97 100644 --- a/app/webpacker/components/Results/resultsFilter.jsx +++ b/app/webpacker/components/Results/resultsFilter.jsx @@ -4,11 +4,13 @@ import { } from 'semantic-ui-react'; import { EventSelector } from '../wca/EventSelector'; import { RegionSelector } from '../CompetitionsOverview/CompetitionsFilters'; +import { countries } from '../../lib/wca-data.js.erb'; export default function ResultsFilter({ filterState }) { const { event, setEvent, region, setRegion, rankingType, setRankingType, gender, setGender, } = filterState; + const regionIso2 = countries.real.find((country) => country.id === region)?.iso2 ?? region; return (
@@ -19,7 +21,10 @@ export default function ResultsFilter({ filterState }) { hideAllButton hideClearButton /> - setRegion(r)} /> + setRegion(countries.byIso2[r]?.id ?? r)} + /> diff --git a/app/webpacker/lib/requests/routes.js.erb b/app/webpacker/lib/requests/routes.js.erb index 5edc022f8f..ebd919c398 100644 --- a/app/webpacker/lib/requests/routes.js.erb +++ b/app/webpacker/lib/requests/routes.js.erb @@ -1,3 +1,4 @@ +import {countries} from "../wca-data.js.erb"; function jsonToQueryString(json) { const jsonAfterRemovingUndefinedAndNull = Object.fromEntries( Object.entries(json).filter(([key, value]) => value !== null && value !== undefined) @@ -292,4 +293,16 @@ export const bulkUpdateRegistrationUrl = `<%= CGI.unescape(Rails.application.rou export const paymentTicketUrl = (competitionId, donationIso) => `<%= CGI.unescape(Rails.application.routes.url_helpers.api_v1_registrations_payment_ticket_path(competition_id: "${competitionId}", donation_iso: "${donationIso}")) %>`; -export const rankingsUrl = (eventId, rankingType, year, region) => `<%= CGI.unescape(Rails.application.routes.url_helpers.rankings_path(event_id: "${eventId}", type: "${rankingType}")) %>`; +export const rankingsUrl = (eventId, rankingType, region, gender) => { + const url = `<%= CGI.unescape(Rails.application.routes.url_helpers.rankings_path(event_id: "${eventId}", type: "${rankingType}")) %>` + const queryParams = new URLSearchParams(); + + if (region !== 'all') { + queryParams.append('region', region); + } + + if (gender !== 'All') { + queryParams.append('gender', gender); + } + return `${url}?${queryParams.toString()}` +}; From 86e2ed8b643c0ef302a30843596aae328de7a867 Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Fri, 10 Jan 2025 15:49:52 +0100 Subject: [PATCH 7/9] added show filters --- app/views/results/rankings.html.erb | 7 ++++- .../components/Results/Rankings/index.jsx | 30 ++++++++++++------- .../components/Results/api/rankings.js | 4 +-- .../components/Results/resultsFilter.jsx | 22 ++++++++++---- app/webpacker/lib/requests/routes.js.erb | 7 ++++- 5 files changed, 49 insertions(+), 21 deletions(-) diff --git a/app/views/results/rankings.html.erb b/app/views/results/rankings.html.erb index 1d367d83cb..c9e36b7025 100644 --- a/app/views/results/rankings.html.erb +++ b/app/views/results/rankings.html.erb @@ -6,6 +6,11 @@

<%= t('results.filters_fixes_underway') %>

<%= react_component("Results/Rankings", { - event: params[:event_id], region: params[:region], rankingType: params[:type], year: params[:year], gender: params[:gender], + event: params[:event_id], + region: params[:region], + rankingType: params[:type], + year: params[:year], + gender: params[:gender], + show: params[:show], }) %> diff --git a/app/webpacker/components/Results/Rankings/index.jsx b/app/webpacker/components/Results/Rankings/index.jsx index a5a0b5dda8..d1275fc16d 100644 --- a/app/webpacker/components/Results/Rankings/index.jsx +++ b/app/webpacker/components/Results/Rankings/index.jsx @@ -1,7 +1,5 @@ import React, { useEffect, useMemo, useState } from 'react'; -import { - Button, ButtonGroup, Container, Grid, Segment, -} from 'semantic-ui-react'; +import { Container } from 'semantic-ui-react'; import { useQuery } from '@tanstack/react-query'; import RankingsTable from './RankingsTable'; import WCAQueryClientProvider from '../../../lib/providers/WCAQueryClientProvider'; @@ -11,22 +9,30 @@ import { rankingsUrl } from '../../../lib/requests/routes.js.erb'; import ResultsFilter from '../resultsFilter'; export default function Wrapper({ - event, region, year, rankingType, gender, + event, region, year, rankingType, gender, show, }) { return ( - + ); } export function Rankings({ - initialEvent, initialRegion, initialRankingType, initialGender, + initialEvent, initialRegion, initialRankingType, initialGender, initialShow, }) { const [event, setEvent] = useState(initialEvent); const [region, setRegion] = useState(initialRegion ?? 'all'); const [rankingType, setRankingType] = useState(initialRankingType); const [gender, setGender] = useState(initialGender); + const [show, setShow] = useState(initialShow ?? 'Persons'); const filterState = useMemo(() => ({ event, @@ -37,16 +43,18 @@ export function Rankings({ setRankingType, gender, setGender, - }), [event, gender, rankingType, region]); + show, + setShow, + }), [event, gender, rankingType, region, show]); const { data, isFetching } = useQuery({ - queryKey: ['rankings', event, region, rankingType, gender], - queryFn: () => getRankings(event, rankingType, region, gender), + queryKey: ['rankings', event, region, rankingType, gender, show], + queryFn: () => getRankings(event, rankingType, region, gender, show), }); useEffect(() => { - window.history.replaceState(null, '', rankingsUrl(event, rankingType, region, gender)); - }, [event, region, rankingType, gender]); + window.history.replaceState(null, '', rankingsUrl(event, rankingType, region, gender, show)); + }, [event, region, rankingType, gender, show]); if (isFetching) { return ; diff --git a/app/webpacker/components/Results/api/rankings.js b/app/webpacker/components/Results/api/rankings.js index 8040cd5a87..0ff4957cc7 100644 --- a/app/webpacker/components/Results/api/rankings.js +++ b/app/webpacker/components/Results/api/rankings.js @@ -2,7 +2,7 @@ import { fetchJsonOrError } from '../../../lib/requests/fetchWithAuthenticityTok import { rankingsUrl } from '../../../lib/requests/routes.js.erb'; // eslint-disable-next-line import/prefer-default-export -export async function getRankings(eventId, rankingType, region, gender) { - const { data } = await fetchJsonOrError(rankingsUrl(eventId, rankingType, region, gender), { headers: { Accept: 'application/json' } }); +export async function getRankings(eventId, rankingType, region, gender, show) { + const { data } = await fetchJsonOrError(rankingsUrl(eventId, rankingType, region, gender, show), { headers: { Accept: 'application/json' } }); return data; } diff --git a/app/webpacker/components/Results/resultsFilter.jsx b/app/webpacker/components/Results/resultsFilter.jsx index 35ae0a7a97..d61cc7a5de 100644 --- a/app/webpacker/components/Results/resultsFilter.jsx +++ b/app/webpacker/components/Results/resultsFilter.jsx @@ -8,7 +8,16 @@ import { countries } from '../../lib/wca-data.js.erb'; export default function ResultsFilter({ filterState }) { const { - event, setEvent, region, setRegion, rankingType, setRankingType, gender, setGender, + event, + setEvent, + region, + setRegion, + rankingType, + setRankingType, + gender, + setGender, + show, + setShow, } = filterState; const regionIso2 = countries.real.find((country) => country.id === region)?.iso2 ?? region; return ( @@ -29,7 +38,7 @@ export default function ResultsFilter({ filterState }) { - + @@ -54,9 +63,10 @@ export default function ResultsFilter({ filterState }) { - - - + + + + diff --git a/app/webpacker/lib/requests/routes.js.erb b/app/webpacker/lib/requests/routes.js.erb index ebd919c398..c66eccab1d 100644 --- a/app/webpacker/lib/requests/routes.js.erb +++ b/app/webpacker/lib/requests/routes.js.erb @@ -293,7 +293,7 @@ export const bulkUpdateRegistrationUrl = `<%= CGI.unescape(Rails.application.rou export const paymentTicketUrl = (competitionId, donationIso) => `<%= CGI.unescape(Rails.application.routes.url_helpers.api_v1_registrations_payment_ticket_path(competition_id: "${competitionId}", donation_iso: "${donationIso}")) %>`; -export const rankingsUrl = (eventId, rankingType, region, gender) => { +export const rankingsUrl = (eventId, rankingType, region, gender, show) => { const url = `<%= CGI.unescape(Rails.application.routes.url_helpers.rankings_path(event_id: "${eventId}", type: "${rankingType}")) %>` const queryParams = new URLSearchParams(); @@ -304,5 +304,10 @@ export const rankingsUrl = (eventId, rankingType, region, gender) => { if (gender !== 'All') { queryParams.append('gender', gender); } + + if (show !== 'Persons') { + queryParams.append('show', show); + } + return `${url}?${queryParams.toString()}` }; From 6f37b6da6f9c0c754ff77137b34504bfab6fd1ba Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Fri, 10 Jan 2025 16:33:50 +0100 Subject: [PATCH 8/9] implement by regions table --- app/controllers/results_controller.rb | 44 ++++++++++++++- app/helpers/results_helper.rb | 39 -------------- .../Results/Rankings/RankingsTable.jsx | 54 ++++++++++++++----- .../components/Results/Rankings/index.jsx | 1 + .../components/Results/resultsFilter.jsx | 17 ++++-- app/webpacker/lib/requests/routes.js.erb | 6 +-- 6 files changed, 99 insertions(+), 62 deletions(-) diff --git a/app/controllers/results_controller.rb b/app/controllers/results_controller.rb index d2f98807b7..5001a3e778 100644 --- a/app/controllers/results_controller.rb +++ b/app/controllers/results_controller.rb @@ -32,7 +32,7 @@ def rankings support_old_links! # Default params - params[:region] ||= "all" + params[:region] ||= REGION_WORLD params[:years] = YEARS_ALL # FIXME: this is disabling years filters for now params[:show] ||= SHOW_100_PERSONS params[:gender] ||= GENDER_ALL @@ -167,6 +167,9 @@ def rankings cached_data = Rails.cache.fetch [*@cache_params, @ranking_timestamp] do rows = DbHelper.execute_cached_query(@cache_params, @ranking_timestamp, @query) comp_ids = rows.map { |r| r["competitionId"] }.uniq + if @is_by_region + rows = compute_rankings_by_region(rows, @continent, @country) + end competitions_by_id = Competition.where(id: comp_ids).to_h { |c| [c.id, c] } { rows: rows.as_json, competitionsById: competitions_by_id.as_json({ methods: %w[country cellName id], includes: [] }) @@ -373,4 +376,43 @@ def records params[:show] = nil end end + + private def compute_rankings_by_region(rows, continent, country) + if rows.empty? + return [[], 0, 0] + end + best_value_of_world = rows.first["value"] + best_values_of_continents = {} + best_values_of_countries = {} + world_rows = [] + continents_rows = [] + countries_rows = [] + rows.each do |row| + result = LightResult.new(row) + value = row["value"] + + world_rows << row if value == best_value_of_world + + if best_values_of_continents[result.country.continent.id].nil? || value == best_values_of_continents[result.country.continent.id] + best_values_of_continents[result.country.continent.id] = value + + if (country.present? && country.continent.id == result.country.continent.id) || (continent.present? && continent.id == result.country.continent.id) || params[:region] == "world" + continents_rows << row + end + end + + if best_values_of_countries[result.country.id].nil? || value == best_values_of_countries[result.country.id] + best_values_of_countries[result.country.id] = value + + if (country.present? && country.id == result.country.id) || params[:region] == "world" + countries_rows << row + end + end + end + + first_continent_index = world_rows.length + first_country_index = first_continent_index + continents_rows.length + rows_to_display = world_rows + continents_rows + countries_rows + [rows_to_display, first_continent_index, first_country_index] + end end diff --git a/app/helpers/results_helper.rb b/app/helpers/results_helper.rb index dbdc746e87..44f6f75705 100644 --- a/app/helpers/results_helper.rb +++ b/app/helpers/results_helper.rb @@ -29,45 +29,6 @@ def historical_pb_markers(results) end end - def compute_rankings_by_region(rows, continent, country) - if rows.empty? - return [[], 0, 0] - end - best_value_of_world = rows.first["value"] - best_values_of_continents = {} - best_values_of_countries = {} - world_rows = [] - continents_rows = [] - countries_rows = [] - rows.each do |row| - result = LightResult.new(row) - value = row["value"] - - world_rows << row if value == best_value_of_world - - if best_values_of_continents[result.country.continent.id].nil? || value == best_values_of_continents[result.country.continent.id] - best_values_of_continents[result.country.continent.id] = value - - if (country.present? && country.continent.id == result.country.continent.id) || (continent.present? && continent.id == result.country.continent.id) || params[:region] == "world" - continents_rows << row - end - end - - if best_values_of_countries[result.country.id].nil? || value == best_values_of_countries[result.country.id] - best_values_of_countries[result.country.id] = value - - if (country.present? && country.id == result.country.id) || params[:region] == "world" - countries_rows << row - end - end - end - - first_continent_index = world_rows.length - first_country_index = first_continent_index + continents_rows.length - rows_to_display = world_rows + continents_rows + countries_rows - [rows_to_display, first_continent_index, first_country_index] - end - def compute_slim_or_separate_records(rows) single_rows = [] average_rows = [] diff --git a/app/webpacker/components/Results/Rankings/RankingsTable.jsx b/app/webpacker/components/Results/Rankings/RankingsTable.jsx index ac0ec51a29..1bafa38cea 100644 --- a/app/webpacker/components/Results/Rankings/RankingsTable.jsx +++ b/app/webpacker/components/Results/Rankings/RankingsTable.jsx @@ -4,32 +4,39 @@ import _ from 'lodash'; import I18n from '../../../lib/i18n'; import { formatAttemptResult } from '../../../lib/wca-live/attempts'; import CountryFlag from '../../wca/CountryFlag'; -import { countries } from '../../../lib/wca-data.js.erb'; +import { continents, countries } from '../../../lib/wca-data.js.erb'; import { personUrl } from '../../../lib/requests/routes.js.erb'; +function CountryCell({ country }) { + return ( + + {country.iso2 && } + {' '} + {country.name} + + ); +} + function ResultRow({ - result, competition, rank, isAverage, + result, competition, rank, isAverage, show, country, }) { const attempts = [result.value1, result.value2, result.value3, result.value4, result.value5]; const bestResult = _.max(attempts); const worstResult = _.min(attempts); const bestResultIndex = attempts.findIndex((a) => a === bestResult); const worstResultIndex = attempts.findIndex((a) => a === worstResult); - const country = countries.real.find((c) => c.id === result.countryId); return ( - {rank} + {show === 'by region' ? + : {rank} } {result.personName} {formatAttemptResult(result.value, result.eventId)} - - - {' '} - {country.name} - + {show !== 'by region' + && } {' '} @@ -47,39 +54,58 @@ function ResultRow({ ); } -export default function RankingsTable({ rows, competitionsById, isAverage }) { +export default function RankingsTable({ + rows, competitionsById, isAverage, show, +}) { const r = useMemo(() => { + let rowsToMap = rows; + let firstContinentIndex = 0; + let firstCountryIndex = 0; + if (show === 'by region') { + [rowsToMap, firstContinentIndex, firstCountryIndex] = rows; + } + let previousValue = 0; let previousRank = 0; - return rows.map((result, index) => { + return rowsToMap.map((result, index) => { const competition = competitionsById[result.competitionId]; const { value } = result; const rank = value === previousValue ? previousRank : index + 1; const tiedPrevious = rank === previousRank; + let country = countries.real.find((c) => c.id === result.countryId); + + if (index < firstContinentIndex) { + country = { name: I18n.t('results.table_elements.world') }; + } else if (index >= firstContinentIndex && index < firstCountryIndex) { + country = continents.real.find((c) => c.id === country.continentId); + } previousValue = value; previousRank = rank; return ( ); }); - }, [competitionsById, isAverage, rows]); + }, [competitionsById, isAverage, rows, show]); return (
- # + {show !== 'by region' ? # + : {I18n.t('results.table_elements.region')}} {I18n.t('results.table_elements.name')} {I18n.t('results.table_elements.result')} - {I18n.t('results.table_elements.representing')} + {show !== 'by region' && {I18n.t('results.table_elements.representing')}} {I18n.t('results.table_elements.competition')} {isAverage && ( <> diff --git a/app/webpacker/components/Results/Rankings/index.jsx b/app/webpacker/components/Results/Rankings/index.jsx index d1275fc16d..1454b7f697 100644 --- a/app/webpacker/components/Results/Rankings/index.jsx +++ b/app/webpacker/components/Results/Rankings/index.jsx @@ -67,6 +67,7 @@ export function Rankings({ competitionsById={data.competitionsById} isAverage={rankingType === 'average'} rows={data.rows} + show={show} /> ); diff --git a/app/webpacker/components/Results/resultsFilter.jsx b/app/webpacker/components/Results/resultsFilter.jsx index d61cc7a5de..00045f3060 100644 --- a/app/webpacker/components/Results/resultsFilter.jsx +++ b/app/webpacker/components/Results/resultsFilter.jsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import { Button, ButtonGroup, Form, Segment, } from 'semantic-ui-react'; @@ -19,7 +19,16 @@ export default function ResultsFilter({ filterState }) { show, setShow, } = filterState; - const regionIso2 = countries.real.find((country) => country.id === region)?.iso2 ?? region; + const regionIso2 = useMemo(() => { + if (region === 'world') { + return 'all'; + } + const iso2 = countries.real.find((country) => country.id === region)?.iso2; + if (iso2) { + return iso2; + } + return region; + }, [region]); return ( @@ -64,8 +73,8 @@ export default function ResultsFilter({ filterState }) { - - + + diff --git a/app/webpacker/lib/requests/routes.js.erb b/app/webpacker/lib/requests/routes.js.erb index c66eccab1d..e0cb28af65 100644 --- a/app/webpacker/lib/requests/routes.js.erb +++ b/app/webpacker/lib/requests/routes.js.erb @@ -297,15 +297,13 @@ export const rankingsUrl = (eventId, rankingType, region, gender, show) => { const url = `<%= CGI.unescape(Rails.application.routes.url_helpers.rankings_path(event_id: "${eventId}", type: "${rankingType}")) %>` const queryParams = new URLSearchParams(); - if (region !== 'all') { - queryParams.append('region', region); - } + queryParams.append('region', region); if (gender !== 'All') { queryParams.append('gender', gender); } - if (show !== 'Persons') { + if (show !== '100 persons') { queryParams.append('show', show); } From 985887cecea7342824b1ef2105f7e5822f2774b3 Mon Sep 17 00:00:00 2001 From: FinnIckler Date: Fri, 10 Jan 2025 16:40:32 +0100 Subject: [PATCH 9/9] add i18n to resultsfilter --- .../components/Results/resultsFilter.jsx | 23 ++++++++++--------- config/i18n.yml | 1 + 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/app/webpacker/components/Results/resultsFilter.jsx b/app/webpacker/components/Results/resultsFilter.jsx index 00045f3060..409d55803d 100644 --- a/app/webpacker/components/Results/resultsFilter.jsx +++ b/app/webpacker/components/Results/resultsFilter.jsx @@ -5,6 +5,7 @@ import { import { EventSelector } from '../wca/EventSelector'; import { RegionSelector } from '../CompetitionsOverview/CompetitionsFilters'; import { countries } from '../../lib/wca-data.js.erb'; +import I18n from '../../lib/i18n'; export default function ResultsFilter({ filterState }) { const { @@ -46,15 +47,15 @@ export default function ResultsFilter({ filterState }) { - + - + {/* */} @@ -63,19 +64,19 @@ export default function ResultsFilter({ filterState }) { {/* */} {/* */} - + - - - + + + - + - - - + + + diff --git a/config/i18n.yml b/config/i18n.yml index 61ec2172ea..4425a6670a 100644 --- a/config/i18n.yml +++ b/config/i18n.yml @@ -76,3 +76,4 @@ translations: - "*.users.edit.*" - "*.persons.index.*" - "*.results.table_elements.*" + - "*.results.selector_elements.*"