npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

nqm-app-framework

v0.3.23

Published

common framework components for nqminds apps

Downloads

3

Readme

nqm-app-framework

introduction

The nquiringminds application framework is a set of components, containers and functions that provide a consistent, scaleable and responsive infrastructure on which to quickly build bespoke applications against the nquiringminds Trusted Data Exchange (TDX).

Core features include:

  • opinionated mobile-first user interface design and layout that scales well across all devices
  • built-in integration with the TDX auth server, plus single sign-on integration with the nquiringminds toolbox
  • application state management with support for serialization and replay
  • built-in support for subscribing to TDX data publications
  • built-in support for the TDX REST API

technologies

You will need to familiarise yourself with the following technologies, utilised by this framework.

  • meteor - Meteor is a full-stack JavaScript platform for developing modern web and mobile applications. Meteor includes a key set of technologies for building connected-client reactive applications.
  • mantra - application architecture and workflow, provides built-in unit testing support, controlled load order, routing, context, consistent module structure.
  • redux - predictable application state management
  • react - library for building component-based user interfaces
  • react-router - client-side router for react apps
  • material-ui - a set of React components implementing Google's Material Design spec.
  • jss - high performance JS to CSS compiler

A working knowledge of mongoDB query syntax is desirable.

background reading

As well as familiarising yourself with the above technologies, you may find the following links useful background reading.

packaging

Use the following steps to publish a meteor application that utilises nqm-app-framework.

install meteor-build-client

sudo npm install -g meteor-build-client

create the html template

An HTML template needs to be created that specifies the React root DOM node, for example if you're using a 'react-root' div element, create a build-template.html file containing:

<!DOCTYPE html>
<html>
    <head>
        {{> css}}
        {{> head}}
    </head>
    <body>
      <div id="render-root"></div>
      {{> scripts}}
    </body>
</html>

build the app

cd /path/to/myApp
meteor-build-client ../myApp-client-only -s ./settings.json -t ../build-template.html

package the app

The application can then be run using a basic nodejs static file http server:

var express = require('express');
var app = express();

app.use("/", express.static(__dirname + "/myApp-client-only"));

app.listen(8081);

components

Layout

The main layout component, provides the central display area, an optional side bar on the left and a title bar. If supplied the sidebar will be responsive to changes in layout and screen size and can be toggled from the title bar navigation button.

properties

  • content - [functional React component] the main layout content
  • sideBarContent - [functional React component] optional content to appear in the left side bar
  • title - [string] the title, displayed in the app bar

example

import framework from "nqm-app-framework";
import Home from "../core/components/home";
import AppSideBar from "./components/app-side-bar";

const Layout = framework.ui.Layout;

export default function(injectDeps, context) {
  const {store} = context;
  const history = syncHistoryWithStore(browserHistory, store);

  const RouterCtx = () => (
    <Router history={history}>
      <Route path="/" component={Layout}>
        <IndexRoute title="lorem upsum" components={{content: Home, sideBarContent: AppSideBar}} />
      </Route>
    </Router>
  );

  ReactDOM.render(
    React.createElement(injectDeps(RouterCtx)),
    document.getElementById("render-root")
  );
}

ModalLayout

A simple modal layout component that provides a central display area and title bar. The title bar supports customisable save and close handlers. Use in conjection with ModalPageBase.

properties

  • content - [functional React component] the main layout content
  • title - [string] the title, displayed in the app bar

example

import framework from "nqm-app-framework";
import About from "../core/containers/about";

const ModalLayout = framework.ui.ModalLayout;

export default function(injectDeps, context) {
  const {store} = context;
  const history = syncHistoryWithStore(browserHistory, store);

  const RouterCtx = () => (
    <Router history={history}>
      <Route path="/modal" component={ModalLayout}>
        <IndexRoute components={{content: About}} />
      </Route>
    </Router>
  );

  ReactDOM.render(
    React.createElement(injectDeps(RouterCtx)),
    document.getElementById("render-root")
  );
}

SideBarContent

This is a container component for side bar panels. It has no properties and acts as a simple container for SideBarPanel components. The SideBar component expects one and only one SideBarContent child.

properties

none

example

import React from "react";
import framework from "nqm-app-framework";

// Import app-specific bar panels
import AppMenu from "../containers/app-menu";
import AppOptions from "../containers/app-options";

// Sidebar framework
const SideBarContent = framework.ui.SideBarContent;
const SideBarPanel = framework.ui.SideBarPanel;

const AppSideBar = () => {
  return (
    <SideBarContent>
      <SideBarPanel title="menu" value="menu" icon="apps">
        <AppMenu />
      </SideBarPanel>
      <SideBarPanel title="options" value="options" icon="settings">
        <AppOptions />
      </SideBarPanel>
    </SideBarContent>
  );
};

SideBarPanel

Defines a panel within the side bar. A tab button will be added to the side bar tabs, and clicking the button will activate the panel within the side bar. If the route property is specified, the panel will only be visible if the current route matches the property. See react router api for details of how the route matching works.

properties

  • title - [string] a short, descriptive title for the panel
  • value - [string] an identifier that uniquely identifies this panel
  • icon - [string] the name of the material-icons icon to use for the panel
  • route - [string] optional route path. The panel will only be visible if the current route matches

example

import React from "react";
import framework from "nqm-app-framework";

// Import app-specific bar panels
import AppMenu from "../containers/app-menu";
import AppOptions from "../containers/app-options";

// Sidebar framework
const SideBarContent = framework.ui.SideBarContent;
const SideBarPanel = framework.ui.SideBarPanel;

const AppSideBar = () => {
  return (
    <SideBarContent>
      <SideBarPanel title="menu" value="menu" icon="apps">
        <AppMenu />
      </SideBarPanel>
      <SideBarPanel title="resource options" value="resource" icon="settings" route="/resource">
        <AppOptions />
      </SideBarPanel>
    </SideBarContent>
  );
};

NotificationUi

Snackbar style notification area, similar to the notifactions section on the TDX. Supports fire and forget actions as well as longer running notification chains.

example

// Container
const depsMapper = (context, actions) => ({
  addNotification: actions.notification.addNotification,
  updateNotification: actions.notification.updateNotification,
});

// addNotification
// autoExpire is a boolean, if true then message will display for 4 seconds or, if specified, the duration in milliseconds then automatically be removed, otherwise it will remain until marked as finished with updateNotification
const id = addNotification("message", autoExpire, (duration));

// The returned id may be used to update an existing notification, finished is a boolean, if true the notification will be removed 4 seconds after the message is updated
updateNotification(id, "Progress", finished);

const id = addNotification(`Deleting resource ${resourceId}`);
tdxApi.deleteDatasetAsync(resourceId)
.then(() => {
  updateNotification(id, `Deleted resource ${resourceId}`, true);
})
.catch((err) => {
  updateNotification(id, `Failed to delete resource ${resourceId}: ${err.message}`, true);
});

data loaders

The framework encourages separating the data loading aspects of an app from it's UI components. Doing this involves 3 types of 'mapping' data from various data sources to properties of the component. These data sources are:

  • application context - application-wide context, such as access to the TDX connection manager and the application state store.
  • application state - the current state of the application, usually created as a result of user actions such as the active view or selected sort order etc. Application state is not usually persisted and should not be used to store 'domain data'.
  • domain data - the data required by the application, usually residing in the TDX, such as LSOA lists, region boundaries, sensor definitions and latest readings etc.

The idea is for each component to define the data it requires using React properties. The component does not concern itself with where that data comes from or how it is loaded or saved. This approach ensures components are self-contained and able to be shared across applications and/or domains if required. It also makes it possible to write tests for the component in a generic way.

Component containers are used to 'map' data from the various data sources described above to the properties defined by the component.

compose

This is a general purpose helper function that provides the 'glue' between the mapping function you provide and the component properties.

merge

This is a general-purpose helper that lets you map data to your component properties using more than one data source, by chaining together one or more compose invocations.

useDeps

Short for 'use dependencies', use this function to declare the aspects of application context your component container needs to access in order to fulfill the data source to property mappings.

trackerFactory

A factory function that creates a reactive wrapper around your data loading function. See the Meteor Tracker documentation for more information about Meteor reactivity.

reduxFactory

For example, if your component has a 'sortOrder' property you probably want to synchronise it with the currently selected sort order from application state.

application state

to do