Skip to content

Commit

Permalink
Merge branch 'feature/announcement' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
thesimonho committed Mar 7, 2020
2 parents c0dbe4c + 6295362 commit d50076e
Show file tree
Hide file tree
Showing 13 changed files with 246 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This website has 2 main purposes:
1. Design and fine-tune your commander talents without worrying about resetting in-game talents
2. Make it easy to share your talent builds with other players

![Screenshot](screenshot.png)
![Screenshot](/public/screenshots/app.png)

## :smile: Usage

Expand Down
File renamed without changes
Binary file added public/screenshots/embed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/screenshots/guide.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 56 additions & 0 deletions src/Announcement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import './styles/Announcement.css';

function Announcement() {
return (
<>
<h1>{`New release: v1.2.0`}</h1>

<h2>New Features</h2>
<div>
Thanks to a partnership with{' '}
<a href="https://rok.guide" target="_blank" rel="noopener noreferrer">
rok.guide
</a>
, each commander now has a guide. Clicking on the guide icon next to the
commander name now takes you to the guide for that commander:
</div>
<img
src={`${process.env.PUBLIC_URL}/screenshots/guide.png`}
className="announce-img"
alt="guide"
></img>

<hr className="announce-hr" />

<div>
You can now embed talent builds directly into other websites. If you run
your own website or blog, your talent build can be directly embedded
into your site using an iframe.
<br />
<br />
The embedded talent build will be view-only (i.e. talent points cannot
be changed). You can find the embed code in the Share menu:
</div>
<img
src={`${process.env.PUBLIC_URL}/screenshots/embed.png`}
className="announce-img"
alt="guide"
></img>

<h2>Other Changes</h2>
<ul>
<li>Added Cleopatra to the commander list</li>
<li>Added a share button for Weibo</li>
<li>Removed the commander background image from the info panel</li>
</ul>

<h2>Bug Fixes</h2>
<ul>
<li>Fixed resolution of images and site logo</li>
</ul>
</>
);
}

export default Announcement;
26 changes: 24 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Spinner from 'react-bootstrap/Spinner';
import GuidedTour from './GuidedTour';
import NavBar from './NavBar';
import InfoPanel from './InfoPanel';
import { InvalidBuildModal } from './Modals';
import { InvalidBuildModal, AnnouncementModal } from './Modals';
import ErrorBoundary from './Error';
import loadTreeData from './data/AllTrees';
import Commanders from './data/commanders.json';
Expand All @@ -14,6 +14,7 @@ import {
getTreeName,
setTitle,
isTouchDevice,
isUpgrade,
encode,
decode
} from './utils';
Expand Down Expand Up @@ -46,6 +47,7 @@ class App extends Component {
this.toggleSpeedMode = this.toggleSpeedMode.bind(this);
this.toggleMouseXY = this.toggleMouseXY.bind(this);
this.toggleTalentID = this.toggleTalentID.bind(this);
this.toggleAnnounce = this.toggleAnnounce.bind(this);
this.toggleTour = this.toggleTour.bind(this);
this.changeCommander = this.changeCommander.bind(this);
this.resetTalents = this.resetTalents.bind(this);
Expand Down Expand Up @@ -195,7 +197,9 @@ class App extends Component {
}

componentDidMount() {
localStorage.setItem('version', version);
if (!this.props.isEmbed) {
localStorage.setItem('version', version);
}
}

/**
Expand Down Expand Up @@ -647,6 +651,15 @@ class App extends Component {
this.tourRef.restartTour();
}

/**
* Toggle announcement
*
* @memberof App
*/
toggleAnnounce() {
this.announceRef.show();
}

render() {
return (
<div id="app">
Expand All @@ -657,6 +670,14 @@ class App extends Component {
{this.invalidModalFlag && (
<InvalidBuildModal message={this.invalidBuildMessage} />
)}

<AnnouncementModal
ref={component => (this.announceRef = component)}
isEmbed={this.props.isEmbed}
isUpgrade={isUpgrade(localStorage.getItem('version'), version)}
isInvalidBuild={this.invalidModalFlag}
/>

{!this.props.isEmbed && (
<ErrorBoundary>
<NavBar
Expand All @@ -667,6 +688,7 @@ class App extends Component {
toggleSpeedMode={this.toggleSpeedMode}
toggleMouseXY={this.toggleMouseXY}
toggleTalentID={this.toggleTalentID}
toggleAnnounce={this.toggleAnnounce}
toggleTour={this.toggleTour}
changeCommander={this.changeCommander}
calcPointsSpent={this.calcPointsSpent}
Expand Down
83 changes: 81 additions & 2 deletions src/Modals.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { Component } from 'react';
import ReactGA from 'react-ga';
import Announcement from './Announcement';
import Tabs from 'react-bootstrap/Tabs';
import Tab from 'react-bootstrap/Tab';
import Button from 'react-bootstrap/Button';
Expand All @@ -11,7 +12,8 @@ import {
faShareAlt,
faLink,
faCode,
faCopy
faCopy,
faBullhorn
} from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
Expand Down Expand Up @@ -95,6 +97,63 @@ export class InvalidBuildModal extends Component {
}
}

/**
* Modal displaying announcements
*
* @class AnnouncementModal
* @extends {Component}
*/
export class AnnouncementModal extends Component {
constructor(props) {
super(props);
this.state = {
modal:
this.props.isEmbed || !this.props.isUpgrade || this.props.isInvalidBuild
? false
: true
};

this.toggle = this.toggle.bind(this);
}

toggle() {
this.setState(prevState => ({
modal: !prevState.modal
}));
}

show() {
this.setState({ modal: true });
}

render() {
return (
<Modal
data-testid="announce-modal"
centered
size="lg"
show={this.state.modal}
onHide={this.toggle}
>
<Modal.Header closeButton>
<span>
<FontAwesomeIcon icon={faBullhorn} className="modal-icon" />
</span>
Announcement
</Modal.Header>
<Modal.Body className="modal-body">
<Announcement />
</Modal.Body>
<Modal.Footer>
<Button variant="primary" onClick={this.toggle}>
Close
</Button>
</Modal.Footer>
</Modal>
);
}
}

/**
* Modal displaying information about the application
*
Expand Down Expand Up @@ -207,6 +266,20 @@ export class AboutModal extends Component {
</div>
</Tab>

<Tab eventKey="releases" title="Releases">
<Button
id="button-releases"
variant="success"
size="sm"
onClick={() => {
this.toggle();
this.props.toggleAnnounce();
}}
>
View latest release
</Button>
</Tab>

<Tab eventKey="instructions" title="Instructions">
<ol>
<li>Choose commander in the top-right dropdown list</li>
Expand Down Expand Up @@ -481,4 +554,10 @@ export class ShareModal extends Component {
}
}

export default { InvalidBuildModal, AboutModal, ResetModal, ShareModal };
export default {
InvalidBuildModal,
AnnouncementModal,
AboutModal,
ResetModal,
ShareModal
};
1 change: 1 addition & 0 deletions src/NavBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class NavBar extends Component {
<AboutModal
ref={component => (this.aboutModalRef = component)}
toggleTour={this.props.toggleTour}
toggleAnnounce={this.props.toggleAnnounce}
/>
<ResetModal
ref={component => (this.resetModalRef = component)}
Expand Down
23 changes: 23 additions & 0 deletions src/__tests__/Modals.test.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,42 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import {
InvalidBuildModal,
AnnouncementModal,
AboutModal,
ResetModal,
ShareModal
} from '../Modals';

import { version } from '../../package.json';

describe('Modal', () => {
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<InvalidBuildModal />, div);
ReactDOM.unmountComponentAtNode(div);
});

it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<AnnouncementModal />, div);
ReactDOM.unmountComponentAtNode(div);
});

it('announce displays the current app version', () => {
const currentVersion = `v${version.split('.')[0]}.${version.split('.')[1]}`;
const { getByTestId } = render(
<AnnouncementModal
isEmbed={false}
isUpgrade={true}
isInvalidBuild={false}
/>
);
expect(getByTestId('announce-modal')).toHaveTextContent(currentVersion);
});

it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<AboutModal />, div);
Expand Down
20 changes: 19 additions & 1 deletion src/__tests__/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
encode,
decode,
getURL,
isEmbed
isEmbed,
isUpgrade
} from '../utils';

test('shallow arrays sum correctly', () => {
Expand Down Expand Up @@ -60,6 +61,7 @@ test('max number of multi dimensional talent values is correct', () => {

test('single dimensional text is replaced correctly', () => {
const values = [5, 6];
// eslint-disable-next-line no-template-curly-in-string
const text = 'String containing value of ${1}';
expect(replaceTalentText(text, values, 0)).toEqual(
'String containing value of 5'
Expand All @@ -68,6 +70,7 @@ test('single dimensional text is replaced correctly', () => {

test('single dimensional text is replaced correctly globally', () => {
const values = [5, 6];
// eslint-disable-next-line no-template-curly-in-string
const text = 'String containing double value of ${1} and ${1}';
expect(replaceTalentText(text, values, 0)).toEqual(
'String containing double value of 5 and 5'
Expand All @@ -79,6 +82,7 @@ test('multi dimensional text is replaced correctly', () => {
[2, 9],
[4, 7]
];
// eslint-disable-next-line no-template-curly-in-string
const text = 'String containing values of ${1} and ${2}';
expect(replaceTalentText(text, values, 1)).toEqual(
'String containing values of 9 and 7'
Expand All @@ -90,6 +94,7 @@ test('multi dimensional text is replaced correctly globally', () => {
[2, 9],
[4, 7]
];
// eslint-disable-next-line no-template-curly-in-string
const text = 'String containing values of ${1} and ${2}, and again ${1}';
expect(replaceTalentText(text, values, 1)).toEqual(
'String containing values of 9 and 7, and again 9'
Expand Down Expand Up @@ -123,3 +128,16 @@ test('returns embed URL', () => {
test('returns non-embed URL', () => {
expect(getURL().includes('embed')).toEqual(false);
});

test('version change upgrade is correctly detected', () => {
localStorage.setItem('isNewUser', false);

expect(isUpgrade('1.2.1', '2.2.1')).toEqual(true);
expect(isUpgrade('1.2.1', '1.3.1')).toEqual(true);
expect(isUpgrade('1.2.1', '2.1.1')).toEqual(true);

expect(isUpgrade('1.2.1', '1.2.1')).toEqual(false);
expect(isUpgrade('2.2.1', '1.2.1')).toEqual(false);
expect(isUpgrade('1.2.1', '1.1.1')).toEqual(false);
expect(isUpgrade('1.2.1', '1.2.2')).toEqual(false);
});
12 changes: 12 additions & 0 deletions src/styles/Announcement.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.announce-img {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 10px;
margin-bottom: 15px;
border: 1px solid rgba(0, 0, 0, 1);
}

.announce-hr {
width: 90%;
}
5 changes: 5 additions & 0 deletions src/styles/Modals.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
border-radius: 5px;
}

#button-releases {
margin: 0 auto;
display: block;
}

#button-tour {
margin: 0 auto;
display: block;
Expand Down
Loading

0 comments on commit d50076e

Please sign in to comment.