Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9a5c1283ce | |||
| da1f0c7b7e | |||
| 0bb72f0d9d | |||
| 19e64fd4b2 | |||
| 63f286cd0b | |||
| e89ccbbe1a | |||
| f77e315623 |
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"ms-dotnettools.csharp",
|
||||
"powerquery.vscode-powerquery-sdk"
|
||||
]
|
||||
}
|
||||
Vendored
+2
-1
@@ -25,7 +25,8 @@
|
||||
"${workspaceFolder}\\tests",
|
||||
"--prettyPrint"
|
||||
],
|
||||
"problemMatcher": []
|
||||
"problemMatcher": [],
|
||||
"dependsOn": ["build"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
</h1>
|
||||
<h3 align="center">
|
||||
Data Connector for Microsoft's PowerBI platform
|
||||
Expected use case is that this data be used as source for the Speckle Visualization for PowerBI (https://github.com/specklesystems/speckle-powerbi-visuals)
|
||||
</h3>
|
||||
<p align="center"><b>Speckle</b> is the data infrastructure for the AEC industry.</p><br/>
|
||||
|
||||
|
||||
+37
-5
@@ -1,4 +1,4 @@
|
||||
[Version = "2.0.0"]
|
||||
[Version = "2.15.0-rc"]
|
||||
section Speckle;
|
||||
|
||||
AuthAppId = "spklpwerbi";
|
||||
@@ -14,7 +14,9 @@ Speckle = [
|
||||
Label = "Speckle.xyz",
|
||||
StartLogin = (clientApplication, dataSourcePath, state, display) =>
|
||||
let
|
||||
server = Text.Combine({"https://", Uri.Parts(dataSourcePath)[Host]})
|
||||
server = Text.Combine(
|
||||
{Uri.Parts(dataSourcePath)[Scheme], "://", Uri.Parts(dataSourcePath)[Host]}
|
||||
)
|
||||
in
|
||||
[
|
||||
LoginUri = Text.Combine({server, "authn", "verify", AuthAppId, state}, "/"),
|
||||
@@ -25,7 +27,9 @@ Speckle = [
|
||||
],
|
||||
FinishLogin = (clientApplication, dataSourcePath, context, callbackUri, state) =>
|
||||
let
|
||||
server = Text.Combine({"https://", Uri.Parts(dataSourcePath)[Host]}),
|
||||
server = Text.Combine(
|
||||
{Uri.Parts(dataSourcePath)[Scheme], "://", Uri.Parts(dataSourcePath)[Host]}
|
||||
),
|
||||
Parts = Uri.Parts(callbackUri)[Query],
|
||||
Source = Web.Contents(
|
||||
Text.Combine({server, "auth", "token"}, "/"),
|
||||
@@ -53,7 +57,9 @@ Speckle = [
|
||||
],
|
||||
Refresh = (dataSourcePath, refreshToken) =>
|
||||
let
|
||||
server = Text.Combine({"https://", Uri.Parts(dataSourcePath)[Host]}),
|
||||
server = Text.Combine(
|
||||
{Uri.Parts(dataSourcePath)[Scheme], "://", Uri.Parts(dataSourcePath)[Host]}
|
||||
),
|
||||
Source = Web.Contents(
|
||||
Text.Combine({server, "auth", "token"}, "/"),
|
||||
[
|
||||
@@ -159,7 +165,10 @@ shared Speckle.Api.Fetch = Value.ReplaceType(
|
||||
);
|
||||
|
||||
// Parses a stream url and returns a record with the type and values
|
||||
shared Speckle.ParseUrl = Speckle.LoadFunction("ParseStreamUrl.pqm");
|
||||
[DataSource.Kind = "Speckle"]
|
||||
shared Speckle.ParseUrl = Value.ReplaceType(
|
||||
Speckle.LoadFunction("ParseStreamUrl.pqm"), type function (url as Uri.Type) as record
|
||||
);
|
||||
|
||||
// [DataSource.Kind = "Speckle"]
|
||||
// shared Speckle.Api.REST.GetObject = Value.ReplaceType(
|
||||
@@ -191,3 +200,26 @@ shared Speckle.LoadFunction = (fileName as text) =>
|
||||
Message.Parameters = {fileName, e[Reason], e[Message]},
|
||||
Detail = [File = fileName, Error = e]
|
||||
];
|
||||
|
||||
shared Speckle.Revit.Parameters.ToNameValueRecord = (r as record, optional exclude as list) as record =>
|
||||
let
|
||||
defaultExclude = {"id", "speckle_type", "applicationId", "totalChildrenCount"},
|
||||
fullExclusion = if exclude = null then defaultExclude else List.Union(defaultExclude, exclude),
|
||||
clean = Record.RemoveFields(r, fullExclusion, MissingField.Ignore),
|
||||
recTable = Record.ToTable(clean),
|
||||
cleanTable = Table.RemoveColumns(recTable, "Name"),
|
||||
expanded = Table.ExpandRecordColumn(
|
||||
cleanTable, "Value", {"name", "value", "applicationInternalName"}, {"Name", "Value", "UID"}
|
||||
),
|
||||
joined = Table.AddColumn(expanded, "Combo", each [Name] & " [" & [UID] & "]"),
|
||||
renamed = Table.RenameColumns(joined, {{"Name", "x"}, {"Combo", "Name"}}),
|
||||
result = Record.FromTable(renamed)
|
||||
in
|
||||
result;
|
||||
|
||||
shared Speckle.Utils.DynamicColumnExpand = (tbl as table, col as text) as table =>
|
||||
let
|
||||
uniqueFields = List.Distinct(List.Combine(List.Transform(Table.Column(tbl, col), Record.FieldNames))),
|
||||
expanded = Table.ExpandRecordColumn(tbl, col, uniqueFields)
|
||||
in
|
||||
expanded;
|
||||
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
// Use this file to write queries to test your data connector
|
||||
let result = Speckle.GetByUrl("https://latest.speckle.dev/streams/c1faab5c62/commits/aefb7a5fff") in result
|
||||
let result = Speckle.GetByUrl("https://app.speckle.systems/projects/e2988234fb/models/60b2300470@b1f31a351a") in result
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
let
|
||||
Speckle.Api.Fetch = Extension.LoadFunction("Api.Fetch.pqm"),
|
||||
Speckle.Log.Receive = Extension.LoadFunction("Log.Receive.pqm"),
|
||||
Speckle.LogEvent = Extension.LoadFunction("LogEvent.pqm"),
|
||||
Extension.LoadFunction = (fileName as text) =>
|
||||
let
|
||||
binary = Extension.Contents(fileName), asText = Text.FromBinary(binary)
|
||||
@@ -27,7 +27,7 @@ in
|
||||
sourceApplication = "PowerBI"
|
||||
]
|
||||
],
|
||||
s = Speckle.Log.Receive(server, commit)
|
||||
s = Speckle.LogEvent(server, commit)
|
||||
in
|
||||
// Read receipts should fail gracefully no matter what
|
||||
try Speckle.Api.Fetch(s, query, variables)[commitReceive] otherwise false
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
let
|
||||
Speckle.Api.Fetch = Extension.LoadFunction("Api.Fetch.pqm"),
|
||||
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
|
||||
(server as text, projectId as text, modelId as text) =>
|
||||
let
|
||||
query = "query Project($projectId: String!, $modelId: String!) {
|
||||
project(id: $projectId) {
|
||||
model(id: $modelId) {
|
||||
name
|
||||
}
|
||||
}
|
||||
}",
|
||||
variables = [
|
||||
projectId = projectId,
|
||||
modelId = modelId
|
||||
]
|
||||
in
|
||||
// Read receipts should fail gracefully no matter what
|
||||
try Speckle.Api.Fetch(server, query, variables)[project][model] otherwise null
|
||||
@@ -1,4 +1,7 @@
|
||||
let
|
||||
GetApplicationSlug = Extension.LoadFunction("GetApplicationSlug.pqm"),
|
||||
GetUser = Extension.LoadFunction("Api.GetUser.pqm"),
|
||||
Hash = Extension.LoadFunction("Hash.pqm"),
|
||||
Extension.LoadFunction = (fileName as text) =>
|
||||
let
|
||||
binary = Extension.Contents(fileName), asText = Text.FromBinary(binary)
|
||||
@@ -13,12 +16,21 @@ let
|
||||
Detail = [File = fileName, Error = e]
|
||||
]
|
||||
in
|
||||
(server as text, event as text, properties as record) =>
|
||||
(server as text, commit as any) =>
|
||||
let
|
||||
trackUrl = "https://analytics.speckle.systems/track?ip=1",
|
||||
user = GetUser(server),
|
||||
isMultiplayer = user[id] <> commit[authorId],
|
||||
body = [
|
||||
event = event,
|
||||
properties = properties
|
||||
event = "Receive",
|
||||
properties = [
|
||||
server_id = Hash(server),
|
||||
token = "acd87c5a50b56df91a795e999812a3a4",
|
||||
hostApp = "powerbi",
|
||||
sourceHostApp = GetApplicationSlug(commit[sourceApplication]),
|
||||
sourceHostAppVersion = commit[sourceApplication],
|
||||
isMultiplayer = user[id] <> commit[authorId]
|
||||
]
|
||||
],
|
||||
Result = Web.Contents(
|
||||
trackUrl,
|
||||
@@ -1,27 +1,51 @@
|
||||
(url as text) as record =>
|
||||
let
|
||||
// Get server and streamId, and branchName / commitId / objectid from the input url
|
||||
server = Text.Combine({"https://", Uri.Parts(url)[Host]}),
|
||||
segments = Text.Split(Text.AfterDelimiter(Uri.Parts(url)[Path], "/", 0), "/"),
|
||||
streamId = segments{1},
|
||||
branchName = if (List.Count(segments) = 4 and segments{2} = "branches") then segments{3} else null,
|
||||
commitId = if (List.Count(segments) = 4 and segments{2} = "commits") then segments{3} else null,
|
||||
objectId = if (List.Count(segments) = 4 and segments{2} = "objects") then segments{3} else null,
|
||||
urlType =
|
||||
if (commitId <> null) then
|
||||
"Commit"
|
||||
else if (objectId <> null) then
|
||||
"Object"
|
||||
else if (branchName <> null) then
|
||||
"Branch"
|
||||
else
|
||||
"Stream"
|
||||
in
|
||||
[
|
||||
urlType = urlType,
|
||||
server = server,
|
||||
id = streamId,
|
||||
branch = branchName,
|
||||
commit = commitId,
|
||||
object = objectId
|
||||
]
|
||||
let
|
||||
GetModel = Extension.LoadFunction("Api.GetModel.pqm"),
|
||||
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 server and streamId, and branchName / commitId / objectid from the input url
|
||||
server = Text.Combine({Uri.Parts(url)[Scheme], "://", Uri.Parts(url)[Host]}),
|
||||
segments = Text.Split(Text.AfterDelimiter(Uri.Parts(url)[Path], "/", 0), "/"),
|
||||
streamId = segments{1},
|
||||
modelList = if (List.Count(segments) = 4 and segments{2} = "models") then segments{3} else null,
|
||||
firstModel = Text.Split(modelList, ","){0},
|
||||
modelAndVersion = Text.Split(firstModel, "@"),
|
||||
modelId = modelAndVersion{0},
|
||||
versionId = if (List.Count(modelAndVersion) > 1) then modelAndVersion{1} else null,
|
||||
model = if (modelId <> null) then GetModel(server, streamId, modelId) else null,
|
||||
branchName = if (List.Count(segments) = 4 and segments{2} = "branches") then segments{3} else null,
|
||||
commitId = if (List.Count(segments) = 4 and segments{2} = "commits") then segments{3} else null,
|
||||
objectId = if (List.Count(segments) = 4 and segments{2} = "objects") then segments{3} else null,
|
||||
modelOrBranchName = if (model <> null) then model[name] else branchName,
|
||||
commitOrVersion = if (versionId <> null) then versionId else commitId,
|
||||
urlType =
|
||||
if (commitOrVersion <> null) then
|
||||
"Commit"
|
||||
else if (objectId <> null) then
|
||||
"Object"
|
||||
else if (modelOrBranchName <> null) then
|
||||
"Branch"
|
||||
else
|
||||
"Stream"
|
||||
in
|
||||
[
|
||||
urlType = urlType,
|
||||
server = server,
|
||||
id = streamId,
|
||||
branch = modelOrBranchName,
|
||||
commit = commitOrVersion,
|
||||
object = objectId
|
||||
]
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
let
|
||||
GetApplicationSlug = Extension.LoadFunction("GetApplicationSlug.pqm"),
|
||||
GetUser = Extension.LoadFunction("Api.GetUser.pqm"),
|
||||
LogEvent = Extension.LoadFunction("LogEvent.pqm"),
|
||||
Hash = Extension.LoadFunction("Hash.pqm"),
|
||||
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
|
||||
(server as text, commit as text) =>
|
||||
let
|
||||
user = GetUser(server),
|
||||
event = "Receive",
|
||||
properties = [
|
||||
server_id = Hash(server),
|
||||
token = "acd87c5a50b56df91a795e999812a3a4",
|
||||
hostApp = "powerbi",
|
||||
sourceHostApp = GetApplicationSlug(commit[sourceApplication]),
|
||||
sourceHostAppVersion = commit[sourceApplication],
|
||||
isMultiplayer = commit[authorId] <> user[id]
|
||||
]
|
||||
in
|
||||
LogEvent(server, event, properties)
|
||||
Reference in New Issue
Block a user