Compare commits

...

6 Commits

Author SHA1 Message Date
Alan Rynne ff7db38b8d feat: Fix load/unload logic and cache to use objectIds 2024-07-12 12:51:56 +02:00
Alan Rynne 1702c95e50 feat: Initial working version 2024-07-12 11:03:16 +02:00
Alan Rynne 920b346175 Merge branch 'main' into dev 2024-06-30 23:24:53 +02:00
Alan Rynne 46ff9acd64 fix(visual): Give user facing pbiviz a better name 2024-05-30 11:03:10 +02:00
Alan Rynne 8031c7da4f feat: CNX-9628 Add visual to installer and CI script (#74)
* feat: Add visual to installer and CI script (attempt 1)

* fix(ci): Working directory set incorrectly

* fix(ci): Run build before pack and set data connector path correctly

* Install visual tools into dev dependencies

* fix(ci): Try fix MakePQX not found

* fix(ci): MakePQX args need correct subfolder

* fix(visual): Rename visual to not have guid

* feat(ci): Set default version to 2.0.0 everywhere, and overwrite on CI jobs

* fix(ci): Missed one version location

* fix(visual): Always use package.json version

This allows us to `npm version` instead of doing some weirder logic

* fix(visual): Allow same version when bumping
2024-05-29 22:34:03 +02:00
Alan Rynne 08554fc864 Merge branch 'main' into dev 2024-05-29 18:20:16 +02:00
17 changed files with 1992 additions and 528 deletions
+69 -7
View File
@@ -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
View File
@@ -339,4 +339,5 @@ ASALocalRun/
**/.tmp/
**/webpack.statistics.*.html
**/webpack.statistics.html
**/Thumbs.db
**/Thumbs.db
installer/
+1 -1
View File
@@ -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 -1
View File
@@ -1,4 +1,4 @@
[Version = "2.15.0-rc"]
[Version = "2.0.0"]
section Speckle;
AuthAppId = "spklpwerbi";
+44 -42
View File
@@ -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 -6
View File
@@ -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
+11 -10
View File
@@ -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",
+1738 -329
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -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 -2
View File
@@ -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)
+61 -83
View File
@@ -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
}
-5
View File
@@ -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 {
+3
View File
@@ -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))
+3
View File
@@ -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
View File
@@ -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"