Skip to content

Commit

Permalink
Added flash messages to rbac user module.
Browse files Browse the repository at this point in the history
  • Loading branch information
Hyperkid123 committed Aug 30, 2018
1 parent 29bf2b5 commit 10a95b7
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 15 deletions.
2 changes: 1 addition & 1 deletion app/assets/javascripts/controllers/tree_view_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
listenToRx(function(payload) {
if (payload.type === 'init-react-routing' && !vm.reactRouting) {
vm.reactRouting = !!payload.reactRouting;
vm.$scope.$apply;
vm.$scope.$apply();
}
if (payload.type === 'disable-react-routing') {
vm.reactRouting = false;
Expand Down
3 changes: 3 additions & 0 deletions app/assets/stylesheets/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ $login-container-details-border-color-rgba: rgba(0, 0, 0, 0.5);
@import "alerts";
@import "graphql_explorer";

// react components styles
@import 'react_components.scss';

.login-pf #brand img { // sets size of brand.svg on login screen (upstream only)
height: 38px;
}
Expand Down
15 changes: 15 additions & 0 deletions app/assets/stylesheets/react_components.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// TO-DO move this to separate file after we have css in webpack

@keyframes FadeAnimation {
0% {
opacity: 1;
}
100% {
opacity: 0;
visibility: hidden;
}
}

.react-fading-flash {
animation: FadeAnimation 1s ease-out 4s forwards;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Alert } from 'patternfly-react';
import { removeFlashMessage } from '../redux/actions';

class FlashMessage extends Component {
componentDidMount() {
const { message, onDismiss } = this.props;
if (message.type !== 'error') {
setTimeout(() => {
onDismiss(message);
}, 5000);
}
}
render() {
const { message: { text, type }, onDismiss } = this.props;
return (
<div className={type !== 'error' ? 'react-fading-flash' : ''}>
<Alert type={type} onDismiss={() => onDismiss(this.props.message)}>
{text}
</Alert>
</div>
);
}
}

const FlashMessages = ({ flashMessages, removeFlashMessage }) =>
flashMessages.map(message =>
<FlashMessage key={message.flashId} message={message} onDismiss={removeFlashMessage}/>);

const mapStateToProps = ({ usersReducer: { flashMessages } }) => ({
flashMessages,
});

const mapDispatchToProps = dispatch => bindActionCreators({
removeFlashMessage,
}, dispatch)

export default connect(mapStateToProps, mapDispatchToProps)(FlashMessages);
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Redirect } from 'react-router-dom';
import { goBack } from 'connected-react-router';
import { Spinner } from 'patternfly-react';
import { RbacAssignCompanyTags } from '@manageiq/react-ui-components/dist/rbac-forms';
import { loadTagsCategories } from '../redux/actions';
import { loadTagsCategories, createFlashMessage } from '../redux/actions';
import { http } from '../../../http_api';

const categoryEntryEndpoint = categoryId => `/ops/get_category_entries?cat_id=${categoryId}`;
Expand All @@ -15,11 +15,17 @@ class TagAssignment extends Component {
if (!this.props.categories) this.props.loadTagsCategories()
}

handleCancelClicked = () => {
const { goBack, createFlashMessage } = this.props;
createFlashMessage(__('Tag Edit was cancelled by the user'), 'info');
goBack();
};

handleLoadMultipleEntries = categories =>
http.get(`/ops/get_category_entries_multi?ids[]=${categories.join('&ids[]=')}`);

render() {
const { categories, goBack, selectedUsers, columns } = this.props;
const { categories, selectedUsers, columns } = this.props;
if (!selectedUsers) return <Redirect to="/" />;
if (!categories) return <div><Spinner loading size="lg" /></div>;
return (
Expand All @@ -30,7 +36,7 @@ class TagAssignment extends Component {
columns={columns}
loadCategoryEntry={categoryId => http.get(categoryEntryEndpoint(categoryId))}
loadMultipleEntries={this.handleLoadMultipleEntries}
handleCancel={goBack}
handleCancel={this.handleCancelClicked}
handleSave={(selection, initial, users) => console.log('tagsSave: ', { selection, initial, users })}
/>
</div>
Expand All @@ -47,6 +53,7 @@ const mapStateToProps = ({ usersReducer: { categories, selectedUsers, columns }
const mapDispatchToProps = dispatch => bindActionCreators({
loadTagsCategories,
goBack,
createFlashMessage,
}, dispatch);

export default connect(mapStateToProps, mapDispatchToProps)(TagAssignment);
19 changes: 13 additions & 6 deletions app/javascript/components/rbac-user-module/components/user-add.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Spinner } from 'patternfly-react';
import { goBack } from 'connected-react-router';
import { Redirect } from 'react-router-dom';
import { RbacUserForm } from '@manageiq/react-ui-components/dist/rbac-forms';
import { loadGroups, saveUser, editUser } from '../redux/actions';
import { loadGroups, saveUser, editUser, createFlashMessage } from '../redux/actions';

const parseUserValues = ({
name,
Expand All @@ -27,20 +27,26 @@ class UserAdd extends Component {
this.props.loadGroups();
}
}
handleCancelClicked = () => {
const { goBack, createFlashMessage } = this.props;
createFlashMessage(__('User Edit was cancelled by the user'), 'info');
goBack();
};
render() {
const { groups, goBack, saveUser, isEditing, editUser, user, copy } = this.props;
const { groups, saveUser, isEditing, editUser, user, copy } = this.props;
if (isEditing && !user) return <Redirect to="/add" />;
if (copy && !user) return <Redirect to="/add" />;
if (!groups) return <div><Spinner loading size="lg" /></div>;
const initialValues = copy ? { ...user, userid: undefined } : user;
return (
<div>
<h1>User add</h1>
<RbacUserForm
groups={groups}
newRecord={!isEditing && !copy}
initialValues={user ? {...user, groups: user.groups.map(({ groupId }) => groupId)} : undefined}
onCancel={goBack}
onSave={values => isEditing || copy ? editUser(parseUserValues(values), user.id) : saveUser(parseUserValues(values))}
newRecord={!isEditing}
initialValues={initialValues ? {...initialValues, groups: user.groups.map(({ groupId }) => groupId)} : undefined}
onCancel={this.handleCancelClicked}
onSave={values => isEditing ? editUser(parseUserValues(values), user.id) : saveUser(parseUserValues(values))}
/>
</div>
);
Expand All @@ -63,6 +69,7 @@ const mapDispatchToProps = dispatch => bindActionCreators({
goBack,
saveUser,
editUser,
createFlashMessage,
}, dispatch);

export default connect(mapStateToProps, mapDispatchToProps)(UserAdd);
4 changes: 4 additions & 0 deletions app/javascript/components/rbac-user-module/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import usersReducer from './redux/users-reducer';
import RbacUsersList from './components/users-list';
import UserDetail from './components/user-detail';
import UserAdd from './components/user-add';
import FlashMessages from './components/flash-messages';
import TagAssignment from './components/tagg-assignment';
import { listenToRx } from '../../miq_observable';
import {
Expand Down Expand Up @@ -105,6 +106,9 @@ class RbacModule extends Component {
return (
<Grid fluid>
<Row>
<Col xs={12}>
<FlashMessages />
</Col>
<Col xs={12}>
<h1>Rbac module</h1>
<ConnectedRouter history={ManageIQ.redux.history}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ export const LOAD_GROUPS = `${prefix}Load user groups`;
export const STORE_GROUPS = `${prefix}Store user groups`;
export const STORE_USERS_TREE = `${prefix}Store users tree`;
export const EDIT_USER = `${prefix}Edit user`;
export const STORE_TAG_CATEGORIES = `${prefix}Store tag categories`;
export const STORE_TAG_CATEGORIES = `${prefix}Store tag categories`;
export const ADD_FLASH_MESSAGE = `${prefix}Add flash message`;
export const REMOVE_FLASH_MESSAGE = `${prefix}Remove flash message;`;
29 changes: 26 additions & 3 deletions app/javascript/components/rbac-user-module/redux/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,23 @@ export const saveUser = user => (dispatch) => {
return API.post(endpoints.modifyUserUrl(), user)
.then(() => dispatch(requestUsers()))
.then(() => dispatch(handleUpdateUsersTree()))
.then(() => dispatch(createFlashMessage(sprintf(__('User "%s" was saved'), user.name), 'success')))
.then(() => dispatch(navigate('/')))
.catch(() => dispatch(fetchFailed));
};

export const deleteUser = userId => (dispatch) => {
export const deleteUser = userId => (dispatch, getState) => {
dispatch(fetchData(actionTypes.DELETE_USER));
dispatch(navigate('/'));
const name = getState().usersReducer.rows.find(({ id }) => id === userId);
return API.delete(endpoints.modifyUserUrl(userId))
.then(() => dispatch(createFlashMessage(sprintf(__('User "%s" was deleted'), name), 'success')))
.then(() => dispatch(requestUsers()))
.then(() => dispatch(handleUpdateUsersTree()))
.catch(() => dispatch(fetchFailed()));
.catch((error) => {
dispatch(fetchFailed());
console.log(error);
});
};

export const editUser = (user, userId) => (dispatch) => {
Expand All @@ -119,6 +125,7 @@ export const editUser = (user, userId) => (dispatch) => {
() => dispatch(navigate('/')),
(err) => { throw err; },
)
.then(() => dispatch(createFlashMessage(sprintf(__('User "%s" was saved'), user.name), 'success')))
.then(() => dispatch(requestUsers()))
.then(() => dispatch(handleUpdateUsersTree()))
.catch(() => dispatch(fetchFailed()));
Expand Down Expand Up @@ -147,7 +154,9 @@ export const deleteMultipleusers = users => (dispatch) => {
return API.post(endpoints.modifyUserUrl(), {
action: 'delete',
resources: users.map(user => ({ id: user.id })),
}).then(
})
.then(() => users.map(({ name }) => dispatch(createFlashMessage(sprintf(__('User "%s" was deleted'), name), 'success'))))
.then(
() => dispatch(requestUsers()),
(error) => { throw error; },
)
Expand Down Expand Up @@ -228,3 +237,17 @@ export const loadTagsCategories = () => dispatch => API.get(endpoints.getTagCate
return (dispatch(fetchFailed));
};
*/

export const createFlashMessage = (text, type) => ({
type: actionTypes.ADD_FLASH_MESSAGE,
flashMessage: {
text,
type,
flashId: Date.now(),
}
})

export const removeFlashMessage = flashMessage => ({
type: actionTypes.REMOVE_FLASH_MESSAGE,
flashMessage,
})
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const usersReducer = (state = {
isFetching: false,
isValid: true,
columns,
flashMessages: [],
}, action) => {
let newState = {};
switch (action.type) {
Expand Down Expand Up @@ -55,6 +56,10 @@ const usersReducer = (state = {
return { ...state, usersTree: action.usersTree };
case actionTypes.STORE_TAG_CATEGORIES:
return { ...state, categories: action.categories };
case actionTypes.ADD_FLASH_MESSAGE:
return { ...state, flashMessages: [...state.flashMessages, action.flashMessage] }
case actionTypes.REMOVE_FLASH_MESSAGE:
return { ...state, flashMessages: state.flashMessages.filter(({ flashId }) => flashId !== action.flashMessage.flashId) }
default:
return { ...state };
}
Expand Down
1 change: 0 additions & 1 deletion app/javascript/packs/component-definitions-common.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import { TagGroup, TableListView, GenericGroup } from '@manageiq/react-ui-components/dist/textual_summary';
import { AmazonSecurityGroupForm } from '@manageiq/react-ui-components/dist/amazon-security-form-group';
import TextualSummaryWrapper from '../react/textual_summary_wrapper';
import TableListViewWrapper from '../react/table_list_view_wrapper';
import GenericGroupWrapper from '../react/generic_group_wrapper';
Expand Down

0 comments on commit 10a95b7

Please sign in to comment.