@mdn/fred 1.3.2 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/build/render.js +5 -2
  3. package/components/baseline-indicator/server.js +3 -3
  4. package/components/compat-table/constants.js +0 -3
  5. package/components/compat-table/element.js +3 -6
  6. package/components/content-feedback/element.js +2 -5
  7. package/components/content-section/server.css +1 -1
  8. package/components/contributor-list/element.css +3 -2
  9. package/components/interactive-example/element.js +1 -1
  10. package/components/menu/constants.js +6 -4
  11. package/components/menu/server.js +142 -89
  12. package/components/placement-bottom/element.js +2 -2
  13. package/components/placement-hp-main/element.js +2 -2
  14. package/components/placement-no/element.js +1 -1
  15. package/components/placement-note/element.js +1 -1
  16. package/components/placement-sidebar/element.js +4 -4
  17. package/components/placement-top/element.js +5 -5
  18. package/components/play-controller/element.js +1 -0
  19. package/components/playground/element.js +2 -1
  20. package/components/recent-contributions/server.js +1 -1
  21. package/components/scrim-inline/element.js +2 -2
  22. package/l10n/en-US.ftl +5 -2
  23. package/out/service-worker.js +1 -1
  24. package/out/service-worker.js.map +1 -1
  25. package/out/static/client/{2308.69b80ae939b202ae.js → 2308.0ccf49974d71523d.js} +6 -6
  26. package/out/static/client/2308.0ccf49974d71523d.js.map +1 -0
  27. package/out/static/client/{2319.daf8150c3dd00fb4.js → 2319.0a40303319ac6a6e.js} +4 -4
  28. package/out/static/client/{2319.daf8150c3dd00fb4.js.map → 2319.0a40303319ac6a6e.js.map} +1 -1
  29. package/out/static/client/{288.ba983e8acda3116e.js → 288.684edb44f92a470c.js} +2 -2
  30. package/out/static/client/288.684edb44f92a470c.js.map +1 -0
  31. package/out/static/client/{3132.ec59f4619872c415.js → 3132.5ae6f61e3998aef1.js} +6 -6
  32. package/out/static/client/{3132.ec59f4619872c415.js.map → 3132.5ae6f61e3998aef1.js.map} +1 -1
  33. package/out/static/client/{3733.60667669ab613e1f.js → 3733.94bd76664194890b.js} +5 -5
  34. package/out/static/client/{3733.60667669ab613e1f.js.map → 3733.94bd76664194890b.js.map} +1 -1
  35. package/out/static/client/{451.cd85e2808f388a00.js → 451.fb2679190b3266e1.js} +2 -2
  36. package/out/static/client/{451.cd85e2808f388a00.js.map → 451.fb2679190b3266e1.js.map} +1 -1
  37. package/out/static/client/{603.8cdd963a9e248a75.js → 603.8670965b0722be3a.js} +5 -5
  38. package/out/static/client/603.8670965b0722be3a.js.map +1 -0
  39. package/out/static/client/{6040.80c6f96d0152ac99.js → 6040.13e672aff6757a47.js} +2 -2
  40. package/out/static/client/{6040.80c6f96d0152ac99.js.map → 6040.13e672aff6757a47.js.map} +1 -1
  41. package/out/static/client/{6536.faff8f026d145aad.js → 6536.ecdcc4458cbd0504.js} +2 -2
  42. package/out/static/client/6536.ecdcc4458cbd0504.js.map +1 -0
  43. package/out/static/client/{8036.9065b84aac240378.js → 8036.6e177b49bfa9b7c4.js} +3 -3
  44. package/out/static/client/{8036.9065b84aac240378.js.map → 8036.6e177b49bfa9b7c4.js.map} +1 -1
  45. package/out/static/client/{8607.266d488ae06c2279.js → 8607.464a88660a040f97.js} +4 -4
  46. package/out/static/client/{8607.266d488ae06c2279.js.map → 8607.464a88660a040f97.js.map} +1 -1
  47. package/out/static/client/{8797.46790b4359b5d1cb.js → 8797.f5880b5ee2659039.js} +2 -2
  48. package/out/static/client/{8797.46790b4359b5d1cb.js.map → 8797.f5880b5ee2659039.js.map} +1 -1
  49. package/out/static/client/{9784.214845ec6d3b77e3.js → 9784.3f8ca449f7d36818.js} +5 -5
  50. package/out/static/client/9784.3f8ca449f7d36818.js.map +1 -0
  51. package/out/static/client/{index.b9d9ebb034538241.js → index.881056601848b5c3.js} +15 -12
  52. package/out/static/client/{index.b9d9ebb034538241.js.map → index.881056601848b5c3.js.map} +1 -1
  53. package/out/static/client/{runtime.cc9114c9e108157f.js → runtime.63305f0549b94aae.js} +2 -2
  54. package/out/static/client/{runtime.cc9114c9e108157f.js.map → runtime.63305f0549b94aae.js.map} +1 -1
  55. package/out/static/client/stats.json +136 -136
  56. package/out/static/client/{styles-content-section.e0bbadd0c4bc857d.css → styles-content-section.2f0727a030110fc9.css} +2 -2
  57. package/out/static/client/{styles-content-section.e0bbadd0c4bc857d.css.map → styles-content-section.2f0727a030110fc9.css.map} +1 -1
  58. package/out/static/legacy/{1289.71de08e7375881e1.js → 1289.61e3f0658b3b42f6.js} +2 -2
  59. package/out/static/legacy/{1289.71de08e7375881e1.js.map → 1289.61e3f0658b3b42f6.js.map} +1 -1
  60. package/out/static/legacy/{2090.29b77e88722868ff.js → 2090.5996133ea26ddd0a.js} +2 -2
  61. package/out/static/legacy/{2090.29b77e88722868ff.js.map → 2090.5996133ea26ddd0a.js.map} +1 -1
  62. package/out/static/legacy/2235.b99812e73c08ee51.js +2 -0
  63. package/out/static/legacy/{2235.c0e6904b64ea18fe.js.map → 2235.b99812e73c08ee51.js.map} +1 -1
  64. package/out/static/legacy/{2465.676e7f0b0f9f9d85.js → 2465.041a63f06f35163c.js} +2 -2
  65. package/out/static/legacy/{2465.676e7f0b0f9f9d85.js.map → 2465.041a63f06f35163c.js.map} +1 -1
  66. package/out/static/legacy/{3172.0c1b9258951929cc.js → 3172.cf1b8a6dcea5d789.js} +2 -2
  67. package/out/static/legacy/{3172.0c1b9258951929cc.js.map → 3172.cf1b8a6dcea5d789.js.map} +1 -1
  68. package/out/static/legacy/{4968.62ad4db7389e93ad.js → 4968.e73f2795a9ca1639.js} +2 -2
  69. package/out/static/legacy/{4968.62ad4db7389e93ad.js.map → 4968.e73f2795a9ca1639.js.map} +1 -1
  70. package/out/static/legacy/{6364.d8cdb19b92fe6dc1.js → 6364.4c2629a5287ded91.js} +2 -2
  71. package/out/static/legacy/{6364.d8cdb19b92fe6dc1.js.map → 6364.4c2629a5287ded91.js.map} +1 -1
  72. package/out/static/legacy/{652.3c82fa8fa13a87b2.js → 652.d7ab50c73c693880.js} +2 -2
  73. package/out/static/legacy/{652.3c82fa8fa13a87b2.js.map → 652.d7ab50c73c693880.js.map} +1 -1
  74. package/out/static/legacy/7510.faa07a788cad6fc7.js +2 -0
  75. package/out/static/legacy/{7510.d1e3773463ecc314.js.map → 7510.faa07a788cad6fc7.js.map} +1 -1
  76. package/out/static/legacy/{7827.838d9e673c56e936.js → 7827.efd03057dbb6c884.js} +2 -2
  77. package/out/static/legacy/{7827.838d9e673c56e936.js.map → 7827.efd03057dbb6c884.js.map} +1 -1
  78. package/out/static/legacy/8183.26862a110c641391.js +2 -0
  79. package/out/static/legacy/8183.26862a110c641391.js.map +1 -0
  80. package/out/static/legacy/{8333.c00c132d6919165b.js → 8333.e5001734aea048b6.js} +2 -2
  81. package/out/static/legacy/{8333.c00c132d6919165b.js.map → 8333.e5001734aea048b6.js.map} +1 -1
  82. package/out/static/legacy/{8504.157e4a48938fdac7.js → 8504.d5df18204dd2b2ef.js} +2 -2
  83. package/out/static/legacy/{8504.157e4a48938fdac7.js.map → 8504.d5df18204dd2b2ef.js.map} +1 -1
  84. package/out/static/legacy/8856.0efcde0ace698d4a.js.map +1 -1
  85. package/out/static/legacy/{9221.64e46eedebf47df8.js → 9221.3cee7be6339f4234.js} +3 -3
  86. package/out/static/legacy/{9221.64e46eedebf47df8.js.map → 9221.3cee7be6339f4234.js.map} +1 -1
  87. package/out/static/legacy/asset-manifest.json +20 -20
  88. package/out/static/legacy/{index.e4ab469094607d20.html → index.17917fe951b4bbfe.html} +1 -1
  89. package/out/static/legacy/index.81f776c8a95b5c6c.js +6 -0
  90. package/out/static/legacy/{index.3504df1c7b6a1b29.js.LICENSE.txt → index.81f776c8a95b5c6c.js.LICENSE.txt} +1 -1
  91. package/out/static/legacy/index.81f776c8a95b5c6c.js.map +1 -0
  92. package/out/static/legacy/stats.json +20 -20
  93. package/out/static/legacy/yari.255b3bc6ef8a8b24.js +7 -0
  94. package/out/static/legacy/{yari.7a85003b4add8414.js.LICENSE.txt → yari.255b3bc6ef8a8b24.js.LICENSE.txt} +1 -1
  95. package/out/static/legacy/yari.255b3bc6ef8a8b24.js.map +1 -0
  96. package/out/static/ssr/index.js +153 -161
  97. package/out/static/ssr/index.js.map +1 -1
  98. package/out/static/ssr/stats.json +4 -4
  99. package/package.json +14 -14
  100. package/utils/glean.js +3 -8
  101. package/out/static/client/2308.69b80ae939b202ae.js.map +0 -1
  102. package/out/static/client/288.ba983e8acda3116e.js.map +0 -1
  103. package/out/static/client/603.8cdd963a9e248a75.js.map +0 -1
  104. package/out/static/client/6536.faff8f026d145aad.js.map +0 -1
  105. package/out/static/client/9784.214845ec6d3b77e3.js.map +0 -1
  106. package/out/static/legacy/2235.c0e6904b64ea18fe.js +0 -2
  107. package/out/static/legacy/7510.d1e3773463ecc314.js +0 -2
  108. package/out/static/legacy/8183.d3c84d03c477eac6.js +0 -2
  109. package/out/static/legacy/8183.d3c84d03c477eac6.js.map +0 -1
  110. package/out/static/legacy/index.3504df1c7b6a1b29.js +0 -6
  111. package/out/static/legacy/index.3504df1c7b6a1b29.js.map +0 -1
  112. package/out/static/legacy/yari.7a85003b4add8414.js +0 -7
  113. package/out/static/legacy/yari.7a85003b4add8414.js.map +0 -1
  114. /package/out/static/client/{2319.daf8150c3dd00fb4.js.LICENSE.txt → 2319.0a40303319ac6a6e.js.LICENSE.txt} +0 -0
  115. /package/out/static/client/{603.8cdd963a9e248a75.js.LICENSE.txt → 603.8670965b0722be3a.js.LICENSE.txt} +0 -0
  116. /package/out/static/client/{9784.214845ec6d3b77e3.js.LICENSE.txt → 9784.3f8ca449f7d36818.js.LICENSE.txt} +0 -0
  117. /package/out/static/client/{index.b9d9ebb034538241.js.LICENSE.txt → index.881056601848b5c3.js.LICENSE.txt} +0 -0
  118. /package/out/static/legacy/{9221.64e46eedebf47df8.js.LICENSE.txt → 9221.3cee7be6339f4234.js.LICENSE.txt} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"7510.d1e3773463ecc314.js","sources":["webpack://@mdn/fred/./node_modules/@mdn/yari/client/src/translations/differences/index.tsx","webpack://@mdn/fred/./node_modules/@mdn/yari/client/src/translations/missing/index.tsx","webpack://@mdn/fred/./node_modules/@mdn/yari/client/src/translations/dashboard/index.tsx","webpack://@mdn/fred/./node_modules/@mdn/yari/client/src/translations/index.tsx","webpack://@mdn/fred/./node_modules/@mdn/yari/client/src/ui/molecules/paginator/index.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n createSearchParams,\n Link,\n useSearchParams,\n useNavigate,\n} from \"react-router-dom\";\nimport useSWR from \"swr\";\nimport dayjs from \"dayjs\";\nimport relativeTime from \"dayjs/plugin/relativeTime\";\n\nimport \"./index.scss\";\n\nimport { MainContentContainer } from \"../../ui/atoms/page-content\";\nimport { Paginator } from \"../../ui/molecules/paginator\";\nimport { useLocale } from \"../../hooks\";\n\ndayjs.extend(relativeTime);\n\ninterface DocumentPopularity {\n value: number;\n ranking: number;\n parentValue: number;\n parentRanking: number;\n}\n\ntype CountByType = { [key: string]: number };\n\ninterface DocumentDifferences {\n countByType: CountByType;\n total: number;\n}\n\ninterface DocumentEdits {\n modified: string;\n parentModified: string;\n commitURL: string;\n parentCommitURL: string;\n sourceCommitsBehindCount?: number;\n sourceCommitURL?: string;\n}\n\ninterface Document {\n mdn_url: string;\n edits: DocumentEdits;\n title: string;\n popularity: DocumentPopularity;\n differences: DocumentDifferences;\n}\n\ninterface Counts {\n found: number;\n total: number;\n pages: number;\n noParents: number;\n cacheMisses: number;\n}\n\ninterface Times {\n took: number;\n}\n\ninterface FlawLevel {\n name: string;\n level: string;\n ignored: boolean;\n}\n\ninterface Data {\n counts: Counts;\n documents: Document[];\n times: Times;\n flawLevels: FlawLevel[];\n}\n\ninterface LocaleStorageData {\n lastLoadTime?: number;\n defaultSort?: string;\n defaultSortReverse?: string;\n}\n\ninterface StorageData {\n [locale: string]: LocaleStorageData;\n}\n\nconst LOCALSTORAGE_KEY = \"translations-dashboard-differences\";\n\nfunction saveStorage(locale: string, data: LocaleStorageData) {\n try {\n const stored = JSON.parse(\n localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\"\n ) as StorageData;\n stored[locale] = Object.assign({}, stored[locale] || {}, data);\n localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(stored));\n } catch (err) {\n console.warn(\"Unable to save to localStorage\", err);\n }\n}\n\nfunction getStorage(locale: string): LocaleStorageData | null {\n try {\n const stored = JSON.parse(localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\");\n if (stored) {\n return stored[locale] as LocaleStorageData;\n }\n } catch (err) {\n console.warn(\"Unable to retrieve from localStorage\", err);\n }\n return null;\n}\n\nexport function TranslationDifferences() {\n const locale = useLocale();\n const [searchParams] = useSearchParams();\n const navigate = useNavigate();\n\n const [lastData, setLastData] = React.useState<Data | null>(null);\n\n React.useEffect(() => {\n if (locale.toLowerCase() === \"en-us\") {\n navigate(`/${locale}/_translations`);\n }\n }, [locale, navigate]);\n\n React.useEffect(() => {\n let title = \"All translations\";\n if (locale.toLowerCase() !== \"en-us\") {\n title += ` for ${locale}`;\n }\n if (lastData) {\n title = `(${lastData.counts.found.toLocaleString()} found) ${title}`;\n }\n document.title = title;\n }, [lastData, locale]);\n\n const { data, error, isValidating } = useSWR<Data, Error>(\n locale.toLowerCase() !== \"en-us\"\n ? `/_translations/differences/?locale=${locale}`\n : null,\n async (url) => {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`${response.status} (${await response.text()})`);\n }\n if (\n !(response.headers.get(\"content-type\") || \"\").includes(\n \"application/json\"\n )\n ) {\n throw new Error(\n `Response is not JSON (${response.headers.get(\"content-type\")})`\n );\n }\n return response.json();\n },\n {\n revalidateOnFocus: false,\n }\n );\n\n // Use this to be able to figure out how long the XHR takes when there's no cache\n const startTime = React.useRef<Date>();\n React.useEffect(() => {\n if (locale) {\n if (!data) {\n startTime.current = new Date();\n } else {\n if (\n data.counts.cacheMisses > 0 &&\n data.counts.cacheMisses === data.counts.total &&\n startTime.current\n ) {\n const lastLoadTime =\n new Date().getTime() - startTime.current.getTime();\n saveStorage(locale, { lastLoadTime });\n }\n }\n }\n }, [locale, data]);\n\n React.useEffect(() => {\n if (data) {\n setLastData(data);\n }\n }, [data]);\n\n const lastStorageData = getStorage(locale);\n const defaultSort = lastStorageData?.defaultSort || \"modified\";\n const defaultSortReverse = lastStorageData?.defaultSortReverse || \"false\";\n const sort = searchParams.get(\"sort\") || defaultSort;\n const sortReverse = JSON.parse(\n searchParams.get(\"sortReverse\") || defaultSortReverse\n );\n\n React.useEffect(() => {\n saveStorage(\n locale,\n Object.assign({}, lastStorageData, {\n defaultSort: sort,\n defaultSortReverse: sortReverse,\n })\n );\n }, [locale, sort, sortReverse, lastStorageData]);\n\n if (locale.toLowerCase() === \"en-us\") {\n return null;\n }\n\n return (\n <Container>\n {lastData && !error && isValidating && (\n <p style={{ float: \"right\" }}>Reloading...</p>\n )}\n {!data && !error && !lastData && (\n <Loading\n estimate={\n (lastStorageData && lastStorageData.lastLoadTime) || 30 * 1000\n }\n />\n )}\n {lastData && (\n <p style={{ textAlign: \"right\" }}>\n Go to{\" \"}\n <Link to={`/${locale}/_translations/missing`}>\n Missing translations for <b>{locale}</b>\n </Link>\n </p>\n )}\n {error && <ShowSearchError error={error} />}\n {lastData && (\n <div className=\"filter-documents\">\n <FilterControls />\n <DocumentsTable\n locale={locale}\n counts={lastData.counts}\n documents={lastData.documents}\n sort={sort}\n sortReverse={sortReverse}\n />\n </div>\n )}\n {data && <BuildTimes times={data.times} />}\n </Container>\n );\n}\n\nfunction Container({ children }: { children: React.ReactNode }) {\n return (\n <MainContentContainer className=\"all-translations\" standalone={true}>\n {children}\n </MainContentContainer>\n );\n}\n\nfunction ShowSearchError({ error }) {\n return (\n <div className=\"error-message search-error\">\n <h3>Search error</h3>\n <pre>{error.toString()}</pre>\n </div>\n );\n}\n\nfunction BuildTimes({ times }: { times: Times }) {\n function format(ms: number) {\n if (ms > 1000) {\n const s = ms / 1000;\n return `${s.toFixed(1)} seconds`;\n } else {\n return `${Math.trunc(ms)} milliseconds`;\n }\n }\n return (\n <div className=\"search-times\">\n <p>Time to find all documents {format(times.took)}</p>\n </div>\n );\n}\n\nfunction Loading({ estimate }: { estimate: number }) {\n const startLoadingTime = new Date();\n const [estimateEndTime] = React.useState(\n new Date(startLoadingTime.getTime() + estimate)\n );\n\n const [, setIncrements] = React.useState(0);\n React.useEffect(() => {\n const interval = setInterval(() => {\n setIncrements((state) => state + 1);\n }, 1000);\n return () => clearInterval(interval);\n }, []);\n\n const distance = estimateEndTime.getTime() - startLoadingTime.getTime();\n const elapsed = new Date().getTime() - startLoadingTime.getTime();\n const percent = (100 * elapsed) / distance;\n return (\n <div className=\"loading\">\n <progress id=\"progress\" max=\"100\" value={percent} style={{ margin: 20 }}>\n {percent}%\n </progress>\n <br />\n <small>\n Estimated time to finish: {((distance - elapsed) / 1000).toFixed(0)}s{\" \"}\n {elapsed > distance ? (\n <span aria-label=\"weird\" role=\"img\">\n 🙃\n </span>\n ) : null}\n </small>\n </div>\n );\n}\n\nfunction FilterControls() {\n const [searchParams, setSearchParams] = useSearchParams();\n const [title, setTitle] = React.useState(searchParams.get(\"title\") || \"\");\n const [url, setURL] = React.useState(searchParams.get(\"url\") || \"\");\n const [differences, setDifferences] = React.useState(\n searchParams.get(\"differences\") || \"\"\n );\n\n function refreshFilters(reset = false) {\n const filterParams = createSearchParams(searchParams);\n for (const [key, value] of [\n [\"url\", url],\n [\"title\", title],\n [\"differences\", differences],\n ]) {\n if (!reset && value) {\n filterParams.set(key, value);\n } else {\n filterParams.delete(key);\n }\n }\n filterParams.delete(\"page\");\n setSearchParams(filterParams);\n }\n\n function resetFilters() {\n setURL(\"\");\n setTitle(\"\");\n setDifferences(\"\");\n refreshFilters(true);\n }\n\n return (\n <div className=\"filters\">\n <h3>Filters</h3>\n <form\n onSubmit={(event) => {\n event.preventDefault();\n refreshFilters();\n }}\n >\n <div>\n <h4>Document</h4>\n <input\n type=\"search\"\n placeholder=\"Filter by document URI\"\n value={url}\n onChange={(event) => {\n setURL(event.target.value);\n }}\n onBlur={() => refreshFilters()}\n />\n <input\n type=\"search\"\n placeholder=\"Filter by document title\"\n value={title}\n onChange={(event) => {\n setTitle(event.target.value);\n }}\n onBlur={() => refreshFilters()}\n />\n </div>\n <div>\n <h4>Differences</h4>\n <input\n type=\"text\"\n placeholder=\"E.g. >0 or >=5\"\n value={differences}\n onChange={(event) => {\n setDifferences(event.target.value);\n }}\n onBlur={() => refreshFilters()}\n />\n </div>\n\n <div>\n <h4>&nbsp;</h4>\n <button type=\"submit\">Filter now</button>{\" \"}\n {(url || title) && (\n <button type=\"button\" onClick={resetFilters}>\n Reset filters\n </button>\n )}\n </div>\n </form>\n </div>\n );\n}\ntype NumericOperation = {\n operation: \"eq\" | \"gt\" | \"gte\" | \"lt\" | \"lte\";\n value: number;\n};\n\nfunction getNumericOperation(expression: string): NumericOperation | null {\n function parseIntOrThrow(v: string) {\n if (!v) {\n throw new Error(\"Can't be empty\");\n }\n\n const parsed = parseInt(v, 10);\n if (isNaN(parsed)) {\n throw new Error(`'${v}' not a valid number`);\n }\n return parsed;\n }\n try {\n if (expression.startsWith(\">=\")) {\n return {\n operation: \"gte\",\n value: parseIntOrThrow(expression.replace(\">=\", \"\")),\n };\n } else if (expression.startsWith(\">\")) {\n return {\n operation: \"gt\",\n value: parseIntOrThrow(expression.replace(\">\", \"\")),\n };\n } else if (expression.startsWith(\"<=\")) {\n return {\n operation: \"lte\",\n value: parseIntOrThrow(expression.replace(\"<=\", \"\")),\n };\n } else if (expression.startsWith(\"<\")) {\n return {\n operation: \"lt\",\n value: parseIntOrThrow(expression.replace(\"<\", \"\")),\n };\n } else if (expression.startsWith(\"==\") || expression.startsWith(\"=\")) {\n return {\n operation: \"eq\",\n value: parseIntOrThrow(expression.replace(/=/g, \"\")),\n };\n } else if (expression) {\n return {\n operation: \"eq\",\n value: parseIntOrThrow(expression),\n };\n } else {\n return null;\n }\n } catch (error) {\n console.warn(error);\n return null;\n }\n}\n\nfunction matchNumericOperation(value: number, op: NumericOperation): boolean {\n if (op.operation === \"eq\") {\n if (value !== op.value) {\n return false;\n }\n } else if (op.operation === \"gt\") {\n if (!(value > op.value)) {\n return false;\n }\n } else if (op.operation === \"gte\") {\n if (!(value >= op.value)) {\n return false;\n }\n } else if (op.operation === \"lt\") {\n if (!(value < op.value)) {\n return false;\n }\n } else if (op.operation === \"lte\") {\n if (!(value <= op.value)) {\n return false;\n }\n } else {\n throw new Error(`Not implemented operation '${op.operation}'`);\n }\n return true;\n}\n\nfunction DocumentsTable({\n locale,\n counts,\n documents,\n sort,\n sortReverse,\n}: {\n locale: string;\n counts: Counts;\n documents: Document[];\n sort: string;\n sortReverse: boolean;\n}) {\n const [searchParams, setSearchParams] = useSearchParams();\n\n const page = parseInt(searchParams.get(\"page\") || \"1\", 10);\n const pageSize = parseInt(searchParams.get(\"pageSize\") || \"20\", 10);\n const filterTitle = searchParams.get(\"title\") || \"\";\n const filterURL = searchParams.get(\"url\") || \"\";\n const filterDifferences = searchParams.get(\"differences\") || \"\";\n const filterDifferencesOperation = getNumericOperation(filterDifferences);\n\n function TableHead({ id, title }: { id: string; title: string }) {\n return (\n <th\n onClick={() => {\n if (sort === id) {\n setSearchParams(\n createSearchParams({\n sort: id,\n sortReverse: JSON.stringify(!sortReverse),\n })\n );\n } else {\n setSearchParams(createSearchParams({ sort: id }));\n }\n }}\n className=\"sortable\"\n >\n {title} {sort === id ? (sortReverse ? \"↓\" : \"↑\") : null}\n </th>\n );\n }\n\n const filteredDocuments = documents\n .filter((document) => {\n if (\n filterTitle &&\n !document.title.toLowerCase().includes(filterTitle.toLowerCase())\n ) {\n return false;\n }\n\n if (\n filterURL &&\n !document.mdn_url.toLowerCase().includes(filterURL.toLowerCase())\n ) {\n return false;\n }\n\n if (\n filterDifferencesOperation &&\n !matchNumericOperation(\n document.differences.total,\n filterDifferencesOperation\n )\n ) {\n return false;\n }\n\n return true;\n })\n .sort((A, B) => {\n let reverse = sortReverse ? -1 : 1;\n if (sort === \"modified\") {\n const a = new Date(A.edits.modified);\n const b = new Date(B.edits.modified);\n return reverse * (b.getTime() - a.getTime());\n } else if (sort === \"popularity\") {\n const a = A.popularity.value;\n const b = B.popularity.value;\n return reverse * (b - a);\n } else if (sort === \"differences\") {\n const a = A.differences.total;\n const b = B.differences.total;\n return reverse * (b - a);\n } else if (sort === \"title\") {\n const a = A.title;\n const b = B.title;\n return reverse * a.localeCompare(b);\n } else if (sort === \"mdn_url\") {\n const a = A.mdn_url;\n const b = B.mdn_url;\n return reverse * a.localeCompare(b);\n } else if (sort === \"sourceCommit\") {\n const a = A.edits.sourceCommitsBehindCount ?? -1;\n const b = B.edits.sourceCommitsBehindCount ?? -1;\n return reverse * (b - a);\n } else {\n throw new Error(`Unrecognized sort '${sort}'`);\n }\n });\n const pageCount = Math.ceil(counts.found / pageSize);\n\n return (\n <div className=\"documents\">\n <h3>\n Documents with differences found (\n {filteredDocuments.length.toLocaleString()}){\" \"}\n {pageCount > 1 && (\n <span className=\"page\">\n page {page}/{pageCount}\n </span>\n )}\n </h3>\n <h4 className=\"subheader\">\n {counts.total.toLocaleString()} total documents found ({locale})\n </h4>\n\n {filterDifferences && !filterDifferencesOperation && (\n <div className=\"error-message\">\n <h3>Invalid differences filter</h3>\n <p>\n The <i>differences</i> filter can't be parsed.\n <br />\n <code>{filterDifferences}</code>\n </p>\n </div>\n )}\n\n <table>\n <thead>\n <tr>\n <TableHead id=\"title\" title=\"Document\" />\n <TableHead id=\"popularity\" title=\"Popularity\" />\n <TableHead id=\"modified\" title=\"Last modified\" />\n <TableHead id=\"differences\" title=\"Differences\" />\n <TableHead id=\"sourceCommit\" title=\"Source Commit\" />\n </tr>\n </thead>\n <tbody>\n {filteredDocuments\n .slice((page - 1) * pageSize, page * pageSize)\n .map((doc: Document) => {\n return (\n <tr key={doc.mdn_url}>\n <td>\n <span className=\"document-title-preview\">\n {filterTitle ? (\n <HighlightedText\n text={doc.title}\n highlight={filterTitle}\n />\n ) : (\n doc.title\n )}\n </span>\n <br />\n <Link\n to={`${doc.mdn_url}#_flaws`}\n title={doc.title}\n target=\"_blank\"\n >\n <BriefURL uri={doc.mdn_url} filterURL={filterURL} />\n </Link>\n </td>\n <td\n title={\n doc.popularity.ranking\n ? `Meaning there are ${\n doc.popularity.ranking - 1\n } more popular pages than this`\n : \"Meaning it has no ranking. Most likely a very rare (or new) document\"\n }\n >\n {!doc.popularity.ranking\n ? \"n/a\"\n : `${getGetOrdinal(doc.popularity.ranking)}`}{\" \"}\n <small title=\"For the parent document\">\n (\n {!doc.popularity.parentRanking\n ? \"n/a\"\n : `${getGetOrdinal(doc.popularity.parentRanking)}`}\n )\n </small>\n </td>\n <td>\n <LastModified edits={doc.edits} />\n </td>\n <td>{doc.differences.total.toLocaleString()}</td>\n <td>\n <L10nSourceCommitModified\n sourceCommitsBehindCount={\n doc.edits.sourceCommitsBehindCount\n }\n sourceCommitURL={doc.edits.sourceCommitURL}\n />\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n\n <Paginator last={pageCount} />\n </div>\n );\n}\n\nfunction L10nSourceCommitModified({\n sourceCommitsBehindCount,\n sourceCommitURL,\n}: Pick<DocumentEdits, \"sourceCommitsBehindCount\" | \"sourceCommitURL\">) {\n if (\n !sourceCommitURL ||\n (!sourceCommitsBehindCount && sourceCommitsBehindCount !== 0)\n ) {\n return <>Metadata does not exist.</>;\n }\n\n const getImportanceColor = () => {\n if (sourceCommitsBehindCount === 0) return \"🟢\";\n return sourceCommitsBehindCount < 10 ? \"🟠\" : \"🔴\";\n };\n\n return (\n <a\n href={sourceCommitURL}\n >{`${getImportanceColor()} ${sourceCommitsBehindCount} commits behind`}</a>\n );\n}\n\nfunction LastModified({ edits }: { edits: DocumentEdits }) {\n const modified = dayjs(edits.modified);\n const parentModified = dayjs(edits.parentModified);\n return (\n <span\n className={`last_modified ${\n parentModified < modified ? \"ahead\" : \"behind\"\n }`}\n >\n <a href={edits.commitURL} target=\"_blank\" rel=\"noreferrer\">\n <time dateTime={modified.toISOString()} title={modified.toISOString()}>\n {modified.fromNow()}\n </time>\n </a>\n <br />\n <a href={edits.parentCommitURL} target=\"_blank\" rel=\"noreferrer\">\n <small>\n <time\n dateTime={parentModified.toISOString()}\n title={parentModified.toISOString()}\n >\n en-US {parentModified.fromNow()}\n </time>\n </small>\n </a>\n </span>\n );\n}\n\nfunction HighlightedText({\n text,\n highlight,\n}: {\n text: string;\n highlight: string;\n}) {\n // Split on highlight term and include term into parts, ignore case\n const parts = text.split(new RegExp(`(${highlight})`, \"gi\"));\n return (\n <span>\n {\" \"}\n {parts.map((part, i) => (\n <span\n key={i}\n style={\n part.toLowerCase() === highlight.toLowerCase()\n ? { fontWeight: \"bold\" }\n : {}\n }\n >\n {part}\n </span>\n ))}{\" \"}\n </span>\n );\n}\n\nfunction BriefURL({ uri, filterURL }: { uri: string; filterURL: string }) {\n const [left, right] = uri.split(/\\/docs\\//, 2);\n return (\n <>\n <span className=\"url-prefix\">{left}/docs/</span>\n <span className=\"url-slug\">\n {filterURL ? (\n <HighlightedText text={right} highlight={filterURL} />\n ) : (\n right\n )}\n </span>\n </>\n );\n}\n\n// https://gist.github.com/jlbruno/1535691/db35b4f3af3dcbb42babc01541410f291a8e8fac\nfunction getGetOrdinal(n: number) {\n const s = [\"th\", \"st\", \"nd\", \"rd\"];\n const v = n % 100;\n return n.toLocaleString() + (s[(v - 20) % 10] || s[v] || s[0]);\n}\n","import React from \"react\";\nimport {\n createSearchParams,\n Link,\n useSearchParams,\n useNavigate,\n} from \"react-router-dom\";\nimport useSWR from \"swr\";\nimport dayjs from \"dayjs\";\nimport relativeTime from \"dayjs/plugin/relativeTime\";\n\nimport { MainContentContainer } from \"../../ui/atoms/page-content\";\nimport { Paginator } from \"../../ui/molecules/paginator\";\nimport { useLocale } from \"../../hooks\";\n\ndayjs.extend(relativeTime);\n\ninterface DocumentPopularity {\n value: number;\n ranking: number;\n parentValue: number;\n parentRanking: number;\n}\n\ntype CountByType = { [key: string]: number };\n\ninterface DocumentDifferences {\n countByType: CountByType;\n total: number;\n}\n\ninterface DocumentEdits {\n modified: string;\n parentModified: string;\n commitURL: string;\n parentCommitURL: string;\n}\n\ninterface Document {\n mdn_url: string;\n edits: DocumentEdits;\n title: string;\n popularity: DocumentPopularity;\n differences: DocumentDifferences;\n}\n\ninterface Counts {\n missing: number;\n translated: number;\n total: number;\n cacheMisses: number;\n}\n\ninterface Times {\n took: number;\n}\n\ninterface FlawLevel {\n name: string;\n level: string;\n ignored: boolean;\n}\n\ninterface Data {\n counts: Counts;\n missingDocuments: Document[];\n times: Times;\n flawLevels: FlawLevel[];\n}\n\ninterface LocaleStorageData {\n lastLoadTime?: number;\n defaultSort?: string;\n defaultSortReverse?: string;\n}\n\ninterface StorageData {\n [locale: string]: LocaleStorageData;\n}\n\nconst LOCALSTORAGE_KEY = \"translations-dashboard-missing\";\n\nfunction saveStorage(locale: string, data: LocaleStorageData) {\n try {\n const stored = JSON.parse(\n localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\"\n ) as StorageData;\n stored[locale] = Object.assign({}, stored[locale] || {}, data);\n localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(stored));\n } catch (err) {\n console.warn(\"Unable to save to localStorage\", err);\n }\n}\n\nfunction getStorage(locale: string): LocaleStorageData | null {\n try {\n const stored = JSON.parse(localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\");\n if (stored) {\n return stored[locale] as LocaleStorageData;\n }\n } catch (err) {\n console.warn(\"Unable to retrieve from localStorage\", err);\n }\n return null;\n}\n\nexport function MissingTranslations() {\n const locale = useLocale();\n const [searchParams] = useSearchParams();\n const navigate = useNavigate();\n\n const [lastData, setLastData] = React.useState<Data | null>(null);\n\n React.useEffect(() => {\n if (locale.toLowerCase() === \"en-us\") {\n navigate(`/${locale}/_translations`);\n }\n }, [locale, navigate]);\n\n React.useEffect(() => {\n let title = \"Missing translations\";\n if (locale.toLowerCase() !== \"en-us\") {\n title += ` for ${locale}`;\n }\n if (lastData) {\n title = `(${lastData.counts.missing.toLocaleString()} found) ${title}`;\n }\n document.title = title;\n }, [lastData, locale]);\n\n const { data, error, isValidating } = useSWR<Data, Error>(\n locale.toLowerCase() !== \"en-us\"\n ? `/_translations/missing/?locale=${locale}`\n : null,\n async (url) => {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`${response.status} (${await response.text()})`);\n }\n if (\n !(response.headers.get(\"content-type\") || \"\").includes(\n \"application/json\"\n )\n ) {\n throw new Error(\n `Response is not JSON (${response.headers.get(\"content-type\")})`\n );\n }\n return response.json();\n },\n {\n revalidateOnFocus: false,\n }\n );\n\n // Use this to be able to figure out how long the XHR takes when there's no cache\n const startTime = React.useRef<Date>();\n React.useEffect(() => {\n if (locale) {\n if (!data) {\n startTime.current = new Date();\n } else {\n if (\n data.counts.cacheMisses > 0 &&\n data.counts.cacheMisses === data.counts.total &&\n startTime.current\n ) {\n const lastLoadTime =\n new Date().getTime() - startTime.current.getTime();\n saveStorage(locale, { lastLoadTime });\n }\n }\n }\n }, [locale, data]);\n\n React.useEffect(() => {\n if (data) {\n setLastData(data);\n }\n }, [data]);\n\n const lastStorageData = getStorage(locale);\n const defaultSort = lastStorageData?.defaultSort || \"popularity\";\n const defaultSortReverse = lastStorageData?.defaultSortReverse || \"false\";\n const sort = searchParams.get(\"sort\") || defaultSort;\n const sortReverse = JSON.parse(\n searchParams.get(\"sortReverse\") || defaultSortReverse\n );\n\n React.useEffect(() => {\n saveStorage(\n locale,\n Object.assign({}, lastStorageData, {\n defaultSort: sort,\n defaultSortReverse: sortReverse,\n })\n );\n }, [locale, sort, sortReverse, lastStorageData]);\n\n if (locale.toLowerCase() === \"en-us\") {\n return null;\n }\n\n return (\n <Container>\n {lastData && !error && isValidating && (\n <p style={{ float: \"right\" }}>Reloading...</p>\n )}\n {!data && !error && !lastData && (\n <Loading\n estimate={\n (lastStorageData && lastStorageData.lastLoadTime) || 30 * 1000\n }\n />\n )}\n {lastData && (\n <p style={{ textAlign: \"right\" }}>\n Go to{\" \"}\n <Link to={`/${locale}/_translations/differences`}>\n Translation differences for <b>{locale}</b>\n </Link>\n </p>\n )}\n {error && <ShowSearchError error={error} />}\n {lastData && (\n <div className=\"filter-documents\">\n <FilterControls />\n <DocumentsTable\n counts={lastData.counts}\n documents={lastData.missingDocuments}\n sort={sort}\n sortReverse={sortReverse}\n />\n </div>\n )}\n {data && <BuildTimes times={data.times} />}\n </Container>\n );\n}\n\nfunction Container({ children }: { children: React.ReactNode }) {\n return (\n <MainContentContainer className=\"missing-translations\" standalone={true}>\n {children}\n </MainContentContainer>\n );\n}\n\nfunction ShowSearchError({ error }) {\n return (\n <div className=\"error-message search-error\">\n <h3>Search error</h3>\n <pre>{error.toString()}</pre>\n </div>\n );\n}\n\nfunction BuildTimes({ times }: { times: Times }) {\n function format(ms: number) {\n if (ms > 1000) {\n const s = ms / 1000;\n return `${s.toFixed(1)} seconds`;\n } else {\n return `${Math.trunc(ms)} milliseconds`;\n }\n }\n return (\n <div className=\"search-times\">\n <p>Time to find all documents {format(times.took)}</p>\n </div>\n );\n}\n\nfunction Loading({ estimate }: { estimate: number }) {\n const startLoadingTime = new Date();\n const [estimateEndTime] = React.useState(\n new Date(startLoadingTime.getTime() + estimate)\n );\n\n const [, setIncrements] = React.useState(0);\n React.useEffect(() => {\n const interval = setInterval(() => {\n setIncrements((state) => state + 1);\n }, 1000);\n return () => clearInterval(interval);\n }, []);\n\n const distance = estimateEndTime.getTime() - startLoadingTime.getTime();\n const elapsed = new Date().getTime() - startLoadingTime.getTime();\n const percent = (100 * elapsed) / distance;\n return (\n <div className=\"loading\">\n <progress id=\"progress\" max=\"100\" value={percent} style={{ margin: 20 }}>\n {percent}%\n </progress>\n <br />\n <small>\n Estimated time to finish: {((distance - elapsed) / 1000).toFixed(0)}s{\" \"}\n {elapsed > distance ? (\n <span aria-label=\"weird\" role=\"img\">\n 🙃\n </span>\n ) : null}\n </small>\n </div>\n );\n}\n\nfunction FilterControls() {\n const [searchParams, setSearchParams] = useSearchParams();\n const [title, setTitle] = React.useState(searchParams.get(\"title\") || \"\");\n const [url, setURL] = React.useState(searchParams.get(\"url\") || \"\");\n\n function refreshFilters(reset = false) {\n const filterParams = createSearchParams(searchParams);\n for (const [key, value] of [\n [\"url\", url],\n [\"title\", title],\n ]) {\n if (!reset && value) {\n filterParams.set(key, value);\n } else {\n filterParams.delete(key);\n }\n }\n filterParams.delete(\"page\");\n setSearchParams(filterParams);\n }\n\n function resetFilters() {\n setURL(\"\");\n setTitle(\"\");\n refreshFilters(true);\n }\n\n return (\n <div className=\"filters\">\n <h3>Filters</h3>\n <form\n onSubmit={(event) => {\n event.preventDefault();\n refreshFilters();\n }}\n >\n <div>\n <h4>Document</h4>\n <input\n type=\"search\"\n placeholder=\"Filter by document URI\"\n value={url}\n onChange={(event) => {\n setURL(event.target.value);\n }}\n onBlur={() => refreshFilters()}\n />\n <input\n type=\"search\"\n placeholder=\"Filter by document title\"\n value={title}\n onChange={(event) => {\n setTitle(event.target.value);\n }}\n onBlur={() => refreshFilters()}\n />\n </div>\n\n <div>\n <h4>&nbsp;</h4>\n <button type=\"submit\">Filter now</button>{\" \"}\n {(url || title) && (\n <button type=\"button\" onClick={resetFilters}>\n Reset filters\n </button>\n )}\n </div>\n </form>\n </div>\n );\n}\ntype NumericOperation = {\n operation: \"eq\" | \"gt\" | \"gte\" | \"lt\" | \"lte\";\n value: number;\n};\n\nfunction getNumericOperation(expression: string): NumericOperation | null {\n function parseIntOrThrow(v: string) {\n if (!v) {\n throw new Error(\"Can't be empty\");\n }\n\n const parsed = parseInt(v, 10);\n if (isNaN(parsed)) {\n throw new Error(`'${v}' not a valid number`);\n }\n return parsed;\n }\n try {\n if (expression.startsWith(\">=\")) {\n return {\n operation: \"gte\",\n value: parseIntOrThrow(expression.replace(\">=\", \"\")),\n };\n } else if (expression.startsWith(\">\")) {\n return {\n operation: \"gt\",\n value: parseIntOrThrow(expression.replace(\">\", \"\")),\n };\n } else if (expression.startsWith(\"<=\")) {\n return {\n operation: \"lte\",\n value: parseIntOrThrow(expression.replace(\"<=\", \"\")),\n };\n } else if (expression.startsWith(\"<\")) {\n return {\n operation: \"lt\",\n value: parseIntOrThrow(expression.replace(\"<\", \"\")),\n };\n } else if (expression.startsWith(\"==\") || expression.startsWith(\"=\")) {\n return {\n operation: \"eq\",\n value: parseIntOrThrow(expression.replace(/=/g, \"\")),\n };\n } else if (expression) {\n return {\n operation: \"eq\",\n value: parseIntOrThrow(expression),\n };\n } else {\n return null;\n }\n } catch (error) {\n console.warn(error);\n return null;\n }\n}\n\nfunction matchNumericOperation(value: number, op: NumericOperation): boolean {\n if (op.operation === \"eq\") {\n if (value !== op.value) {\n return false;\n }\n } else if (op.operation === \"gt\") {\n if (!(value > op.value)) {\n return false;\n }\n } else if (op.operation === \"gte\") {\n if (!(value >= op.value)) {\n return false;\n }\n } else if (op.operation === \"lt\") {\n if (!(value < op.value)) {\n return false;\n }\n } else if (op.operation === \"lte\") {\n if (!(value <= op.value)) {\n return false;\n }\n } else {\n throw new Error(`Not implemented operation '${op.operation}'`);\n }\n return true;\n}\n\nfunction DocumentsTable({\n counts,\n documents,\n sort,\n sortReverse,\n}: {\n counts: Counts;\n documents: Document[];\n sort: string;\n sortReverse: boolean;\n}) {\n const [searchParams, setSearchParams] = useSearchParams();\n\n const page = parseInt(searchParams.get(\"page\") || \"1\", 10);\n const pageSize = parseInt(searchParams.get(\"pageSize\") || \"20\", 10);\n const filterTitle = searchParams.get(\"title\") || \"\";\n const filterURL = searchParams.get(\"url\") || \"\";\n const filterDifferences = searchParams.get(\"differences\") || \"\";\n const filterDifferencesOperation = getNumericOperation(filterDifferences);\n\n function TableHead({ id, title }: { id: string; title: string }) {\n return (\n <th\n onClick={() => {\n if (sort === id) {\n setSearchParams(\n createSearchParams({\n sort: id,\n sortReverse: JSON.stringify(!sortReverse),\n })\n );\n } else {\n setSearchParams(createSearchParams({ sort: id }));\n }\n }}\n className=\"sortable\"\n >\n {title} {sort === id ? (sortReverse ? \"↓\" : \"↑\") : null}\n </th>\n );\n }\n\n const filteredDocuments = documents\n .filter((document) => {\n if (\n filterTitle &&\n !document.title.toLowerCase().includes(filterTitle.toLowerCase())\n ) {\n return false;\n }\n\n if (\n filterURL &&\n !document.mdn_url.toLowerCase().includes(filterURL.toLowerCase())\n ) {\n return false;\n }\n\n if (\n filterDifferencesOperation &&\n !matchNumericOperation(\n document.differences.total,\n filterDifferencesOperation\n )\n ) {\n return false;\n }\n\n return true;\n })\n .sort((A, B) => {\n let reverse = sortReverse ? -1 : 1;\n if (sort === \"modified\") {\n const a = new Date(A.edits.modified);\n const b = new Date(B.edits.modified);\n return reverse * (b.getTime() - a.getTime());\n } else if (sort === \"popularity\") {\n const a = A.popularity.value;\n const b = B.popularity.value;\n return reverse * (b - a);\n } else if (sort === \"differences\") {\n const a = A.differences.total;\n const b = B.differences.total;\n return reverse * (b - a);\n } else if (sort === \"title\") {\n const a = A.title;\n const b = B.title;\n return reverse * a.localeCompare(b);\n } else if (sort === \"mdn_url\") {\n const a = A.mdn_url;\n const b = B.mdn_url;\n return reverse * a.localeCompare(b);\n } else {\n throw new Error(`Unrecognized sort '${sort}'`);\n }\n });\n const pageCount = Math.ceil(counts.total / pageSize);\n\n return (\n <div className=\"documents\">\n <h3>\n {counts.missing.toLocaleString()} missing translations (of{\" \"}\n {counts.total.toLocaleString()} possible)\n </h3>\n\n <table>\n <thead>\n <tr>\n <TableHead id=\"title\" title=\"Document\" />\n <TableHead id=\"popularity\" title=\"Popularity\" />\n <TableHead id=\"modified\" title=\"Last modified\" />\n </tr>\n </thead>\n <tbody>\n {filteredDocuments\n .slice((page - 1) * pageSize, page * pageSize)\n .map((doc: Document) => {\n return (\n <tr key={doc.mdn_url}>\n <td>\n <span className=\"document-title-preview\">\n {filterTitle ? (\n <HighlightedText\n text={doc.title}\n highlight={filterTitle}\n />\n ) : (\n doc.title\n )}\n </span>\n <br />\n <Link\n to={`${doc.mdn_url}#_flaws`}\n title={doc.title}\n target=\"_blank\"\n >\n <BriefURL uri={doc.mdn_url} filterURL={filterURL} />\n </Link>\n </td>\n <td\n title={\n doc.popularity.ranking\n ? `Meaning there are ${\n doc.popularity.ranking - 1\n } more popular pages than this`\n : \"Meaning it has no ranking. Most likely a very rare (or new) document\"\n }\n >\n {!doc.popularity.ranking\n ? \"n/a\"\n : `${getGetOrdinal(doc.popularity.ranking)}`}{\" \"}\n </td>\n <td>\n <LastModified edits={doc.edits} />\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n\n <Paginator last={pageCount} />\n </div>\n );\n}\n\nfunction LastModified({ edits }: { edits: DocumentEdits }) {\n const modified = dayjs(edits.modified);\n return (\n <span className=\"last_modified\">\n <a href={edits.commitURL} target=\"_blank\" rel=\"noreferrer\">\n <time dateTime={modified.toISOString()} title={modified.toISOString()}>\n {modified.fromNow()}\n </time>\n </a>\n </span>\n );\n}\n\nfunction HighlightedText({\n text,\n highlight,\n}: {\n text: string;\n highlight: string;\n}) {\n // Split on highlight term and include term into parts, ignore case\n const parts = text.split(new RegExp(`(${highlight})`, \"gi\"));\n return (\n <span>\n {\" \"}\n {parts.map((part, i) => (\n <span\n key={i}\n style={\n part.toLowerCase() === highlight.toLowerCase()\n ? { fontWeight: \"bold\" }\n : {}\n }\n >\n {part}\n </span>\n ))}{\" \"}\n </span>\n );\n}\n\nfunction BriefURL({ uri, filterURL }: { uri: string; filterURL: string }) {\n const [left, right] = uri.split(/\\/docs\\//, 2);\n return (\n <>\n <span className=\"url-prefix\">{left}/docs/</span>\n <span className=\"url-slug\">\n {filterURL ? (\n <HighlightedText text={right} highlight={filterURL} />\n ) : (\n right\n )}\n </span>\n </>\n );\n}\n\n// https://gist.github.com/jlbruno/1535691/db35b4f3af3dcbb42babc01541410f291a8e8fac\nfunction getGetOrdinal(n: number) {\n const s = [\"th\", \"st\", \"nd\", \"rd\"];\n const v = n % 100;\n return n.toLocaleString() + (s[(v - 20) % 10] || s[v] || s[0]);\n}\n","import React from \"react\";\nimport {\n createSearchParams,\n Link,\n useSearchParams,\n useNavigate,\n} from \"react-router-dom\";\nimport useSWR from \"swr\";\n\nimport { MainContentContainer } from \"../../ui/atoms/page-content\";\nimport { Icon } from \"../../ui/atoms/icon\";\nimport { useLocale } from \"../../hooks\";\n\ninterface Data {\n l10nKPIs: L10nKPIs;\n sections: Section[];\n detailDocuments: DetailDocument[];\n}\n\ninterface Section {\n l10nKPIs: L10nKPIs;\n name: string;\n}\n\ninterface L10nKPIs {\n missing: number;\n outOfDate: number;\n upToDate: number;\n total: number;\n}\n\ninterface DetailDocument {\n url: string;\n info: InfoDocument;\n}\n\ninterface InfoDocument {\n popularity: DocumentPopularity;\n localePopularity: DocumentPopularity;\n defaultLocaleInfo: LocaleInfo;\n localeInfo?: LocaleInfo;\n dateDiff?: number;\n}\n\ninterface DocumentPopularity {\n value: number;\n ranking: number;\n parentValue: number;\n parentRanking: number;\n}\n\ninterface LocaleInfo {\n modified: string;\n commitURL: string;\n}\n\ninterface LocaleStorageData {\n defaultSort?: string;\n defaultSortReverse?: string;\n}\n\ninterface StorageData {\n [locale: string]: LocaleStorageData;\n}\n\nconst LOCALSTORAGE_KEY = \"translations-dashboard-sections\";\n\nfunction saveStorage(locale: string, data: LocaleStorageData) {\n try {\n const stored = JSON.parse(\n localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\"\n ) as StorageData;\n stored[locale] = Object.assign({}, stored[locale] || {}, data);\n localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(stored));\n } catch (err) {\n console.warn(\"Unable to save to localStorage\", err);\n }\n}\n\nfunction getStorage(locale: string): LocaleStorageData | null {\n try {\n const stored = JSON.parse(localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\");\n if (stored) {\n return stored[locale] as LocaleStorageData;\n }\n } catch (err) {\n console.warn(\"Unable to retrieve from localStorage\", err);\n }\n return null;\n}\n\nexport function TranslationDashboard() {\n const locale = useLocale();\n const [searchParams] = useSearchParams();\n const navigate = useNavigate();\n\n const [lastData, setLastData] = React.useState<Data | null>(null);\n\n const currentSection = searchParams.get(\"section\") || \"\";\n React.useEffect(() => {\n if (locale.toLowerCase() === \"en-us\") {\n navigate(`/${locale}/_translations`);\n }\n }, [locale, navigate]);\n\n React.useEffect(() => {\n let title = \"Translation dashboard \";\n if (locale.toLowerCase() !== \"en-us\") {\n title += ` for ${locale}`;\n }\n if (currentSection !== \"\") {\n title += ` - section ${currentSection}`;\n }\n document.title = title;\n }, [lastData, locale, currentSection]);\n\n let { data, error, isValidating } = useSWR<Data, Error>(\n locale.toLowerCase() !== \"en-us\"\n ? `/_translations/dashboard/?locale=${locale}&section=${currentSection}`\n : null,\n async (url) => {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`${response.status} (${await response.text()})`);\n }\n if (\n !(response.headers.get(\"content-type\") || \"\").includes(\n \"application/json\"\n )\n ) {\n throw new Error(\n `Response is not JSON (${response.headers.get(\"content-type\")})`\n );\n }\n return response.json();\n },\n {\n revalidateOnFocus: false,\n }\n );\n\n React.useEffect(() => {\n if (data) {\n setLastData(data);\n }\n }, [data]);\n\n const lastStorageData = getStorage(locale);\n const defaultSort = lastStorageData?.defaultSort || \"url\";\n const defaultSortReverse = lastStorageData?.defaultSortReverse || \"false\";\n const sort = searchParams.get(\"sort\") || defaultSort;\n const sortReverse = JSON.parse(\n searchParams.get(\"sortReverse\") || defaultSortReverse\n );\n\n React.useEffect(() => {\n saveStorage(\n locale,\n Object.assign({}, lastStorageData, {\n defaultSort: sort,\n defaultSortReverse: sortReverse,\n })\n );\n }, [locale, sort, sortReverse, lastStorageData]);\n\n if (locale.toLowerCase() === \"en-us\") {\n return null;\n }\n\n let parentSection = \"/\";\n if (currentSection.split(\"/\").length > 2) {\n const arrPathSection = currentSection.split(\"/\");\n arrPathSection.pop();\n parentSection = arrPathSection.join(\"/\");\n }\n\n return (\n <Container>\n {lastData && !error && isValidating && (\n <p style={{ float: \"right\" }}>Reloading...</p>\n )}\n {!data && !error && !lastData && <Loading />}\n {lastData && (\n <p style={{ textAlign: \"right\" }}>\n Go to{\" \"}\n <Link to={`/${locale}/_translations/differences`}>\n Translation differences for <b>{locale}</b>\n </Link>\n {\" / \"}\n <Link to={`/${locale}/_translations/missing`}>\n Missing translations for <b>{locale}</b>\n </Link>\n </p>\n )}\n {error && <ShowError error={error} />}\n {lastData && (\n <div>\n <SectionHeader\n l10nKPIs={lastData.l10nKPIs}\n section={currentSection}\n parentSection={parentSection}\n />\n <SubsectionTable\n sections={lastData.sections}\n currentSection={currentSection}\n />\n <DocumentsTable\n documents={lastData.detailDocuments}\n sort={sort}\n sortReverse={sortReverse}\n locale={locale}\n />\n </div>\n )}\n </Container>\n );\n /*\n );\n }\n */\n}\n\nfunction Container({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"dashboard-section-translations\">\n <MainContentContainer standalone={true}>{children}</MainContentContainer>\n </div>\n );\n}\n\nfunction ShowError({ error }) {\n return (\n <div className=\"error-message\">\n <h3>Error</h3>\n <pre>{error.toString()}</pre>\n </div>\n );\n}\n\nfunction Loading() {\n return (\n <div>\n <label htmlFor=\"progress\">Loading</label>\n <progress id=\"progress\" max=\"100\" style={{ margin: 20 }}></progress>\n </div>\n );\n}\n\nfunction SectionHeader({\n l10nKPIs,\n section,\n parentSection,\n}: {\n l10nKPIs: L10nKPIs;\n section: string;\n parentSection: string;\n}) {\n const completenessExact =\n (100 * (l10nKPIs.total - l10nKPIs.missing)) / l10nKPIs.total;\n const completenessStr = completenessExact.toFixed(1) + \"%\";\n const freshnessExact = (100 * l10nKPIs.upToDate) / l10nKPIs.total;\n const freshnessStr = freshnessExact.toFixed(1) + \"%\";\n return (\n <div className=\"documents\">\n <h2>Localization dashboard for: {section || \"/\"}</h2>\n <p>\n Parent section:{\" \"}\n <a href={`dashboard?section=${parentSection}`}>{parentSection}</a>\n </p>\n <h3>Summary</h3>\n <dl>\n <dt>Total number of pages</dt>\n <dd>{l10nKPIs.total}</dd>\n <dt>Number of untranslated pages</dt>\n <dd>{l10nKPIs.missing}</dd>\n <dt>Number of outdated pages (older than English in Git) </dt>\n <dd>{l10nKPIs.outOfDate}</dd>\n <dt>Number of up-to-date pages</dt>\n <dd>{l10nKPIs.upToDate}</dd>\n <dt>\n <label htmlFor=\"completeness\">Localization completeness</label>\n </dt>\n <dd>\n <progress id=\"completeness\" max=\"100\" value={completenessExact}>\n {completenessStr}\n </progress>{\" \"}\n {completenessStr}\n </dd>\n <dt>\n <label htmlFor=\"freshness\">Localization freshness</label>\n </dt>\n <dd>\n <progress id=\"freshness\" max=\"100\" value={freshnessExact}>\n {freshnessStr}\n </progress>{\" \"}\n {freshnessStr}\n </dd>\n </dl>\n </div>\n );\n}\n\nfunction SubsectionTable({\n sections,\n currentSection,\n}: {\n sections: Section[];\n currentSection: string;\n}) {\n if (sections.length > 0) {\n return (\n <section id=\"subsection-table\">\n <h3>Subsections</h3>\n <table>\n <thead>\n <tr>\n <th>Section</th>\n <th>Total / Untranslated / Out of date</th>\n <th>Completeness</th>\n <th>Freshness</th>\n </tr>\n </thead>\n <tbody>\n {sections\n .sort(\n (sectionA, sectionB) =>\n sectionB.l10nKPIs.total - sectionA.l10nKPIs.total\n )\n .map((section) => {\n const completenessExact =\n (100 * (section.l10nKPIs.total - section.l10nKPIs.missing)) /\n section.l10nKPIs.total;\n const completenessStr = completenessExact.toFixed(1) + \"%\";\n const freshnessExact =\n (100 * section.l10nKPIs.upToDate) / section.l10nKPIs.total;\n const freshnessStr = freshnessExact.toFixed(1) + \"%\";\n const sectionHref =\n \"dashboard?section=%2F\" + encodeURIComponent(section.name);\n return (\n <tr key={section.name}>\n <td>\n <a href={sectionHref}>\n {section.name\n .replace(currentSection.slice(1), \"\")\n .replace(\"/\", \"\")}\n </a>\n </td>\n <td>\n {section.l10nKPIs.total} / {section.l10nKPIs.missing} /{\" \"}\n {section.l10nKPIs.outOfDate}\n </td>\n <td>\n <progress max=\"100\" value={completenessExact}>\n {completenessStr}\n </progress>{\" \"}\n {completenessStr}\n </td>\n <td>\n <progress max=\"100\" value={freshnessExact}>\n {freshnessStr}\n </progress>{\" \"}\n {freshnessStr}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </section>\n );\n } else {\n return null;\n }\n}\n\nfunction DocumentsTable({\n documents,\n sort,\n sortReverse,\n locale,\n}: {\n documents: DetailDocument[];\n sort: string;\n sortReverse: boolean;\n locale: string;\n}) {\n const [searchParams, setSearchParams] = useSearchParams();\n const currentSection = searchParams.get(\"section\") || \"\";\n documents.map((documentDetail) => {\n if (documentDetail.info.localeInfo) {\n const dateLocale = new Date(documentDetail.info.localeInfo.modified);\n const dateDefaultLocale = new Date(\n documentDetail.info.defaultLocaleInfo.modified\n );\n const dateDiff = dateLocale.getTime() - dateDefaultLocale.getTime();\n documentDetail.info.dateDiff = dateDiff;\n } else {\n documentDetail.info.dateDiff = Number.POSITIVE_INFINITY;\n }\n return documentDetail;\n });\n\n function TableHead({\n id,\n title,\n sortable,\n }: {\n id: string;\n title: string;\n sortable?: boolean;\n }) {\n function getClassName() {\n const className = [\"sortable\"];\n\n if (sort === id) {\n className.push(\"active\");\n }\n\n if (sortReverse) {\n className.push(\"reverse\");\n }\n\n return className.join(\" \");\n }\n\n function onClick() {\n if (sort === id) {\n setSearchParams(\n createSearchParams({\n sort: id,\n sortReverse: JSON.stringify(!sortReverse),\n section: currentSection,\n })\n );\n } else {\n setSearchParams(\n createSearchParams({ sort: id, section: currentSection })\n );\n }\n }\n\n return sortable ? (\n <th className={getClassName()} onClick={onClick}>\n {title} <Icon name=\"small-arrow\" />\n </th>\n ) : (\n <th>{title}</th>\n );\n }\n\n return (\n <section id=\"documents-table\">\n <h3>List of direct subpages</h3>\n\n <table>\n <thead>\n <tr>\n <TableHead id=\"url\" title=\"Slug\" sortable />\n <TableHead id=\"enMDNURL\" title=\"English doc on MDN\" />\n <TableHead\n id=\"enCommitGHURL\"\n title=\"English doc commit on GitHub\"\n />\n <TableHead id=\"localURL\" title=\"Local localized doc\" />\n <TableHead id=\"localMDNURL\" title=\"Localized doc on MDN\" />\n <TableHead\n id=\"localCommitGHURL\"\n title=\"Localized doc commit on GitHub\"\n />\n <TableHead\n id=\"popularityEn\"\n title=\"Popularity rank (en-US)\"\n sortable\n />\n <TableHead\n id=\"popularityLocale\"\n title={`Popularity rank (${locale})`}\n sortable\n />\n <TableHead id=\"dateDiff\" title=\"Date delta\" sortable />\n </tr>\n </thead>\n\n <tbody>\n {documents\n .sort((A, B) => {\n let reverse = sortReverse ? -1 : 1;\n if (sort === \"dateDiff\") {\n const a = A.info.dateDiff || Number.POSITIVE_INFINITY;\n const b = B.info.dateDiff || Number.POSITIVE_INFINITY;\n return reverse * (b - a);\n } else if (sort === \"popularityLocale\") {\n const a =\n A.info.localePopularity?.ranking || Number.POSITIVE_INFINITY;\n const b =\n B.info.localePopularity?.ranking || Number.POSITIVE_INFINITY;\n return reverse * (a - b);\n } else if (sort === \"popularityEn\") {\n const a = A.info.popularity.ranking || Number.POSITIVE_INFINITY;\n const b = B.info.popularity.ranking || Number.POSITIVE_INFINITY;\n return reverse * (a - b);\n } else if (sort === \"url\") {\n const a = A.url;\n const b = B.url;\n return reverse * a.localeCompare(b);\n } else {\n throw new Error(`Unrecognized sort '${sort}'`);\n }\n })\n .map((documentDetail) => {\n const url = \"https://developer.mozilla.org\" + documentDetail.url;\n const englishCommitHash =\n documentDetail.info.defaultLocaleInfo.commitURL\n .split(\"commit/\")[1]\n .substring(0, 7);\n const localeCommitHash = documentDetail.info.localeInfo?.commitURL\n .split(\"commit/\")[1]\n .substring(0, 7);\n let status = \"Untranslated\";\n if (documentDetail.info.localeInfo) {\n let dateDiff =\n documentDetail.info.dateDiff ?? Number.POSITIVE_INFINITY;\n status = \"Out of date\";\n\n if (dateDiff > 0) {\n status = \"Fresher than English\";\n } else if (dateDiff > -2678400000) {\n const nbDays = Math.round(-dateDiff / (3600 * 24 * 1000));\n status = nbDays + \" day\" + (nbDays > 1 ? \"s\" : \"\");\n } else {\n const nbMonths = Math.round(\n -dateDiff / (3600 * 24 * 1000 * 30)\n );\n status = nbMonths + \" month\" + (nbMonths > 1 ? \"s\" : \"\");\n }\n }\n return (\n <tr key={documentDetail.url}>\n <td>\n <a href={documentDetail.url}>{documentDetail.url}</a>\n </td>\n <td>\n <a href={url}>English current MDN page</a>\n </td>\n <td>\n <a href={documentDetail.info.defaultLocaleInfo.commitURL}>\n GitHub link for <code>{englishCommitHash}</code>\n </a>\n </td>\n <td>\n {documentDetail.info.localeInfo && (\n <a\n href={documentDetail.url.replace(\n \"/en-US/\",\n \"/\" + locale + \"/\"\n )}\n >\n Local {locale} page\n </a>\n )}\n </td>\n <td>\n {documentDetail.info.localeInfo && (\n <a href={url.replace(\"/en-US/\", \"/\" + locale + \"/\")}>\n Locale current MDN page\n </a>\n )}\n </td>\n <td>\n {documentDetail.info.localeInfo && (\n <a href={documentDetail.info.localeInfo.commitURL}>\n GitHub link for <code>{localeCommitHash}</code>\n </a>\n )}\n </td>\n <td>{documentDetail.info.popularity.ranking}</td>\n <td>\n {documentDetail.info.localePopularity &&\n documentDetail.info.localePopularity.ranking}\n </td>\n <td>{status}</td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </section>\n );\n}\n","import React from \"react\";\nimport { Link, Routes, Route } from \"react-router-dom\";\nimport useSWR from \"swr\";\n\nimport \"./index.scss\";\n\nimport { Loading } from \"../ui/atoms/loading\";\nimport { MainContentContainer } from \"../ui/atoms/page-content\";\n\nimport { TranslationDifferences } from \"./differences\";\nimport { MissingTranslations } from \"./missing\";\nimport { TranslationDashboard } from \"./dashboard\";\nimport { useLocale } from \"../hooks\";\n\ninterface Locale {\n locale: string;\n language: {\n English: string;\n native: string;\n };\n isActive: boolean;\n count: number;\n}\n\ninterface LocalesData {\n locales: Locale[];\n}\n\nexport default function Translations() {\n return (\n <Container>\n <Routes>\n <Route path=\"/\" element={<PickLocale />} />\n <Route path=\"differences\" element={<TranslationDifferences />} />\n <Route path=\"missing\" element={<MissingTranslations />} />\n <Route path=\"dashboard\" element={<TranslationDashboard />} />\n </Routes>\n </Container>\n );\n}\n\nfunction PickLocale() {\n const locale = useLocale();\n React.useEffect(() => {\n let title = \"All translations\";\n if (locale.toLowerCase() !== \"en-us\") {\n title += ` for ${locale}`;\n }\n document.title = title;\n }, [locale]);\n\n const { data: dataLocales, error: errorLocales } = useSWR<LocalesData, Error>(\n locale.toLowerCase() === \"en-us\" ? \"/_translations/\" : null,\n async (url) => {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`${response.status} (${await response.text()})`);\n }\n return response.json();\n }\n );\n\n if (locale.toLowerCase() === \"en-us\") {\n return (\n <>\n {!dataLocales && !errorLocales && <Loading />}\n {errorLocales && (\n <div className=\"error-message\">\n <h3>Server error</h3>\n <pre>{errorLocales.toString()}</pre>\n </div>\n )}\n {dataLocales && <ShowLocales locales={dataLocales.locales} />}\n </>\n );\n }\n\n return (\n <div className=\"translation-choices\">\n <Link to={`/${locale}/_translations/differences`} className=\"button\">\n Translation differences\n </Link>{\" \"}\n <Link to={`/${locale}/_translations/missing`} className=\"button\">\n Missing translations\n </Link>{\" \"}\n <Link to={`/${locale}/_translations/dashboard`} className=\"button\">\n Dashboard\n </Link>\n </div>\n );\n}\n\nfunction Container({ children }: { children: React.ReactNode }) {\n return (\n <MainContentContainer className=\"all-translations\" standalone={true}>\n {children}\n </MainContentContainer>\n );\n}\n\nfunction ShowLocales({ locales }: { locales: Locale[] }) {\n return (\n <div>\n <h2>Select locale</h2>\n <table>\n <tbody>\n {locales.map((locale) => {\n return (\n <tr key={locale.locale}>\n <td>\n <b>\n {locale.language.English} ({locale.locale})\n </b>{\" \"}\n {!locale.isActive && <small>not active</small>}\n </td>\n <td>{locale.count.toLocaleString()} documents</td>\n <td>\n <Link to={`/${locale.locale}/_translations/differences`}>\n Translation differences\n </Link>{\" \"}\n </td>\n <td>\n <Link to={`/${locale.locale}/_translations/missing`}>\n Missing translations\n </Link>{\" \"}\n </td>\n <td>\n <Link to={`/${locale.locale}/_translations/dashboard`}>\n Dashboard\n </Link>{\" \"}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n","import { Link, useSearchParams } from \"react-router-dom\";\nimport { range } from \"../../../utils\";\n\nconst PARAM = \"page\";\n\nfunction PageLink({\n page,\n children,\n onClick,\n disabled,\n}: {\n page: number;\n children?: React.ReactNode;\n onClick?: (page: number) => unknown;\n disabled?: boolean;\n}) {\n const [searchParams, setSearchParams] = useSearchParams();\n\n return (\n <Link\n to={{}}\n className={disabled ? \"disabled\" : \"\"}\n onClick={(event) => {\n event.preventDefault();\n if (disabled) {\n return;\n }\n\n onClick && onClick(page);\n setSearchParams({\n ...Object.fromEntries(searchParams.entries()),\n [PARAM]: page.toString(),\n });\n\n window.setTimeout(() => document.documentElement.scrollTo());\n }}\n >\n {children || page}\n </Link>\n );\n}\n\nexport function Paginator({\n first = 1,\n last,\n endPadding = 2,\n middlePadding = 2,\n onChange,\n}: {\n first?: number;\n last: number;\n endPadding?: number;\n middlePadding?: number;\n onChange?: (page: number, oldPage: number) => unknown;\n}) {\n const [searchParams] = useSearchParams();\n const current = parseInt(searchParams.get(PARAM) || \"\", 10) || first;\n const middleFirst = Math.max(current - middlePadding, first);\n const middleLast = Math.min(middleFirst + middlePadding * 2 + 1, last + 1);\n const left = range(first, Math.min(endPadding, middleFirst));\n const middle = range(middleFirst, middleLast);\n const right = range(Math.max(last + 1 - endPadding, middleLast), last + 1);\n\n const onClick = (page: number) => {\n onChange && onChange(page, current);\n };\n\n if (first === last) {\n // There are no pages, so return nothing\n return <></>;\n }\n\n return (\n <div className=\"pagination\">\n <PageLink\n page={current - 1}\n onClick={onClick}\n disabled={current === first}\n >\n ← Previous\n </PageLink>\n {left.map((page) => (\n <PageLink key={page} page={page} onClick={onClick} />\n ))}\n {Boolean(left.length) && left[left.length - 1] + 1 !== middle[0] && \"…\"}\n {middle.map((page) =>\n current === page ? (\n <span className=\"current-page\" key={page}>\n {page}\n </span>\n ) : (\n <PageLink key={page} page={page} onClick={onClick} />\n )\n )}\n {Boolean(right.length) &&\n middle[middle.length - 1] + 1 !== right[0] &&\n \"…\"}\n {right.map((page) => (\n <PageLink key={page} page={page} onClick={onClick} />\n ))}\n <PageLink\n page={current + 1}\n onClick={onClick}\n disabled={current === last}\n >\n Next →\n </PageLink>\n </div>\n );\n}\n"],"names":["dayjs","relativeTime","LOCALSTORAGE_KEY","saveStorage","locale","data","stored","JSON","localStorage","Object","err","console","TranslationDifferences","useLocale","searchParams","_useSearchParams","navigate","useNavigate","_React_useState","lastData","setLastData","React","title","document","_useSWR","url","response","fetch","Error","n","error","isValidating","startTime","lastLoadTime","Date","lastStorageData","getStorage","defaultSort","defaultSortReverse","sort","sortReverse","Container","Loading","Link","ShowSearchError","FilterControls","DocumentsTable","BuildTimes","param","children","MainContentContainer","ms","times","s","Math","estimate","startLoadingTime","estimateEndTime","setIncrements","_React_useState1","interval","setInterval","state","clearInterval","distance","elapsed","percent","setSearchParams","setTitle","setURL","_React_useState2","differences","setDifferences","refreshFilters","reset","filterParams","createSearchParams","_iter","key","value","event","counts","documents","page","parseInt","pageSize","filterTitle","filterURL","filterDifferences","filterDifferencesOperation","getNumericOperation","expression","parseIntOrThrow","v","parsed","isNaN","TableHead","id","filteredDocuments","document1","matchNumericOperation","op","A","B","reverse","a","b","a1","b1","a2","b2","a3","b3","a4","b4","_A_edits_sourceCommitsBehindCount","_B_edits_sourceCommitsBehindCount","a5","b5","pageCount","doc","HighlightedText","BriefURL","getGetOrdinal","LastModified","L10nSourceCommitModified","Paginator","sourceCommitsBehindCount","sourceCommitURL","edits","modified","parentModified","text","highlight","parts","RegExp","part","i","uri","_uri_split","left","right","MissingTranslations","TranslationDashboard","currentSection","parentSection","arrPathSection","ShowError","SectionHeader","SubsectionTable","l10nKPIs","section","completenessExact","completenessStr","freshnessExact","freshnessStr","sections","sectionA","sectionB","sectionHref","encodeURIComponent","className","sortable","Icon","documentDetail","dateLocale","dateDefaultLocale","dateDiff","Number","_A_info_localePopularity","_B_info_localePopularity","englishCommitHash","localeCommitHash","_documentDetail_info_localeInfo","status","_documentDetail_info_dateDiff","nbDays","nbMonths","Translations","Routes","Route","PickLocale","dataLocales","errorLocales","ShowLocales","locales","PARAM","PageLink","onClick","disabled","window","first","last","endPadding","middlePadding","onChange","current","middleFirst","middleLast","range","middle","Boolean"],"mappings":"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"}
1
+ {"version":3,"file":"7510.faa07a788cad6fc7.js","sources":["webpack://@mdn/fred/./node_modules/@mdn/yari/client/src/translations/differences/index.tsx","webpack://@mdn/fred/./node_modules/@mdn/yari/client/src/translations/missing/index.tsx","webpack://@mdn/fred/./node_modules/@mdn/yari/client/src/translations/dashboard/index.tsx","webpack://@mdn/fred/./node_modules/@mdn/yari/client/src/translations/index.tsx","webpack://@mdn/fred/./node_modules/@mdn/yari/client/src/ui/molecules/paginator/index.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n createSearchParams,\n Link,\n useSearchParams,\n useNavigate,\n} from \"react-router-dom\";\nimport useSWR from \"swr\";\nimport dayjs from \"dayjs\";\nimport relativeTime from \"dayjs/plugin/relativeTime\";\n\nimport \"./index.scss\";\n\nimport { MainContentContainer } from \"../../ui/atoms/page-content\";\nimport { Paginator } from \"../../ui/molecules/paginator\";\nimport { useLocale } from \"../../hooks\";\n\ndayjs.extend(relativeTime);\n\ninterface DocumentPopularity {\n value: number;\n ranking: number;\n parentValue: number;\n parentRanking: number;\n}\n\ntype CountByType = { [key: string]: number };\n\ninterface DocumentDifferences {\n countByType: CountByType;\n total: number;\n}\n\ninterface DocumentEdits {\n modified: string;\n parentModified: string;\n commitURL: string;\n parentCommitURL: string;\n sourceCommitsBehindCount?: number;\n sourceCommitURL?: string;\n}\n\ninterface Document {\n mdn_url: string;\n edits: DocumentEdits;\n title: string;\n popularity: DocumentPopularity;\n differences: DocumentDifferences;\n}\n\ninterface Counts {\n found: number;\n total: number;\n pages: number;\n noParents: number;\n cacheMisses: number;\n}\n\ninterface Times {\n took: number;\n}\n\ninterface FlawLevel {\n name: string;\n level: string;\n ignored: boolean;\n}\n\ninterface Data {\n counts: Counts;\n documents: Document[];\n times: Times;\n flawLevels: FlawLevel[];\n}\n\ninterface LocaleStorageData {\n lastLoadTime?: number;\n defaultSort?: string;\n defaultSortReverse?: string;\n}\n\ninterface StorageData {\n [locale: string]: LocaleStorageData;\n}\n\nconst LOCALSTORAGE_KEY = \"translations-dashboard-differences\";\n\nfunction saveStorage(locale: string, data: LocaleStorageData) {\n try {\n const stored = JSON.parse(\n localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\"\n ) as StorageData;\n stored[locale] = Object.assign({}, stored[locale] || {}, data);\n localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(stored));\n } catch (err) {\n console.warn(\"Unable to save to localStorage\", err);\n }\n}\n\nfunction getStorage(locale: string): LocaleStorageData | null {\n try {\n const stored = JSON.parse(localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\");\n if (stored) {\n return stored[locale] as LocaleStorageData;\n }\n } catch (err) {\n console.warn(\"Unable to retrieve from localStorage\", err);\n }\n return null;\n}\n\nexport function TranslationDifferences() {\n const locale = useLocale();\n const [searchParams] = useSearchParams();\n const navigate = useNavigate();\n\n const [lastData, setLastData] = React.useState<Data | null>(null);\n\n React.useEffect(() => {\n if (locale.toLowerCase() === \"en-us\") {\n navigate(`/${locale}/_translations`);\n }\n }, [locale, navigate]);\n\n React.useEffect(() => {\n let title = \"All translations\";\n if (locale.toLowerCase() !== \"en-us\") {\n title += ` for ${locale}`;\n }\n if (lastData) {\n title = `(${lastData.counts.found.toLocaleString()} found) ${title}`;\n }\n document.title = title;\n }, [lastData, locale]);\n\n const { data, error, isValidating } = useSWR<Data, Error>(\n locale.toLowerCase() !== \"en-us\"\n ? `/_translations/differences/?locale=${locale}`\n : null,\n async (url) => {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`${response.status} (${await response.text()})`);\n }\n if (\n !(response.headers.get(\"content-type\") || \"\").includes(\n \"application/json\"\n )\n ) {\n throw new Error(\n `Response is not JSON (${response.headers.get(\"content-type\")})`\n );\n }\n return response.json();\n },\n {\n revalidateOnFocus: false,\n }\n );\n\n // Use this to be able to figure out how long the XHR takes when there's no cache\n const startTime = React.useRef<Date>();\n React.useEffect(() => {\n if (locale) {\n if (!data) {\n startTime.current = new Date();\n } else {\n if (\n data.counts.cacheMisses > 0 &&\n data.counts.cacheMisses === data.counts.total &&\n startTime.current\n ) {\n const lastLoadTime =\n new Date().getTime() - startTime.current.getTime();\n saveStorage(locale, { lastLoadTime });\n }\n }\n }\n }, [locale, data]);\n\n React.useEffect(() => {\n if (data) {\n setLastData(data);\n }\n }, [data]);\n\n const lastStorageData = getStorage(locale);\n const defaultSort = lastStorageData?.defaultSort || \"modified\";\n const defaultSortReverse = lastStorageData?.defaultSortReverse || \"false\";\n const sort = searchParams.get(\"sort\") || defaultSort;\n const sortReverse = JSON.parse(\n searchParams.get(\"sortReverse\") || defaultSortReverse\n );\n\n React.useEffect(() => {\n saveStorage(\n locale,\n Object.assign({}, lastStorageData, {\n defaultSort: sort,\n defaultSortReverse: sortReverse,\n })\n );\n }, [locale, sort, sortReverse, lastStorageData]);\n\n if (locale.toLowerCase() === \"en-us\") {\n return null;\n }\n\n return (\n <Container>\n {lastData && !error && isValidating && (\n <p style={{ float: \"right\" }}>Reloading...</p>\n )}\n {!data && !error && !lastData && (\n <Loading\n estimate={\n (lastStorageData && lastStorageData.lastLoadTime) || 30 * 1000\n }\n />\n )}\n {lastData && (\n <p style={{ textAlign: \"right\" }}>\n Go to{\" \"}\n <Link to={`/${locale}/_translations/missing`}>\n Missing translations for <b>{locale}</b>\n </Link>\n </p>\n )}\n {error && <ShowSearchError error={error} />}\n {lastData && (\n <div className=\"filter-documents\">\n <FilterControls />\n <DocumentsTable\n locale={locale}\n counts={lastData.counts}\n documents={lastData.documents}\n sort={sort}\n sortReverse={sortReverse}\n />\n </div>\n )}\n {data && <BuildTimes times={data.times} />}\n </Container>\n );\n}\n\nfunction Container({ children }: { children: React.ReactNode }) {\n return (\n <MainContentContainer className=\"all-translations\" standalone={true}>\n {children}\n </MainContentContainer>\n );\n}\n\nfunction ShowSearchError({ error }) {\n return (\n <div className=\"error-message search-error\">\n <h3>Search error</h3>\n <pre>{error.toString()}</pre>\n </div>\n );\n}\n\nfunction BuildTimes({ times }: { times: Times }) {\n function format(ms: number) {\n if (ms > 1000) {\n const s = ms / 1000;\n return `${s.toFixed(1)} seconds`;\n } else {\n return `${Math.trunc(ms)} milliseconds`;\n }\n }\n return (\n <div className=\"search-times\">\n <p>Time to find all documents {format(times.took)}</p>\n </div>\n );\n}\n\nfunction Loading({ estimate }: { estimate: number }) {\n const startLoadingTime = new Date();\n const [estimateEndTime] = React.useState(\n new Date(startLoadingTime.getTime() + estimate)\n );\n\n const [, setIncrements] = React.useState(0);\n React.useEffect(() => {\n const interval = setInterval(() => {\n setIncrements((state) => state + 1);\n }, 1000);\n return () => clearInterval(interval);\n }, []);\n\n const distance = estimateEndTime.getTime() - startLoadingTime.getTime();\n const elapsed = new Date().getTime() - startLoadingTime.getTime();\n const percent = (100 * elapsed) / distance;\n return (\n <div className=\"loading\">\n <progress id=\"progress\" max=\"100\" value={percent} style={{ margin: 20 }}>\n {percent}%\n </progress>\n <br />\n <small>\n Estimated time to finish: {((distance - elapsed) / 1000).toFixed(0)}s{\" \"}\n {elapsed > distance ? (\n <span aria-label=\"weird\" role=\"img\">\n 🙃\n </span>\n ) : null}\n </small>\n </div>\n );\n}\n\nfunction FilterControls() {\n const [searchParams, setSearchParams] = useSearchParams();\n const [title, setTitle] = React.useState(searchParams.get(\"title\") || \"\");\n const [url, setURL] = React.useState(searchParams.get(\"url\") || \"\");\n const [differences, setDifferences] = React.useState(\n searchParams.get(\"differences\") || \"\"\n );\n\n function refreshFilters(reset = false) {\n const filterParams = createSearchParams(searchParams);\n for (const [key, value] of [\n [\"url\", url],\n [\"title\", title],\n [\"differences\", differences],\n ]) {\n if (!reset && value) {\n filterParams.set(key, value);\n } else {\n filterParams.delete(key);\n }\n }\n filterParams.delete(\"page\");\n setSearchParams(filterParams);\n }\n\n function resetFilters() {\n setURL(\"\");\n setTitle(\"\");\n setDifferences(\"\");\n refreshFilters(true);\n }\n\n return (\n <div className=\"filters\">\n <h3>Filters</h3>\n <form\n onSubmit={(event) => {\n event.preventDefault();\n refreshFilters();\n }}\n >\n <div>\n <h4>Document</h4>\n <input\n type=\"search\"\n placeholder=\"Filter by document URI\"\n value={url}\n onChange={(event) => {\n setURL(event.target.value);\n }}\n onBlur={() => refreshFilters()}\n />\n <input\n type=\"search\"\n placeholder=\"Filter by document title\"\n value={title}\n onChange={(event) => {\n setTitle(event.target.value);\n }}\n onBlur={() => refreshFilters()}\n />\n </div>\n <div>\n <h4>Differences</h4>\n <input\n type=\"text\"\n placeholder=\"E.g. >0 or >=5\"\n value={differences}\n onChange={(event) => {\n setDifferences(event.target.value);\n }}\n onBlur={() => refreshFilters()}\n />\n </div>\n\n <div>\n <h4>&nbsp;</h4>\n <button type=\"submit\">Filter now</button>{\" \"}\n {(url || title) && (\n <button type=\"button\" onClick={resetFilters}>\n Reset filters\n </button>\n )}\n </div>\n </form>\n </div>\n );\n}\ntype NumericOperation = {\n operation: \"eq\" | \"gt\" | \"gte\" | \"lt\" | \"lte\";\n value: number;\n};\n\nfunction getNumericOperation(expression: string): NumericOperation | null {\n function parseIntOrThrow(v: string) {\n if (!v) {\n throw new Error(\"Can't be empty\");\n }\n\n const parsed = parseInt(v, 10);\n if (isNaN(parsed)) {\n throw new Error(`'${v}' not a valid number`);\n }\n return parsed;\n }\n try {\n if (expression.startsWith(\">=\")) {\n return {\n operation: \"gte\",\n value: parseIntOrThrow(expression.replace(\">=\", \"\")),\n };\n } else if (expression.startsWith(\">\")) {\n return {\n operation: \"gt\",\n value: parseIntOrThrow(expression.replace(\">\", \"\")),\n };\n } else if (expression.startsWith(\"<=\")) {\n return {\n operation: \"lte\",\n value: parseIntOrThrow(expression.replace(\"<=\", \"\")),\n };\n } else if (expression.startsWith(\"<\")) {\n return {\n operation: \"lt\",\n value: parseIntOrThrow(expression.replace(\"<\", \"\")),\n };\n } else if (expression.startsWith(\"==\") || expression.startsWith(\"=\")) {\n return {\n operation: \"eq\",\n value: parseIntOrThrow(expression.replace(/=/g, \"\")),\n };\n } else if (expression) {\n return {\n operation: \"eq\",\n value: parseIntOrThrow(expression),\n };\n } else {\n return null;\n }\n } catch (error) {\n console.warn(error);\n return null;\n }\n}\n\nfunction matchNumericOperation(value: number, op: NumericOperation): boolean {\n if (op.operation === \"eq\") {\n if (value !== op.value) {\n return false;\n }\n } else if (op.operation === \"gt\") {\n if (!(value > op.value)) {\n return false;\n }\n } else if (op.operation === \"gte\") {\n if (!(value >= op.value)) {\n return false;\n }\n } else if (op.operation === \"lt\") {\n if (!(value < op.value)) {\n return false;\n }\n } else if (op.operation === \"lte\") {\n if (!(value <= op.value)) {\n return false;\n }\n } else {\n throw new Error(`Not implemented operation '${op.operation}'`);\n }\n return true;\n}\n\nfunction DocumentsTable({\n locale,\n counts,\n documents,\n sort,\n sortReverse,\n}: {\n locale: string;\n counts: Counts;\n documents: Document[];\n sort: string;\n sortReverse: boolean;\n}) {\n const [searchParams, setSearchParams] = useSearchParams();\n\n const page = parseInt(searchParams.get(\"page\") || \"1\", 10);\n const pageSize = parseInt(searchParams.get(\"pageSize\") || \"20\", 10);\n const filterTitle = searchParams.get(\"title\") || \"\";\n const filterURL = searchParams.get(\"url\") || \"\";\n const filterDifferences = searchParams.get(\"differences\") || \"\";\n const filterDifferencesOperation = getNumericOperation(filterDifferences);\n\n function TableHead({ id, title }: { id: string; title: string }) {\n return (\n <th\n onClick={() => {\n if (sort === id) {\n setSearchParams(\n createSearchParams({\n sort: id,\n sortReverse: JSON.stringify(!sortReverse),\n })\n );\n } else {\n setSearchParams(createSearchParams({ sort: id }));\n }\n }}\n className=\"sortable\"\n >\n {title} {sort === id ? (sortReverse ? \"↓\" : \"↑\") : null}\n </th>\n );\n }\n\n const filteredDocuments = documents\n .filter((document) => {\n if (\n filterTitle &&\n !document.title.toLowerCase().includes(filterTitle.toLowerCase())\n ) {\n return false;\n }\n\n if (\n filterURL &&\n !document.mdn_url.toLowerCase().includes(filterURL.toLowerCase())\n ) {\n return false;\n }\n\n if (\n filterDifferencesOperation &&\n !matchNumericOperation(\n document.differences.total,\n filterDifferencesOperation\n )\n ) {\n return false;\n }\n\n return true;\n })\n .sort((A, B) => {\n let reverse = sortReverse ? -1 : 1;\n if (sort === \"modified\") {\n const a = new Date(A.edits.modified);\n const b = new Date(B.edits.modified);\n return reverse * (b.getTime() - a.getTime());\n } else if (sort === \"popularity\") {\n const a = A.popularity.value;\n const b = B.popularity.value;\n return reverse * (b - a);\n } else if (sort === \"differences\") {\n const a = A.differences.total;\n const b = B.differences.total;\n return reverse * (b - a);\n } else if (sort === \"title\") {\n const a = A.title;\n const b = B.title;\n return reverse * a.localeCompare(b);\n } else if (sort === \"mdn_url\") {\n const a = A.mdn_url;\n const b = B.mdn_url;\n return reverse * a.localeCompare(b);\n } else if (sort === \"sourceCommit\") {\n const a = A.edits.sourceCommitsBehindCount ?? -1;\n const b = B.edits.sourceCommitsBehindCount ?? -1;\n return reverse * (b - a);\n } else {\n throw new Error(`Unrecognized sort '${sort}'`);\n }\n });\n const pageCount = Math.ceil(counts.found / pageSize);\n\n return (\n <div className=\"documents\">\n <h3>\n Documents with differences found (\n {filteredDocuments.length.toLocaleString()}){\" \"}\n {pageCount > 1 && (\n <span className=\"page\">\n page {page}/{pageCount}\n </span>\n )}\n </h3>\n <h4 className=\"subheader\">\n {counts.total.toLocaleString()} total documents found ({locale})\n </h4>\n\n {filterDifferences && !filterDifferencesOperation && (\n <div className=\"error-message\">\n <h3>Invalid differences filter</h3>\n <p>\n The <i>differences</i> filter can't be parsed.\n <br />\n <code>{filterDifferences}</code>\n </p>\n </div>\n )}\n\n <table>\n <thead>\n <tr>\n <TableHead id=\"title\" title=\"Document\" />\n <TableHead id=\"popularity\" title=\"Popularity\" />\n <TableHead id=\"modified\" title=\"Last modified\" />\n <TableHead id=\"differences\" title=\"Differences\" />\n <TableHead id=\"sourceCommit\" title=\"Source Commit\" />\n </tr>\n </thead>\n <tbody>\n {filteredDocuments\n .slice((page - 1) * pageSize, page * pageSize)\n .map((doc: Document) => {\n return (\n <tr key={doc.mdn_url}>\n <td>\n <span className=\"document-title-preview\">\n {filterTitle ? (\n <HighlightedText\n text={doc.title}\n highlight={filterTitle}\n />\n ) : (\n doc.title\n )}\n </span>\n <br />\n <Link\n to={`${doc.mdn_url}#_flaws`}\n title={doc.title}\n target=\"_blank\"\n >\n <BriefURL uri={doc.mdn_url} filterURL={filterURL} />\n </Link>\n </td>\n <td\n title={\n doc.popularity.ranking\n ? `Meaning there are ${\n doc.popularity.ranking - 1\n } more popular pages than this`\n : \"Meaning it has no ranking. Most likely a very rare (or new) document\"\n }\n >\n {!doc.popularity.ranking\n ? \"n/a\"\n : `${getGetOrdinal(doc.popularity.ranking)}`}{\" \"}\n <small title=\"For the parent document\">\n (\n {!doc.popularity.parentRanking\n ? \"n/a\"\n : `${getGetOrdinal(doc.popularity.parentRanking)}`}\n )\n </small>\n </td>\n <td>\n <LastModified edits={doc.edits} />\n </td>\n <td>{doc.differences.total.toLocaleString()}</td>\n <td>\n <L10nSourceCommitModified\n sourceCommitsBehindCount={\n doc.edits.sourceCommitsBehindCount\n }\n sourceCommitURL={doc.edits.sourceCommitURL}\n />\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n\n <Paginator last={pageCount} />\n </div>\n );\n}\n\nfunction L10nSourceCommitModified({\n sourceCommitsBehindCount,\n sourceCommitURL,\n}: Pick<DocumentEdits, \"sourceCommitsBehindCount\" | \"sourceCommitURL\">) {\n if (\n !sourceCommitURL ||\n (!sourceCommitsBehindCount && sourceCommitsBehindCount !== 0)\n ) {\n return <>Metadata does not exist.</>;\n }\n\n const getImportanceColor = () => {\n if (sourceCommitsBehindCount === 0) return \"🟢\";\n return sourceCommitsBehindCount < 10 ? \"🟠\" : \"🔴\";\n };\n\n return (\n <a\n href={sourceCommitURL}\n >{`${getImportanceColor()} ${sourceCommitsBehindCount} commits behind`}</a>\n );\n}\n\nfunction LastModified({ edits }: { edits: DocumentEdits }) {\n const modified = dayjs(edits.modified);\n const parentModified = dayjs(edits.parentModified);\n return (\n <span\n className={`last_modified ${\n parentModified < modified ? \"ahead\" : \"behind\"\n }`}\n >\n <a href={edits.commitURL} target=\"_blank\" rel=\"noreferrer\">\n <time dateTime={modified.toISOString()} title={modified.toISOString()}>\n {modified.fromNow()}\n </time>\n </a>\n <br />\n <a href={edits.parentCommitURL} target=\"_blank\" rel=\"noreferrer\">\n <small>\n <time\n dateTime={parentModified.toISOString()}\n title={parentModified.toISOString()}\n >\n en-US {parentModified.fromNow()}\n </time>\n </small>\n </a>\n </span>\n );\n}\n\nfunction HighlightedText({\n text,\n highlight,\n}: {\n text: string;\n highlight: string;\n}) {\n // Split on highlight term and include term into parts, ignore case\n const parts = text.split(new RegExp(`(${highlight})`, \"gi\"));\n return (\n <span>\n {\" \"}\n {parts.map((part, i) => (\n <span\n key={i}\n style={\n part.toLowerCase() === highlight.toLowerCase()\n ? { fontWeight: \"bold\" }\n : {}\n }\n >\n {part}\n </span>\n ))}{\" \"}\n </span>\n );\n}\n\nfunction BriefURL({ uri, filterURL }: { uri: string; filterURL: string }) {\n const [left, right] = uri.split(/\\/docs\\//, 2);\n return (\n <>\n <span className=\"url-prefix\">{left}/docs/</span>\n <span className=\"url-slug\">\n {filterURL ? (\n <HighlightedText text={right} highlight={filterURL} />\n ) : (\n right\n )}\n </span>\n </>\n );\n}\n\n// https://gist.github.com/jlbruno/1535691/db35b4f3af3dcbb42babc01541410f291a8e8fac\nfunction getGetOrdinal(n: number) {\n const s = [\"th\", \"st\", \"nd\", \"rd\"];\n const v = n % 100;\n return n.toLocaleString() + (s[(v - 20) % 10] || s[v] || s[0]);\n}\n","import React from \"react\";\nimport {\n createSearchParams,\n Link,\n useSearchParams,\n useNavigate,\n} from \"react-router-dom\";\nimport useSWR from \"swr\";\nimport dayjs from \"dayjs\";\nimport relativeTime from \"dayjs/plugin/relativeTime\";\n\nimport { MainContentContainer } from \"../../ui/atoms/page-content\";\nimport { Paginator } from \"../../ui/molecules/paginator\";\nimport { useLocale } from \"../../hooks\";\n\ndayjs.extend(relativeTime);\n\ninterface DocumentPopularity {\n value: number;\n ranking: number;\n parentValue: number;\n parentRanking: number;\n}\n\ntype CountByType = { [key: string]: number };\n\ninterface DocumentDifferences {\n countByType: CountByType;\n total: number;\n}\n\ninterface DocumentEdits {\n modified: string;\n parentModified: string;\n commitURL: string;\n parentCommitURL: string;\n}\n\ninterface Document {\n mdn_url: string;\n edits: DocumentEdits;\n title: string;\n popularity: DocumentPopularity;\n differences: DocumentDifferences;\n}\n\ninterface Counts {\n missing: number;\n translated: number;\n total: number;\n cacheMisses: number;\n}\n\ninterface Times {\n took: number;\n}\n\ninterface FlawLevel {\n name: string;\n level: string;\n ignored: boolean;\n}\n\ninterface Data {\n counts: Counts;\n missingDocuments: Document[];\n times: Times;\n flawLevels: FlawLevel[];\n}\n\ninterface LocaleStorageData {\n lastLoadTime?: number;\n defaultSort?: string;\n defaultSortReverse?: string;\n}\n\ninterface StorageData {\n [locale: string]: LocaleStorageData;\n}\n\nconst LOCALSTORAGE_KEY = \"translations-dashboard-missing\";\n\nfunction saveStorage(locale: string, data: LocaleStorageData) {\n try {\n const stored = JSON.parse(\n localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\"\n ) as StorageData;\n stored[locale] = Object.assign({}, stored[locale] || {}, data);\n localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(stored));\n } catch (err) {\n console.warn(\"Unable to save to localStorage\", err);\n }\n}\n\nfunction getStorage(locale: string): LocaleStorageData | null {\n try {\n const stored = JSON.parse(localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\");\n if (stored) {\n return stored[locale] as LocaleStorageData;\n }\n } catch (err) {\n console.warn(\"Unable to retrieve from localStorage\", err);\n }\n return null;\n}\n\nexport function MissingTranslations() {\n const locale = useLocale();\n const [searchParams] = useSearchParams();\n const navigate = useNavigate();\n\n const [lastData, setLastData] = React.useState<Data | null>(null);\n\n React.useEffect(() => {\n if (locale.toLowerCase() === \"en-us\") {\n navigate(`/${locale}/_translations`);\n }\n }, [locale, navigate]);\n\n React.useEffect(() => {\n let title = \"Missing translations\";\n if (locale.toLowerCase() !== \"en-us\") {\n title += ` for ${locale}`;\n }\n if (lastData) {\n title = `(${lastData.counts.missing.toLocaleString()} found) ${title}`;\n }\n document.title = title;\n }, [lastData, locale]);\n\n const { data, error, isValidating } = useSWR<Data, Error>(\n locale.toLowerCase() !== \"en-us\"\n ? `/_translations/missing/?locale=${locale}`\n : null,\n async (url) => {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`${response.status} (${await response.text()})`);\n }\n if (\n !(response.headers.get(\"content-type\") || \"\").includes(\n \"application/json\"\n )\n ) {\n throw new Error(\n `Response is not JSON (${response.headers.get(\"content-type\")})`\n );\n }\n return response.json();\n },\n {\n revalidateOnFocus: false,\n }\n );\n\n // Use this to be able to figure out how long the XHR takes when there's no cache\n const startTime = React.useRef<Date>();\n React.useEffect(() => {\n if (locale) {\n if (!data) {\n startTime.current = new Date();\n } else {\n if (\n data.counts.cacheMisses > 0 &&\n data.counts.cacheMisses === data.counts.total &&\n startTime.current\n ) {\n const lastLoadTime =\n new Date().getTime() - startTime.current.getTime();\n saveStorage(locale, { lastLoadTime });\n }\n }\n }\n }, [locale, data]);\n\n React.useEffect(() => {\n if (data) {\n setLastData(data);\n }\n }, [data]);\n\n const lastStorageData = getStorage(locale);\n const defaultSort = lastStorageData?.defaultSort || \"popularity\";\n const defaultSortReverse = lastStorageData?.defaultSortReverse || \"false\";\n const sort = searchParams.get(\"sort\") || defaultSort;\n const sortReverse = JSON.parse(\n searchParams.get(\"sortReverse\") || defaultSortReverse\n );\n\n React.useEffect(() => {\n saveStorage(\n locale,\n Object.assign({}, lastStorageData, {\n defaultSort: sort,\n defaultSortReverse: sortReverse,\n })\n );\n }, [locale, sort, sortReverse, lastStorageData]);\n\n if (locale.toLowerCase() === \"en-us\") {\n return null;\n }\n\n return (\n <Container>\n {lastData && !error && isValidating && (\n <p style={{ float: \"right\" }}>Reloading...</p>\n )}\n {!data && !error && !lastData && (\n <Loading\n estimate={\n (lastStorageData && lastStorageData.lastLoadTime) || 30 * 1000\n }\n />\n )}\n {lastData && (\n <p style={{ textAlign: \"right\" }}>\n Go to{\" \"}\n <Link to={`/${locale}/_translations/differences`}>\n Translation differences for <b>{locale}</b>\n </Link>\n </p>\n )}\n {error && <ShowSearchError error={error} />}\n {lastData && (\n <div className=\"filter-documents\">\n <FilterControls />\n <DocumentsTable\n counts={lastData.counts}\n documents={lastData.missingDocuments}\n sort={sort}\n sortReverse={sortReverse}\n />\n </div>\n )}\n {data && <BuildTimes times={data.times} />}\n </Container>\n );\n}\n\nfunction Container({ children }: { children: React.ReactNode }) {\n return (\n <MainContentContainer className=\"missing-translations\" standalone={true}>\n {children}\n </MainContentContainer>\n );\n}\n\nfunction ShowSearchError({ error }) {\n return (\n <div className=\"error-message search-error\">\n <h3>Search error</h3>\n <pre>{error.toString()}</pre>\n </div>\n );\n}\n\nfunction BuildTimes({ times }: { times: Times }) {\n function format(ms: number) {\n if (ms > 1000) {\n const s = ms / 1000;\n return `${s.toFixed(1)} seconds`;\n } else {\n return `${Math.trunc(ms)} milliseconds`;\n }\n }\n return (\n <div className=\"search-times\">\n <p>Time to find all documents {format(times.took)}</p>\n </div>\n );\n}\n\nfunction Loading({ estimate }: { estimate: number }) {\n const startLoadingTime = new Date();\n const [estimateEndTime] = React.useState(\n new Date(startLoadingTime.getTime() + estimate)\n );\n\n const [, setIncrements] = React.useState(0);\n React.useEffect(() => {\n const interval = setInterval(() => {\n setIncrements((state) => state + 1);\n }, 1000);\n return () => clearInterval(interval);\n }, []);\n\n const distance = estimateEndTime.getTime() - startLoadingTime.getTime();\n const elapsed = new Date().getTime() - startLoadingTime.getTime();\n const percent = (100 * elapsed) / distance;\n return (\n <div className=\"loading\">\n <progress id=\"progress\" max=\"100\" value={percent} style={{ margin: 20 }}>\n {percent}%\n </progress>\n <br />\n <small>\n Estimated time to finish: {((distance - elapsed) / 1000).toFixed(0)}s{\" \"}\n {elapsed > distance ? (\n <span aria-label=\"weird\" role=\"img\">\n 🙃\n </span>\n ) : null}\n </small>\n </div>\n );\n}\n\nfunction FilterControls() {\n const [searchParams, setSearchParams] = useSearchParams();\n const [title, setTitle] = React.useState(searchParams.get(\"title\") || \"\");\n const [url, setURL] = React.useState(searchParams.get(\"url\") || \"\");\n\n function refreshFilters(reset = false) {\n const filterParams = createSearchParams(searchParams);\n for (const [key, value] of [\n [\"url\", url],\n [\"title\", title],\n ]) {\n if (!reset && value) {\n filterParams.set(key, value);\n } else {\n filterParams.delete(key);\n }\n }\n filterParams.delete(\"page\");\n setSearchParams(filterParams);\n }\n\n function resetFilters() {\n setURL(\"\");\n setTitle(\"\");\n refreshFilters(true);\n }\n\n return (\n <div className=\"filters\">\n <h3>Filters</h3>\n <form\n onSubmit={(event) => {\n event.preventDefault();\n refreshFilters();\n }}\n >\n <div>\n <h4>Document</h4>\n <input\n type=\"search\"\n placeholder=\"Filter by document URI\"\n value={url}\n onChange={(event) => {\n setURL(event.target.value);\n }}\n onBlur={() => refreshFilters()}\n />\n <input\n type=\"search\"\n placeholder=\"Filter by document title\"\n value={title}\n onChange={(event) => {\n setTitle(event.target.value);\n }}\n onBlur={() => refreshFilters()}\n />\n </div>\n\n <div>\n <h4>&nbsp;</h4>\n <button type=\"submit\">Filter now</button>{\" \"}\n {(url || title) && (\n <button type=\"button\" onClick={resetFilters}>\n Reset filters\n </button>\n )}\n </div>\n </form>\n </div>\n );\n}\ntype NumericOperation = {\n operation: \"eq\" | \"gt\" | \"gte\" | \"lt\" | \"lte\";\n value: number;\n};\n\nfunction getNumericOperation(expression: string): NumericOperation | null {\n function parseIntOrThrow(v: string) {\n if (!v) {\n throw new Error(\"Can't be empty\");\n }\n\n const parsed = parseInt(v, 10);\n if (isNaN(parsed)) {\n throw new Error(`'${v}' not a valid number`);\n }\n return parsed;\n }\n try {\n if (expression.startsWith(\">=\")) {\n return {\n operation: \"gte\",\n value: parseIntOrThrow(expression.replace(\">=\", \"\")),\n };\n } else if (expression.startsWith(\">\")) {\n return {\n operation: \"gt\",\n value: parseIntOrThrow(expression.replace(\">\", \"\")),\n };\n } else if (expression.startsWith(\"<=\")) {\n return {\n operation: \"lte\",\n value: parseIntOrThrow(expression.replace(\"<=\", \"\")),\n };\n } else if (expression.startsWith(\"<\")) {\n return {\n operation: \"lt\",\n value: parseIntOrThrow(expression.replace(\"<\", \"\")),\n };\n } else if (expression.startsWith(\"==\") || expression.startsWith(\"=\")) {\n return {\n operation: \"eq\",\n value: parseIntOrThrow(expression.replace(/=/g, \"\")),\n };\n } else if (expression) {\n return {\n operation: \"eq\",\n value: parseIntOrThrow(expression),\n };\n } else {\n return null;\n }\n } catch (error) {\n console.warn(error);\n return null;\n }\n}\n\nfunction matchNumericOperation(value: number, op: NumericOperation): boolean {\n if (op.operation === \"eq\") {\n if (value !== op.value) {\n return false;\n }\n } else if (op.operation === \"gt\") {\n if (!(value > op.value)) {\n return false;\n }\n } else if (op.operation === \"gte\") {\n if (!(value >= op.value)) {\n return false;\n }\n } else if (op.operation === \"lt\") {\n if (!(value < op.value)) {\n return false;\n }\n } else if (op.operation === \"lte\") {\n if (!(value <= op.value)) {\n return false;\n }\n } else {\n throw new Error(`Not implemented operation '${op.operation}'`);\n }\n return true;\n}\n\nfunction DocumentsTable({\n counts,\n documents,\n sort,\n sortReverse,\n}: {\n counts: Counts;\n documents: Document[];\n sort: string;\n sortReverse: boolean;\n}) {\n const [searchParams, setSearchParams] = useSearchParams();\n\n const page = parseInt(searchParams.get(\"page\") || \"1\", 10);\n const pageSize = parseInt(searchParams.get(\"pageSize\") || \"20\", 10);\n const filterTitle = searchParams.get(\"title\") || \"\";\n const filterURL = searchParams.get(\"url\") || \"\";\n const filterDifferences = searchParams.get(\"differences\") || \"\";\n const filterDifferencesOperation = getNumericOperation(filterDifferences);\n\n function TableHead({ id, title }: { id: string; title: string }) {\n return (\n <th\n onClick={() => {\n if (sort === id) {\n setSearchParams(\n createSearchParams({\n sort: id,\n sortReverse: JSON.stringify(!sortReverse),\n })\n );\n } else {\n setSearchParams(createSearchParams({ sort: id }));\n }\n }}\n className=\"sortable\"\n >\n {title} {sort === id ? (sortReverse ? \"↓\" : \"↑\") : null}\n </th>\n );\n }\n\n const filteredDocuments = documents\n .filter((document) => {\n if (\n filterTitle &&\n !document.title.toLowerCase().includes(filterTitle.toLowerCase())\n ) {\n return false;\n }\n\n if (\n filterURL &&\n !document.mdn_url.toLowerCase().includes(filterURL.toLowerCase())\n ) {\n return false;\n }\n\n if (\n filterDifferencesOperation &&\n !matchNumericOperation(\n document.differences.total,\n filterDifferencesOperation\n )\n ) {\n return false;\n }\n\n return true;\n })\n .sort((A, B) => {\n let reverse = sortReverse ? -1 : 1;\n if (sort === \"modified\") {\n const a = new Date(A.edits.modified);\n const b = new Date(B.edits.modified);\n return reverse * (b.getTime() - a.getTime());\n } else if (sort === \"popularity\") {\n const a = A.popularity.value;\n const b = B.popularity.value;\n return reverse * (b - a);\n } else if (sort === \"differences\") {\n const a = A.differences.total;\n const b = B.differences.total;\n return reverse * (b - a);\n } else if (sort === \"title\") {\n const a = A.title;\n const b = B.title;\n return reverse * a.localeCompare(b);\n } else if (sort === \"mdn_url\") {\n const a = A.mdn_url;\n const b = B.mdn_url;\n return reverse * a.localeCompare(b);\n } else {\n throw new Error(`Unrecognized sort '${sort}'`);\n }\n });\n const pageCount = Math.ceil(counts.total / pageSize);\n\n return (\n <div className=\"documents\">\n <h3>\n {counts.missing.toLocaleString()} missing translations (of{\" \"}\n {counts.total.toLocaleString()} possible)\n </h3>\n\n <table>\n <thead>\n <tr>\n <TableHead id=\"title\" title=\"Document\" />\n <TableHead id=\"popularity\" title=\"Popularity\" />\n <TableHead id=\"modified\" title=\"Last modified\" />\n </tr>\n </thead>\n <tbody>\n {filteredDocuments\n .slice((page - 1) * pageSize, page * pageSize)\n .map((doc: Document) => {\n return (\n <tr key={doc.mdn_url}>\n <td>\n <span className=\"document-title-preview\">\n {filterTitle ? (\n <HighlightedText\n text={doc.title}\n highlight={filterTitle}\n />\n ) : (\n doc.title\n )}\n </span>\n <br />\n <Link\n to={`${doc.mdn_url}#_flaws`}\n title={doc.title}\n target=\"_blank\"\n >\n <BriefURL uri={doc.mdn_url} filterURL={filterURL} />\n </Link>\n </td>\n <td\n title={\n doc.popularity.ranking\n ? `Meaning there are ${\n doc.popularity.ranking - 1\n } more popular pages than this`\n : \"Meaning it has no ranking. Most likely a very rare (or new) document\"\n }\n >\n {!doc.popularity.ranking\n ? \"n/a\"\n : `${getGetOrdinal(doc.popularity.ranking)}`}{\" \"}\n </td>\n <td>\n <LastModified edits={doc.edits} />\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n\n <Paginator last={pageCount} />\n </div>\n );\n}\n\nfunction LastModified({ edits }: { edits: DocumentEdits }) {\n const modified = dayjs(edits.modified);\n return (\n <span className=\"last_modified\">\n <a href={edits.commitURL} target=\"_blank\" rel=\"noreferrer\">\n <time dateTime={modified.toISOString()} title={modified.toISOString()}>\n {modified.fromNow()}\n </time>\n </a>\n </span>\n );\n}\n\nfunction HighlightedText({\n text,\n highlight,\n}: {\n text: string;\n highlight: string;\n}) {\n // Split on highlight term and include term into parts, ignore case\n const parts = text.split(new RegExp(`(${highlight})`, \"gi\"));\n return (\n <span>\n {\" \"}\n {parts.map((part, i) => (\n <span\n key={i}\n style={\n part.toLowerCase() === highlight.toLowerCase()\n ? { fontWeight: \"bold\" }\n : {}\n }\n >\n {part}\n </span>\n ))}{\" \"}\n </span>\n );\n}\n\nfunction BriefURL({ uri, filterURL }: { uri: string; filterURL: string }) {\n const [left, right] = uri.split(/\\/docs\\//, 2);\n return (\n <>\n <span className=\"url-prefix\">{left}/docs/</span>\n <span className=\"url-slug\">\n {filterURL ? (\n <HighlightedText text={right} highlight={filterURL} />\n ) : (\n right\n )}\n </span>\n </>\n );\n}\n\n// https://gist.github.com/jlbruno/1535691/db35b4f3af3dcbb42babc01541410f291a8e8fac\nfunction getGetOrdinal(n: number) {\n const s = [\"th\", \"st\", \"nd\", \"rd\"];\n const v = n % 100;\n return n.toLocaleString() + (s[(v - 20) % 10] || s[v] || s[0]);\n}\n","import React from \"react\";\nimport {\n createSearchParams,\n Link,\n useSearchParams,\n useNavigate,\n} from \"react-router-dom\";\nimport useSWR from \"swr\";\n\nimport { MainContentContainer } from \"../../ui/atoms/page-content\";\nimport { Icon } from \"../../ui/atoms/icon\";\nimport { useLocale } from \"../../hooks\";\n\ninterface Data {\n l10nKPIs: L10nKPIs;\n sections: Section[];\n detailDocuments: DetailDocument[];\n}\n\ninterface Section {\n l10nKPIs: L10nKPIs;\n name: string;\n}\n\ninterface L10nKPIs {\n missing: number;\n outOfDate: number;\n upToDate: number;\n total: number;\n}\n\ninterface DetailDocument {\n url: string;\n info: InfoDocument;\n}\n\ninterface InfoDocument {\n popularity: DocumentPopularity;\n localePopularity: DocumentPopularity;\n defaultLocaleInfo: LocaleInfo;\n localeInfo?: LocaleInfo;\n dateDiff?: number;\n}\n\ninterface DocumentPopularity {\n value: number;\n ranking: number;\n parentValue: number;\n parentRanking: number;\n}\n\ninterface LocaleInfo {\n modified: string;\n commitURL: string;\n}\n\ninterface LocaleStorageData {\n defaultSort?: string;\n defaultSortReverse?: string;\n}\n\ninterface StorageData {\n [locale: string]: LocaleStorageData;\n}\n\nconst LOCALSTORAGE_KEY = \"translations-dashboard-sections\";\n\nfunction saveStorage(locale: string, data: LocaleStorageData) {\n try {\n const stored = JSON.parse(\n localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\"\n ) as StorageData;\n stored[locale] = Object.assign({}, stored[locale] || {}, data);\n localStorage.setItem(LOCALSTORAGE_KEY, JSON.stringify(stored));\n } catch (err) {\n console.warn(\"Unable to save to localStorage\", err);\n }\n}\n\nfunction getStorage(locale: string): LocaleStorageData | null {\n try {\n const stored = JSON.parse(localStorage.getItem(LOCALSTORAGE_KEY) || \"{}\");\n if (stored) {\n return stored[locale] as LocaleStorageData;\n }\n } catch (err) {\n console.warn(\"Unable to retrieve from localStorage\", err);\n }\n return null;\n}\n\nexport function TranslationDashboard() {\n const locale = useLocale();\n const [searchParams] = useSearchParams();\n const navigate = useNavigate();\n\n const [lastData, setLastData] = React.useState<Data | null>(null);\n\n const currentSection = searchParams.get(\"section\") || \"\";\n React.useEffect(() => {\n if (locale.toLowerCase() === \"en-us\") {\n navigate(`/${locale}/_translations`);\n }\n }, [locale, navigate]);\n\n React.useEffect(() => {\n let title = \"Translation dashboard \";\n if (locale.toLowerCase() !== \"en-us\") {\n title += ` for ${locale}`;\n }\n if (currentSection !== \"\") {\n title += ` - section ${currentSection}`;\n }\n document.title = title;\n }, [lastData, locale, currentSection]);\n\n let { data, error, isValidating } = useSWR<Data, Error>(\n locale.toLowerCase() !== \"en-us\"\n ? `/_translations/dashboard/?locale=${locale}&section=${currentSection}`\n : null,\n async (url) => {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`${response.status} (${await response.text()})`);\n }\n if (\n !(response.headers.get(\"content-type\") || \"\").includes(\n \"application/json\"\n )\n ) {\n throw new Error(\n `Response is not JSON (${response.headers.get(\"content-type\")})`\n );\n }\n return response.json();\n },\n {\n revalidateOnFocus: false,\n }\n );\n\n React.useEffect(() => {\n if (data) {\n setLastData(data);\n }\n }, [data]);\n\n const lastStorageData = getStorage(locale);\n const defaultSort = lastStorageData?.defaultSort || \"url\";\n const defaultSortReverse = lastStorageData?.defaultSortReverse || \"false\";\n const sort = searchParams.get(\"sort\") || defaultSort;\n const sortReverse = JSON.parse(\n searchParams.get(\"sortReverse\") || defaultSortReverse\n );\n\n React.useEffect(() => {\n saveStorage(\n locale,\n Object.assign({}, lastStorageData, {\n defaultSort: sort,\n defaultSortReverse: sortReverse,\n })\n );\n }, [locale, sort, sortReverse, lastStorageData]);\n\n if (locale.toLowerCase() === \"en-us\") {\n return null;\n }\n\n let parentSection = \"/\";\n if (currentSection.split(\"/\").length > 2) {\n const arrPathSection = currentSection.split(\"/\");\n arrPathSection.pop();\n parentSection = arrPathSection.join(\"/\");\n }\n\n return (\n <Container>\n {lastData && !error && isValidating && (\n <p style={{ float: \"right\" }}>Reloading...</p>\n )}\n {!data && !error && !lastData && <Loading />}\n {lastData && (\n <p style={{ textAlign: \"right\" }}>\n Go to{\" \"}\n <Link to={`/${locale}/_translations/differences`}>\n Translation differences for <b>{locale}</b>\n </Link>\n {\" / \"}\n <Link to={`/${locale}/_translations/missing`}>\n Missing translations for <b>{locale}</b>\n </Link>\n </p>\n )}\n {error && <ShowError error={error} />}\n {lastData && (\n <div>\n <SectionHeader\n l10nKPIs={lastData.l10nKPIs}\n section={currentSection}\n parentSection={parentSection}\n />\n <SubsectionTable\n sections={lastData.sections}\n currentSection={currentSection}\n />\n <DocumentsTable\n documents={lastData.detailDocuments}\n sort={sort}\n sortReverse={sortReverse}\n locale={locale}\n />\n </div>\n )}\n </Container>\n );\n /*\n );\n }\n */\n}\n\nfunction Container({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"dashboard-section-translations\">\n <MainContentContainer standalone={true}>{children}</MainContentContainer>\n </div>\n );\n}\n\nfunction ShowError({ error }) {\n return (\n <div className=\"error-message\">\n <h3>Error</h3>\n <pre>{error.toString()}</pre>\n </div>\n );\n}\n\nfunction Loading() {\n return (\n <div>\n <label htmlFor=\"progress\">Loading</label>\n <progress id=\"progress\" max=\"100\" style={{ margin: 20 }}></progress>\n </div>\n );\n}\n\nfunction SectionHeader({\n l10nKPIs,\n section,\n parentSection,\n}: {\n l10nKPIs: L10nKPIs;\n section: string;\n parentSection: string;\n}) {\n const completenessExact =\n (100 * (l10nKPIs.total - l10nKPIs.missing)) / l10nKPIs.total;\n const completenessStr = completenessExact.toFixed(1) + \"%\";\n const freshnessExact = (100 * l10nKPIs.upToDate) / l10nKPIs.total;\n const freshnessStr = freshnessExact.toFixed(1) + \"%\";\n return (\n <div className=\"documents\">\n <h2>Localization dashboard for: {section || \"/\"}</h2>\n <p>\n Parent section:{\" \"}\n <a href={`dashboard?section=${parentSection}`}>{parentSection}</a>\n </p>\n <h3>Summary</h3>\n <dl>\n <dt>Total number of pages</dt>\n <dd>{l10nKPIs.total}</dd>\n <dt>Number of untranslated pages</dt>\n <dd>{l10nKPIs.missing}</dd>\n <dt>Number of outdated pages (older than English in Git) </dt>\n <dd>{l10nKPIs.outOfDate}</dd>\n <dt>Number of up-to-date pages</dt>\n <dd>{l10nKPIs.upToDate}</dd>\n <dt>\n <label htmlFor=\"completeness\">Localization completeness</label>\n </dt>\n <dd>\n <progress id=\"completeness\" max=\"100\" value={completenessExact}>\n {completenessStr}\n </progress>{\" \"}\n {completenessStr}\n </dd>\n <dt>\n <label htmlFor=\"freshness\">Localization freshness</label>\n </dt>\n <dd>\n <progress id=\"freshness\" max=\"100\" value={freshnessExact}>\n {freshnessStr}\n </progress>{\" \"}\n {freshnessStr}\n </dd>\n </dl>\n </div>\n );\n}\n\nfunction SubsectionTable({\n sections,\n currentSection,\n}: {\n sections: Section[];\n currentSection: string;\n}) {\n if (sections.length > 0) {\n return (\n <section id=\"subsection-table\">\n <h3>Subsections</h3>\n <table>\n <thead>\n <tr>\n <th>Section</th>\n <th>Total / Untranslated / Out of date</th>\n <th>Completeness</th>\n <th>Freshness</th>\n </tr>\n </thead>\n <tbody>\n {sections\n .sort(\n (sectionA, sectionB) =>\n sectionB.l10nKPIs.total - sectionA.l10nKPIs.total\n )\n .map((section) => {\n const completenessExact =\n (100 * (section.l10nKPIs.total - section.l10nKPIs.missing)) /\n section.l10nKPIs.total;\n const completenessStr = completenessExact.toFixed(1) + \"%\";\n const freshnessExact =\n (100 * section.l10nKPIs.upToDate) / section.l10nKPIs.total;\n const freshnessStr = freshnessExact.toFixed(1) + \"%\";\n const sectionHref =\n \"dashboard?section=%2F\" + encodeURIComponent(section.name);\n return (\n <tr key={section.name}>\n <td>\n <a href={sectionHref}>\n {section.name\n .replace(currentSection.slice(1), \"\")\n .replace(\"/\", \"\")}\n </a>\n </td>\n <td>\n {section.l10nKPIs.total} / {section.l10nKPIs.missing} /{\" \"}\n {section.l10nKPIs.outOfDate}\n </td>\n <td>\n <progress max=\"100\" value={completenessExact}>\n {completenessStr}\n </progress>{\" \"}\n {completenessStr}\n </td>\n <td>\n <progress max=\"100\" value={freshnessExact}>\n {freshnessStr}\n </progress>{\" \"}\n {freshnessStr}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </section>\n );\n } else {\n return null;\n }\n}\n\nfunction DocumentsTable({\n documents,\n sort,\n sortReverse,\n locale,\n}: {\n documents: DetailDocument[];\n sort: string;\n sortReverse: boolean;\n locale: string;\n}) {\n const [searchParams, setSearchParams] = useSearchParams();\n const currentSection = searchParams.get(\"section\") || \"\";\n documents.map((documentDetail) => {\n if (documentDetail.info.localeInfo) {\n const dateLocale = new Date(documentDetail.info.localeInfo.modified);\n const dateDefaultLocale = new Date(\n documentDetail.info.defaultLocaleInfo.modified\n );\n const dateDiff = dateLocale.getTime() - dateDefaultLocale.getTime();\n documentDetail.info.dateDiff = dateDiff;\n } else {\n documentDetail.info.dateDiff = Number.POSITIVE_INFINITY;\n }\n return documentDetail;\n });\n\n function TableHead({\n id,\n title,\n sortable,\n }: {\n id: string;\n title: string;\n sortable?: boolean;\n }) {\n function getClassName() {\n const className = [\"sortable\"];\n\n if (sort === id) {\n className.push(\"active\");\n }\n\n if (sortReverse) {\n className.push(\"reverse\");\n }\n\n return className.join(\" \");\n }\n\n function onClick() {\n if (sort === id) {\n setSearchParams(\n createSearchParams({\n sort: id,\n sortReverse: JSON.stringify(!sortReverse),\n section: currentSection,\n })\n );\n } else {\n setSearchParams(\n createSearchParams({ sort: id, section: currentSection })\n );\n }\n }\n\n return sortable ? (\n <th className={getClassName()} onClick={onClick}>\n {title} <Icon name=\"small-arrow\" />\n </th>\n ) : (\n <th>{title}</th>\n );\n }\n\n return (\n <section id=\"documents-table\">\n <h3>List of direct subpages</h3>\n\n <table>\n <thead>\n <tr>\n <TableHead id=\"url\" title=\"Slug\" sortable />\n <TableHead id=\"enMDNURL\" title=\"English doc on MDN\" />\n <TableHead\n id=\"enCommitGHURL\"\n title=\"English doc commit on GitHub\"\n />\n <TableHead id=\"localURL\" title=\"Local localized doc\" />\n <TableHead id=\"localMDNURL\" title=\"Localized doc on MDN\" />\n <TableHead\n id=\"localCommitGHURL\"\n title=\"Localized doc commit on GitHub\"\n />\n <TableHead\n id=\"popularityEn\"\n title=\"Popularity rank (en-US)\"\n sortable\n />\n <TableHead\n id=\"popularityLocale\"\n title={`Popularity rank (${locale})`}\n sortable\n />\n <TableHead id=\"dateDiff\" title=\"Date delta\" sortable />\n </tr>\n </thead>\n\n <tbody>\n {documents\n .sort((A, B) => {\n let reverse = sortReverse ? -1 : 1;\n if (sort === \"dateDiff\") {\n const a = A.info.dateDiff || Number.POSITIVE_INFINITY;\n const b = B.info.dateDiff || Number.POSITIVE_INFINITY;\n return reverse * (b - a);\n } else if (sort === \"popularityLocale\") {\n const a =\n A.info.localePopularity?.ranking || Number.POSITIVE_INFINITY;\n const b =\n B.info.localePopularity?.ranking || Number.POSITIVE_INFINITY;\n return reverse * (a - b);\n } else if (sort === \"popularityEn\") {\n const a = A.info.popularity.ranking || Number.POSITIVE_INFINITY;\n const b = B.info.popularity.ranking || Number.POSITIVE_INFINITY;\n return reverse * (a - b);\n } else if (sort === \"url\") {\n const a = A.url;\n const b = B.url;\n return reverse * a.localeCompare(b);\n } else {\n throw new Error(`Unrecognized sort '${sort}'`);\n }\n })\n .map((documentDetail) => {\n const url = \"https://developer.mozilla.org\" + documentDetail.url;\n const englishCommitHash =\n documentDetail.info.defaultLocaleInfo.commitURL\n .split(\"commit/\")[1]\n .substring(0, 7);\n const localeCommitHash = documentDetail.info.localeInfo?.commitURL\n .split(\"commit/\")[1]\n .substring(0, 7);\n let status = \"Untranslated\";\n if (documentDetail.info.localeInfo) {\n let dateDiff =\n documentDetail.info.dateDiff ?? Number.POSITIVE_INFINITY;\n status = \"Out of date\";\n\n if (dateDiff > 0) {\n status = \"Fresher than English\";\n } else if (dateDiff > -2678400000) {\n const nbDays = Math.round(-dateDiff / (3600 * 24 * 1000));\n status = nbDays + \" day\" + (nbDays > 1 ? \"s\" : \"\");\n } else {\n const nbMonths = Math.round(\n -dateDiff / (3600 * 24 * 1000 * 30)\n );\n status = nbMonths + \" month\" + (nbMonths > 1 ? \"s\" : \"\");\n }\n }\n return (\n <tr key={documentDetail.url}>\n <td>\n <a href={documentDetail.url}>{documentDetail.url}</a>\n </td>\n <td>\n <a href={url}>English current MDN page</a>\n </td>\n <td>\n <a href={documentDetail.info.defaultLocaleInfo.commitURL}>\n GitHub link for <code>{englishCommitHash}</code>\n </a>\n </td>\n <td>\n {documentDetail.info.localeInfo && (\n <a\n href={documentDetail.url.replace(\n \"/en-US/\",\n \"/\" + locale + \"/\"\n )}\n >\n Local {locale} page\n </a>\n )}\n </td>\n <td>\n {documentDetail.info.localeInfo && (\n <a href={url.replace(\"/en-US/\", \"/\" + locale + \"/\")}>\n Locale current MDN page\n </a>\n )}\n </td>\n <td>\n {documentDetail.info.localeInfo && (\n <a href={documentDetail.info.localeInfo.commitURL}>\n GitHub link for <code>{localeCommitHash}</code>\n </a>\n )}\n </td>\n <td>{documentDetail.info.popularity.ranking}</td>\n <td>\n {documentDetail.info.localePopularity &&\n documentDetail.info.localePopularity.ranking}\n </td>\n <td>{status}</td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </section>\n );\n}\n","import React from \"react\";\nimport { Link, Routes, Route } from \"react-router-dom\";\nimport useSWR from \"swr\";\n\nimport \"./index.scss\";\n\nimport { Loading } from \"../ui/atoms/loading\";\nimport { MainContentContainer } from \"../ui/atoms/page-content\";\n\nimport { TranslationDifferences } from \"./differences\";\nimport { MissingTranslations } from \"./missing\";\nimport { TranslationDashboard } from \"./dashboard\";\nimport { useLocale } from \"../hooks\";\n\ninterface Locale {\n locale: string;\n language: {\n English: string;\n native: string;\n };\n isActive: boolean;\n count: number;\n}\n\ninterface LocalesData {\n locales: Locale[];\n}\n\nexport default function Translations() {\n return (\n <Container>\n <Routes>\n <Route path=\"/\" element={<PickLocale />} />\n <Route path=\"differences\" element={<TranslationDifferences />} />\n <Route path=\"missing\" element={<MissingTranslations />} />\n <Route path=\"dashboard\" element={<TranslationDashboard />} />\n </Routes>\n </Container>\n );\n}\n\nfunction PickLocale() {\n const locale = useLocale();\n React.useEffect(() => {\n let title = \"All translations\";\n if (locale.toLowerCase() !== \"en-us\") {\n title += ` for ${locale}`;\n }\n document.title = title;\n }, [locale]);\n\n const { data: dataLocales, error: errorLocales } = useSWR<LocalesData, Error>(\n locale.toLowerCase() === \"en-us\" ? \"/_translations/\" : null,\n async (url) => {\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`${response.status} (${await response.text()})`);\n }\n return response.json();\n }\n );\n\n if (locale.toLowerCase() === \"en-us\") {\n return (\n <>\n {!dataLocales && !errorLocales && <Loading />}\n {errorLocales && (\n <div className=\"error-message\">\n <h3>Server error</h3>\n <pre>{errorLocales.toString()}</pre>\n </div>\n )}\n {dataLocales && <ShowLocales locales={dataLocales.locales} />}\n </>\n );\n }\n\n return (\n <div className=\"translation-choices\">\n <Link to={`/${locale}/_translations/differences`} className=\"button\">\n Translation differences\n </Link>{\" \"}\n <Link to={`/${locale}/_translations/missing`} className=\"button\">\n Missing translations\n </Link>{\" \"}\n <Link to={`/${locale}/_translations/dashboard`} className=\"button\">\n Dashboard\n </Link>\n </div>\n );\n}\n\nfunction Container({ children }: { children: React.ReactNode }) {\n return (\n <MainContentContainer className=\"all-translations\" standalone={true}>\n {children}\n </MainContentContainer>\n );\n}\n\nfunction ShowLocales({ locales }: { locales: Locale[] }) {\n return (\n <div>\n <h2>Select locale</h2>\n <table>\n <tbody>\n {locales.map((locale) => {\n return (\n <tr key={locale.locale}>\n <td>\n <b>\n {locale.language.English} ({locale.locale})\n </b>{\" \"}\n {!locale.isActive && <small>not active</small>}\n </td>\n <td>{locale.count.toLocaleString()} documents</td>\n <td>\n <Link to={`/${locale.locale}/_translations/differences`}>\n Translation differences\n </Link>{\" \"}\n </td>\n <td>\n <Link to={`/${locale.locale}/_translations/missing`}>\n Missing translations\n </Link>{\" \"}\n </td>\n <td>\n <Link to={`/${locale.locale}/_translations/dashboard`}>\n Dashboard\n </Link>{\" \"}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n );\n}\n","import { Link, useSearchParams } from \"react-router-dom\";\nimport { range } from \"../../../utils\";\n\nconst PARAM = \"page\";\n\nfunction PageLink({\n page,\n children,\n onClick,\n disabled,\n}: {\n page: number;\n children?: React.ReactNode;\n onClick?: (page: number) => unknown;\n disabled?: boolean;\n}) {\n const [searchParams, setSearchParams] = useSearchParams();\n\n return (\n <Link\n to={{}}\n className={disabled ? \"disabled\" : \"\"}\n onClick={(event) => {\n event.preventDefault();\n if (disabled) {\n return;\n }\n\n onClick && onClick(page);\n setSearchParams({\n ...Object.fromEntries(searchParams.entries()),\n [PARAM]: page.toString(),\n });\n\n window.setTimeout(() => document.documentElement.scrollTo());\n }}\n >\n {children || page}\n </Link>\n );\n}\n\nexport function Paginator({\n first = 1,\n last,\n endPadding = 2,\n middlePadding = 2,\n onChange,\n}: {\n first?: number;\n last: number;\n endPadding?: number;\n middlePadding?: number;\n onChange?: (page: number, oldPage: number) => unknown;\n}) {\n const [searchParams] = useSearchParams();\n const current = parseInt(searchParams.get(PARAM) || \"\", 10) || first;\n const middleFirst = Math.max(current - middlePadding, first);\n const middleLast = Math.min(middleFirst + middlePadding * 2 + 1, last + 1);\n const left = range(first, Math.min(endPadding, middleFirst));\n const middle = range(middleFirst, middleLast);\n const right = range(Math.max(last + 1 - endPadding, middleLast), last + 1);\n\n const onClick = (page: number) => {\n onChange && onChange(page, current);\n };\n\n if (first === last) {\n // There are no pages, so return nothing\n return <></>;\n }\n\n return (\n <div className=\"pagination\">\n <PageLink\n page={current - 1}\n onClick={onClick}\n disabled={current === first}\n >\n ← Previous\n </PageLink>\n {left.map((page) => (\n <PageLink key={page} page={page} onClick={onClick} />\n ))}\n {Boolean(left.length) && left[left.length - 1] + 1 !== middle[0] && \"…\"}\n {middle.map((page) =>\n current === page ? (\n <span className=\"current-page\" key={page}>\n {page}\n </span>\n ) : (\n <PageLink key={page} page={page} onClick={onClick} />\n )\n )}\n {Boolean(right.length) &&\n middle[middle.length - 1] + 1 !== right[0] &&\n \"…\"}\n {right.map((page) => (\n <PageLink key={page} page={page} onClick={onClick} />\n ))}\n <PageLink\n page={current + 1}\n onClick={onClick}\n disabled={current === last}\n >\n Next →\n </PageLink>\n </div>\n );\n}\n"],"names":["dayjs","relativeTime","LOCALSTORAGE_KEY","saveStorage","locale","data","stored","JSON","localStorage","Object","err","console","TranslationDifferences","useLocale","searchParams","_useSearchParams","navigate","useNavigate","_React_useState","lastData","setLastData","React","title","document","_useSWR","url","response","fetch","Error","n","error","isValidating","startTime","lastLoadTime","Date","lastStorageData","getStorage","defaultSort","defaultSortReverse","sort","sortReverse","Container","Loading","Link","ShowSearchError","FilterControls","DocumentsTable","BuildTimes","param","children","MainContentContainer","ms","times","s","Math","estimate","startLoadingTime","estimateEndTime","setIncrements","_React_useState1","interval","setInterval","state","clearInterval","distance","elapsed","percent","setSearchParams","setTitle","setURL","_React_useState2","differences","setDifferences","refreshFilters","reset","filterParams","createSearchParams","_iter","key","value","event","counts","documents","page","parseInt","pageSize","filterTitle","filterURL","filterDifferences","filterDifferencesOperation","getNumericOperation","expression","parseIntOrThrow","v","parsed","isNaN","TableHead","id","filteredDocuments","document1","matchNumericOperation","op","A","B","reverse","a","b","a1","b1","a2","b2","a3","b3","a4","b4","_A_edits_sourceCommitsBehindCount","_B_edits_sourceCommitsBehindCount","a5","b5","pageCount","doc","HighlightedText","BriefURL","getGetOrdinal","LastModified","L10nSourceCommitModified","Paginator","sourceCommitsBehindCount","sourceCommitURL","edits","modified","parentModified","text","highlight","parts","RegExp","part","i","uri","_uri_split","left","right","MissingTranslations","TranslationDashboard","currentSection","parentSection","arrPathSection","ShowError","SectionHeader","SubsectionTable","l10nKPIs","section","completenessExact","completenessStr","freshnessExact","freshnessStr","sections","sectionA","sectionB","sectionHref","encodeURIComponent","className","sortable","Icon","documentDetail","dateLocale","dateDefaultLocale","dateDiff","Number","_A_info_localePopularity","_B_info_localePopularity","englishCommitHash","localeCommitHash","_documentDetail_info_localeInfo","status","_documentDetail_info_dateDiff","nbDays","nbMonths","Translations","Routes","Route","PickLocale","dataLocales","errorLocales","ShowLocales","locales","PARAM","PageLink","onClick","disabled","window","first","last","endPadding","middlePadding","onChange","current","middleFirst","middleLast","range","middle","Boolean"],"mappings":"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"}