Merge remote-tracking branch 'jar0s/feature/radar-chart'

This commit is contained in:
Bastian Ike
2022-01-07 13:25:05 +01:00
28 changed files with 1238 additions and 46 deletions

View File

@@ -1,9 +0,0 @@
{
"quadrants": {
"languages-and-frameworks": "Languages & Frameworks",
"methods-and-patterns": "Methods & Patterns",
"platforms-and-aoe-services": "Platforms & Operations",
"tools": "Tools"
},
"rings":["all", "adopt", "trial", "assess", "hold"]
}

View File

@@ -83,6 +83,7 @@ var front_matter_1 = __importDefault(require("front-matter"));
var marked_1 = __importDefault(require("marked")); var marked_1 = __importDefault(require("marked"));
var highlight_js_1 = __importDefault(require("highlight.js")); var highlight_js_1 = __importDefault(require("highlight.js"));
var file_1 = require("./file"); var file_1 = require("./file");
var model_1 = require("../../src/model");
var paths_1 = require("../paths"); var paths_1 = require("../paths");
marked_1.default.setOptions({ marked_1.default.setOptions({
highlight: function (code) { return highlight_js_1.default.highlightAuto(code).value; }, highlight: function (code) { return highlight_js_1.default.highlightAuto(code).value; },
@@ -180,7 +181,7 @@ var ignoreEmptyRevisionBody = function (revision, item) {
}; };
var addRevisionToItem = function (item, revision) { var addRevisionToItem = function (item, revision) {
if (item === void 0) { item = { if (item === void 0) { item = {
flag: "default", flag: model_1.FlagType.default,
featured: true, featured: true,
revisions: [], revisions: [],
name: "", name: "",
@@ -215,10 +216,10 @@ var hasItemChanged = function (item, allReleases) {
}; };
var getItemFlag = function (item, allReleases) { var getItemFlag = function (item, allReleases) {
if (isNewItem(item, allReleases)) { if (isNewItem(item, allReleases)) {
return "new"; return model_1.FlagType.new;
} }
if (hasItemChanged(item, allReleases)) { if (hasItemChanged(item, allReleases)) {
return "changed"; return model_1.FlagType.changed;
} }
return "default"; return model_1.FlagType.changed;
}; };

View File

@@ -16,7 +16,19 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
return to; return to;
}; };
Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true });
exports.getFirstLetter = exports.groupByFirstLetter = exports.groupByQuadrants = exports.nonFeaturedOnly = exports.featuredOnly = void 0; exports.getFirstLetter = exports.groupByFirstLetter = exports.groupByQuadrants = exports.nonFeaturedOnly = exports.featuredOnly = exports.FlagType = exports.HomepageOption = void 0;
var HomepageOption;
(function (HomepageOption) {
HomepageOption[HomepageOption["chart"] = 0] = "chart";
HomepageOption[HomepageOption["columns"] = 1] = "columns";
HomepageOption[HomepageOption["both"] = 2] = "both";
})(HomepageOption = exports.HomepageOption || (exports.HomepageOption = {}));
var FlagType;
(function (FlagType) {
FlagType["new"] = "new";
FlagType["changed"] = "changed";
FlagType["default"] = "default";
})(FlagType = exports.FlagType || (exports.FlagType = {}));
var featuredOnly = function (items) { var featuredOnly = function (items) {
return items.filter(function (item) { return item.featured; }); return items.filter(function (item) { return item.featured; });
}; };

View File

@@ -24,15 +24,18 @@
"lint": "yarn ts:check && eslint src/**/*.tsx" "lint": "yarn ts:check && eslint src/**/*.tsx"
}, },
"dependencies": { "dependencies": {
"@types/d3": "^7.1.0",
"@types/fs-extra": "^9.0.13", "@types/fs-extra": "^9.0.13",
"@types/marked": "^2.0.3", "@types/marked": "^2.0.3",
"@types/node": "^16.10.1", "@types/node": "^16.10.1",
"@types/react": "^17.0.24", "@types/react": "^17.0.24",
"@types/react-dom": "^17.0.9", "@types/react-dom": "^17.0.9",
"@types/react-router-dom": "^5.3.0", "@types/react-router-dom": "^5.3.0",
"@types/react-tooltip": "^4.2.4",
"@types/sanitize-html": "^2.5.0", "@types/sanitize-html": "^2.5.0",
"@types/walk": "^2.3.1", "@types/walk": "^2.3.1",
"classnames": "^2.3.1", "classnames": "^2.3.1",
"d3": "^7.2.1",
"front-matter": "^4.0.2", "front-matter": "^4.0.2",
"fs-extra": "^10.0.0", "fs-extra": "^10.0.0",
"highlight.js": "^11.2.0", "highlight.js": "^11.2.0",
@@ -44,6 +47,7 @@
"react-icons": "^4.2.0", "react-icons": "^4.2.0",
"react-router-dom": "^5.3.0", "react-router-dom": "^5.3.0",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",
"react-tooltip": "^4.2.21",
"sanitize-html": "^2.5.2", "sanitize-html": "^2.5.2",
"sass": "^1.42.1", "sass": "^1.42.1",
"typescript": "4.3.5", "typescript": "4.3.5",

View File

@@ -5,6 +5,64 @@
"platforms-and-aoe-services": "Platforms & Operations", "platforms-and-aoe-services": "Platforms & Operations",
"tools": "Tools" "tools": "Tools"
}, },
"rings":["all", "adopt", "trial", "assess", "hold"], "rings": [
"showEmptyRings": false "adopt",
"trial",
"assess",
"hold"
],
"showEmptyRings": false,
"homepageContent": "both",
"quadrantsMap": {
"languages-and-frameworks": {
"colour": "#84BFA4",
"txtColour": "#444444",
"position": 1,
"description": "We've placed development languages (such as Scala or Golang) here, as well as more low-level development frameworks (such as Play or Symfony), which are useful for implementing custom software of all kinds."
},
"methods-and-patterns": {
"colour": "#248EA6",
"txtColour": "white",
"position": 2,
"description": "Here we put information on methods and patterns concerning development, continuous x, testing, organization, architecture, etc."
},
"platforms-and-aoe-services": {
"colour": "#F25244",
"txtColour": "#444444",
"position": 3,
"description": "Here we include infrastructure platforms and services. We also use this category to communicate news about AOE services that we want all AOE teams to be aware of."
},
"tools": {
"colour": "#F2A25C",
"txtColour": "white",
"position": 4,
"description": "Here we put different software tools - from small helpers to bigger software projects"
}
},
"chartConfig": {
"size": 800,
"scale": [
-16,
16
],
"blipSize": 12,
"ringsAttributes": [
{
"radius": 8,
"arcWidth": 6
},
{
"radius": 11,
"arcWidth": 4
},
{
"radius": 14,
"arcWidth": 2
},
{
"radius": 16,
"arcWidth": 2
}
]
}
} }

View File

@@ -7,7 +7,7 @@ import marked from "marked";
import highlight from "highlight.js"; import highlight from "highlight.js";
import { radarPath, getAllMarkdownFiles } from "./file"; import { radarPath, getAllMarkdownFiles } from "./file";
import { Item, Revision, ItemAttributes, Radar } from "../../src/model"; import { Item, Revision, ItemAttributes, Radar, FlagType } from "../../src/model";
import { appBuild } from "../paths"; import { appBuild } from "../paths";
type FMAttributes = ItemAttributes; type FMAttributes = ItemAttributes;
@@ -124,7 +124,7 @@ const ignoreEmptyRevisionBody = (revision: Revision, item: Item) => {
const addRevisionToItem = ( const addRevisionToItem = (
item: Item = { item: Item = {
flag: "default", flag: FlagType.default,
featured: true, featured: true,
revisions: [], revisions: [],
name: "", name: "",
@@ -177,10 +177,10 @@ const hasItemChanged = (item: Item, allReleases: string[]) =>
const getItemFlag = (item: Item, allReleases: string[]): string => { const getItemFlag = (item: Item, allReleases: string[]): string => {
if (isNewItem(item, allReleases)) { if (isNewItem(item, allReleases)) {
return "new"; return FlagType.new;
} }
if (hasItemChanged(item, allReleases)) { if (hasItemChanged(item, allReleases)) {
return "changed"; return FlagType.changed;
} }
return "default"; return FlagType.changed;
}; };

View File

@@ -1,6 +1,7 @@
import React, { MouseEventHandler } from "react"; import React, { MouseEventHandler } from "react";
import classNames from "classnames"; import classNames from "classnames";
import "./badge.scss"; import "./badge.scss";
type BadgeProps = { type BadgeProps = {
onClick?: MouseEventHandler; onClick?: MouseEventHandler;
big?: boolean; big?: boolean;

View File

@@ -0,0 +1,46 @@
import React, { useRef, useLayoutEffect } from 'react';
import * as d3 from "d3";
export const YAxis: React.FC<{
scale: d3.ScaleLinear<number, number>
}> = ({ scale }) => {
const ref = useRef<SVGSVGElement>(null);
useLayoutEffect(() => {
if (ref.current == null) {
return
}
const axisGenerator = d3.axisLeft(scale).ticks(6);
d3.select(ref.current)
.attr('class', 'y-axis')
.call(axisGenerator)
.call(g => g.selectAll('.tick text').remove())
.call(g => g.selectAll('.tick line').remove())
.call(g => g.selectAll('.domain').remove());
}, [scale]);
return <g ref={ref} />;
};
export const XAxis: React.FC<{
scale: d3.ScaleLinear<number, number>
}> = ({ scale }) => {
const ref = useRef<SVGSVGElement>(null);
useLayoutEffect(() => {
if (ref.current == null) {
return
}
const axisGenerator = d3.axisBottom(scale).ticks(6);
d3.select(ref.current)
.attr('class', 'x-axis')
.call(axisGenerator)
.call(g => g.selectAll('.tick text').remove())
.call(g => g.selectAll('.tick line').remove())
.call(g => g.selectAll('.domain').remove());
}, [scale]);
return <g ref={ref} />;
};

View File

@@ -0,0 +1,126 @@
import React from 'react';
import { ScaleLinear } from 'd3';
import { FlagType, Item, Blip, Point } from '../../model';
import Link from '../Link/Link';
import { NewBlip, ChangedBlip, DefaultBlip } from './BlipShapes';
import { ConfigData } from '../../config';
/*
See https://medium.com/create-code/build-a-radar-diagram-with-d3-js-9db6458a9248
for a good explanation of formulas used to calculate various things in this component
*/
function generateCoordinates(blip: Blip, xScale: ScaleLinear<number, number>, yScale: ScaleLinear<number, number>, config: ConfigData): Point {
const pi = Math.PI,
ringRadius = config.chartConfig.ringsAttributes[blip.ringPosition].radius,
previousRingRadius = blip.ringPosition === 0 ? 0 : config.chartConfig.ringsAttributes[blip.ringPosition - 1].radius,
ringPadding = 0.7;
// radian between 0 and 90 degrees
const randomDegree = ((Math.random() * 90) * pi) / 180;
// random distance from the centre of the radar, but within given ring. Also, with some "padding" so the points don't touch ring borders.
const radius = randomBetween(previousRingRadius + ringPadding, ringRadius - ringPadding);
/*
Multiples of PI/2. To apply the calculated position to the specific quadrant.
Order here is counter-clockwise, so we need to "invert" quadrant positions (i.e. swap 2 with 4)
*/
const shift = pi * [1, 4, 3, 2][blip.quadrantPosition - 1] / 2;
return {
x: xScale(Math.cos(randomDegree + shift) * radius),
y: yScale(Math.sin(randomDegree + shift) * radius)
};
};
function randomBetween (min: number, max: number): number {
return Math.random() * (max - min) + min;
};
function distanceBetween(point1: Point, point2: Point): number {
const a = point2.x - point1.x;
const b = point2.y - point1.y;
return Math.sqrt((a * a) + (b * b));
};
function renderBlip(blip: Blip, index: number, config: ConfigData): JSX.Element {
const props = {
blip,
className: 'blip',
fill: blip.colour,
'data-background-color': blip.colour,
'data-text-color': blip.txtColour,
'data-tip': blip.title,
key: index
}
switch (blip.flag) {
case FlagType.new:
return <NewBlip {...props} config={config} />;
case FlagType.changed:
return <ChangedBlip {...props} config={config} />;
default:
return <DefaultBlip {...props} config={config} />;
}
};
const BlipPoints: React.FC<{
items: Item[]
xScale:ScaleLinear<number, number>
yScale:ScaleLinear<number, number>
config:ConfigData
}> = ({items, xScale, yScale, config}) => {
const blips: Blip[] = items.reduce((list: Blip[], item: Item) => {
if (!item.ring || !item.quadrant) {
// skip the blip if it doesn't have a ring or quadrant assigned
return list;
}
const quadrantConfig = config.quadrantsMap[item.quadrant];
if (!quadrantConfig) {
return list;
}
let blip: Blip = { ...item,
quadrantPosition: quadrantConfig.position,
ringPosition: config.rings.findIndex(r => r === item.ring),
colour: quadrantConfig.colour,
txtColour: quadrantConfig.txtColour,
coordinates: {x: 0, y: 0},
};
let point: Point;
let counter = 1;
let distanceBetweenCheck: boolean;
do {
const localpoint = generateCoordinates(blip, xScale, yScale, config);
point = localpoint
counter++;
/*
Generate position of the new blip until it has a satisfactory distance to every other blip (so that they don't touch each other)
and quadrant borders (so that they don't overlap quadrants)
This feels pretty inefficient, but good enough for now.
*/
distanceBetweenCheck = list.some(b => distanceBetween(localpoint, b.coordinates) < config.chartConfig.blipSize + config.chartConfig.blipSize / 2)
} while (counter < 100
&& (Math.abs(point.x - xScale(0)) < 15
|| Math.abs(point.y - yScale(0)) < 15
|| distanceBetweenCheck
));
blip.coordinates = point;
list.push(blip);
return list;
}, []);
return (
<g className="blips">
{blips.map((blip, index) => (
<Link pageName={`${blip.quadrant}/${blip.name}`} key={index}>
{renderBlip(blip, index, config)}
</Link>
))}
</g>
);
};
export default BlipPoints;

View File

@@ -0,0 +1,64 @@
import React from 'react';
import { ConfigData } from '../../config';
import { Blip } from '../../model';
type VisualBlipProps = {
className: string,
fill: string,
'data-background-color': string,
'data-text-color': string,
'data-tip': string,
key: number
}
export const ChangedBlip: React.FC<
{blip: Blip, config: ConfigData} & VisualBlipProps
> = ({blip, config, ...props}) => {
const centeredX = blip.coordinates.x - config.chartConfig.blipSize/2,
centeredY = blip.coordinates.y - config.chartConfig.blipSize/2;
return (
<rect
transform={`rotate(-45 ${centeredX} ${centeredY})`}
x={centeredX}
y={centeredY}
width={config.chartConfig.blipSize}
height={config.chartConfig.blipSize}
rx="3"
{...props}
/>
);
};
export const NewBlip: React.FC<
{blip: Blip, config: ConfigData} & VisualBlipProps
> = ({blip, config, ...props}) => {
const centeredX = blip.coordinates.x - config.chartConfig.blipSize/2,
centeredY = blip.coordinates.y - config.chartConfig.blipSize/2;
/*
The below is a predefined path of a triangle with rounded corners.
I didn't find any more human friendly way of doing this as all examples I found have tons of lines of code
e.g. https://observablehq.com/@perlmonger42/interactive-rounded-corners-on-svg-polygons-using-d3-js
*/
return (
<path
transform={`translate(${centeredX}, ${centeredY})`}
d="M.247 10.212l5.02-8.697a2 2 0 013.465 0l5.021 8.697a2 2 0 01-1.732 3H1.98a2 2 0 01-1.732-3z"
{...props}
/>
);
};
export const DefaultBlip: React.FC<
{blip: Blip, config: ConfigData} & VisualBlipProps
> = ({blip, config, ...props}) => {
return (
<circle
r={config.chartConfig.blipSize / 2}
cx={blip.coordinates.x}
cy={blip.coordinates.y}
{...props}
/>
);
};

View File

@@ -0,0 +1,74 @@
import React from 'react';
import * as d3 from 'd3';
import { QuadrantConfig } from '../../model';
import { ConfigData } from '../../config';
function arcPath(quadrantPosition: number, ringPosition: number, xScale: d3.ScaleLinear<number, number>, config: ConfigData) {
const startAngle = quadrantPosition === 1 ?
3 * Math.PI / 2
: (quadrantPosition - 2) * Math.PI / 2
const endAngle = quadrantPosition === 1 ?
4 * Math.PI / 2
: (quadrantPosition -1) * Math.PI / 2
const arcAttrs = config.chartConfig.ringsAttributes[ringPosition],
ringRadiusPx = xScale(arcAttrs.radius) - xScale(0),
arc = d3.arc();
return arc({
innerRadius: ringRadiusPx - arcAttrs.arcWidth,
outerRadius: ringRadiusPx,
startAngle,
endAngle
}) || undefined;
}
const QuadrantRings: React.FC<{
quadrant: QuadrantConfig
xScale: d3.ScaleLinear<number, number>
config: ConfigData
}> = ({ quadrant, xScale, config}) => {
// order from top-right clockwise
const gradientAttributes = [
{x: 0, y: 0, cx: 1, cy: 1, r: 1},
{x: xScale(0), y: 0, cx: 0, cy: 1, r: 1},
{x: xScale(0), y: xScale(0), cx: 0, cy: 0, r: 1},
{x: 0, y: xScale(0), cx: 1, cy: 0, r: 1}
];
const gradientId = `${quadrant.position}-radial-gradient`,
quadrantSize = config.chartConfig.size / 2;
return (
<g className="quadrant-ring">
{/* Definition of the quadrant gradient */}
<defs>
<radialGradient id={gradientId} {...gradientAttributes[quadrant.position - 1]}>
<stop offset="0%" stopColor={quadrant.colour}></stop>
<stop offset="100%" stopColor={quadrant.colour} stopOpacity="0"></stop>
</radialGradient>
</defs>
{/* Gradient background area */}
<rect
width={quadrantSize}
height={quadrantSize}
x={gradientAttributes[quadrant.position - 1].x}
y={gradientAttributes[quadrant.position - 1].y}
fill={`url(#${gradientId})`}
style={{opacity: 0.5}}
/>
{/* Rings' arcs */}
{Array.from(config.rings).map((ringPosition, index) => (
<path
key={index}
fill={quadrant.colour}
d={arcPath(quadrant.position, index, xScale, config)}
style={{transform: `translate(${quadrantSize}px, ${quadrantSize}px)`}}
/>
))}
</g>
);
}
export default QuadrantRings;

View File

@@ -0,0 +1,77 @@
import React from 'react';
import * as d3 from "d3";
import ReactTooltip from 'react-tooltip';
import { Item } from '../../model';
import { YAxis, XAxis } from './Axes';
import QuadrantRings from './QuadrantRings';
import BlipPoints from './BlipPoints';
import './chart.scss';
import { ConfigData } from '../../config';
const RingLabel: React.FC<{
ring: string
xScale: d3.ScaleLinear<number, number>
yScale: d3.ScaleLinear<number, number>
config: ConfigData
}> = ({ring, xScale, yScale, config}) => {
const ringIndex = config.rings.findIndex(r => r === ring)
const ringRadius = config.chartConfig.ringsAttributes[ringIndex].radius,
previousRingRadius = ringIndex === 0 ? 0 : config.chartConfig.ringsAttributes[ringIndex - 1].radius,
// middle point in between two ring arcs
distanceFromCentre = previousRingRadius + (ringRadius - previousRingRadius) / 2;
return (
<g className="ring-label">
{/* Right hand-side label */}
<text x={xScale(distanceFromCentre)} y={yScale(0)} textAnchor="middle" dy=".35em">
{ring}
</text>
{/* Left hand-side label */}
<text x={xScale(-distanceFromCentre)} y={yScale(0)} textAnchor="middle" dy=".35em">
{ring}
</text>
</g>
);
};
const RadarChart: React.FC<{
items: Item[]
config: ConfigData
}> = ({ items, config }) => {
const xScale = d3.scaleLinear()
.domain(config.chartConfig.scale)
.range([0, config.chartConfig.size]);
const yScale = d3.scaleLinear()
.domain(config.chartConfig.scale)
.range([config.chartConfig.size, 0]);
return (
<div className="chart" style={{maxWidth: `${config.chartConfig.size}px`}}>
<svg viewBox={`0 0 ${config.chartConfig.size} ${config.chartConfig.size}`}>
<g transform={`translate(${xScale(0)}, 0)`}>
<YAxis scale={yScale}/>
</g>
<g transform={`translate(0, ${yScale(0)})`}>
<XAxis scale={xScale}/>
</g>
{Object.values(config.quadrantsMap).map((value, index) => (
<QuadrantRings key={index} quadrant={value} xScale={xScale} config={config} />
))}
{Array.from(config.rings).map((ring: string, index) => (
<RingLabel key={index} ring={ring} xScale={xScale} yScale={yScale} config={config} />
))}
<BlipPoints items={items} xScale={xScale} yScale={yScale} config={config} />
</svg>
<ReactTooltip className="tooltip" offset={{top: -5}}/>
</div>
);
}
export default RadarChart;

View File

@@ -0,0 +1,20 @@
.chart {
fill: white;
font-size: 12px;
text-align: center;
position: relative;
margin: 0 auto;
}
.chart .blip:hover {
cursor: pointer;
}
.chart .tooltip {
padding: 5px 10px;
border-radius: 11px;
}
.chart .ring-label {
text-transform: uppercase;
}

View File

@@ -1,8 +1,6 @@
import React from "react"; import { FlagType } from "../../model";
import "./flag.scss"; import "./flag.scss";
export type FlagType = "new" | "changed" | "default";
interface ItemFlag { interface ItemFlag {
flag: FlagType; flag: FlagType;
} }
@@ -16,7 +14,7 @@ export default function Flag({
}) { }) {
const ucFirst = (s: string) => s.charAt(0).toUpperCase() + s.slice(1); const ucFirst = (s: string) => s.charAt(0).toUpperCase() + s.slice(1);
if (item.flag !== "default") { if (item.flag !== FlagType.default) {
let name = item.flag.toUpperCase(); let name = item.flag.toUpperCase();
let title = ucFirst(item.flag); let title = ucFirst(item.flag);
if (short === true) { if (short === true) {

View File

@@ -1,7 +1,7 @@
import { Item } from "../../model"; import { FlagType, Item } from "../../model";
export const item: Item = { export const item: Item = {
flag: "default", flag: FlagType.default,
featured: false, featured: false,
revisions: [ revisions: [
{ {

View File

@@ -1,4 +1,3 @@
import React from "react";
import Badge from "../Badge/Badge"; import Badge from "../Badge/Badge";
import { formatRelease } from "../../date"; import { formatRelease } from "../../date";
import { Revision } from "../../model"; import { Revision } from "../../model";

View File

@@ -1,6 +1,7 @@
import React from "react"; import React from "react";
import { Link as RLink } from "react-router-dom"; import { Link as RLink } from "react-router-dom";
import "./link.scss"; import "./link.scss";
type LinkProps = { type LinkProps = {
pageName: string; pageName: string;
style?: React.CSSProperties; style?: React.CSSProperties;

View File

@@ -33,14 +33,13 @@ const PageHelp: React.FC<Props> = ({ leaving, onLeave }) => {
<React.Fragment key={headline}> <React.Fragment key={headline}>
<h3>{headline}</h3> <h3>{headline}</h3>
{values.map((element, index) => { {values.map((element, index) => {
const content = sanitizeHtml(element, { return (
<p key={index} dangerouslySetInnerHTML={sanitize(element, {
allowedTags: ['b', 'i', 'em', 'strong', 'a', 'ul', 'ol', 'li'], allowedTags: ['b', 'i', 'em', 'strong', 'a', 'ul', 'ol', 'li'],
allowedAttributes: { allowedAttributes: {
'a': ['href', 'target'] 'a': ['href', 'target']
}, },
}); })}></p>
return (
<p key={index} dangerouslySetInnerHTML={sanitize(element)}></p>
) )
}) })
} }

View File

@@ -1,7 +1,8 @@
import { formatRelease } from "../../date"; import { formatRelease } from "../../date";
import { featuredOnly, Item } from "../../model"; import { featuredOnly, Item, HomepageOption } from "../../model";
import HeroHeadline from "../HeroHeadline/HeroHeadline"; import HeroHeadline from "../HeroHeadline/HeroHeadline";
import QuadrantGrid from "../QuadrantGrid/QuadrantGrid"; import QuadrantGrid from "../QuadrantGrid/QuadrantGrid";
import RadarGrid from '../RadarGrid/RadarGrid';
import Fadeable from "../Fadeable/Fadeable"; import Fadeable from "../Fadeable/Fadeable";
import SetTitle from "../SetTitle"; import SetTitle from "../SetTitle";
import { ConfigData, radarName, radarNameShort } from "../../config"; import { ConfigData, radarName, radarNameShort } from "../../config";
@@ -28,6 +29,8 @@ export default function PageIndex({
const newestRelease = releases.slice(-1)[0]; const newestRelease = releases.slice(-1)[0];
const numberOfReleases = releases.length; const numberOfReleases = releases.length;
const showChart = config.homepageContent === HomepageOption.chart || config.homepageContent === HomepageOption.both;
const showColumns = config.homepageContent === HomepageOption.columns || config.homepageContent === HomepageOption.both;
return ( return (
<Fadeable leaving={leaving} onLeave={onLeave}> <Fadeable leaving={leaving} onLeave={onLeave}>
<SetTitle title={radarNameShort} /> <SetTitle title={radarNameShort} />
@@ -36,7 +39,12 @@ export default function PageIndex({
{radarName} {radarName}
</HeroHeadline> </HeroHeadline>
</div> </div>
{showChart && (
<RadarGrid items={featuredOnly(items)} config={config} />
)}
{showColumns && (
<QuadrantGrid items={featuredOnly(items)} config={config} /> <QuadrantGrid items={featuredOnly(items)} config={config} />
)}
<div className="publish-date"> <div className="publish-date">
{publishedLabel} {formatRelease(newestRelease)} {publishedLabel} {formatRelease(newestRelease)}
</div> </div>

View File

@@ -0,0 +1,75 @@
import React from "react";
import RadarChart from "../Chart/RadarChart";
import { ConfigData } from "../../config";
import { Item, QuadrantConfig } from "../../model";
import "./radar-grid.scss";
import Link from "../Link/Link";
const QuadrantLabel: React.FC<{
quadrantConfig: QuadrantConfig;
quadrantName: string;
quadrantLabel: string;
}> = ({ quadrantConfig, quadrantName, quadrantLabel }) => {
const stylesMap = [
{ top: 0, left: 0 },
{ top: 0, right: 0 },
{ bottom: 0, right: 0 },
{ bottom: 0, left: 0 },
];
return (
<div className="quadrant-label" style={stylesMap[quadrantConfig.position - 1]}>
<div className="split">
<div className="split__left">
<small>Quadrant {quadrantConfig.position}</small>
</div>
<div className="split__right">
<Link className="icon-link" pageName={`${quadrantName}`}>
<span className="icon icon--pie icon-link__icon" />
Zoom In
</Link>
</div>
</div>
<hr style={{ borderColor: quadrantConfig.colour }} />
<h4 className="headline">{quadrantLabel}</h4>
<div className="description">{quadrantConfig.description}</div>
</div>
);
};
const Legend: React.FC = () => {
return (
<div className="radar-legend">
<div className="wrapper">
<span className="icon icon--blip_new"></span>
New in this version
</div>
<div className="wrapper">
<span className="icon icon--blip_changed"></span>
Recently changed
</div>
<div className="wrapper">
<span className="icon icon--blip_default"></span>
Unchanged
</div>
</div>
);
};
const RadarGrid: React.FC<{ items: Item[]; config: ConfigData }> = ({
items,
config,
}) => {
return (
<div className="radar-grid">
<RadarChart items={items} config={config} />
{Object.entries(config.quadrantsMap).map(([name, quadrant], index) => (
<QuadrantLabel key={index} quadrantConfig={quadrant} quadrantName={name} quadrantLabel={config.quadrants[name]} />
))}
<Legend />
</div>
);
};
export default RadarGrid;

View File

@@ -0,0 +1,59 @@
.radar-grid {
position: relative;
margin-bottom: 50px;
color: white;
display: none;
}
@media screen and (min-width: 800px) {
.radar-grid {
display: block;
}
}
.radar-grid .quadrant-label {
position: absolute;
width: 20%;
}
.quadrant-label .split {
font-size: 12 px;
text-transform: uppercase;
}
.quadrant-label hr {
width: 100%;
margin: 10px 0 10px 0;
}
.quadrant-label .description {
font-size: 14px;
color: #a6b1bb
}
.quadrant-label .icon-link {
font-size: 12px;
}
.quadrant-label .icon-link .icon {
background-size: 18px 18px;
width: 18px;
height: 18px;
}
.radar-grid .radar-legend {
position: absolute;
width: 15%;
right: 0;
top: 45%;
}
.radar-legend .wrapper {
margin-bottom: 10px;
}
.radar-legend .icon {
background-position: center;
margin-right: 5px;
}

View File

@@ -1,9 +1,17 @@
import { Item } from "./model"; import {Item, HomepageOption, QuadrantConfig} from './model';
export interface ConfigData { export interface ConfigData {
quadrants: { [key: string]: string }; quadrants: { [key: string]: string };
rings: string[]; rings: string[];
showEmptyRings: boolean; showEmptyRings: boolean;
quadrantsMap: { [quadrant: string]: QuadrantConfig };
chartConfig: {
size: number,
scale: number[],
blipSize: number,
ringsAttributes: {radius: number, arcWidth: number}[]
};
homepageContent: HomepageOption;
} }
export const radarName = export const radarName =

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<rect transform="rotate(-45 8 8)" x="2" y="2" width="12" height="12" rx="3" fill="#a6b1bb"></rect>
</svg>

After

Width:  |  Height:  |  Size: 319 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="6" fill="#a6b1bb"></circle>
</svg>

After

Width:  |  Height:  |  Size: 273 B

4
src/icons/blip_new.svg Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewbox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path fill="#a6b1bb" d="M.247 10.212l5.02-8.697a2 2 0 013.465 0l5.021 8.697a2 2 0 01-1.732 3H1.98a2 2 0 01-1.732-3z"></path>
</svg>

After

Width:  |  Height:  |  Size: 345 B

View File

@@ -1,3 +1,9 @@
export enum HomepageOption {
chart = "chart",
columns = "columns",
both = "both"
}
export type ItemAttributes = { export type ItemAttributes = {
name: string; name: string;
ring: string; ring: string;
@@ -6,7 +12,11 @@ export type ItemAttributes = {
featured?: boolean; featured?: boolean;
}; };
export type FlagType = "new" | "changed" | "default"; export enum FlagType {
new = 'new',
changed = 'changed',
default = 'default'
}
export type Item = ItemAttributes & { export type Item = ItemAttributes & {
featured: boolean; featured: boolean;
@@ -16,6 +26,14 @@ export type Item = ItemAttributes & {
revisions: Revision[]; revisions: Revision[];
}; };
export type Blip = Item & {
quadrantPosition: number
ringPosition: number
colour: string
txtColour: string
coordinates: Point
}
export type Revision = ItemAttributes & { export type Revision = ItemAttributes & {
body: string; body: string;
fileName: string; fileName: string;
@@ -26,6 +44,13 @@ export type Quadrant = {
[name: string]: Item[]; [name: string]: Item[];
}; };
export type QuadrantConfig = {
colour: string,
txtColour: string,
position: number,
description: string
}
export type Radar = { export type Radar = {
items: Item[]; items: Item[];
releases: string[]; releases: string[];
@@ -40,6 +65,11 @@ export const featuredOnly = (items: Item[]) =>
export const nonFeaturedOnly = (items: Item[]) => export const nonFeaturedOnly = (items: Item[]) =>
items.filter((item) => !item.featured); items.filter((item) => !item.featured);
export type Point = {
x: number,
y: number
}
export const groupByQuadrants = (items: Item[]): Group => export const groupByQuadrants = (items: Item[]): Group =>
items.reduce( items.reduce(
(quadrants, item: Item) => ({ (quadrants, item: Item) => ({

View File

@@ -30,4 +30,25 @@
&--close { &--close {
background-image: url("../../icons/close.svg"); background-image: url("../../icons/close.svg");
} }
&--blip_new {
background-image: url('../../icons/blip_new.svg');
width: 18px;
height: 18px;
background-size: 18px;
}
&--blip_changed {
background-image: url('../../icons/blip_changed.svg');
width: 18px;
height: 18px;
background-size: 18px;
}
&--blip_default {
background-image: url('../../icons/blip_default.svg');
width: 18px;
height: 18px;
background-size: 18px;
}
} }

520
yarn.lock
View File

@@ -1786,6 +1786,216 @@
dependencies: dependencies:
"@babel/types" "^7.3.0" "@babel/types" "^7.3.0"
"@types/d3-array@*":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.2.tgz#71c35bca8366a40d1b8fce9279afa4a77fb0065d"
integrity sha512-5mjGjz6XOXKOCdTajXTZ/pMsg236RdiwKPrRPWAEf/2S/+PzwY+LLYShUpeysWaMvsdS7LArh6GdUefoxpchsQ==
"@types/d3-axis@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-3.0.1.tgz#6afc20744fa5cc0cbc3e2bd367b140a79ed3e7a8"
integrity sha512-zji/iIbdd49g9WN0aIsGcwcTBUkgLsCSwB+uH+LPVDAiKWENMtI3cJEWt+7/YYwelMoZmbBfzA3qCdrZ2XFNnw==
dependencies:
"@types/d3-selection" "*"
"@types/d3-brush@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-3.0.1.tgz#ae5f17ce391935ca88b29000e60ee20452c6357c"
integrity sha512-B532DozsiTuQMHu2YChdZU0qsFJSio3Q6jmBYGYNp3gMDzBmuFFgPt9qKA4VYuLZMp4qc6eX7IUFUEsvHiXZAw==
dependencies:
"@types/d3-selection" "*"
"@types/d3-chord@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-3.0.1.tgz#54c8856c19c8e4ab36a53f73ba737de4768ad248"
integrity sha512-eQfcxIHrg7V++W8Qxn6QkqBNBokyhdWSAS73AbkbMzvLQmVVBviknoz2SRS/ZJdIOmhcmmdCRE/NFOm28Z1AMw==
"@types/d3-color@*":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-3.0.2.tgz#53f2d6325f66ee79afd707c05ac849e8ae0edbb0"
integrity sha512-WVx6zBiz4sWlboCy7TCgjeyHpNjMsoF36yaagny1uXfbadc9f+5BeBf7U+lRmQqY3EHbGQpP8UdW8AC+cywSwQ==
"@types/d3-contour@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-3.0.1.tgz#9ff4e2fd2a3910de9c5097270a7da8a6ef240017"
integrity sha512-C3zfBrhHZvrpAAK3YXqLWVAGo87A4SvJ83Q/zVJ8rFWJdKejUnDYaWZPkA8K84kb2vDA/g90LTQAz7etXcgoQQ==
dependencies:
"@types/d3-array" "*"
"@types/geojson" "*"
"@types/d3-delaunay@*":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-6.0.0.tgz#c09953ac7e5460997f693d2d7bf3522e0d4a88e6"
integrity sha512-iGm7ZaGLq11RK3e69VeMM6Oqj2SjKUB9Qhcyd1zIcqn2uE8w9GFB445yCY46NOQO3ByaNyktX1DK+Etz7ZaX+w==
"@types/d3-dispatch@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.1.tgz#a1b18ae5fa055a6734cb3bd3cbc6260ef19676e3"
integrity sha512-NhxMn3bAkqhjoxabVJWKryhnZXXYYVQxaBnbANu0O94+O/nX9qSjrA1P1jbAQJxJf+VC72TxDX/YJcKue5bRqw==
"@types/d3-drag@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-3.0.1.tgz#fb1e3d5cceeee4d913caa59dedf55c94cb66e80f"
integrity sha512-o1Va7bLwwk6h03+nSM8dpaGEYnoIG19P0lKqlic8Un36ymh9NSkNFX1yiXMKNMx8rJ0Kfnn2eovuFaL6Jvj0zA==
dependencies:
"@types/d3-selection" "*"
"@types/d3-dsv@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-3.0.0.tgz#f3c61fb117bd493ec0e814856feb804a14cfc311"
integrity sha512-o0/7RlMl9p5n6FQDptuJVMxDf/7EDEv2SYEO/CwdG2tr1hTfUVi0Iavkk2ax+VpaQ/1jVhpnj5rq1nj8vwhn2A==
"@types/d3-ease@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-3.0.0.tgz#c29926f8b596f9dadaeca062a32a45365681eae0"
integrity sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==
"@types/d3-fetch@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-3.0.1.tgz#f9fa88b81aa2eea5814f11aec82ecfddbd0b8fe0"
integrity sha512-toZJNOwrOIqz7Oh6Q7l2zkaNfXkfR7mFSJvGvlD/Ciq/+SQ39d5gynHJZ/0fjt83ec3WL7+u3ssqIijQtBISsw==
dependencies:
"@types/d3-dsv" "*"
"@types/d3-force@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-3.0.3.tgz#76cb20d04ae798afede1ea6e41750763ff5a9c82"
integrity sha512-z8GteGVfkWJMKsx6hwC3SiTSLspL98VNpmvLpEFJQpZPq6xpA1I8HNBDNSpukfK0Vb0l64zGFhzunLgEAcBWSA==
"@types/d3-format@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-3.0.1.tgz#194f1317a499edd7e58766f96735bdc0216bb89d"
integrity sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg==
"@types/d3-geo@*":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-3.0.2.tgz#e7ec5f484c159b2c404c42d260e6d99d99f45d9a"
integrity sha512-DbqK7MLYA8LpyHQfv6Klz0426bQEf7bRTvhMy44sNGVyZoWn//B0c+Qbeg8Osi2Obdc9BLLXYAKpyWege2/7LQ==
dependencies:
"@types/geojson" "*"
"@types/d3-hierarchy@*":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.0.2.tgz#ca63f2f4da15b8f129c5b7dffd71d904cba6aca2"
integrity sha512-+krnrWOZ+aQB6v+E+jEkmkAx9HvsNAD+1LCD0vlBY3t+HwjKnsBFbpVLx6WWzDzCIuiTWdAxXMEnGnVXpB09qQ==
"@types/d3-interpolate@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz#e7d17fa4a5830ad56fe22ce3b4fac8541a9572dc"
integrity sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==
dependencies:
"@types/d3-color" "*"
"@types/d3-path@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-3.0.0.tgz#939e3a784ae4f80b1fde8098b91af1776ff1312b"
integrity sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==
"@types/d3-polygon@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-3.0.0.tgz#5200a3fa793d7736fa104285fa19b0dbc2424b93"
integrity sha512-D49z4DyzTKXM0sGKVqiTDTYr+DHg/uxsiWDAkNrwXYuiZVd9o9wXZIo+YsHkifOiyBkmSWlEngHCQme54/hnHw==
"@types/d3-quadtree@*":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-3.0.2.tgz#433112a178eb7df123aab2ce11c67f51cafe8ff5"
integrity sha512-QNcK8Jguvc8lU+4OfeNx+qnVy7c0VrDJ+CCVFS9srBo2GL9Y18CnIxBdTF3v38flrGy5s1YggcoAiu6s4fLQIw==
"@types/d3-random@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.1.tgz#5c8d42b36cd4c80b92e5626a252f994ca6bfc953"
integrity sha512-IIE6YTekGczpLYo/HehAy3JGF1ty7+usI97LqraNa8IiDur+L44d0VOjAvFQWJVdZOJHukUJw+ZdZBlgeUsHOQ==
"@types/d3-scale-chromatic@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#103124777e8cdec85b20b51fd3397c682ee1e954"
integrity sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==
"@types/d3-scale@*":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.2.tgz#41be241126af4630524ead9cb1008ab2f0f26e69"
integrity sha512-Yk4htunhPAwN0XGlIwArRomOjdoBFXC3+kCxK2Ubg7I9shQlVSJy/pG/Ht5ASN+gdMIalpk8TJ5xV74jFsetLA==
dependencies:
"@types/d3-time" "*"
"@types/d3-selection@*":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.2.tgz#23e48a285b24063630bbe312cc0cfe2276de4a59"
integrity sha512-d29EDd0iUBrRoKhPndhDY6U/PYxOWqgIZwKTooy2UkBfU7TNZNpRho0yLWPxlatQrFWk2mnTu71IZQ4+LRgKlQ==
"@types/d3-shape@*":
version "3.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-3.0.2.tgz#4b1ca4ddaac294e76b712429726d40365cd1e8ca"
integrity sha512-5+ButCmIfNX8id5seZ7jKj3igdcxx+S9IDBiT35fQGTLZUfkFgTv+oBH34xgeoWDKpWcMITSzBILWQtBoN5Piw==
dependencies:
"@types/d3-path" "*"
"@types/d3-time-format@*":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-4.0.0.tgz#ee7b6e798f8deb2d9640675f8811d0253aaa1946"
integrity sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw==
"@types/d3-time@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.0.tgz#e1ac0f3e9e195135361fa1a1d62f795d87e6e819"
integrity sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==
"@types/d3-timer@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-3.0.0.tgz#e2505f1c21ec08bda8915238e397fb71d2fc54ce"
integrity sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==
"@types/d3-transition@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-3.0.1.tgz#c9a96125567173d6163a6985b874f79154f4cc3d"
integrity sha512-Sv4qEI9uq3bnZwlOANvYK853zvpdKEm1yz9rcc8ZTsxvRklcs9Fx4YFuGA3gXoQN/c/1T6QkVNjhaRO/cWj94g==
dependencies:
"@types/d3-selection" "*"
"@types/d3-zoom@*":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-3.0.1.tgz#4bfc7e29625c4f79df38e2c36de52ec3e9faf826"
integrity sha512-7s5L9TjfqIYQmQQEUcpMAcBOahem7TRoSO/+Gkz02GbMVuULiZzjF2BOdw291dbO2aNon4m2OdFsRGaCq2caLQ==
dependencies:
"@types/d3-interpolate" "*"
"@types/d3-selection" "*"
"@types/d3@^7.1.0":
version "7.1.0"
resolved "https://registry.yarnpkg.com/@types/d3/-/d3-7.1.0.tgz#8f32a7e7f434d8f920c8b1ebdfed55e18c033720"
integrity sha512-gYWvgeGjEl+zmF8c+U1RNIKqe7sfQwIXeLXO5Os72TjDjCEtgpvGBvZ8dXlAuSS1m6B90Y1Uo6Bm36OGR/OtCA==
dependencies:
"@types/d3-array" "*"
"@types/d3-axis" "*"
"@types/d3-brush" "*"
"@types/d3-chord" "*"
"@types/d3-color" "*"
"@types/d3-contour" "*"
"@types/d3-delaunay" "*"
"@types/d3-dispatch" "*"
"@types/d3-drag" "*"
"@types/d3-dsv" "*"
"@types/d3-ease" "*"
"@types/d3-fetch" "*"
"@types/d3-force" "*"
"@types/d3-format" "*"
"@types/d3-geo" "*"
"@types/d3-hierarchy" "*"
"@types/d3-interpolate" "*"
"@types/d3-path" "*"
"@types/d3-polygon" "*"
"@types/d3-quadtree" "*"
"@types/d3-random" "*"
"@types/d3-scale" "*"
"@types/d3-scale-chromatic" "*"
"@types/d3-selection" "*"
"@types/d3-shape" "*"
"@types/d3-time" "*"
"@types/d3-time-format" "*"
"@types/d3-timer" "*"
"@types/d3-transition" "*"
"@types/d3-zoom" "*"
"@types/eslint@^7.2.6": "@types/eslint@^7.2.6":
version "7.28.0" version "7.28.0"
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.28.0.tgz#7e41f2481d301c68e14f483fe10b017753ce8d5a" resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.28.0.tgz#7e41f2481d301c68e14f483fe10b017753ce8d5a"
@@ -1811,6 +2021,11 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/geojson@*":
version "7946.0.8"
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca"
integrity sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==
"@types/glob@^7.1.1": "@types/glob@^7.1.1":
version "7.1.4" version "7.1.4"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.4.tgz#ea59e21d2ee5c517914cb4bc8e4153b99e566672" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.4.tgz#ea59e21d2ee5c517914cb4bc8e4153b99e566672"
@@ -1937,6 +2152,13 @@
"@types/history" "*" "@types/history" "*"
"@types/react" "*" "@types/react" "*"
"@types/react-tooltip@^4.2.4":
version "4.2.4"
resolved "https://registry.yarnpkg.com/@types/react-tooltip/-/react-tooltip-4.2.4.tgz#d0acad2a3061806e10aab91dd26a95a77fd35125"
integrity sha512-UzjzmgY/VH3Str6DcAGTLMA1mVVhGOyARNTANExrirtp+JgxhaIOVDxq4TIRmpSi4voLv+w4HA9CC5GvhhCA0A==
dependencies:
react-tooltip "*"
"@types/react@*", "@types/react@^17.0.24": "@types/react@*", "@types/react@^17.0.24":
version "17.0.27" version "17.0.27"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.27.tgz#6498ed9b3ad117e818deb5525fa1946c09f2e0e6" resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.27.tgz#6498ed9b3ad117e818deb5525fa1946c09f2e0e6"
@@ -3531,6 +3753,11 @@ combined-stream@^1.0.8:
dependencies: dependencies:
delayed-stream "~1.0.0" delayed-stream "~1.0.0"
commander@7, commander@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
commander@^2.20.0: commander@^2.20.0:
version "2.20.3" version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@@ -3541,11 +3768,6 @@ commander@^4.1.1:
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
commander@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
common-tags@^1.8.0: common-tags@^1.8.0:
version "1.8.0" version "1.8.0"
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
@@ -4060,6 +4282,250 @@ cyclist@^1.0.1:
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=
"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3:
version "3.1.1"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.1.1.tgz#7797eb53ead6b9083c75a45a681e93fc41bc468c"
integrity sha512-33qQ+ZoZlli19IFiQx4QEpf2CBEayMRzhlisJHSCsSUbDXv6ZishqS1x7uFVClKG4Wr7rZVHvaAttoLow6GqdQ==
dependencies:
internmap "1 - 2"
d3-axis@3:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322"
integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==
d3-brush@3:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c"
integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==
dependencies:
d3-dispatch "1 - 3"
d3-drag "2 - 3"
d3-interpolate "1 - 3"
d3-selection "3"
d3-transition "3"
d3-chord@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966"
integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==
dependencies:
d3-path "1 - 3"
"d3-color@1 - 3", d3-color@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.0.1.tgz#03316e595955d1fcd39d9f3610ad41bb90194d0a"
integrity sha512-6/SlHkDOBLyQSJ1j1Ghs82OIUXpKWlR0hCsw0XrLSQhuUPuCSmLQ1QPH98vpnQxMUQM2/gfAkUEWsupVpd9JGw==
d3-contour@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-3.0.1.tgz#2c64255d43059599cd0dba8fe4cc3d51ccdd9bbd"
integrity sha512-0Oc4D0KyhwhM7ZL0RMnfGycLN7hxHB8CMmwZ3+H26PWAG0ozNuYG5hXSDNgmP1SgJkQMrlG6cP20HoaSbvcJTQ==
dependencies:
d3-array "2 - 3"
d3-delaunay@6:
version "6.0.2"
resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.2.tgz#7fd3717ad0eade2fc9939f4260acfb503f984e92"
integrity sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==
dependencies:
delaunator "5"
"d3-dispatch@1 - 3", d3-dispatch@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e"
integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
"d3-drag@2 - 3", d3-drag@3:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba"
integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==
dependencies:
d3-dispatch "1 - 3"
d3-selection "3"
"d3-dsv@1 - 3", d3-dsv@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73"
integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==
dependencies:
commander "7"
iconv-lite "0.6"
rw "1"
"d3-ease@1 - 3", d3-ease@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4"
integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==
d3-fetch@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22"
integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==
dependencies:
d3-dsv "1 - 3"
d3-force@3:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4"
integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==
dependencies:
d3-dispatch "1 - 3"
d3-quadtree "1 - 3"
d3-timer "1 - 3"
"d3-format@1 - 3", d3-format@3:
version "3.1.0"
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641"
integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==
d3-geo@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.0.1.tgz#4f92362fd8685d93e3b1fae0fd97dc8980b1ed7e"
integrity sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==
dependencies:
d3-array "2.5.0 - 3"
d3-hierarchy@3:
version "3.1.1"
resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.1.tgz#9cbb0ffd2375137a351e6cfeed344a06d4ff4597"
integrity sha512-LtAIu54UctRmhGKllleflmHalttH3zkfSi4NlKrTAoFKjC+AFBJohsCAdgCBYQwH0F8hIOGY89X1pPqAchlMkA==
"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
dependencies:
d3-color "1 - 3"
"d3-path@1 - 3", d3-path@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.0.1.tgz#f09dec0aaffd770b7995f1a399152bf93052321e"
integrity sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==
d3-polygon@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398"
integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==
"d3-quadtree@1 - 3", d3-quadtree@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f"
integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==
d3-random@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4"
integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==
d3-scale-chromatic@3:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz#15b4ceb8ca2bb0dcb6d1a641ee03d59c3b62376a"
integrity sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==
dependencies:
d3-color "1 - 3"
d3-interpolate "1 - 3"
d3-scale@4:
version "4.0.2"
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396"
integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==
dependencies:
d3-array "2.10.0 - 3"
d3-format "1 - 3"
d3-interpolate "1.2.0 - 3"
d3-time "2.1.1 - 3"
d3-time-format "2 - 4"
"d3-selection@2 - 3", d3-selection@3:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31"
integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==
d3-shape@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.0.1.tgz#9ccdfb28fd9b0d12f2d8aec234cd5c4a9ea27931"
integrity sha512-HNZNEQoDhuCrDWEc/BMbF/hKtzMZVoe64TvisFLDp2Iyj0UShB/E6/lBsLlJTfBMbYgftHj90cXJ0SEitlE6Xw==
dependencies:
d3-path "1 - 3"
"d3-time-format@2 - 4", d3-time-format@4:
version "4.1.0"
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a"
integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==
dependencies:
d3-time "1 - 3"
"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.0.0.tgz#65972cb98ae2d4954ef5c932e8704061335d4975"
integrity sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==
dependencies:
d3-array "2 - 3"
"d3-timer@1 - 3", d3-timer@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0"
integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==
"d3-transition@2 - 3", d3-transition@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f"
integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==
dependencies:
d3-color "1 - 3"
d3-dispatch "1 - 3"
d3-ease "1 - 3"
d3-interpolate "1 - 3"
d3-timer "1 - 3"
d3-zoom@3:
version "3.0.0"
resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3"
integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==
dependencies:
d3-dispatch "1 - 3"
d3-drag "2 - 3"
d3-interpolate "1 - 3"
d3-selection "2 - 3"
d3-transition "2 - 3"
d3@^7.2.1:
version "7.2.1"
resolved "https://registry.yarnpkg.com/d3/-/d3-7.2.1.tgz#97eafaa6fc8cd7c564c3ace1e6678cbecf63f3ea"
integrity sha512-E/5sP0aeK6YPXI/+4QlefvBFgmcyR2jYftId0PrYWv4Y/gW3c3thp1XG4rQzF0eUwV9tR1x05X5eWuJ6rQXvew==
dependencies:
d3-array "3"
d3-axis "3"
d3-brush "3"
d3-chord "3"
d3-color "3"
d3-contour "3"
d3-delaunay "6"
d3-dispatch "3"
d3-drag "3"
d3-dsv "3"
d3-ease "3"
d3-fetch "3"
d3-force "3"
d3-format "3"
d3-geo "3"
d3-hierarchy "3"
d3-interpolate "3"
d3-path "3"
d3-polygon "3"
d3-quadtree "3"
d3-random "3"
d3-scale "4"
d3-scale-chromatic "3"
d3-selection "3"
d3-shape "3"
d3-time "3"
d3-time-format "4"
d3-timer "3"
d3-transition "3"
d3-zoom "3"
d@1, d@^1.0.1: d@1, d@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
@@ -4195,6 +4661,13 @@ del@^4.1.1:
pify "^4.0.1" pify "^4.0.1"
rimraf "^2.6.3" rimraf "^2.6.3"
delaunator@5:
version "5.0.0"
resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b"
integrity sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==
dependencies:
robust-predicates "^3.0.0"
delayed-stream@~1.0.0: delayed-stream@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -5883,6 +6356,13 @@ iconv-lite@0.4.24:
dependencies: dependencies:
safer-buffer ">= 2.1.2 < 3" safer-buffer ">= 2.1.2 < 3"
iconv-lite@0.6:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
dependencies:
safer-buffer ">= 2.1.2 < 3.0.0"
icss-utils@^4.0.0, icss-utils@^4.1.1: icss-utils@^4.0.0, icss-utils@^4.1.1:
version "4.1.1" version "4.1.1"
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467"
@@ -6033,6 +6513,11 @@ internal-slot@^1.0.3:
has "^1.0.3" has "^1.0.3"
side-channel "^1.0.4" side-channel "^1.0.4"
"internmap@1 - 2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009"
integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==
ip-regex@^2.1.0: ip-regex@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
@@ -9576,6 +10061,14 @@ react-scripts@4.0.3:
optionalDependencies: optionalDependencies:
fsevents "^2.1.3" fsevents "^2.1.3"
react-tooltip@*, react-tooltip@^4.2.21:
version "4.2.21"
resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.2.21.tgz#840123ed86cf33d50ddde8ec8813b2960bfded7f"
integrity sha512-zSLprMymBDowknr0KVDiJ05IjZn9mQhhg4PRsqln0OZtURAJ1snt1xi5daZfagsh6vfsziZrc9pErPTDY1ACig==
dependencies:
prop-types "^15.7.2"
uuid "^7.0.3"
react@^17.0.2: react@^17.0.2:
version "17.0.2" version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
@@ -9950,6 +10443,11 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0" hash-base "^3.0.0"
inherits "^2.0.1" inherits "^2.0.1"
robust-predicates@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.1.tgz#ecde075044f7f30118682bd9fb3f123109577f9a"
integrity sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==
rollup-plugin-babel@^4.3.3: rollup-plugin-babel@^4.3.3:
version "4.4.0" version "4.4.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz#d15bd259466a9d1accbdb2fe2fff17c52d030acb" resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz#d15bd259466a9d1accbdb2fe2fff17c52d030acb"
@@ -10004,6 +10502,11 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies: dependencies:
aproba "^1.1.1" aproba "^1.1.1"
rw@1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=
rxjs@^6.6.7: rxjs@^6.6.7:
version "6.6.7" version "6.6.7"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
@@ -10028,7 +10531,7 @@ safe-regex@^1.1.0:
dependencies: dependencies:
ret "~0.1.10" ret "~0.1.10"
"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0: "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
@@ -11404,6 +11907,11 @@ uuid@^3.3.2, uuid@^3.4.0:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
uuid@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==
uuid@^8.3.0: uuid@^8.3.0:
version "8.3.2" version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"