-
Notifications
You must be signed in to change notification settings - Fork 114
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
Jamie/19 new line graph #3598
Jamie/19 new line graph #3598
Conversation
@@ -25,20 +27,22 @@ import { DesktopRoutingModule } from './desktop-routing.module'; | |||
ChefPipesModule | |||
], | |||
exports: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no major changes - just alphabetized them while I was here
<defs> | ||
<linearGradient id="chef-gradient-purple" x1="0%" y1="0%" x2="100%" y2="0%" gradientTransform="rotate(315)"> | ||
<stop id="stop1" offset="0%" /> | ||
<stop id="stop2" offset="100%" /> | ||
</linearGradient> | ||
</defs> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is placed within the SVG so that we can reuse it as a gradient across any items needing to have our gradient
background: linear-gradient(315deg, #3023AE, #C86DD7); | ||
|
||
.inner { | ||
color: white; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
noticing a few of these and other colors that need variable treatment... will fix up
|
||
it('contains an svg area for the chart', () => { | ||
expect(d3.select(component.svg)).not.toBeNull(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really wanted to test the items getting appended to the graph, but I was having a difficult time selecting anything within the svg or outside of it that was being appended via d3. Any thoughts might be helpful. I was attempting to queryAll
using By.css
@Input() data: DayPercentage[] = []; | ||
@Input() width = 900; | ||
@Input() height = 156; // we want a 116px height on the ticks, this minus margins | ||
private locked: number = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
locked
stores a number to reference when the graph is being redrawn or resized, so that it can re-attach to whatever the selected number was.
get margin() { | ||
return { right: 20, left: 20, top: 20, bottom: 20 }; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While it seems like you would just want to say return 20
, its important to store each of these individually, so that if you change just one number - like the right margin, the math is correct across the rest of the file.
get domainY(): [number, number] { | ||
const min = 0; | ||
const max = 100; // since this based on a percentage we are doing 0 to 100; | ||
return [min, max]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
leaving these values as variables to make flexible in the future if we desire.
const theLine = this.svgSelection.selectAll('.line').data([this.data], d => d.daysAgo); | ||
theLine.exit().remove(); | ||
theLine.enter().append('path').attr('class', 'line').merge(theLine) | ||
.transition().duration(1000) | ||
.attr('d', line); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the d3 standard update pattern. You will see it a lot in this file. In order to update, this is needed, in this order.
It first searches for a selector that may or may not exist and passes it our data
Then it removes any of the elements from that search that are no longer needed.
Then it adds any new items from data its being passed and merges them.
|
||
private renderPoints(): void { | ||
const points = this.svgSelection.selectAll('circle.point') | ||
.data(this.data, d => d.daysAgo); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you will notice that many of the d3 update patterns are passing a second parameter to .data()
. in this case i'm referring to d => d.daysAgo
. This provides d3 a key to index the data on, which allows us to keep a reference when we're animating the data around.
// these numbers are specific to its container | ||
const localWidth = this.width - this.margin.right - this.margin.left - 34; | ||
const thisRange = [localWidth, -this.margin.right]; | ||
const thisScale = d3.scaleLinear() | ||
.domain(this.domainX) | ||
.range(thisRange); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the tooltips have been a bit difficult to work with. The reason is that we cannot append html elements to an SVG, instead we have to attach them somewhere else in the dom. If we attach to the body, the positioning is easier, but we have unintended scroll issues, i.e. a tooltip scrolls with us when it shouldnt.
Instead I've chosen to attach it to the svg parent container. The best thing I could come up with to make the scaling fit across the X axis is to adjust the scaling down to roughly what the svg container is.
// these numbers are specific to its container | ||
const thisRange = [this.width - 48, 53]; | ||
const thisScale = d3.scaleLinear() | ||
.domain(this.domainX) | ||
.range(thisRange); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I applied the same trick for the buttons for the same reason, however the given UX styles required this anyways.
} | ||
} | ||
|
||
private renderGrid() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All through rendering the grid is where you'll see the margin variables come into play. This is standard d3.
private getHoveredElement(d3Event): number { | ||
const classes = d3.select(d3Event.target).attr('class'); | ||
const match = classes.match(/elem-([0-9]{1,2})/g)[0]; | ||
const num = match.split('-')[1]; | ||
return num; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function is used to gather which number element is being highlighted, which we can then use to highlight all of our other elements in pairing.
6ce896c
to
5db3e71
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize you're not yet in review, but just a few comments.
...nents/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.scss
Outdated
Show resolved
Hide resolved
components/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.ts
Outdated
Show resolved
Hide resolved
components/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.ts
Outdated
Show resolved
Hide resolved
components/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.ts
Outdated
Show resolved
Hide resolved
components/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.ts
Show resolved
Hide resolved
components/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.ts
Outdated
Show resolved
Hide resolved
a4ec8fd
to
0862a29
Compare
Updated with stronger typing, named constants, and feedback from UI team |
...nents/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.scss
Show resolved
Hide resolved
components/automate-ui/src/app/modules/desktop/desktop.module.ts
Outdated
Show resolved
Hide resolved
...nents/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.html
Outdated
Show resolved
Hide resolved
...nents/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.scss
Outdated
Show resolved
Hide resolved
components/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.ts
Outdated
Show resolved
Hide resolved
components/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.ts
Outdated
Show resolved
Hide resolved
components/automate-ui/src/app/page-components/simple-line-graph/simple-line-graph.component.ts
Outdated
Show resolved
Hide resolved
@@ -0,0 +1,13 @@ | |||
<svg #svg [attr.viewBox]="viewBox" | |||
[ngStyle]="{'width': width}" | |||
(window:resize)="onResize()"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reminds me of a potential future issue with the compliance line chart as well. If the parent container of the chart should change its width for whatever reason (maybe an extra panel opens or something) then the chart will not resize itself because the overall viewport is not being resized:
However with the current dashboard layout and how it resizes its layout when opening side panels, the parent container of this chart still remains the same size so relying on window:resize
is okay for now just like it's currently okay in the compliance reports view. But it could perhaps be an issue in the future should things change with the design so wanted to make a note of this elsewhere besides my own brain. It'll be trickier to implement but I know there are ways to avoid needing to manually redraw based on viewport or parent container width, giving us more flexible and performant charts to work with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a really good snag. Thanks for documenting. I'll leave for now because of the reasons you mention, but will keep in mind. I'll do a little research on this when I have the opportunity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh interesting! 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ResizeObserver could offer a solution if a polyfill exists for IE.
97f2e76
to
4f3fe2c
Compare
Waiting til desktop updates are merged to pull this one in |
Signed-off-by: seajamied <[email protected]>
its gets a little unweildy with d3, and I can't seem to find good , solid resources on how to apply typescript to d3, so i'm leaving as is for now Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
…wn container Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
Signed-off-by: seajamied <[email protected]>
4f3fe2c
to
7bc0be3
Compare
Signed-off-by: seajamied <[email protected]>
7bc0be3
to
99d2255
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (this.data && this.data.length > 0) { | ||
this.renderChart(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if you can do away with this by deleting the guard against changes.data.firstChange
in ngOnChanges
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems like I can't - I always end up with errors in the console if I don't check for firstChange
@apriofrost - This is a simple change so can always update later, but wanted to make sure you've seen that whenever the last 2 check ins are in high percentages, the 100% gets obscured. Thanks for pointing out @msorens |
🔩 Description: What code changed, and why?
This is a new line graph being built for desktop. In its current state it is not reusable, but can be converted to usable in a swift manner when we are ready.
⛓️ Related Resources
fixes: https://github.com/chef/chef-design-system/issues/19
fixes #3723
👍 Definition of Done
Line graph is ready to be used in desktop and matches UX mock ups
👟 How to Build and Test the Change
build component/automate-ui-devproxy && start_all_services
run
load_compliance_reports
in hab studio(unfortunately, I do not know how to provide varied data at this time)
navigate to https://a2-dev.test/desktop
Scroll down to "Last Check in By day"
See a chart with a few data points, change from 3 to 7 to 14 and all around using the dropdown within the component.
At 14, the labels will turn to allow for space.
Please note - the styles we are concerned about right now are only those of the graph, not its larger container.
Another important note - in its current container, 7 days worth of labels will overlap. In its planned implementation, the container will be around 600px, and the labels fit fine. Will work with UX to adjust as requested.
✅ Checklist
📷 Screenshots, if applicable
it doesn't appear the GIF is running at full speed - so take with a grain of salt
