From a378765a29ca12a2d7ef3df55e280c65b95f73db Mon Sep 17 00:00:00 2001 From: Akos Marton Date: Fri, 10 Dec 2021 10:54:27 +0100 Subject: [PATCH 01/11] Use universal interpreter path. --- upload.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/upload.sh b/upload.sh index d6665f9..efbfc38 100644 --- a/upload.sh +++ b/upload.sh @@ -1,4 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash + API_KEY="" DASHBOARD_ID="" URL="" @@ -8,4 +9,4 @@ cd dashboard; zip -r ../upload.zip *; cd .. curl -X POST "${URL}/api/v2/custom-dashboards/${DASHBOARD_ID}/source" \ -H "Authorization: API-Key ${API_KEY}" \ - -F file=@"upload.zip" \ No newline at end of file + -F file=@"upload.zip" From bdc270c846ef43616257e1fbf67c40db32751602 Mon Sep 17 00:00:00 2001 From: Akos Marton Date: Fri, 10 Dec 2021 11:47:30 +0100 Subject: [PATCH 02/11] Set fixed length of lines in readme; use inline grave-accents. --- README.md | 71 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 4aaa067..676a8a9 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,66 @@ # Python Dashboard for Lana PM -A documented example for python dashboards that can be used as a starting point for any new dashboards. The example shows a multipage app with a rather simple page 1 and a more complicated page 2. Page one can be seen as an example of how to create simple dashboard pages with elements being mostly independent of each other. Page 2 shows a complicated case where a table can be updated by the user, which then calculates the cost and updates a KPI below. Additionally a graph shows the occurences of the event selected in the table. For documentation of how to create plots, we refer to the documentation of Ploty and Dash. For an explanation of how to make api requests to the backend please see the Pylana Documentation and the api specifications of Lana Process Mining. + +A documented example for python dashboards that can be used as a starting point +for any new dashboards. The example shows a multipage app with a rather simple +page 1 and a more complicated page 2. Page one can be seen as an example of how +to create simple dashboard pages with elements being mostly independent of each +other. Page 2 shows a complicated case where a table can be updated by the user, +which then calculates the cost and updates a KPI below. Additionally a graph +shows the occurences of the event selected in the table. For documentation of +how to create plots, we refer to the documentation of Ploty and Dash. For an +explanation of how to make api requests to the backend please see the Pylana +Documentation and the api specifications of Lana Process Mining. ## Getting started + ### Install requirements -Create a new conda environment using: + +Create a new conda environment using: + `conda create env --env name` -Activate that environment using: +Activate that environment using: + `conda activate ` -Install required packages: -`conda install requirements.txt` +Install required packages: + +`conda install requirements.txt` `conda install lana_listener-0.0.1.tar.gz` ### Setting up configs and running the dashboard locally -It is possible to run the dashboard independent of LANA PM. -Simply fill in the API key and log_id into the `lana_listener` object and start `index.py`. + +It is possible to run the dashboard independent of LANA PM. +Simply fill in the API key and log_id into the `lana_listener` object and start +`index.py`. ### Uploading your first dashboard -Simply follow the steps in the jupyter-notebook to create a dashbaord and link it to the log. Once you have the ```dashboard_id``` and it is connected to the log, you will be able to upload source code either using the notebook, or using the ```upload.sh``` script. -For a detailed instruction of how to upload also other types of dashboards, as well as a Bash and Python guide to upload, please see ```UploadTutorial.pdf```. + +Simply follow the steps in the jupyter-notebook to create a dashbaord and link +it to the log. Once you have the `dashboard_id` and it is connected to the +log, you will be able to upload source code either using the notebook, or using +the `upload.sh` script. For a detailed instruction of how to upload also +other types of dashboards, as well as a Bash and Python guide to upload, please +see `UploadTutorial.pdf`. ### Uploading (new) source-code -First stop tracking the ```upload.sh``` file so that you can change the file without pushing the changes to git by accident. -```git update-index --assume-unchanged upload.sh``` -After filling in the api_key, dashboard_id and url, open the terminal and run -```bash upload.sh``` + +First stop tracking the `upload.sh` file so that you can change the file without +pushing the changes to git by accident. + +`git update-index --assume-unchanged upload.sh` + +After filling in the api_key, dashboard_id and url, open the terminal and run + +`bash upload.sh` + Refresh the Advanced Dashboard page in LANA PM and the dashboard should appear. ## Add Graphs, Interactions and Pages -This repository follows a basic structure to allow for multiple pages. Each page has its own URL with navigation enabled by the navbar at the top. The folder structure is as follows: + +This repository follows a basic structure to allow for multiple pages. Each page +has its own URL with navigation enabled by the navbar at the top. The folder +structure is as follows: ``` - app.py @@ -42,10 +73,14 @@ This repository follows a basic structure to allow for multiple pages. Each page |-- indicator_objects.py |-- api_requests.py ``` -Common functionality should be shared across pages using the `dashboard-components` submodule. Elements that have the same formatting should be defined as functions and not as copy pasted code. If API calls or data can be used by other functions, they should also be implemented in an accessible way. The more functions elements and functions are implemented, the fewer time it will take to build new dashboards. -On how to use submodules please see the Wiki entry here: -https://github.com/lanalabs/python-dashboard/wiki/Working-with-submodules-in-VS-Code - +Common functionality should be shared across pages using the +`dashboard-components` submodule. Elements that have the same formatting should +be defined as functions and not as copy pasted code. If API calls or data can be +used by other functions, they should also be implemented in an accessible way. +The more functions elements and functions are implemented, the fewer time it +will take to build new dashboards. On how to use submodules please see the Wiki +entry here: +https://github.com/lanalabs/python-dashboard/wiki/Working-with-submodules-in-VS-Code From 954a35a277a3d4764ae901b261b2e10e7ff92183 Mon Sep 17 00:00:00 2001 From: Akos Marton Date: Fri, 10 Dec 2021 18:44:19 +0100 Subject: [PATCH 03/11] Add a small executor script for quick iteration. --- develop.sh | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100755 develop.sh diff --git a/develop.sh b/develop.sh new file mode 100755 index 0000000..6486960 --- /dev/null +++ b/develop.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash + +set -e + +DASHBOARD_NAME="csimple" +ASSETSRC="simple_dashboard" +LOG_ID="3fc2d6e5-c9b8-4f5f-9167-8a6691a4b469" +API_KEY="abbbed8d6f5544c9873ee353d95d2fe4" +URL="http://localhost:4000" +ASSET="../upload.zip" + +while [ 1 ]; do + rm -f ${ASSET} + pushd $ASSETSRC && zip -r ${ASSET} * && popd + + DASHBOARD_ID=$(curl -X POST ${URL}/api/v2/custom-dashboards \ + -H "Authorization: API-Key ${API_KEY}" \ + -H "Content-Type: application/json" \ + --data-raw '{ + "name": "csimple", + "type": "python_dashboard" + }' | jq -r .id) + + echo "Advanced dashboard id: ${DASHBOARD_ID}" + + echo "Uploading ..." + + curl -X POST ${URL}/api/v2/custom-dashboards/${DASHBOARD_ID}/source \ + -H "Authorization: API-Key ${API_KEY}" \ + -F file=@"./upload.zip" + + echo "Connecting ..." + + curl -X POST ${URL}/api/v2/resource-connections \ + -H "Authorization: API-Key ${API_KEY}" \ + -H "Content-Type: application/json" \ + --data-raw '{ + "log_id":"'"${LOG_ID}"'", + "custom_dashboard_id":"'"${DASHBOARD_ID}"'" + }' 1>/dev/null + + echo + echo "Either press Ctrl-C to interrupt _or_ ENTER to clean up and move on!" + + read + + echo "DELETING" + + curl -X DELETE ${URL}/api/v2/custom-dashboards/${DASHBOARD_ID} \ + -H "Authorization: API-Key ${API_KEY}" \ + -H "Content-Type: application/json" + read +done + +exit 0 + + +# curl -X POST http://localhost:4000/api/v2/custom-dashboards/${DASHBOARD_ID}/source \ +# -H "Authorization: API-Key ${API_KEY}" \ +# -F file=@"./python_app.zip" + +# curl -X POST http://localhost:4000/api/v2/resource-connections \ +# -H "Authorization: API-Key ${API_KEY}" \ +# -H "Content-Type: application/json" \ +# --data-raw '{ +# "log_id":"'"${LOG_ID}"'", +# "custom_dashboard_id":"'"${DASHBOARD_ID}"'" +# }' + +# SHINY_ID=$(curl -X POST http://localhost:4000/api/v2/custom-dashboards \ +# -H "Authorization: API-Key ${API_KEY}" \ +# -H "Content-Type: application/json" \ +# --data-raw '{ +# "name": "Shining Shiny", +# "type": "shiny_dashboard" +# }' \ +# | jq -r .id) + +# echo "." +# echo $SHINY_ID +# echo "." +# curl -X POST http://localhost:4000/api/v2/custom-dashboards/${SHINY_ID}/source \ +# -H "Authorization: API-Key ${API_KEY}" \ +# -F file=@"./shiny_app.zip" + +# curl -X POST http://localhost:4000/api/v2/resource-connections \ +# -H "Authorization: API-Key ${API_KEY}" \ +# -H "Content-Type: application/json" \ +# --data-raw '{ +# "log_id":"'"${LOG_ID}"'", +# "custom_dashboard_id":"'"${SHINY_ID}"'" +# }' From afda559df8610e3b8428c3db26eae432f3f9b360 Mon Sep 17 00:00:00 2001 From: Akos Marton Date: Fri, 10 Dec 2021 18:51:37 +0100 Subject: [PATCH 04/11] Add and restructure the Readme file. --- README.md | 55 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 676a8a9..211d190 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,33 @@ +git submodule update --init --recursive + # Python Dashboard for Lana PM A documented example for python dashboards that can be used as a starting point for any new dashboards. The example shows a multipage app with a rather simple -page 1 and a more complicated page 2. Page one can be seen as an example of how -to create simple dashboard pages with elements being mostly independent of each -other. Page 2 shows a complicated case where a table can be updated by the user, -which then calculates the cost and updates a KPI below. Additionally a graph -shows the occurences of the event selected in the table. For documentation of -how to create plots, we refer to the documentation of Ploty and Dash. For an -explanation of how to make api requests to the backend please see the Pylana -Documentation and the api specifications of Lana Process Mining. +page-1 and a more complex page-2. + +* Page-1 can be seen as an example of how to create simple dashboard page with + elements being mostly independent of each other. + +* Page 2 shows a more complex case where a table can be updated by the user, + which then calculates the cost and updates a KPI below. -## Getting started +Additionally a graph shows the occurences of the event selected in the table. +For documentation of how to create plots, we refer to the documentation of Plotly +and Dash. For an explanation of how to make api requests to the backend please +see the Pylana documentation and the api specifications of Lana Process Mining. -### Install requirements +## Getting started for a local setup without Process Mining front-end + +TODO rephrase +### Preparing the local system Create a new conda environment using: -`conda create env --env name` +`conda-shell` +`conda create -n ` + +where __ is the name of the conda environment to be used. Activate that environment using: @@ -25,24 +35,41 @@ Activate that environment using: Install required packages: -`conda install requirements.txt` -`conda install lana_listener-0.0.1.tar.gz` +`conda install -u` + +`pip install pylana` +`pip install lana_listener-0.0.1.tar.gz` + +Where _pylana_ is available in public repository; +_lana-listener_ component shall be sourced as a ready made package from lanalabs/github. + +One may use a _requirements.txt_ to install generic dependencies into the +particular conda environment that is hosted natively on the local system in +order to develop the dashboard. Note that, these installed dependencies will not +be carried over into target system as installed ones! + +A requirements file may be used from the mining repository which is also used +for production setup to look up and install dependencies. +TODO ### Setting up configs and running the dashboard locally It is possible to run the dashboard independent of LANA PM. Simply fill in the API key and log_id into the `lana_listener` object and start `index.py`. +TODO where is it uploaded? local/production/cloud? +TODO Call it deployment instead of uploading. ### Uploading your first dashboard -Simply follow the steps in the jupyter-notebook to create a dashbaord and link +Simply follow the steps in the jupyter-notebook to create a dashboard and link it to the log. Once you have the `dashboard_id` and it is connected to the log, you will be able to upload source code either using the notebook, or using the `upload.sh` script. For a detailed instruction of how to upload also other types of dashboards, as well as a Bash and Python guide to upload, please see `UploadTutorial.pdf`. +TODO This is called replacing source code of an existing dashboard. ### Uploading (new) source-code First stop tracking the `upload.sh` file so that you can change the file without From 49d88c2c3558cc35eb22f6875106b2805e213ea2 Mon Sep 17 00:00:00 2001 From: Akos Marton Date: Mon, 13 Dec 2021 18:17:03 +0100 Subject: [PATCH 05/11] Another example with smaller number of features. --- .gitmodules | 3 ++ minimalistic_dashboard/api_calls.py | 16 ++++++++ minimalistic_dashboard/app.py | 30 ++++++++++++++ minimalistic_dashboard/apps/page_1.py | 43 +++++++++++++++++++++ minimalistic_dashboard/dashboard_components | 1 + minimalistic_dashboard/index.py | 25 ++++++++++++ 6 files changed, 118 insertions(+) create mode 100644 minimalistic_dashboard/api_calls.py create mode 100644 minimalistic_dashboard/app.py create mode 100644 minimalistic_dashboard/apps/page_1.py create mode 160000 minimalistic_dashboard/dashboard_components create mode 100644 minimalistic_dashboard/index.py diff --git a/.gitmodules b/.gitmodules index db2aae6..09e4ea4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "dashboard/dashboard_components"] path = dashboard/dashboard_components url = git@github.com:lanalabs/dashboard_components.git +[submodule "minimalistic_dashboard/dashboard_components"] + path = minimalistic_dashboard/dashboard_components + url = git@github.com:lanalabs/dashboard_components.git diff --git a/minimalistic_dashboard/api_calls.py b/minimalistic_dashboard/api_calls.py new file mode 100644 index 0000000..d84a2dc --- /dev/null +++ b/minimalistic_dashboard/api_calls.py @@ -0,0 +1,16 @@ +import json +import pylana + +from app import config +from dashboard_components.api_abstraction import aggregate + +def number_of_cases(log_id, api_key, tfs=[]) -> int: + """Returns the number of cases.""" + + df = aggregate(api_key, + trace_filter_sequence=tfs, + log_id=log_id, + metric="frequency", + aggregation_function="sum" + ) + return int(df["frequency"].iloc[0]) diff --git a/minimalistic_dashboard/app.py b/minimalistic_dashboard/app.py new file mode 100644 index 0000000..4d9d070 --- /dev/null +++ b/minimalistic_dashboard/app.py @@ -0,0 +1,30 @@ +import dash +import os +import dash_bootstrap_components as dbc + +from flask import Flask +from urllib.parse import urlparse + +try: + fooConfig = urlparse(os.environ['JANUS_URL']) + config = {"scheme": fooConfig.scheme, + "host": fooConfig.hostname, + "port": fooConfig.port, + "url": fooConfig.url, + "dashboard_id": os.path.basename(os.getcwd())} +except Exception: + config = {"scheme": "http", + "host": "janus", + "port": 4000, + "url": "http://localhost", + "dashboard_id": os.path.basename(os.getcwd())} + +application = Flask("example_dashboard") + +app = dash.Dash(name=__name__, + server=application, + suppress_callback_exceptions=True, + external_stylesheets=[dbc.themes.FLATLY], + url_base_pathname=f'/{config["dashboard_id"]}/') + +server = app.server diff --git a/minimalistic_dashboard/apps/page_1.py b/minimalistic_dashboard/apps/page_1.py new file mode 100644 index 0000000..f89a097 --- /dev/null +++ b/minimalistic_dashboard/apps/page_1.py @@ -0,0 +1,43 @@ +import lana_listener +import dash_html_components as html +import dash_bootstrap_components as dbc + +from app import app +from api_calls import number_of_cases +from dash.dependencies import Input, Output +from dashboard_components.indicator_objects import indicator_div, indicator_col + +llistener = lana_listener.LanaListener( + id='LanaListener', + lana_api_key='', + lana_log_id='', + lana_trace_filter_sequence='[]' +) + +layout = html.Div(children=[llistener, + html.Br(), + dbc.Row([dbc.Col(id="number_cases", width={"size": 3}), + dbc.Col(id="number_cases_tfs",width={"size": 3}) + ])]) + +@app.callback( + Output(component_id='number_cases', component_property='children'), + [Input('LanaListener', 'lana_api_key'), + Input('LanaListener', 'lana_log_id')] +) +def number_cases(api_key, log_id): + num_cases = number_of_cases(log_id, api_key) + ind = indicator_div(num_cases, title="Anzahl Cases (ohne TFS)") + return ind + +@app.callback( + Output(component_id='number_cases_tfs', component_property='children'), + [Input('LanaListener', 'lana_api_key'), + Input('LanaListener', 'lana_log_id'), + Input('LanaListener', 'lana_trace_filter_sequence')] +) +def number_case_tfs(api_key, log_id, tfs): + num_cases = number_of_cases(log_id, api_key, tfs) + ind = indicator_div(num_cases, title="Anzahl Cases (mit TFS)") + return ind + diff --git a/minimalistic_dashboard/dashboard_components b/minimalistic_dashboard/dashboard_components new file mode 160000 index 0000000..9ca27b4 --- /dev/null +++ b/minimalistic_dashboard/dashboard_components @@ -0,0 +1 @@ +Subproject commit 9ca27b4063c20bb68c2524f9d518e63128d4920b diff --git a/minimalistic_dashboard/index.py b/minimalistic_dashboard/index.py new file mode 100644 index 0000000..6d9a1f5 --- /dev/null +++ b/minimalistic_dashboard/index.py @@ -0,0 +1,25 @@ +import dash_core_components as dcc +import dash_html_components as html + +from app import app, application, config +from apps import page_1 +from dash.dependencies import Input, Output + +print(f"Server {str(application)} running.") + +app.layout = html.Div([ + dcc.Location(id='url', refresh=True), + html.Div(id='page-content') +]) + +@app.callback(Output('page-content', 'children'), + [Input('url', 'pathname')]) +def display_page(pathname): + dashboard_id = config["dashboard_id"] + if pathname == f'/{dashboard_id}/apps/app1': + return page_1.layout + else: + return page_1.layout + +if __name__ == '__main__': + app.run_server(debug=False) From 4ebd0dfa5affe6ea080faa6af7a1c7c8efc9bd3d Mon Sep 17 00:00:00 2001 From: Akos Marton Date: Mon, 13 Dec 2021 19:02:57 +0100 Subject: [PATCH 06/11] Resolve compiler warnings. --- minimalistic_dashboard/api_calls.py | 4 ---- minimalistic_dashboard/apps/page_1.py | 5 ++--- minimalistic_dashboard/index.py | 1 + 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/minimalistic_dashboard/api_calls.py b/minimalistic_dashboard/api_calls.py index d84a2dc..f021b14 100644 --- a/minimalistic_dashboard/api_calls.py +++ b/minimalistic_dashboard/api_calls.py @@ -1,7 +1,3 @@ -import json -import pylana - -from app import config from dashboard_components.api_abstraction import aggregate def number_of_cases(log_id, api_key, tfs=[]) -> int: diff --git a/minimalistic_dashboard/apps/page_1.py b/minimalistic_dashboard/apps/page_1.py index f89a097..9204c62 100644 --- a/minimalistic_dashboard/apps/page_1.py +++ b/minimalistic_dashboard/apps/page_1.py @@ -5,7 +5,7 @@ from app import app from api_calls import number_of_cases from dash.dependencies import Input, Output -from dashboard_components.indicator_objects import indicator_div, indicator_col +from dashboard_components.indicator_objects import indicator_div llistener = lana_listener.LanaListener( id='LanaListener', @@ -17,7 +17,7 @@ layout = html.Div(children=[llistener, html.Br(), dbc.Row([dbc.Col(id="number_cases", width={"size": 3}), - dbc.Col(id="number_cases_tfs",width={"size": 3}) + dbc.Col(id="number_cases_tfs", width={"size": 3}) ])]) @app.callback( @@ -40,4 +40,3 @@ def number_case_tfs(api_key, log_id, tfs): num_cases = number_of_cases(log_id, api_key, tfs) ind = indicator_div(num_cases, title="Anzahl Cases (mit TFS)") return ind - diff --git a/minimalistic_dashboard/index.py b/minimalistic_dashboard/index.py index 6d9a1f5..0c25b4a 100644 --- a/minimalistic_dashboard/index.py +++ b/minimalistic_dashboard/index.py @@ -21,5 +21,6 @@ def display_page(pathname): else: return page_1.layout + if __name__ == '__main__': app.run_server(debug=False) From 08bf40c8c95ae30448a594876961a0bb47f93c6f Mon Sep 17 00:00:00 2001 From: Akos Marton Date: Mon, 13 Dec 2021 22:36:58 +0100 Subject: [PATCH 07/11] Rewording and adding content to the ReadMe file. --- README.md | 78 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 211d190..e774b48 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ -git submodule update --init --recursive +develop.sh +emphaise what partial results and where can be accessed # Python Dashboard for Lana PM A documented example for python dashboards that can be used as a starting point -for any new dashboards. The example shows a multipage app with a rather simple -page-1 and a more complex page-2. +for any new dashboards. An example project _dashboards_ shows a multipage app +with a rather simple page-1 and a more complex page-2. * Page-1 can be seen as an example of how to create simple dashboard page with elements being mostly independent of each other. @@ -17,12 +18,29 @@ For documentation of how to create plots, we refer to the documentation of Plotl and Dash. For an explanation of how to make api requests to the backend please see the Pylana documentation and the api specifications of Lana Process Mining. +Additionally, a rather minimalistic dashboard is also provided by the project +_minimalistic\_dashboard_, which is potentially the simplest example that +involves the smallest set of external dependencies. + ## Getting started for a local setup without Process Mining front-end -TODO rephrase -### Preparing the local system +There are two potential ways to choose from for developing any dashboard, in +order to run the desired code: + - Running the entire system via docker-compose on a local computer. This + involves to be able to run _Process Mining_ as a whole. + - Developing the dashboard code independently and uploading the code + incrementally over and over again until ready to some remotely available + setup. (not recommended) + +### Preparing a (your) local system + for using Python + +Make sure the submodules are pulled and up-to-date on the example project of +your interest, execute in the root of this repository: -Create a new conda environment using: +`git submodule update --init --recursive` + +Create a new conda environment using in one of the example project folder: `conda-shell` `conda create -n ` @@ -46,21 +64,22 @@ _lana-listener_ component shall be sourced as a ready made package from lanalabs One may use a _requirements.txt_ to install generic dependencies into the particular conda environment that is hosted natively on the local system in order to develop the dashboard. Note that, these installed dependencies will not -be carried over into target system as installed ones! +be carried over onto the target system as installed ones! + +When the setup of the local system and the remote system diverges, e.g. +supported python versions, available dependencies, etc; that may result in +failure. -A requirements file may be used from the mining repository which is also used -for production setup to look up and install dependencies. +A __requirements.txt_ file may be used, that is defined in the mining repository's +container setup that is actually used for production setup. -TODO ### Setting up configs and running the dashboard locally It is possible to run the dashboard independent of LANA PM. Simply fill in the API key and log_id into the `lana_listener` object and start -`index.py`. +`index.py` in your own python (potentially _conda_) environment. -TODO where is it uploaded? local/production/cloud? -TODO Call it deployment instead of uploading. -### Uploading your first dashboard +### Deploying your dashboard Simply follow the steps in the jupyter-notebook to create a dashboard and link it to the log. Once you have the `dashboard_id` and it is connected to the @@ -69,15 +88,16 @@ the `upload.sh` script. For a detailed instruction of how to upload also other types of dashboards, as well as a Bash and Python guide to upload, please see `UploadTutorial.pdf`. -TODO This is called replacing source code of an existing dashboard. -### Uploading (new) source-code +### Uploading/replacing source-code of an existing Advanced dashboard -First stop tracking the `upload.sh` file so that you can change the file without -pushing the changes to git by accident. +First, stop tracking the `upload.sh` file by git on your local machine, so that +you can modify its content without making actual changes to the original version +in the repository, by accident. `git update-index --assume-unchanged upload.sh` -After filling in the api_key, dashboard_id and url, open the terminal and run +After assigning value to the `API_KEY`, `DASHBOARD_ID` and `URL` variables +respectively in the `upload.sh` scipt, open a terminal and execute it: `bash upload.sh` @@ -85,8 +105,8 @@ Refresh the Advanced Dashboard page in LANA PM and the dashboard should appear. ## Add Graphs, Interactions and Pages -This repository follows a basic structure to allow for multiple pages. Each page -has its own URL with navigation enabled by the navbar at the top. The folder +The provided _dashboards_ project example follows a basic structure to allow for multiple pages. Each page +has its own URL with navigation enabled by the navigation-bar at the top. The folder structure is as follows: ``` @@ -101,13 +121,13 @@ structure is as follows: |-- api_requests.py ``` -Common functionality should be shared across pages using the -`dashboard-components` submodule. Elements that have the same formatting should -be defined as functions and not as copy pasted code. If API calls or data can be -used by other functions, they should also be implemented in an accessible way. -The more functions elements and functions are implemented, the fewer time it -will take to build new dashboards. On how to use submodules please see the Wiki -entry here: - +Common functionalities should be shared across pages using the +`dashboard-components` git-submodule. Elements that have the same formatting +should be defined as functions and not as copy pasted code. In case API calls or +data needs to be used by any other function, those should also be implemented in +an accessible way. The more function elements and functions are implemented, +the fewer time it will take to build new dashboards. On how to use submodules +please see the Wiki entry here: https://github.com/lanalabs/python-dashboard/wiki/Working-with-submodules-in-VS-Code +. From 193b88b656c69efab11af885dbe788acd325bc3c Mon Sep 17 00:00:00 2001 From: Akos Marton Date: Mon, 13 Dec 2021 23:01:35 +0100 Subject: [PATCH 08/11] fixup! Add a small executor script for quick iteration. --- develop.sh | 38 +------------------------------------- 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/develop.sh b/develop.sh index 6486960..15e51b8 100755 --- a/develop.sh +++ b/develop.sh @@ -2,6 +2,7 @@ set -e +# TODO Remove secrets DASHBOARD_NAME="csimple" ASSETSRC="simple_dashboard" LOG_ID="3fc2d6e5-c9b8-4f5f-9167-8a6691a4b469" @@ -53,40 +54,3 @@ while [ 1 ]; do done exit 0 - - -# curl -X POST http://localhost:4000/api/v2/custom-dashboards/${DASHBOARD_ID}/source \ -# -H "Authorization: API-Key ${API_KEY}" \ -# -F file=@"./python_app.zip" - -# curl -X POST http://localhost:4000/api/v2/resource-connections \ -# -H "Authorization: API-Key ${API_KEY}" \ -# -H "Content-Type: application/json" \ -# --data-raw '{ -# "log_id":"'"${LOG_ID}"'", -# "custom_dashboard_id":"'"${DASHBOARD_ID}"'" -# }' - -# SHINY_ID=$(curl -X POST http://localhost:4000/api/v2/custom-dashboards \ -# -H "Authorization: API-Key ${API_KEY}" \ -# -H "Content-Type: application/json" \ -# --data-raw '{ -# "name": "Shining Shiny", -# "type": "shiny_dashboard" -# }' \ -# | jq -r .id) - -# echo "." -# echo $SHINY_ID -# echo "." -# curl -X POST http://localhost:4000/api/v2/custom-dashboards/${SHINY_ID}/source \ -# -H "Authorization: API-Key ${API_KEY}" \ -# -F file=@"./shiny_app.zip" - -# curl -X POST http://localhost:4000/api/v2/resource-connections \ -# -H "Authorization: API-Key ${API_KEY}" \ -# -H "Content-Type: application/json" \ -# --data-raw '{ -# "log_id":"'"${LOG_ID}"'", -# "custom_dashboard_id":"'"${SHINY_ID}"'" -# }' From 54fe390d413f2a0e804ebd97c62f2633de4a71fe Mon Sep 17 00:00:00 2001 From: Akos Marton Date: Tue, 14 Dec 2021 10:19:59 +0100 Subject: [PATCH 09/11] Improve prompting in the develop loop script. --- develop.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/develop.sh b/develop.sh index 15e51b8..2cce73c 100755 --- a/develop.sh +++ b/develop.sh @@ -45,11 +45,13 @@ while [ 1 ]; do read - echo "DELETING" + echo "DELETING dashboard ..." curl -X DELETE ${URL}/api/v2/custom-dashboards/${DASHBOARD_ID} \ -H "Authorization: API-Key ${API_KEY}" \ -H "Content-Type: application/json" + + echo "Press Enter to move on!" read done From 518f29e38d8c7adbbcdedeb8b6e8357721cb79cf Mon Sep 17 00:00:00 2001 From: Akos Marton Date: Wed, 15 Dec 2021 10:40:23 +0100 Subject: [PATCH 10/11] Leverage `set -e` --- develop.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/develop.sh b/develop.sh index 2cce73c..10b4634 100755 --- a/develop.sh +++ b/develop.sh @@ -11,8 +11,10 @@ URL="http://localhost:4000" ASSET="../upload.zip" while [ 1 ]; do - rm -f ${ASSET} - pushd $ASSETSRC && zip -r ${ASSET} * && popd + rm -f $ASSET + pushd $ASSETSRC + zip -r $ASSET * + popd DASHBOARD_ID=$(curl -X POST ${URL}/api/v2/custom-dashboards \ -H "Authorization: API-Key ${API_KEY}" \ From aa06d9ec4ded073d5d86250709418b128bf3543e Mon Sep 17 00:00:00 2001 From: Akos Marton Date: Tue, 21 Dec 2021 14:44:21 +0100 Subject: [PATCH 11/11] Formatting and cleanup. --- develop.sh | 9 ++++----- minimalistic_dashboard/api_calls.py | 10 ++++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/develop.sh b/develop.sh index 10b4634..b630499 100755 --- a/develop.sh +++ b/develop.sh @@ -1,12 +1,11 @@ #!/usr/bin/env bash -set -e +#set -e -# TODO Remove secrets +LOG_ID="" +API_KEY="" DASHBOARD_NAME="csimple" -ASSETSRC="simple_dashboard" -LOG_ID="3fc2d6e5-c9b8-4f5f-9167-8a6691a4b469" -API_KEY="abbbed8d6f5544c9873ee353d95d2fe4" +ASSETSRC="minimalistic_dashboard" URL="http://localhost:4000" ASSET="../upload.zip" diff --git a/minimalistic_dashboard/api_calls.py b/minimalistic_dashboard/api_calls.py index f021b14..09e6c75 100644 --- a/minimalistic_dashboard/api_calls.py +++ b/minimalistic_dashboard/api_calls.py @@ -1,12 +1,18 @@ +import requests +import argparse +import ast + from dashboard_components.api_abstraction import aggregate -def number_of_cases(log_id, api_key, tfs=[]) -> int: +def number_of_cases(log_id, auth_token, tfs=[]) -> int: """Returns the number of cases.""" - df = aggregate(api_key, + df = aggregate(auth_token, trace_filter_sequence=tfs, log_id=log_id, metric="frequency", aggregation_function="sum" ) return int(df["frequency"].iloc[0]) + +