Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add point styling for quadrant chart #5173

Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
cba803a
add: point styling for quadrant chart (incomplete)
ilyes-ced Jan 1, 2024
8ab0044
add: tests
ilyes-ced Jan 2, 2024
e965507
Merge branch 'mermaid-js:develop' into feature/add-point-styling-quad…
ilyes-ced Jan 11, 2024
9cca389
fix:styles can be in random order and are optional
ilyes-ced Jan 11, 2024
a599e33
add: class names and class definitions|todo: tests
ilyes-ced Jan 12, 2024
0d8016d
cypress tests
ilyes-ced Jan 13, 2024
38ee172
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Jan 16, 2024
4e3d935
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Jan 18, 2024
42589a0
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Feb 5, 2024
b550146
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Feb 6, 2024
2640120
fixed parsing for classes and styles are in jison
ilyes-ced Feb 6, 2024
17959f6
various fixes + add unit tests for parsed styles
ilyes-ced Feb 7, 2024
c1cb171
added styles values validation + unit tests
ilyes-ced Feb 7, 2024
8ad056b
1 tiny typo
ilyes-ced Feb 7, 2024
f1aa6ff
some fixes
ilyes-ced Feb 11, 2024
14e1e63
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Feb 12, 2024
af7364b
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Feb 14, 2024
cabcf1e
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Feb 20, 2024
fc74275
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Feb 29, 2024
67e482f
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Feb 29, 2024
b8e6672
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Mar 5, 2024
1059dd3
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Mar 6, 2024
358d855
fixed typo
ilyes-ced Mar 6, 2024
01082f8
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
sidharthv96 Mar 7, 2024
b191513
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Mar 8, 2024
3344446
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Mar 8, 2024
5b43460
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Mar 9, 2024
37ba7af
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Mar 11, 2024
3072604
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
sidharthv96 Mar 23, 2024
29ec8cb
small fixes
ilyes-ced Mar 24, 2024
3b8e6ec
small fix (follow)
ilyes-ced Mar 24, 2024
3f95c78
added styling docs
ilyes-ced Mar 26, 2024
1d8332d
Merge branch 'develop' into feature/add-point-styling-quadrant-to-charts
ilyes-ced Mar 26, 2024
585609b
lint fix
ilyes-ced Mar 26, 2024
253adcb
added docs build
ilyes-ced Mar 26, 2024
3357844
feat: Change precedence of styling
sidharthv96 Apr 16, 2024
eb4a6fd
docs: Add quadrant point styling
sidharthv96 Apr 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions cypress/integration/rendering/quadrantChart.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,4 +226,54 @@ describe('Quadrant Chart', () => {
);
cy.get('svg');
});

it('it should render data points with styles', () => {
imgSnapshotTest(
`
quadrantChart
title Reach and engagement of campaigns
x-axis Reach -->
y-axis Engagement -->
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6] radius: 20
Campaign B: [0.45, 0.23] color: #ff0000
Campaign C: [0.57, 0.69] stroke_color: #ff00ff
Campaign D: [0.78, 0.34] stroke_width: 3px
Campaign E: [0.40, 0.34] radius: 20, color: #ff0000, stroke_color: #ff00ff, stroke_width: 3px
Campaign F: [0.35, 0.78] stroke_width: 3px, color: #ff0000, radius: 20, stroke_color: #ff00ff
Campaign G: [0.22, 0.22] stroke_width: 3px, color: #309708, radius: 20, stroke_color: #5060ff
Campaign H: [0.22, 0.44]
`,
{}
);
cy.get('svg');
});

it('it should render data points with styles + classes', () => {
imgSnapshotTest(
`
quadrantChart
title Reach and engagement of campaigns
x-axis Reach -->
y-axis Engagement -->
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A:::class1: [0.3, 0.6] radius: 20
Campaign B: [0.45, 0.23] color: #ff0000
Campaign C: [0.57, 0.69] stroke_color: #ff00ff
Campaign D:::class2: [0.78, 0.34] stroke_width: 3px
Campaign E:::class2: [0.40, 0.34] radius: 20 color: #ff0000, stroke_color: #ff00ff, stroke_width: 3px
Campaign F:::class1: [0.35, 0.78]
classDef class1 color: #908342, radius : 10, stroke-color: #310085, stroke-width: 10px
classDef class2 color: #f00fff, radius : 10
`,
{}
);
cy.get('svg');
ilyes-ced marked this conversation as resolved.
Show resolved Hide resolved
});
});
14 changes: 12 additions & 2 deletions packages/mermaid/src/diagrams/quadrant-chart/parser/quadrant.jison
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
%x point_start
%x point_x
%x point_y
%x styles_string
%x class_styles
%x class_name
%%
\%\%(?!\{)[^\n]* /* skip comments */
[^\}]\%\%[^\n]* /* skip comments */
Expand Down Expand Up @@ -43,11 +46,17 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
<string>["] this.popState();
<string>[^"]* return "STR";

\:\:\: {this.begin('class_name')}
<class_name>^\w+ {this.popState(); return 'class_name';}

\s*\:\s*\[\s* {this.begin("point_start"); return 'point_start';}
<point_start>(1)|(0(.\d+)?) {this.begin('point_x'); return 'point_x';}
<point_start>\s*\]" "* {this.popState();}
<point_start>\s*\]" "* {this.popState(); this.begin('styles_string')}
<styles_string>.* {this.popState(); return 'styles_string';}
<point_x>\s*\,\s* {this.popState(); this.begin('point_y');}
<point_y>(1)|(0(.\d+)?) {this.popState(); return 'point_y';}
\s*classDef\s* {this.begin('class_styles')}
<class_styles>.* {this.popState(); yy.addClass(this.match);}

" "*"quadrantChart"" "* return 'QUADRANT';

Expand Down Expand Up @@ -103,7 +112,8 @@ statement
;

points
: text point_start point_x point_y {yy.addPoint($1, $3, $4);}
: text point_start point_x point_y styles_string {yy.addPoint($1, "", $3, $4, $5);}
| text class_name point_start point_x point_y styles_string {yy.addPoint($1, $2, $4, $5, $6);}
;

axisDetails
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,4 +266,180 @@ describe('Testing quadrantChart jison file', () => {
expect(mockDB.addPoint).toHaveBeenCalledWith({ text: 'IBM', type: 'text' }, '0.51', '0.40');
expect(mockDB.addPoint).toHaveBeenCalledWith({ text: 'Incorta', type: 'text' }, '0.20', '0.30');
});

it('should be able to parse the whole chart with point styling with all params or some params', () => {
const str = `quadrantChart
title Analytics and Business Intelligence Platforms
x-axis "Completeness of Vision ❀" --> "x-axis-2"
y-axis Ability to Execute --> "y-axis-2"
quadrant-1 Leaders
quadrant-2 Challengers
quadrant-3 Niche
quadrant-4 Visionaries
Microsoft: [0.75, 0.75] radius: 10
Salesforce: [0.55, 0.60] radius: 10, color: #ff0000
IBM: [0.51, 0.40] radius: 10, color: #ff0000, stroke_color: #ff00ff
Incorta: [0.20, 0.30] radius: 10 ,color: #ff0000 ,stroke_color: #ff00ff ,stroke_width: 10px`;

expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setXAxisLeftText).toHaveBeenCalledWith({
text: 'Completeness of Vision ❀',
type: 'text',
});
expect(mockDB.setXAxisRightText).toHaveBeenCalledWith({ text: 'x-axis-2', type: 'text' });
expect(mockDB.setYAxisTopText).toHaveBeenCalledWith({ text: 'y-axis-2', type: 'text' });
expect(mockDB.setYAxisBottomText).toHaveBeenCalledWith({
text: 'Ability to Execute',
type: 'text',
});
expect(mockDB.setQuadrant1Text).toHaveBeenCalledWith({ text: 'Leaders', type: 'text' });
expect(mockDB.setQuadrant2Text).toHaveBeenCalledWith({ text: 'Challengers', type: 'text' });
expect(mockDB.setQuadrant3Text).toHaveBeenCalledWith({ text: 'Niche', type: 'text' });
expect(mockDB.setQuadrant4Text).toHaveBeenCalledWith({ text: 'Visionaries', type: 'text' });
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'Microsoft', type: 'text' },
'',
'0.75',
'0.75',
'radius: 10'
);
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'Salesforce', type: 'text' },
'',
'0.55',
'0.60',
'radius: 10, color: #ff0000'
);
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'IBM', type: 'text' },
'',
'0.51',
'0.40',
'radius: 10, color: #ff0000, stroke_color: #ff00ff'
);
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'Incorta', type: 'text' },
'',
'0.20',
'0.30',
'radius: 10 ,color: #ff0000 ,stroke_color: #ff00ff ,stroke_width: 10px'
);
});
it('should be able to parse the whole chart with point styling with 1 param', () => {
const str = `quadrantChart
title Analytics and Business Intelligence Platforms
x-axis "Completeness of Vision ❀" --> "x-axis-2"
y-axis Ability to Execute --> "y-axis-2"
quadrant-1 Leaders
quadrant-2 Challengers
quadrant-3 Niche
quadrant-4 Visionaries
Microsoft: [0.75, 0.75] radius: 10
Salesforce: [0.55, 0.60] color: #ff0000
IBM: [0.51, 0.40] stroke_color: #ff00ff
Incorta: [0.20, 0.30] stroke_width: 10px`;

expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setXAxisLeftText).toHaveBeenCalledWith({
text: 'Completeness of Vision ❀',
type: 'text',
});
expect(mockDB.setXAxisRightText).toHaveBeenCalledWith({ text: 'x-axis-2', type: 'text' });
expect(mockDB.setYAxisTopText).toHaveBeenCalledWith({ text: 'y-axis-2', type: 'text' });
expect(mockDB.setYAxisBottomText).toHaveBeenCalledWith({
text: 'Ability to Execute',
type: 'text',
});
expect(mockDB.setQuadrant1Text).toHaveBeenCalledWith({ text: 'Leaders', type: 'text' });
expect(mockDB.setQuadrant2Text).toHaveBeenCalledWith({ text: 'Challengers', type: 'text' });
expect(mockDB.setQuadrant3Text).toHaveBeenCalledWith({ text: 'Niche', type: 'text' });
expect(mockDB.setQuadrant4Text).toHaveBeenCalledWith({ text: 'Visionaries', type: 'text' });
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'Microsoft', type: 'text' },
'',
'0.75',
'0.75',
'radius: 10'
);
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'Salesforce', type: 'text' },
'',
'0.55',
'0.60',
'color: #ff0000'
);
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'IBM', type: 'text' },
'',
'0.51',
'0.40',
'stroke_color: #ff00ff'
);
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'Incorta', type: 'text' },
'',
'0.20',
'0.30',
'stroke_width: 10px'
);
});

it('should be able to parse the whole chart with point styling with params in a random order + class names', () => {
const str = `quadrantChart
title Analytics and Business Intelligence Platforms
x-axis "Completeness of Vision ❀" --> "x-axis-2"
y-axis Ability to Execute --> "y-axis-2"
quadrant-1 Leaders
quadrant-2 Challengers
quadrant-3 Niche
quadrant-4 Visionaries
Microsoft: [0.75, 0.75] stroke_color: #ff00ff ,stroke_width: 10px, color: #ff0000, radius: 10
Salesforce:::class1: [0.55, 0.60] radius: 10, color: #ff0000
IBM: [0.51, 0.40] stroke_color: #ff00ff ,stroke_width: 10px
Incorta: [0.20, 0.30] stroke_width: 10px`;

expect(parserFnConstructor(str)).not.toThrow();
expect(mockDB.setXAxisLeftText).toHaveBeenCalledWith({
text: 'Completeness of Vision ❀',
type: 'text',
});
expect(mockDB.setXAxisRightText).toHaveBeenCalledWith({ text: 'x-axis-2', type: 'text' });
expect(mockDB.setYAxisTopText).toHaveBeenCalledWith({ text: 'y-axis-2', type: 'text' });
expect(mockDB.setYAxisBottomText).toHaveBeenCalledWith({
text: 'Ability to Execute',
type: 'text',
});
expect(mockDB.setQuadrant1Text).toHaveBeenCalledWith({ text: 'Leaders', type: 'text' });
expect(mockDB.setQuadrant2Text).toHaveBeenCalledWith({ text: 'Challengers', type: 'text' });
expect(mockDB.setQuadrant3Text).toHaveBeenCalledWith({ text: 'Niche', type: 'text' });
expect(mockDB.setQuadrant4Text).toHaveBeenCalledWith({ text: 'Visionaries', type: 'text' });
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'Microsoft', type: 'text' },
'',
'0.75',
'0.75',
'stroke_color: #ff00ff ,stroke_width: 10px, color: #ff0000, radius: 10'
);
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'Salesforce', type: 'text' },
'class1',
'0.55',
'0.60',
'radius: 10, color: #ff0000'
);
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'IBM', type: 'text' },
'',
'0.51',
'0.40',
'stroke_color: #ff00ff ,stroke_width: 10px'
);
expect(mockDB.addPoint).toHaveBeenCalledWith(
{ text: 'Incorta', type: 'text' },
'',
'0.20',
'0.30',
'stroke_width: 10px'
);
});
});
51 changes: 49 additions & 2 deletions packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,21 @@ const defaultThemeVariables = getThemeVariables();
export type TextVerticalPos = 'left' | 'center' | 'right';
export type TextHorizontalPos = 'top' | 'middle' | 'bottom';

export interface stylesObject {
className?: string;
radius?: number;
color?: string;
strokeColor?: string;
strokeWidth?: string;
}

export interface QuadrantPointInputType extends Point {
text: string;
className?: string;
radius?: number;
color?: string;
strokeColor?: string;
strokeWidth?: string;
}
ilyes-ced marked this conversation as resolved.
Show resolved Hide resolved

export interface QuadrantTextType extends Point {
Expand All @@ -27,6 +40,8 @@ export interface QuadrantPointType extends Point {
fill: string;
radius: number;
text: QuadrantTextType;
strokeColor: string;
strokeWidth: string;
}
ilyes-ced marked this conversation as resolved.
Show resolved Hide resolved

export interface QuadrantQuadrantsType extends Point {
Expand Down Expand Up @@ -117,6 +132,7 @@ export class QuadrantBuilder {
private config: QuadrantBuilderConfig;
private themeConfig: QuadrantBuilderThemeConfig;
private data: quadrantBuilderData;
private classes: stylesObject[] = [];

constructor() {
this.config = this.getDefaultConfig();
Expand Down Expand Up @@ -202,6 +218,13 @@ export class QuadrantBuilder {
this.data.points = [...points, ...this.data.points];
}

addClass(className: string, styles: stylesObject) {
this.classes.push({
className,
...styles,
});
ilyes-ced marked this conversation as resolved.
Show resolved Hide resolved
}

setConfig(config: Partial<QuadrantBuilderConfig>) {
log.trace('setConfig called with: ', config);
this.config = { ...this.config, ...config };
Expand Down Expand Up @@ -470,11 +493,29 @@ export class QuadrantBuilder {
.range([quadrantHeight + quadrantTop, quadrantTop]);

const points: QuadrantPointType[] = this.data.points.map((point) => {
const classStyles = this.classes.find((obj) => obj.className === point.className);
if (classStyles !== undefined) {
if (classStyles.color !== undefined) {
point.color = classStyles.color;
}
if (classStyles.radius !== undefined) {
point.radius = classStyles.radius;
}
if (classStyles.strokeColor !== undefined) {
point.strokeColor = classStyles.strokeColor;
}
if (classStyles.strokeWidth !== undefined) {
point.strokeWidth = classStyles.strokeWidth;
}
}
const props: QuadrantPointType = {
x: xAxis(point.x),
y: yAxis(point.y),
fill: this.themeConfig.quadrantPointFill,
radius: this.config.pointRadius,
fill:
point.color !== undefined && point.color !== ''
? point.color
: this.themeConfig.quadrantPointFill,
radius: point.radius !== undefined && point.radius ? point.radius : this.config.pointRadius,
ilyes-ced marked this conversation as resolved.
Show resolved Hide resolved
text: {
text: point.text,
fill: this.themeConfig.quadrantPointTextFill,
Expand All @@ -485,6 +526,12 @@ export class QuadrantBuilder {
fontSize: this.config.pointLabelFontSize,
rotation: 0,
},
strokeColor:
point.strokeColor !== undefined && point.strokeColor !== ''
? point.strokeColor
: this.themeConfig.quadrantPointFill,
strokeWidth:
point.strokeWidth !== undefined && point.strokeWidth !== '' ? point.strokeWidth : '0px',
};
return props;
});
Expand Down
Loading
Loading