Skip to content

Commit 82bd109

Browse files
oguzhankoraljsdbroughtondogukankaratas
authored
Feat: visual revamp (#156)
* delete debugger * No need tooltip data as part of interactivity * Fix coloring * delete logging * Fix messaging on interactivity for tooltip data * Delete unused code * Navbar and cursors * Revamp viewer actions * Hide viewer actions * not a css master commit * Toggle projection/orthi * Remove console log * Fix saved objects * Remove console log * Sort performance logging * fix view mode cache * Fix initial isolate issue * Update README.md (#147) * Update README.md * Update README.md * fix typo on conditions * capabilities for object ids * Revert isolating every setDataInput * Fix selection issues * Fix tooltip fckp * Reset filters * Fix reset filter * Ghost hidden on filter * Bring conditional formatting back * Remove ghost hidden context from color card * Disable shadow catcher * Disable camera position persistence for performance reasons * feat (data): sending version and branding info (#157) * get version * adds workspace info * adds hideBranding * adds workspace info --------- Co-authored-by: Oğuzhan Koral <[email protected]> * Enrich receive info from desktop service * test * fix path * fix path again * file version * correct the version with assembly for file version * sanitize tag * Use version from receive info * Fix clipped zoom extend * Workspace name logo * Add can hide branding logic * Fix tooltip for toggle * Fix capabilities for storing branding * Tooltips * Store is ortho in file * Store camera position and target into file according to selected view * Fix loading bar reactivity * Update connector flow * Fix ghost state * Store is ghost in file * Consider ghost value on reset filter * More * excludes rawencoding (#159) * adds null check for personal (#158) * Progress update and error handling * Call pre get before --------- Co-authored-by: Jonathon Broughton <[email protected]> Co-authored-by: Dogukan Karatas <[email protected]>
1 parent 38fb5f7 commit 82bd109

File tree

86 files changed

+3333
-492
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+3333
-492
lines changed

.github/workflows/build_powerbi.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ jobs:
1717
with:
1818
fetch-depth: 0
1919

20+
- name: Set up Python 3.10
21+
uses: actions/setup-python@v3
22+
with:
23+
python-version: "3.10"
24+
2025
- name: Install GitVersion
2126
uses: gittools/actions/gitversion/[email protected]
2227
with:
@@ -26,6 +31,10 @@ jobs:
2631
id: gitversion
2732
uses: gittools/actions/gitversion/[email protected]
2833

34+
- name: Set connector version
35+
run: |
36+
python patch_version.py ${{steps.gitversion.outputs.AssemblySemVer}}
37+
2938
- name: Setup MSBuild
3039
uses: microsoft/setup-msbuild@v2
3140

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ This repo is home to our Power BI connector. The Speckle Server provides all the
3232

3333
# Installation
3434

35-
Speckle connector can be installed directly from [Manager for Speckle](https://speckle.systems/download/). Full instructions for [installation](https://speckle.guide/user/powerbi/installation.html) and [configuration](https://speckle.guide/user/powerbi/configuration.html) can be found on our docs.
35+
Speckle connector can be installed directly from the [connectors portal](https://app.speckle.systems/connectors/). Full instructions for [installation](https://speckle.guide/user/powerbi/installation.html) and [configuration](https://speckle.guide/user/powerbi/configuration.html) can be found on our docs.
3636

3737
# Using 3D Visual
3838

patch_version.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import re
2+
import sys
3+
import os
4+
5+
6+
def sanitize_version(tag):
7+
"""Extracts the first three numeric segments from a tag string, because PowerBI is..."""
8+
parts = re.findall(r"\d+", tag)
9+
return ".".join(parts[:3]) if len(parts) >= 3 else tag
10+
11+
def patch_connector(tag):
12+
"""Patches the connector version within the data connector file"""
13+
sanitized_tag = sanitize_version(tag)
14+
pq_file = os.path.join(os.path.dirname(__file__), "src", "powerbi-data-connector", "Speckle.pq")
15+
16+
with open(pq_file, "r") as file:
17+
lines = file.readlines()
18+
19+
for (index, line) in enumerate(lines):
20+
if '[Version = "3.0.0"]' in line:
21+
lines[index] = f'[Version = "{sanitized_tag}"]\n'
22+
print(f"Patched connector version number in {pq_file}")
23+
break
24+
25+
with open(pq_file, "w") as file:
26+
file.writelines(lines)
27+
28+
29+
def main():
30+
if len(sys.argv) < 2:
31+
return
32+
33+
tag = sys.argv[1]
34+
if not re.match(r"([0-9]+)\.([0-9]+)\.([0-9]+)", tag):
35+
raise ValueError(f"Invalid tag provided: {tag}")
36+
37+
print(f"Patching version: {tag}")
38+
patch_connector(tag)
39+
40+
41+
if __name__ == "__main__":
42+
main()

src/powerbi-data-connector/Speckle.pq

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,23 @@ shared Speckle.GetStructuredData = Value.ReplaceType(
5858
type function (url as Uri.Type) as table
5959
);
6060

61+
shared Speckle.GetVersion = Value.ReplaceType(
62+
Speckle.LoadFunction("GetVersion.pqm"),
63+
type function () as text
64+
);
65+
6166
[DataSource.Kind = "Speckle"]
6267
shared Speckle.SendToServer = Value.ReplaceType(
6368
Speckle.LoadFunction("SendToServer.pqm"),
6469
type function (url as Uri.Type) as table
6570
);
6671

72+
[DataSource.Kind = "Speckle"]
73+
shared Speckle.GetWorkspace = Value.ReplaceType(
74+
Speckle.LoadFunction("GetWorkspace.pqm"),
75+
type function (url as Uri.Type) as record
76+
);
77+
6778
[DataSource.Kind = "Speckle", Publish="GetByUrl.Publish"]
6879
shared Speckle.GetByUrl = Value.ReplaceType(
6980
Speckle.LoadFunction("GetByUrl.pqm"),

src/powerbi-data-connector/Speckle.query.pq

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// NOTE! for tests, be make sure you put here a model that in private project to make sure all good.
44
let
55
result = Speckle.GetByUrl(
6-
"https://latest.speckle.systems/projects/126cd4b7bb/models/85c44d39c6"
6+
"https://app.speckle.systems/projects/b61ab234b0/models/a8166255b5"
77
)
88
in
99
result

src/powerbi-data-connector/speckle/api/GetStructuredData.pqm

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,32 @@
5959
)
6060
),
6161

62+
// Function to check if a row should be excluded based on speckle type
63+
ShouldExcludeRow = (row as record) as logical =>
64+
let
65+
speckleType = Record.FieldOrDefault(row[data], "speckle_type", "")
66+
in
67+
speckleType = "Speckle.Core.Models.DataChunk" or
68+
Text.Contains(speckleType, "Objects.Other.RawEncoding"),
69+
6270
// Filtering logic here
63-
// If, model data contains any DataObject -> fetch only data objects
64-
// If there are no data objects in the data -> fetch everything but DataChunks
71+
// If model data contains any DataObject -> fetch only data objects (excluding unwanted types)
72+
// If there are no data objects in the data -> fetch everything but exclude DataChunks and RawEncoding
6573
HasDataObjects = Table.RowCount(
66-
Table.SelectRows(FinalTable, each Text.Contains(Record.FieldOrDefault([data], "speckle_type", ""), "DataObject"))
74+
Table.SelectRows(
75+
FinalTable,
76+
each Text.Contains(Record.FieldOrDefault([data], "speckle_type", ""), "DataObject")
77+
and not ShouldExcludeRow(_)
78+
)
6779
) > 0,
6880

6981
FilteredTable = if HasDataObjects then
70-
Table.SelectRows(FinalTable, each Text.Contains(Record.FieldOrDefault([data], "speckle_type", ""), "DataObject"))
82+
Table.SelectRows(
83+
FinalTable,
84+
each Text.Contains(Record.FieldOrDefault([data], "speckle_type", ""), "DataObject")
85+
and not ShouldExcludeRow(_)
86+
)
7187
else
72-
Table.SelectRows(FinalTable, each Record.FieldOrDefault([data], "speckle_type", "") <> "Speckle.Core.Models.DataChunk")
88+
Table.SelectRows(FinalTable, each not ShouldExcludeRow(_))
7389
in
7490
FilteredTable
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
() as text =>
2+
let
3+
// read the Speckle.pq file
4+
specklePqContent = try
5+
Text.FromBinary(Extension.Contents("Speckle.pq"))
6+
otherwise
7+
error "Could not read Speckle.pq file",
8+
9+
lines = Text.Split(specklePqContent, "#(lf)"),
10+
11+
versionLine = List.First(
12+
List.Select(
13+
lines,
14+
each Text.Contains(_, "[Version = ")
15+
),
16+
null
17+
),
18+
19+
version = if versionLine <> null then
20+
let
21+
// find the start and end positions of the version string
22+
startPos = Text.PositionOf(versionLine, """") + 1,
23+
tempText = Text.Middle(versionLine, startPos),
24+
endPos = Text.PositionOf(tempText, """"),
25+
versionText = Text.Middle(tempText, 0, endPos)
26+
in
27+
versionText
28+
else
29+
// fallback version if parsing fails
30+
"3.0.0",
31+
32+
// validate version format
33+
isValidVersion =
34+
let
35+
parts = Text.Split(version, "."),
36+
isValid = List.Count(parts) = 3 and
37+
List.AllTrue(List.Transform(parts, each try Number.From(_) >= 0 otherwise false))
38+
in
39+
isValid,
40+
41+
result = if isValidVersion then
42+
version
43+
else
44+
error "Invalid version format found: " & version
45+
in
46+
result
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// function for getting workspace information
2+
(url as text) as record =>
3+
let
4+
ApiFetch = Extension.LoadFunction("Api.Fetch.pqm"),
5+
Parser = Extension.LoadFunction("Parser.pqm"),
6+
7+
// the logic for importing functions from other files
8+
Extension.LoadFunction = (fileName as text) =>
9+
let
10+
binary = Extension.Contents(fileName),
11+
asText = Text.FromBinary(binary)
12+
in
13+
try
14+
Expression.Evaluate(asText, #shared)
15+
catch (e) =>
16+
error
17+
[
18+
Reason = "Extension.LoadFunction Failure",
19+
Message.Format = "Loading '#{0}' failed - '#{1}': '#{2}'",
20+
Message.Parameters = {fileName, e[Reason], e[Message]},
21+
Detail = [File = fileName, Error = e]
22+
],
23+
24+
parsedUrl = Parser(url),
25+
server = parsedUrl[baseUrl],
26+
projectId = parsedUrl[projectId],
27+
28+
// query to get workspace ID from project
29+
projectQuery = "query Project($projectId: String!) {
30+
data:project(id: $projectId) {
31+
workspaceId
32+
}
33+
}",
34+
35+
projectVariables = [
36+
projectId = projectId
37+
],
38+
39+
projectResult = ApiFetch(server, projectQuery, projectVariables),
40+
workspaceId = projectResult[data][workspaceId],
41+
42+
// check if workspaceId is null (personal project)
43+
workspaceInfo = if workspaceId = null then
44+
[
45+
workspaceId = null,
46+
workspaceLogo = null,
47+
workspaceName = null,
48+
canHideBranding = false
49+
]
50+
else
51+
// query workspace only if workspaceId exists
52+
let
53+
workspaceQuery = "query Workspace($workspaceId: String!, $featureName: WorkspaceFeatureName!) {
54+
data:workspace(id: $workspaceId) {
55+
logo
56+
name
57+
hasAccessToFeature(featureName: $featureName)
58+
}
59+
}",
60+
61+
workspaceVariables = [
62+
workspaceId = workspaceId,
63+
featureName = "hideSpeckleBranding"
64+
],
65+
66+
workspaceResult = ApiFetch(server, workspaceQuery, workspaceVariables),
67+
workspace = workspaceResult[data]
68+
in
69+
[
70+
workspaceId = workspaceId,
71+
workspaceLogo = workspace[logo],
72+
workspaceName = workspace[name],
73+
canHideBranding = workspace[hasAccessToFeature]
74+
]
75+
in
76+
workspaceInfo

src/powerbi-data-connector/speckle/api/SendToServer.pqm

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
GetModel = Extension.LoadFunction("GetModel.pqm"),
55
Parser = Extension.LoadFunction("Parser.pqm"),
66
GetUser = Extension.LoadFunction("GetUser.pqm"),
7+
GetVersion = Extension.LoadFunction("GetVersion.pqm"),
8+
GetWorkspace = Extension.LoadFunction("GetWorkspace.pqm"),
9+
710
// the logic for importing functions from other files
811
Extension.LoadFunction = (fileName as text) =>
912
let
@@ -20,18 +23,20 @@
2023
Message.Parameters = {fileName, e[Reason], e[Message]},
2124
Detail = [File = fileName, Error = e]
2225
],
23-
24-
// Get model info and parsed URL
26+
2527
modelInfo = GetModel(url),
2628
parsedUrl = Parser(url),
2729
userInfo = GetUser(url),
28-
29-
// Get API key if available
30+
3031
apiKey = userInfo[Token],
3132

32-
// Get user email from credentials
3333
userEmail = userInfo[UserEmail],
34-
34+
35+
// get version from Speckle.pq - look GetVersion.pqm
36+
connectorVersion = GetVersion(),
37+
38+
workspaceInfo = GetWorkspace(url),
39+
3540
// Prepare request data
3641
requestData = Json.FromValue([
3742
Url = url,
@@ -40,7 +45,12 @@
4045
ProjectId = parsedUrl[projectId],
4146
ObjectId = modelInfo[rootObjectId],
4247
SourceApplication = modelInfo[sourceApplication],
43-
Token = apiKey
48+
Token = apiKey,
49+
Version = connectorVersion,
50+
WorkspaceId = workspaceInfo[workspaceId],
51+
WorkspaceName = workspaceInfo[workspaceName],
52+
WorkspaceLogo = workspaceInfo[workspaceLogo],
53+
CanHideBranding = workspaceInfo[canHideBranding]
4454
]),
4555

4656
// Send request to local server

0 commit comments

Comments
 (0)