Skip to content

Commit

Permalink
feat(tree): allow attribute paths as input (#562)
Browse files Browse the repository at this point in the history
ref #534
  • Loading branch information
ingeridhellen authored Sep 29, 2023
1 parent c3d1231 commit 6a842e3
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const DestinationPicker = (props: TDestinationPickerProps) => {
useEffect(() => {
setLoading(true)
if (scope) {
tree.initFromFolder(scope).finally(() => setLoading(false))
tree.initFromPath(scope).finally(() => setLoading(false))
} else {
tree
.initFromDataSources(appConfig.visibleDataSources)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const EntityPickerDialog = (props: {
useEffect(() => {
setLoading(true)
if (scope) {
tree.initFromFolder(scope).finally(() => setLoading(false))
tree.initFromPath(scope).finally(() => setLoading(false))
} else {
tree
.initFromDataSources(appConfig.visibleDataSources)
Expand Down
162 changes: 93 additions & 69 deletions packages/dm-core/src/domain/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { EBlueprint } from '../Enums'
import { useDMSS } from '../context/DMSSContext'
import { DmssAPI } from '../services'
import { TAttribute, TBlueprint, TPackage } from '../types'
import { splitAddress } from '../utils/addressUtilities'

type TTreeMap = {
[nodeId: string]: TreeNode
Expand Down Expand Up @@ -73,7 +72,7 @@ const createFolderChildren = (
}

const updateRootPackagesInTree = (
rootPackages: TPackage[],
rootPackages: { [key: string]: TPackage },
tree: Tree,
dataSource: string
) => {
Expand Down Expand Up @@ -113,7 +112,7 @@ export class TreeNode {
isDataSource: boolean = false
entity: any
name?: string
message: string = ''
message: string

constructor(
tree: Tree,
Expand All @@ -124,7 +123,8 @@ export class TreeNode {
name: string | undefined = undefined,
isRoot = false,
isDataSource = false,
children: TTreeMap = {}
children: TTreeMap = {},
message: string = ''
) {
this.tree = tree
this.nodeId = nodeId
Expand All @@ -136,6 +136,7 @@ export class TreeNode {
this.name = name
this.type = type
this.children = children
this.message = message
}

// Fetches the unresolved document of the node
Expand Down Expand Up @@ -262,78 +263,101 @@ export class Tree {
this.updateCallback = updateCallback
}

async initFromDataSources(dataSources: string[]) {
async initFromDataSources(dataSources?: string[]) {
// Add the dataSources as the top-level nodes
dataSources.forEach((dataSourceId: string) => {
this.index[dataSourceId] = new TreeNode(
this,
dataSourceId,
{ name: dataSourceId, type: 'dataSource' },
'dataSource',
undefined,
dataSourceId,
false,
true
)
})
const allDataSources = await this.dmssApi
.dataSourceGetAll()
.then((response) => response.data)
const validDataSources = dataSources
? allDataSources.filter((ds) => dataSources.includes(ds.name))
: allDataSources
validDataSources.forEach(
(ds) =>
(this.index[ds.id] = new TreeNode(
this,
ds.id,
{ name: ds.name, type: 'dataSource' },
'dataSource',
undefined,
ds.name,
false,
true
))
)
const invalidDataSources = dataSources?.filter((ds) =>
allDataSources.every((x) => x.id !== ds)
)
invalidDataSources?.forEach(
(ds) =>
(this.index[ds] = new TreeNode(
this,
ds,
{ name: ds, type: 'dataSource' },
'error',
undefined,
ds,
false,
true,
{},
`${ds} does not exist`
))
)
this.updateCallback(this)
}

/**
* Initialize the Tree view from a given folder.
* Initialize the Tree view from a given path.
*
* @param path: Define scope for tree view. The path can point to either a package, a document or a complex attribute.
*
* @param folderPath: Define scope for tree view. The folderPath must be on the format: <DataSource>/<rootPackage>/<pathToFolder> and be an address to an entity of type Package.
* The folder specified by folderPath and all subfolders of folderPath will be included, but not anything else.
* The object specified by path and all subfolders of path will be included, but not anything else.
*/
async initFromFolder(folderPath: string) {
const { dataSource } = splitAddress(folderPath)
this.dmssApi
.documentGet({ address: folderPath })
.then((response: any) => {
const data = response.data
if (data['type'] !== EBlueprint.PACKAGE) {
throw new Error(
`Tried to initialize the tree from a path '${folderPath}' that does not refer to a package.`
)
}

const folderNode = new TreeNode(
this,
`${dataSource}/$${data._id}`,
data,
data.type,
undefined,
data?.name || data._id,
true,
false
)
folderNode.expand()
if (data.type !== EBlueprint.PACKAGE)
throw new Error('Path does not resolve to a package')

folderNode.children = createFolderChildren(data, folderNode)
this.index = { [`${dataSource}/$${data._id}`]: folderNode }
})
.catch((error: Error) => {
const folderNode = new TreeNode(
this,
folderPath,
{
type: EBlueprint.PACKAGE,
name: 'failed',
description: error.message,
},
EBlueprint.PACKAGE,
undefined,
'unknown',
true,
false
)
folderNode.type = 'error'
folderNode.message = error.message
this.index = { [folderPath]: folderNode }
})
.finally(() => this.updateCallback(this))
async initFromPath(path: string) {
const exists = (await this.dmssApi.documentCheck({ address: path })).data
const data: any = exists
? (await this.dmssApi.documentGet({ address: path })).data
: undefined
const isEmpty =
data == undefined || (Array.isArray(data) && data.length == 0)
let node: TreeNode
if (isEmpty) {
node = new TreeNode(
this,
path,
{},
'error',
undefined,
path,
true,
false,
{},
`${path} ${data == undefined ? 'does not exist' : 'is empty'}`
)
} else if (Array.isArray(data)) {
node = new TreeNode(
this,
path,
data,
data[0].type,
undefined,
path,
false,
false
)
} else {
node = new TreeNode(
this,
path,
data,
data.type,
undefined,
data?.name || data._id,
data?.isRoot ?? false,
false
)
}
this.index[path] = node
this.updateCallback(this)
}

// "[Symbol.iterator]" is similar to "__next__" in a python class.
Expand Down

0 comments on commit 6a842e3

Please sign in to comment.