Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
REACT_APP_VERSION=$npm_package_version
18 changes: 12 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

* **Footer** now accepts a `version` prop to include your app version, and
a `versionUrl` prop if you want the version number to be a link. Works
great if you use dotenv (see **Footer** docs for more)

## [0.1.6] - 2018-04-12

### Fixed

* `Button` now allows a `type` prop to be passed through to the DOM element.
* Prevent `className` being doubled up on `Button`.
* Prevent `variation` being passed through to `Button`'s DOM element'.
* **Button** now allows a `type` prop to be passed through to the DOM element.
* Prevent `className` being doubled up on **Button**.
* Prevent `variation` being passed through to **Button**'s DOM element.

## [0.1.5] - 2018-04-03

### Fixed

* Use indexOf for strings in Buttons and Card examples. This fixes support in
* Use `indexOf` for strings in **Buttons** and **Card** examples. This fixes support in
old versions of IE.

## [0.1.4] - 2018-03-22

### Fixed

* Added CRICOS code to Footer.
* Added CRICOS code to **Footer**.

## [0.1.3] - 2018-03-09

Expand All @@ -37,7 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [0.1.2] - 2018-02-19

### Addded
### Added

* Added CHANGELOG.md.

Expand Down
98 changes: 77 additions & 21 deletions lib/layout/Footer.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
"use strict";
'use strict';

Object.defineProperty(exports, "__esModule", {
value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _react = require("react");
var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
Expand All @@ -28,36 +32,79 @@ var Footer = function (_Component) {
}

_createClass(Footer, [{
key: "render",
key: 'resolveVersionString',
value: function resolveVersionString() {
// this bit of fancy footwork makes the `version` prop
// work as a boolean, to use a default value:
// <Footer version />
// and also as a string to supply a value directly:
// <Footer version="1.2.3" />
var vString = this.props.version;
if (vString === true) {
// boolean true means they've requested the default version
vString = process.env.REACT_APP_VERSION || '';
} else if (vString === false) {
// boolean false means some looney has passed in `false`
vString = '';
}
// vString is now one of:
// - the string specified as the `version` prop value
// - the string from the REACT_APP_VERSION env var
// - '' coz REACT_APP_VERSION wasn't set
// - '' coz that's the prop's default value
// - '' coz the weirdo user passed in `false`
return vString;
}
}, {
key: 'render',
value: function render() {
var versionTag = this.resolveVersionString();
if (versionTag !== '') {
// if the user provided a versionUrl..
if (this.props.versionUrl) {
versionTag = _react2.default.createElement(
'a',
{ href: this.props.versionUrl },
versionTag
);
}
// TODO: bootstrap 'pull-*-right' will become 'float-*-right'
versionTag = _react2.default.createElement(
'div',
{ className: 'pull-xs-right float-xs-right' },
versionTag
);
}

return _react2.default.createElement(
"footer",
{ className: "container jcu-footer" },
'footer',
{ className: 'container jcu-footer' },
_react2.default.createElement(
"div",
{ className: "row jcu-colophon" },
'div',
{ className: 'row jcu-colophon' },
_react2.default.createElement(
"div",
{ className: "col-xs-12" },
'div',
{ className: 'col-xs-12' },
versionTag,
_react2.default.createElement(
"ul",
{ className: "list-inline" },
'ul',
{ className: 'list-inline' },
_react2.default.createElement(
"li",
{ className: "list-inline-item" },
"Copyright \xA9 1995 to ",
'li',
{ className: 'list-inline-item' },
'Copyright \xA9 1995 to ',
new Date().getFullYear(),
" James Cook University. All rights reserved."
' James Cook University. All rights reserved.'
),
_react2.default.createElement(
"li",
{ className: "list-inline-item" },
"ABN 46253211955"
'li',
{ className: 'list-inline-item' },
'ABN 46253211955'
),
_react2.default.createElement(
"li",
{ className: "list-inline-item" },
"CRICOS Provider Code 00117J"
'li',
{ className: 'list-inline-item' },
'CRICOS Provider Code 00117J'
)
)
)
Expand All @@ -69,4 +116,13 @@ var Footer = function (_Component) {
return Footer;
}(_react.Component);

Footer.propTypes = {
/** Include a version number (defaults to the app version, otherwise specify a string) */
version: _propTypes2.default.oneOfType([_propTypes2.default.bool, _propTypes2.default.string]),
/** Displayed version number will be a link to this URL */
versionUrl: _propTypes2.default.string
};
Footer.defaultProps = {
version: ''
};
exports.default = Footer;
20 changes: 20 additions & 0 deletions lib/layout/Footer.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@

```jsx
<Footer />
```

Including the `version` prop displays an application version number along with the other content:

```jsx
<Footer version />
```

If you specify the `version` prop without supplying a string value, `Footer` will check the `REACT_APP_VERSION` environment variable. The [`dotenv`](https://github.com/motdotla/dotenv) package ([included in create-react-app](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#user-content-adding-development-environment-variables-in-env)) can set this variable from your `package.json` file, if you add a `.env` file to the root of your project containing the following line:

```bash
REACT_APP_VERSION=$npm_package_version
```

You may supply a version string directly, and an optional URL the version should link to.

```jsx
<Footer version="1970-04-20v0" versionUrl="https://web.jcu.io/v2/#footer" />
```

49 changes: 49 additions & 0 deletions src/layout/Footer.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,60 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'

export default class Footer extends Component {
static propTypes = {
/** Include a version number (defaults to the app version, otherwise specify a string) */
version: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.string
]),
/** Displayed version number will be a link to this URL */
versionUrl: PropTypes.string
}

static defaultProps = {
version: ''
}

resolveVersionString () {
// this bit of fancy footwork makes the `version` prop
// work as a boolean, to use a default value:
// <Footer version />
// and also as a string to supply a value directly:
// <Footer version="1.2.3" />
let vString = this.props.version
if (vString === true) {
// boolean true means they've requested the default version
vString = process.env.REACT_APP_VERSION || ''
} else if (vString === false) {
// boolean false means some looney has passed in `false`
vString = ''
}
// vString is now one of:
// - the string specified as the `version` prop value
// - the string from the REACT_APP_VERSION env var
// - '' coz REACT_APP_VERSION wasn't set
// - '' coz that's the prop's default value
// - '' coz the weirdo user passed in `false`
return vString
}

render () {
let versionTag = this.resolveVersionString()
if (versionTag !== '') {
// if the user provided a versionUrl..
if (this.props.versionUrl) {
versionTag = <a href={this.props.versionUrl}>{versionTag}</a>
}
// TODO: bootstrap 'pull-*-right' will become 'float-*-right'
versionTag = <div className="footer-version pull-xs-right float-xs-right">{versionTag}</div>
}

return (
<footer className="container jcu-footer">
<div className="row jcu-colophon">
<div className="col-xs-12">
{versionTag}
<ul className="list-inline">
<li className="list-inline-item">
Copyright &copy; 1995 to {(new Date()).getFullYear()} James Cook University. All rights reserved.
Expand Down
19 changes: 19 additions & 0 deletions src/layout/Footer.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@

```jsx
<Footer />
```

Including the `version` prop displays an application version number along with the other content:

```jsx
<Footer version />
```

If you specify the `version` prop without supplying a string value, `Footer` will check the `REACT_APP_VERSION` environment variable. The [`dotenv`](https://github.com/motdotla/dotenv) package ([included in create-react-app](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#user-content-adding-development-environment-variables-in-env)) can set this variable from your `package.json` file, if you add a `.env` file to the root of your project containing the following line:

```bash
REACT_APP_VERSION=$npm_package_version
```

You may supply a version string directly, and an optional URL the version should link to.

```jsx
<Footer version='1970-04-20v0' versionUrl='https://web.jcu.io/v2/#footer' />
```
50 changes: 50 additions & 0 deletions src/layout/Footer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,53 @@ test('shows current year', () => {
const currentYear = (new Date()).getFullYear()
expect(footer.contains(currentYear)).toBe(true)
})

test('shows version from environment', () => {
// save original env var
const originalVer = process.env.REACT_APP_VERSION

const verString = '1.2.specialversionstring'
process.env.REACT_APP_VERSION = verString
const footer = shallow(<Footer version />)
expect(footer.contains(verString)).toBe(true)

// restore original env var
if (originalVer) {
process.env.REACT_APP_VERSION = originalVer
} else {
delete process.env.REACT_APP_VERSION
}
})

test('no crash if environment version not set', () => {
// save original env var
const originalVer = process.env.REACT_APP_VERSION
delete process.env.REACT_APP_VERSION
shallow(<Footer version />)

// restore original env var
if (originalVer) {
process.env.REACT_APP_VERSION = originalVer
}
})

test('shows version from prop', () => {
const verString = '1.2.specialversionstring'
const footer = shallow(<Footer version={verString} />)
expect(footer.contains(verString)).toBe(true)
})

test('handles boolean version prop values', () => {
let footer = shallow(<Footer version={false} />)
expect(footer.find('.footer-version')).toHaveLength(0)

footer = shallow(<Footer version={true} />)
expect(footer.find('.footer-version')).toHaveLength(1)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added these expect clauses so we check that the footer version is being rendered when it should and shouldn't. Previously, the tests just tested if rendering worked but not the outcome.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I need to be more careful about refreshing my pull req conversations -- twice now I've noticed a code update but missed the related comment.

Yes I originally wrote those tests to just confirm no crash; passing a boolean false as the prop value is technically allowed but not useful. I think there's a valid case where passing true (the code reformatting removes the explicit boolean true, so it's just prop-exists-true) when there's no env var set will result in no version number appearing. I'll add an issue for that so i remember to come back around and fix it.

})

test('links to version url', () => {
const verString = '1.2.specialversionstring'
const verUrl = 'https://example.com'
const footer = shallow(<Footer version={verString} versionUrl={verUrl} />)
expect(footer.find(`a[href="${verUrl}"]`)).not.toBeNull()
})