Compare commits

...

7 Commits

Author SHA1 Message Date
Alan Rynne 9a5c1283ce Adds Frontend2 URL Support for single model urls (#58)
* feat: Adds FE2 Url support for single model urls

* fix: Minor formatting changes
2023-11-09 16:48:36 +01:00
Alan Rynne da1f0c7b7e feat: Added extensions.json (#57) 2023-10-30 10:58:17 +01:00
Alan Rynne 0bb72f0d9d fix: Get back metrics by using old specific Receive log method (#56) 2023-10-30 10:56:04 +01:00
Ryan Haunfelder 19e64fd4b2 Parses the stream URL in a slightly more robust way. (#55) 2023-10-25 11:26:46 +02:00
Alan Rynne 63f286cd0b bump: 2.15.0-rc 2023-07-07 14:54:01 +02:00
Alan Rynne e89ccbbe1a feat: Adds new ToNameValueRecord function for revit params and DynamicExpand for table columns (#49) 2023-07-07 10:35:38 +02:00
garylzimmer f77e315623 Update README.md (#47)
added note about expected use case and link to relevant github
2023-06-14 13:11:13 +02:00
10 changed files with 147 additions and 72 deletions
+6
View File
@@ -0,0 +1,6 @@
{
"recommendations": [
"ms-dotnettools.csharp",
"powerquery.vscode-powerquery-sdk"
]
}
+2 -1
View File
@@ -25,7 +25,8 @@
"${workspaceFolder}\\tests",
"--prettyPrint"
],
"problemMatcher": []
"problemMatcher": [],
"dependsOn": ["build"]
}
]
}
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2 -2
View File
@@ -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
+32
View File
@@ -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,
+51 -27
View File
@@ -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
]
-33
View File
@@ -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)