@myrmidon/cadmus-graph-ui-ex
Version:
Cadmus - extensions to semantic graph components.
495 lines (487 loc) • 19.3 kB
TypeScript
import * as _angular_core from '@angular/core';
import { OnInit, OnDestroy, PipeTransform } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { Node, Edge, NgxGraphZoomOptions } from '@swimlane/ngx-graph';
import { DialogService } from '@myrmidon/ngx-mat-tools';
import { LinkedNodeFilter, LinkedLiteralFilter, TripleFilter, NodeSourceType, GraphService, UriNode } from '@myrmidon/cadmus-api';
import { FormControl, FormGroup, FormBuilder } from '@angular/forms';
import { PageEvent } from '@angular/material/paginator';
import { GraphNodeLookupService } from '@myrmidon/cadmus-graph-ui';
interface PagedTripleFilter extends TripleFilter {
pageNumber: number;
pageSize: number;
}
interface PagedLinkedLiteralFilter extends LinkedLiteralFilter {
pageNumber: number;
pageSize: number;
}
interface PagedLinkedNodeFilter extends LinkedNodeFilter {
pageNumber: number;
pageSize: number;
}
/**
* Essential graph walker data.
*/
interface WalkerData {
originId: string;
customColor?: string;
hidden?: boolean;
}
/**
* Graph walker widget data, i.e. a node or a property group.
*/
interface WalkerWidgetData extends WalkerData {
selected?: boolean;
expanded?: boolean;
error?: string;
}
/**
* Graph walker node data.
* ID: "N" + nodeid (e.g. "N3").
*/
interface WalkerNodeData extends WalkerWidgetData {
uri: string;
sourceType: NodeSourceType;
isClass?: boolean;
sid?: string;
tag?: string;
outFilter: PagedTripleFilter;
inFilter: PagedTripleFilter;
outTotal?: number;
inTotal?: number;
}
/**
* Graph walker property group data.
* ID: "P" + propertyid + "N" + source nodeid ("P2N3").
*/
interface WalkerPropData extends WalkerWidgetData {
uri: string;
outFilter: PagedLinkedNodeFilter;
inFilter: PagedLinkedNodeFilter;
litFilter: PagedLinkedLiteralFilter;
outTotal?: number;
inTotal?: number;
litTotal?: number;
}
/**
* Graph walker literal node data.
* ID: "L" + tripleid (e.g. "L5").
*/
interface WalkerLitData extends WalkerWidgetData {
value: string;
type?: string;
language?: string;
number?: number;
}
/**
* The total counts of items fetched by each children graph nodes filter.
*/
interface NodeChildTotals {
pOut: number;
pIn: number;
pLit: number;
nOut: number;
nIn: number;
}
/**
* Graph walker.
* This class encapsulates data used for interactively exploring a graph
* starting from a designated origin node.
*/
declare class GraphWalker {
private _graphService;
private readonly _nodes$;
private readonly _edges$;
private readonly _loading$;
private readonly _error$;
private _rootNode?;
private readonly _selectedNode$;
private readonly _pOutFilter$;
private readonly _pInFilter$;
private readonly _pLitFilter$;
private readonly _nOutFilter$;
private readonly _nInFilter$;
private readonly _childTotals$;
/**
* The page size. Default is 10.
*/
pageSize: number;
/**
* Max length of literal value to show. Default is 30.
*/
maxLiteralLen: number;
/**
* The nodes of the walker graph, which can represent nodes, literals,
* or property groups. You can easily determine the type of each node
* by looking at the first character of its id (N=node, L=literal,
* P=property).
*/
get nodes$(): Observable<Node[]>;
/**
* The edges connecting nodes.
*/
get edges$(): Observable<Edge[]>;
/**
* True if the walker is loading data.
*/
get loading$(): Observable<boolean>;
/**
* The last error occurred in communicating with the server, if any.
*/
get error$(): Observable<string | null>;
/**
* The selected node. Only one node at a time can be selected.
*/
get selectedNode$(): Observable<Node | null>;
/**
* The outbound linked nodes filter for the selected P node.
*/
get pOutFilter$(): Observable<PagedLinkedNodeFilter | null>;
/**
* The inbound linked nodes filter for the selected P node.
*/
get pInFilter$(): Observable<PagedLinkedNodeFilter | null>;
/**
* The literal linked nodes filter for the selected P node.
*/
get pLitFilter$(): Observable<PagedLinkedLiteralFilter | null>;
/**
* The outbound triples filter for the selected N node.
*/
get nOutFilter$(): Observable<PagedTripleFilter | null>;
/**
* The inbound triples filter for the selected N node.
*/
get nInFilter$(): Observable<PagedTripleFilter | null>;
/**
* The total items fetched for each filter of the selected node.
*/
get childTotals$(): Observable<NodeChildTotals>;
constructor(_graphService: GraphService);
getSelectedNode(): Node | null;
private toggleLoading;
private setError;
private buildNodeId;
/**
* Get the numeric ID of the data node being the source of the graph node
* with the specified ID.
*
* @param id The graph node ID (...N + its data node numeric ID)
* @returns The data node numeric ID.
*/
private getNodeNumericId;
private getPredicateNumericId;
private buildEdgeId;
private buildPropertyId;
private buildLiteralId;
private scale;
private addEdgeIfAbsent;
private resetFilters;
/**
* Select the specified node. This also implies updating all the current
* filters, which depend on the selected node.
*
* @param id The node ID or null to deselect the selected node.
*/
selectNode(id: string | null): void;
/**
* Reset the graph setting its origin to the specified node.
*
* @param id The ID of the origin node to start from ("root origin").
*/
reset(id: number): void;
/**
* Get the source and target graph nodes IDs from the specified edge ID.
*
* @param edgeId The ID of the edge graph node.
* @returns IDs of the source and target graph nodes.
*/
private getEdgeEndIds;
/**
* Remove all the nodes with the specified origin node ID.
*
* @param originId The ID of the origin graph node.
* @param nodes The nodes array to remove nodes from.
* @param removedIds The IDs of all the removed nodes.
*/
private removeDescendantNodes;
/**
* Remove all the children graph nodes of the specified origin graph node.
*
* @param originId The ID of the origin graph node.
* @param nodes The nodes array to remove nodes from.
* @param edges The edges array to remove edges from.
*/
private removeChildren;
/**
* Build a new graph node representing a property.
*
* @param sourceId The source node ID.
* @param group The triple group emitting this node.
* @returns A new graph node.
*/
private buildPropertyNode;
/**
* Expand the specified node, by loading its property groups.
*
* @param node The node to expand.
* @param outFilter The properties to update for the output filter.
* @param inFilter The properties to update for the input filter.
*/
expandNode(node: Node, outFilter?: Partial<PagedTripleFilter> | null, inFilter?: Partial<PagedTripleFilter> | null): void;
/**
* Expand the selected node, by loading its property groups.
*
* @param outFilter The properties to update for the output filter.
* @param inFilter The properties to update for the input filter.
*/
expandSelectedNode(outFilter?: Partial<PagedTripleFilter> | null, inFilter?: Partial<PagedTripleFilter> | null): void;
private buildLiteralLabel;
private buildNonLiteralNode;
private buildLiteralNode;
/**
* Expand the currently selected properties group node, by loading its
* outbound nodes, inbound nodes, and literal nodes.
*
* @param node The property group node to expand.
* @param outFilter The properties to update for the outbound nodes filter.
* @param inFilter The properties to update for the inbound nodes filter.
* @param litFilter The properties to update for the literal nodes filter.
*/
expandProperty(node: Node, outFilter?: Partial<PagedLinkedNodeFilter> | null, inFilter?: Partial<PagedLinkedNodeFilter> | null, litFilter?: Partial<PagedLinkedLiteralFilter> | null): void;
/**
* Expand the currently selected properties group node, by loading its
* outbound nodes, inbound nodes, and literal nodes. If there is no
* selection, or the selected node is not a properties group node, nothing
* is done.
*
* @param outFilter The properties to update for the outbound nodes filter.
* @param inFilter The properties to update for the inbound nodes filter.
* @param litFilter The properties to update for the literal nodes filter.
*/
expandSelectedProperty(outFilter?: Partial<PagedLinkedNodeFilter> | null, inFilter?: Partial<PagedLinkedNodeFilter> | null, litFilter?: Partial<PagedLinkedLiteralFilter> | null): void;
/**
* Toggle the specified node by expanding or collapsing it.
*
* @param node The node to toggle.
*/
toggleNode(node: Node): void;
}
/**
* Graph walker component. This starts from a given node, and let users
* walk along edges to discover new nodes.
*/
declare class GraphWalkerComponent implements OnInit, OnDestroy {
private _dialog;
private _sub?;
private readonly _walker;
/**
* The root origin node ID.
*/
readonly nodeId: _angular_core.InputSignal<number>;
/**
* True if user can pick a node from the graph.
*/
readonly canPick: _angular_core.InputSignal<boolean | undefined>;
/**
* True if user can move to the source of a picked node when
* shift-clicking it.
*/
readonly canMoveToSource: _angular_core.InputSignal<boolean | undefined>;
/**
* Emitted when a graph node is picked by user.
*/
readonly nodePick: _angular_core.OutputEmitterRef<Node>;
/**
* Emitted when the user requests to move to the source of a picked node.
*/
readonly moveToSource: _angular_core.OutputEmitterRef<Node>;
nodes$: Observable<Node[]>;
edges$: Observable<Edge[]>;
loading$: Observable<boolean>;
error$: Observable<string | null>;
selectedNode$: Observable<Node | null>;
pOutFilter$: Observable<PagedLinkedNodeFilter | null>;
pInFilter$: Observable<PagedLinkedNodeFilter | null>;
pLitFilter$: Observable<PagedLinkedLiteralFilter | null>;
nOutFilter$: Observable<PagedTripleFilter | null>;
nInFilter$: Observable<PagedTripleFilter | null>;
childTotals$: Observable<NodeChildTotals>;
update$: Subject<boolean>;
center$: Subject<boolean>;
zoomToFit$: Subject<NgxGraphZoomOptions>;
constructor(graphService: GraphService, _dialog: DialogService);
ngOnInit(): void;
ngOnDestroy(): void;
onNodeSelect(node: Node): void;
private reset;
onReset(): void;
onNodeDblClick(node: Node): void;
onPOutFilterChange(filter: PagedLinkedNodeFilter): void;
onPInFilterChange(filter: PagedLinkedNodeFilter): void;
onPLitFilterChange(filter: PagedLinkedLiteralFilter): void;
onNOutFilterChange(filter: PagedTripleFilter): void;
onNInFilterChange(filter: PagedTripleFilter): void;
pickSelectedNode(event: MouseEvent): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<GraphWalkerComponent, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<GraphWalkerComponent, "cadmus-graph-walker", never, { "nodeId": { "alias": "nodeId"; "required": false; "isSignal": true; }; "canPick": { "alias": "canPick"; "required": false; "isSignal": true; }; "canMoveToSource": { "alias": "canMoveToSource"; "required": false; "isSignal": true; }; }, { "nodePick": "nodePick"; "moveToSource": "moveToSource"; }, never, never, true, never>;
}
/**
* Linked literal filter.
*/
declare class LinkedLiteralFilterComponent {
lookupService: GraphNodeLookupService;
private _graphService;
/**
* True if this component is disabled.
*/
readonly disabled: _angular_core.InputSignal<boolean | undefined>;
/**
* True if this component should show a pager.
*/
readonly hasPager: _angular_core.InputSignal<boolean | undefined>;
/**
* The total number of triples returned from the last
* page fetch operation. Used when hasPager is true.
*/
readonly total: _angular_core.InputSignal<number>;
/**
* The filter.
*/
readonly filter: _angular_core.ModelSignal<PagedLinkedLiteralFilter>;
pageNumber: FormControl<number>;
pageSize: FormControl<number>;
litPattern: FormControl<string | null>;
litType: FormControl<string | null>;
litLanguage: FormControl<string | null>;
minLitNumber: FormControl<number | null>;
maxLitNumber: FormControl<number | null>;
subj: FormControl<UriNode | null>;
pred: FormControl<UriNode | null>;
form: FormGroup;
constructor(formBuilder: FormBuilder, lookupService: GraphNodeLookupService, _graphService: GraphService);
private updateForm;
private getFilter;
onSubjectNodeChange(node: unknown): void;
onPredicateNodeChange(node: unknown): void;
onPageChange(page: PageEvent): void;
reset(): void;
apply(): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<LinkedLiteralFilterComponent, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<LinkedLiteralFilterComponent, "cadmus-walker-linked-literal-filter", never, { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "hasPager": { "alias": "hasPager"; "required": false; "isSignal": true; }; "total": { "alias": "total"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; }, { "filter": "filterChange"; }, never, never, true, never>;
}
/**
* Linked non-literal node filter.
*/
declare class LinkedNodeFilterComponent {
lookupService: GraphNodeLookupService;
private _graphService;
/**
* True if this component is disabled.
*/
readonly disabled: _angular_core.InputSignal<boolean | undefined>;
/**
* True if this component should show a pager.
*/
readonly hasPager: _angular_core.InputSignal<boolean>;
/**
* The total number of nodes returned from the last
* page fetch operation. Used when hasPager is true.
*/
readonly total: _angular_core.InputSignal<number>;
/**
* The filter.
*/
readonly filter: _angular_core.ModelSignal<PagedLinkedNodeFilter>;
otherNodeId: number;
predicateId: number;
isObject: boolean;
pageNumber: FormControl<number>;
pageSize: FormControl<number>;
uid: FormControl<string | null>;
isClass: FormControl<boolean | null>;
tag: FormControl<string | null>;
label: FormControl<string | null>;
sourceType: FormControl<NodeSourceType | null>;
sid: FormControl<string | null>;
isSidPrefix: FormControl<boolean>;
classes: FormControl<UriNode[]>;
form: FormGroup;
constructor(formBuilder: FormBuilder, lookupService: GraphNodeLookupService, _graphService: GraphService);
private updateForm;
private getFilter;
onPageChange(page: PageEvent): void;
onClassAdd(node: unknown): void;
onClassRemove(node: UriNode): void;
reset(): void;
apply(): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<LinkedNodeFilterComponent, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<LinkedNodeFilterComponent, "cadmus-walker-linked-node-filter", never, { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "hasPager": { "alias": "hasPager"; "required": false; "isSignal": true; }; "total": { "alias": "total"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; }, { "filter": "filterChange"; }, never, never, true, never>;
}
/**
* Triples filter.
*/
declare class TripleFilterComponent {
lookupService: GraphNodeLookupService;
private _graphService;
/**
* True if this component is disabled.
*/
readonly disabled: _angular_core.InputSignal<boolean>;
/**
* True if this component should show a pager.
*/
readonly hasPager: _angular_core.InputSignal<boolean>;
/**
* The total number of triples returned from the last
* page fetch operation. Used when hasPager is true.
*/
readonly total: _angular_core.InputSignal<number>;
/**
* The filter.
*/
readonly filter: _angular_core.ModelSignal<PagedTripleFilter>;
pageNumber: FormControl<number>;
pageSize: FormControl<number>;
litPattern: FormControl<string | null>;
litType: FormControl<string | null>;
litLanguage: FormControl<string | null>;
minLitNumber: FormControl<number | null>;
maxLitNumber: FormControl<number | null>;
subj: FormControl<UriNode | null>;
isNotPred: FormControl<boolean>;
preds: FormControl<UriNode[]>;
notPreds: FormControl<UriNode[]>;
hasLiteralObj: FormControl<boolean | null>;
obj: FormControl<UriNode | null>;
sid: FormControl<string | null>;
isSidPrefix: FormControl<boolean>;
tag: FormControl<string | null>;
form: FormGroup;
constructor(formBuilder: FormBuilder, lookupService: GraphNodeLookupService, _graphService: GraphService);
private updateForm;
private getFilter;
onPageChange(page: PageEvent): void;
onSubjectNodeChange(node: unknown): void;
onObjectNodeChange(node: unknown): void;
onPredicateNodeChange(node: unknown): void;
deleteNotPred(node: UriNode): void;
deletePred(node: UriNode): void;
reset(): void;
apply(): void;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TripleFilterComponent, never>;
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TripleFilterComponent, "cadmus-walker-triple-filter", never, { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "hasPager": { "alias": "hasPager"; "required": false; "isSignal": true; }; "total": { "alias": "total"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; }, { "filter": "filterChange"; }, never, never, true, never>;
}
/**
* Get the extended label for the specified graph node. This returns the label
* for N nodes, and the uri + "=" + the label for P nodes. That's because P
* nodes label is just the count of the triples group, so the predicate ID is
* got from the property node's data uri.
*/
declare class GraphNodeLabelPipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown;
static ɵfac: _angular_core.ɵɵFactoryDeclaration<GraphNodeLabelPipe, never>;
static ɵpipe: _angular_core.ɵɵPipeDeclaration<GraphNodeLabelPipe, "graphNodeLabel", true>;
}
export { GraphNodeLabelPipe, GraphWalker, GraphWalkerComponent, LinkedLiteralFilterComponent, LinkedNodeFilterComponent, TripleFilterComponent };
export type { NodeChildTotals, PagedLinkedLiteralFilter, PagedLinkedNodeFilter, PagedTripleFilter, WalkerData, WalkerLitData, WalkerNodeData, WalkerPropData, WalkerWidgetData };