Skip to content

Commit

Permalink
Merge branch 'master' into react-fix-travis
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdns authored Apr 27, 2018
2 parents 9ca54b8 + 2cec187 commit 09cc71d
Show file tree
Hide file tree
Showing 34 changed files with 378 additions and 103 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ env:

# if JHIPSTER_LIB_BRANCH value is release, use the release from Maven
- JHIPSTER_LIB_REPO=https://github.com/jhipster/jhipster.git
- JHIPSTER_LIB_BRANCH=release
- JHIPSTER_LIB_BRANCH=master
# if JHIPSTER_BRANCH value is release, use the release from NPM
- JHIPSTER_REPO=https://github.com/jhipster/generator-jhipster.git
- JHIPSTER_BRANCH=release
Expand Down
6 changes: 4 additions & 2 deletions generators/client/files-react.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ const files = {
templates: [
'shared/reducers/index.ts',
'shared/reducers/action-type.util.ts',
'shared/reducers/authentication.ts'
'shared/reducers/authentication.ts',
'shared/reducers/application-profile.ts'
]
},
{
Expand Down Expand Up @@ -364,10 +365,11 @@ const files = {
'spec/entry.ts',
'spec/app/utils.ts',
'spec/app/config/notification-middleware.spec.ts',
'spec/app/shared/layout/header.spec.tsx',
'spec/app/shared/reducers/application-profile.spec.ts',
'spec/app/shared/reducers/authentication.spec.ts',
'spec/app/shared/util/entity-utils.spec.ts',
'spec/app/shared/auth/private-route.spec.tsx',
'spec/app/shared/layout/header.spec.tsx',
'spec/app/modules/account/register/register.spec.tsx',
'spec/app/modules/account/register/register.reducer.spec.ts',
'spec/app/modules/account/activate/activate.reducer.spec.ts',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,27 @@ import { ProfileInfo } from './profile-info.model';
@Injectable()
export class ProfileService {

private profileInfoUrl = SERVER_API_URL + 'api/profile-info';
private infoUrl = SERVER_API_URL + 'management/info';
private profileInfo: Promise<ProfileInfo>;

constructor(private http: HttpClient) { }

getProfileInfo(): Promise<ProfileInfo> {
if (!this.profileInfo) {
this.profileInfo = this.http.get<ProfileInfo>(this.profileInfoUrl, { observe: 'response' })
this.profileInfo = this.http.get<ProfileInfo>(this.infoUrl, { observe: 'response' })
.map((res: HttpResponse<ProfileInfo>) => {
const data = res.body;
const pi = new ProfileInfo();
pi.activeProfiles = data.activeProfiles;
pi.ribbonEnv = data.ribbonEnv;
pi.inProduction = data.activeProfiles.includes('prod') ;
pi.swaggerEnabled = data.activeProfiles.includes('swagger');
pi.activeProfiles = data['activeProfiles'];
const displayRibbonOnProfiles = data['display-ribbon-on-profiles'].split(',');
if (pi.activeProfiles) {
const ribbonProfiles = displayRibbonOnProfiles.filter((profile) => pi.activeProfiles.includes(profile));
if (ribbonProfiles.length !== 0) {
pi.ribbonEnv = ribbonProfiles[0];
}
pi.inProduction = pi.activeProfiles.includes('prod');
pi.swaggerEnabled = pi.activeProfiles.includes('swagger');
}
return pi;
}).toPromise();
}
Expand Down
18 changes: 15 additions & 3 deletions generators/client/templates/react/src/main/webapp/app/app.tsx.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { HashRouter as Router } from 'react-router-dom';
import { ToastContainer, toast } from 'react-toastify';

import { getSession } from 'app/shared/reducers/authentication';
import { getProfile } from 'app/shared/reducers/application-profile';
<%_ if (enableTranslation) { _%>
import { setLocale } from 'app/shared/reducers/locale';
<%_ } _%>
Expand All @@ -37,16 +38,21 @@ import AppRoutes from 'app/routes';
export interface IAppProps {
isAuthenticated: boolean;
isAdmin: boolean;
ribbonEnv: string;
isInProduction: boolean;
isSwaggerEnabled: boolean;
<%_ if (enableTranslation) { _%>
currentLocale: string;
setLocale: Function;
<%_ } _%>
getSession: Function;
getProfile: Function;
}

export class App extends React.Component<IAppProps> {
componentDidMount() {
this.props.getSession();
this.props.getProfile();
}

render() {
Expand All @@ -62,6 +68,9 @@ export class App extends React.Component<IAppProps> {
currentLocale={this.props.currentLocale}
onLocaleChange={this.props.setLocale}
<%_ } _%>
ribbonEnv={this.props.ribbonEnv}
isInProduction={this.props.isInProduction}
isSwaggerEnabled={this.props.isSwaggerEnabled}
/>
<div className="container-fluid view-container" id="app-view-container">
<Card className="jh-card">
Expand All @@ -75,14 +84,17 @@ export class App extends React.Component<IAppProps> {
}
}

const mapStateToProps = ({ authentication<% if (enableTranslation) { %>, locale<% } %> }) => ({
const mapStateToProps = ({ authentication, applicationProfile<% if (enableTranslation) { %>, locale<% } %> }) => ({
<%_ if (enableTranslation) { _%>
currentLocale: locale.currentLocale,
<%_ } _%>
isAuthenticated: authentication.isAuthenticated,
isAdmin: hasAnyAuthority(authentication.account.authorities, [AUTHORITIES.ADMIN])
isAdmin: hasAnyAuthority(authentication.account.authorities, [AUTHORITIES.ADMIN]),
ribbonEnv: applicationProfile.ribbonEnv,
isInProduction: applicationProfile.inProduction,
isSwaggerEnabled: applicationProfile.isSwaggerEnabled
});

const mapDispatchToProps = { <% if (enableTranslation) { %>setLocale, <% } %>getSession };
const mapDispatchToProps = { <% if (enableTranslation) { %>setLocale, <% } %>getSession, getProfile };

export default connect(mapStateToProps, mapDispatchToProps)(App);
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ import appConfig from 'app/config/constants';
export interface IHeaderProps {
isAuthenticated: boolean;
isAdmin: boolean;
ribbonEnv: string;
isInProduction: boolean;
isSwaggerEnabled: boolean;
<%_ if (enableTranslation) { _%>
currentLocale: string;
onLocaleChange: Function;
Expand All @@ -72,7 +75,8 @@ const BrandIcon = props => (
/>
</div>
);
export class Header extends React.Component<IHeaderProps, IHeaderState> {

export default class Header extends React.Component<IHeaderProps, IHeaderState> {
state: IHeaderState = {
menuOpen: false
};
Expand All @@ -89,13 +93,19 @@ export class Header extends React.Component<IHeaderProps, IHeaderState> {
document.querySelector('html').setAttribute('dir', isRTL(event.target.value) ? 'rtl' : 'ltr');
<%_ } _%>
}
<%_ } _%>
renderDevRibbon = () => (
process.env.NODE_ENV === 'development' ?
<div className="ribbon dev"><a href=""><Translate contentKey="global.ribbon.dev">Development</Translate></a></div> :
null
)

renderDevRibbon = () => this.props.isInProduction === false ? (
<div className="ribbon dev">
<a href="">
<%_ if (enableTranslation) { _%>
<Translate contentKey={`global.ribbon.${this.props.ribbonEnv}`} />
<%_ } else { _%>
Development
<%_ } _%>
</a>
</div>
) : null;

toggleMenu = () => {
this.setState({ menuOpen: !this.state.menuOpen });
Expand All @@ -121,15 +131,27 @@ export class Header extends React.Component<IHeaderProps, IHeaderState> {
<DropdownItem tag={Link} key="metrics" to="/admin/metrics"><FaDashboard /> Metrics</DropdownItem>,
<DropdownItem tag={Link} key="health" to="/admin/health"><FaHeart /> Health</DropdownItem>,
<DropdownItem tag={Link} key="configuration" to="/admin/configuration"><FaList /> Configuration</DropdownItem>,
<%_ if (databaseType !== 'cassandra') { _%>
<%_ if (databaseType !== 'cassandra') { _%>
<DropdownItem tag={Link} key="audits" to="/admin/audits"><FaBell /> Audits</DropdownItem>,
<%_ } _%>
<DropdownItem tag={Link} key="logs" to="/admin/logs"><FaTasks /> Logs</DropdownItem>,
<%_ } _%>
/* jhipster-needle-add-element-to-admin-menu - JHipster will add entities to the admin menu here */
<DropdownItem tag={Link} key="docs" to="/admin/docs"><FaBook /> API Docs</DropdownItem><% if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { %>,
<DropdownItem tag="a" key="h2-console" href="./h2-console" target="_tab"><FaHddO /> Database</DropdownItem>
<%_ } _%>
<DropdownItem tag={Link} key="logs" to="/admin/logs"><FaTasks /> Logs</DropdownItem>
];

const swaggerItem = (
<DropdownItem tag={Link} key="docs" to="/admin/docs">
<FaBook /> API Docs
</DropdownItem>
);

<% if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { %>
const databaseItem = [
<DropdownItem tag="a" key="h2-console" href="./h2-console" target="_tab">
<FaHddO /> Database
</DropdownItem>
];
<%_ } _%>

const accountMenuItems = [];
if (isAuthenticated) {
accountMenuItems.push(
Expand Down Expand Up @@ -172,6 +194,10 @@ export class Header extends React.Component<IHeaderProps, IHeaderState> {
</DropdownToggle>
<DropdownMenu right style={{ width: '130%' }}>
{adminMenuItems}
{this.props.isSwaggerEnabled ? swaggerItem : null}
<% if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { %>
{!this.props.isInProduction ? databaseItem : null}
<%_ } _%>
</DropdownMenu>
</UncontrolledDropdown>
);
Expand Down Expand Up @@ -225,5 +251,3 @@ export class Header extends React.Component<IHeaderProps, IHeaderState> {
);
}
}

export default Header;
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<%#
Copyright 2013-2018 the original author or authors from the JHipster project.
This file is part of the JHipster project, see https://www.jhipster.tech/
for more information.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-%>
import axios from 'axios';

import { SUCCESS } from 'app/shared/reducers/action-type.util';

export const ACTION_TYPES = {
GET_PROFILE: 'applicationProfile/GET_PROFILE'
};

const initialState = {
ribbonEnv: '',
inProduction: true,
isSwaggerEnabled: false
};

export default (state = initialState, action) => {
switch (action.type) {
case SUCCESS(ACTION_TYPES.GET_PROFILE):
const { data } = action.payload;
return {
...state,
ribbonEnv: data.ribbonEnv,
inProduction: data.activeProfiles.includes('prod'),
isSwaggerEnabled: data.activeProfiles.includes('swagger')
};
default:
return state;
}
};

export const getProfile = () => ({
type: ACTION_TYPES.GET_PROFILE,
payload: axios.get('/api/profile-info')
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,30 @@ describe('Header', () => {
<% if (enableTranslation) { %>
const localeSpy = sinon.spy();
<% } %>
const wrapper = () => {
const devWrapper = () => {
if (!mountedWrapper) {
mountedWrapper = shallow(
<Header isAuthenticated isAdmin<% if (enableTranslation) { %> currentLocale="en" onLocaleChange={localeSpy}<% } %>/>
<Header
isAuthenticated
isAdmin<% if (enableTranslation) { %> currentLocale="en" onLocaleChange={localeSpy}<% } %>
ribbonEnv="dev"
isInProduction={false}
isSwaggerEnabled
/>
);
}
return mountedWrapper;
};
const prodWrapper = () => {
if (!mountedWrapper) {
mountedWrapper = shallow(
<Header
isAuthenticated
isAdmin<% if (enableTranslation) { %> currentLocale="en" onLocaleChange={localeSpy}<% } %>
ribbonEnv="prod"
isInProduction
isSwaggerEnabled={false}
/>
);
}
return mountedWrapper;
Expand All @@ -49,12 +69,25 @@ describe('Header', () => {
});

// All tests will go here
it('Renders a component with LoadingBar, Navbar and Nav', () => {
const navbar = wrapper().find(Navbar);
it('Renders a Header component in dev profile with LoadingBar, Navbar, Nav and dev ribbon.', () => {
const navbar = devWrapper().find(Navbar);
expect(navbar.length).to.equal(1);
expect(navbar.find(NavbarBrand).find('.brand-logo').length).to.equal(1);
const nav = devWrapper().find(Nav);
expect(nav.length).to.equal(1);
expect(nav.find(NavItem).length).to.equal(1);
const ribbon = devWrapper().find('.ribbon .dev');
expect(ribbon.length).to.equal(1);
});

it('Renders a Header component in prod profile with LoadingBar, Navbar, Nav.', () => {
const navbar = prodWrapper().find(Navbar);
expect(navbar.length).to.equal(1);
expect(navbar.find(NavbarBrand).find('.brand-logo').length).to.equal(1);
const nav = wrapper().find(Nav);
const nav = prodWrapper().find(Nav);
expect(nav.length).to.equal(1);
expect(nav.find(NavItem).length).to.equal(1);
const ribbon = prodWrapper().find('.ribbon .dev');
expect(ribbon.length).to.equal(0);
});
});
Loading

0 comments on commit 09cc71d

Please sign in to comment.