// $Id$
// @ts-check
'use strict';
import { RestResponse, RestServices } from '../tools/RestServices.js';
import { ApiResponse } from '../tools/ApiResponse.js';
import { Context } from './Context.js';
import { cnObject } from '../gom/cnObject.js';
/**
*
* @category COLNEO infohub
*
* @classdesc
* Node (Version of Object) on COLNEO infohub
*
*/
export class Node extends cnObject {
static className = "Node";
/*
*
* @since 09.2025, jh
*/
constructor() {
super();
}
}
/**
*
* @category COLNEO infohub
*
* @classdesc
* Node Services to get/write objects as tree, etc.
*
*/
export class NodeServices {
#_ctx = null
/**
* @since 1.0, 09.2025, jh
* @param {Context} ctx - Context instance
*
*/
constructor(ctx) {
this.#_ctx = ctx;
}
/**
*
* @param {string} node_sid
* @param {object} params = {
* 'depth'
* 'members'
* 'properties'
* 'geometry'
* 'filter'
* 'nodes'
* 'relations'
* 'relations_right'
* 'groupby'
* 'sortby'
* 'limit'
* 'offset'
* } each parameter has to be encoded as URI component
*
* @example
* {
* 'members': ['info', 'properties', 'relations', 'relations_right'],
* 'filter': '$object_type ~eq~ \'act_issue\'',
* 'depth': 0,
* 'sortby': 'issue:wbs##xs:string',
* 'relations_right': JSON.stringify({
* 'members': ['info', 'properties'],
* 'filter': '$name ~eq~ \'cnSUCCESSORS\'',
* }),
* }
* }
* @param {function} cb
}}
*/
async getTree(node_sid, params, cb) {
let q = ''
let c = '?'
for (const p in params) {
q += `${c}${p}=${encodeURIComponent(params[p])}`
c = '&'
}
let scope = this.#_ctx.getScope()
let path_endpoint = `${this.#_ctx.getServiceUrl(Context.SERVICE.HUB)}/${scope}/nodes/${node_sid}/tree${q}`
console.log(`call [${path_endpoint}]`)
let resp = await RestServices.makeApiCall(this.#_ctx.getToken(), RestServices.METHODS.GET, path_endpoint)
// console.log( "RESPONSE:" )
// console.log( JSON.stringify(resp.getData()) )
return cb(resp)
}
/**
*
* Update node tree.
* Keep existing nodes in parentnode_sid
*
* PUT /{scope}/nodes/{node}/tree
*
* @param {*} parentnode_sid
* @param {*} node_tree
* @param {*} cb
*/
async updateTree(parentnode_sid, node_tree, cb) {
let scope = this.#_ctx.getScope()
let path_endpoint = `${this.#_ctx.getServiceUrl(Context.SERVICE.HUB)}/${scope}/nodes/${parentnode_sid}/tree`
console.log(`call [${path_endpoint}]`)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
let resp = await RestServices.makeApiCall(this.#_ctx.getToken(), RestServices.METHODS.PUT, path_endpoint, node_tree)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return cb(resp)
}
/**
*
* Update/create node tree.
* Replace existing nodes in 'parentnode_sid', if existing nodes are deleted if not in 'node_tree'
*
* POST /{scope}/nodes/{node}/tree
*
* @param {*} parentnode_sid
* @param {*} node_tree
* @param {*} cb
*/
async saveTree(parentnode_sid, node_tree, cb) {
let scope = this.#_ctx.getScope()
let path_endpoint = `${this.#_ctx.getServiceUrl(Context.SERVICE.HUB)}/${scope}/nodes/${parentnode_sid}/tree`
console.log(`call [${path_endpoint}]`)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
let resp = await RestServices.makeApiCall(this.#_ctx.getToken(), RestServices.METHODS.POST, path_endpoint, node_tree)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return cb(resp)
}
/**
*
* @param {*} node_sid
* @param {object} query =
* {
* "as_blob" : true download as file, false if the document should be loaded as json
* }
* @param {*} cb data = {
* "doc" : json or blob
* }
*/
async getDocument(node_sid, query, cb) {
let xhr = new XMLHttpRequest()
xhr.addEventListener("load", function (e) {
if (xhr.status < 300) {
let ret = null
let fn = xhr.getResponseHeader('x-filename')
if (query.as_blob == true) {
// let fn = xhr.getResponseHeader('x-filename')
let r = {
'doc': xhr.response,
"filename": fn
}
return cb(new ApiResponse(200, r))
}
// console.log( 'JSON DOC : ')
// console.log( xhr.responseText)
try {
ret = JSON.parse(xhr.responseText)
} catch (e) {
console.log("ERROR")
return cb(new ApiResponse(500, null))
}
if (ret == '') {
console.log("DOC IS EMPTY")
return cb(new ApiResponse(400, null, "DOC IS EMPTY"))
}
let r = {
'doc': ret,
"filename": fn
}
return cb(new ApiResponse(200, r))
} else {
console.log("status : " + xhr.status)
return cb(new ApiResponse(xhr.status, null))
}
}, false)
xhr.addEventListener("error", function (e) {
console.log(JSON.stringify(e))
return cb(new ApiResponse(500, null))
})
// #########################################################################################################
const target = `${this.#_ctx.getServiceUrl(Context.SERVICE.HUB)}/${this.#_ctx.getScope()}/nodes/${node_sid}`
// #########################################################################################################
// console.log("GET : " + target)
xhr.open("GET", target)
xhr.setRequestHeader('Authorization', 'Bearer ' + this.#_ctx.getToken())
xhr.setRequestHeader('Accept', 'application/object')
if (query.as_blob == true) xhr.responseType = "blob"
xhr.send()
}
/**
*
* Get path of node hierarchy from root to node.
*
* @param {*} node_sid
* @param {*} query
* @param {*} cb
* @returns {Promise<ApiResponse>}
*/
async getNodePath(node_sid, query, cb) {
let q = ''
let c = '?'
if (query['members']) {
let plist = query['members'].join(',')
q += c + 'members=' + encodeURIComponent(plist)
c = '&'
}
const url = `${this.#_ctx.getServiceUrl(Context.SERVICE.HUB)}/${this.#_ctx.getScope()}/nodes/${node_sid}/path/data${q}`;
console.log(`GET : ${url}`)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* RestResponse */ const resp = await RestServices.makeApiCall(this.#_ctx.getToken(), RestServices.METHODS.GET, url)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (resp.status < 300) {
let array = []
for (const obj_json of resp.data) {
let obj = new cnObject()
obj.setFromJson(obj_json)
array.push(obj)
}
return cb(new ApiResponse(resp.status, array))
} else {
return cb(resp)
}
}
/**
*
* @param {*} node_sid
* @param {*} query
* @param {*} cb
* @returns {Promise<RestResponse>}
*/
async getNodeData(node_sid, query, cb ) {
let q = ''
let c = '?'
if (query.members) {
let mstr = query.members.join(',')
q += `${c}members=` + encodeURIComponent(mstr)
c = '&'
}
if (query.properties) {
let pstr = query.properties.join(',')
q += `${c}properties=` + encodeURIComponent(pstr)
c = '&'
}
const url = `${this.#_ctx.getServiceUrl(Context.SERVICE.HUB)}/${this.#_ctx.getScope()}/nodes/${node_sid}/data${q}`;
console.log(`target: [${url}]`)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* RestResponse */ const resp = await RestServices.makeApiCall(this.#_ctx.getToken(), RestServices.METHODS.GET, url)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
return cb(resp)
}
}
Source