Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/gfarrell/grasana
Represent Asana projects as graphs (well, trees mostly)
https://github.com/gfarrell/grasana
Last synced: about 22 hours ago
JSON representation
Represent Asana projects as graphs (well, trees mostly)
- Host: GitHub
- URL: https://github.com/gfarrell/grasana
- Owner: gfarrell
- License: bsd-3-clause
- Created: 2021-07-24T13:39:02.000Z (over 3 years ago)
- Default Branch: trunk
- Last Pushed: 2021-07-25T14:22:09.000Z (over 3 years ago)
- Last Synced: 2024-11-16T14:11:42.674Z (2 months ago)
- Language: Haskell
- Size: 182 KB
- Stars: 3
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Grasana
Grasana is a tool for representing Asana projects as graphs (well, mostly as
trees actually). It can output the following formats:- DOT: the graphviz DOT language
- HTML: an HTML page complete with D3 to render the graph nicely and
interactively
- JSON: representing either in graph form or tree form in JSONThere are two representations Grasana uses for projects: "graph" form and "tree"
form. The graph form represents the project as a tuple containing a list of
tasks and a list of edges (relations between tasks). Edges can represent either
subtask relations or dependencies (NB. Grasana does not currently parse
dependencies, only subtasks). The tree form represents the project as a tree in
which each node has an `id`, a `name`, and `children` (a list of child nodes).The `DOT` output format uses the graph representation, whereas the `HTML` format
technically uses the tree representation under the hood. You can output either
graph or tree form when using the `JSON` format## Building and installing
There are two parts of Grasana: a typescript part and a Haskell part. The
typescript part is for the HTML output to make a nice tree viewer.### Dependencies
In order to build this project you will need to install:
- [stack](haskellstack.org)
- [ghc](https://www.haskell.org/ghc/) >= 8.10
- [nodejs](nodejs.org/)
- [yarn](classic.yarnpkg.com) (v1)### Building
You can build the `grasana` executable by running `make dist/grasana`.
If it already exists, run `make clean` first. The executable will then
be copied, somewhat unsurprisingly, to `dist/grasana`.### Installing
If you want to install the binary you can run `make install` which will
clean, build, and then copy the binary to your local binary path (you
can find out what this is by running `stack path --local-bin`, the
default is `$HOME/.local/bin`). You will now be able to run `grasana` from
wherever you like!## Usage
grasana format [-t token] projectid
* `format`: can be one of `html`, `dot`, `jsontree`, or `jsongraph`;
* `token`: your [Asana PAT][asana-pat] (optionally as an environment variable
instead to keep it out of your command history);
* `projectid`: the id of the project you want to represent graphically.[asana-pat]: https://developers.asana.com/docs/personal-access-token
### Example: using environment variables
To avoid having to pass your Asana personal access token explicitly on
the command line you can set it in your shell's environment, for example
if you had a file called `secrets.env` with the following contents, you
could run `. ./secrets.env && grasana format projectid`.ASANA_PAT=""
### Example: rendering immediately with graphviz
If you have [graphviz](https://graphviz.org/) installed, you can use it to
immediately render your project as an SVG.grasana dot | dot -Tsvg > ./project.svg
## Testing
Some (but not all) of grasana has unit tests, just run `stack test` to go
through the spec. All tests specs are written using `Hspec` and can be found in
the `/test` directory.stack test
### Mocking HTTP Requests
I haven't yet worked out a good way to do this in Haskell so everything which
touches the Asana API via HTTP requests lacks unit tests. I have some ideas,
however, inspired by the following resources:- https://making.pusher.com/unit-testing-io-in-haskell/
- https://lexi-lambda.github.io/blog/2017/06/29/unit-testing-effectful-haskell-with-monad-mock/This might look something along the lines of a specialised Monad for HTTP:
class Monad m => MonadHTTP m where
httpJSON :: Network.HTTP.Simple.Request -> m (Network.HTTP.Simple.Response Data.ByteString.Lazy.ByteString)## Contributing
Grasana was a toy project because I was frustrated by how bad Asana is at
handling deeply nested projects (which seems to me to be a good way of
representing [outcome maps][outcome-maps]).If you would like to help make Grasana better, here is my TODO list which I'm
sure is missing many things. I have not been as good as I would have liked at
adding tests for Grasana (as you can see above) but please do add them where
possible when you are submitting features or fixes. Fork the repo, make some
changes in a branch, push it up and open a PR explaining the changes and the
reasoning behind the implementation and I'll review and merge (or reject).[outcome-maps]: http://www.aaronsw.com/weblog/theoryofchange
### TODO
- [x] Asana API interactions
- [x] Graph representation
- [x] Tree representation
- [x] DOT output
- [x] Incorporate built JS for HTML output
- [x] Update JS app to handle incl. json
- [ ] Write tests for DOT rendering
- [ ] Write tests for HTML rendering
- [ ] Handle unsound graphs and exit properly
- [ ] Handle Asana errors nicely (auth, 404, etc.)
- [x] Handle missing PAT nicely
- [ ] Find a way to mock HTTP requests
- [x] Add installation instructions
- [x] Add contribution instructions
- [x] Allow passing of asana token as an option
- [ ] Zoom to mouse point not origin in `InteractiveSVGViewer`
- [ ] Add bounds around labels in the HTML visualisation
- [ ] Wrap text labels in the HTML visualisation### Developing the HTML viewer
In order to make development of the HTML viewer easier, you can run a
local webpack server with live-reloading of changes. Just work inside
the `js` directory and run `yarn serve`. This will fire up a development
server on `localhost:8080` which you can use to test your changes.Note that the application expects a JSON representation of the project
in tree form to be accessible at `window.treejson`. The `index.html` has
a dummy project copied in there for convenience of development, but if
you want to test something specific you can replace it with a project of
your choice. The easiest way to do this is to get Grasana to generate
the JSON of an actual project using `grasana jsontree -t
` which you can then copy to your clipboard (e.g.
piping into `xclip -selection clipboard`) and pasting into `index.html`.### Developing the CLI
Stack's `run` command is very useful for running the programme as you
develop. The project is organised into some representations (`TaskGraph`
and `TaskTree` modules) and renderers (`Html` and `Dot`). The `Asana`
module contains the functions for actually tasking to the Asana API.In order to include the typescript project output into the generated
HTML, Grasana uses Template Haskell via `blaze-html` and `shakespeare`.