-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 612278e
Showing
47 changed files
with
1,559 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[core] | ||
autocrlf = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: Attach Custom Connector as release asset | ||
|
||
on: | ||
release: | ||
types: [published] | ||
|
||
jobs: | ||
build-and-attach: | ||
runs-on: windows-latest | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v3 | ||
|
||
- name: Set up MSBuild | ||
uses: microsoft/setup-msbuild@v1 | ||
|
||
- name: Build .mez file | ||
run: | | ||
msbuild enlyze.pq.proj /p:Configuration=Release | ||
- name: Upload `.mez` as release asset | ||
uses: softprops/action-gh-release@v1 | ||
with: | ||
files: bin/AnyCPU/Release/enlyze-powerbi.mez | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
*.DS_Store | ||
bin/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"type": "powerquery", | ||
"request": "launch", | ||
"name": "Evaluate power query file.", | ||
"program": "${workspaceFolder}/${command:AskForPowerQueryFileName}" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"powerquery.sdk.defaultQueryFile": "${workspaceFolder}\\enlyze.query.pq", | ||
"powerquery.sdk.defaultExtension": "${workspaceFolder}\\bin\\AnyCPU\\Debug\\enlyze-powerbi.mez", | ||
"powerquery.general.mode": "SDK" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"version": "2.0.0", | ||
"tasks": [ | ||
{ | ||
"label": "Build and deploy", | ||
"type": "shell", | ||
"command": "powershell.exe", | ||
"args": [ | ||
"-ExecutionPolicy", | ||
"Bypass", | ||
"-File", | ||
"${workspaceFolder}/push-extension.ps1" | ||
], | ||
"presentation": { | ||
"reveal": "always", | ||
"panel": "new" | ||
}, | ||
"group": "build", | ||
"problemMatcher": [] | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
let | ||
BaseUrl = "https://app.enlyze.com/api/v2", | ||
CommonHeaders = [ | ||
#"Content-Type" = "application/json", | ||
#"user-agent" = "enlyze-powerbi/1.0.0" | ||
], | ||
CreateHeaders = (apiToken as text) as record => | ||
Record.Combine({CommonHeaders, [#"Authorization" = "Bearer " & apiToken]}), | ||
FetchPage = (apiPath as text, cursor as nullable text, optional queryParams as nullable record) => | ||
let | ||
apiUrl = BaseUrl & apiPath, | ||
apiToken = Extension.CurrentCredential()[Key], | ||
headers = CreateHeaders(apiToken), | ||
combinedQueryParams = | ||
if queryParams <> null then | ||
Record.Combine({queryParams, [cursor = cursor]}) | ||
else | ||
[cursor = cursor], | ||
fieldNames = Record.FieldNames(combinedQueryParams), | ||
nullValueFields = List.Select(fieldNames, each Record.Field(combinedQueryParams, _) = null), | ||
queryParamsNonNull = Record.RemoveFields(combinedQueryParams, nullValueFields), | ||
queryString = Uri.BuildQueryString(queryParamsNonNull), | ||
apiUrlWithQueryParams = if Text.Length(queryString) > 0 then apiUrl & "?" & queryString else apiUrl, | ||
parsedResponse = Json.Document(Web.Contents(apiUrlWithQueryParams, [Headers = headers])) | ||
in | ||
parsedResponse, | ||
FetchPaginated = (apiPath as text, cursor as nullable text, optional queryParams as nullable record) as list => | ||
let | ||
currentPage = FetchPage(apiPath, cursor, queryParams), | ||
nextCursor = currentPage[metadata][next_cursor], | ||
data = currentPage[data], | ||
remainingData = if nextCursor = null then {} else @FetchPaginated(apiPath, nextCursor, queryParams) | ||
in | ||
List.Combine({data, remainingData}), | ||
PostRequestPage = (apiPath as text, body as record, cursor as nullable text) as record => | ||
let | ||
bodyWithCursor = if cursor <> null then Record.Combine({body, [cursor = cursor]}) else body, | ||
url = BaseUrl & apiPath, | ||
apiToken = Extension.CurrentCredential()[Key], | ||
headers = CreateHeaders(apiToken), | ||
response = Web.Contents( | ||
url, | ||
[ | ||
Headers = headers, | ||
Content = Json.FromValue(bodyWithCursor), | ||
ManualStatusHandling = {400, 401, 403, 404, 422, 500} | ||
] | ||
), | ||
statusCode = Value.Metadata(response)[Response.Status], | ||
parsedResponse = | ||
if statusCode = 200 then | ||
Json.Document(response) | ||
else | ||
error "HTTP Error: " & Text.From(statusCode) & ". Response body: " & Text.FromBinary(response) | ||
in | ||
parsedResponse, | ||
PaginatedPostRequest = (apiPath as text, body as record, optional cursor as nullable text) as list => | ||
let | ||
currentPage = PostRequestPage(apiPath, body, cursor), | ||
dataMaybeRecord = currentPage[data], | ||
data = if Type.Is(Value.Type(dataMaybeRecord), List.Type) then dataMaybeRecord else {dataMaybeRecord}, | ||
nextCursor = currentPage[metadata][next_cursor], | ||
remainingData = if nextCursor = null then {} else @PaginatedPostRequest(apiPath, body, nextCursor) | ||
in | ||
List.Combine({data, remainingData}) | ||
in | ||
[ | ||
FetchPaginated = FetchPaginated, | ||
PaginatedPostRequest = PaginatedPostRequest | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# ENLYZE Power BI Integration | ||
|
||
The ENLYZE Power BI Integration enables users to pull in their production data into Power BI. The project is based on the [Power Query Connector Development SDK](https://github.com/microsoft/vscode-powerquery-sdk). | ||
|
||
## Features | ||
|
||
The ENLYZE Power BI Integration currently supports querying the following resources: | ||
|
||
- Sites | ||
- Machines | ||
- Production Runs | ||
- Products | ||
- Downtimes | ||
- Productivity Metrics for machines | ||
|
||
## Installation | ||
|
||
In order to get started with the ENLYZE Power BI Integration, | ||
|
||
1. Download the `enlyze-powerbi.mez` file from the [Latest Release](/releases/latest/download/enlyze-powerbi.mez) | ||
2. Follow the steps [described in the official documentation](https://learn.microsoft.com/en-us/power-bi/connect-data/desktop-connector-extensibility#custom-connectors). | ||
3. Restart Power BI | ||
|
||
## Fetching data | ||
|
||
With Power BI open, click on get data: | ||
|
||
![menu bar](docs/images/menu-bar.png) | ||
|
||
Then, search for enlyze: | ||
|
||
![connector selection](docs/images/connector-select.png) | ||
|
||
Finally, select the dataset you want to query: | ||
|
||
![dataset selection](docs/images/dataset-select.png) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
let | ||
DowntimesTableSchema = type table [ | ||
uuid = text, | ||
machine = text, | ||
#"type" = text, | ||
start = datetimezone, | ||
end = nullable datetimezone, | ||
updated_first_name = nullable text, | ||
updated_last_name = nullable text, | ||
updated_timestamp = nullable datetimezone, | ||
reason_uuid = nullable text, | ||
reason_name = nullable text, | ||
reason_category = nullable text | ||
] | ||
in | ||
DowntimesTableSchema |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
let | ||
loadModule = (fileName as text) => | ||
let | ||
binary = Extension.Contents(fileName), asText = Text.FromBinary(binary) | ||
in | ||
try | ||
Expression.Evaluate(asText, #shared) catch (e) => | ||
error | ||
[ | ||
Reason = "Extension.LoadModule Failure", | ||
Message.Format = "Loading '#{0}' failed - '#{1}': '#{2}'", | ||
Message.Parameters = {fileName, e[Reason], e[Message]}, | ||
Detail = [File = fileName, Error = e] | ||
], | ||
TableSchema = loadModule("Downtimes.TableSchema.pqm"), | ||
Table.ChangeType = loadModule("Table.ChangeType.pqm"), | ||
TimeseriesData = loadModule("TimeseriesData.pqm"), | ||
TransformDowntimes = (downtimes as list) as table => | ||
let | ||
downtimesTable = Table.FromList(downtimes, Splitter.SplitByNothing(), null, null, ExtraValues.Error), | ||
namedTable = Value.ReplaceMetadata(downtimesTable, Value.Metadata(downtimesTable) & [Name = "Downtimes"]), | ||
expandedTable = Table.ExpandRecordColumn( | ||
namedTable, "Column1", {"uuid", "machine", "comment", "type", "updated", "reason", "start", "end"} | ||
), | ||
expandedUpdated = Table.ExpandRecordColumn( | ||
expandedTable, | ||
"updated", | ||
{"first_name", "last_name", "timestamp"}, | ||
{"updated_first_name", "updated_last_name", "updated_timestamp"} | ||
), | ||
expandedReason = Table.ExpandRecordColumn( | ||
expandedUpdated, | ||
"reason", | ||
{"uuid", "name", "category"}, | ||
{"reason_uuid", "reason_name", "reason_category"} | ||
) | ||
in | ||
Table.ChangeType(expandedReason, TableSchema) | ||
in | ||
[TransformDowntimes = TransformDowntimes] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
[Version = "1.0.0"] | ||
section enlyze; | ||
|
||
loadModule = (fileName as text) => | ||
let | ||
binary = Extension.Contents(fileName), asText = Text.FromBinary(binary) | ||
in | ||
try | ||
Expression.Evaluate(asText, #shared) catch (e) => | ||
error | ||
[ | ||
Reason = "loadModule Failure", | ||
Message.Format = "Loading '#{0}' failed - '#{1}': '#{2}'", | ||
Message.Parameters = {fileName, e[Reason], e[Message]}, | ||
Detail = [File = fileName, Error = e] | ||
]; | ||
|
||
Table.ToNavigationTable = loadModule("Table.ToNavigationTable.pqm"); | ||
|
||
FetchPaginated = loadModule("ApiClient.pqm")[FetchPaginated]; | ||
PaginatedPostRequest = loadModule("ApiClient.pqm")[PaginatedPostRequest]; | ||
|
||
TransformProductivityMetrics = loadModule("ProductivityMetrics.Transform.pqm")[TransformProductivityMetrics]; | ||
TransformProductionRuns = loadModule("ProductionRuns.Transform.pqm")[TransformProductionRuns]; | ||
TransformSites = loadModule("Sites.Transform.pqm")[TransformSites]; | ||
TransformMachines = loadModule("Machines.Transform.pqm")[TransformMachines]; | ||
TransformProducts = loadModule("Products.Transform.pqm")[TransformProducts]; | ||
TransformDowntimes = loadModule("Downtimes.Transform.pqm")[TransformDowntimes]; | ||
TransformTimeseriesData = loadModule("TimeseriesData.Transform.pqm")[TransformTimeseriesData]; | ||
TransformVariables = loadModule("Variables.Transform.pqm")[TransformVariables]; | ||
|
||
MachineProductivityMetrics = loadModule("MachineProductivityMetrics.pqm"); | ||
TimeseriesData = loadModule("TimeseriesData.pqm"); | ||
|
||
[DataSource.Kind = "enlyze", Publish = "enlyze.Publish"] | ||
shared enlyze.Contents = () => | ||
let | ||
NavTable = Table.ToNavigationTable( | ||
#table( | ||
{"Name", "Key", "Data", "ItemKind", "ItemName", "IsLeaf"}, | ||
{ | ||
{ | ||
"Downtimes", | ||
"downtimes", | ||
TransformDowntimes(FetchPaginated("/downtimes", null)), | ||
"Table", | ||
"Table", | ||
true | ||
}, | ||
{ | ||
"Production Runs", | ||
"productionRuns", | ||
TransformProductionRuns(FetchPaginated("/production-runs", null)), | ||
"Table", | ||
"Table", | ||
true | ||
}, | ||
{ | ||
"Machines", | ||
"machines", | ||
TransformMachines(FetchPaginated("/machines", null)), | ||
"Table", | ||
"Table", | ||
true | ||
}, | ||
{"Sites", "sites", TransformSites(FetchPaginated("/sites", null)), "Table", "Table", true}, | ||
{ | ||
"Products", | ||
"products", | ||
TransformProducts(FetchPaginated("/products", null)), | ||
"Table", | ||
"Table", | ||
true | ||
}, | ||
{ | ||
"Machine Productivity Metrics", | ||
"machineProductivityMetrics", | ||
MachineProductivityMetrics, | ||
"Function", | ||
"Function", | ||
true | ||
}, | ||
{ | ||
"Variables", | ||
"Variables", | ||
TransformVariables(FetchPaginated("/variables", null)), | ||
"Table", | ||
"Table", | ||
true | ||
}, | ||
{"Timeseries", "Timeseries", TimeseriesData, "Function", "Function", true} | ||
} | ||
), | ||
{"Key"}, | ||
"Name", | ||
"Data", | ||
"ItemKind", | ||
"ItemName", | ||
"IsLeaf" | ||
) | ||
in | ||
NavTable; | ||
|
||
enlyze = [ | ||
Authentication = [ | ||
Key = [ | ||
Label = "ENLYZE API Key", | ||
KeyLabel = "ENLYZE API Key" | ||
] | ||
], | ||
Label = "ENLYZE" | ||
]; | ||
|
||
enlyze.Publish = [ | ||
Beta = true, | ||
Category = "Other", | ||
ButtonText = {Extension.LoadString("ButtonTitle"), Extension.LoadString("ButtonHelp")}, | ||
LearnMoreUrl = "https://docs.enlyze.com/", | ||
SourceImage = enlyze.Icons, | ||
SourceTypeImage = enlyze.Icons | ||
]; | ||
|
||
enlyze.Icons = [ | ||
Icon16 = { | ||
Extension.Contents("ENLYZE16.png"), | ||
Extension.Contents("ENLYZE20.png"), | ||
Extension.Contents("ENLYZE24.png"), | ||
Extension.Contents("ENLYZE32.png") | ||
}, | ||
Icon32 = { | ||
Extension.Contents("ENLYZE32.png"), | ||
Extension.Contents("ENLYZE40.png"), | ||
Extension.Contents("ENLYZE48.png"), | ||
Extension.Contents("ENLYZE64.png") | ||
} | ||
]; |
Oops, something went wrong.