Git Product home page Git Product logo

strudel-kit's Introduction

STRUDEL Kit (Beta)

STRUDEL Kit is a React-based JavaScript library for building scientific UIs based on the STRUDEL Design System and Task Flows. Visit strudel.science for more information about the STRUDEL project.

This library provides a suite of templates to implement UIs for various different task flows common to the scientific domain. The app is intended to be used as a starting point for building out a web app that includes one or more of the task flows provided.

Quickstart

Install strudel-cli from PyPi:

pip install strudel-cli

Create a strudel base app:

strudel create-app my-app

This will generate a base web application in a new directory called my-app. Go into the new directory:

cd my-app

Install the app dependencies:

npm install

Start up your app locally:

npm start

Open your app in the browser at http://localhost:5173

Add a Task Flow to your app:

strudel add-taskflow my-taskflow --template compare-data

This generates new template files for your Task Flow in my-app/src/pages/my-taskflow. Check out the First Steps and Configuration page for the template you are using to learn how to customize it.

Navigate to http://localhost:5173/my-taskflow to see your new Task Flow.

Packages

The strudel-cli is a command-line tool for bootstrapping web applications based on the STRUDEL Design System. If you're looking to get started building web applications with STRUDEL, this is the best way to start.

Demo react app that implements each of the STRUDEL task flows. This code is an example of what you can build using the strudel-cli. If you prefer to just copy and paste code from GitHub, this is a good place to start.

Templates designed for the cookiecutter tool. These templates are what strudel-cli uses to generate apps/task-flows. This package is not intended to be interacted with directly. It's best to use the strudel-cli.

strudel-kit's People

Contributors

codytodonnell avatar dangunter avatar techmaarten avatar

Stargazers

Bryan Lancien avatar Maxwell Kambona avatar Ed Allen avatar Axel Huebl avatar Andrew Schmeder avatar  avatar Vismayak Mohanarajan avatar

Watchers

Drew Paine avatar  avatar

strudel-kit's Issues

Some deprecated package versions

Hello!

Just checking out your package after I received an email about strudel. Some warnings on npm install:

npm WARN deprecated [email protected]: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
npm WARN deprecated @humanwhocodes/[email protected]: Use @eslint/config-array instead
npm WARN deprecated [email protected]: Rimraf versions prior to v4 are no longer supported
npm WARN deprecated [email protected]: Glob versions prior to v9 are no longer supported
npm WARN deprecated [email protected]: Redundant dependency in your project.
npm WARN deprecated @humanwhocodes/[email protected]: Use @eslint/object-schema instead

I know these aren't too serious, but do you have any CI stuff to bump versions?

Simulate API integration

From Smartsheet:

Anywhere an API would be called in a real app, send a request to a mock API. The goal is to demonstrate asynchronous behavior both visually and in the code.

Generate a user story around the GBIF example

Write up a paragraph or two that grounds the example in a story about a user who is using STRUDEL Kit to implement an app with the GBIF API. This is not necessarily meant to be public. It's more to help you think about the user and the kinds of decisions they might make as they are building their app with the kit.

Here is a good article on user stories: https://www.nngroup.com/articles/ux-stories/

Windows warnings about cookiecutter cache

During creating of an app and task flow, I get 2 types of warnings about the cookiecutter cache. Neither I nor any non-developer user will know what to do with these, so I think we should try to eliminate them.

When I do strudel create ... I get warning about not clearing the cache and then a question about re-downloading it (every time)

[09:23:30] WARNING  could not clear cookiecutter cache: [WinError main.py:51
                    5] Access is denied:
                    'C:\\Users\\dkgun\\.cookiecutters/strudel-kit
                    \\.git\\objects\\pack\\pack-76720496dfba6732f
                    897353bd871576178fd0110.idx'
continuing to create your app...
You've downloaded C:\Users\dkgun\.cookiecutters\strudel-kit before. Is it
okay to delete and re-download it? [y/n] (y): y

When I do strudel add-taskflow ... I get the cookiecutter cache warning without an associated request to re-download:

[09:26:57] WARNING  could not clear cookiecutter cache: [WinError main.py:51
                    5] Access is denied:
                    'C:\\Users\\dkgun\\.cookiecutters/strudel-kit
                    \\.git\\objects\\pack\\pack-27825654dd4dbc024
                    0103e13eff402d285b89193.idx'

Populate detail page with data from the occurrence

Add UI elements to the detail page, [id].tsx, that include as much information as you can logically display about the selected occurrence. The page could be similar to the detail page on GBIF, or you can put your own spin on it.

For any elements you think should be included in this page but you aren't ready to implement, you could add placeholder boxes.

Add CLI tool for bootstrapping apps

We want to have an easier way to get started with the strudel task flow implementations other than simply cloning the github repo. The CLI tool can handle bootstrapping the initial app structure, plugging in some variables, and adding various task flows to the app using the implementations as templates.

To Do:

  • Add Developer Quickstart section to README
  • Clarify allowable app names
  • Give helpful status message after command succeeds
  • Fix PUBLIC_URL issue for windows on npm start

Add a gallery view to Explore Data page

Implement a feature similar to the gallery view in the GBIF occurrence search page. There should be a new toggle button above the table that hides the <DataGrid> and shows a gallery of the data items instead.

The first pass of this feature could just show, for each data item, a box with two or three fields in it (like scientific name, date, and region). If possible, you could try to display an image for the data item if it exists, using the media field from GBIF.

Image

Implement server-side filter for gbifRegion

Add a new checkbox filter for the gbifRegion field and connect it to the API so that when a region is checked or unchecked, it triggers a new fetch for the data. When the data is fetched, it should pass in the checked values as URL parameters. For example, if "EUROPE" and "NORTH_AMERICA" are checked, the request URL to the API would be:

https://api.gbif.org/v1/occurrence/search?gbifRegion=EUROPE&gbifRegion=NORTH_AMERICA

Because this is an array parameter, the gbifRegion= is repeated for every value that should be included in the filter.

In our case, we want the fetch to trigger any time the filters change. This can be controlled by the useEffect "hook" in ContextProvider.tsx on line 122. Right now, filteredData is assigned the result of the filterData function which does only client side filtering. What we want to do is replace the filterData function with a new server side filter function that runs the request to the GBIF API using the filter parameters from our state.activeFilters variable.

Populate the preview panel with data about the selected GBIF occurrence

Modify the PreviewPanel.tsx component so that it displays additional data about the selected occurrence row. The panel should utilize the state.previewItem variable to make the information dynamic based on the selected row. Ideally some of the data that is displayed in the PreviewPanel is not visible from the table view.

This task flow uses React Context to share the state across the different components. Check out _context/ContextProvider.tsx to see under the hood how state.previewItem works.

Image

Implement server-side pagination

Right now all the pagination in the Explore table is done client-side. This means all the data is fetched at once and changing the page simply decides which rows to show/hide. Instead, we want the pagination to happen server-side. With server-side pagination, each page of data is fetched separately.

The whole table, including pagination, is handled inside of _components/DataTablePanel.tsx in the <DataGrid> component from MUI. Check out their documentation on pagination, specifically the Server-Side Pagination section.

What you will need to do is create a function that is triggered onPaginationModelChange. This function should fetch data from the GBIF API using limit (aka items per page) and offset (aka page + items per page) parameters that are derived from the current page and page size. The data that is returned from that fetch should then be used as the rows prop of the <DataGrid>.

When it's all working, you should be able to use the arrows to click through the pages in the table, fetching new data each time you click to the next or previous page.

strudel --version does not work

When I try strudel --version on the current version from GH main, I get:

❯ strudel --version
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ in _run_module_as_main:198                                                                       │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │   alter_argv = False                                                                         │ │
│ │         code = <code object <module> at 0x0000028C6BCB0030, file                             │ │
│ │                "C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Scripts\strudel.exe\__main… │ │
│ │                line 1>                                                                       │ │
│ │ main_globals = {                                                                             │ │
│ │                │   '__name__': '__main__',                                                   │ │
│ │                │   '__doc__': None,                                                          │ │
│ │                │   '__package__': '',                                                        │ │
│ │                │   '__loader__': <zipimporter object                                         │ │
│ │                "C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Scripts\strudel.exe\">,     │ │
│ │                │   '__spec__': ModuleSpec(name='__main__', loader=<zipimporter object        │ │
│ │                "C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Scripts\strudel.exe\">,     │ │
│ │                origin='C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Scripts\\stru… │ │
│ │                │   '__annotations__': {},                                                    │ │
│ │                │   '__builtins__': <module 'builtins' (built-in)>,                           │ │
│ │                │   '__file__':                                                               │ │
│ │                'C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Scripts\\strudel.exe… │ │
│ │                │   '__cached__':                                                             │ │
│ │                'C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Scripts\\strudel.exe… │ │
│ │                │   're': <module 're' from                                                   │ │
│ │                'C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Lib\\re\\__init__.py… │ │
│ │                │   ... +2                                                                    │ │
│ │                }                                                                             │ │
│ │     mod_name = '__main__'                                                                    │ │
│ │     mod_spec = ModuleSpec(name='__main__', loader=<zipimporter object                        │ │
│ │                "C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Scripts\strudel.exe\">,     │ │
│ │                origin='C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Scripts\\stru… │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ in _run_code:88                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │       cached = 'C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Scripts\\strudel.exe… │ │
│ │         code = <code object <module> at 0x0000028C6BCB0030, file                             │ │
│ │                "C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Scripts\strudel.exe\__main… │ │
│ │                line 1>                                                                       │ │
│ │        fname = 'C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Scripts\\strudel.exe… │ │
│ │ init_globals = None                                                                          │ │
│ │       loader = <zipimporter object                                                           │ │
│ │                "C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Scripts\strudel.exe\">      │ │
│ │     mod_name = '__main__'                                                                    │ │
│ │     mod_spec = ModuleSpec(name='__main__', loader=<zipimporter object                        │ │
│ │                "C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Scripts\strudel.exe\">,     │ │
│ │                origin='C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Scripts\\stru… │ │
│ │     pkg_name = ''                                                                            │ │
│ │  run_globals = {                                                                             │ │
│ │                │   '__name__': '__main__',                                                   │ │
│ │                │   '__doc__': None,                                                          │ │
│ │                │   '__package__': '',                                                        │ │
│ │                │   '__loader__': <zipimporter object                                         │ │
│ │                "C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Scripts\strudel.exe\">,     │ │
│ │                │   '__spec__': ModuleSpec(name='__main__', loader=<zipimporter object        │ │
│ │                "C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Scripts\strudel.exe\">,     │ │
│ │                origin='C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Scripts\\stru… │ │
│ │                │   '__annotations__': {},                                                    │ │
│ │                │   '__builtins__': <module 'builtins' (built-in)>,                           │ │
│ │                │   '__file__':                                                               │ │
│ │                'C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Scripts\\strudel.exe… │ │
│ │                │   '__cached__':                                                             │ │
│ │                'C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Scripts\\strudel.exe… │ │
│ │                │   're': <module 're' from                                                   │ │
│ │                'C:\\Users\\dkgun\\miniconda3\\envs\\strudel-kit-learn\\Lib\\re\\__init__.py… │ │
│ │                │   ... +2                                                                    │ │
│ │                }                                                                             │ │
│ │  script_name = None                                                                          │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ in <module>:7                                                                                    │
│                                                                                                  │
│ C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Lib\site-packages\typer\main.py:328 in __call__ │
│                                                                                                  │
│ C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Lib\site-packages\typer\main.py:311 in __call__ │
│                                                                                                  │
│ C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Lib\site-packages\click\core.py:1157 in         │
│ __call__                                                                                         │
│                                                                                                  │
│ C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Lib\site-packages\typer\core.py:778 in main     │
│                                                                                                  │
│ C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Lib\site-packages\typer\core.py:215 in _main    │
│                                                                                                  │
│ C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Lib\site-packages\click\core.py:943 in          │
│ make_context                                                                                     │
│                                                                                                  │
│ C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Lib\site-packages\click\core.py:1644 in         │
│ parse_args                                                                                       │
│                                                                                                  │
│ C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Lib\site-packages\click\core.py:1408 in         │
│ parse_args                                                                                       │
│                                                                                                  │
│ C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Lib\site-packages\click\core.py:2400 in         │
│ handle_parse_result                                                                              │
│                                                                                                  │
│ C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Lib\site-packages\click\core.py:2362 in         │
│ process_value                                                                                    │
│                                                                                                  │
│ C:\Users\dkgun\miniconda3\envs\strudel-kit-learn\Lib\site-packages\typer\main.py:994 in wrapper  │
│                                                                                                  │
│ C:\Users\dkgun\src\strudel-project\strudel-kit\strudel-cli\src\strudel\callbacks.py:39 in        │
│ version_callback                                                                                 │
│                                                                                                  │
│   36                                                                                             │
│   37 def version_callback(value: bool):                                                          │
│   38 │   if value:                                                                               │
│ ❱ 39 │   │   print(f"strudel-cli {__version__}")                                                 │
│   40 │   │   raise typer.Exit()                                                                  │
│   41                                                                                             │
│   42                                                                                             │
│                                                                                                  │
│ ╭─── locals ───╮                                                                                 │
│ │ value = True │                                                                                 │
│ ╰──────────────╯                                                                                 │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
NameError: name '__version__' is not defined
(strudel-kit-learn) dkgun ~\src\strudel-project\strudel-kit\docs dstut ≡*?4  1  628ms
❯

Connect detail page to /occurence/{gbifId} endpoint

Right now, the detail page, [id].tsx , that shows when you drill into a preview panel uses data from the originally fetched list of items from the explore page. This would cause problems if you loaded a detail page on its own, without first loading the explore page. Instead, we want the detail page to fetch a single record of data when it loads. The record it fetches should be based on the id in the URL. If we load the page /explore-data/3, we should fetch the occurrence with the id (or key) of 3.

Specifically, what we want to do is replace the function that populates the entity variable with a new fetch request to the /occurrence/{gbifId} endpoint of the API. Here's an example of that endpoint for key=4514082304:

https://api.gbif.org/v1/occurrence/4514082304

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.