From e8bc7d3116e9b2ba153044e5539ee5872af13028 Mon Sep 17 00:00:00 2001 From: Kyle Johnson Date: Mon, 5 Feb 2024 12:09:59 +0000 Subject: [PATCH] feat: Add audit log detail page (#3356) Co-authored-by: Matthew Elwell --- frontend/common/services/useAuditLogItem.ts | 44 + frontend/common/types/requests.ts | 1 + frontend/common/types/responses.ts | 8 + frontend/package-lock.json | 893 ++++++++++++++++-- frontend/package.json | 11 +- frontend/web/components/AuditLog.tsx | 34 +- frontend/web/components/Breadcrumb.tsx | 32 + frontend/web/components/Icon.tsx | 51 + frontend/web/components/PageTitle.tsx | 2 +- frontend/web/components/diff/DiffEnabled.tsx | 44 + frontend/web/components/diff/DiffFeature.tsx | 164 ++++ frontend/web/components/diff/DiffSegments.tsx | 141 +++ frontend/web/components/diff/DiffString.tsx | 62 ++ .../web/components/diff/DiffVariations.tsx | 50 + frontend/web/components/diff/diff-utils.ts | 165 ++++ .../web/components/pages/AuditLogItemPage.tsx | 125 +++ frontend/web/routes.js | 6 + frontend/web/styles/3rdParty/_index.scss | 1 + frontend/web/styles/3rdParty/_react-diff.scss | 73 ++ frontend/web/styles/components/_panel.scss | 4 + frontend/web/styles/new/_variables-new.scss | 2 + frontend/web/styles/project/_utils.scss | 4 + 22 files changed, 1807 insertions(+), 110 deletions(-) create mode 100644 frontend/common/services/useAuditLogItem.ts create mode 100644 frontend/web/components/Breadcrumb.tsx create mode 100644 frontend/web/components/diff/DiffEnabled.tsx create mode 100644 frontend/web/components/diff/DiffFeature.tsx create mode 100644 frontend/web/components/diff/DiffSegments.tsx create mode 100644 frontend/web/components/diff/DiffString.tsx create mode 100644 frontend/web/components/diff/DiffVariations.tsx create mode 100644 frontend/web/components/diff/diff-utils.ts create mode 100644 frontend/web/components/pages/AuditLogItemPage.tsx create mode 100644 frontend/web/styles/3rdParty/_react-diff.scss diff --git a/frontend/common/services/useAuditLogItem.ts b/frontend/common/services/useAuditLogItem.ts new file mode 100644 index 000000000000..a0c63a110874 --- /dev/null +++ b/frontend/common/services/useAuditLogItem.ts @@ -0,0 +1,44 @@ +import { Res } from 'common/types/responses' +import { Req } from 'common/types/requests' +import { service } from 'common/service' + +export const auditLogItemService = service + .enhanceEndpoints({ addTagTypes: ['AuditLogItem'] }) + .injectEndpoints({ + endpoints: (builder) => ({ + getAuditLogItem: builder.query< + Res['auditLogItem'], + Req['getAuditLogItem'] + >({ + providesTags: (res) => [{ id: res?.id, type: 'AuditLogItem' }], + query: (query: Req['getAuditLogItem']) => ({ + url: `audit/${query.id}/`, + }), + }), + // END OF ENDPOINTS + }), + }) + +export async function getAuditLogItem( + store: any, + data: Req['getAuditLogItem'], + options?: Parameters< + typeof auditLogItemService.endpoints.getAuditLogItem.initiate + >[1], +) { + return store.dispatch( + auditLogItemService.endpoints.getAuditLogItem.initiate(data, options), + ) +} +// END OF FUNCTION_EXPORTS + +export const { + useGetAuditLogItemQuery, + // END OF EXPORTS +} = auditLogItemService + +/* Usage examples: +const { data, isLoading } = useGetAuditLogItemQuery({ id: 2 }, {}) //get hook +const [createAuditLogItem, { isLoading, data, isSuccess }] = useCreateAuditLogItemMutation() //create hook +auditLogItemService.endpoints.getAuditLogItem.select({id: 2})(store.getState()) //access data from any function +*/ diff --git a/frontend/common/types/requests.ts b/frontend/common/types/requests.ts index 5e6b933a5872..2845c4afadd8 100644 --- a/frontend/common/types/requests.ts +++ b/frontend/common/types/requests.ts @@ -155,5 +155,6 @@ export type Req = { getGroupSummaries: { orgId: string } + getAuditLogItem: { id: string } // END OF TYPES } diff --git a/frontend/common/types/responses.ts b/frontend/common/types/responses.ts index ff4ac3ea343f..ce039237a412 100644 --- a/frontend/common/types/responses.ts +++ b/frontend/common/types/responses.ts @@ -151,6 +151,13 @@ export type AuditLogItem = { is_system_event: boolean } +export type AuditLogDetail = AuditLogItem & { + change_details: { + field: string + old: FlagsmithValue + new: FlagsmithValue + }[] +} export type Subscription = { id: number uuid: string @@ -397,5 +404,6 @@ export type Res = { groupWithRole: PagedResponse changeRequests: PagedResponse groupSummaries: UserGroupSummary[] + auditLogItem: AuditLogDetail // END OF TYPES } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d9504e072395..347da76355da 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -73,17 +73,19 @@ "polyfill-react-native": "1.0.5", "postcss-loader": "4.3.0", "prettier": "^2.5.1", + "prismjs": "^1.29.0", "promise-polyfill": "7.1.2", "prop-types": "15.6.2", "qrcode.react": "1.0.0", "rc-slider": "^9.7.2", "rc-switch": "1.9.0", - "react": "16.9.0", + "react": "16.14.0", "react-async-script": "1.2.0", "react-click-outside": "3.0.1", "react-datepicker": "4.16.0", "react-device-detect": "1.9.9", - "react-dom": "16.9.0", + "react-diff-viewer-continued": "^3.3.1", + "react-dom": "16.14.0", "react-markdown": "^8.0.5", "react-maskedinput": "4.0.1", "react-redux": "8.0.2", @@ -97,6 +99,7 @@ "reactstrap": "9.0.1", "recharts": "^2.1.14", "redux-persist": "^6.0.0", + "refractor": "^4.8.1", "sass": "1.54.8", "sass-loader": "13.0.2", "semver": "^7.5.2", @@ -121,7 +124,7 @@ "@types/classnames": "^2.3.1", "@types/color": "^3.0.3", "@types/dompurify": "^3.0.2", - "@types/react-router": "^5.1.19", + "@types/react-router": "^4.4.5", "@types/react-router-dom": "^4.3.1", "@types/react-select": "^2.0.3", "@typescript-eslint/eslint-plugin": "5.4.0", @@ -138,13 +141,13 @@ "eslint-plugin-sort-keys-fix": "^1.1.2", "nodemon": "^3.0.1", "raw-loader": "0.5.1", - "ssgrtk": "^0.3.4", + "ssgrtk": "^0.3.5", "testcafe": "^3.2.0", "typescript": "4.6.4" }, "engines": { - "node": "20.x", - "npm": "8.x" + "node": "18.x", + "npm": "9.x" } }, "node_modules/@adobe/css-tools": { @@ -2628,6 +2631,145 @@ "node": "*" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/serialize": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", + "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/babel-plugin/node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/babel-plugin/node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/@emotion/babel-plugin/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, "node_modules/@emotion/babel-utils": { "version": "0.6.10", "resolved": "https://registry.npmjs.org/@emotion/babel-utils/-/babel-utils-0.6.10.tgz", @@ -2649,6 +2791,82 @@ "node": ">= 8" } }, + "node_modules/@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "dependencies": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/cache/node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/cache/node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "node_modules/@emotion/css": { + "version": "11.11.2", + "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.11.2.tgz", + "integrity": "sha512-VJxe1ucoMYMS7DkiMdC2T7PWNbrEI0a39YRiyDvK2qq4lXwjRbVP/z4lpG+odCsRzadlR+1ywwrTzhdm5HNdew==", + "dependencies": { + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1" + } + }, + "node_modules/@emotion/css/node_modules/@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "node_modules/@emotion/css/node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "node_modules/@emotion/css/node_modules/@emotion/serialize": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", + "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", + "dependencies": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/css/node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "node_modules/@emotion/css/node_modules/@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "node_modules/@emotion/css/node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, "node_modules/@emotion/hash": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.6.6.tgz", @@ -2670,6 +2888,11 @@ "@emotion/utils": "^0.8.2" } }, + "node_modules/@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, "node_modules/@emotion/stylis": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.7.1.tgz", @@ -2685,6 +2908,11 @@ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.8.2.tgz", "integrity": "sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw==" }, + "node_modules/@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, "node_modules/@ffmpeg-installer/darwin-arm64": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@ffmpeg-installer/darwin-arm64/-/darwin-arm64-4.1.5.tgz", @@ -4048,6 +4276,11 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, + "node_modules/@types/prismjs": { + "version": "1.26.3", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.3.tgz", + "integrity": "sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==" + }, "node_modules/@types/prop-types": { "version": "15.7.5", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", @@ -4073,12 +4306,12 @@ } }, "node_modules/@types/react-router": { - "version": "5.1.19", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.19.tgz", - "integrity": "sha512-Fv/5kb2STAEMT3wHzdKQK2z8xKq38EDIGVrutYLmQVVLe+4orDFquU52hQrULnEHinMKv9FSA6lf9+uNT1ITtA==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-4.4.5.tgz", + "integrity": "sha512-12+VOu1+xiC8RPc9yrgHCyLI79VswjtuqeS2gPrMcywH6tkc8rGIUhs4LaL3AJPqo5d+RPnfRpNKiJ7MK2Qhcg==", "dev": true, "dependencies": { - "@types/history": "^4.7.11", + "@types/history": "*", "@types/react": "*" } }, @@ -5923,6 +6156,24 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -9475,6 +9726,18 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "node_modules/hast-util-parse-selector": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", + "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", + "dependencies": { + "@types/hast": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-whitespace": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", @@ -9484,6 +9747,22 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hastscript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", + "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^3.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -10424,6 +10703,28 @@ "node": ">= 0.10" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-array-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", @@ -10560,6 +10861,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-directory": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", @@ -10625,6 +10935,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-in-browser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", @@ -13857,6 +14176,42 @@ "node": ">=6" } }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse5": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", @@ -14186,23 +14541,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-loader/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/postcss-loader/node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -14361,6 +14699,14 @@ "node": ">= 0.8" } }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -14732,9 +15078,9 @@ } }, "node_modules/react": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.9.0.tgz", - "integrity": "sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w==", + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -14811,18 +15157,57 @@ "react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0" } }, + "node_modules/react-diff-viewer-continued": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/react-diff-viewer-continued/-/react-diff-viewer-continued-3.4.0.tgz", + "integrity": "sha512-kMZmUyb3Pv5L9vUtCfIGYsdOHs8mUojblGy1U1Sm0D7FhAOEsH9QhnngEIRo5hXWIPNGupNRJls1TJ6Eqx84eg==", + "dependencies": { + "@emotion/css": "^11.11.2", + "classnames": "^2.3.2", + "diff": "^5.1.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">= 8" + }, + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-diff-viewer-continued/node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, + "node_modules/react-diff-viewer-continued/node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "node_modules/react-diff-viewer-continued/node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/react-dom": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.9.0.tgz", - "integrity": "sha512-YFT2rxO9hM70ewk9jq0y6sQk8cL02xm4+IzYBz75CQGlClQQ1Bxq0nhHF6OtSbit+AIahujJgb/CPRibFkMNJQ==", + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "scheduler": "^0.15.0" + "scheduler": "^0.19.1" }, "peerDependencies": { - "react": "^16.0.0" + "react": "^16.14.0" } }, "node_modules/react-fast-compare": { @@ -15310,23 +15695,6 @@ "node": ">=8" } }, - "node_modules/read-pkg/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/read-pkg/node_modules/type-fest": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", @@ -15472,6 +15840,21 @@ "redux": "^4" } }, + "node_modules/refractor": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-4.8.1.tgz", + "integrity": "sha512-/fk5sI0iTgFYlmVGYVew90AoYnNMP6pooClx/XKqyeeCQXrL0Kvgn8V0VEht5ccdljbzzF1i3Q213gcntkRExg==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/prismjs": "^1.0.0", + "hastscript": "^7.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -15948,9 +16331,9 @@ } }, "node_modules/scheduler": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.15.0.tgz", - "integrity": "sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -16396,9 +16779,9 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "node_modules/ssgrtk": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/ssgrtk/-/ssgrtk-0.3.4.tgz", - "integrity": "sha512-5BXJSVrg8Vq6fOMRDulTD0jF0Rts+2DjROTNHmN009Y3uVsZRGmqj8MWOkqOzVnLWveN1ko3cK9XRs04/whY0Q==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/ssgrtk/-/ssgrtk-0.3.5.tgz", + "integrity": "sha512-7SHtl+a7jJwGlUn0JHyfu3somKyXBTw2Uc7UhErbpdfrdQH8ofSDHUqvVBwlt5rhJ/qtkTLfQ3vUk8Roo62ebA==", "dev": true, "dependencies": { "@oclif/core": "^1", @@ -21254,6 +21637,119 @@ } } }, + "@emotion/babel-plugin": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + }, + "dependencies": { + "@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "@emotion/serialize": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", + "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", + "requires": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "requires": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + } + }, + "cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + } + } + }, "@emotion/babel-utils": { "version": "0.6.10", "resolved": "https://registry.npmjs.org/@emotion/babel-utils/-/babel-utils-0.6.10.tgz", @@ -21274,6 +21770,86 @@ } } }, + "@emotion/cache": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", + "requires": { + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" + }, + "dependencies": { + "@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + } + } + }, + "@emotion/css": { + "version": "11.11.2", + "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.11.2.tgz", + "integrity": "sha512-VJxe1ucoMYMS7DkiMdC2T7PWNbrEI0a39YRiyDvK2qq4lXwjRbVP/z4lpG+odCsRzadlR+1ywwrTzhdm5HNdew==", + "requires": { + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1" + }, + "dependencies": { + "@emotion/hash": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" + }, + "@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "@emotion/serialize": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.3.tgz", + "integrity": "sha512-iD4D6QVZFDhcbH0RAG1uVu1CwVLMWUkCvAqqlewO/rxf8+87yIBAlt4+AxMiiKPLs5hFc0owNk/sLLAOROw3cA==", + "requires": { + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" + }, + "@emotion/utils": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" + }, + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + } + } + }, "@emotion/hash": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.6.6.tgz", @@ -21295,6 +21871,11 @@ "@emotion/utils": "^0.8.2" } }, + "@emotion/sheet": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" + }, "@emotion/stylis": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.7.1.tgz", @@ -21310,6 +21891,11 @@ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.8.2.tgz", "integrity": "sha512-rLu3wcBWH4P5q1CGoSSH/i9hrXs7SlbRLkoq9IGuoPYNGQvDJ3pt/wmOM+XgYjIDRMVIdkUWt0RsfzF50JfnCw==" }, + "@emotion/weak-memoize": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, "@ffmpeg-installer/darwin-arm64": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@ffmpeg-installer/darwin-arm64/-/darwin-arm64-4.1.5.tgz", @@ -22366,6 +22952,11 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, + "@types/prismjs": { + "version": "1.26.3", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.3.tgz", + "integrity": "sha512-A0D0aTXvjlqJ5ZILMz3rNfDBOx9hHxLZYv2by47Sm/pqW35zzjusrZTryatjN/Rf8Us2gZrJD+KeHbUSTux1Cw==" + }, "@types/prop-types": { "version": "15.7.5", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", @@ -22398,12 +22989,12 @@ } }, "@types/react-router": { - "version": "5.1.19", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.19.tgz", - "integrity": "sha512-Fv/5kb2STAEMT3wHzdKQK2z8xKq38EDIGVrutYLmQVVLe+4orDFquU52hQrULnEHinMKv9FSA6lf9+uNT1ITtA==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-4.4.5.tgz", + "integrity": "sha512-12+VOu1+xiC8RPc9yrgHCyLI79VswjtuqeS2gPrMcywH6tkc8rGIUhs4LaL3AJPqo5d+RPnfRpNKiJ7MK2Qhcg==", "dev": true, "requires": { - "@types/history": "^4.7.11", + "@types/history": "*", "@types/react": "*" } }, @@ -23749,6 +24340,16 @@ "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==" }, + "character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==" + }, + "character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==" + }, "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -26422,11 +27023,31 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "hast-util-parse-selector": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", + "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", + "requires": { + "@types/hast": "^2.0.0" + } + }, "hast-util-whitespace": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==" }, + "hastscript": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", + "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", + "requires": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^3.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -27112,6 +27733,20 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==" + }, + "is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "requires": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + } + }, "is-array-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", @@ -27200,6 +27835,11 @@ "has-tostringtag": "^1.0.0" } }, + "is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==" + }, "is-directory": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", @@ -27241,6 +27881,11 @@ "is-extglob": "^2.1.1" } }, + "is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==" + }, "is-in-browser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", @@ -29529,6 +30174,32 @@ } } }, + "parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "requires": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, "parse5": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", @@ -29768,17 +30439,6 @@ "resolve-from": "^4.0.0" } }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -29881,6 +30541,11 @@ "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", "dev": true }, + "prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==" + }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -30165,9 +30830,9 @@ } }, "react": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.9.0.tgz", - "integrity": "sha512-+7LQnFBwkiw+BobzOF6N//BdoNw0ouwmSJTEm9cglOOmsg/TMiFHZLe2sEoN5M7LgJTj9oHH0gxklfnQe66S1w==", + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -30234,15 +30899,49 @@ "ua-parser-js": "^0.7.20" } }, + "react-diff-viewer-continued": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/react-diff-viewer-continued/-/react-diff-viewer-continued-3.4.0.tgz", + "integrity": "sha512-kMZmUyb3Pv5L9vUtCfIGYsdOHs8mUojblGy1U1Sm0D7FhAOEsH9QhnngEIRo5hXWIPNGupNRJls1TJ6Eqx84eg==", + "requires": { + "@emotion/css": "^11.11.2", + "classnames": "^2.3.2", + "diff": "^5.1.0", + "memoize-one": "^6.0.0", + "prop-types": "^15.8.1" + }, + "dependencies": { + "classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, + "memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + } + } + }, "react-dom": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.9.0.tgz", - "integrity": "sha512-YFT2rxO9hM70ewk9jq0y6sQk8cL02xm4+IzYBz75CQGlClQQ1Bxq0nhHF6OtSbit+AIahujJgb/CPRibFkMNJQ==", + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", "prop-types": "^15.6.2", - "scheduler": "^0.15.0" + "scheduler": "^0.19.1" } }, "react-fast-compare": { @@ -30569,17 +31268,6 @@ "type-fest": "^0.6.0" }, "dependencies": { - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, "type-fest": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", @@ -30752,6 +31440,17 @@ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==" }, + "refractor": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-4.8.1.tgz", + "integrity": "sha512-/fk5sI0iTgFYlmVGYVew90AoYnNMP6pooClx/XKqyeeCQXrL0Kvgn8V0VEht5ccdljbzzF1i3Q213gcntkRExg==", + "requires": { + "@types/hast": "^2.0.0", + "@types/prismjs": "^1.0.0", + "hastscript": "^7.0.0", + "parse-entities": "^4.0.0" + } + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -31091,9 +31790,9 @@ } }, "scheduler": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.15.0.tgz", - "integrity": "sha512-xAefmSfN6jqAa7Kuq7LIJY0bwAPG3xlCj0HMEBQk1lxYiDKZscY2xJ5U/61ZTrYbmNQbXa+gc7czPkVo11tnCg==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -31451,9 +32150,9 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "ssgrtk": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/ssgrtk/-/ssgrtk-0.3.4.tgz", - "integrity": "sha512-5BXJSVrg8Vq6fOMRDulTD0jF0Rts+2DjROTNHmN009Y3uVsZRGmqj8MWOkqOzVnLWveN1ko3cK9XRs04/whY0Q==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/ssgrtk/-/ssgrtk-0.3.5.tgz", + "integrity": "sha512-7SHtl+a7jJwGlUn0JHyfu3somKyXBTw2Uc7UhErbpdfrdQH8ofSDHUqvVBwlt5rhJ/qtkTLfQ3vUk8Roo62ebA==", "dev": true, "requires": { "@oclif/core": "^1", diff --git a/frontend/package.json b/frontend/package.json index fd7ef9d6788e..ab2b392bf73e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -91,17 +91,19 @@ "polyfill-react-native": "1.0.5", "postcss-loader": "4.3.0", "prettier": "^2.5.1", + "prismjs": "^1.29.0", "promise-polyfill": "7.1.2", "prop-types": "15.6.2", "qrcode.react": "1.0.0", "rc-slider": "^9.7.2", "rc-switch": "1.9.0", - "react": "16.9.0", + "react": "16.14.0", "react-async-script": "1.2.0", "react-click-outside": "3.0.1", "react-datepicker": "4.16.0", "react-device-detect": "1.9.9", - "react-dom": "16.9.0", + "react-diff-viewer-continued": "^3.3.1", + "react-dom": "16.14.0", "react-markdown": "^8.0.5", "react-maskedinput": "4.0.1", "react-redux": "8.0.2", @@ -115,6 +117,7 @@ "reactstrap": "9.0.1", "recharts": "^2.1.14", "redux-persist": "^6.0.0", + "refractor": "^4.8.1", "sass": "1.54.8", "sass-loader": "13.0.2", "semver": "^7.5.2", @@ -139,7 +142,7 @@ "@types/classnames": "^2.3.1", "@types/color": "^3.0.3", "@types/dompurify": "^3.0.2", - "@types/react-router": "^5.1.19", + "@types/react-router": "^4.4.5", "@types/react-router-dom": "^4.3.1", "@types/react-select": "^2.0.3", "@typescript-eslint/eslint-plugin": "5.4.0", @@ -156,7 +159,7 @@ "eslint-plugin-sort-keys-fix": "^1.1.2", "nodemon": "^3.0.1", "raw-loader": "0.5.1", - "ssgrtk": "^0.3.4", + "ssgrtk": "^0.3.5", "testcafe": "^3.2.0", "typescript": "4.6.4" }, diff --git a/frontend/web/components/AuditLog.tsx b/frontend/web/components/AuditLog.tsx index f87e87f47deb..d578cb01dd68 100644 --- a/frontend/web/components/AuditLog.tsx +++ b/frontend/web/components/AuditLog.tsx @@ -1,16 +1,14 @@ import React, { FC, ReactNode, useEffect, useRef, useState } from 'react' // we need this to make JSX compile import moment from 'moment' import Utils from 'common/utils/utils' -import { AuditLogItem, Environment, Project } from 'common/types/responses' +import { AuditLogItem, Environment } from 'common/types/responses' import { useGetAuditLogsQuery } from 'common/services/useAuditLog' import useSearchThrottle from 'common/useSearchThrottle' -import ProjectProvider from 'common/providers/ProjectProvider' import JSONReference from './JSONReference' -import { Link } from 'react-router-dom' +import { Link, withRouter } from 'react-router-dom' import PanelSearch from './PanelSearch' import ProjectStore from 'common/stores/project-store' import Tag from './tags/Tag' -import Constants from 'common/constants' type AuditLogType = { environmentId: string @@ -19,6 +17,12 @@ type AuditLogType = { onSearchChange?: (search: string) => void searchPanel?: ReactNode onErrorChange?: (err: boolean) => void + match: { + params: { + environmentId: string + projectId: string + } + } } const widths = [210, 210, 210] @@ -72,14 +76,16 @@ const AuditLog: FC = (props) => { author, created_date, environment, + id, log, }: AuditLogItem) => { - const index = ProjectStore.getEnvs()?.findIndex((v) => { + const environments = ProjectStore.getEnvs() as Environment[] | null + const index = environments?.findIndex((v) => { return v.id === environment?.id }) const colour = index === -1 ? 0 : index - return ( - + const inner = ( +
= (props) => { {log} ) + return Utils.getFlagsmithHasFeature('audit_log_detail') ? ( + + {inner} + + ) : ( + + {inner} + + ) } const { env: envFilter } = Utils.fromParam() @@ -188,4 +206,4 @@ const AuditLog: FC = (props) => { ) } -export default AuditLog +export default withRouter(AuditLog) diff --git a/frontend/web/components/Breadcrumb.tsx b/frontend/web/components/Breadcrumb.tsx new file mode 100644 index 000000000000..ad25b1216840 --- /dev/null +++ b/frontend/web/components/Breadcrumb.tsx @@ -0,0 +1,32 @@ +import React, { FC } from 'react' +import { Link } from 'react-router-dom' + +type BreadcrumbType = { + items: { title: string; url: string }[] + currentPage: string +} + +const Breadcrumb: FC = ({ currentPage, items }) => { + return ( + + ) +} + +export default Breadcrumb diff --git a/frontend/web/components/Icon.tsx b/frontend/web/components/Icon.tsx index ccc01c5e7bd7..5faa8d796b2c 100644 --- a/frontend/web/components/Icon.tsx +++ b/frontend/web/components/Icon.tsx @@ -26,6 +26,7 @@ export type IconName = | 'calendar' | 'edit' | 'clock' + | 'diff' | 'person' | 'edit-outlined' | 'refresh' @@ -66,6 +67,56 @@ export type IconType = React.DetailedHTMLProps< const Icon: FC = ({ fill, fill2, height, name, width, ...rest }) => { switch (name) { + case 'diff': { + return ( + + + + + + + ) + } case 'plus': { return ( diff --git a/frontend/web/components/diff/DiffEnabled.tsx b/frontend/web/components/diff/DiffEnabled.tsx new file mode 100644 index 000000000000..6f973cd8e2a1 --- /dev/null +++ b/frontend/web/components/diff/DiffEnabled.tsx @@ -0,0 +1,44 @@ +import React, { FC } from 'react' +import classNames from 'classnames' +import Switch from 'components/Switch' + +type DiffType = { + oldValue: boolean + newValue: boolean +} + +const DiffEnabled: FC = ({ newValue, oldValue }) => { + if (E2E) { + return ( + <> +
{`${oldValue}`}
+
{`${newValue}`}
+ + ) + } + if (oldValue === newValue) { + return + } + return ( + <> +
+
+
-
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+ + ) +} + +export default DiffEnabled diff --git a/frontend/web/components/diff/DiffFeature.tsx b/frontend/web/components/diff/DiffFeature.tsx new file mode 100644 index 000000000000..fcce1486da7e --- /dev/null +++ b/frontend/web/components/diff/DiffFeature.tsx @@ -0,0 +1,164 @@ +import React, { FC, useEffect, useState } from 'react' +import { FeatureState } from 'common/types/responses' +import Tabs from 'components/base/forms/Tabs' +import TabItem from 'components/base/forms/TabItem' +import { useGetProjectFlagQuery } from 'common/services/useProjectFlag' +import { useGetSegmentsQuery } from 'common/services/useSegment' +import { + getFeatureStateDiff, + getSegmentDiff, + getVariationDiff, +} from './diff-utils' +import DiffString from './DiffString' +import DiffEnabled from './DiffEnabled' +import DiffSegments from './DiffSegments' +import DiffVariations from './DiffVariations' +import InfoMessage from 'components/InfoMessage' + +type FeatureDiffType = { + oldState: FeatureState[] + newState: FeatureState[] + noChangesMessage?: string + featureId: number + projectId: string + tabTheme?: string +} + +const DiffFeature: FC = ({ + featureId, + newState, + noChangesMessage, + oldState, + projectId, + tabTheme, +}) => { + const oldEnv = oldState?.find((v) => !v.feature_segment) + const newEnv = newState?.find((v) => !v.feature_segment) + const { data: feature } = useGetProjectFlagQuery({ + id: `${featureId}`, + project: projectId, + }) + + const diff = getFeatureStateDiff(oldEnv, newEnv) + const { totalChanges } = diff + const [value, setValue] = useState(0) + + const { data: segments } = useGetSegmentsQuery({ + projectId, + }) + + const segmentDiffs = getSegmentDiff(oldState, newState, segments?.results) + const variationDiffs = getVariationDiff(oldEnv, newEnv, feature) + const totalSegmentChanges = segmentDiffs?.totalChanges + const totalVariationChanges = variationDiffs?.totalChanges + useEffect(() => { + if (!totalChanges && (totalSegmentChanges || totalVariationChanges)) { + setValue(1) + } + }, [totalSegmentChanges, totalVariationChanges, totalChanges]) + const hideValue = + !totalChanges && (diff.newValue === null || diff.newValue === undefined) + return ( +
+ {!feature ? ( +
+ +
+ ) : ( + <> + {!totalChanges && + !totalSegmentChanges && + !totalVariationChanges && + noChangesMessage && {noChangesMessage}} + + + Value + {totalChanges ? ( + {totalChanges} + ) : null} +
+ } + > +
+
+
+ {!hideValue && ( +
+ Value +
+ )} +
+ Enabled +
+
+
+ {!hideValue && ( +
+
+ +
+
+ )} + +
+ +
+
+
+
+ + {!!variationDiffs?.diffs?.length && ( + + Variations{' '} + {variationDiffs.totalChanges ? ( + + {variationDiffs.totalChanges} + + ) : null} +
+ } + > + + + )} + {!!segmentDiffs?.diffs.length && ( + + Segment Overrides + {!!segmentDiffs.totalChanges && ( + + {segmentDiffs.totalChanges} + + )} + + } + > + + + )} + + + )} + + ) +} + +export default DiffFeature diff --git a/frontend/web/components/diff/DiffSegments.tsx b/frontend/web/components/diff/DiffSegments.tsx new file mode 100644 index 000000000000..6c8a2355ca6d --- /dev/null +++ b/frontend/web/components/diff/DiffSegments.tsx @@ -0,0 +1,141 @@ +import { TDiffSegment } from './diff-utils' +import React, { FC, useMemo } from 'react' +import DiffString from './DiffString' +import DiffEnabled from './DiffEnabled' +import { sortBy } from 'lodash' +import Tabs from 'components/base/forms/Tabs' +import TabItem from 'components/base/forms/TabItem' + +type DiffSegment = { + diff: TDiffSegment +} + +const widths = [80, 105] +const DiffSegment: FC = ({ diff }) => { + return ( +
+
+ +
+
+ +
+
+ +
+
+ ) +} + +type DiffSegmentsType = { + diffs: TDiffSegment[] | undefined +} +const DiffSegments: FC = ({ diffs }) => { + const { created, deleted, modified, unChanged } = useMemo(() => { + const created: TDiffSegment[] = [] + const deleted: TDiffSegment[] = [] + const modified: TDiffSegment[] = [] + const unChanged: TDiffSegment[] = [] + + sortBy(diffs || [], (diff) => diff.newPriority)?.forEach((diff) => { + if (diff.created) { + created.push(diff) + } else if (diff.deleted) { + deleted.push(diff) + } else if (diff.totalChanges) { + modified.push(diff) + } else { + unChanged.push(diff) + } + }) + return { created, deleted, modified, unChanged } + }, [diffs]) + + const tableHeader = ( + +
+ Priority +
+
Value
+
+ Enabled +
+
+ ) + + return diffs ? ( + + {!!created.length && ( + + Created
{created.length}
+ + } + > + {tableHeader} + {created.map((diff, i) => ( + + ))} +
+ )} + {!!deleted.length && ( + + Deleted
{deleted.length}
+ + } + > + {tableHeader} + {deleted.map((diff, i) => ( + + ))} +
+ )} + {!!modified.length && ( + + Modified
{modified.length}
+ + } + > + {tableHeader} + {modified.map((diff, i) => ( + + ))} +
+ )} + {!!unChanged.length && ( + + Unchanged
{unChanged.length}
+ + } + > + {tableHeader} + {unChanged.map((diff, i) => ( + + ))} +
+ )} +
+ ) : ( +
+ +
+ ) +} + +export default DiffSegments diff --git a/frontend/web/components/diff/DiffString.tsx b/frontend/web/components/diff/DiffString.tsx new file mode 100644 index 000000000000..22d642571c13 --- /dev/null +++ b/frontend/web/components/diff/DiffString.tsx @@ -0,0 +1,62 @@ +import React, { FC } from 'react' +// @ts-ignore +import { diffLines, formatLines } from 'unidiff' +import Diff, { DiffMethod } from 'react-diff-viewer-continued' +import Prism from 'prismjs' +import 'prismjs/components/prism-json' + +type DiffType = { + oldValue: string + newValue: string + compareMethod?: DiffMethod +} + +const DiffString: FC = ({ + compareMethod = DiffMethod.CHARS, + newValue, + oldValue, +}) => { + if (E2E) { + return ( + <> +
{oldValue}
+
{newValue}
+ + ) + } + + if (oldValue === newValue) { + if (oldValue === null || oldValue === '') { + return null + } + return ( +
+
+      
+ ) + } + return ( + ( +
+      )}
+      splitView={false}
+    />
+  )
+}
+
+export default DiffString
diff --git a/frontend/web/components/diff/DiffVariations.tsx b/frontend/web/components/diff/DiffVariations.tsx
new file mode 100644
index 000000000000..89d944431e8e
--- /dev/null
+++ b/frontend/web/components/diff/DiffVariations.tsx
@@ -0,0 +1,50 @@
+import { TDiffVariation } from './diff-utils'
+import React, { FC } from 'react'
+import DiffString from './DiffString'
+import { DiffMethod } from 'react-diff-viewer-continued'
+
+const widths = [120]
+
+type DiffVariationsType = {
+  diffs: TDiffVariation[] | undefined
+}
+const DiffVariations: FC = ({ diffs }) => {
+  const tableHeader = (
+    
+      
Value
+
+ Weight +
+
+ ) + + return ( + <> + {tableHeader} + {diffs?.map((diff, i) => ( + +
+ +
+
+ +
+
+ ))} + + ) +} + +export default DiffVariations diff --git a/frontend/web/components/diff/diff-utils.ts b/frontend/web/components/diff/diff-utils.ts new file mode 100644 index 000000000000..1094261bc0cf --- /dev/null +++ b/frontend/web/components/diff/diff-utils.ts @@ -0,0 +1,165 @@ +import { FeatureState, ProjectFlag, Segment } from 'common/types/responses' +import Utils from 'common/utils/utils' +import { sortBy } from 'lodash' +export function getFeatureStateDiff( + oldFeatureState: FeatureState | undefined, + newFeatureState: FeatureState | undefined, +) { + const oldValue = Utils.getTypedValue( + Utils.featureStateToValue(oldFeatureState?.feature_state_value), + ) + const newValue = Utils.getTypedValue( + Utils.featureStateToValue(newFeatureState?.feature_state_value), + ) + const oldEnabled = !!oldFeatureState?.enabled + const newEnabled = !!newFeatureState?.enabled + const enabledChanged = oldEnabled !== newEnabled + const valueChanged = oldValue !== newValue + const diff = { + enabledChanged, + newEnabled, + newValue, + oldEnabled, + oldValue, + totalChanges: (enabledChanged ? 1 : 0) + (valueChanged ? 1 : 0), + valueChanged, + } + return diff +} + +export type TDiffSegment = { + segment: Segment + newEnabled: boolean + newPriority: number + newValue: string + oldEnabled: boolean + oldPriority: number + oldValue: string + totalChanges: number + created: boolean + deleted: boolean +} +export type TDiffVariation = { + hasChanged: boolean + newValue: string + newWeight: number + oldValue: string + oldWeight: number +} +export type TDiffVariations = { + diffs: TDiffVariation[] + totalChanges: number +} + +export const getSegmentDiff = ( + oldFeatureStates: FeatureState[] | undefined, + newFeatureStates: FeatureState[] | undefined, + segments: Segment[] | undefined, +) => { + if (!oldFeatureStates || !newFeatureStates || !segments) { + return null + } + + const relatedSegments = sortBy( + segments?.filter((segment) => { + return newFeatureStates + .concat(oldFeatureStates) + .find((v) => v.feature_segment?.segment === segment.id) + }), + (s) => s.name, + ) + let totalChanges = 0 + const diffs = relatedSegments?.map((segment) => { + const oldFeatureState = oldFeatureStates?.find( + (v) => v.feature_segment?.segment === segment.id, + ) + const newFeatureState = newFeatureStates?.find( + (v) => v.feature_segment?.segment === segment.id, + ) + + const oldEnabled = !!oldFeatureState?.enabled + const oldPriority = oldFeatureState?.feature_segment + ? oldFeatureState.feature_segment.priority + 1 + : -1 + const newPriority = newFeatureState?.feature_segment + ? newFeatureState.feature_segment.priority + 1 + : -1 + const newEnabled = !!newFeatureState?.enabled + + const oldValue = `${Utils.getTypedValue( + oldFeatureState + ? Utils.featureStateToValue(oldFeatureState?.feature_state_value) + : '', + )}` + const newValue = `${Utils.getTypedValue( + newFeatureState + ? Utils.featureStateToValue(newFeatureState?.feature_state_value) + : '', + )}` + + const enabledChanged = oldEnabled !== newEnabled + const valueChanged = oldValue !== newValue + const priorityChanged = oldPriority !== newPriority + const segmentChanges = + (enabledChanged ? 1 : 0) + + (valueChanged ? 1 : 0) + + (priorityChanged ? 1 : 0) + if (segmentChanges) { + totalChanges += 1 + } + return { + created: !oldFeatureState, + deleted: !newFeatureState, + enabledChanged, + newEnabled, + newPriority, + newValue, + oldEnabled, + oldPriority, + oldValue, + segment, + totalChanges: segmentChanges, + } as TDiffSegment + }) + return { + diffs, + totalChanges, + } +} + +export const getVariationDiff = ( + oldFeatureState: FeatureState | undefined, + newFeatureState: FeatureState | undefined, + feature: ProjectFlag | undefined, +) => { + let totalChanges = 0 + const diffs = feature?.multivariate_options?.map((variationOption) => { + const oldMV = oldFeatureState?.multivariate_feature_state_values?.find( + (v) => v.multivariate_feature_option === variationOption.id, + ) + const newMV = newFeatureState?.multivariate_feature_state_values?.find( + (v) => v.multivariate_feature_option === variationOption.id, + ) + + const oldValue = variationOption.string_value + const newValue = variationOption.string_value // todo: This would eventually be based on the old and new feature versions + const oldWeight = oldMV?.percentage_allocation + const newWeight = newMV?.percentage_allocation + const hasChanged = oldWeight !== newWeight || oldValue !== newValue + if (hasChanged) { + totalChanges += 1 + } + return { + hasChanged, + newValue, + newWeight, + oldValue, + oldWeight, + } as TDiffVariation + }) + + return { + diffs, + totalChanges, + } as TDiffVariations +} diff --git a/frontend/web/components/pages/AuditLogItemPage.tsx b/frontend/web/components/pages/AuditLogItemPage.tsx new file mode 100644 index 000000000000..54c2f64a754f --- /dev/null +++ b/frontend/web/components/pages/AuditLogItemPage.tsx @@ -0,0 +1,125 @@ +import React, { FC } from 'react' +import { useGetAuditLogItemQuery } from 'common/services/useAuditLogItem' +import ErrorMessage from 'components/ErrorMessage' +import Breadcrumb from 'components/Breadcrumb' +import PageTitle from 'components/PageTitle' +import Panel from 'components/base/grid/Panel' +import moment from 'moment' +import ProjectStore from 'common/stores/project-store' +import Utils from 'common/utils/utils' +import Tag from 'components/tags/Tag' +import DiffString from 'components/diff/DiffString' +import DiffEnabled from 'components/diff/DiffEnabled' +import Format from 'common/utils/format' +import { Environment } from 'common/types/responses' +type AuditLogItemPageType = { + match: { + params: { + environmentId: string + projectId: string + id: string + } + } +} + +const AuditLogItemPage: FC = ({ match }) => { + const { data, error, isLoading } = useGetAuditLogItemQuery({ + id: match.params.id, + }) + + const index = (ProjectStore.getEnvs() as Environment[] | null)?.findIndex( + (v) => { + return v.id === data?.environment?.id + }, + ) + const colour = index === -1 ? 0 : index + + return ( +
+ + + Log #{match.params.id} + {!!data?.environment && ( +
+ +
+ )} + + } + > + {!!data && + `Created ${moment(data.created_date).format('Do MMM YYYY HH:mma')}${ + data.author + ? ` by ${data.author.first_name || ''} ${ + data.author.last_name || '' + }` + : '' + }`} +
+ {isLoading ? ( +
+ +
+ ) : ( +
+ {error} + {!!data && ( + <> + +

{data.log}

+
+ {!!data?.change_details?.length && ( + +
+
+
Field
+
Value
+
+ {data?.change_details?.map((v) => ( + +
+ {Format.camelCase(Format.enumeration.get(v.field))} +
+
+ {v.field === 'enabled' ? ( + + ) : ( + + )} +
+
+ ))} +
+
+ )} + + )} +
+ )} +
+ ) +} + +export default AuditLogItemPage diff --git a/frontend/web/routes.js b/frontend/web/routes.js index b3ad40d7eba9..45e3660a3971 100644 --- a/frontend/web/routes.js +++ b/frontend/web/routes.js @@ -29,6 +29,7 @@ import ComparePage from './components/pages/ComparePage' import WidgetPage from './components/pages/WidgetPage' import BrokenPage from './components/pages/BrokenPage' import ProjectsPage from './components/pages/ProjectsPage' +import AuditLogItemPage from './components/pages/AuditLogItemPage' export default ( @@ -158,6 +159,11 @@ export default ( exact component={AuditLogPage} /> + diff --git a/frontend/web/styles/3rdParty/_index.scss b/frontend/web/styles/3rdParty/_index.scss index f857b31cb4dc..423ed6ff9a0a 100644 --- a/frontend/web/styles/3rdParty/_index.scss +++ b/frontend/web/styles/3rdParty/_index.scss @@ -3,3 +3,4 @@ @import "hljs"; @import "react-datepicker"; @import "hw-badge"; +@import "react-diff"; diff --git a/frontend/web/styles/3rdParty/_react-diff.scss b/frontend/web/styles/3rdParty/_react-diff.scss new file mode 100644 index 000000000000..0e1c491796b0 --- /dev/null +++ b/frontend/web/styles/3rdParty/_react-diff.scss @@ -0,0 +1,73 @@ +@import "../variables"; +.react-diff-1n5o7vh-diff-container { + background-color: transparent !important; + +} +.token.property { + color: $success; +} +.token.number,.token.boolean { + color: $info; +} +.react-diff-marker { + background-color: $black-alpha-8; + width: 31px; + height: 31px; + justify-content: center; + display: flex; + align-items: center; + &.react-diff-marker--added { + background-color: $success-alfa-16 !important; + + } + &.react-diff-marker--removed { + background-color: $danger-alfa-16 !important; + } +} +.react-diff-line { + line-height: 31px; + &.react-diff-line--added { + background-color: $success-alfa-16 !important; + } + &.react-diff-line--removed { + background-color: $danger-alfa-16 !important; + } +} +.react-diff-line pre { + background-color: $black-alpha-8; + display: flex; + flex:1; + line-height: 28px; +} +.react-diff-42iver-word-diff { + padding:0 !important; +} +.react-diff-1p2tkx4-marker.react-diff-1fxlvce-diff-removed { + background-color: $danger-alfa-16 !important; +} +.react-diff-1p2tkx4-marker.react-diff-1fqrsd-diff-added { + background-color: $success-alfa-16 !important; +} +.react-diff-hf3w1f-word-removed { + background-color: $danger-alfa-8 !important; +} +.react-diff-1u4zuq6-word-added { + background-color: $success-alfa-8 !important; +} +.react-diff-1n5o7vh-diff-container pre { + font-family: $font-family-monospace; + font-size: $font-caption !important; + color: $body-text !important; +} +.react-diff-1fxlvce-diff-removed { + background-color: $danger-alfa-8 !important; +} +.react-diff-1fqrsd-diff-added { + background-color: $success-alfa-8 !important; +} + +.dark { + .react-diff-1n5o7vh-diff-container pre { + color: $body-text-dark !important; + } +} diff --git a/frontend/web/styles/components/_panel.scss b/frontend/web/styles/components/_panel.scss index 3f248260d38b..6abc79b2530a 100644 --- a/frontend/web/styles/components/_panel.scss +++ b/frontend/web/styles/components/_panel.scss @@ -204,6 +204,10 @@ a.text-white { border-bottom-left-radius: $border-radius-default; border-bottom-right-radius: $border-radius-default; } + &:first-of-type { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } } } } diff --git a/frontend/web/styles/new/_variables-new.scss b/frontend/web/styles/new/_variables-new.scss index 209cbbbbc506..fce19c5559a0 100644 --- a/frontend/web/styles/new/_variables-new.scss +++ b/frontend/web/styles/new/_variables-new.scss @@ -44,9 +44,11 @@ $white-alpha-24: rgba(255, 255, 255, 0.24); $white-alpha-32: rgba(255, 255, 255, 0.32); $white-alpha-48: rgba(255, 255, 255, 0.48); $black-alpha-16: rgba(0, 0, 0, 0.16); +$black-alpha-8: rgba(0, 0, 0, 0.08); $black-alpha-32: rgba(0, 0, 0, 0.32); $secondary-alfa-16: rgba(247, 213, 110, 0.16); $success-alfa-8: rgba(39, 171, 149, 0.08); +$success-alfa-16: rgba(39, 171, 149, 0.16); $success-solid-alert: rgba(238, 248, 247); $info-solid-alert: rgba(236, 249, 252); $warning-solid-alert: rgba(255, 248, 240); diff --git a/frontend/web/styles/project/_utils.scss b/frontend/web/styles/project/_utils.scss index de609acb7b70..2a0752e6ec21 100644 --- a/frontend/web/styles/project/_utils.scss +++ b/frontend/web/styles/project/_utils.scss @@ -181,6 +181,10 @@ } } +.mh-auto { + min-height: auto !important; +} + .text-overflow { flex: 1; white-space: nowrap;