diff --git a/locale/en/translation.json b/locale/en/translation.json index 552b0594e..8976a33ba 100644 --- a/locale/en/translation.json +++ b/locale/en/translation.json @@ -117,5 +117,21 @@ "fab": { "scrollToTop": "Scroll to top", "goToFeedback": "Was this page helpful?" + }, + "versionFilter": { + "yes": "Yes", + "no": "No", + "diffLabel": "Diff filter:", + "diffModeOlderVersion": "Older Version", + "diffModeNewerVersion": "Newer Version", + "introducedInitVersion": "From the beginning", + "introducedVersion": "New in {{version}}", + "type": "Type: ", + "persists": "Persists to cluster: ", + "hintSetVar": "Applies to hint <0>SET_VAR: ", + "default": "Default value: ", + "range": "Range: ", + "possibleValues": "Possible values: ", + "unit": "Unit: " } } diff --git a/locale/ja/translation.json b/locale/ja/translation.json index 850bc9ec6..8308dd879 100644 --- a/locale/ja/translation.json +++ b/locale/ja/translation.json @@ -117,5 +117,21 @@ "fab": { "scrollToTop": "トップへ戻る", "goToFeedback": "このページは役に立ちましたか?" + }, + "versionFilter": { + "yes": "はい", + "no": "いいえ", + "diffLabel": "差分フィルタ:", + "diffModeOlderVersion": "古いバージョン", + "diffModeNewerVersion": "新しいバージョン", + "introducedInitVersion": "最初から", + "introducedVersion": "{{version}} から新しい", + "type": "タイプ:", + "persists": "クラスターに保持:", + "hintSetVar": "ヒント <0>SET_VAR に適用:", + "default": "デフォルト値:", + "range": "範囲:", + "possibleValues": "可能な値:", + "unit": "単位:" } } diff --git a/locale/zh/translation.json b/locale/zh/translation.json index a3e849298..3237322a4 100644 --- a/locale/zh/translation.json +++ b/locale/zh/translation.json @@ -114,5 +114,21 @@ "fab": { "scrollToTop": "回到顶部", "goToFeedback": "文档内容是否有帮助?" + }, + "versionFilter": { + "yes": "是", + "no": "否", + "diffLabel": "差异过滤:", + "diffModeOlderVersion": "较旧版本", + "diffModeNewerVersion": "较新版本", + "introducedInitVersion": "初始版本引入", + "introducedVersion": "从 {{version}} 版本开始引入", + "type": "类型:", + "persists": "是否持久化到集群:", + "hintSetVar": "是否受 Hint <0>SET_VAR 控制:", + "default": "默认值:", + "range": "范围:", + "possibleValues": "可选值:", + "unit": "单位:" } } diff --git a/src/components/Layout/MDXContent.tsx b/src/components/Layout/MDXContent.tsx index 692ce12c6..1346b4537 100644 --- a/src/components/Layout/MDXContent.tsx +++ b/src/components/Layout/MDXContent.tsx @@ -17,6 +17,7 @@ import { Locale, PathConfig, FrontMatter, BuildType } from "static/Type"; import { useTotalContributors } from "components/Avatar/Contributors"; import replaceInternalHref from "utils/anchor"; import { Pre } from "components/MDXComponents/Pre"; +import { MdxContext } from "context/MdxContext"; export default function MDXContent(props: { data: any; @@ -74,15 +75,19 @@ export default function MDXContent(props: { availIn={availIn} /> )} - - {data} - + + {data} + + ); diff --git a/src/components/MDXComponents/MDLink.tsx b/src/components/MDXComponents/MDLink.tsx new file mode 100644 index 000000000..a1ff7f1b8 --- /dev/null +++ b/src/components/MDXComponents/MDLink.tsx @@ -0,0 +1,21 @@ +import * as React from "react"; + +import { MdxContext } from "context/MdxContext"; +import { Link } from "gatsby-plugin-react-i18next"; +import { Locale } from "static/Type"; + +export function MDLink(props: { + url: string; + children?: any; + }) { + const mdxContextData = React.useContext(MdxContext); + const { pathConfig } = mdxContextData; + const {url} = props; + const localeURL = pathConfig.locale === Locale.en ? "" : "/" + pathConfig.locale; + const relativeURL = url.startsWith("/") ? url : "/" + url; + const realURL = localeURL + "/" + pathConfig.repo + "/" + pathConfig.version + relativeURL; + + return ( + {props.children} + ) +} \ No newline at end of file diff --git a/src/components/MDXComponents/VersionVarsFilter.tsx b/src/components/MDXComponents/VersionVarsFilter.tsx new file mode 100644 index 000000000..5a6879193 --- /dev/null +++ b/src/components/MDXComponents/VersionVarsFilter.tsx @@ -0,0 +1,229 @@ +import * as React from "react"; +import Stack from "@mui/material/Stack"; +import Typography from "@mui/material/Typography"; +import { Link, Trans, useI18next } from "gatsby-plugin-react-i18next"; +import { Container, Autocomplete, TextField, ToggleButtonGroup, ToggleButton, Card, CardContent, Chip, Accordion, AccordionDetails, AccordionSummary } from '@mui/material'; +import { MDLink } from "./MDLink"; + +type ScopeType = "SESSION" | "GLOBAL" | "BOTH"; + +export function VersionVarsFilter(props: { + versions: string; + children?: React.FC[]; + }) { + + const [startVersion, setStartVersion] = React.useState(""); + const [endVersion, setEndVersion] = React.useState(""); + + const { + versions = "", + children = [], + } = props; + + const versionArray = versions.split(","); + + const compareVersions = (ver1: string, ver2: string) => { + if (ver1.startsWith("v")) { + ver1 = ver1.substring(1); + } + + if (ver2.startsWith("v")) { + ver2 = ver2.substring(1); + } + + const ver1Array = ver1.split("."); + const ver2Array = ver2.split("."); + + if (ver1Array.length !== 3 || ver2Array.length !== 3) { + console.log(ver1, ver2); + throw new Error("Version format is incorrect"); + } + + for (let i = 0; i < ver1Array.length; i++) { + if (parseInt(ver1Array[i]) > parseInt(ver2Array[i])) { + return 1; + } else if (parseInt(ver1Array[i]) < parseInt(ver2Array[i])) { + return -1; + } + } + return 0; + } + + versionArray.sort((a, b) => -compareVersions(a, b)); + + const MIN_VERSION = "v0.0.0"; + const MAX_VERSION = "v999.999.999"; + const filterVersion = (versions: string[], includeEqual: boolean, left?: string|null, right?: string|null) => { + return versions.filter((version) => { + if (left === undefined || left === null || left === "") { + left = MIN_VERSION; + } + + if (right === undefined || right === null || right === "") { + right = MAX_VERSION; + } + + let leftCompare = compareVersions(version, left); + let rightCompare = compareVersions(right, version); + let standard = includeEqual ? 0 : 1; + + return leftCompare >= standard && rightCompare >= standard; + }); + } + + const filterVersionVars = (children: any[]) => { + if (!Array.isArray(children)) { + children = [children]; + } + + return children.map((child) => { + if (child.props?.mdxType !== VersionVars.name) { + // It's not of the filter scope, skip it. + return child; + } + + if (startVersion === "" || endVersion === "") { + // No version is selected, skip it. + return ; + } + + let introducedVersion = child.props.introducedVersion; + if (!introducedVersion) { + introducedVersion = "v0.0.1"; + } + + if (compareVersions(startVersion!, introducedVersion) <= 0 && + compareVersions(introducedVersion, endVersion!) <= 0) { + return ( + + ) + } + + return ""; + }); + } + + return ( +
+ + +
+ { + setStartVersion(newVersion ? newVersion : "") + }} + renderInput={(params) => } />} + /> + + {setEndVersion(newVersion ? newVersion : "")}} + renderInput={(params) => } />} + /> +
+
+ + + {filterVersionVars(children)} + +
+ ); +} + + +export function VersionVars(props: { + name: string; + scope: ScopeType; + type?: string; + applyHint: string; + defaultValue: string; + persists?: string; + introducedVersion?: string; + possibleValues?: string; + range?: string; + unit?: string; + children?: any; + }) { + + const INIT_VERSION = "v0.0.1" + const { + name = "", + introducedVersion = INIT_VERSION, + scope = "GLOBAL", + type = "", + applyHint = "false", + defaultValue = "", + children = [], + possibleValues = "", + range = "", + unit = "", + } = props; + + const yesOrNoI18n = (value: string) => { + return value === "true" ? : ; + } + + return ( + + + + {name} + + {scope === "SESSION" || scope === "BOTH" ? : null} + {scope === "GLOBAL" || scope === "BOTH" ? : null} + + + + { introducedVersion === INIT_VERSION ? + : + } + + {type === "" ? "" : {type} } + {props.persists === undefined ? "" : {yesOrNoI18n(props.persists)}} + ]}/> {yesOrNoI18n(applyHint)} + {defaultValue} + {range === "" ? "" : {range} } + {possibleValues === "" ? "" : {possibleValues} } + {unit === "" ? "" : {unit} } + + + {children} + + ); +} \ No newline at end of file diff --git a/src/components/MDXComponents/index.tsx b/src/components/MDXComponents/index.tsx index df02beaea..f04898cd7 100644 --- a/src/components/MDXComponents/index.tsx +++ b/src/components/MDXComponents/index.tsx @@ -25,3 +25,6 @@ export { DocHomeCard, } from "components/MDXComponents/DocHome"; export { MDSvgIcon } from "components/MDXComponents/MDSvgIcon"; +export { + VersionVarsFilter, +} from "components/MDXComponents/VersionVarsFilter"; diff --git a/src/context/MdxContext.tsx b/src/context/MdxContext.tsx new file mode 100644 index 000000000..fcfe8f0c0 --- /dev/null +++ b/src/context/MdxContext.tsx @@ -0,0 +1,17 @@ +import * as React from "react"; +import { Locale, PathConfig, Repo } from "static/Type"; + +interface IDefalutMdxContext { + pathConfig: PathConfig; +} + +export const DefalutMdxContext: IDefalutMdxContext = { + pathConfig: { + repo: Repo.tidb, + locale: Locale.en, + branch: "dev", + version: null + } +}; + +export const MdxContext = React.createContext(DefalutMdxContext); diff --git a/src/templates/DocTemplate.tsx b/src/templates/DocTemplate.tsx index 439be158a..b8166d0a0 100644 --- a/src/templates/DocTemplate.tsx +++ b/src/templates/DocTemplate.tsx @@ -65,7 +65,6 @@ export default function DocTemplate({ }, [tableOfContents.items]); const stableBranch = getStable(pathConfig.repo); - const { language } = useI18next(); return (