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

#690 #689 graph node coloring changes #691

Merged
merged 2 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 24 additions & 0 deletions src/lib/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,30 @@ export function isValueTypeOfArray(value: any) {
return retVal;
}

/** are all values in one array present in the comparison array with no extra members
* present in either.
*/
export function areArrayMembersEqual(value1: any[], value2: any[]) {
let _tempArr1ValsMap = new Map( (value1 as unknown as string[]).map((val) => { return [val.toString(), val]; }));
let _tempAllValsMap = new Map(_tempArr1ValsMap);
// add existing entityId's to hashmap
if(value2 && value2.forEach) {
value2.forEach((value) => {
_tempAllValsMap.set(value as string, value);
});
// now remove all entity id's that are identical to the values in input values
// if there is a remaining value then the id sets are different
if((value1 as unknown as string[]) && (value1 as unknown as string[]).forEach) {
(value1 as unknown as string[]).forEach((valStr) => {
if(_tempAllValsMap.has(valStr.toString())) { _tempAllValsMap.delete(valStr.toString()); }
});
}

}
let noRemainder = _tempAllValsMap.size <= 0;
return noRemainder;
}

export function interpolateTemplate(template, args) {
return Object.entries(args).reduce(
(result, [arg, val]) => result.replace(`$\{${arg}}`, `${val}`),
Expand Down
1 change: 0 additions & 1 deletion src/lib/graph/sz-graph-filter.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ <h3>{{ sectionTitles[4] }}</h3>
Active/Focused Enitity
<span #ttt6 class="tooltip-text">The color of the current entity or entities</span>
</span>
<small class="note-sub">(*note overrides datasource member color if selected)</small>
</label>
</li>
</ul>
Expand Down
25 changes: 21 additions & 4 deletions src/lib/graph/sz-graph-filter.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export class SzGraphFilterComponent implements OnInit, AfterViewInit, OnDestroy
// assume it's already cast correctly
this._matchKeyTokenSelectionScope = (value as SzMatchKeyTokenFilterScope);
}
console.log(`@senzing/sdk-components-ng/sz-graph-filter.matchKeyTokenSelectionScope(${value} | ${(this._matchKeyTokenSelectionScope as unknown as string)})`, this._matchKeyTokenSelectionScope);
//console.log(`@senzing/sdk-components-ng/sz-graph-filter.matchKeyTokenSelectionScope(${value} | ${(this._matchKeyTokenSelectionScope as unknown as string)})`, this._matchKeyTokenSelectionScope);
}
/**
* get the value of match key token filterings scope. possible values are
Expand All @@ -225,7 +225,7 @@ export class SzGraphFilterComponent implements OnInit, AfterViewInit, OnDestroy
private _showCoreMatchKeyTokenChips: boolean = false;
@Input() public set showCoreMatchKeyTokenChips(value: boolean) {
this._showCoreMatchKeyTokenChips = value;
console.log(`@senzing/sdk-components-ng/sz-graph-filter.showCoreMatchKeyTokenChips(${value})`, this._showCoreMatchKeyTokenChips);
//console.log(`@senzing/sdk-components-ng/sz-graph-filter.showCoreMatchKeyTokenChips(${value})`, this._showCoreMatchKeyTokenChips);
}
public get showCoreMatchKeyTokenChips(): boolean {
return this._showCoreMatchKeyTokenChips;
Expand Down Expand Up @@ -582,19 +582,36 @@ export class SzGraphFilterComponent implements OnInit, AfterViewInit, OnDestroy
}
/** handler for when a color value for a source in the "colorsByDataSourcesForm" has changed */
onDsColorChange(dsValue: string, src?: any, evt?) {
// first check if color is 000 or fff
// if so this is a remove not an update
let _isRemoveOp = false;
//console.log(`changed color for "${dsValue}" to "${src.value}"`);
if(['#ffffff','#000000'].includes(src.value)) {
_isRemoveOp = true;
}
// update color value in array
if(this._dataSources) {
let _dsIndex = this._dataSources.findIndex((dsVal: SzDataSourceComposite) => {
return dsVal.name === dsValue;
});
if(_dsIndex && this._dataSources && this._dataSources[ _dsIndex ]) {
this._dataSources[ _dsIndex ].color = src.value;
if(_isRemoveOp) {
this._dataSources[ _dsIndex ].color = undefined;
//delete this._dataSources[ _dsIndex ].color;
} else {
this._dataSources[ _dsIndex ].color = src.value;
}
}
}
// update color swatch bg color(for prettier boxes)
if(src && src.style && src.style.setProperty){
src.style.setProperty('background-color', src.value);
if(_isRemoveOp) {
src.style.removeProperty('background-color');
} else {
src.style.setProperty('background-color', src.value);
}
}

// update colors pref
if( this.prefs && this.prefs.graph) {
// there is some sort of mem reference clone issue
Expand Down
68 changes: 49 additions & 19 deletions src/lib/graph/sz-graph.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,8 @@ export class SzGraphComponent implements OnInit, OnDestroy {
/** proxy handler for when prefs have changed externally */
private onPrefsChange(prefs: SzGraphPrefs) {
//console.log('@senzing/sdk-components-ng/sz-graph-component.onPrefsChange(): ', prefs, this.prefs.graph.toJSONObject());
let queryParamChanged = false;
let queryParamChanged = false;
let queryParametersChanged = [];
let _oldQueryParams = {maxDegrees: this.maxDegrees, maxEntities: this.maxEntities, buildOut: this.buildOut, unlimitedMaxEntities: this.unlimitedMaxEntities, unlimitedMaxScope: this.unlimitedMaxScope};
let _newQueryParams = {maxDegrees: prefs.maxDegreesOfSeparation, maxEntities: prefs.maxEntities, buildOut: prefs.buildOut, unlimitedMaxEntities: prefs.unlimitedMaxEntities, unlimitedMaxScope: prefs.unlimitedMaxScope};
if(
Expand All @@ -910,8 +911,23 @@ export class SzGraphComponent implements OnInit, OnDestroy {
!this.unlimitedMaxEntities
)
) ||
this.buildOut != prefs.buildOut
(this.buildOut != prefs.buildOut && !prefs.unlimitedMaxScope)
){
if(this.maxDegrees != prefs.maxDegreesOfSeparation) {
queryParametersChanged.push('maxDegrees');
}
if(this.maxEntities != prefs.maxEntities && ((this.unlimitedMaxEntities != prefs.unlimitedMaxEntities) || !this.unlimitedMaxEntities)) {
queryParametersChanged.push('maxEntities');
}
if(this.unlimitedMaxEntities != prefs.unlimitedMaxEntities) {
queryParametersChanged.push('unlimitedMaxEntities');
}
if(this.graphNetworkComponent && this.graphNetworkComponent.noMaxEntitiesLimit != prefs.unlimitedMaxEntities) {
queryParametersChanged.push('noMaxEntitiesLimit');
}
if(this.buildOut != prefs.buildOut && !prefs.unlimitedMaxScope) {
queryParametersChanged.push(`buildOut`);
}
// only params that factor in to the API call
// should trigger full redraw
queryParamChanged = true;
Expand Down Expand Up @@ -947,21 +963,25 @@ export class SzGraphComponent implements OnInit, OnDestroy {
}
if(prefs.dataSourceColors && prefs.dataSourceColors.sort) {
let sorted = Array.from(prefs.dataSourceColors)
.filter((dsColorEntry: SzDataSourceComposite) => {
return dsColorEntry.color !== undefined;
})
.sort((dsColorEntry1: SzDataSourceComposite, dsColorEntry2: SzDataSourceComposite) => {
let retVal = dsColorEntry1.index > dsColorEntry2.index ? -1 : (dsColorEntry1.index < dsColorEntry2.index) ? 1 : 0 ;
return retVal;
})
.forEach((dsColorEntry: SzDataSourceComposite) => {
this.graphContainerEle.nativeElement.style.setProperty(
`--sz-graph-node-ds-${dsColorEntry.name.toLowerCase()}-fill`,
dsColorEntry.color
);
//this.cssClassesService.setStyle(`.sz-node-ds-${dsColorEntry.name.toLowerCase()}`, "fill", dsColorEntry.color);
this.cssClassesService.setStyle(`body .sz-relationship-network-graph .sz-node-ds-${dsColorEntry.name.toLowerCase()} .sz-graph-node-icon .sz-node-ds-${dsColorEntry.name.toLowerCase()}-fill`, "fill", `var(--sz-graph-node-ds-${dsColorEntry.name.toLowerCase()}-fill)`);
this.cssClassesService.setStyle(`body .sz-relationship-network-graph .sz-node-ds-${dsColorEntry.name.toLowerCase()} .sz-graph-node-icon .sz-graph-node-icon-fill`, "fill", `var(--sz-graph-node-ds-${dsColorEntry.name.toLowerCase()}-fill)`);
if(dsColorEntry.color !== undefined) {
this.graphContainerEle.nativeElement.style.setProperty(
`--sz-graph-node-ds-${dsColorEntry.name.toLowerCase()}-fill`,
dsColorEntry.color
);
//this.cssClassesService.setStyle(`.sz-node-ds-${dsColorEntry.name.toLowerCase()}`, "fill", dsColorEntry.color);
this.cssClassesService.setStyle(`body .sz-relationship-network-graph .sz-node-ds-${dsColorEntry.name.toLowerCase()} .sz-graph-node-icon .sz-node-ds-${dsColorEntry.name.toLowerCase()}-fill`, "fill", `var(--sz-graph-node-ds-${dsColorEntry.name.toLowerCase()}-fill)`);
this.cssClassesService.setStyle(`body .sz-relationship-network-graph .sz-node-ds-${dsColorEntry.name.toLowerCase()} .sz-graph-node-icon .sz-graph-node-icon-fill`, "fill", `var(--sz-graph-node-ds-${dsColorEntry.name.toLowerCase()}-fill)`);
} else {
// try removing value of variable so we can unset any previous values
this.graphContainerEle.nativeElement.style.removeProperty(`--sz-graph-node-ds-${dsColorEntry.name.toLowerCase()}-fill`);
this.cssClassesService.removeStyle(`body .sz-relationship-network-graph .sz-node-ds-${dsColorEntry.name.toLowerCase()} .sz-graph-node-icon .sz-node-ds-${dsColorEntry.name.toLowerCase()}-fill`, "fill");
this.cssClassesService.removeStyle(`body .sz-relationship-network-graph .sz-node-ds-${dsColorEntry.name.toLowerCase()} .sz-graph-node-icon .sz-graph-node-icon-fill`, "fill");
}
})
}
}
Expand Down Expand Up @@ -990,11 +1010,21 @@ export class SzGraphComponent implements OnInit, OnDestroy {
}
if(this.graphNetworkComponent && queryParamChanged) {
// update graph with new properties
this.graphNetworkComponent.maxDegrees = this.maxDegrees;
this.graphNetworkComponent.maxEntities = this.maxEntities;
this.graphNetworkComponent.buildOut = this.buildOut;
this.graphNetworkComponent.noMaxEntitiesLimit = this.unlimitedMaxEntities;
this.graphNetworkComponent.noMaxScopeLimit = this.unlimitedMaxScope;
if(queryParametersChanged.includes('maxDegrees')){
this.graphNetworkComponent.maxDegrees = this.maxDegrees;
}
if(queryParametersChanged.includes('maxEntities')){
this.graphNetworkComponent.maxEntities = this.maxEntities;
}
if(queryParametersChanged.includes('buildOut')){
this.graphNetworkComponent.buildOut = this.buildOut;
}
if(queryParametersChanged.includes('unlimitedMaxEntities')){
this.graphNetworkComponent.noMaxEntitiesLimit = this.unlimitedMaxEntities;
}
if(queryParametersChanged.includes('unlimitedMaxScope')){
this.graphNetworkComponent.noMaxScopeLimit = this.unlimitedMaxScope;
}
if(this._graphComponentRendered){
console.log('re-rendering graph');
this.reload( this._graphIds );
Expand Down Expand Up @@ -1092,12 +1122,12 @@ export class SzGraphComponent implements OnInit, OnDestroy {
const _ret = this.entityNodecolorsByDataSource;
if( this.queriedEntitiesColor && this.queriedEntitiesColor !== undefined && this.queriedEntitiesColor !== null){
// add special color for active/primary nodes
_ret.push( {
/* _ret.push( {
selectorFn: this.isEntityNodeInQuery.bind(this),
modifierFn: this.setEntityNodeFillColor.bind(this, this.queriedEntitiesColor),
selectorArgs: this.graphIds,
modifierArgs: this.queriedEntitiesColor
} );
} );*/
}
return _ret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from '@senzing/rest-api-client-ng';
import { map, tap, first, takeUntil, take, filter } from 'rxjs/operators';
import { Subject, Observable, BehaviorSubject, forkJoin } from 'rxjs';
import { parseSzIdentifier, parseBool, isValueTypeOfArray } from '../../common/utils';
import { parseSzIdentifier, parseBool, isValueTypeOfArray, areArrayMembersEqual } from '../../common/utils';
import { SzNetworkGraphInputs, SzGraphTooltipEntityModel, SzGraphTooltipLinkModel, SzGraphNodeFilterPair, SzEntityNetworkMatchKeyTokens } from '../../../lib/models/graph';
import { SzSearchService } from '../../services/sz-search.service';

Expand Down Expand Up @@ -426,12 +426,15 @@ export class SzRelationshipNetworkComponent implements AfterViewInit, OnDestroy
this._entityIds = [ value.toString() ];
} else if(value && isValueTypeOfArray(value)) {
// passed string[] or number[].
// we need to always convert to "string[]" or else the
// result wont be what we expect
let _tempArr = (value as unknown as string[]).map((val) => { return val.toString(); });
_changed = this._entityIds != _tempArr;
this._entityIds = _tempArr;
//console.log(`entityIds = ${value}(any[]) | ${_changed}`, this._entityIds, value, (value as unknown as []));
_changed = !areArrayMembersEqual((value as unknown as string[]), this._entityIds);
this._entityIds = (value as unknown as string[]).map((val) => { return val.toString(); });

/*console.log(`entityIds = ${value}(any[]) | ${_changed} from "${_oldIds && _oldIds.join ? _oldIds.join(',') : ''}"`,
_oldIds,
this._entityIds,
new Map( (value as unknown as string[]).map((val) => { return [val.toString(), val]; })),
(value as unknown as [])
);*/
} else if(value) {
// unknown type of value
// I guess we just.... guess??
Expand All @@ -444,7 +447,7 @@ export class SzRelationshipNetworkComponent implements AfterViewInit, OnDestroy
return this._focalEntities.indexOf(parseSzIdentifier(eId)) <= -1;
}).map(parseSzIdentifier) : [];
this._focalEntities = this._focalEntities.concat(uniqueEntityIds);
if(this.reloadOnIdChange && this._entityIds && this._entityIds.some( (eId) => { return _oldIds && _oldIds.indexOf(eId) < 0; })) {
if(this.reloadOnIdChange && _changed && this._entityIds && this._entityIds.some( (eId) => { return _oldIds && _oldIds.indexOf(eId) < 0; })) {
this.reload( this._entityIds.map((eId) => { return parseInt(eId); }) );
}
//console.log('sdk-graph-components/sz-relationship-network.component: entityIds setter( '+_changed+' )', this._entityIds);
Expand Down
6 changes: 6 additions & 0 deletions src/lib/scss/graph.scss
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,12 @@ body {
fill: var(--sz-graph-node-icon-color);
}

&.sz-graph-primary-node {
.sz-graph-icon-enclosure {
fill: var(--sz-graph-primary-entity-color);
}
}

&.graph-node-rel-primary {
.sz-graph-node-icon-colored {
fill: var(--sz-graph-node-icon-color);
Expand Down
21 changes: 19 additions & 2 deletions src/lib/services/sz-css-class.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export class SzCSSClassService {
this.headElement.appendChild(cssEle);
return cssEle.sheet as CSSStyleSheet;
}
/** dynamicall set/create a css class and it's values */
/** dynamically set/create a css class and it's values */
public setStyle(selectorText: string, styleName: string, value: string): void {
let rules: CSSRuleList = this.styleSheet.cssRules.length > 0 || this.styleSheet.rules.length == 0 ? this.styleSheet.cssRules : this.styleSheet.rules;
let ruleIndex: number = Array.from(rules).findIndex(r => r instanceof CSSStyleRule && r.selectorText.toLowerCase() == selectorText.toLowerCase());
Expand All @@ -78,10 +78,27 @@ export class SzCSSClassService {
let newRuleIndex = this.styleSheet.insertRule(selectorText + `{ ${styleName}: ${value}}`, rules.length);
return;
} else {
this.styleSheet.deleteRule(ruleIndex);
if(ruleIndex >= 0) {
this.styleSheet.deleteRule(ruleIndex);
}
this.styleSheet.insertRule(selectorText + `{ ${styleName}: ${value}}`, rules.length);
}
}
/** dynamically remove a css class by selector and */
public removeStyle(selectorText: string, styleName?: string) {
if(!this.styleSheet){ return; }
let rules: CSSRuleList = this.styleSheet.cssRules.length > 0 || this.styleSheet.rules.length == 0 ? this.styleSheet.cssRules : this.styleSheet.rules;
let ruleIndex: number = Array.from(rules).findIndex(r => r instanceof CSSStyleRule && r.selectorText.toLowerCase() == selectorText.toLowerCase());
if(ruleIndex >= 0){
//try{
if(!styleName) {
this.styleSheet.deleteRule(ruleIndex);
} else {
(this.styleSheet.cssRules[ruleIndex] as CSSStyleRule).style.removeProperty(styleName);
}
//} catch(err) {}
}
}
/** dynamically set a css variable on the body element */
public setVariable(variableName: string, value: string) {
if(this.bodyElement && this.bodyElement.style && this.bodyElement.style.setProperty) {
Expand Down
Loading