0.0.1 • Published 9 months ago

appskd v0.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

H5Web App & Providers

Demos Version

H5Web is a collection of React components to visualize and explore data. It consists of two main packages:

@h5web/app exposes the HDF5 viewer component App, as well as the following built-in data providers:

  • H5GroveProvider for use with server implementations based on H5Grove, like jupyterlab-h5web;
  • HsdsProvider for use with HSDS;
  • MockProvider for testing purposes.

Getting started 🚀

npm install @h5web/app
import '@h5web/app/dist/styles.css';

import React from 'react';
import { App, MockProvider } from '@h5web/app';

function MyApp() {
  return (
    <div style={{ height: '100vh' }}>
      <MockProvider>
        <App />
      </MockProvider>
    </div>
  );
}

export default MyApp;

If your bundler supports it (e.g. webpack 5), you may be able to shorten the stylesheet import path as follows:

import '@h5web/app/styles.css';

Examples

The following code sandboxes demonstrate how to set up and use @h5web/app with various front-end development stacks:

Browser support

H5Web works out of the box on Firefox 78 ESR.

Support for Firefox 68 ESR is possible by polyfilling the ResizeObserver API. One easy way to do this is with polyfill.io:

<head>
  <!-- title, meta, link, etc. -->
  <script src="https://polyfill.io/v3/polyfill.min.js?features=default%2CResizeObserver"></script>
</head>

Older versions of Firefox are not supported.

API reference

App

Renders the HDF5 viewer.

For App to work, it must be wrapped in a data provider:

<MockProvider>
  <App />
</MockProvider>

explorerOpen?: boolean (optional)

Whether the viewer should start with the explorer panel open. Defaults to true. Pass false to hide the explorer on initial render, thus giving more space to the visualization. This may be useful when H5Web is embeded inside another app.

<App explorerOpen={false} />

initialPath?: string (optional)

The path to select within the file when the viewer is first rendered. Defaults to '/'.

<MockProvider>
  <App initialPath="/nD_datasets/threeD" />
</MockProvider>

getFeedbackURL?: (context: FeedbackContext) => string (optional)

If provided, a "Give feedback" button appears in the breadcrumbs bar, which invokes the function when clicked. The function should return a valid URL, for instance a mailto: URL with a pre-filled subject and body: mailto:some@email.com?subject=Feedback&body=<url-encoded-text>. If the app is publicly available, we recommend returning the URL of a secure online contact form instead.

<App getFeedbackURL={() => 'https://my-feedback-form.com'} />
<App
  getFeedbackURL={(context) => {
    const {
      filePath, // path of current file
      entityPath, // path of currently selected entity
    } = context;

    return `mailto:some@email.com?subject=Feedback&body=${encodeURIComponent(...)}`;
  }}
/>

disableDarkMode?: boolean (optional)

By default, the viewer follows your browser's and/or operating system's dark mode setting. This prop disables this beahviour by forcing the viewer into light mode.

<App disableDarkMode />

propagateErrors?: boolean (optional)

The viewer has a top-level ErrorBoundary that, by default, handles errors thrown outside of the visualization area. These include errors thrown by the data provider when fetching metadata for the explorer. If you prefer to implement your own error boundary, you may choose to let errors through the viewer's top-level boundary:

import { ErrorBoundary } from 'react-error-boundary';

<ErrorBoundary FallbackComponent={MyErrorFallback}>
  <MockProvider>
    <App propagateErrors />
  </MockProvider>
</ErrorBoundary>;

H5GroveProvider

Data provider for H5Grove.

<H5GroveProvider
  url="https://h5grove.server.url"
  filepath="some-file.h5"
  axiosParams={{ file: 'some-file.h5' }}
>
  <App />
</H5GroveProvider>

url: string (required)

The base URL of the H5Grove server.

filepath: string (required)

The path and/or name of the file to display in the UI.

axiosParams?: Record<string, string> (optional)

By default, H5GroveProvider does not make any assumption as to which query parameters to send to the server. If you use one of H5Grove's default API implementations, then you'll need to use this prop to pass the file query parameter as shown above.

HsdsProvider

Data provider for HSDS.

<HsdsProvider
  url="https://hsds.server.url"
  username="foo"
  password="abc123"
  filepath="/home/reader/some-file.h5"
>
  <App />
</HsdsProvider>

url: string (required)

The base URL of the HSDS server.

username: string; password: string (required)

The credentials to use to authenticate to the HSDS server. Note that this authentication mechanism is not secure; please do not use it to grant access to private data.

filepath: string (required)

The path of the file to request.

MockProvider

Data provider for demonstration and testing purposes.

<MockProvider>
  <App />
</MockProvider>

Utilities

getFeedbackMailto

Generate a feedback mailto: URL using H5Web's built-in feedback email template.

(context: FeedbackContext, email: string, subject = 'Feedback') => string;
import { getFeedbackMailto } from '@h5web/app';
...
<App getFeedbackURL={(context) => {
  return getFeedbackMailto(context, 'some@email.com');
}} />

Context

The viewer component App communicates with its wrapping data provider through a React context called DataContext. This context is available via a custom hook called useDataContext. This means you can use the built-in data providers in your own applications:

<MockProvider>
  <MyApp />
</MockProvider>;

function MyApp() {
  const { filename } = useDataContext();
  return <p>{filename}</p>;
}

useDataContext returns the following object:

interface DataContextValue {
  filepath: string;
  filename: string;

  entitiesStore: EntitiesStore;
  valuesStore: ValuesStore;
  attrValuesStore: AttrValuesStore;
}

The three stores are created with the react-suspense-fetch library, which relies on React Suspense. A component that uses one of these stores (e.g. entitiesStore.get('/path/to/entity')) must have a Suspense ancestor to manage the loading state.

<MockProvider>
  <Suspense fallback={<span>Loading...</span>}>
    <MyApp />
  </Suspense>
</MockProvider>;

function MyApp() {
  const { entitiesStore } = useDataContext();
  const group = entitiesStore.get('/resilience/slow_metadata');
  return <pre>{JSON.stringify(group, null, 2)}</pre>;
}