diff --git a/CHANGELOG.md b/CHANGELOG.md index bdb3a6f0f..4f98213b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ You can also check the # Unreleased + - Features - Limits can now be displayed in bar charts - Exact limit values are now displayed in legend @@ -58,7 +59,9 @@ You can also check the - Fixed Map Symbol Layer custom color palette support for all palette types - Maintenance - Added authentication method to e2e tests - - Added authentication to Vercel previews for easier testing + - Added authentication to vercel previews for easier testing + - flags can now be toggle by clicking "ctrl + t + d" on the keyboard (t,d => + toggle debug) # [5.2.4] - 2025-02-06 diff --git a/app/flags/index.tsx b/app/flags/index.tsx index 49a62d67a..8c35267a2 100644 --- a/app/flags/index.tsx +++ b/app/flags/index.tsx @@ -1,2 +1,2 @@ export { flag } from "./flag"; -export { default as useFlag, useFlags } from "./useFlag"; +export { default as useFlag, useFlags } from "./use-flags"; diff --git a/app/flags/use-flags.ts b/app/flags/use-flags.ts new file mode 100644 index 000000000..b48c862c8 --- /dev/null +++ b/app/flags/use-flags.ts @@ -0,0 +1,84 @@ +import qs from "qs"; +import { useEffect, useState } from "react"; +import useKonami, { UseKonamiArgs } from "use-konami"; + +import { flag, FLAG_PREFIX } from "./flag"; +import { FlagName } from "./types"; + +export default function useFlagValue(name: FlagName) { + const [flagValue, setFlag] = useState(() => flag(name)); + + useEffect(() => { + const handleChange = (changed: string) => { + if (changed === name) { + setFlag(flag(name)); + } + }; + + flag.store.ee.on("change", handleChange); + + return () => { + flag.store.removeListener("change", handleChange); + }; + }, [setFlag, name]); + + return flagValue; +} + +export function useFlags() { + const [flags, setFlags] = useState(flag.list()); + + useEffect(() => { + const handleChange = () => { + setFlags(flag.list()); + }; + + flag.store.ee.on("change", handleChange); + + return () => { + flag.store.removeListener("change", handleChange); + }; + }, [setFlags]); + + return flags; +} + +type UseDebugShortcutProps = { + enable?: boolean; +}; + +export const useDebugShortcut = ({ + enable, +}: UseDebugShortcutProps = {}): void => { + const konamiConfig: UseKonamiArgs = { + sequence: ["t", "o", "g", "g", "l", "e", "d", "e", "b", "u", "g"], + onUnlock: () => { + if (enable) { + addDebugFlag(); + } + }, + }; + + useKonami(konamiConfig); +}; + +const addDebugFlag = () => { + const currentUrl = new URL(window.location.href); + const currentParams = qs.parse(currentUrl.search.substring(1)); + + const debugFlagKey = `${FLAG_PREFIX}debug`; + const hasDebugFlag = currentParams[debugFlagKey] === "true"; + + if (hasDebugFlag) { + delete currentParams[debugFlagKey]; + } else { + currentParams[debugFlagKey] = "true"; + } + + const newSearch = qs.stringify(currentParams); + const newUrl = `${window.location.pathname}${newSearch ? `?${newSearch}` : ""}`; + window.history.pushState({}, "", newUrl); + + const event = new Event("popstate"); + window.dispatchEvent(event); +}; diff --git a/app/flags/useFlag.ts b/app/flags/useFlag.ts deleted file mode 100644 index 8d829f547..000000000 --- a/app/flags/useFlag.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { useEffect, useState } from "react"; - -import { flag } from "./flag"; -import { FlagName } from "./types"; - -export default function useFlagValue(name: FlagName) { - const [flagValue, setFlag] = useState(() => flag(name)); - - useEffect(() => { - const handleChange = (changed: string) => { - if (changed === name) { - setFlag(flag(name)); - } - }; - - flag.store.ee.on("change", handleChange); - - return () => { - flag.store.removeListener("change", handleChange); - }; - }, [setFlag, name]); - - return flagValue; -} - -export function useFlags() { - const [flags, setFlags] = useState(flag.list()); - - useEffect(() => { - const handleChange = () => { - setFlags(flag.list()); - }; - - flag.store.ee.on("change", handleChange); - - return () => { - flag.store.removeListener("change", handleChange); - }; - }, [setFlags]); - - return flags; -} diff --git a/app/package.json b/app/package.json index 317181656..38cb66f91 100644 --- a/app/package.json +++ b/app/package.json @@ -151,6 +151,7 @@ "urql": "^2.0.5", "use-debounce": "^7.0.0", "use-immer": "^0.5.1", + "use-konami": "^1.0.1", "use-sync-external-store": "^1.2.0", "wellknown": "^0.5.0", "wonka": "4.0.15", diff --git a/app/pages/_app.tsx b/app/pages/_app.tsx index 5687cadaf..f770b4449 100644 --- a/app/pages/_app.tsx +++ b/app/pages/_app.tsx @@ -11,8 +11,10 @@ import { useRouter } from "next/router"; import { useEffect } from "react"; import { SnackbarProvider } from "@/components/snackbar"; +import "@/configurator/components/color-picker.css"; import { PUBLIC_URL } from "@/domain/env"; import { flag } from "@/flags/flag"; +import { useDebugShortcut } from "@/flags/use-flags"; import { GraphqlProvider } from "@/graphql/GraphqlProvider"; import { i18n, parseLocaleString } from "@/locales/locales"; import { LocaleProvider } from "@/locales/use-locale"; @@ -24,8 +26,6 @@ import AsyncLocalizationProvider from "@/utils/l10n-provider"; import "@/utils/nprogress.css"; import { useNProgress } from "@/utils/use-nprogress"; -import "@/configurator/components/color-picker.css"; - const GQLDebugPanel = dynamic(() => import("@/gql-flamegraph/devtool"), { ssr: false, }); @@ -68,6 +68,8 @@ export default function App({ const shouldShowGQLDebug = process.env.NODE_ENV === "development" || flag("debug"); + useDebugShortcut({ enable: true }); + return ( <> diff --git a/yarn.lock b/yarn.lock index 0065a1504..b15bd05d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -257,7 +257,7 @@ "@babel/highlight" "^7.24.2" picocolors "^1.0.0" -"@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0": +"@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0", "@babel/code-frame@^7.26.2": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== @@ -286,7 +286,29 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.2.tgz#278b6b13664557de95b8f35b90d96785850bb56e" integrity sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg== -"@babel/core@7.12.9", "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.10.5", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.12.9", "@babel/core@^7.14.6", "@babel/core@^7.18.9", "@babel/core@^7.23.0", "@babel/core@^7.23.2", "@babel/core@^7.24.4", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.7.7": +"@babel/core@7.12.9": + version "7.12.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" + integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.5" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.7" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.9" + "@babel/types" "^7.12.7" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.10.5", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.12.9", "@babel/core@^7.18.9", "@babel/core@^7.23.0", "@babel/core@^7.23.2", "@babel/core@^7.24.4", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.7.7": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40" integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== @@ -316,6 +338,17 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.12.5", "@babel/generator@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca" + integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== + dependencies: + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + "@babel/generator@^7.20.14": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" @@ -594,6 +627,15 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" + integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" + "@babel/helper-module-transforms@^7.14.5": version "7.15.8" resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz" @@ -619,15 +661,6 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.20" -"@babel/helper-module-transforms@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" - integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" - "@babel/helper-optimise-call-expression@^7.14.5", "@babel/helper-optimise-call-expression@^7.15.4": version "7.15.4" resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz" @@ -837,6 +870,14 @@ "@babel/template" "^7.22.15" "@babel/types" "^7.22.19" +"@babel/helpers@^7.12.5": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.9.tgz#28f3fb45252fc88ef2dc547c8a911c255fc9fef6" + integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== + dependencies: + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" + "@babel/helpers@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.0.tgz#30e621f1eba5aa45fe6f4868d2e9154d884119a4" @@ -882,13 +923,25 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@7.12.16", "@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.14.6", "@babel/parser@^7.14.7", "@babel/parser@^7.15.4", "@babel/parser@^7.20.15", "@babel/parser@^7.20.7", "@babel/parser@^7.21.4", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0", "@babel/parser@^7.24.0", "@babel/parser@^7.24.4", "@babel/parser@^7.24.5", "@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.2", "@babel/parser@^7.7.2": +"@babel/parser@7.12.16": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.16.tgz#cc31257419d2c3189d394081635703f549fc1ed4" + integrity sha512-c/+u9cqV6F0+4Hpq01jnJO+GLp2DdT63ppz9Xa+6cHaajM9VFzK/iDXiKK65YtpeVwu+ctfS6iqlMqRgQRzeCw== + +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.14.7", "@babel/parser@^7.15.4", "@babel/parser@^7.20.15", "@babel/parser@^7.20.7", "@babel/parser@^7.21.4", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0", "@babel/parser@^7.24.0", "@babel/parser@^7.24.4", "@babel/parser@^7.24.5", "@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.2", "@babel/parser@^7.7.2": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.5.tgz#6fec9aebddef25ca57a935c86dbb915ae2da3e1f" integrity sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw== dependencies: "@babel/types" "^7.26.5" +"@babel/parser@^7.12.7", "@babel/parser@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" + integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== + dependencies: + "@babel/types" "^7.26.9" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.5": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.5.tgz#4c3685eb9cd790bcad2843900fe0250c91ccf895" @@ -2542,6 +2595,15 @@ resolved "https://registry.npmjs.org/@babel/standalone/-/standalone-7.14.6.tgz" integrity sha512-oAoSp82jhJFnXKybKTOj5QF04XxiDRyiiqrFToiU1udlBXuZoADlPmmnOcuqBrZxSNNUjzJIVK8vt838Qoqjxg== +"@babel/template@^7.12.7", "@babel/template@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" + integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" + "@babel/template@^7.15.4", "@babel/template@^7.3.3": version "7.15.4" resolved "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz" @@ -2608,6 +2670,19 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.12.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" + integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.9" + "@babel/parser" "^7.26.9" + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" + debug "^4.3.1" + globals "^11.1.0" + "@babel/traverse@^7.18.9", "@babel/traverse@^7.23.2": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.0.tgz#4a408fbf364ff73135c714a2ab46a5eab2831b1e" @@ -2670,6 +2745,14 @@ "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" +"@babel/types@^7.12.7", "@babel/types@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" + integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/types@^7.16.7": version "7.17.0" resolved "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz" @@ -16741,7 +16824,7 @@ fwd-stream@^1.0.4: dependencies: readable-stream "~1.0.26-4" -gensync@^1.0.0-beta.2: +gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== @@ -24613,7 +24696,7 @@ resolve@^1.21.0, resolve@^1.22.1: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.22.4: +resolve@^1.22.4, resolve@^1.3.2: version "1.22.10" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== @@ -24930,6 +25013,11 @@ semver-compare@^1.0.0: resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@^5.4.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" @@ -27295,6 +27383,11 @@ use-immer@^0.5.1: resolved "https://registry.npmjs.org/use-immer/-/use-immer-0.5.2.tgz" integrity sha512-aHnLa85kftWo05lqJVOy3GLXrydqu6kl0MXvo5k5OW8IoLJixa9NY/48Xdy0LlcqdakBTFLbSDZaYVPMVhYy8Q== +use-konami@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/use-konami/-/use-konami-1.0.1.tgz#7bdca59e37bba347b21f1bafca1eca59e6596531" + integrity sha512-oqLN0zMKnzCc2eHoPlTq63eZrigCTGPSizUHiqB0tmZE1FDD8ieP0U670YmEIodsUvt2eT0JHLzs603uj30+TA== + use-memo-one@^1.1.1: version "1.1.2" resolved "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz"