@spinnaker/kayenta 0.0.0-2025.1-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +9 -0
- package/.eslintrc.js +1 -0
- package/.huskyrc +5 -0
- package/.lintstagedrc.json +4 -0
- package/.prettierignore +4 -0
- package/.prettierrc.js +1 -0
- package/LICENSE.txt +203 -0
- package/README.md +81 -0
- package/__mocks__/styleMock.js +1 -0
- package/__mocks__/version.json +4 -0
- package/babel.config.js +3 -0
- package/build.gradle +67 -0
- package/build_scripts/checkLicenses.js +79 -0
- package/gradle.properties +0 -0
- package/jest.config.js +204 -0
- package/jest.setup.js +5 -0
- package/package.json +166 -0
- package/rollup-plugin-angularjs-template-loader.js +82 -0
- package/rollup.config.js +30 -0
- package/src/index.ts +2 -0
- package/src/kayenta/actions/creators.ts +163 -0
- package/src/kayenta/actions/index.ts +98 -0
- package/src/kayenta/canary.dataSource.bridge.ts +53 -0
- package/src/kayenta/canary.dataSource.stub.ts +64 -0
- package/src/kayenta/canary.help.ts +136 -0
- package/src/kayenta/canary.less +168 -0
- package/src/kayenta/canary.settings.ts +26 -0
- package/src/kayenta/canary.tsx +67 -0
- package/src/kayenta/components/canaryScore.component.less +77 -0
- package/src/kayenta/components/canaryScore.component.ts +12 -0
- package/src/kayenta/components/canaryScore.tsx +63 -0
- package/src/kayenta/components/canaryScores.component.ts +20 -0
- package/src/kayenta/components/canaryScores.less +22 -0
- package/src/kayenta/components/canaryScores.tsx +163 -0
- package/src/kayenta/components/loadStates.tsx +52 -0
- package/src/kayenta/domain/ICanaryConfig.ts +57 -0
- package/src/kayenta/domain/ICanaryConfigSummary.ts +7 -0
- package/src/kayenta/domain/ICanaryConfigUpdateResponse.ts +3 -0
- package/src/kayenta/domain/ICanaryExecutionStatusResult.ts +72 -0
- package/src/kayenta/domain/ICanaryJudgeResult.ts +51 -0
- package/src/kayenta/domain/ICanaryJudgeResultSummary.ts +5 -0
- package/src/kayenta/domain/ICanaryScoreThresholds.ts +4 -0
- package/src/kayenta/domain/IJudge.ts +5 -0
- package/src/kayenta/domain/IKayentaAccount.ts +14 -0
- package/src/kayenta/domain/IKayentaStageConfig.ts +58 -0
- package/src/kayenta/domain/IMetricSetPair.ts +17 -0
- package/src/kayenta/domain/IMetricsServiceMetadata.ts +2 -0
- package/src/kayenta/domain/ISetupCanaryStage.ts +11 -0
- package/src/kayenta/domain/MetricClassificationLabel.ts +8 -0
- package/src/kayenta/domain/ScoreClassificationLabel.ts +7 -0
- package/src/kayenta/domain/index.ts +15 -0
- package/src/kayenta/edit/changeMetricGroupModal.tsx +107 -0
- package/src/kayenta/edit/configDetail.tsx +31 -0
- package/src/kayenta/edit/configDetailActionButtons.tsx +24 -0
- package/src/kayenta/edit/configDetailHeader.tsx +104 -0
- package/src/kayenta/edit/configDetailLoadStates.tsx +36 -0
- package/src/kayenta/edit/configDetailLoader.tsx +60 -0
- package/src/kayenta/edit/configJson.less +42 -0
- package/src/kayenta/edit/configJsonModal.tsx +158 -0
- package/src/kayenta/edit/configList.less +7 -0
- package/src/kayenta/edit/configList.tsx +57 -0
- package/src/kayenta/edit/copyConfigButton.tsx +34 -0
- package/src/kayenta/edit/createConfigButton.tsx +34 -0
- package/src/kayenta/edit/deleteModal.tsx +87 -0
- package/src/kayenta/edit/edit.tsx +24 -0
- package/src/kayenta/edit/editMetricEffectSizes.tsx +186 -0
- package/src/kayenta/edit/editMetricModal.less +9 -0
- package/src/kayenta/edit/editMetricModal.spec.tsx +129 -0
- package/src/kayenta/edit/editMetricModal.tsx +294 -0
- package/src/kayenta/edit/editMetricValidation.spec.ts +63 -0
- package/src/kayenta/edit/editMetricValidation.ts +50 -0
- package/src/kayenta/edit/filterTemplateSelector.less +15 -0
- package/src/kayenta/edit/filterTemplateSelector.spec.tsx +106 -0
- package/src/kayenta/edit/filterTemplateSelector.tsx +194 -0
- package/src/kayenta/edit/filterTemplatesValidation.spec.ts +108 -0
- package/src/kayenta/edit/filterTemplatesValidation.ts +95 -0
- package/src/kayenta/edit/footer.less +30 -0
- package/src/kayenta/edit/footer.tsx +12 -0
- package/src/kayenta/edit/groupName.tsx +80 -0
- package/src/kayenta/edit/groupTabs.tsx +106 -0
- package/src/kayenta/edit/groupWeight.tsx +80 -0
- package/src/kayenta/edit/groupWeights.tsx +38 -0
- package/src/kayenta/edit/inlineTemplateEditor.spec.tsx +42 -0
- package/src/kayenta/edit/inlineTemplateEditor.tsx +61 -0
- package/src/kayenta/edit/judgeSelect.tsx +82 -0
- package/src/kayenta/edit/metricConfigurerDelegator.tsx +30 -0
- package/src/kayenta/edit/metricList.less +21 -0
- package/src/kayenta/edit/metricList.tsx +215 -0
- package/src/kayenta/edit/metricStoreSelector.tsx +66 -0
- package/src/kayenta/edit/nameAndDescription.tsx +90 -0
- package/src/kayenta/edit/openConfigJsonModalButton.tsx +33 -0
- package/src/kayenta/edit/openDeleteModalButton.tsx +50 -0
- package/src/kayenta/edit/ownedBy.tsx +34 -0
- package/src/kayenta/edit/save.tsx +19 -0
- package/src/kayenta/edit/saveConfigButton.tsx +65 -0
- package/src/kayenta/edit/saveConfigError.tsx +59 -0
- package/src/kayenta/edit/scoring.tsx +35 -0
- package/src/kayenta/edit/selectConfig.tsx +10 -0
- package/src/kayenta/edit/validationErrors.tsx +39 -0
- package/src/kayenta/index.ts +6 -0
- package/src/kayenta/layout/addNewButton.tsx +20 -0
- package/src/kayenta/layout/centeredDetail.tsx +13 -0
- package/src/kayenta/layout/deleteButton.tsx +11 -0
- package/src/kayenta/layout/disableable.tsx +87 -0
- package/src/kayenta/layout/formList.tsx +26 -0
- package/src/kayenta/layout/formRow.tsx +36 -0
- package/src/kayenta/layout/formattedDate.tsx +14 -0
- package/src/kayenta/layout/index.ts +2 -0
- package/src/kayenta/layout/keyValueList.less +20 -0
- package/src/kayenta/layout/keyValueList.tsx +114 -0
- package/src/kayenta/layout/list.less +9 -0
- package/src/kayenta/layout/list.spec.tsx +83 -0
- package/src/kayenta/layout/list.tsx +73 -0
- package/src/kayenta/layout/listDetail.tsx +33 -0
- package/src/kayenta/layout/radioChoice.tsx +29 -0
- package/src/kayenta/layout/styleguide.tsx +16 -0
- package/src/kayenta/layout/table/index.ts +5 -0
- package/src/kayenta/layout/table/nativeTable.tsx +51 -0
- package/src/kayenta/layout/table/nativeTableHeader.tsx +26 -0
- package/src/kayenta/layout/table/table.tsx +56 -0
- package/src/kayenta/layout/table/tableColumn.ts +7 -0
- package/src/kayenta/layout/table/tableHeader.tsx +23 -0
- package/src/kayenta/layout/tabs.tsx +26 -0
- package/src/kayenta/layout/titledSection.less +16 -0
- package/src/kayenta/layout/titledSection.tsx +20 -0
- package/src/kayenta/layout/titledSubsection.less +11 -0
- package/src/kayenta/layout/titledSubsection.tsx +22 -0
- package/src/kayenta/manualAnalysis/ManualAnalysisModal.tsx +716 -0
- package/src/kayenta/metricStore/atlas/atlasMetricConfigurer.tsx +130 -0
- package/src/kayenta/metricStore/atlas/index.ts +8 -0
- package/src/kayenta/metricStore/datadog/domain/IDatadogMetricDescriptor.ts +5 -0
- package/src/kayenta/metricStore/datadog/index.ts +9 -0
- package/src/kayenta/metricStore/datadog/metricConfigurer.tsx +90 -0
- package/src/kayenta/metricStore/datadog/metricTypeSelector.spec.tsx +59 -0
- package/src/kayenta/metricStore/datadog/metricTypeSelector.tsx +73 -0
- package/src/kayenta/metricStore/graphite/domain/IGraphiteMetricDescriptor.ts +5 -0
- package/src/kayenta/metricStore/graphite/index.ts +8 -0
- package/src/kayenta/metricStore/graphite/metricConfigurer.tsx +54 -0
- package/src/kayenta/metricStore/graphite/metricTypeSelector.tsx +80 -0
- package/src/kayenta/metricStore/graphite/typeahead.less +3 -0
- package/src/kayenta/metricStore/index.ts +8 -0
- package/src/kayenta/metricStore/metricStoreConfig.service.ts +12 -0
- package/src/kayenta/metricStore/newrelic/domain/INewRelicMetricDescriptor.ts +5 -0
- package/src/kayenta/metricStore/newrelic/index.ts +8 -0
- package/src/kayenta/metricStore/newrelic/metricConfigurer.tsx +58 -0
- package/src/kayenta/metricStore/prometheus/domain/IPrometheusCanaryMetricSetQueryConfig.ts +14 -0
- package/src/kayenta/metricStore/prometheus/domain/IPrometheusMetricDescriptor.ts +5 -0
- package/src/kayenta/metricStore/prometheus/index.ts +12 -0
- package/src/kayenta/metricStore/prometheus/metricConfigurer.tsx +157 -0
- package/src/kayenta/metricStore/prometheus/metricTypeSelector.less +5 -0
- package/src/kayenta/metricStore/prometheus/metricTypeSelector.spec.tsx +62 -0
- package/src/kayenta/metricStore/prometheus/metricTypeSelector.tsx +144 -0
- package/src/kayenta/metricStore/prometheus/queryTypeSelectors.spec.ts +61 -0
- package/src/kayenta/metricStore/prometheus/queryTypeSelectors.ts +38 -0
- package/src/kayenta/metricStore/signalfx/domain/ISignalFxCanaryMetricSetQueryConfig.ts +7 -0
- package/src/kayenta/metricStore/signalfx/index.ts +8 -0
- package/src/kayenta/metricStore/signalfx/metricConfigurer.less +10 -0
- package/src/kayenta/metricStore/signalfx/metricConfigurer.tsx +187 -0
- package/src/kayenta/metricStore/stackdriver/domain/IStackdriverCanaryMetricSetQueryConfig.ts +9 -0
- package/src/kayenta/metricStore/stackdriver/domain/IStackdriverMetricDescriptor.ts +17 -0
- package/src/kayenta/metricStore/stackdriver/index.ts +12 -0
- package/src/kayenta/metricStore/stackdriver/metricConfigurer.tsx +144 -0
- package/src/kayenta/metricStore/stackdriver/metricTypeSelector.spec.tsx +92 -0
- package/src/kayenta/metricStore/stackdriver/metricTypeSelector.tsx +113 -0
- package/src/kayenta/middleware/actionInterceptor.ts +29 -0
- package/src/kayenta/middleware/asyncDispatch.ts +37 -0
- package/src/kayenta/middleware/epics.ts +211 -0
- package/src/kayenta/middleware/index.ts +3 -0
- package/src/kayenta/navigation/canary.states.stub.ts +28 -0
- package/src/kayenta/navigation/canary.states.ts +182 -0
- package/src/kayenta/reducers/app.ts +56 -0
- package/src/kayenta/reducers/asyncRequest.ts +5 -0
- package/src/kayenta/reducers/data.ts +169 -0
- package/src/kayenta/reducers/editingTemplate.ts +54 -0
- package/src/kayenta/reducers/group.ts +82 -0
- package/src/kayenta/reducers/index.ts +245 -0
- package/src/kayenta/reducers/prometheusMetricConfig.spec.ts +33 -0
- package/src/kayenta/reducers/prometheusMetricConfig.ts +56 -0
- package/src/kayenta/reducers/selectedConfig.spec.ts +190 -0
- package/src/kayenta/reducers/selectedConfig.ts +566 -0
- package/src/kayenta/reducers/selectedRun.ts +101 -0
- package/src/kayenta/reducers/signalFxMetricConfig.ts +36 -0
- package/src/kayenta/reducers/stackdriverMetricConfig.spec.ts +33 -0
- package/src/kayenta/reducers/stackdriverMetricConfig.ts +41 -0
- package/src/kayenta/reducers/templates.spec.ts +192 -0
- package/src/kayenta/reducers/validators.ts +118 -0
- package/src/kayenta/report/detail/allMetricResultsHeader.tsx +32 -0
- package/src/kayenta/report/detail/clickableHeader.tsx +21 -0
- package/src/kayenta/report/detail/colors.ts +47 -0
- package/src/kayenta/report/detail/detail.less +16 -0
- package/src/kayenta/report/detail/detail.tsx +48 -0
- package/src/kayenta/report/detail/detailLoader.tsx +55 -0
- package/src/kayenta/report/detail/graph/graph.tsx +37 -0
- package/src/kayenta/report/detail/graph/metricSetPairGraph.service.ts +35 -0
- package/src/kayenta/report/detail/graph/semiotic/boxplot.less +45 -0
- package/src/kayenta/report/detail/graph/semiotic/boxplot.tsx +283 -0
- package/src/kayenta/report/detail/graph/semiotic/chartHeader.tsx +19 -0
- package/src/kayenta/report/detail/graph/semiotic/chartLegend.less +26 -0
- package/src/kayenta/report/detail/graph/semiotic/chartLegend.tsx +42 -0
- package/src/kayenta/report/detail/graph/semiotic/circleIcon.tsx +16 -0
- package/src/kayenta/report/detail/graph/semiotic/config.less +5 -0
- package/src/kayenta/report/detail/graph/semiotic/config.ts +38 -0
- package/src/kayenta/report/detail/graph/semiotic/customAxisTickLabel.tsx +17 -0
- package/src/kayenta/report/detail/graph/semiotic/declarations/labella.d.ts +16 -0
- package/src/kayenta/report/detail/graph/semiotic/declarations/react-container-dimensions.d.ts +3 -0
- package/src/kayenta/report/detail/graph/semiotic/declarations/semiotic.d.ts +160 -0
- package/src/kayenta/report/detail/graph/semiotic/differenceArea.less +17 -0
- package/src/kayenta/report/detail/graph/semiotic/differenceArea.tsx +186 -0
- package/src/kayenta/report/detail/graph/semiotic/histogram.less +22 -0
- package/src/kayenta/report/detail/graph/semiotic/histogram.tsx +251 -0
- package/src/kayenta/report/detail/graph/semiotic/index.tsx +19 -0
- package/src/kayenta/report/detail/graph/semiotic/noValidDataSign.less +5 -0
- package/src/kayenta/report/detail/graph/semiotic/noValidDataSign.tsx +10 -0
- package/src/kayenta/report/detail/graph/semiotic/secondaryTSXAxis.less +6 -0
- package/src/kayenta/report/detail/graph/semiotic/secondaryTSXAxis.tsx +58 -0
- package/src/kayenta/report/detail/graph/semiotic/semiotic.service.ts +32 -0
- package/src/kayenta/report/detail/graph/semiotic/semioticGraph.less +53 -0
- package/src/kayenta/report/detail/graph/semiotic/semioticGraph.tsx +49 -0
- package/src/kayenta/report/detail/graph/semiotic/timeSeries.less +42 -0
- package/src/kayenta/report/detail/graph/semiotic/timeSeries.tsx +473 -0
- package/src/kayenta/report/detail/graph/semiotic/tooltip.tsx +55 -0
- package/src/kayenta/report/detail/graph/semiotic/utils.ts +90 -0
- package/src/kayenta/report/detail/graphTypeSelector.less +4 -0
- package/src/kayenta/report/detail/graphTypeSelector.tsx +50 -0
- package/src/kayenta/report/detail/groupScores.tsx +68 -0
- package/src/kayenta/report/detail/header.less +70 -0
- package/src/kayenta/report/detail/header.tsx +39 -0
- package/src/kayenta/report/detail/headerArrow.tsx +13 -0
- package/src/kayenta/report/detail/loadStates.tsx +31 -0
- package/src/kayenta/report/detail/metricResultActions.less +29 -0
- package/src/kayenta/report/detail/metricResultActions.tsx +87 -0
- package/src/kayenta/report/detail/metricResultClassification.tsx +22 -0
- package/src/kayenta/report/detail/metricResultDetail.tsx +20 -0
- package/src/kayenta/report/detail/metricResultDetailLayout.tsx +19 -0
- package/src/kayenta/report/detail/metricResultDeviation.tsx +25 -0
- package/src/kayenta/report/detail/metricResultStats.less +9 -0
- package/src/kayenta/report/detail/metricResultStats.tsx +120 -0
- package/src/kayenta/report/detail/metricResults.less +12 -0
- package/src/kayenta/report/detail/metricResults.tsx +52 -0
- package/src/kayenta/report/detail/metricResultsClassificationFilters.tsx +65 -0
- package/src/kayenta/report/detail/metricResultsColumns.tsx +27 -0
- package/src/kayenta/report/detail/metricResultsList.less +44 -0
- package/src/kayenta/report/detail/metricResultsList.tsx +120 -0
- package/src/kayenta/report/detail/metricSetPairLoadStates.tsx +22 -0
- package/src/kayenta/report/detail/multipleResultsTable.tsx +81 -0
- package/src/kayenta/report/detail/reportException.tsx +57 -0
- package/src/kayenta/report/detail/reportExplanation.less +12 -0
- package/src/kayenta/report/detail/reportExplanation.tsx +32 -0
- package/src/kayenta/report/detail/reportMetadata.tsx +167 -0
- package/src/kayenta/report/detail/reportScores.less +47 -0
- package/src/kayenta/report/detail/reportScores.tsx +80 -0
- package/src/kayenta/report/detail/score.tsx +33 -0
- package/src/kayenta/report/detail/sourceLinks.tsx +69 -0
- package/src/kayenta/report/list/configLink.tsx +32 -0
- package/src/kayenta/report/list/executionList.less +7 -0
- package/src/kayenta/report/list/loadStates.tsx +32 -0
- package/src/kayenta/report/list/pipelineLink.tsx +15 -0
- package/src/kayenta/report/list/reportLink.tsx +33 -0
- package/src/kayenta/report/list/table.tsx +309 -0
- package/src/kayenta/report/report.tsx +11 -0
- package/src/kayenta/selectors/filterTemplatesSelectors.ts +87 -0
- package/src/kayenta/selectors/index.ts +62 -0
- package/src/kayenta/service/canaryConfig.service.ts +122 -0
- package/src/kayenta/service/canaryRun.service.ts +60 -0
- package/src/kayenta/service/delegateFactory.ts +24 -0
- package/src/kayenta/service/metricsServiceMetadata.service.ts +9 -0
- package/src/kayenta/stages/kayentaStage/AnalysisType.spec.tsx +47 -0
- package/src/kayenta/stages/kayentaStage/AnalysisType.tsx +49 -0
- package/src/kayenta/stages/kayentaStage/CanaryExecutionLabel.tsx +26 -0
- package/src/kayenta/stages/kayentaStage/analysisType.component.ts +12 -0
- package/src/kayenta/stages/kayentaStage/canaryRunSummaries.component.ts +12 -0
- package/src/kayenta/stages/kayentaStage/canaryRunSummaries.less +5 -0
- package/src/kayenta/stages/kayentaStage/canaryRunSummaries.tsx +136 -0
- package/src/kayenta/stages/kayentaStage/forAnalysisType.component.ts +45 -0
- package/src/kayenta/stages/kayentaStage/kayentaStage.controller.ts +789 -0
- package/src/kayenta/stages/kayentaStage/kayentaStage.html +528 -0
- package/src/kayenta/stages/kayentaStage/kayentaStage.less +5 -0
- package/src/kayenta/stages/kayentaStage/kayentaStage.transformer.ts +179 -0
- package/src/kayenta/stages/kayentaStage/kayentaStage.ts +221 -0
- package/src/kayenta/stages/kayentaStage/kayentaStageConfigSection.component.ts +21 -0
- package/src/kayenta/stages/kayentaStage/kayentaStageExecutionDetails.controller.ts +88 -0
- package/src/kayenta/stages/kayentaStage/kayentaStageExecutionDetails.html +114 -0
- package/src/kayenta/stages/kayentaStage/kayentaStageExecutionDetails.less +6 -0
- package/src/kayenta/stages/kayentaStage/stageTypes.ts +5 -0
- package/src/kayenta/utils/duration.spec.ts +69 -0
- package/src/kayenta/utils/duration.ts +48 -0
- package/src/lazy.ts +29 -0
- package/src/stub.ts +60 -0
- package/tsconfig.json +11 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
.boxplot {
|
|
2
|
+
.tooltip-container {
|
|
3
|
+
.columns {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: row;
|
|
6
|
+
.column {
|
|
7
|
+
padding: 10px;
|
|
8
|
+
.header {
|
|
9
|
+
font-weight: 600;
|
|
10
|
+
padding-left: 0px;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.boxplot-annotation {
|
|
17
|
+
text {
|
|
18
|
+
fill: var(--color-text-primary);
|
|
19
|
+
font-size: 12px;
|
|
20
|
+
font-weight: 600;
|
|
21
|
+
}
|
|
22
|
+
.annotation-connector {
|
|
23
|
+
display: none;
|
|
24
|
+
}
|
|
25
|
+
.note-line {
|
|
26
|
+
display: none;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.boxplot-chart {
|
|
31
|
+
.boxplot-summary {
|
|
32
|
+
g {
|
|
33
|
+
opacity: 0.8;
|
|
34
|
+
}
|
|
35
|
+
g:nth-child(1),
|
|
36
|
+
g:nth-child(2),
|
|
37
|
+
g:nth-child(3) {
|
|
38
|
+
opacity: 0.3;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
g.pieces {
|
|
42
|
+
shape-rendering: geometricprecision;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { extent } from 'd3-array';
|
|
2
|
+
import { Force, Node } from 'labella';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import {
|
|
5
|
+
Annotation,
|
|
6
|
+
IAnnotationType,
|
|
7
|
+
IOrFrameHoverArgs,
|
|
8
|
+
IOrGroup,
|
|
9
|
+
IOrSummaryPiece,
|
|
10
|
+
ISemioticAnnotationArgs,
|
|
11
|
+
OrdinalFrame,
|
|
12
|
+
} from 'semiotic';
|
|
13
|
+
|
|
14
|
+
import ChartHeader from './chartHeader';
|
|
15
|
+
import ChartLegend from './chartLegend';
|
|
16
|
+
import CircleIcon from './circleIcon';
|
|
17
|
+
import { vizConfig } from './config';
|
|
18
|
+
import { IMargin, ISemioticChartProps, ITooltip } from './semiotic.service';
|
|
19
|
+
import Tooltip from './tooltip';
|
|
20
|
+
import * as utils from './utils';
|
|
21
|
+
|
|
22
|
+
import './boxplot.less';
|
|
23
|
+
|
|
24
|
+
interface IChartDataPoint {
|
|
25
|
+
value: number;
|
|
26
|
+
group: string;
|
|
27
|
+
color: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface IHoverData {
|
|
31
|
+
value: number;
|
|
32
|
+
label: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface IHoverDataGroup {
|
|
36
|
+
[group: string]: IHoverData[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
interface IAnnotationData {
|
|
40
|
+
group: string;
|
|
41
|
+
summaryKeys: string[];
|
|
42
|
+
type: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface IBoxPlotState {
|
|
46
|
+
tooltip: ITooltip;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default class BoxPlot extends React.Component<ISemioticChartProps, IBoxPlotState> {
|
|
50
|
+
public state: IBoxPlotState = {
|
|
51
|
+
tooltip: null,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
private margin: IMargin = {
|
|
55
|
+
top: 10,
|
|
56
|
+
bottom: 20,
|
|
57
|
+
left: 60,
|
|
58
|
+
right: 40,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
private decorateData = (dataPoints: number[], group: string): IChartDataPoint[] => {
|
|
62
|
+
return dataPoints.map((dp) => ({
|
|
63
|
+
group,
|
|
64
|
+
value: dp,
|
|
65
|
+
color: vizConfig.colors[group],
|
|
66
|
+
}));
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
private generateChartData = () => {
|
|
70
|
+
const { metricSetPair } = this.props;
|
|
71
|
+
const filterFunc = (v: IChartDataPoint) => typeof v.value === 'number';
|
|
72
|
+
const baselineInput = this.decorateData(metricSetPair.values.control, 'baseline');
|
|
73
|
+
const canaryInput = this.decorateData(metricSetPair.values.experiment, 'canary');
|
|
74
|
+
const chartData = baselineInput.concat(canaryInput).filter(filterFunc);
|
|
75
|
+
return chartData;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Generate tooltip content that shows the summary statistics of a boxplot
|
|
79
|
+
private createChartHoverHandler = () => {
|
|
80
|
+
return (d: IOrFrameHoverArgs<IChartDataPoint> & IOrSummaryPiece): void => {
|
|
81
|
+
if (d && d.type === 'frame-hover') {
|
|
82
|
+
const points = d.points;
|
|
83
|
+
const data: IHoverDataGroup = {
|
|
84
|
+
baseline: [],
|
|
85
|
+
canary: [],
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
points.forEach((p: IOrSummaryPiece) => {
|
|
89
|
+
data[p.key].push({ label: p.label, value: p.value });
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const summaryLabels = data.baseline.map((b: IHoverData) => b.label);
|
|
93
|
+
const summaryKeysColumn = [
|
|
94
|
+
<div className={'header'} key={'summary'}>
|
|
95
|
+
Summary
|
|
96
|
+
</div>,
|
|
97
|
+
...summaryLabels.map((label: string) => {
|
|
98
|
+
return <div key={label}>{label}</div>;
|
|
99
|
+
}),
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
const baselineColumn = [
|
|
103
|
+
<div className={'header'} key={'baseline'}>
|
|
104
|
+
<CircleIcon group={'baseline'} />
|
|
105
|
+
Baseline
|
|
106
|
+
</div>,
|
|
107
|
+
data.baseline.map((hd: IHoverData, i: number) => {
|
|
108
|
+
return <div key={i}>{utils.formatMetricValue(hd.value)}</div>;
|
|
109
|
+
}),
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
const canaryColumn = [
|
|
113
|
+
<div className="header" key="canary">
|
|
114
|
+
<CircleIcon group="canary" />
|
|
115
|
+
Canary
|
|
116
|
+
</div>,
|
|
117
|
+
data.canary.map((hd: IHoverData, i: number) => {
|
|
118
|
+
return <div key={i}>{utils.formatMetricValue(hd.value)}</div>;
|
|
119
|
+
}),
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
const tooltipContent = (
|
|
123
|
+
<div className="tooltip-container">
|
|
124
|
+
<div className="columns">
|
|
125
|
+
<div className="column">{summaryKeysColumn}</div>
|
|
126
|
+
<div className="column">{baselineColumn}</div>
|
|
127
|
+
<div className="column">{canaryColumn}</div>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
this.setState({
|
|
133
|
+
tooltip: {
|
|
134
|
+
content: tooltipContent,
|
|
135
|
+
x: d.x + this.margin.left,
|
|
136
|
+
y: d.y + this.margin.top,
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
} else {
|
|
140
|
+
this.setState({ tooltip: null });
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
private defineAnnotations = () => {
|
|
146
|
+
return ['baseline', 'canary'].map((g: string) => {
|
|
147
|
+
return {
|
|
148
|
+
type: 'summary-custom',
|
|
149
|
+
group: g,
|
|
150
|
+
summaryKeys: ['q1area', 'median', 'q3area'],
|
|
151
|
+
};
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
private customAnnotationFunction = (args: ISemioticAnnotationArgs<IAnnotationData, IOrGroup<IChartDataPoint>>) => {
|
|
156
|
+
const {
|
|
157
|
+
d,
|
|
158
|
+
orFrameState: { pieceDataXY },
|
|
159
|
+
categories,
|
|
160
|
+
} = args;
|
|
161
|
+
|
|
162
|
+
if (d.type === 'summary-custom') {
|
|
163
|
+
// If no data exists for this group, don't return any annotation elements
|
|
164
|
+
if (!categories[d.group]) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const summaryData = pieceDataXY.filter((sd: IOrSummaryPiece) => sd.key === d.group);
|
|
169
|
+
const boxPlotWidth = categories[d.group].width;
|
|
170
|
+
const statLabelMap: { [stat: string]: string } = {
|
|
171
|
+
median: 'median',
|
|
172
|
+
q1area: '25th %-ile',
|
|
173
|
+
q3area: '75th %-ile',
|
|
174
|
+
};
|
|
175
|
+
const createNoteElement = (posY: number, dataPoint: IOrSummaryPiece) => {
|
|
176
|
+
const name = dataPoint.summaryPieceName;
|
|
177
|
+
const label = statLabelMap[name];
|
|
178
|
+
const noteData = {
|
|
179
|
+
x: dataPoint.x,
|
|
180
|
+
y: posY,
|
|
181
|
+
dx: boxPlotWidth / 2,
|
|
182
|
+
dy: 0,
|
|
183
|
+
note: {
|
|
184
|
+
label: `${label}: ${utils.formatMetricValue(dataPoint.value)}`,
|
|
185
|
+
wrap: 100,
|
|
186
|
+
lineType: 'vertical',
|
|
187
|
+
align: 'middle',
|
|
188
|
+
orientation: 'topBottom',
|
|
189
|
+
padding: 10,
|
|
190
|
+
},
|
|
191
|
+
className: 'boxplot-annotation',
|
|
192
|
+
};
|
|
193
|
+
return <Annotation key={name} noteData={noteData} />;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const nodes = d.summaryKeys
|
|
197
|
+
.map((summaryKey: string) => {
|
|
198
|
+
const pieceData = summaryData.find((sd: IOrSummaryPiece) => sd.summaryPieceName === summaryKey);
|
|
199
|
+
return pieceData ? new Node<IOrSummaryPiece>(pieceData.y, 20, pieceData) : null;
|
|
200
|
+
})
|
|
201
|
+
.map((v: null | Node<IOrSummaryPiece>) => v) as Array<Node<IOrSummaryPiece>>;
|
|
202
|
+
|
|
203
|
+
const forceOptions = {
|
|
204
|
+
minPos: this.margin.top,
|
|
205
|
+
maxPos: vizConfig.height - this.margin.bottom,
|
|
206
|
+
};
|
|
207
|
+
const annotations = new Force<IOrSummaryPiece>(forceOptions)
|
|
208
|
+
.nodes(nodes)
|
|
209
|
+
.compute()
|
|
210
|
+
.nodes()
|
|
211
|
+
.map((n: Node<IOrSummaryPiece>) => createNoteElement(n.currentPos, n.data));
|
|
212
|
+
|
|
213
|
+
return annotations;
|
|
214
|
+
} else {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
private getChartProps = () => {
|
|
220
|
+
const { parentWidth } = this.props;
|
|
221
|
+
const chartData = this.generateChartData();
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
size: [parentWidth, vizConfig.height],
|
|
225
|
+
margin: this.margin,
|
|
226
|
+
projection: 'vertical',
|
|
227
|
+
summaryType: 'boxplot',
|
|
228
|
+
oLabel: false,
|
|
229
|
+
oPadding: 160,
|
|
230
|
+
style: (d: IChartDataPoint) => {
|
|
231
|
+
return {
|
|
232
|
+
fill: d.color,
|
|
233
|
+
fillOpacity: 0.7,
|
|
234
|
+
};
|
|
235
|
+
},
|
|
236
|
+
summaryStyle: (d: IChartDataPoint) => {
|
|
237
|
+
return {
|
|
238
|
+
fill: d.color,
|
|
239
|
+
fillOpacity: 0.4,
|
|
240
|
+
stroke: '#6a6a6a',
|
|
241
|
+
strokeWidth: 2,
|
|
242
|
+
};
|
|
243
|
+
},
|
|
244
|
+
pieceClass: (d: IChartDataPoint) => `piece ${d.group}`,
|
|
245
|
+
type: {
|
|
246
|
+
type: 'swarm',
|
|
247
|
+
r: 3,
|
|
248
|
+
iterations: 50,
|
|
249
|
+
},
|
|
250
|
+
rExtent: extent(chartData.map((o) => o.value)),
|
|
251
|
+
customHoverBehavior: this.createChartHoverHandler(),
|
|
252
|
+
hoverAnnotation: false,
|
|
253
|
+
annotations: this.defineAnnotations(),
|
|
254
|
+
summaryHoverAnnotation: [] as IAnnotationType[],
|
|
255
|
+
data: chartData,
|
|
256
|
+
oAccessor: (d: IChartDataPoint) => d.group,
|
|
257
|
+
rAccessor: (d: IChartDataPoint) => d.value,
|
|
258
|
+
svgAnnotationRules: this.customAnnotationFunction,
|
|
259
|
+
summaryClass: 'boxplot-summary',
|
|
260
|
+
axis: {
|
|
261
|
+
orient: 'left',
|
|
262
|
+
label: 'metric value',
|
|
263
|
+
tickFormat: (d: number) => utils.formatMetricValue(d),
|
|
264
|
+
},
|
|
265
|
+
};
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
public render() {
|
|
269
|
+
const { metricSetPair } = this.props;
|
|
270
|
+
return (
|
|
271
|
+
<div className="boxplot">
|
|
272
|
+
<ChartHeader metric={metricSetPair.name} />
|
|
273
|
+
<ChartLegend />
|
|
274
|
+
<div className="graph-container">
|
|
275
|
+
<div className="boxplot-chart">
|
|
276
|
+
<OrdinalFrame {...this.getChartProps()} />
|
|
277
|
+
</div>
|
|
278
|
+
<Tooltip {...this.state.tooltip} />
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
export interface IChartHeaderProps {
|
|
4
|
+
metric: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export default ({ metric }: IChartHeaderProps) => {
|
|
8
|
+
return (
|
|
9
|
+
<div className="chart-header">
|
|
10
|
+
<h6 className="heading-6 color-text-primary">
|
|
11
|
+
<span className="uppercase prefix">metric name:</span>
|
|
12
|
+
<span>
|
|
13
|
+
|
|
14
|
+
{metric}
|
|
15
|
+
</span>
|
|
16
|
+
</h6>
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
.chart-legend {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: row;
|
|
4
|
+
align-items: center;
|
|
5
|
+
justify-content: center;
|
|
6
|
+
height: 24px;
|
|
7
|
+
margin-top: 4px;
|
|
8
|
+
.legend-item {
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
margin: 0px 40px;
|
|
12
|
+
font-size: 12px;
|
|
13
|
+
}
|
|
14
|
+
.clickable {
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
}
|
|
17
|
+
.deselected {
|
|
18
|
+
opacity: 0.5;
|
|
19
|
+
}
|
|
20
|
+
.legend-icon {
|
|
21
|
+
height: 12px;
|
|
22
|
+
width: 40px;
|
|
23
|
+
border-radius: 6px;
|
|
24
|
+
margin-right: 8px;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
import { vizConfig } from './config';
|
|
5
|
+
|
|
6
|
+
import './chartLegend.less';
|
|
7
|
+
|
|
8
|
+
interface IChartLegendProps {
|
|
9
|
+
isClickable?: boolean;
|
|
10
|
+
onClickHandler?: (group: string) => void;
|
|
11
|
+
showGroup?: { [group: string]: boolean };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default (props: IChartLegendProps) => {
|
|
15
|
+
const { onClickHandler, showGroup = { baseline: true, canary: true }, isClickable = false } = props;
|
|
16
|
+
|
|
17
|
+
const baselineIconStyle = {
|
|
18
|
+
backgroundColor: vizConfig.colors.baseline,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const canaryIconStyle = {
|
|
22
|
+
backgroundColor: vizConfig.colors.canary,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const handleClick = (group: string) => (onClickHandler ? () => onClickHandler(group) : undefined);
|
|
26
|
+
|
|
27
|
+
const legendItemClass = classNames('legend-item', { clickable: isClickable });
|
|
28
|
+
const legendItemClassCanary = classNames(legendItemClass, { deselected: !showGroup.canary });
|
|
29
|
+
const legendItemClassBaseline = classNames(legendItemClass, { deselected: !showGroup.baseline });
|
|
30
|
+
return (
|
|
31
|
+
<div className="chart-legend">
|
|
32
|
+
<div className={legendItemClassBaseline} onClick={handleClick('baseline')}>
|
|
33
|
+
<div className="legend-icon" style={baselineIconStyle} />
|
|
34
|
+
<div>Baseline</div>
|
|
35
|
+
</div>
|
|
36
|
+
<div className={legendItemClassCanary} onClick={handleClick('canary')}>
|
|
37
|
+
<div className="legend-icon" style={canaryIconStyle} />
|
|
38
|
+
<div>Canary</div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import { vizConfig } from './config';
|
|
4
|
+
|
|
5
|
+
export interface ICircleIconProps {
|
|
6
|
+
group: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// simple component to show circle icons in tooltips
|
|
10
|
+
export default ({ group }: ICircleIconProps) => {
|
|
11
|
+
const iconStyle = {
|
|
12
|
+
color: vizConfig.colors[group],
|
|
13
|
+
paddingRight: 4,
|
|
14
|
+
};
|
|
15
|
+
return <i className="fas fa-circle" style={iconStyle} />;
|
|
16
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
interface IColorConfig {
|
|
2
|
+
[propName: string]: string;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
interface ITimeSeriesConfig {
|
|
6
|
+
[propName: string]: any;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface IDataGroup {
|
|
10
|
+
[group: string]: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface IVizConfig {
|
|
14
|
+
readonly colors: IColorConfig;
|
|
15
|
+
readonly height: number;
|
|
16
|
+
readonly timeSeries: ITimeSeriesConfig;
|
|
17
|
+
readonly dataGroupMap: IDataGroup;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const vizConfig: IVizConfig = {
|
|
21
|
+
colors: {
|
|
22
|
+
baseline: '#52b3d9',
|
|
23
|
+
canary: '#e26a6a',
|
|
24
|
+
background: '#f8f8f8',
|
|
25
|
+
},
|
|
26
|
+
height: 400,
|
|
27
|
+
timeSeries: {
|
|
28
|
+
minimapDataPointsThreshold: 240,
|
|
29
|
+
minimapHeight: 40,
|
|
30
|
+
axisTickLineHeight: 4,
|
|
31
|
+
axisTickLabelHeight: 32,
|
|
32
|
+
axisLabelHeight: 16,
|
|
33
|
+
},
|
|
34
|
+
dataGroupMap: {
|
|
35
|
+
baseline: 'control',
|
|
36
|
+
canary: 'experiment',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import * as utils from './utils';
|
|
4
|
+
|
|
5
|
+
export interface ICustomAxisTickLabel {
|
|
6
|
+
millis: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// custom labels as we want two label rows when showing date + hour at midnight
|
|
10
|
+
export default ({ millis }: ICustomAxisTickLabel) => {
|
|
11
|
+
const text = utils.dateTimeTickFormatter(millis).map((s: string, i: number) => (
|
|
12
|
+
<text textAnchor={'middle'} className={'axis-label'} key={i}>
|
|
13
|
+
{s}
|
|
14
|
+
</text>
|
|
15
|
+
));
|
|
16
|
+
return <g className={'axis-label'}>{text}</g>;
|
|
17
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
declare module 'labella' {
|
|
2
|
+
export class Node<Data> {
|
|
3
|
+
public readonly idealPos: number;
|
|
4
|
+
public readonly currentPos: number;
|
|
5
|
+
public readonly width: number;
|
|
6
|
+
public readonly data: Data;
|
|
7
|
+
public readonly layerIndex: number;
|
|
8
|
+
constructor(idealPos: number, width: number, data?: Data);
|
|
9
|
+
}
|
|
10
|
+
export class Force<Data> {
|
|
11
|
+
constructor(options: { [option: string]: number | string | boolean | null });
|
|
12
|
+
nodes(nodes: Array<Node<Data>>): this;
|
|
13
|
+
nodes(): Array<Node<Data>>; // eslint-disable-line no-dupe-class-members
|
|
14
|
+
compute(): this;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
declare module 'semiotic' {
|
|
2
|
+
import { CurveFactory } from 'd3-shape';
|
|
3
|
+
import { ScaleTime } from 'd3-scale';
|
|
4
|
+
|
|
5
|
+
export class XYFrame extends React.Component<IXYFrameProps<DataSet, DataPoint>> {}
|
|
6
|
+
export class MinimapXYFrame extends React.Component<IMinimapProps<DataSet, DataPoint>> {}
|
|
7
|
+
export class OrdinalFrame extends React.Component {}
|
|
8
|
+
export class Annotation extends React.Component<IAnnotationProps> {}
|
|
9
|
+
export class Axis extends React.Component<IAxisProps> {}
|
|
10
|
+
|
|
11
|
+
// Props for the XYFrame component
|
|
12
|
+
export interface IXYFrameProps<DataSet, DataPoint> {
|
|
13
|
+
lines?: DataSet[];
|
|
14
|
+
lineType?: { type: string; interpolator: CurveFactory };
|
|
15
|
+
lineStyle?: (ds: DataSet) => object;
|
|
16
|
+
xAccessor?: string | ((d: DataPoint) => Date);
|
|
17
|
+
yAccessor?: string | ((d: DataPoint) => number);
|
|
18
|
+
xScaleType?: ScaleTime<number, number>;
|
|
19
|
+
baseMarkProps?: object;
|
|
20
|
+
hoverAnnotation?: boolean | Array<object | Function> | object | Function;
|
|
21
|
+
customHoverBehavior?: (d: IXYFrameHoverBaseArgs<DataPoint> & DataPoint) => void;
|
|
22
|
+
xExtent?: Date[] | number[];
|
|
23
|
+
axes?: object[];
|
|
24
|
+
margin?: IMargin;
|
|
25
|
+
matte?: boolean;
|
|
26
|
+
size?: number[];
|
|
27
|
+
yBrushable?: boolean;
|
|
28
|
+
brushEnd?: (d: Date[]) => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Props for the Minimap component
|
|
32
|
+
export interface IMinimapProps<DataSet, DataPoint> extends IXYFrameProps<DataSet, DataPoint> {
|
|
33
|
+
minimap?: IXYFrameProps<DataSet, DataPoint>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Props for the Annotation component
|
|
37
|
+
export interface IAnnotationProps {
|
|
38
|
+
noteData: {
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
dx?: number;
|
|
42
|
+
dy?: number;
|
|
43
|
+
nx?: number;
|
|
44
|
+
ny?: number;
|
|
45
|
+
note: {
|
|
46
|
+
label: string;
|
|
47
|
+
wrap?: number;
|
|
48
|
+
align?: string;
|
|
49
|
+
orientation?: string;
|
|
50
|
+
padding?: number;
|
|
51
|
+
color?: string;
|
|
52
|
+
lineType?: string;
|
|
53
|
+
};
|
|
54
|
+
className?: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Props for the Axis component
|
|
59
|
+
export interface IAxisProps {
|
|
60
|
+
className?: string;
|
|
61
|
+
size: number[];
|
|
62
|
+
scale: ScaleTime;
|
|
63
|
+
orient?: string;
|
|
64
|
+
label?: string | object;
|
|
65
|
+
tickValues?: number[] | Date[];
|
|
66
|
+
tickFormat?: (d: number) => JSX.Element | string;
|
|
67
|
+
ticks?: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Args supplied by semiotic's XYFrame to client's hover event callback function
|
|
71
|
+
export interface IXYFrameHoverBaseArgs<DataPoint> {
|
|
72
|
+
data: DataPoint;
|
|
73
|
+
points?: DataPoint[];
|
|
74
|
+
voronoiX: number;
|
|
75
|
+
voronoiY: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
* Args supplied by semiotic's OrdinalFrame to client's custom hover event callback function
|
|
80
|
+
*/
|
|
81
|
+
export interface IOrFrameHoverArgs<DataPoint> {
|
|
82
|
+
column?: IOrGroup<DataPoint>;
|
|
83
|
+
summary?: Array<IOrPiece<DataPoint>>;
|
|
84
|
+
type?: string; // type of hover event (e.g. frame-hover)
|
|
85
|
+
points: undefined | IOrSummaryPiece[]; // used for calculated summary datasets (e.g. boxplot)
|
|
86
|
+
voronoiX?: number; // x position on the SVG element
|
|
87
|
+
voronoiY?: number; // y position on the SVG element
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface IOrSummaryPiece {
|
|
91
|
+
isSummaryData: boolean;
|
|
92
|
+
key: string; // data group (i.e. baseline or canary)
|
|
93
|
+
label: string;
|
|
94
|
+
summaryPieceName: string;
|
|
95
|
+
type: string; // type of hover event (e.g. frame-hover)
|
|
96
|
+
value: number;
|
|
97
|
+
x: number; // x position on the SVG element
|
|
98
|
+
y: number; // y position on the SVG element
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export interface IOrPiece<DataPoint> {
|
|
102
|
+
base: number; // coordinate of the base along the y-axis
|
|
103
|
+
value: number; // original value of the data point
|
|
104
|
+
scaledValue: number; // value in pixels
|
|
105
|
+
data: DataPoint;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface IOrGroup<DataPoint> {
|
|
109
|
+
middle: number; // absolute position of the center of the column along the main axis
|
|
110
|
+
name: string; // ordinal label
|
|
111
|
+
padding: number;
|
|
112
|
+
width: number; // width of the column
|
|
113
|
+
x: number; // starting position of the column (along the main axis)
|
|
114
|
+
xyData: Array<IOrXyData<DataPoint>>;
|
|
115
|
+
y: number;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface IOrXyData<DataPoint> {
|
|
119
|
+
o: string; // ordinal label for this data
|
|
120
|
+
xy: {
|
|
121
|
+
height: number; //height of the data point svg along the y axis
|
|
122
|
+
width: number; // width of the data point svg (e.g. bar width)
|
|
123
|
+
x: number; // starting x coordinate of the drawn data svg
|
|
124
|
+
y: number; // starting y coordinate of the drawn data svg
|
|
125
|
+
|
|
126
|
+
// center coordinate of the data point svg along the main (x) axis
|
|
127
|
+
// relative to x
|
|
128
|
+
middle: number;
|
|
129
|
+
};
|
|
130
|
+
piece: IOrPiece<DataPoint>;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/*
|
|
134
|
+
* Args supplied by semiotic's Frame to client's custom annotation function
|
|
135
|
+
*/
|
|
136
|
+
export interface ISemioticAnnotationArgs<AnnotationData, CategoryData> {
|
|
137
|
+
d: AnnotationData; // client-defined custom annotation data
|
|
138
|
+
i: number; // index
|
|
139
|
+
categories: {
|
|
140
|
+
[label: string]: CategoryData;
|
|
141
|
+
};
|
|
142
|
+
orFrameState?: ISemioticOrFrameState;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface ISemioticOrFrameState {
|
|
146
|
+
pieceDataXY: IOrSummaryPiece[];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Frame prop that specifies any pre-defined semiotic annotation
|
|
150
|
+
export type IAnnotationType = {
|
|
151
|
+
type?: string | Function;
|
|
152
|
+
column?: { name: string };
|
|
153
|
+
x?: number;
|
|
154
|
+
y?: number;
|
|
155
|
+
yTop?: number;
|
|
156
|
+
yBottom?: number;
|
|
157
|
+
yMiddle?: number;
|
|
158
|
+
coordinates?: object[];
|
|
159
|
+
};
|
|
160
|
+
}
|