notification

This commit is contained in:
insanity 2017-08-29 16:16:36 +09:00
parent b6a028c6d8
commit 481c602f61
12 changed files with 261 additions and 21 deletions

View File

@ -45,6 +45,7 @@ import HistoryReadAllByProbeReducer from '@overflow/history/redux/reducer/read_a
import HistoryReadAllByProbeAndTypeReducer from '@overflow/history/redux/reducer/read_all_by_probe_and_type';
import HistoryTypeReadAllReducer from '@overflow/meta/redux/reducer/history_type_read_all';
import NotificationReadAllUnconfirmedReducer from '@overflow/notification/redux/reducer/read_all_unconfirmed';
import NotificationReadAllReducer from '@overflow/notification/redux/reducer/read_all';
import AsyncRequest from '@overflow/app/redux/saga/AsyncRequest';
@ -115,6 +116,7 @@ const reduxConfig: ReduxConfig = {
HistoryTypeReadAllReducer,
SensorRegistSensorConfigReducer,
NotificationReadAllUnconfirmedReducer,
NotificationReadAllReducer,
],
sagaWatchers: [
AsyncRequest,

View File

@ -14,6 +14,8 @@ import ProbeSetup from '../../views/monitoring/probe/Setup';
import HistoryList from '../../views/history/List';
import TitleBarContainer from '@overflow/app/views/layout/TitleBarContainer';
import SensorSetup from '../../views/monitoring/sensor/Setup';
import NotificationList from '../../views/notification/Notification';
export interface Props extends RouteComponentProps<any> {
}
@ -47,6 +49,7 @@ export class AppLayout extends React.Component<Props, State> {
<Route exact={true} path={`${this.props.match.url}histories`} component={HistoryList}/>
<Route exact={true} path={`${this.props.match.url}sensor_setup`} component={SensorSetup}/>
<Route exact={true} path={`${this.props.match.url}sensor_setup/:id`} component={SensorSetup}/>
<Route exact={true} path={`${this.props.match.url}notifications`} component={NotificationList}/>
<Redirect to='/error/404' />
</Switch>
</Segment>

View File

@ -5,6 +5,8 @@ import {
Container,
Popup,
Image,
Label,
Button,
} from 'semantic-ui-react';
import Notification from '@overflow/notification/react/Notification';
@ -21,11 +23,16 @@ export class LogoBar extends React.Component<any, any> {
alert('handleLogoClick');
}
public handleNotiClick = () => {
alert('handleNotiClick');
}
public render(): JSX.Element {
let icon =
<Button
color='red'
content='Notifications'
icon='bell'
floated='right'
label={{ basic: true, color: 'red', pointing: 'left', content: '3' }}
/>;
return (
<Container fluid style={{ background: '#f8f8f8', 'paddingRight': '7px' }}>
<Menu borderless secondary >
@ -33,11 +40,7 @@ export class LogoBar extends React.Component<any, any> {
{/*<Image src='../asset/image/overFlow_CI_blue_180.png'
style={{width:'120px'}} onClick={this.handleLogoClick} /> */}
</Menu.Item>
<Popup trigger={<Menu.Item
position='right'
icon='bell'
/>}
on='click' wide >
<Popup trigger={icon} on='click' wide >
<Notification />
</Popup>

View File

@ -0,0 +1,21 @@
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import NotificationListContainer from '@overflow/notification/react/NotificationList';
class NotificationList extends React.Component<RouteComponentProps<object>, object> {
public constructor(props?: RouteComponentProps<object>, context?: object) {
super(props, context);
}
public render(): JSX.Element {
return (
<div>
<NotificationListContainer params={this.props.match.url}/>
</div>
);
}
}
export default NotificationList;

View File

@ -1,8 +1,8 @@
interface PageParams {
pageNo: string;
countPerPage: string;
sortCol: string;
sortDirection: string;
sortCol?: string;
sortDirection?: string;
}
export default PageParams;

View File

@ -8,8 +8,9 @@ import { push as routerPush } from 'react-router-redux';
import * as asyncRequestActions from '@overflow/commons/redux/action/asyncRequest';
import Member from '@overflow/member/api/model/Member';
import * as readAllUnconfirmedActions from '../redux/action/read_all_unconfirmed';
import PageParams from '@overflow/commons/api/model/PageParams';
export function mapStateToProps(state: any, props: StateProps): StateProps {
export function mapStateToProps(state: any, props: any): StateProps {
return {
notifications: state.notifications,
};
@ -17,9 +18,12 @@ export function mapStateToProps(state: any, props: StateProps): StateProps {
export function mapDispatchToProps(dispatch: Dispatch<any>): DispatchProps {
return {
onReadAllUnconfirmed: (member: Member, pageNo: string, countPerPage: string) => {
onReadTop5Unconfirmed: (member: Member, pageParams: PageParams) => {
dispatch(asyncRequestActions.request('NotificationService', 'readAllUnconfirmedByMember',
readAllUnconfirmedActions.REQUEST, JSON.stringify(member), pageNo, countPerPage));
readAllUnconfirmedActions.REQUEST, JSON.stringify(member), JSON.stringify(pageParams)));
},
onRedirectAllNotifications: () => {
dispatch(routerPush('/notifications/'));
},
};
}

View File

@ -0,0 +1,29 @@
import { connect, Dispatch } from 'react-redux';
import {
NotificationList,
StateProps as StateProps,
DispatchProps as DispatchProps,
} from './components/NotificationList';
import { push as routerPush } from 'react-router-redux';
import * as asyncRequestActions from '@overflow/commons/redux/action/asyncRequest';
import Member from '@overflow/member/api/model/Member';
import * as readAllActions from '../redux/action/read_all';
import PageParams from '@overflow/commons/api/model/PageParams';
export function mapStateToProps(state: any, props: any): StateProps {
return {
notiPage: state.allNotifications,
};
}
export function mapDispatchToProps(dispatch: Dispatch<any>): DispatchProps {
return {
onReadAll: (member: Member, pageParams: PageParams) => {
dispatch(asyncRequestActions.request('NotificationService', 'readAllByMember',
readAllActions.REQUEST, JSON.stringify(member), JSON.stringify(pageParams)));
},
};
}
export default connect(mapStateToProps, mapDispatchToProps)(NotificationList);

View File

@ -7,18 +7,21 @@ import {
import Page from '@overflow/commons/api/model/Page';
import Member from '@overflow/member/api/model/Member';
import Notification from '../../api/model/Notification';
import PageParams from '@overflow/commons/api/model/PageParams';
export interface StateProps {
notifications: Page;
}
export interface DispatchProps {
onReadAllUnconfirmed(member: Member, pageNo: string, countPerPage: string): void;
onReadTop5Unconfirmed(member: Member, pageParams: PageParams): void;
onRedirectAllNotifications(): void;
}
export type Props = StateProps & DispatchProps;
export interface State {
show: boolean;
}
export class NotificationModal extends React.Component<Props, State> {
@ -27,14 +30,20 @@ export class NotificationModal extends React.Component<Props, State> {
constructor(props: Props, context: State) {
super(props, context);
this.state = {
list: null,
show: true,
};
}
public componentWillMount(): void {
const member = {
const member: Member = {
id: 1,
};
this.props.onReadAllUnconfirmed(member, String(0), String(this.countPerPage));
const pageParams: PageParams = {
sortCol: 'id',
sortDirection: 'descending',
countPerPage: String(this.countPerPage),
pageNo: String(0),
};
this.props.onReadTop5Unconfirmed(member, pageParams);
}
public renderItems(): (JSX.Element | JSX.Element[]) {
@ -43,24 +52,39 @@ export class NotificationModal extends React.Component<Props, State> {
}
return this.props.notifications.content.map((item: Notification, index: number) => (
<List.Item key={index}>
<List.Icon name='bell outline' size='large' verticalAlign='middle' />
<List.Icon name='bell outline' size='large' verticalAlign='middle' />
<List.Content>
<List.Header as='a'>{item.title}</List.Header>
<List.Description as='a'>{item.message}</List.Description>
<List.Header >{item.title}</List.Header>
<List.Description >{item.message}</List.Description>
</List.Content>
</List.Item>
));
}
public render(): JSX.Element {
if(!this.state.show) {
return null;
}
return (
<Container fluid>
<Header as='h4' content='User Notifications' />
<List divided relaxed>
{this.renderItems()}
<List.Item onClick={this.handleViewAll}>
<List.Content>
<List.Description as='a'><b>View All</b></List.Description>
</List.Content>
</List.Item>
</List>
</Container>
);
}
private handleViewAll = (): void => {
this.setState({
show: false,
});
this.props.onRedirectAllNotifications();
}
}

View File

@ -0,0 +1,110 @@
import * as React from 'react';
import {
Container,
Table,
} from 'semantic-ui-react';
import Page from '@overflow/commons/api/model/Page';
import Member from '@overflow/member/api/model/Member';
import Notification from '../../api/model/Notification';
import { SortTableHeaderRow } from '@overflow/commons/react/component/SortTableHeaderRow';
import { Pager } from '@overflow/commons/react/component/Pager';
import PageParams from '@overflow/commons/api/model/PageParams';
export interface StateProps {
notiPage: Page;
}
export interface DispatchProps {
onReadAll(member: Member, pageParams: PageParams): void;
}
export type Props = StateProps & DispatchProps;
export interface State {
}
export class NotificationList extends React.Component<Props, State> {
private countPerPage: number = 10;
private sortCol: string = 'id';
private sortDirection: string = 'descending';
private pageNo: number = 0;
constructor(props: Props, context: State) {
super(props, context);
this.state = {
};
}
public componentWillMount(): void {
this.getData();
}
private getData(): void {
const member = {
id: 1,
};
const pageParams: PageParams = {
sortCol: 'id',
sortDirection: 'descending',
countPerPage: String(this.countPerPage),
pageNo: String(this.pageNo),
};
this.props.onReadAll(member, pageParams);
}
public renderItems(): (JSX.Element | JSX.Element[]) {
if (this.props.notiPage === undefined || this.props.notiPage.content.length === 0) {
return <div>No user notifications found. </div>;
}
return this.props.notiPage.content.map((noti: Notification, index: number) => (
<Table.Row key={index}>
<Table.Cell textAlign={'center'}>{noti.id}</Table.Cell>
<Table.Cell textAlign={'center'}>{noti.createDate}</Table.Cell>
<Table.Cell textAlign={'center'}>{noti.title}</Table.Cell>
<Table.Cell textAlign={'center'}>{noti.message}</Table.Cell>
</Table.Row>
));
}
public render(): JSX.Element {
let colsmap: Map<string, string> = new Map();
colsmap.set('No.', 'id');
colsmap.set('Created At', 'createDate');
colsmap.set('Title', 'title');
colsmap.set('Message', 'message');
return (
<Container fluid>
<Table celled striped sortable>
<Table.Header>
<SortTableHeaderRow columnMap={colsmap} onHeaderColumnClick={this.handleSort} />
</Table.Header>
<Table.Body>
{this.renderItems()}
</Table.Body>
<Table.Footer>
<Table.Row>
<Table.HeaderCell colSpan='4'>
<Pager page={this.props.notiPage} onPageChange={this.handlePaging} />
</Table.HeaderCell>
</Table.Row>
</Table.Footer>
</Table>
</Container>
);
}
private handleSelect = (selected: Notification) => {
console.log('handleSelect');
}
private handleSort = (col: string, direction: string) => {
this.sortCol = col;
this.sortDirection = direction;
this.getData();
}
private handlePaging = (pageNo: number) => {
this.pageNo = pageNo;
this.getData();
}
}

View File

@ -0,0 +1,7 @@
export type REQUEST = '@overflow/notification/read_all/REQUEST';
export type REQUEST_SUCCESS = '@overflow/notification/read_all/REQUEST/SUCCESS';
export type REQUEST_FAILURE = '@overflow/notification/read_all/REQUEST/FAILURE';
export const REQUEST: REQUEST = '@overflow/notification/read_all/REQUEST';
export const REQUEST_SUCCESS: REQUEST_SUCCESS = '@overflow/notification/read_all/REQUEST/SUCCESS';
export const REQUEST_FAILURE: REQUEST_FAILURE = '@overflow/notification/read_all/REQUEST/FAILURE';

View File

@ -0,0 +1,24 @@
import Action from '@overflow/commons/redux/Action';
import { ReducersMapObject } from 'redux';
import Page from '@overflow/commons/api/model/Page';
import * as ReadAllActionTypes from '../action/read_all';
import ReadAllState, { defaultState as ReadAllDefaultState } from '../state/ReadAll';
const reducer: ReducersMapObject = {
[ReadAllActionTypes.REQUEST_SUCCESS]:
(state: ReadAllState = ReadAllDefaultState, action: Action<Page>):
ReadAllState => {
return {
...state,
allNotifications: <Page>action.payload,
};
},
[ReadAllActionTypes.REQUEST_FAILURE]:
(state: ReadAllState = ReadAllDefaultState, action: Action<Error>):
ReadAllState => {
return state;
},
};
export default reducer;

View File

@ -0,0 +1,13 @@
import Page from '@overflow/commons/api/model/Page';
export interface State {
readonly allNotifications?: Page;
readonly error?: Error;
}
export const defaultState: State = {
allNotifications: undefined,
error: undefined,
};
export default State;