fixes the structure of data connector (#91)
This commit is contained in:
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"name": "👀 powerbi-visual",
|
||||
"path": "src/powerbi-visual"
|
||||
"name": "🏠 root",
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"name": "➡️ powerbi-data-connector",
|
||||
"path": "src/powerbi-data-connector"
|
||||
},
|
||||
{
|
||||
"name": "🏠 root",
|
||||
"path": "."
|
||||
"name": "👀 powerbi-visual",
|
||||
"path": "src/powerbi-visual"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
@@ -36,25 +36,19 @@
|
||||
"typings": true,
|
||||
"dist": true,
|
||||
"wepbpack.statistics.dev.html": true,
|
||||
"wepbpack.statistics.html": true,
|
||||
"wepbpack.statistics.html": true
|
||||
},
|
||||
"json.schemas": [
|
||||
{
|
||||
"fileMatch": [
|
||||
"/pbiviz.json"
|
||||
],
|
||||
"fileMatch": ["/pbiviz.json"],
|
||||
"url": "./src/powerbi-visual/node_modules/powerbi-visuals-api/schema.pbiviz.json"
|
||||
},
|
||||
{
|
||||
"fileMatch": [
|
||||
"/capabilities.json"
|
||||
],
|
||||
"fileMatch": ["/capabilities.json"],
|
||||
"url": "./src/powerbi-visual/node_modules/powerbi-visuals-api/schema.capabilities.json"
|
||||
},
|
||||
{
|
||||
"fileMatch": [
|
||||
"/dependencies.json"
|
||||
],
|
||||
"fileMatch": ["/dependencies.json"],
|
||||
"url": "./src/powerbi-visual/node_modules/powerbi-visuals-api/schema.dependencies.json"
|
||||
}
|
||||
]
|
||||
@@ -66,4 +60,4 @@
|
||||
"powerquery.vscode-powerquery-sdk"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
GetStructuredData = Extension.LoadFunction("GetStructuredData.pqm"),
|
||||
GetRawData = Extension.LoadFunction("GetRawData.pqm"),
|
||||
GetModel = Extension.LoadFunction("GetModel.pqm"),
|
||||
|
||||
// the logic for importing functions from other files
|
||||
Extension.LoadFunction = (fileName as text) =>
|
||||
let
|
||||
@@ -36,7 +37,6 @@
|
||||
),
|
||||
|
||||
// add navigation table metadata directly
|
||||
|
||||
tableType = Value.Type(source),
|
||||
newTableType = Type.AddTableKey(tableType, {"Name"}, true) meta [
|
||||
NavigationTable.NameColumn = "Name",
|
||||
@@ -44,7 +44,6 @@
|
||||
Documentation.Name = "Speckle Model"
|
||||
],
|
||||
|
||||
|
||||
// convert to navigation table
|
||||
navTable = Value.ReplaceType(source, newTableType)
|
||||
in
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
// function for getting model information through graphql query
|
||||
(url as text) as record =>
|
||||
let
|
||||
// Import the parser function
|
||||
Parser = Extension.LoadFunction("Parser.pqm"),
|
||||
|
||||
// the logic for importing functions from other files
|
||||
Extension.LoadFunction = (fileName as text) =>
|
||||
let
|
||||
binary = Extension.Contents(fileName),
|
||||
asText = Text.FromBinary(binary)
|
||||
in
|
||||
try
|
||||
Expression.Evaluate(asText, #shared)
|
||||
catch (e) =>
|
||||
error
|
||||
[
|
||||
Reason = "Extension.LoadFunction Failure",
|
||||
Message.Format = "Loading '#{0}' failed - '#{1}': '#{2}'",
|
||||
Message.Parameters = {fileName, e[Reason], e[Message]},
|
||||
Detail = [File = fileName, Error = e]
|
||||
],
|
||||
|
||||
// Get parsed URL components
|
||||
parsedUrl = Parser(url),
|
||||
server = parsedUrl[baseUrl],
|
||||
projectId = parsedUrl[projectId],
|
||||
modelId = parsedUrl[modelId],
|
||||
|
||||
// Get API key if available
|
||||
apiKey = try Extension.CurrentCredential()[Key] otherwise null,
|
||||
|
||||
// GraphQL query to get model info including root object id
|
||||
query = "query ($projectId: String!, $modelId: String!) {
|
||||
project(id: $projectId) {
|
||||
model(id: $modelId) {
|
||||
id
|
||||
name
|
||||
versions {
|
||||
items {
|
||||
id
|
||||
referencedObject
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}",
|
||||
|
||||
variables = [
|
||||
projectId = projectId,
|
||||
modelId = modelId
|
||||
],
|
||||
|
||||
// Make the API request
|
||||
Source = Web.Contents(
|
||||
Text.Combine({server, "graphql"}, "/"),
|
||||
[
|
||||
Headers = [
|
||||
#"Method" = "POST",
|
||||
#"Content-Type" = "application/json",
|
||||
#"Authorization" = if apiKey = null then "" else Text.Format("Bearer #{0}", {apiKey})
|
||||
],
|
||||
ManualStatusHandling = {400, 401, 403},
|
||||
Content = Json.FromValue([
|
||||
query = query,
|
||||
variables = variables
|
||||
])
|
||||
]
|
||||
),
|
||||
|
||||
// Parse the response
|
||||
JsonResponse = Json.Document(Source),
|
||||
|
||||
// Extract needed information
|
||||
result = if Record.HasFields(JsonResponse, {"errors"}) then
|
||||
error JsonResponse[errors]{0}[message]
|
||||
else if JsonResponse[data]?[project]?[model] = null then
|
||||
error "Model not found or access denied. Please check your authentication and model ID."
|
||||
else
|
||||
[
|
||||
modelId = JsonResponse[data][project][model][id],
|
||||
modelName = JsonResponse[data][project][model][name],
|
||||
versionId = JsonResponse[data][project][model][versions][items]{0}[id],
|
||||
rootObjectId = JsonResponse[data][project][model][versions][items]{0}[referencedObject]
|
||||
]
|
||||
in
|
||||
result
|
||||
@@ -1,65 +0,0 @@
|
||||
// function for getting the user info with graphql query
|
||||
let
|
||||
// import the parser function from Parser.pqm file
|
||||
Parser = Extension.LoadFunction("Parser.pqm"),
|
||||
|
||||
// the logic for importing functions from other files
|
||||
Extension.LoadFunction = (fileName as text) =>
|
||||
let
|
||||
binary = Extension.Contents(fileName),
|
||||
asText = Text.FromBinary(binary)
|
||||
in
|
||||
try
|
||||
Expression.Evaluate(asText, #shared)
|
||||
catch (e) =>
|
||||
error
|
||||
[
|
||||
Reason = "Extension.LoadFunction Failure",
|
||||
Message.Format = "Loading '#{0}' failed - '#{1}': '#{2}'",
|
||||
Message.Parameters = {fileName, e[Reason], e[Message]},
|
||||
Detail = [File = fileName, Error = e]
|
||||
]
|
||||
in
|
||||
(url as text) as record =>
|
||||
let
|
||||
// get base server URL using the imported function
|
||||
parsedUrl = Parser(url),
|
||||
server = parsedUrl[baseUrl],
|
||||
|
||||
apiKey = try Extension.CurrentCredential()[Key] otherwise null,
|
||||
|
||||
query = "query {
|
||||
activeUser {
|
||||
email
|
||||
name
|
||||
}
|
||||
serverInfo {
|
||||
name
|
||||
company
|
||||
version
|
||||
}
|
||||
}",
|
||||
Source = Web.Contents(
|
||||
Text.Combine({server, "graphql"}, "/"),
|
||||
[
|
||||
Headers = [
|
||||
#"Method" = "POST",
|
||||
#"Content-Type" = "application/json",
|
||||
#"Authorization" = if apiKey = null then "" else Text.Format("Bearer #{0}", {apiKey})
|
||||
],
|
||||
ManualStatusHandling = {400},
|
||||
Content = Json.FromValue([query = query])
|
||||
]
|
||||
),
|
||||
JsonResponse = Json.Document(Source)
|
||||
in
|
||||
if Record.HasFields(JsonResponse, {"errors"}) then
|
||||
error JsonResponse[errors]{0}[message]
|
||||
else
|
||||
[
|
||||
UserEmail = JsonResponse[data][activeUser][email],
|
||||
UserName = JsonResponse[data][activeUser][name],
|
||||
ServerName = JsonResponse[data][serverInfo][name],
|
||||
ServerCompany = JsonResponse[data][serverInfo][company],
|
||||
ServerVersion = JsonResponse[data][serverInfo][version]
|
||||
]
|
||||
@@ -1,20 +0,0 @@
|
||||
// function for parsing the url into base url, project id and model id
|
||||
(url as text) as record =>
|
||||
let
|
||||
urlParts = Uri.Parts(url),
|
||||
baseUrl = Text.Combine({urlParts[Scheme], "://", urlParts[Host]}),
|
||||
|
||||
pathSegments = List.Select(Text.Split(urlParts[Path], "/"), each _ <> ""),
|
||||
|
||||
// extract project and model IDs if they exist
|
||||
projectId = if List.Count(pathSegments) >= 2 and pathSegments{0} = "projects"
|
||||
then pathSegments{1} else null,
|
||||
|
||||
modelId = if List.Count(pathSegments) >= 4 and pathSegments{2} = "models"
|
||||
then pathSegments{3} else null
|
||||
in
|
||||
[
|
||||
baseUrl = baseUrl,
|
||||
projectId = projectId,
|
||||
modelId = modelId
|
||||
]
|
||||
@@ -1,61 +0,0 @@
|
||||
// function for getting object data
|
||||
(url as text) as table =>
|
||||
let
|
||||
// Import the parser function and getModel
|
||||
Parser = Extension.LoadFunction("Parser.pqm"),
|
||||
GetModel = Extension.LoadFunction("GetModel.pqm"),
|
||||
// the logic for importing functions from other files
|
||||
Extension.LoadFunction = (fileName as text) =>
|
||||
let
|
||||
binary = Extension.Contents(fileName),
|
||||
asText = Text.FromBinary(binary)
|
||||
in
|
||||
try
|
||||
Expression.Evaluate(asText, #shared)
|
||||
catch (e) =>
|
||||
error
|
||||
[
|
||||
Reason = "Extension.LoadFunction Failure",
|
||||
Message.Format = "Loading '#{0}' failed - '#{1}': '#{2}'",
|
||||
Message.Parameters = {fileName, e[Reason], e[Message]},
|
||||
Detail = [File = fileName, Error = e]
|
||||
],
|
||||
|
||||
// Get parsed URL components and model info
|
||||
parsedUrl = Parser(url),
|
||||
server = parsedUrl[baseUrl],
|
||||
modelInfo = GetModel(url),
|
||||
|
||||
// Get API key if available
|
||||
apiKey = try Extension.CurrentCredential()[Key] otherwise null,
|
||||
|
||||
// Make the API request to objects endpoint
|
||||
Source = Web.Contents(
|
||||
Text.Combine({server, "objects", parsedUrl[projectId], modelInfo[rootObjectId]}, "/"),
|
||||
[
|
||||
Headers = [
|
||||
#"Authorization" = if apiKey = null then "" else Text.Format("Bearer #{0}", {apiKey})
|
||||
],
|
||||
ManualStatusHandling = {400, 401, 403}
|
||||
]
|
||||
),
|
||||
|
||||
// Parse the response and return the raw JSON
|
||||
JsonResponse = Json.Document(Source),
|
||||
|
||||
ConvertedToTable = Table.FromList(
|
||||
JsonResponse,
|
||||
Splitter.SplitByNothing(),
|
||||
{"viewer_data"},
|
||||
null,
|
||||
ExtraValues.Error
|
||||
),
|
||||
|
||||
ExpandedTable = Table.AddColumn(
|
||||
ConvertedToTable,
|
||||
"speckle_id",
|
||||
each Record.Field([viewer_data], "id"),
|
||||
type text
|
||||
)
|
||||
in
|
||||
ExpandedTable
|
||||
@@ -1,98 +0,0 @@
|
||||
// Function for getting structured object data
|
||||
(url as text) as table =>
|
||||
let
|
||||
// Import the parser function and getModel
|
||||
Parser = Extension.LoadFunction("Parser.pqm"),
|
||||
GetModel = Extension.LoadFunction("GetModel.pqm"),
|
||||
// the logic for importing functions from other files
|
||||
Extension.LoadFunction = (fileName as text) =>
|
||||
let
|
||||
binary = Extension.Contents(fileName),
|
||||
asText = Text.FromBinary(binary)
|
||||
in
|
||||
try
|
||||
Expression.Evaluate(asText, #shared)
|
||||
catch (e) =>
|
||||
error
|
||||
[
|
||||
Reason = "Extension.LoadFunction Failure",
|
||||
Message.Format = "Loading '#{0}' failed - '#{1}': '#{2}'",
|
||||
Message.Parameters = {fileName, e[Reason], e[Message]},
|
||||
Detail = [File = fileName, Error = e]
|
||||
],
|
||||
|
||||
// Get parsed URL components and model info
|
||||
parsedUrl = Parser(url),
|
||||
server = parsedUrl[baseUrl],
|
||||
modelInfo = GetModel(url),
|
||||
|
||||
// Get API key if available
|
||||
apiKey = try Extension.CurrentCredential()[Key] otherwise null,
|
||||
|
||||
// Make the API request to objects endpoint
|
||||
Source = Web.Contents(
|
||||
Text.Combine({server, "objects", parsedUrl[projectId], modelInfo[rootObjectId]}, "/"),
|
||||
[
|
||||
Headers = [
|
||||
#"Authorization" = if apiKey = null then "" else Text.Format("Bearer #{0}", {apiKey})
|
||||
],
|
||||
ManualStatusHandling = {400, 401, 403}
|
||||
]
|
||||
),
|
||||
|
||||
// Parse the JSON response
|
||||
JsonResponse = Json.Document(Source),
|
||||
|
||||
// Convert list to table
|
||||
ConvertedToTable = Table.FromList(
|
||||
JsonResponse,
|
||||
Splitter.SplitByNothing(),
|
||||
null,
|
||||
null,
|
||||
ExtraValues.Error
|
||||
),
|
||||
|
||||
// Expand initial record
|
||||
ExpandedTable = Table.ExpandRecordColumn(
|
||||
ConvertedToTable,
|
||||
"Column1",
|
||||
{
|
||||
"id",
|
||||
"name",
|
||||
"type",
|
||||
"units",
|
||||
"version",
|
||||
"elements",
|
||||
"profile",
|
||||
"material",
|
||||
"__closure",
|
||||
"properties",
|
||||
"displayValue",
|
||||
"data",
|
||||
"speckle_type",
|
||||
"applicationId",
|
||||
"collectionType",
|
||||
"renderMaterialProxies",
|
||||
"totalChildrenCount"
|
||||
}
|
||||
),
|
||||
|
||||
// Remove rows where applicationId is null
|
||||
FilteredTable = Table.SelectRows(ExpandedTable, each [applicationId] <> null),
|
||||
|
||||
// Create data column by combining all other columns except applicationId and speckle_type
|
||||
FinalTable = Table.FromRecords(
|
||||
List.Transform(
|
||||
Table.ToRecords(FilteredTable),
|
||||
each [
|
||||
speckle_id = [id],
|
||||
speckle_type = [speckle_type],
|
||||
data = Record.RemoveFields(
|
||||
_,
|
||||
{"id", "speckle_type", "collectionType", "displayValue", "totalChildrenCount", "renderMaterialProxies", "data", "__closure"}
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
in
|
||||
FinalTable
|
||||
Reference in New Issue
Block a user