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

Implement non-measured layers of nodes to plexus #420

Merged
merged 5 commits into from
Jul 25, 2019

Conversation

tiffon
Copy link
Member

@tiffon tiffon commented Jul 22, 2019

Which problem is this PR solving?

Add support for rendering supplemental layers of nodes in plexus graphs.

Short description of the changes

Nodes can now also be rendered as layers of non-measured nodes. Non-measured means they take the position and size of nodes in as parameters to the render function. This is handy for decorating the main nodes with supplemental visual elements, such as UX based highlights or borders that scale well when zoom is being used.

Other changes:

  • Add a comparison of using SVG vs HTML for borders and emphasis on nodes to the demo; show as both medium and small sized graphs

  • Consolidate common code to the HtmlLayer and SvgLayer components

  • Switch to the more succinct getClassName prop instead of classNamePrefix for internal components

  • Allow SvgEdgesLayer to have defs prop when it's a standalone layer

Screenshots

For the screenshots, we're adding a 1 pixel border to the nodes and highlighting nodes with labels that start with a vowel.

The HTML version of the border and emphasis is rendered with a 1 pixel border on the node and the vowel emphasis is via a padded, striped background with a one pixel dashed outline.

For the version which uses SVG to look better when zoomed out:

  • The border is a rect with a 2 pixel stroke behind the main node's HTML content (causing 1 pixel to be viewable)
  • The vowel emphasis has three layers:
    • Top layer: A SVG rect with a 10 pixel stroke (5 pixels are viewable)
    • Middle layer: The same HTML padded background as the HTML version
    • Bottom layer: A SVG rect with a 12 pixel stroke (causing 1 pixel to be viewable)

The rationale for the SVG + HTML version is the HTML background will be visible when the node is not zoomed out. When it is zoomed out, the HTML padded background will become small and the strokes will stay viewable. This allows the detailed styling of the HTML version to be seen while near normal scale but for the emphasis, in general, to still be visible when the scale is small.

The HTML version

Normal zoom ↓

Screen Shot 2019-07-22 at 12 21 45 PM

Zoomed out to a medium size ↓

Screen Shot 2019-07-22 at 12 36 35 PM

Zoomed out to a small size ↓

Screen Shot 2019-07-22 at 12 48 52 PM


The SVG + HTML version

Normal zoom ↓

Screen Shot 2019-07-22 at 12 35 54 PM

Zoomed out to a medium size ↓

Screen Shot 2019-07-22 at 12 36 44 PM

Zoomed out to a small size ↓

Screen Shot 2019-07-22 at 12 49 03 PM

Nodes can now be rendered as layers of non-measurable nodes. This means
they take the position and size of nodes in as parameters to the render
function. This is handy for decorating the main nodes with highlights
or metadata.

Other changes:

 - Add a comparison of using SVG vs HTML for borders and emphasis on
   nodes to the demo; show as both medium and small sized graphs

 - Consolidate common code to the HtmlLayer and SvgLayer components

 - Switch to the more succinct  prop instead of
    for internal components

 - Allow SvgEdgesLayer to have defs prop when it's a standalone layer

Signed-off-by: Joe Farro <joef@uber.com>
@tiffon tiffon added the plexus Specific to packages/plexus label Jul 22, 2019
@tiffon tiffon requested a review from everett980 July 22, 2019 16:51
@codecov
Copy link

codecov bot commented Jul 22, 2019

Codecov Report

Merging #420 into master will decrease coverage by 0.05%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #420      +/-   ##
==========================================
- Coverage   91.63%   91.58%   -0.06%     
==========================================
  Files         176      176              
  Lines        3994     3994              
  Branches      921      921              
==========================================
- Hits         3660     3658       -2     
- Misses        296      298       +2     
  Partials       38       38
Impacted Files Coverage Δ
...eViewer/TimelineHeaderRow/TimelineViewingLayer.tsx 88.13% <0%> (-3.39%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 28be2cd...a87b5a9. Read the comment docs.

@tiffon tiffon force-pushed the layered-digraph-nodes-layer branch from 79d5f3c to a208da8 Compare July 23, 2019 10:51
Copy link
Collaborator

@everett980 everett980 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM, but was pretty dense to get through. As discussed yesterday, documentation once the implementation is tested and settled will be worthwhile!

I added two questions that may not result in any changes.

@@ -143,8 +146,8 @@ export type TLayer<T = {}, U = {}> = TOneOfFour<
>;

export type TMeasurableNodeProps<T = {}> = Omit<TMeasurableNodeRenderer<T>, 'measurable'> & {
classNamePrefix?: string;
hidden?: boolean;
getClassName: (name: string) => string;
Copy link
Collaborator

@everett980 everett980 Jul 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why were these made mandatory? what name would be provided to this function? could it be (name: string) => string | string?

Edit as I saw use cases for name. I think this can be optional and default to an identity function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Damn, my first comment was lost due to flaky internet)

The public API is clasNamePrefix which defaults to plexus.

Only internal components use getClassName which is basically just:

const { classNamePrefix: prefix = 'plexus' } = this.props;
const getClassName = (name: string) = `${prefix} ${prefix}--LayeredDigraph--${name}`;

// e.g.
getClassName(`SvgEdge`) === 'plexus plexus--LayeredDigraph--SvgEdge';

It just serves to shorten and the class name generation and ensure consistency.

</g>
);
if (extraWrapper) {
content = <g {...extraWrapper}>{content}</g>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since the consumer can add props to the "standard" g, what is the use case for the extra g?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ultimately, this results in:

<svg>
  <g className={ consumerDefinedClassName } style={ CONSTANT_STYLE }>
    <g className={ anotherConsumerDefinedClassName } transform={ basedOnZoomManager }>
      <g { ...extraWrapperPropsDefinedByConsumer }>
        <g { ...containerPropsAlsoDefinedByConsumer }>
          {defs /* ... */}
          {children}
        </g>
      </g>
    </g>
  </g>
</svg>

I don't know if there is a downside to having multiple nested <g>s, but it seems like this is more complicated than necessary. It leaves me wondering when a consumer would define something through setOnContainer vs extraWrapper, and which of the two classNames that I defined I should style.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extraWrapper is for internal use only; it's not part of the public API.. So, the public API is not ambiguous, the user would use setOnContainer.

Mainly, extraWrapper so the edges can have the stroke defaulted to #000 without it inadvertently overriding the CSS styling set through the public API. E.g. the container the user applies setOnContainer to inherits the stroke="#000" but can override it via CSS styling.

Right now there is a <g> for each thing that needs to be accomplished. To reduce the nesting would entail combining some <g> elements, which will be a bit more complex to map the code to the DOM elements.

I agree the levels of nesting could be reduced. But I'm pretty sure it's still very light as this happens on the scale of the number of layers not the number of vertices or edges in the graph. I would think the perf impact is negligible.

Copy link
Collaborator

@everett980 everett980 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, when we document this, we may also want to update what is public v private v protected

@tiffon tiffon merged commit 6b59893 into jaegertracing:master Jul 25, 2019
@tiffon tiffon deleted the layered-digraph-nodes-layer branch July 25, 2019 02:51
@tiffon tiffon restored the layered-digraph-nodes-layer branch July 25, 2019 02:51
vvvprabhakar pushed a commit to vvvprabhakar/jaeger-ui that referenced this pull request Jul 5, 2021
Implement non-measured layers of nodes to plexus
Signed-off-by: vvvprabhakar <vvvprabhakar@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plexus Specific to packages/plexus
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants