File

src/lib/entity/detail/sz-entity-detail-graph/sz-standalone-graph.component.ts

Description

Embeddable Graph Component used to display a entity and its network relationships to other entities visually.

Optionally can display a embedded filter control to allow user to change the components parameters of this component.

Example :
<!-- (Angular) -->
<sz-standalone-graph
filterWidth="320"
[graphIds]="graphIds"
[showPopOutIcon]="false"
[showMatchKeyControl]="false"
[showFiltersControl]="false"
[filterControlPosition]="'top-right'"
(entityClick)="onGraphEntityClick($event)"
[showMatchKeys]="true"
></sz-standalone-graph>
Example :
<!-- (WC) by attribute -->
<sz-wc-standalone-graph
filter-width="320"
graph-ids="1,1001,1002"
show-pop-out-icon="false"
show-match-key-control="false"
show-filters-control="false"
filter-control-position="top-right"
show-match-keys="true"
></sz-wc-standalone-graph>
Example :
<!-- (WC) by DOM -->
<sz-wc-standalone-graph id="sz-wc-standalone-graph"></sz-wc-standalone-graph>
<script>
document.getElementById('sz-wc-standalone-graph').graphIds = [1,1001,1002];
document.getElementById('sz-wc-standalone-graph').addEventListener('entityClick', (data) => { console.log('entity clicked on!', data); })
</script>

Extends

SzGraphComponent

Implements

AfterViewInit

Metadata

Index

Properties
Methods
Inputs
Accessors

Constructor

constructor(_p_prefs: SzPrefsService, _p_cd: ChangeDetectorRef, _p_css: SzCSSClassService, overlay: Overlay, dialog: MatDialog, viewContainerRef: ViewContainerRef)
Parameters :
Name Type Optional
_p_prefs SzPrefsService No
_p_cd ChangeDetectorRef No
_p_css SzCSSClassService No
overlay Overlay No
dialog MatDialog No
viewContainerRef ViewContainerRef No

Inputs

showGraphContextMenu
Type : boolean

whether or not to show the built-in context menu on graph entity right-click

showGraphEntityContextMenuOnClick
Type : boolean

whether or not to trigger the built-in entity context menu on single-click instead of the default right-click

showGraphLinkContextMenu
Type : boolean

whether or not to show the built-in context menu on graph link right-click

showGraphLinkContextMenuOnClick
Type : boolean

whether or not to trigger the built-in relationship context menu on single-click instead of the default right-click

Methods

Public hideGraphEntity
hideGraphEntity(entityId: SzEntityIdentifier)

remove single node and any directly related nodes that are only related to the entity specified

Parameters :
Name Type Optional
entityId SzEntityIdentifier No
Returns : void
Public hideGraphEntityRelationships
hideGraphEntityRelationships(entityId: SzEntityIdentifier)

hide all visible(expanded) entities related to a specific entity that are themselves not related to any other visible entities

Parameters :
Name Type Optional
entityId SzEntityIdentifier No
Returns : void
Public isGraphEntityRemovable
isGraphEntityRemovable(entityId: SzEntityIdentifier)

can a specific entity node be removed from canvas

Parameters :
Name Type Optional
entityId SzEntityIdentifier No
Returns : boolean
ngAfterViewInit
ngAfterViewInit()
Returns : void
Public onFilterMatchKeyTokenSelectionScopeChanged
onFilterMatchKeyTokenSelectionScopeChanged(scope: SzMatchKeyTokenFilterScope)

when the filter component's match key scope is changed from EXTRANEOUS to CORE or vice-versa

Parameters :
Name Type Optional
scope SzMatchKeyTokenFilterScope No
Returns : void
Public showGraphEntityRelationships
showGraphEntityRelationships(entityId: SzEntityIdentifier)

show any entities that are related to a specific entity that are currently not on the canvas

Parameters :
Name Type Optional
entityId SzEntityIdentifier No
Returns : void

Properties

Public _p_prefs
Type : SzPrefsService
Public dialog
Type : MatDialog
Public filterShowDataSources
Type : string[]
Default value : []
graphLinkContextMenu
Type : TemplateRef<any>
Decorators :
@ViewChild('graphLinkContextMenu')
graphNodeContextMenu
Type : TemplateRef<any>
Decorators :
@ViewChild('graphNodeContextMenu')

built-in graph context menus

Public overlay
Type : Overlay
Public viewContainerRef
Type : ViewContainerRef

Accessors

showGraphLinkContextMenu
getshowGraphLinkContextMenu()

whether or not to show the built-in context menu on graph link right-click

Returns : boolean
setshowGraphLinkContextMenu(value: boolean)

whether or not to show the built-in context menu on graph link right-click

Parameters :
Name Type Optional
value boolean No
Returns : void
showGraphContextMenu
getshowGraphContextMenu()

whether or not to show the built-in context menu on graph entity right-click

Returns : boolean
setshowGraphContextMenu(value: boolean)

whether or not to show the built-in context menu on graph entity right-click

Parameters :
Name Type Optional
value boolean No
Returns : void
showGraphEntityContextMenuOnClick
setshowGraphEntityContextMenuOnClick(value: boolean)

whether or not to trigger the built-in entity context menu on single-click instead of the default right-click

Parameters :
Name Type Optional
value boolean No
Returns : void
showGraphLinkContextMenuOnClick
setshowGraphLinkContextMenuOnClick(value: boolean)

whether or not to trigger the built-in relationship context menu on single-click instead of the default right-click

Parameters :
Name Type Optional
value boolean No
Returns : void
<!-- start graph entity context menu template -->
<ng-template #graphNodeContextMenu let-entityEvt>
  <ul class="graph-context-menu">
      <li>#{{entityEvt?.entityId}}</li>
      <li [class.disabled]="!isGraphEntityRemovable(entityEvt)" (click)="hideGraphEntity(entityEvt)">Hide Entity</li>
  </ul>
</ng-template>
<!-- end graph entity context menu template -->
<!-- start graph link context menu template -->
<ng-template #graphLinkContextMenu let-linkEvt>
<ul class="graph-context-menu">
    <li (click)="openWhyReportForGraphRelationship(linkEvt)">Show "Why Not" Report</li>
</ul>
</ng-template>
<!-- end graph link context menu template -->
<!-- start graph container -->
<div #graphContainer class="sz-graph-container">
    <div *ngIf="showZoomControl" class="zoom-control-container"
    [class.top-left]="zoomControlPosition == 'top-left'"
    [class.top-right]="zoomControlPosition == 'top-right'"
    [class.bottom-right]="zoomControlPosition == 'bottom-right'"
    [class.bottom-left]="zoomControlPosition == 'bottom-left'">
      <span><button class="zoom-out" (click)="zoomOut()"></button></span>
      <input disabled="disabled" type="range" min="1" max="100" [value]="graphZoom" class="slider">
      <span><button class="zoom-in" (click)="zoomIn()"></button></span>
    </div>
    <sz-relationship-network #graph class="sz-relationship-network-graph"
      [class.filters-showing]="this.showFiltersControl"
      svgViewBox="150 50 400 300"
      svgPreserveAspectRatio="xMinYMid meet"
      [entityIds]="graphIds"
      [maxDegrees]="maxDegrees"
      [buildOut]="buildOut"
      [linkGravity]="5"
      [highlight]="entityNodeColors"
      [filter]="entityNodeFilters"
      [includes]="entityMatchTokenFilter"
      [expandByDefaultWhenLessThan]="expandByDefaultWhenLessThan"
      [showLinkLabels]="_showLinkLabels"
      [suppressL1InterLinks]="_suppressL1InterLinks"
      (contextMenuClick)="onRightClick($event)"
      (entityClick)="onEntityClick($event)"
      (relationshipClick)="onLinkClick($event)"
      (relationshipContextMenuClick)="onLinkRightClick($event)"
      (noResults)="onNoResults($event)"
      (onTotalRelationshipsCountUpdated)="onTotalRelationshipsCountUpdated($event)"
      (onDataLoaded)="onGraphDataLoaded($event)"
      (onDataUpdated)="onGraphDataUpdated($event)"
      (scaleChanged)="onGraphZoom($event)"
      [noMaxEntitiesLimit]="unlimitedMaxEntities"
      [noMaxScopeLimit]="unlimitedMaxScope"
      [maxEntities]="maxEntities"></sz-relationship-network>  
    <sz-graph-control *ngIf="showMatchKeyControl" class="sz-graph-control"
      [showLinkLabels]="_showLinkLabels"
      (optionChanged)="onOptionChange($event)"
    ></sz-graph-control>
  
    <sz-graph-filter *ngIf="showFiltersControl" class="sz-graph-filter"
        [ngStyle]="{'width.px': filterWidth}"
        [class.top-left]="filterControlPosition == 'top-left'"
        [class.top-right]="filterControlPosition == 'top-right'"
        [class.bottom-right]="filterControlPosition == 'bottom-right'"
        [class.bottom-left]="filterControlPosition == 'bottom-left'"
        [showLinkLabels]="_showLinkLabels"
        (optionChanged)="onOptionChange($event)"
        (matchKeyTokenSelectionScopeChanged)="onFilterMatchKeyTokenSelectionScopeChanged($event)"
        [showDataSources]="filterShowDataSources"
        [showMatchKeys]="filterShowMatchKeys"
        [showMatchKeyTokens]="filterShowMatchKeyTokens"
        [showMatchKeyFilters]="showMatchKeyFilters"
        [matchKeyTokenSelectionScope]="matchKeyTokenSelectionScope"
        [showMatchKeyTokenFilters]="showMatchKeyTokenFilters"
        [showMatchKeyTokenSelectAll]="showMatchKeyTokenSelectAll"
        [showTooltips]="showFilterTooltips"
        [showCoreMatchKeyTokenChips]="showCoreMatchKeyTokenChips"
        [showExtraneousMatchKeyTokenChips]="showExtraneousMatchKeyTokenChips"
        [maxEntitiesLimit]="maxEntitiesFilterLimit"
    ></sz-graph-filter>
  
    <svg class="popout-icon"
        [class.top-left]="popOutIconPosition == 'top-left'"
        [class.top-right]="popOutIconPosition == 'top-right'"
        [class.bottom-right]="popOutIconPosition == 'bottom-right'"
        [class.bottom-left]="popOutIconPosition == 'bottom-left'" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
        viewBox="0 0 64 64"
        (click)="onPopOutClick()"
        *ngIf="showPopOutIcon"
        enable-background="new 0 0 64 64" xml:space="preserve">
      <g>
        <g><g><polygon points="53,56 8,56 8,11 30,11 30,3 0,3 0,64 61,64 61,34 53,34"/></g></g>
        <g><g><polygon points="42,0 50,8 33,25 39,31 56,14 64,23 64,0"/></g></g>
       </g>
    </svg>
  </div>
  <!--
    showLinkLabels: {{ showLinkLabels }}<br/>
    _suppressL1InterLinks: {{ _suppressL1InterLinks }}<br/>
    matchKeyTokenSelectionScope: {{matchKeyTokenSelectionScope}}<br/>
    filterControlPosition: "{{ filterControlPosition }}"<br/>
    entityIds: {{ graphIds }} 
  -->
<!-- end graph container -->

../../../graph/sz-graph.component.scss

@use "../scss/theme";

:host {
  height: var(--sz-large-graph-height);
  display: block;
  transition: height 500ms;

  &.open {
    .arrow {
      transform: rotate(180deg);
      transition: all 300ms;
    }
  }
  &.closed {
    height: var(--sz-entity-detail-section-graph-collapsed-height);
    .arrow {
      transition: all 300ms;
    }

    .sz-entity-detail-section-collapsible-card {
      height: 6px;
    }

    sz-graph-control, .sz-graph-control {
      display: none;
    }

    sz-relationship-network, .sz-relationship-network {
      display: none;
    }
  }
  .arrow, .icon-inline {
    margin: 0 10px 0 0;
    color: var(--sz-entity-detail-section-header-color);
    fill: var(--sz-entity-detail-section-header-color);
  }
  .icon-flip {
    transform: rotate(180deg);
  }

  sz-relationship-network {
    height: 100%;

    &.filters-showing {
      sz-relationship-network-graph, .sz-relationship-network-graph {
        width: calc(100% - 340px);
      }
    }
  }
  sz-relationship-network-graph, .sz-relationship-network-graph {
    width: 100%;
    height: 100%;
    display: block;
    background-color: #fff;
  }

  .popout-icon {
    display: block;
    bottom: 10px;
    left: 10px;
    position: absolute;
    width: 22px;
    height: 22px;
    z-index: 2000;
    color: var(--sz-entity-graph-overlay-color);
    fill: var(--sz-entity-graph-overlay-color);
    cursor: pointer;

    &.top-left {
      top: 10px;
      left: 10px;
    }
    &.top-right {
      top: 10px;
      left: unset;
      right: 10px;
    }
    &.bottom-left {
      top: unset;
      bottom: 10px;
      left: 10px;
    }
    &.bottom-right {
      top: unset;
      bottom: 10px;
      left: unset;
      right: 10px;
    }
  }

  sz-entity-detail-section-collapsible-card, .sz-entity-detail-section-collapsible-card {
    width: 100%;
    height: calc( 100% - 60px);
    display: block;
    background: var(--sz-entity-detail-section-graph-background);
    color: var(--sz-entity-detail-section-color);
    font-size: var(--sz-entity-detail-section-font-size);
    line-height: var(--sz-entity-detail-section-line-height);

    border-bottom: var(--sz-entity-detail-section-border-top);
    border-left: var(--sz-entity-detail-section-border-left);
    border-right: var(--sz-entity-detail-section-border-right);
    border-bottom: var(--sz-entity-detail-section-border-bottom);
    /*overflow: hidden;*/

    &:last-child {
      border-radius: var(--sz-entity-detail-section-border-radius);
    }
  }
  sz-graph-container, .sz-graph-container {
    width: 100%;
    height: 100%;
    display: block;
    position: relative;
    background: var(--sz-entity-detail-section-graph-background);
    color: var(--sz-entity-detail-section-color);
    font-size: var(--sz-entity-detail-section-font-size);
    line-height: var(--sz-entity-detail-section-line-height);

    border-bottom: var(--sz-entity-detail-section-border-top);
    border-left: var(--sz-entity-detail-section-border-left);
    border-right: var(--sz-entity-detail-section-border-right);
    border-bottom: var(--sz-entity-detail-section-border-bottom);
    /*overflow: hidden;*/

    &:last-child {
      border-radius: var(--sz-entity-detail-section-border-radius);
    }
  }
}
/* header */
.section-header__wrapper {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 -2px 0 0px;
  /*margin: var(--sz-entity-detail-section-header-margin);*/
  padding: var(--sz-entity-detail-section-header-padding);
  color: var(--sz-entity-detail-section-header-color);
  font-size: var(--sz-entity-detail-section-header-font-size);
  font-weight: 600;
  font-family: var(--sz-entity-detail-section-header-font-family);
  border-radius: var(--sz-entity-detail-section-header-border-radius);
  background: var(--sz-color-graph-relationships);

  svg.mat-icon {
    display: inline-block;
    width: var(--sz-entity-detail-section-header-font-size);
    height: calc( var(--sz-entity-detail-section-header-font-size) *1.15 );
    stroke-width: 0;
    stroke: var(--sz-entity-detail-section-header-color);
    fill: var(--sz-entity-detail-section-header-color);
    margin-right: .3em;
  }

  .section-header__right-content {
    display: flex;
    align-items: center;
    .section-header__countLabel {
      font-size: var(--sz-entity-detail-section-header-count-label-font-size);
      /*font-weight: 300;*/
      margin: 0 0 0 6px;
    }
    .section-header__count {
      font-size: var(--sz-entity-detail-section-header-count-font-size);
      margin: 0 4px 0 8px;
    }
  }
  .section-header__left-content {
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
    max-width: 70%;

    .section-header__title {
      overflow: hidden;
      white-space: nowrap;
      width: 100%;
      text-overflow: ellipsis;
    }
  }
}
/* control surface */
.sz-entity-detail-section-collapsible-card, .sz-entity-detail-section-collapsible-card {
  position: relative;
}

sz-graph-control, .sz-graph-control, .sz-graph-filter {
  background-color: var(--sz-entity-graph-control-background-color);
  display: var(--sz-entity-graph-control-display);
  z-index: var(--sz-entity-graph-control-z-index);
  position: var(--sz-entity-graph-control-position);
  height: calc( 100% - 3px);
  overflow-x: hidden;
  top: var(--sz-entity-graph-control-top);
  left: var(--sz-entity-graph-control-left);
  right: var(--sz-entity-graph-control-right);
  bottom: var(--sz-entity-graph-control-bottom);
  font-size: var(--sz-entity-graph-control-font-size);
  color: var(--sz-entity-graph-control-color);
  padding-top: var(--sz-entity-graph-control-padding-top);
  padding-right: var(--sz-entity-graph-control-padding-right);
  padding-bottom: var(--sz-entity-graph-control-padding-bottom);
  padding-left: var(--sz-entity-graph-control-padding-left);

  border: var(--sz-entity-graph-control-border);
  border-top: var(--sz-entity-graph-control-border-top);
  border-right: var(--sz-entity-graph-control-border-right);
  border-left: var(--sz-entity-graph-control-border-left);
  border-bottom: var(--sz-entity-graph-control-border-bottom);
  border-bottom-left-radius: var(--sz-entity-graph-control-border-bottom-left-radius);
  border-bottom-right-radius: var(--sz-entity-graph-control-border-bottom-right-radius);
  border-top-left-radius: var(--sz-entity-graph-control-border-top-left-radius);
  border-top-right-radius: var(--sz-entity-graph-control-border-top-right-radius);

  -moz-user-select: none; /* Firefox */
  -ms-user-select: none; /* Internet Explorer */
  -khtml-user-select: none; /* KHTML browsers (e.g. Konqueror) */
  -webkit-user-select: none; /* Chrome, Safari, and Opera */
  -webkit-touch-callout: none; /* Disable Android and iOS callouts*/
}

.sz-graph-filter {
  max-width: 300px;

  &.top-left {
    top: 21px;
    left: 0px;
    right: unset;
  }
  &.top-right {
    top: 0px;
    left: unset;
    right: 0px;
    bottom: unset;
  }
  &.bottom-left {
    top: unset;
    bottom: 0px;
    left: 0px;
    right: unset;
  }
  &.bottom-right {
    top: unset;
    bottom: 0px;
    left: unset;
    right: 0px;
  }
}

.zoom-control-container {
  position: absolute;
  width: theme.$sz-graph-zoom-slider-width;
  top: calc(#{theme.$sz-graph-zoom-slider-width} / 2 + 30px);
  left: calc(30px - (#{theme.$sz-graph-zoom-slider-width} / 2));
  z-index: 100;
  -webkit-transform: rotate(270deg);
  -moz-transform: rotate(270deg);
  -o-transform: rotate(270deg);
  transform: rotate(270deg);
  display: flex;
  flex-direction: row;

  &.top-left {
    top: calc(#{theme.$sz-graph-zoom-slider-width} / 2 + 30px);
    left: calc(30px - (#{theme.$sz-graph-zoom-slider-width} / 2 + 4px));
  }
  &.top-right {
    top: calc(#{theme.$sz-graph-zoom-slider-width} / 2 + 30px);
    left: unset;
    right: calc(30px - (#{theme.$sz-graph-zoom-slider-width} / 2));
  }
  &.bottom-left {
    top: unset;
    bottom: calc(#{theme.$sz-graph-zoom-slider-width} / 2 + 40px);
    left: calc(30px - (#{theme.$sz-graph-zoom-slider-width} / 2 + 4px));
  }
  &.bottom-right {
    top: unset;
    left: unset;
    bottom: calc(#{theme.$sz-graph-zoom-slider-width} / 2 + 40px);
    right: calc(30px - (#{theme.$sz-graph-zoom-slider-width} / 2));
  }

  button.zoom-in,
  button.zoom-out {
      border: 1px solid #bbb;
      border-radius: 50%;
      width: 18px;
      height: 18px;
      line-height: 18px;
      font-size: 18px;
      display: block;
      overflow: hidden;
      color: #858585;
      cursor: pointer;
      position: relative;
      top: calc(0px - (20px / 2) + 5.5px);
      font-weight: bold;
      background-repeat: no-repeat;
  }

  a.zoom-in, button.zoom-in {
      right: -3px;
      background-image: url("data:image/svg+xml,%3Csvg width='100%25' height='100%25' viewBox='-4 -4 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' xml:space='preserve' xmlns:serif='http://www.serif.com/' style='fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;'%3E%3Cg%3E%3Crect x='7' y='0' width='6' height='20' style='fill:%23707070;'/%3E%3C/g%3E%3Cg%3E%3Crect x='0' y='7' width='20' height='6' style='fill:%23707070;'/%3E%3C/g%3E%3C/svg%3E");
      background-position: 1px 1px;
      background-size: 12px;
  }
  a.zoom-out, button.zoom-out {
      right: 3px;
      background-image: url("data:image/svg+xml,%3Csvg width='100%25' height='100%25' viewBox='0 5 20 20' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' xml:space='preserve' xmlns:serif='http://www.serif.com/' style='fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;'%3E%3Crect x='7' y='0' width='6' height='20' style='fill: %23707070'/%3E%3C/svg%3E");
      background-position: 2px 3px;
      background-size: 12px 13px;
  }
}

.slider {
  -webkit-appearance: none;
  width: 100%;
  height: 5px;
  border-radius: 1px;  
  background-color: #fff;
  outline: solid 1px #707070;
  /*opacity: 0.7;*/
  -webkit-transition: .2s;
  transition: opacity .2s;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='25 -25 250 150' xmlns='http://www.w3.org/2000/svg' fill='%23bbbbbb'%3E%3Ccircle cx='50' cy='50' r='50'/%3E%3C/svg%3E");
  background-repeat: repeat-x;
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 12px;
  border-radius: 1px; 
  background: #707070;
  border: 1px solid #707070;
  cursor: default;
}

.slider::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #7a7a7a;
  cursor: default;
}

results matching ""

    No results matching ""