Skip to content

Commit

Permalink
Minor tweaks and more documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
maxott committed Sep 17, 2019
1 parent 0dbf68e commit 768ad34
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 89 deletions.
114 changes: 67 additions & 47 deletions examples/fcaTechSprint19/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ On 'submit` the UI changes to a waiting animation roughly animating what is happ
a query message is being sent to various organisations in a ring like fashion. When the answer to the
query is calculated and returned to the frontend, the final screen shows the result.

## Demonstrates:

* Multi-step/page app
* `registerGET` from REST Client
* App specific cards

## Building

To build the javascript bundle and front page, run the `yarn build`
Expand Down Expand Up @@ -43,101 +49,115 @@ As mentioned in the overview the app takes a user through three different step,
Now let us get back to [app.pihanga.js](src/app.pihanga.js) and look at the entry point `page`.

page: {
cardType: 'PiSimplePage',
contentCard: s => s.step,
...
cardType: 'PiSimplePage',
contentCard: s => s.step,
...
},

`PiSimplePage` is a card provided by the standard __Pihanga__ library and provides ust minimal scaffolding for displaying a single child card identified through `contentCard`. In our case we
simply use the workflow `step` from the _Redux_ state.
simply use the workflow `step` from the _Redux_ state (`s => s.step`).

The initial workflow state is `passport` and indeed we find a `passport` entry in [app.pihanga.js](src/app.pihanga.js):
The initial workflow state is `passport` (as defined in [app.initial-state.js](src/app.initial-state.js)) and indeed we find a `passport` entry in [app.pihanga.js](src/app.pihanga.js):

passport: {
cardType: 'PiTitledPage',
contentCard: 'form',
...
cardType: 'PiTitledPage',
contentCard: 'form',
...
},

form: {
cardType: 'PiForm',
title: 'Ask the Ring',
submitLabel: 'Send Query',
fields: [
...
],
...
cardType: 'PiForm',
title: 'Ask the Ring',
submitLabel: 'Send Query',
fields: [
...
],
...
},

![Passport Page](doc/passport.png)

The `passport` page consists of a titled page and an embedded form (`form`). Pressing the 'submit' button will trigger the default action:

{
type: "PI_FORM:FORM_SUBMIT"
id: "form"
passport: "44444"
question: "0"
ring: "0"
type: "PI_FORM:FORM_SUBMIT"
id: "form"
passport: "44444"
question: "0"
ring: "0"
}

which is 'reduced' in [workflow.js](src/workflow.js):
which is 'reduced' in [workflow.js](src/workflow.js) in two places:

registerGET({
name: 'verifyPassport',
url: '/passport/:id',
trigger: actions('PiForm').FORM_SUBMIT,
request: (action) => {
return {id: action.passport || 999};
},
reply: (state, reply) => {
const s = update(state, ['step'], 'answer');
return update(s, ['answer'], reply);
},
});
...
register.reducer(actions('PiForm').FORM_SUBMIT, (state, action) => {
dispatchFromReducer(() => {
getPassportCount(action.passport);
});
const s = update(state, ['step'], 'spinner');
return update(s, ['question'], action.question);
const s = update(state, ['step'], 'spinner');
return update(s, ['question'], action.question);
});

The reducer first initiates an API call `getPassportCount`, and then changes both the `step`, as well
as the `answer` property of the _Redux_ state. Changing the `step` property to `spinner` will, according
to the `page.contentCard` declaration in [app.pihanga.js](src/app.pihanga.js), now display the `spinner` card
The first code fragment registers a REST client to perform a GET query (`registerGET`) whenever it encounters an
`actions('PiForm').FORM_SUBMIT` action (`trigger`). The `request` function sets the `id` variable from the
url pattern `/passport/:id` to the form's `passport` value. Finally, the `request` function stores the reply
from the API call in hte state's `answer` sub tree and also changes the current `step` to `answer`.

The second code fragment changes the state's `step` value to `spinner`, which in turn, according
to the `page.contentCard` declaration in [app.pihanga.js](src/app.pihanga.js), will now display the `spinner` card
which is defined as:

spinner: {
cardType: 'Spinner',
...
cardType: 'Spinner',
...
},

'Spinner' is an application specific card and defined in the [spinner](src/spinner) directory.

![Spinner Page](doc/spinner.png)

The above referenced `getPassportCount` function will dispatch a `UPDATE_PASSPORT` event on successful
completion of the API request, which in turn is reduced in [workflow.js](src/workflow.js):

register.reducer(ACTION_TYPES.UPDATE_PASSPORT, (state, action) => {
const s = update(state, ['step'], 'answer');
return update(s, ['answer'], action.reply);
});

The first update is setting the step to `answer` which in turn will display the `answer` card defined in
As mentioned above the `reply` function in `registerGet` will on a success API call, store the result in
`state.answer` as well as the `step` to `answer`. This, in turn, will display the `answer` card defined in
[app.pihanga.js](src/app.pihanga.js) as follows:

answer: {
cardType: 'Answer',
answer: s => s.answer,
question: s => s.question,
cardType: 'Answer',
answer: s => s.answer,
question: s => s.question,
},

As with the `Spinner` card type, `Answer` is also an app specific card and defined in the [answer](src/answer) directory. It's properties `answer` and `question` are bound to the equally named properties in _Redux_.
As with the `Spinner` card type, `Answer` is also an app specific card and defined in the [answer](src/answer) directory. It's properties `answer` and `question` are bound to the equally named properties in the _Redux_ state.

![Answer Page](doc/answer.png)

Finally, the action `NEW_REQUEST` associated with the `NEW REQUEST` button on the answer page is reduced in
[workflow.js](src/workflow.js) to return to the `passport` page:

register.reducer(ANSWER_TYPES.NEW_REQUEST, (state) => {
return update(state, ['step'], 'passport');
return update(state, ['step'], 'passport');
});



# Developer

To further develop the UI start the development server with

% yarn start

and start the server in a different shell with:

% yarn server

Any API request to the development server on port 3000 will be forwarded to the app server according to the

"proxy": "http://localhost:8080",

setting in `package.json'.
20 changes: 19 additions & 1 deletion examples/real-time-charts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ for the CPU load and one for the memory consumption.

Periodically the front end is querying a REST API provided by the serving web server for the most recent measurements.

## Demonstrates:

* Meta cards
* Periodic GET from REST Client
* Recharts package

## Building

To build the javascript bundle and front page, run the `yarn build`
Expand All @@ -16,10 +22,13 @@ in the `build` directory.

## Running

% yarn
% yarn server

This will start a web server listening at port 8080, and pointing
your web browser at `http://__this_machine_name__:8080`.
your web browser at `http://__this_machine_name__:8080` and you should see something like:

![Screenshot](doc/screenshot1.png)

# How does it work?

Expand Down Expand Up @@ -133,3 +142,12 @@ To further develop the UI start the development server with

% yarn start

and start the server in a different shell with:

% yarn server

Any API request to the development server on port 3000 will be forwarded to the app server according to the

"proxy": "http://localhost:8080",

setting in `package.json'.
Binary file added examples/real-time-charts/doc/screenshot1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions examples/real-time-charts/src/app.pihanga.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ import moment from 'moment';
export function init(register) {
// x axis is time in `h:mm:ss` format.
const xAxisFormatter = (ts) => moment(ts).format("h:mm:ss");
const xAxisOpts = {dataKey: 'ts', domain: ['dataMin', 'dataMax'], type: 'number', tickFormatter: xAxisFormatter};
const xAxisOpts = {
dataKey: 'ts',
domain: ['dataMin', 'dataMax'],
type: 'number',
tickFormatter: xAxisFormatter,
//padding: { left: 0, right: 20 },
};

register.metaCard('WrappedCard', (name, defs) => {
const {
Expand All @@ -31,6 +37,7 @@ export function init(register) {
yAxisOpts: {domain: [0, maxY], label: {value: yLabel, angle: -90, position: 'insideLeft'}},
tooltipOpts: {labelFormatter: ts => `Time: ${xAxisFormatter(ts)}`},
height: 300,
chartOpts: {margin: { top: 5, right: 35, bottom: 15, left: 20 }},
...inner,
}
return h;
Expand All @@ -46,7 +53,6 @@ const page = {
cardType: 'PiPageR1',
contentCard: 'graphs',
title: 'Realtime Charts',
//titleIcon: 'rotate_right',
footer: {copyright: 'The Pihanga Team'}
},

Expand Down
68 changes: 36 additions & 32 deletions packages/material/src/card/muiCard/muiCard.component.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/* eslint-disable react/jsx-tag-spacing */
/* eslint-disable no-trailing-spaces */
import React from 'react';
import clsx from 'clsx';
//import clsx from 'clsx';
import Grid from '@material-ui/core/Grid';
import Card from '@material-ui/core/Card';
import CardHeader from '@material-ui/core/CardHeader';
Expand All @@ -23,10 +25,10 @@ export const MuiCard = styled(({
titleAvatar,
titleMedia, // {image, title}
content, // ["para1, "para2"]
contentCard,
contentCard,
grid = {},
mui = {},
classes
classes,
}) => {
const [expanded, setExpanded] = React.useState(false);

Expand All @@ -35,7 +37,7 @@ export const MuiCard = styled(({
}

function addHeader() {
const h = {title: title || '???'};
const h = { title: title || '???' };
if (subTitle) {
h.subheader = subTitle;
}
Expand All @@ -58,7 +60,7 @@ export const MuiCard = styled(({

function addMedia() {
if (titleMedia) {
return (
return (
<CardMedia
className={classes.media}
image="/static/images/cards/paella.jpg"
Expand All @@ -82,7 +84,7 @@ export const MuiCard = styled(({
if (contentCard) {
return (
<PiCard cardName={contentCard} parentCard={cardName} />
)
);
} else {
const ca = content || ['Missing \'content\''];
return (
Expand All @@ -94,34 +96,36 @@ export const MuiCard = styled(({
}

function addActions() {
if (false) {
return (
<CardActions disableSpacing>
<IconButton aria-label="add to favorites">
<FavoriteIcon />
</IconButton>
<IconButton aria-label="share">
<ShareIcon />
</IconButton>
<IconButton
className={clsx(classes.expand, {
[classes.expandOpen]: expanded,
})}
onClick={handleExpandClick}
aria-expanded={expanded}
aria-label="show more"
>
<ExpandMoreIcon />
</IconButton>
</CardActions>
);
} else {
return null;
}
return null;

// if (false) {
// return (
// <CardActions disableSpacing>
// <IconButton aria-label="add to favorites">
// <FavoriteIcon />
// </IconButton>
// <IconButton aria-label="share">
// <ShareIcon />
// </IconButton>
// <IconButton
// className={clsx(classes.expand, {
// [classes.expandOpen]: expanded,
// })}
// onClick={handleExpandClick}
// aria-expanded={expanded}
// aria-label="show more"
// >
// <ExpandMoreIcon />
// </IconButton>
// </CardActions>
// );
// } else {
// return null;
// }
}

return (
<Grid item {...grid}>
<Grid item {...grid} className={classes.outer}>
<Card className={classes.card}>
{ addHeader() }
{ addMedia() }
Expand All @@ -139,4 +143,4 @@ MuiCard.propTypes = {
titleMedia: PiPropTypes.shape(),
content: PiPropTypes.arrayOf(PiPropTypes.string),
contentCard: PiPropTypes.string,
};
};
11 changes: 7 additions & 4 deletions packages/material/src/card/muiCard/muiCard.style.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { withStyles } from '@material-ui/core/styles';


export default withStyles(theme => ({
export default withStyles((theme) => ({
outer: {
padding: theme.spacing(1),
},
card: {
//maxWidth: 345,
// maxWidth: 345,
},
media: {
height: 0,
Expand All @@ -20,6 +23,6 @@ export default withStyles(theme => ({
transform: 'rotate(180deg)',
},
avatar: {
//backgroundColor: red[500],
// backgroundColor: red[500],
},
}));
}));
2 changes: 0 additions & 2 deletions packages/material/src/card/pageR1/pageR1.style.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { withStyles } from '@material-ui/core/styles';



export default withStyles((theme) => {
const contentSpacing = {
top: 3,
Expand Down
Loading

0 comments on commit 768ad34

Please sign in to comment.