An open-source tool for visual and modular block programing in python

Overview

PyFlow

Pytest badge Codacy Badge Pylint badge Total coverage Codacy Badge Unit coverage badge Integration coverage badge Licence - GPLv3 PRs Welcome

PyFlow is an open-source tool for modular visual programing in python !

Although for now the tool is in Beta and features are coming in bit by bit, stay tuned for the first release soon !

Help the project !

Join our Discord to beta-test features, share your ideas or even contribute !

Features

  • Put your python code in small interconnected blocks

  • Export and Import your graphs and share them with other people in the new Interactive PYthon Graph format (.ipyg)

  • Chain your blocks to perform complex functions.

Installation

Make sure you have Python 3 installed. You can download it from here

Clone the current repo:

git clone https://github.com/MathisFederico/OpenCodeBlocks/

Install the dependencies

pip install -r requirements.txt

Run !

python -m opencodeblocks optional_path_to_ipyg

Contributing

If you are interested in contributing to the project, see CONTRIBUTING.md.

License

See LICENSE

Comments
  • Add ipynb conversion

    Add ipynb conversion

    This is a draft, many required features are missing. What is there

    1. A basic converter which uses the default code block and fills it with the pieces of codes, and align them left to right
    2. The load button now supports loading a ipynb file What is missing
    3. Many crucial things (such as markdown and outputs) are ignored by the converter (see the TODOs in the python file)
    4. There is not dedicated "load ipynb button" for now. It works with the load button when a .ipynb file is selected.
    5. Unit tests might be required for this one, but are not yet present
    opened by FabienRoger 11
  • :tada: Adds Visual Flow

    :tada: Adds Visual Flow

    https://user-images.githubusercontent.com/62465003/145698162-1afec762-46e0-4770-9be7-2a928c58af22.mp4

    Pressing a run button will now highlight in green the graph traversal that is made to gather the blocks to run Running blocks are now highlighted in red

    Closes #66

    enhancement 
    opened by AlexandreSajus 5
  • Vertical structure

    Vertical structure

    To help with lowering the barrier of entry between Jupyter and Pyflow, we could adopt a vertical structure where blocks are aligned top to bottom instead of left to right.

    A good first step towards this would be having top and bottom sockets

    enhancement 
    opened by AlexandreSajus 4
  • 🛠️Execution Refactor & 🎉 Nested Nodes

    🛠️Execution Refactor & 🎉 Nested Nodes

    A lot of new blocks have been added but they are not executable yet !

    This pull request aims to:

    • Make the new blocks like slider executable
    • Polish the executing code
    • Fix some bugs
    • Introduce new node types

    While this might seem like multiple features added at once, because they are all deeply intertwined, it makes sense to group them in the same branch. More specifically, we will try to fix:

    • #112
    • Tests to prevent #112 regressions
    • #94
    • Tests to prevent #94 regressions
    • #5
    opened by vanyle 4
  • Add new shortcuts for block creations

    Add new shortcuts for block creations

    In a Jupyter notebook, adding new blocks is easy. Just press "Shift+Enter" and it adds a new block after executing the current one. In OCB, for now, you have to right-click, new block, and link it with the previous one, which is cumbersome.

    The new shortcuts which could be added:

    • Shift+ Arrow to add a new block linked to the current one in the direction of the arrow and launch the execution of the current cell
    • Shift+ Enter to add a new block linked to the current one to the right and launch the execution of the current cell
    • Control + Enter to execute the current cell
    • Something to insert a cell between two others (this is really slow with the current system)
    enhancement 
    opened by FabienRoger 4
  • :tada: Add editing navigation using alt & escape

    :tada: Add editing navigation using alt & escape

    Adds:

    • Navigation can be trigger from inside editors using alt+arrow
    • Editing mode can be entered from navigation using alt
    • Selection & Focus can be cleared using escape
    opened by MathisFederico 3
  • 🎉 🎨 Add persistent colors

    🎉 🎨 Add persistent colors

    Add persistent colors to ease the user comprehension and let him remember what was run. Fixes #272 Refactored 'run_state' and 'has_been_run' using Enum for better maintenance.

    opened by MathisFederico 3
  • stdout is not correctly rendered in some cases

    stdout is not correctly rendered in some cases

    import pandas as pd
    
    d = {'col1':[1,2],'col2':[3,4]}
    df = pd.DataFrame(data=d)
    
    df.describe()
    

    On a jupyter notebook, the code above renders a pretty image: image

    This is not the case currently: image

    bug 
    opened by vanyle 3
  • Execution Flow

    Execution Flow

    Executing a cell should trigger other cells depending of the graph.

    • Cells before should be run if they have not already or have been modified
    • Cells after should be run if the socket allows for it depending on socket flowtype (#47)

    This should be sequentially at first, in a depth-first or breadth-first manner (this could be a user choice for both before and after cells).

    enhancement 
    opened by MathisFederico 3
  • PyFlow crashes because undefined symbol: _ZdlPvm

    PyFlow crashes because undefined symbol: _ZdlPvm

    Installation goes normally and without error. But try to run PyFlow and there is a message about an undefined symbol _ZdlPvm. What might the remedy be?

    python3 -m pyflow
    Traceback (most recent call last):
      File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
        return _run_code(code, main_globals, None,
      File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
        exec(code, run_globals)
      File "/home/johnb/.local/lib/python3.9/site-packages/pyflow/__main__.py", line 22, in <module>
        from pyflow.graphics.window import Window
      File "/home/johnb/.local/lib/python3.9/site-packages/pyflow/graphics/window.py", line 22, in <module>
        from pyflow.graphics.widget import Widget
      File "/home/johnb/.local/lib/python3.9/site-packages/pyflow/graphics/widget.py", line 11, in <module>
        from pyflow.scene import Scene
      File "/home/johnb/.local/lib/python3.9/site-packages/pyflow/scene/__init__.py", line 6, in <module>
        from pyflow.scene.scene import Scene
      File "/home/johnb/.local/lib/python3.9/site-packages/pyflow/scene/scene.py", line 17, in <module>
        from pyflow.blocks.block import Block
      File "/home/johnb/.local/lib/python3.9/site-packages/pyflow/blocks/__init__.py", line 7, in <module>
        from pyflow.blocks.codeblock import CodeBlock
      File "/home/johnb/.local/lib/python3.9/site-packages/pyflow/blocks/codeblock.py", line 15, in <module>
        from pyflow.blocks.pyeditor import PythonEditor
      File "/home/johnb/.local/lib/python3.9/site-packages/pyflow/blocks/pyeditor.py", line 18, in <module>
        from PyQt5.Qsci import QsciScintilla, QsciLexerPython
    ImportError: /home/johnb/.local/lib/python3.9/site-packages/PyQt5/Qsci.abi3.so: undefined symbol: _ZdlPvm, version Qt_5
    

    System info:

    qmake --version
    QMake version 3.1
    Using Qt version 5.15.2 in /usr/lib/x86_64-linux-gnu
    
    python3 --version
    Python 3.9.7
    
    cat /etc/lsb-release
    DISTRIB_ID=Pop
    DISTRIB_RELEASE=21.10
    DISTRIB_CODENAME=impish
    DISTRIB_DESCRIPTION="Pop!_OS 21.10"
    
    qtdiag
    Qt 5.15.2 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 11.2.0) on "xcb" 
    OS: Pop!_OS 21.10 [linux version 5.16.11-76051611-generic]
    
    Architecture: x86_64; features: SSE2 SSE3 SSSE3 SSE4.1 SSE4.2 AVX AVX2
    <snip>
    
    opened by johnblommers 2
  • Run right does not work: it executes itself multiple times

    Run right does not work: it executes itself multiple times

    Steps to reproduce: Take the flow_test asset and add "counter += 1" in Cell 5 in the middle. Initialize the counter elsewhere. Run right the cell with the "counter += 1" Print what is in the counter elsewhere. It contains 4.

    image

    bug 
    opened by FabienRoger 2
  • Separate graphs should have different variables spaces

    Separate graphs should have different variables spaces

    Graphs that are not connected together should work on separate kernels so that if the same variable name exists in both graphs, changing the variable in one graph should not change the variable in the other graph

    For example: image

    This seems wrong

    enhancement 
    opened by AlexandreSajus 1
  • Duplicating saves to clipboard permanently

    Duplicating saves to clipboard permanently

    Duplicating a block using Ctrl + D saves the block to clipboard permanently. Trying to Ctrl + C then Ctrl + V after duplicating will paste the duplicating block instead of the Ctrl + C one.

    Duplicating should not save to clipboard and should not hinder copy pasting

    bug 
    opened by AlexandreSajus 0
  • Dragging an edge on a block should highlight the block

    Dragging an edge on a block should highlight the block

    During closed beta 2, a user complained about not getting feedback when dragging an edge onto a block.

    He suggested that the block should be highlighted when dragging an edge over it to explain that the edge will connect to the block when dropped.

    In this situation: image

    The block should be highlighted

    enhancement 
    opened by AlexandreSajus 0
Releases(v1.0.0)
  • v1.0.0(Feb 24, 2022)

    PyFlow - Release 1.0.0

    First Full Release

    We are happy to release the first full version of PyFlow by Bycelium ! Feel free to reach us on discord for feedback, suggestions, contribution or a simple chat !

    What's Changed

    • :beetle: Fix block execution freeze by @AlexandreSajus in #138
    • :beetle: Fix zoom stuck by @FabienRoger in #145
    • :beetle: Fix socket missing when converting from .ipynb by @FabienRoger in #143
    • :beetle: Fix execution of complex ipynb by @AlexandreSajus in #147
    • :beetle: Deal with ipynb of different format by @FabienRoger in #221
    • :tada: Sort blocks when saving as ipynb by @FabienRoger in #144
    • :beetle: Paste exactly where the mouse is by @FabienRoger in #224
    • :tada: Restrict file loading to .ipyg and .ipynb by @FabienRoger in #223
    • :beetle: Fix click-selection bug by @FabienRoger in #226
    • 🎉 Create a distinct clipboard for blocks by @FabienRoger in #229
    • 🎉:art: Switch to vertical layout by @FabienRoger in #227
    • :tada: Add logging & improve CLI by @MathisFederico in #231
    • :tada: Add custom undo system by @FabienRoger in #118
    • :tada: Make execution flow ignore off-sockets by @FabienRoger in #255
    • 🎉 Add socket on/off toggle by @FabienRoger in #254
    • :tada: Create a new add socket button by @FabienRoger in #249
    • :art: Make blocks output more visible by @FabienRoger in #257
    • :art: Highlight the add edge button on block hover by @FabienRoger in #258
    • :beetle: Removes kernel timeout by @AlexandreSajus in #259
    • ☔ Add python 3.10 support by @MathisFederico in #262
    • :tada: Add interrupt execution on error by @AlexandreSajus in #265
    • 🪲 Fix block removing crash by @FabienRoger in #267
    • :tada: Add button to create linked block by @AlexandreSajus in #266
    • :tada: Improve markdown editing by @FabienRoger in #269
    • :tada: Add new shortcuts by @AlexandreSajus in #264
    • 🎉 Make shift+enter in editor run left by @FabienRoger in #270
    • :tada: Add prompt before exiting the program by @FabienRoger in #271
    • :beetle: Prevent crash when there is a loop by @FabienRoger in #279
    • 🎉 🎨 Add persistent colors by @MathisFederico in #276
    • :beetle: Prevent checkpoint when the scene has not changed by @FabienRoger in #281
    • :art: Set exit font color to white by @AlexandreSajus in #285
    • :tada: Add zoom in and out shortcut by @FabienRoger in #286
    • :beetle: Fix Ctrl+z crash by @FabienRoger in #289
    • :tada: Add editing navigation using alt & escape by @MathisFederico in #287
    • :art: updated gifs and README by @AlexandreSajus in #290

    Full Changelog: https://github.com/Bycelium/PyFlow/compare/v1.0.0-beta...v1.0.0

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-beta(Jan 8, 2022)

    PyFlow - Release 1.0.0-beta

    First Beta Release

    We are happy to release the first beta version of PyFlow by Bycelium ! More is to come as we will have our features tested in the following weeks ! Feel free to reach us on discord for feedback, suggestions, contribution or a simple chat !

    What's Changed

    • :tada: Add base node editor application inspired from this tutorials series by @MathisFederico
    • :tada: Bring selected blocks to the front. by @vanyle in https://github.com/Bycelium/PyFlow/pull/11
    • :memo: Write a CONTRIBUTING file with contributing guidelines by @vanyle in https://github.com/Bycelium/PyFlow/pull/13
    • :beetle: Fix the null pointer error issue when deleting a code block by @vanyle in https://github.com/Bycelium/PyFlow/pull/14
    • 📝 Add docstrings to graphics classes by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/15
    • :tada: Add multiple windows handleling by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/18
    • :beetle: Fix cursor and resize by @vanyle in https://github.com/Bycelium/PyFlow/pull/29
    • :tada: Add select pasted items by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/30
    • ☔ Integration tests by @vanyle in https://github.com/Bycelium/PyFlow/pull/31
    • :wrench: ☔ Refactor integration tests by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/34
    • :tada: :art: Syntax highlighting and Themes by @vanyle in https://github.com/Bycelium/PyFlow/pull/33
    • :tada: Add IPython kernel by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/17
    • :tada: Add IPython console by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/38
    • :memo: :art: better readme gif by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/39
    • ✨ Autopep8, shorter lines, docstring and removed unnecessary function by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/40
    • 📝 ☔ Add codacy workflow and total coverage badge by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/45
    • 🔨 Sizes and widgets refactor by @vanyle in https://github.com/Bycelium/PyFlow/pull/41
    • :tada: :art: Adds ANSI color coding support in codeblocks by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/53
    • 🎉 Add saves and loads codeblock output by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/55
    • :tada: Add separate threads for GUI and Kernel by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/58
    • :tada: Add socket flow type by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/59
    • :tada: New block creation by @vanyle in https://github.com/Bycelium/PyFlow/pull/60
    • :art: Increases output fontsize by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/69
    • 🎉 Prevent bad autoscroll in PyEditor by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/73
    • :tada: Add arrow navigation from block to block by @vanyle in https://github.com/Bycelium/PyFlow/pull/74
    • :tada: 🔨 Improve autoscroll & Tests refactor by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/77
    • :beetle: Improve codeblock displays for tensorflow history by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/79
    • :tada: Add open example from command line by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/78
    • :beetle: Hide output panel without output by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/70
    • :tada: Editable titles and :wrench: Refactor of block widgets by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/81
    • Add move to global view by @FabienRoger in https://github.com/Bycelium/PyFlow/pull/84
    • :memo: Add Discord link and beta disclaimer by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/87
    • :tada: Add support for new block types by @vanyle in https://github.com/Bycelium/PyFlow/pull/80
    • 🎉 Add sockets on codeblocks by default by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/89
    • :tada: Functional flow execution by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/98
    • :tada: Add zoom on blocks pressing spacebar by @FabienRoger in https://github.com/Bycelium/PyFlow/pull/91
    • 🎉 Improve arrow navigation by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/99
    • :beetle: Fix splitter position saving by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/101
    • :beetle: Add html output support by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/102
    • :beetle: Add indentation in pyeditor by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/104
    • 🪲 Fix 'Save As' bug by @FabienRoger in https://github.com/Bycelium/PyFlow/pull/107
    • :beetle: Fix saving bug by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/105
    • :tada: Adds the ability to cancel execution by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/103
    • :sparkles: switched autopep8 to black by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/115
    • :tada: Add notebook-pygraph conversion by @FabienRoger in https://github.com/Bycelium/PyFlow/pull/86
    • 🪲 Fix default fields handling by @FabienRoger in https://github.com/Bycelium/PyFlow/pull/96
    • :umbrella: Add execution flow testing by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/116
    • :sparkles: Apply black formatter to everything by @FabienRoger in https://github.com/Bycelium/PyFlow/pull/120
    • :memo: Improve CONTRIBUTING.md by @FabienRoger in https://github.com/Bycelium/PyFlow/pull/121
    • :umbrella: Add unit tests to ipynb conversion by @FabienRoger in https://github.com/Bycelium/PyFlow/pull/117
    • 🛠️ Execution Refactor & 🎉 Nested Nodes by @vanyle in https://github.com/Bycelium/PyFlow/pull/113
    • :tada: Add Visual Flow by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/114
    • :beetle: Fix editing a block resets output's states by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/127
    • 🪲 Fix bug related to ipynb conversion by @FabienRoger in https://github.com/Bycelium/PyFlow/pull/129
    • 📝 🎨 Adds gifs describing each main feature on README.md by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/130
    • :beetle: fixes run_right without output by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/134
    • 🔨 Huge refactor before release by @AlexandreSajus in https://github.com/Bycelium/PyFlow/pull/133
    • :tada: Released the beta 1.0.0 by @MathisFederico in https://github.com/Bycelium/PyFlow/pull/135

    New Contributors

    • @vanyle made their first contribution in https://github.com/Bycelium/PyFlow/pull/10
    • @AlexandreSajus made their first contribution in https://github.com/Bycelium/PyFlow/pull/17
    • @FabienRoger made their first contribution in https://github.com/Bycelium/PyFlow/pull/84
    Source code(tar.gz)
    Source code(zip)
BGraph is a tool designed to generate dependencies graphs from Android.bp soong files.

BGraph BGraph is a tool designed to generate dependencies graphs from Android.bp soong files. Overview BGraph (for Build-Graphs) is a project aimed at

Quarkslab 10 Dec 19, 2022
The official colors of the FAU as matplotlib/seaborn colormaps

FAU - Colors The official colors of Friedrich-Alexander-Universität Erlangen-Nürnberg (FAU) as matplotlib / seaborn colormaps. We support the old colo

Machine Learning and Data Analytics Lab FAU 9 Sep 05, 2022
A Python toolbox for gaining geometric insights into high-dimensional data

"To deal with hyper-planes in a 14 dimensional space, visualize a 3D space and say 'fourteen' very loudly. Everyone does it." - Geoff Hinton Overview

Contextual Dynamics Laboratory 1.8k Dec 29, 2022
Pretty Confusion Matrix

Pretty Confusion Matrix Why pretty confusion matrix? We can make confusion matrix by using matplotlib. However it is not so pretty. I want to make con

Junseo Ko 5 Nov 22, 2022
web application for flight log analysis & review

Flight Review This is a web application for flight log analysis. It allows users to upload ULog flight logs, and analyze them through the browser. It

PX4 Drone Autopilot 145 Dec 20, 2022
script to generate HeN ipfs app exports of GLSL shaders

HeNerator A simple script to generate HeN ipfs app exports from any frag shader created with: GlslViewer GlslEditor The Book of Shaders glslCanvas VS

Patricio Gonzalez Vivo 22 Dec 21, 2022
Rick and Morty Data Visualization with python

Rick and Morty Data Visualization For this project I looked at data for the TV show Rick and Morty Number of Episodes at a Certain Location Here is th

7 Aug 29, 2022
Color maps for POV-Ray v3.7 from the Plasma, Inferno, Magma and Viridis color maps in Python's Matplotlib

POV-Ray-color-maps Color maps for POV-Ray v3.7 from the Plasma, Inferno, Magma and Viridis color maps in Python's Matplotlib. The include file Color_M

Tor Olav Kristensen 1 Apr 05, 2022
The windML framework provides an easy-to-use access to wind data sources within the Python world, building upon numpy, scipy, sklearn, and matplotlib. Renewable Wind Energy, Forecasting, Prediction

windml Build status : The importance of wind in smart grids with a large number of renewable energy resources is increasing. With the growing infrastr

Computational Intelligence Group 125 Dec 24, 2022
Compute and visualise incidence (reworking of the original incidence package)

incidence2 incidence2 is an R package that implements functions and classes to compute, handle and visualise incidence from linelist data. It refocuss

15 Nov 22, 2022
Visualize your pandas data with one-line code

PandasEcharts 简介 基于pandas和pyecharts的可视化工具 安装 pip 安装 $ pip install pandasecharts 源码安装 $ git clone https://github.com/gamersover/pandasecharts $ cd pand

陈华杰 2 Apr 13, 2022
It's an application to calculate I from v and r. It can also plot a graph between V vs I.

Ohm-s-Law-Visualizer It's an application to calculate I from v and r using Ohm's Law. It can also plot a graph between V vs I. Story I'm doing my Unde

Sihab Sahariar 1 Nov 20, 2021
RockNext is an Open Source extending ERPNext built on top of Frappe bringing enterprise ready utilization.

RockNext is an Open Source extending ERPNext built on top of Frappe bringing enterprise ready utilization.

Matheus Breguêz 13 Oct 12, 2022
A Python-based non-fungible token (NFT) generator built using Samilla and Matplotlib

PyNFT A Pythonic NF (non-fungible token) generator built using Samilla and Matplotlib Use python pynft.py [amount] The intention behind this generato

Ayush Gundawar 6 Feb 07, 2022
Visualize data of Vietnam's regions with interactive maps.

Plotting Vietnam Development Map This is my personal project that I use plotly to analyse and visualize data of Vietnam's regions with interactive map

1 Jun 26, 2022
eoplatform is a Python package that aims to simplify Remote Sensing Earth Observation by providing actionable information on a wide swath of RS platforms and provide a simple API for downloading and visualizing RS imagery

An Earth Observation Platform Earth Observation made easy. Report Bug | Request Feature About eoplatform is a Python package that aims to simplify Rem

Matthew Tralka 4 Aug 11, 2022
Dimensionality reduction in very large datasets using Siamese Networks

ivis Implementation of the ivis algorithm as described in the paper Structure-preserving visualisation of high dimensional single-cell datasets. Ivis

beringresearch 284 Jan 01, 2023
A python package for animating plots build on matplotlib.

animatplot A python package for making interactive as well as animated plots with matplotlib. Requires Python = 3.5 Matplotlib = 2.2 (because slider

Tyler Makaro 394 Dec 18, 2022
An XLSX spreadsheet renderer for Django REST Framework.

drf-renderer-xlsx provides an XLSX renderer for Django REST Framework. It uses OpenPyXL to create the spreadsheet and returns the data.

The Wharton School 166 Dec 01, 2022
An interactive dashboard built with python that enables you to visualise how rent prices differ across Sweden.

sweden-rent-dashboard An interactive dashboard built with python that enables you to visualise how rent prices differ across Sweden. The dashboard/web

Rory Crean 5 Dec 19, 2021