mirror of
https://github.com/datahub-project/datahub.git
synced 2025-07-29 12:30:07 +00:00
86 lines
3.0 KiB
TypeScript
86 lines
3.0 KiB
TypeScript
import Component from '@ember/component';
|
|
import { task, Task } from 'ember-concurrency';
|
|
import { LineageList, IDatasetLineage } from 'wherehows-web/typings/api/datasets/relationships';
|
|
import { readDownstreamDatasetsByUrn, readUpstreamDatasetsByUrn } from 'wherehows-web/utils/api/datasets/lineage';
|
|
import { containerDataSource } from '@datahub/utils/api/data-source';
|
|
import GraphDb, { INode } from 'wherehows-web/utils/graph-db';
|
|
import { action } from '@ember/object';
|
|
import { ETaskPromise } from '@datahub/utils/types/concurrency';
|
|
import { IDatasetEntity } from '@datahub/metadata-types/types/entity/dataset/dataset-entity';
|
|
|
|
/**
|
|
* Container component for the lineage graph. Will use upstream and downstream to generate the graph
|
|
*/
|
|
@containerDataSource<DatasetRelationshipLevels>('firstLoadTask', ['dataset'])
|
|
export default class DatasetRelationshipLevels extends Component {
|
|
/**
|
|
* GraphDb will be the one contain the nodes and edges. It will help us to generate the graph
|
|
*/
|
|
graphDb: GraphDb<IDatasetLineage> = GraphDb.create({
|
|
uniqueKeys: ['dataset.uri']
|
|
}) as GraphDb<IDatasetLineage>;
|
|
|
|
/**
|
|
* This is the dataset that we need to show upstream and downstream data
|
|
*/
|
|
dataset!: IDatasetEntity;
|
|
|
|
/**
|
|
* This task will fetch lineage data for a node. If a node is downtream, it will load children
|
|
* If the node is upstream, it will fetch its parents.
|
|
* @param id
|
|
* @param upstream
|
|
*/
|
|
@task(function*(
|
|
this: DatasetRelationshipLevels,
|
|
id: number,
|
|
upstream: boolean = false
|
|
): IterableIterator<Promise<LineageList>> {
|
|
const currentNode = this.graphDb.nodesById[id];
|
|
if (currentNode) {
|
|
const method = upstream ? readUpstreamDatasetsByUrn : readDownstreamDatasetsByUrn;
|
|
const nodes: Array<IDatasetLineage> = yield method(
|
|
(currentNode.payload && currentNode.payload.dataset.uri) || ''
|
|
);
|
|
nodes.forEach((node): INode<IDatasetLineage> => this.graphDb.addNode(node, currentNode, upstream));
|
|
this.graphDb.setNodeAttrs(id, {
|
|
loaded: true
|
|
});
|
|
}
|
|
})
|
|
getLineageDataTask: Task<Promise<LineageList>, (a: number, b?: boolean) => Promise<LineageList>>;
|
|
|
|
/**
|
|
* It will create the first node using the dataset passed, and invoke upstream and downstream tasks
|
|
*/
|
|
@task(function*(this: DatasetRelationshipLevels): IterableIterator<Promise<LineageList>> {
|
|
const rootNode = this.graphDb.addNode({
|
|
dataset: this.dataset,
|
|
type: '',
|
|
actor: ''
|
|
});
|
|
|
|
yield this.getLineageDataTask.perform(rootNode.id, false);
|
|
|
|
yield this.getLineageDataTask.perform(rootNode.id, true);
|
|
|
|
//select first node
|
|
this.graphDb.setNodeAttrs(rootNode.id, {
|
|
selected: true
|
|
});
|
|
})
|
|
firstLoadTask!: ETaskPromise<LineageList>;
|
|
|
|
/**
|
|
* When we select a node, we need to toggle it and load it if necessary
|
|
* @param node
|
|
*/
|
|
@action
|
|
toggleNode(node: INode<IDatasetLineage>): void {
|
|
this.graphDb.toggle(node.id);
|
|
if (!node.loaded) {
|
|
this.getLineageDataTask.perform(node.id, node.level < 0);
|
|
}
|
|
}
|
|
}
|