Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ff7db38b8d | |||
| 1702c95e50 | |||
| 920b346175 | |||
| 46ff9acd64 | |||
| 8031c7da4f | |||
| 08554fc864 |
+69
-7
@@ -27,6 +27,36 @@ commands:
|
||||
& $env:SSM\smksp_cert_sync.exe
|
||||
|
||||
jobs:
|
||||
build-visual:
|
||||
docker:
|
||||
- image: cimg/node:18.20.3
|
||||
steps:
|
||||
- checkout
|
||||
- run: node --version
|
||||
- run:
|
||||
name: "npm install"
|
||||
command: "npm i"
|
||||
working_directory: src/powerbi-visual
|
||||
- run:
|
||||
name: Set version
|
||||
command: |
|
||||
npm version ${CIRCLE_TAG:-2.0.0} --allow-same-version
|
||||
working_directory: src/powerbi-visual
|
||||
- run:
|
||||
name: "npm run build"
|
||||
command: "npm run build"
|
||||
working_directory: src/powerbi-visual
|
||||
- run:
|
||||
name: "npm run pack"
|
||||
command: "npm run pack"
|
||||
working_directory: src/powerbi-visual
|
||||
- store_artifacts:
|
||||
path: dist/*.pbiviz
|
||||
- persist_to_workspace:
|
||||
root: ./
|
||||
paths:
|
||||
- src/powerbi-visual/dist/*.pbiviz
|
||||
|
||||
build-connector:
|
||||
executor:
|
||||
name: win/default
|
||||
@@ -38,14 +68,31 @@ jobs:
|
||||
- run:
|
||||
name: "Set connector internal version"
|
||||
command: |
|
||||
$env:VERSION = if([string]::IsNullOrEmpty($env:CIRCLE_TAG)) { "2.0.0.$($env:WORKFLOW_NUM)" } else { $env:CIRCLE_TAG }
|
||||
(Get-Content ./src/powerbi-data-connector/Speckle.pq).replace('[Version = "2.0.0"]', '[Version = "'+$($env:VERSION)+'"]') | Set-Content ./src/powerbi-data-connector/Speckle.pq
|
||||
$env:VERSION = if([string]::IsNullOrEmpty($env:CIRCLE_TAG)) { "2.0.0" } else { $env:CIRCLE_TAG }
|
||||
(Get-Content ./Speckle.pq).replace('[Version = "2.0.0"]', '[Version = "'+$($env:VERSION)+'"]') | Set-Content ./Speckle.pq
|
||||
working_directory: src/powerbi-data-connector
|
||||
- run:
|
||||
name: "Build Data Connector"
|
||||
command: "msbuild ./src/powerbi-data-connector/Speckle.proj /restore /consoleloggerparameters:NoSummary /property:GenerateFullPaths=true"
|
||||
command: "msbuild Speckle.proj /restore /consoleloggerparameters:NoSummary /property:GenerateFullPaths=true"
|
||||
working_directory: src/powerbi-data-connector
|
||||
- run:
|
||||
name: Create PQX file
|
||||
command: .\tools\MakePQX\MakePQX.exe pack -mz src/powerbi-data-connector/bin/Speckle.mez -t src/powerbi-data-connector/bin/Speckle.pqx
|
||||
- persist_to_workspace:
|
||||
root: ./
|
||||
paths:
|
||||
- src/powerbi-data-connector/bin/Speckle.pqx
|
||||
|
||||
build-installer:
|
||||
executor:
|
||||
name: win/default
|
||||
shell: powershell.exe
|
||||
environment:
|
||||
SSM: 'C:\Program Files\DigiCert\DigiCert One Signing Manager Tools'
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: ./
|
||||
- unless: # Build installers unsigned on non-tagged builds
|
||||
condition: << pipeline.git.tag >>
|
||||
steps:
|
||||
@@ -54,7 +101,7 @@ jobs:
|
||||
shell: cmd.exe #does not work in powershell
|
||||
environment:
|
||||
WORKFLOW_NUM: << pipeline.number >>
|
||||
CIRCLE_TAG: 2.0.999-beta/all
|
||||
CIRCLE_TAG: 2.0.0
|
||||
command: .circleci\build-installer.bat
|
||||
- when: # Setup certificates and build installers signed for tagged builds
|
||||
condition: << pipeline.git.tag >>
|
||||
@@ -85,29 +132,44 @@ jobs:
|
||||
- run:
|
||||
name: Upload new version
|
||||
command: |
|
||||
TAG=$(if [ "${CIRCLE_TAG}" ]; then echo $CIRCLE_TAG; else echo "2.0.999"; fi;)
|
||||
TAG=$(if [ "${CIRCLE_TAG}" ]; then echo $CIRCLE_TAG; else echo "2.0.0"; fi;)
|
||||
SEMVER=$(echo "$TAG" | sed -e 's/\/[a-zA-Z-]*//')
|
||||
VER=$(echo "$SEMVER" | sed -e 's/-.*//')
|
||||
VERSION=$(echo $VER.$WORKFLOW_NUM)
|
||||
/root/.dotnet/tools/Speckle.Manager.Feed deploy -s powerbi -v ${SEMVER} -u https://releases.speckle.dev/installers/powerbi/powerbi-${SEMVER}.exe -o Win -a Any -f ./installer/powerbi-${SEMVER}.exe
|
||||
environment:
|
||||
WORKFLOW_NUM: << pipeline.number >>
|
||||
|
||||
workflows:
|
||||
build:
|
||||
jobs:
|
||||
- build-connector:
|
||||
context: digicert-keylocker
|
||||
- build-visual
|
||||
- build-installer:
|
||||
context: digicert-keylocker
|
||||
requires:
|
||||
- build-connector
|
||||
- build-visual
|
||||
deploy:
|
||||
jobs:
|
||||
- build-connector:
|
||||
filters: &deploy_filter
|
||||
branches:
|
||||
ignore: /.*/ # For testing only: /ci\/.*/
|
||||
ignore: /.*/
|
||||
tags:
|
||||
only: /^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-\w{1,10})?$/
|
||||
context: digicert-keylocker
|
||||
- build-visual:
|
||||
filters: *deploy_filter
|
||||
- build-installer:
|
||||
filters: *deploy_filter
|
||||
context: digicert-keylocker
|
||||
requires:
|
||||
- build-connector
|
||||
- build-visual
|
||||
- deploy-connector-to-feed:
|
||||
filters: *deploy_filter
|
||||
requires:
|
||||
- build-connector
|
||||
- build-installer
|
||||
context: do-spaces-speckle-releases
|
||||
|
||||
+2
-1
@@ -339,4 +339,5 @@ ASALocalRun/
|
||||
**/.tmp/
|
||||
**/webpack.statistics.*.html
|
||||
**/webpack.statistics.html
|
||||
**/Thumbs.db
|
||||
**/Thumbs.db
|
||||
installer/
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"settings": {
|
||||
"powerquery.general.mode": "SDK",
|
||||
"powerquery.sdk.defaultQueryFile": "${workspaceFolder}\\src\\powerbi-data-connector\\Speckle.query.pq",
|
||||
"powerquery.sdk.defaultExtension": "${workspaceFolder}\\bin\\${workspaceFolderBasename}.mez",
|
||||
"powerquery.sdk.defaultExtension": "${workspaceFolder}\\src\\powerbi-data-connector\\bin\\Speckle.mez",
|
||||
"files.eol": "\n",
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[Version = "2.15.0-rc"]
|
||||
[Version = "2.0.0"]
|
||||
section Speckle;
|
||||
|
||||
AuthAppId = "spklpwerbi";
|
||||
|
||||
@@ -1,45 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
|
||||
DefaultTargets="BuildMez">
|
||||
<PropertyGroup>
|
||||
<Version Condition="'$(Version)' == ''">2.0.0-wip</Version>
|
||||
<OutputPath Condition="'$(OutputPath)' == ''">$(MSBuildProjectDirectory)\bin\</OutputPath>
|
||||
<IntermediateOutputPath Condition="'$(IntermediateOutputPath)' == ''">
|
||||
$(MSBuildProjectDirectory)\obj\</IntermediateOutputPath>
|
||||
<MezIntermediatePath>$(IntermediateOutputPath)MEZ\</MezIntermediatePath>
|
||||
<MezOutputPath>$(OutputPath)$(MsBuildProjectName).mez</MezOutputPath>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<MezContent Include="Speckle.pq" />
|
||||
<MezContent Include="utilities\**\*.pqm" />
|
||||
<MezContent Include="speckle\**\*.pqm" />
|
||||
<MezContent Include="assets\SpeckleLogo16.png" />
|
||||
<MezContent Include="assets\SpeckleLogo20.png" />
|
||||
<MezContent Include="assets\SpeckleLogo24.png" />
|
||||
<MezContent Include="assets\SpeckleLogo32.png" />
|
||||
<MezContent Include="assets\SpeckleLogo40.png" />
|
||||
<MezContent Include="assets\SpeckleLogo48.png" />
|
||||
<MezContent Include="assets\SpeckleLogo64.png" />
|
||||
<MezContent Include="assets\SpeckleLogo80.png" />
|
||||
<MezContent Include="assets\resources.resx" />
|
||||
</ItemGroup>
|
||||
<Target Name="BuildMez" AfterTargets="Build" Inputs="@(MezContent)" Outputs="$(MezOutputPath)">
|
||||
<RemoveDir Directories="$(MezIntermediatePath)" />
|
||||
<Copy SourceFiles="@(MezContent)" DestinationFolder="$(MezIntermediatePath)" />
|
||||
<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
|
||||
<ZipDirectory SourceDirectory="$(MezIntermediatePath)" DestinationFile="$(MezOutputPath)"
|
||||
Overwrite="true" />
|
||||
</Target>
|
||||
<Target Name="CopyToConnectors" AfterTargets="BuildMez">
|
||||
<Message
|
||||
Text="Copying .mez file to: $(UserProfile)\Documents\Power BI Desktop\Custom Connectors"
|
||||
Importance="High" />
|
||||
<MakeDir Directories="$(UserProfile)\Documents\Power BI Desktop\Custom Connectors\" />
|
||||
<Copy SourceFiles="$(MezOutputPath)"
|
||||
DestinationFolder="$(UserProfile)\Documents\Power BI Desktop\Custom Connectors\" />
|
||||
</Target>
|
||||
<Target Name="Clean">
|
||||
<RemoveDir Directories="$(MezIntermediatePath)" />
|
||||
<Delete Files="$(MezOutputPath)" />
|
||||
</Target>
|
||||
DefaultTargets="BuildMez">
|
||||
<PropertyGroup>
|
||||
<Version Condition="'$(Version)' == ''">2.0.0-wip</Version>
|
||||
<OutputPath Condition="'$(OutputPath)' == ''">$(MSBuildProjectDirectory)\bin\</OutputPath>
|
||||
<IntermediateOutputPath Condition="'$(IntermediateOutputPath)' == ''">
|
||||
$(MSBuildProjectDirectory)\obj\</IntermediateOutputPath>
|
||||
<MezIntermediatePath>$(IntermediateOutputPath)MEZ\</MezIntermediatePath>
|
||||
<MezOutputPath>$(OutputPath)$(MsBuildProjectName).mez</MezOutputPath>
|
||||
<IsContinuousIntegrationBuild>false</IsContinuousIntegrationBuild>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<MezContent Include="Speckle.pq" />
|
||||
<MezContent Include="utilities\**\*.pqm" />
|
||||
<MezContent Include="speckle\**\*.pqm" />
|
||||
<MezContent Include="assets\SpeckleLogo16.png" />
|
||||
<MezContent Include="assets\SpeckleLogo20.png" />
|
||||
<MezContent Include="assets\SpeckleLogo24.png" />
|
||||
<MezContent Include="assets\SpeckleLogo32.png" />
|
||||
<MezContent Include="assets\SpeckleLogo40.png" />
|
||||
<MezContent Include="assets\SpeckleLogo48.png" />
|
||||
<MezContent Include="assets\SpeckleLogo64.png" />
|
||||
<MezContent Include="assets\SpeckleLogo80.png" />
|
||||
<MezContent Include="assets\resources.resx" />
|
||||
</ItemGroup>
|
||||
<Target Name="BuildMez" AfterTargets="Build" Inputs="@(MezContent)" Outputs="$(MezOutputPath)">
|
||||
<RemoveDir Directories="$(MezIntermediatePath)" />
|
||||
<Copy SourceFiles="@(MezContent)" DestinationFolder="$(MezIntermediatePath)" />
|
||||
<MakeDir Directories="$(OutputPath)" Condition="!Exists('$(OutputPath)')" />
|
||||
<ZipDirectory SourceDirectory="$(MezIntermediatePath)" DestinationFile="$(MezOutputPath)"
|
||||
Overwrite="true" />
|
||||
</Target>
|
||||
<Target Name="CopyToConnectors" AfterTargets="BuildMez"
|
||||
Condition="$(IsContinuousIntegrationBuild) == 'false'">
|
||||
<Message
|
||||
Text="Copying .mez file to: $(UserProfile)\Documents\Power BI Desktop\Custom Connectors"
|
||||
Importance="High" />
|
||||
<MakeDir Directories="$(UserProfile)\Documents\Power BI Desktop\Custom Connectors\" />
|
||||
<Copy SourceFiles="$(MezOutputPath)"
|
||||
DestinationFolder="$(UserProfile)\Documents\Power BI Desktop\Custom Connectors\" />
|
||||
</Target>
|
||||
<Target Name="Clean">
|
||||
<RemoveDir Directories="$(MezIntermediatePath)" />
|
||||
<Delete Files="$(MezOutputPath)" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,7 +1,2 @@
|
||||
// Use this file to write queries to test your data connector
|
||||
let
|
||||
result = Speckle.GetByUrl(
|
||||
"https://app.speckle.systems/projects/e2988234fb/models/60b2300470@b1f31a351a,60b2300470"
|
||||
)
|
||||
in
|
||||
result
|
||||
let result = Speckle.GetByUrl("https://app.speckle.systems/projects/e2988234fb/models/60b2300470@b1f31a351a") in result
|
||||
|
||||
@@ -44,15 +44,13 @@ in
|
||||
addSpeckleTypeCol = Table.AddColumn(
|
||||
addObjectIdCol, "speckle_type", each try[data][speckle_type] otherwise null
|
||||
),
|
||||
// TODO: JSON Column must be added here so that any detached objects can be re-attached before doing the json thing. If we just pick the raw result from the API, it will only work in the simplest of objects.
|
||||
addJsonCol = Table.AddColumn(
|
||||
addSpeckleTypeCol, "json", each try Text.FromBinary(Json.FromValue([data])) otherwise null
|
||||
),
|
||||
final = Table.ReorderColumns(
|
||||
addSpeckleTypeCol, {
|
||||
"Model URL",
|
||||
"URL Type",
|
||||
"Version Object ID",
|
||||
"Object ID",
|
||||
"speckle_type",
|
||||
"data"
|
||||
}
|
||||
addJsonCol,
|
||||
{"Model URL", "URL Type", "Version Object ID", "Object ID", "speckle_type", "data", "json"}
|
||||
)
|
||||
in
|
||||
final
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
"kind": "Grouping",
|
||||
"name": "objectColorBy"
|
||||
},
|
||||
{
|
||||
"displayName": "JSON Data",
|
||||
"kind": "Measure",
|
||||
"name": "json"
|
||||
},
|
||||
{
|
||||
"displayName": "Tooltip Data",
|
||||
"kind": "Measure",
|
||||
@@ -36,16 +41,6 @@
|
||||
}
|
||||
},
|
||||
"select": [
|
||||
{
|
||||
"bind": {
|
||||
"to": "stream"
|
||||
}
|
||||
},
|
||||
{
|
||||
"bind": {
|
||||
"to": "parentObject"
|
||||
}
|
||||
},
|
||||
{
|
||||
"bind": {
|
||||
"to": "objectColorBy"
|
||||
@@ -60,6 +55,11 @@
|
||||
},
|
||||
"values": {
|
||||
"select": [
|
||||
{
|
||||
"bind": {
|
||||
"to": "json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"bind": {
|
||||
"to": "objectData"
|
||||
@@ -206,6 +206,7 @@
|
||||
"essential": true,
|
||||
"name": "WebAccess",
|
||||
"parameters": [
|
||||
"https://*.speckle.systems",
|
||||
"https://speckle.xyz",
|
||||
"https://*.speckle.xyz",
|
||||
"https://latest.speckle.dev",
|
||||
|
||||
Generated
+1738
-329
File diff suppressed because it is too large
Load Diff
@@ -7,6 +7,7 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"pbiviz": "pbiviz",
|
||||
"pack": "webpack --config webpack.config.ts",
|
||||
"build": "webpack --config webpack.config.dev.ts",
|
||||
"serve": "webpack-dev-server --config webpack.config.dev.ts"
|
||||
@@ -57,6 +58,7 @@
|
||||
"mini-css-extract-plugin": "^2.7.5",
|
||||
"postcss": "^8.4.23",
|
||||
"postcss-import": "^15.1.0",
|
||||
"powerbi-visuals-tools": "^5.4.3",
|
||||
"powerbi-visuals-webpack-plugin": "^4.0.0",
|
||||
"prettier": "^2.8.8",
|
||||
"style-loader": "^3.3.2",
|
||||
@@ -73,5 +75,6 @@
|
||||
"webpack-bundle-analyzer": "^4.8.0",
|
||||
"webpack-cli": "^5.1.1",
|
||||
"webpack-dev-server": "^4.15.0"
|
||||
}
|
||||
},
|
||||
"version": "2.0.0"
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
"visual": {
|
||||
"name": "Speckle PowerBI Viewer",
|
||||
"displayName": "Speckle PowerBI Viewer",
|
||||
"guid": "powerbiSpeckleVisualAA98F06515D847E8ACB33BAB487244E0",
|
||||
"guid": "specklePowerBiVisual",
|
||||
"visualClassName": "Visual",
|
||||
"version": "2.19.0",
|
||||
"version": "2.0.0",
|
||||
"description": "An interactive 3D viewer for Speckle Data",
|
||||
"supportUrl": "https://speckle.community",
|
||||
"gitHubUrl": "https://github.com/specklesystems/speckle-powerbi-visuals"
|
||||
|
||||
@@ -90,62 +90,74 @@ export default class ViewerHandler {
|
||||
}
|
||||
|
||||
public async unloadObjects(
|
||||
objects: string[],
|
||||
objectIds: string[],
|
||||
signal?: AbortSignal,
|
||||
onObjectUnloaded?: (url: string) => void
|
||||
) {
|
||||
for (const url of objects) {
|
||||
console.log('Unloading objects', objectIds)
|
||||
for (const speckleObjectId of objectIds) {
|
||||
if (signal?.aborted) return
|
||||
await this.viewer
|
||||
.cancelLoad(url, true)
|
||||
.catch((e) => console.warn('Viewer Unload error', url, e))
|
||||
.finally(() => {
|
||||
if (this.loadedObjectsCache.has(url)) this.loadedObjectsCache.delete(url)
|
||||
if (onObjectUnloaded) onObjectUnloaded(url)
|
||||
})
|
||||
// TODO: Here's where the viewer unloads any objects that have been removed. It first ensures any loading is cancelled.
|
||||
// await this.viewer
|
||||
// .cancelLoad(url, true)
|
||||
// .catch((e) => console.warn('Viewer error while cancelling load', url, e))
|
||||
|
||||
if (this.loadedObjectsCache.has(speckleObjectId))
|
||||
this.loadedObjectsCache.delete(speckleObjectId)
|
||||
if (onObjectUnloaded) onObjectUnloaded(speckleObjectId)
|
||||
}
|
||||
}
|
||||
|
||||
public async loadObjectsWithAutoUnload(
|
||||
objectUrls: string[],
|
||||
objects: any[],
|
||||
onLoad: (url: string, index: number) => void,
|
||||
onError: (url: string, error: Error) => void,
|
||||
signal: AbortSignal
|
||||
) {
|
||||
var objectsToUnload = _.difference([...this.loadedObjectsCache], objectUrls)
|
||||
var objectsToUnload = _.difference(
|
||||
[...this.loadedObjectsCache],
|
||||
objects.map((o) => o.id as string)
|
||||
)
|
||||
await this.unloadObjects(objectsToUnload, signal)
|
||||
await this.loadObjects(objectUrls, onLoad, onError, signal)
|
||||
await this.loadObjects(objects, onLoad, onError, signal)
|
||||
}
|
||||
|
||||
public async loadObjects(
|
||||
objectUrls: string[],
|
||||
objectsToLoad: any[],
|
||||
onLoad: (url: string, index: number) => void,
|
||||
onError: (url: string, error: Error) => void,
|
||||
signal: AbortSignal
|
||||
) {
|
||||
console.log('Loading objects', objectsToLoad)
|
||||
try {
|
||||
let index = 0
|
||||
//let index = 0
|
||||
let promises = []
|
||||
for (const url of objectUrls) {
|
||||
for (const speckleObject of objectsToLoad) {
|
||||
signal.throwIfAborted()
|
||||
console.log('Attempting to load', url)
|
||||
if (!this.loadedObjectsCache.has(url)) {
|
||||
console.log('Attempting to load', speckleObject.id, speckleObject)
|
||||
|
||||
if (!this.loadedObjectsCache.has(speckleObject.id)) {
|
||||
console.log('Object is not in cache')
|
||||
const promise = this.viewer
|
||||
.loadObjectAsync(url, this.config.authToken, false)
|
||||
.then(() => onLoad(url, index++))
|
||||
.catch((e: Error) => onError(url, e))
|
||||
.finally(() => {
|
||||
if (!this.loadedObjectsCache.has(url)) this.loadedObjectsCache.add(url)
|
||||
})
|
||||
promises.push(promise)
|
||||
|
||||
// TODO: Here's were the viewer loads each object, this used to be done via URL but is now changed to use JSON objects instead (already deserialized)
|
||||
|
||||
// const promise = this.viewer
|
||||
// .loadObjectAsync(speckleObject, this.config.authToken, false)
|
||||
// .then(() => onLoad(speckleObject.id, index++))
|
||||
// .catch((e: Error) => onError(speckleObject, e))
|
||||
|
||||
// promises.push(promise)
|
||||
|
||||
// If batchSize has been reached, wait till all promises resolve before continuing
|
||||
if (promises.length == this.config.batchSize) {
|
||||
//this.promises.push(Promise.resolve(this.later(1000)))
|
||||
await Promise.all(promises)
|
||||
promises = []
|
||||
}
|
||||
|
||||
if (!this.loadedObjectsCache.has(speckleObject.id))
|
||||
this.loadedObjectsCache.add(speckleObject.id)
|
||||
} else {
|
||||
console.log('Object was already in cache')
|
||||
console.log('Object was already in cache/already loaded')
|
||||
}
|
||||
}
|
||||
await Promise.all(promises)
|
||||
@@ -174,6 +186,7 @@ export default class ViewerHandler {
|
||||
objects: res.objects
|
||||
}
|
||||
}
|
||||
|
||||
public zoom(objectIds?: string[]) {
|
||||
this.viewer.zoom(objectIds)
|
||||
}
|
||||
@@ -181,6 +194,7 @@ export default class ViewerHandler {
|
||||
public zoomExtents() {
|
||||
this.viewer.zoom()
|
||||
}
|
||||
|
||||
public async unIsolateObjects() {
|
||||
if (this.state.isolatedObjects)
|
||||
this.state = await this.viewer.unIsolateObjects(this.state.isolatedObjects, 'powerbi', true)
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import powerbi from 'powerbi-visuals-api'
|
||||
import { IViewerTooltip, IViewerTooltipData, SpeckleDataInput } from '../types'
|
||||
import { formattingSettings as fs } from 'powerbi-visuals-utils-formattingmodel'
|
||||
import {
|
||||
createDataViewWildcardSelector,
|
||||
DataViewWildcardMatchingOption
|
||||
} from 'powerbi-visuals-utils-dataviewutils/lib/dataViewWildcard'
|
||||
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions
|
||||
import { SpeckleVisualSettingsModel } from 'src/settings/visualSettingsModel'
|
||||
|
||||
@@ -15,23 +11,18 @@ export function validateMatrixView(options: VisualUpdateOptions): {
|
||||
const matrixVew = options.dataViews[0].matrix
|
||||
if (!matrixVew) throw new Error('Data does not contain a matrix data view')
|
||||
|
||||
let hasStream = false,
|
||||
hasParentObject = false,
|
||||
hasObject = false,
|
||||
let hasObject = false,
|
||||
hasColorFilter = false
|
||||
|
||||
matrixVew.rows.levels.forEach((level) => {
|
||||
level.sources.forEach((source) => {
|
||||
if (!hasStream) hasStream = source.roles['stream'] != undefined
|
||||
if (!hasParentObject) hasParentObject = source.roles['parentObject'] != undefined
|
||||
if (!hasObject) hasObject = source.roles['object'] != undefined
|
||||
if (!hasColorFilter) hasColorFilter = source.roles['objectColorBy'] != undefined
|
||||
})
|
||||
})
|
||||
|
||||
if (!hasStream) throw new Error('Missing Stream ID input')
|
||||
if (!hasParentObject) throw new Error('Missing Commit Object ID input')
|
||||
if (!hasObject) throw new Error('Missing Object Id input')
|
||||
|
||||
return {
|
||||
hasColorFilter,
|
||||
view: matrixVew
|
||||
@@ -65,7 +56,7 @@ function processObjectValues(
|
||||
displayName: colInfo.displayName,
|
||||
value: value.value.toString()
|
||||
}
|
||||
objectData.push(propData)
|
||||
if (value.valueSourceIndex) objectData.push(propData)
|
||||
})
|
||||
return { data: objectData, shouldColor, shouldSelect }
|
||||
}
|
||||
@@ -126,94 +117,50 @@ export function processMatrixView(
|
||||
settings: SpeckleVisualSettingsModel,
|
||||
onSelectionPair: (objId: string, selectionId: powerbi.extensibility.ISelectionId) => void
|
||||
): SpeckleDataInput {
|
||||
const objectUrlsToLoad = [],
|
||||
const objectJsonToLoad = [],
|
||||
objectIds = [],
|
||||
selectedIds = [],
|
||||
colorByIds = [],
|
||||
objectTooltipData = new Map<string, IViewerTooltip>()
|
||||
|
||||
matrixView.rows.root.children.forEach((streamUrlChild) => {
|
||||
const url = streamUrlChild.value
|
||||
// Assume this has color filter
|
||||
matrixView.rows.root?.children?.forEach((colorByGroup) => {
|
||||
const colorByValue = colorByGroup.value
|
||||
console.log('Color by group', colorByValue, colorByGroup)
|
||||
|
||||
streamUrlChild.children?.forEach((parentObjectIdChild) => {
|
||||
const parentId = parentObjectIdChild.value
|
||||
objectUrlsToLoad.push(`${url}/objects/${parentId}`)
|
||||
const colorGroup = createColorGroup(host, colorByGroup, matrixView)
|
||||
|
||||
if (!hasColorFilter) {
|
||||
processObjectIdLevel(parentObjectIdChild, host, matrixView).forEach((objRes) => {
|
||||
objectIds.push(objRes.id)
|
||||
onSelectionPair(objRes.id, objRes.selectionId)
|
||||
if (objRes.shouldSelect) selectedIds.push(objRes.id)
|
||||
if (objRes.color) {
|
||||
let group = colorByIds.find((g) => g.color === objRes.color)
|
||||
if (!group) {
|
||||
group = {
|
||||
color: objRes.color,
|
||||
objectIds: []
|
||||
}
|
||||
colorByIds.push(group)
|
||||
}
|
||||
group.objectIds.push(objRes.id)
|
||||
}
|
||||
objectTooltipData.set(objRes.id, {
|
||||
selectionId: objRes.selectionId,
|
||||
data: objRes.data
|
||||
})
|
||||
})
|
||||
} else {
|
||||
if (previousPalette) host.colorPalette['colorPalette'] = previousPalette
|
||||
parentObjectIdChild.children?.forEach((colorByChild) => {
|
||||
const colorSelectionId = host
|
||||
.createSelectionIdBuilder()
|
||||
.withMatrixNode(colorByChild, matrixView.rows.levels)
|
||||
.createSelectionId()
|
||||
colorByGroup.children.forEach((objectIdGroup) => {
|
||||
const uniqueId = objectIdGroup.value
|
||||
const jsonValue = objectIdGroup.values[0] // TODO: Json value is set as first value in capabilities.json
|
||||
|
||||
const color = host.colorPalette.getColor(colorByChild.value as string)
|
||||
if (colorByChild.objects) {
|
||||
console.log(
|
||||
'⚠️COLOR NODE HAS objects',
|
||||
colorByChild.objects,
|
||||
colorByChild.objects.color?.fill
|
||||
)
|
||||
}
|
||||
objectJsonToLoad.push(JSON.parse(jsonValue.value.toString()))
|
||||
colorGroup.objectIds.push(uniqueId)
|
||||
|
||||
const colorSlice = new fs.ColorPicker({
|
||||
name: 'selectorFill',
|
||||
displayName: colorByChild.value.toString(),
|
||||
value: {
|
||||
value: color.value
|
||||
},
|
||||
selector: colorSelectionId.getSelector()
|
||||
})
|
||||
if (jsonValue.highlight) console.log(uniqueId, jsonValue)
|
||||
var processedObject = processObjectNode(objectIdGroup, host, matrixView)
|
||||
console.log(processedObject)
|
||||
|
||||
const colorGroup = {
|
||||
color: color.value,
|
||||
slice: colorSlice,
|
||||
objectIds: []
|
||||
}
|
||||
onSelectionPair(uniqueId.toString(), processedObject.selectionId)
|
||||
|
||||
processObjectIdLevel(colorByChild, host, matrixView).forEach((objRes) => {
|
||||
objectIds.push(objRes.id)
|
||||
onSelectionPair(objRes.id, objRes.selectionId)
|
||||
if (objRes.shouldSelect) selectedIds.push(objRes.id)
|
||||
if (objRes.shouldColor) {
|
||||
colorGroup.objectIds.push(objRes.id)
|
||||
}
|
||||
objectTooltipData.set(objRes.id, {
|
||||
selectionId: objRes.selectionId,
|
||||
data: objRes.data
|
||||
})
|
||||
})
|
||||
if (colorGroup.objectIds.length > 0) colorByIds.push(colorGroup)
|
||||
})
|
||||
}
|
||||
if (processedObject.shouldSelect) selectedIds.push(processedObject.id)
|
||||
if (processedObject.shouldColor) colorGroup.objectIds.push(processedObject.id)
|
||||
|
||||
objectTooltipData.set(processedObject.id, {
|
||||
selectionId: processedObject.selectionId,
|
||||
data: processedObject.data
|
||||
})
|
||||
})
|
||||
|
||||
if (colorGroup.objectIds.length > 0) colorByIds.push(colorGroup)
|
||||
})
|
||||
|
||||
// TODO: Code behavior without color filter
|
||||
|
||||
previousPalette = host.colorPalette['colorPalette']
|
||||
|
||||
return {
|
||||
objectsToLoad: objectUrlsToLoad,
|
||||
objectsToLoad: objectJsonToLoad,
|
||||
objectIds,
|
||||
selectedIds,
|
||||
colorByIds: colorByIds.length > 0 ? colorByIds : null,
|
||||
@@ -221,3 +168,34 @@ export function processMatrixView(
|
||||
view: matrixView
|
||||
}
|
||||
}
|
||||
function createColorGroup(
|
||||
host: powerbi.extensibility.visual.IVisualHost,
|
||||
colorByGroup: powerbi.DataViewMatrixNode,
|
||||
matrixView: powerbi.DataViewMatrix
|
||||
) {
|
||||
const colorSelectionId = host
|
||||
.createSelectionIdBuilder()
|
||||
.withMatrixNode(colorByGroup, matrixView.rows.levels)
|
||||
.createSelectionId()
|
||||
|
||||
const color = host.colorPalette.getColor(colorByGroup.value as string)
|
||||
if (colorByGroup.objects) {
|
||||
console.log('⚠️COLOR NODE HAS objects', colorByGroup.objects, colorByGroup.objects.color?.fill)
|
||||
}
|
||||
|
||||
const colorSlice = new fs.ColorPicker({
|
||||
name: 'selectorFill',
|
||||
displayName: colorByGroup.value.toString(),
|
||||
value: {
|
||||
value: color.value
|
||||
},
|
||||
selector: colorSelectionId.getSelector()
|
||||
})
|
||||
|
||||
const colorGroup = {
|
||||
color: color.value,
|
||||
slice: colorSlice,
|
||||
objectIds: []
|
||||
}
|
||||
return colorGroup
|
||||
}
|
||||
|
||||
@@ -20,11 +20,6 @@ import VisualConstructorOptions = powerbi.extensibility.visual.VisualConstructor
|
||||
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions
|
||||
import IVisual = powerbi.extensibility.visual.IVisual
|
||||
import ITooltipService = powerbi.extensibility.ITooltipService
|
||||
import {
|
||||
createDataViewWildcardSelector,
|
||||
DataViewWildcardMatchingOption
|
||||
} from 'powerbi-visuals-utils-dataviewutils/lib/dataViewWildcard'
|
||||
import { ColorSelectorSettings } from 'src/settings/colorSettings'
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
export class Visual implements IVisual {
|
||||
|
||||
@@ -20,6 +20,9 @@ const powerbiApi: any = powerbi // Types for PowerBI seem to be off, so I'm inst
|
||||
const pbivizPath = './pbiviz.json'
|
||||
const pbivizFile = require(path.join(__dirname, pbivizPath))
|
||||
|
||||
const packageJsonFile = require(path.join(__dirname, 'package.json'))
|
||||
pbivizFile.visual.version = packageJsonFile.version
|
||||
|
||||
// the visual capabilities content
|
||||
const capabilitiesPath = './capabilities.json'
|
||||
const capabilitiesFile = require(path.join(__dirname, capabilitiesPath))
|
||||
|
||||
@@ -20,6 +20,9 @@ const powerbiApi: any = powerbi // Types for PowerBI seem to be off, so I'm inst
|
||||
const pbivizPath = './pbiviz.json'
|
||||
const pbivizFile = require(path.join(__dirname, pbivizPath))
|
||||
|
||||
const packageJsonFile = require(path.join(__dirname, 'package.json'))
|
||||
pbivizFile.visual.version = packageJsonFile.version
|
||||
|
||||
// the visual capabilities content
|
||||
const capabilitiesPath = './capabilities.json'
|
||||
const capabilitiesFile = require(path.join(__dirname, capabilitiesPath))
|
||||
|
||||
+5
-5
@@ -5,13 +5,14 @@
|
||||
|
||||
#define BasePath "..\"
|
||||
#define Bin BasePath + "src\powerbi-data-connector\bin\"
|
||||
#define VisualDistPath BasePath + "src\powerbi-data-connector\dist\"
|
||||
#define VisualDistPath BasePath + "src\powerbi-visual\dist\"
|
||||
|
||||
#ifndef Version
|
||||
#define Version "2.0.999"
|
||||
#define Version "2.0.0"
|
||||
#endif
|
||||
|
||||
#ifndef InfoVersion
|
||||
#define InfoVersion "2.0.999.9999"
|
||||
#define InfoVersion "2.0.0.0"
|
||||
#endif
|
||||
|
||||
#define AppPublisher "Speckle"
|
||||
@@ -56,7 +57,7 @@ Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Files]
|
||||
Source: "{#Bin}Speckle.pqx"; DestDir: "{#CustomConnectorFolder}";
|
||||
; Source: "{#VisualDistPath}/specklePowerBiVisual.*.pbiviz"; DestDir: "{#CustomVisualFolder}";
|
||||
Source: "{#VisualDistPath}specklePowerBiVisual.{#Version}.pbiviz"; DestDir: "{#CustomVisualFolder}"; DestName: "Speckle Power BI 3D Visual.pbiviz";
|
||||
|
||||
; TODO: Including the thumbprint in the registry will enable this running in higher security environments.
|
||||
; Currently blocked because of MakePQX.exe not being ready to work with online CSP's like Digicert Keylocker.
|
||||
@@ -65,4 +66,3 @@ Source: "{#Bin}Speckle.pqx"; DestDir: "{#CustomConnectorFolder}";
|
||||
[InstallDelete]
|
||||
; Remove old .mez file connector to prevent conflicts with prior versions.
|
||||
Type: filesandordirs; Name: "{#CustomConnectorFolder}\Speckle.mez"
|
||||
Type: filesandordirs; Name: "{#CustomConnectorFolder}\Speckle.mez"
|
||||
|
||||
Reference in New Issue
Block a user