Skip to content
Open
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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ Set the environment variables found in `set_envs.sample`.
#### Important: if running the development server, prefix all `SERVER`
variables with http://. The proxy won't work otherwise and all the servers will
break

- Important debug note: due to limitation set by Chrome (which doesn't
allow cookies to be set by localhost), the login feature might not work
properly in Chrome. Therefore, please test with other browsers (e.g.
Safari) or put the site on a standard domain to test.
128 changes: 128 additions & 0 deletions client/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,136 @@ export const RESIZE_WINDOW = 'RESIZE_WINDOW';
// Logging - track data, doesn't impact rendering
export const LOG_BOUNDS = 'LOG_BOUNDS';

// User Settings
export const TOGGLE_TRACKING = 'TOGGLE_TRACKING';
export const OPEN_USER_SETTINGS_PANE = 'OPEN_USER_SETTINGS_PANE';
export const CLOSE_USER_SETTINGS_PANE = 'CLOSE_USER_SETTINGS_PANE';
export const OPEN_PROFILE_MANAGER_PANE = 'OPEN_PROFILE_MANAGER_PANE';
export const CLOSE_PROFILE_MANAGER_PANE = 'CLOSE_PROFILE_MANAGER_PANE';
export const FETCHING_USER_ROUTING_PROFILE = 'FETCHING_USER_ROUTING_PROFILE';
export const FINISHED_FETCHING_USER_ROUTING_PROFILE = 'FINISHED_FETCHING_USER_ROUTING_PROFILE';
export const UPDATE_USER_ROUTING_PROFILE = 'UPDATE_USER_ROUTING_PROFILE';
export const CHANGE_USER_ROUTING_PROFILE_SELECTION = 'CHANGE_USER_ROUTING_PROFILE_SELECTION';

// Action creators
export function changeUserRoutingProfileSelection (selectedIndex) {
return {
type: CHANGE_USER_ROUTING_PROFILE_SELECTION,
payload: selectedIndex,
meta: {
analytics: {
type: 'change-user-routing-profile-selection',
}
}
};
}

export function refreshUserRoutingProfiles() {
return (dispatch) => {
dispatch(isFetchingUserRoutingProfiles(true));
const loadUserProfiles = require('../utils/api').loadUserProfiles;
loadUserProfiles().then(result => {
if (result.error != null) {
dispatch(updateUserRoutingProfiles(null));
dispatch(isFetchingUserRoutingProfiles(false));
return;
}
const profiles = result.data;
dispatch(updateUserRoutingProfiles([]));
dispatch(updateUserRoutingProfiles(profiles));
dispatch(isFetchingUserRoutingProfiles(false));
});
};
}

export function isFetchingUserRoutingProfiles(isFetching) {
if (isFetching) {
return {
type: FETCHING_USER_ROUTING_PROFILE,
meta: {
analytics: {
type: 'fetching-user-routing-profile',
}
}
};
}
return {
type: FINISHED_FETCHING_USER_ROUTING_PROFILE,
meta: {
analytics: {
type: 'finished-fetching-user-routing-profile',
}
}
};
}

export function updateUserRoutingProfiles(profiles) {
return {
type: UPDATE_USER_ROUTING_PROFILE,
payload: profiles,
meta: {
analytics: {
type: 'update-user-routing-profile',
}
}
};
}

export function openRoutingProfileManager() {
return {
type: OPEN_PROFILE_MANAGER_PANE,
meta: {
analytics: {
type: 'open-routing-profile-manager',
}
}
};
}

export function closeRoutingProfileManager() {
return {
type: CLOSE_PROFILE_MANAGER_PANE,
meta: {
analytics: {
type: 'close-routing-profile-manager',
}
}
};
}

export function openUserPreferences() {
return {
type: OPEN_USER_SETTINGS_PANE,
meta: {
analytics: {
type: 'open-user-setting',
}
}
};
}

export function closeUserPreferences() {
return {
type: CLOSE_USER_SETTINGS_PANE,
meta: {
analytics: {
type: 'close-user-setting',
}
}
};
}

export function toggleTracking() {
return {
type: TOGGLE_TRACKING,
meta: {
analytics: {
type: 'toggle-tracking',
}
}
};
}

export function toggleTripPlanning(planningTrip) {
return (dispatch, getState) => {
const {waypoints} = getState();
Expand Down
27 changes: 27 additions & 0 deletions client/components/OpenIDAuth/AuthProviderCallback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";
import { connect } from "react-redux";
import { CallbackComponent } from "redux-oidc";
import { push } from "react-router-redux";
import userManager from "../../utils/UserManager";

class CallbackPage extends React.Component {
render() {
// just redirect to '/' in both cases
return (
<CallbackComponent
userManager={userManager}
successCallback={() => this.props.dispatch(push("/"))}
errorCallback={() => this.props.dispatch(push("/"))}
>
<div>
<br/>
&nbsp;&nbsp; Redirecting...<br/><br/>
&nbsp;&nbsp; If this page take too long to respond, please try logging in again or
contact AccessMap group.
</div>
</CallbackComponent>
);
}
}

export default connect()(CallbackPage);
17 changes: 17 additions & 0 deletions client/components/OpenIDAuth/SilentRenew.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from "react";
import { connect } from "react-redux";
import { processSilentRenew } from 'redux-oidc';

class SilentRenewPage extends React.Component {
componentWillMount () {
processSilentRenew();
}

render() {
return (
<div style={{display: 'none'}}/>
);
}
}

export default connect()(SilentRenewPage);
130 changes: 130 additions & 0 deletions client/components/OpenIDAuth/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import React from 'react';
import { connect } from 'react-redux';
import userManager from '../../utils/UserManager';
import { loadUserInfo } from '../../utils/api';
import PropTypes from 'prop-types';
import { DropdownMenu } from 'react-md/lib/Menus/index';
import Avatar from 'react-md/lib/Avatars';
import {
AccessibleFakeButton,
IconSeparator,
} from 'react-md/lib/Helpers';
import { FontIcon } from 'react-md/lib/FontIcons';
import * as AppActions from '../../actions';
import { bindActionCreators } from 'redux';

function UserMenu (props) {
const {
actions,
user
} = props;

const DropdownItems = [];
if (user && (!user.expired)) {
DropdownItems.push({
primaryText: '[DEBUG] Show Token Info',
onClick: () => {
// TODO: delete debug prompt
alert(
JSON.stringify(user, null, 2),
);
},
},
{
primaryText: '[DEBUG] Get User Info with Token',
onClick: () => loadUserInfo(),
},
{
primaryText: 'Manage Routing Profiles',
onClick: actions.openRoutingProfileManager,
});
}
DropdownItems.push({
primaryText: 'Preferences',
onClick: actions.openUserPreferences,
},
{divider: true});
if (!user || user.expired) {
DropdownItems.push({
primaryText: 'Sign In',
onClick: onSignInButtonClick,
});
} else {
DropdownItems.push({
primaryText: 'Manage Account',
onClick: () => window.open(
'https://accounts.open-to-all.com/auth/realms/OpenToAll/account',
'_blank'),
}, {
primaryText: 'Sign Out',
onClick: onSignOutButtonClick,
});
}

const AccountMenu = ({simplifiedMenu}) => (
<DropdownMenu
className={'md-btn--toolbar'}
id={`${!simplifiedMenu ? 'smart-' : ''}avatar-dropdown-menu`}
menuItems={DropdownItems}
anchor={{
x: DropdownMenu.HorizontalAnchors.INNER_RIGHT,
y: DropdownMenu.VerticalAnchors.BOTTOM,
}}
position={DropdownMenu.Positions.BELOW}
animationPosition="below"
sameWidth
simplifiedMenu={simplifiedMenu}
>
<AccessibleFakeButton
component={IconSeparator}
iconBefore
label={
<IconSeparator
label={user ? user.profile.email : 'Guest'}>
<FontIcon>arrow_drop_down</FontIcon>
</IconSeparator>
}
>
<Avatar suffix={user ? 'pink' : 'grey'}>
{user ? user.profile.name.charAt(0) : 'G'}
</Avatar>
</AccessibleFakeButton>
</DropdownMenu>
);

AccountMenu.propTypes = {
simplifiedMenu: PropTypes.bool,
};

return (<AccountMenu/>);
}

function onSignInButtonClick (event) {
event.preventDefault();
userManager.signinRedirect();
}

function onSignOutButtonClick (event) {
event.preventDefault();
userManager.removeUser(); // removes the user data from sessionStorage
}

function mapStateToProps (state) {
return {
user: state.oidc.user,
};
}

// function mapDispatchToProps (dispatch) {
// return {
// dispatch,
// };
// }

function mapDispatchToProps (dispatch) {
return {
actions: bindActionCreators(AppActions, dispatch)
};
}

export default connect(mapStateToProps, mapDispatchToProps)(UserMenu);
62 changes: 62 additions & 0 deletions client/components/Preferences/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* WithScrollingContent.jsx */
/* eslint-disable react/no-array-index-key */
import React from 'react';
import { connect } from 'react-redux';
import { DialogContainer } from 'react-md/lib/Dialogs';
import { Switch } from 'react-md/lib/SelectionControls';
import * as AppActions from '../../actions';
import { bindActionCreators } from 'redux';

function UserPreferences (props) {
const {
actions,
visible,
preferences,
} = props;

const contentProps = {id: 'scrolling-content-dialog-content'};

return (
<DialogContainer
id="scrolling-content-dialog"
aria-describedby="scrolling-content-dialog-content"
title='Preferences'
visible={visible}
onHide={actions.closeUserPreferences}
actions={[
{
label: 'Close',
primary: true,
onClick: actions.closeUserPreferences,
}]}
contentProps={contentProps}
>
<Switch
id="switch-toggle-tracking"
type="switch"
label="Tracking"
name="toggleTracking"
checked={preferences.enableTracking}
onChange={actions.toggleTracking}
/>
</DialogContainer>
);
}

function mapStateToProps (state) {
return {
visible: state.viewVisibility.showUserSettingsPane,
preferences: state.userpreference,
};
}

function mapDispatchToProps (dispatch) {
return {
actions: bindActionCreators(AppActions, dispatch)
};
}

export default connect(
mapStateToProps,
mapDispatchToProps,
)(UserPreferences);
Loading