2015-10-08 12:27:09 -04:00
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
2015-07-01 18:40:20 -07:00
// See License.txt for license information.
2015-08-31 11:31:55 -04:00
const UserStore = require ( '../stores/user_store.jsx' ) ;
const Client = require ( '../utils/client.jsx' ) ;
const AsyncClient = require ( '../utils/async_client.jsx' ) ;
2015-10-30 10:45:54 -04:00
const Modal = ReactBootstrap . Modal ;
2015-08-31 11:31:55 -04:00
const LoadingScreen = require ( './loading_screen.jsx' ) ;
const Utils = require ( '../utils/utils.jsx' ) ;
2015-07-01 18:40:20 -07:00
2015-08-31 11:31:55 -04:00
export default class ActivityLogModal extends React . Component {
constructor ( props ) {
super ( props ) ;
this . submitRevoke = this . submitRevoke . bind ( this ) ;
this . onListenerChange = this . onListenerChange . bind ( this ) ;
this . handleMoreInfo = this . handleMoreInfo . bind ( this ) ;
2015-10-05 09:58:42 -04:00
this . onHide = this . onHide . bind ( this ) ;
this . onShow = this . onShow . bind ( this ) ;
2015-07-01 18:40:20 -07:00
2015-10-05 09:58:42 -04:00
let state = this . getStateFromStores ( ) ;
state . moreInfo = [ ] ;
this . state = state ;
2015-08-31 11:31:55 -04:00
}
getStateFromStores ( ) {
return {
sessions : UserStore . getSessions ( ) ,
serverError : null ,
clientError : null
} ;
}
2015-09-26 17:38:02 -07:00
submitRevoke ( altId , e ) {
e . preventDefault ( ) ;
2015-10-06 21:34:16 +05:00
var modalContent = $ ( e . target ) . closest ( '.modal-content' ) ;
modalContent . addClass ( 'animation--highlight' ) ;
setTimeout ( ( ) => {
modalContent . removeClass ( 'animation--highlight' ) ;
} , 1500 ) ;
2015-07-01 18:40:20 -07:00
Client . revokeSession ( altId ,
2015-08-31 11:31:55 -04:00
function handleRevokeSuccess ( ) {
2015-07-01 18:40:20 -07:00
AsyncClient . getSessions ( ) ;
2015-08-31 11:31:55 -04:00
} ,
function handleRevokeError ( err ) {
let state = this . getStateFromStores ( ) ;
2015-08-14 09:09:39 -07:00
state . serverError = err ;
2015-07-01 18:40:20 -07:00
this . setState ( state ) ;
} . bind ( this )
) ;
2015-08-31 11:31:55 -04:00
}
2015-10-05 09:58:42 -04:00
onShow ( ) {
AsyncClient . getSessions ( ) ;
2015-10-30 10:45:54 -04:00
$ ( ReactDOM . findDOMNode ( this . refs . modalBody ) ) . css ( 'max-height' , $ ( window ) . height ( ) - 300 ) ;
if ( $ ( window ) . width ( ) > 768 ) {
$ ( ReactDOM . findDOMNode ( this . refs . modalBody ) ) . perfectScrollbar ( ) ;
}
2015-10-05 09:58:42 -04:00
}
onHide ( ) {
this . setState ( { moreInfo : [ ] } ) ;
2015-10-30 10:45:54 -04:00
this . props . onModalDismissed ( ) ;
2015-10-05 09:58:42 -04:00
}
2015-08-31 11:31:55 -04:00
componentDidMount ( ) {
2015-08-14 09:09:39 -07:00
UserStore . addSessionsChangeListener ( this . onListenerChange ) ;
2015-10-30 10:45:54 -04:00
}
componentDidUpdate ( prevProps ) {
if ( this . props . show && ! prevProps . show ) {
this . onShow ( ) ;
}
2015-08-31 11:31:55 -04:00
}
componentWillUnmount ( ) {
2015-08-14 09:09:39 -07:00
UserStore . removeSessionsChangeListener ( this . onListenerChange ) ;
2015-08-31 11:31:55 -04:00
}
onListenerChange ( ) {
const newState = this . getStateFromStores ( ) ;
if ( ! Utils . areStatesEqual ( newState . sessions , this . state . sessions ) ) {
2015-07-28 09:28:00 -07:00
this . setState ( newState ) ;
}
2015-08-31 11:31:55 -04:00
}
handleMoreInfo ( index ) {
let newMoreInfo = this . state . moreInfo ;
2015-07-01 18:40:20 -07:00
newMoreInfo [ index ] = true ;
2015-08-14 09:09:39 -07:00
this . setState ( { moreInfo : newMoreInfo } ) ;
2015-08-31 11:31:55 -04:00
}
render ( ) {
let activityList = [ ] ;
2015-07-01 18:40:20 -07:00
2015-08-31 11:31:55 -04:00
for ( let i = 0 ; i < this . state . sessions . length ; i ++ ) {
const currentSession = this . state . sessions [ i ] ;
const lastAccessTime = new Date ( currentSession . last _activity _at ) ;
const firstAccessTime = new Date ( currentSession . create _at ) ;
2015-10-16 14:21:46 -07:00
let devicePlatform = currentSession . props . platform ;
2015-08-31 11:31:55 -04:00
let devicePicture = '' ;
2015-07-01 18:40:20 -07:00
2015-08-14 09:09:39 -07:00
if ( currentSession . props . platform === 'Windows' ) {
devicePicture = 'fa fa-windows' ;
2015-08-31 11:31:55 -04:00
} else if ( currentSession . props . platform === 'Macintosh' || currentSession . props . platform === 'iPhone' ) {
2015-08-14 09:09:39 -07:00
devicePicture = 'fa fa-apple' ;
2015-08-31 11:31:55 -04:00
} else if ( currentSession . props . platform === 'Linux' ) {
2015-10-16 14:21:46 -07:00
if ( currentSession . props . os . indexOf ( 'Android' ) >= 0 ) {
devicePlatform = 'Android' ;
devicePicture = 'fa fa-android' ;
} else {
devicePicture = 'fa fa-linux' ;
}
2015-08-14 09:09:39 -07:00
}
2015-08-31 11:31:55 -04:00
let moreInfo ;
2015-08-14 09:09:39 -07:00
if ( this . state . moreInfo [ i ] ) {
moreInfo = (
< div >
2015-08-31 11:31:55 -04:00
< div > { ` First time active: ${ firstAccessTime . toDateString ( ) } , ${ lastAccessTime . toLocaleTimeString ( ) } ` } < / div >
< div > { ` OS: ${ currentSession . props . os } ` } < / div >
< div > { ` Browser: ${ currentSession . props . browser } ` } < / div >
2015-09-26 17:38:02 -07:00
< div > { ` Session ID: ${ currentSession . id } ` } < / div >
2015-08-14 09:09:39 -07:00
< / div >
) ;
} else {
2015-08-31 11:31:55 -04:00
moreInfo = (
< a
className = 'theme'
href = '#'
onClick = { this . handleMoreInfo . bind ( this , i ) }
>
More info
< / a >
) ;
2015-07-23 00:54:40 +05:00
}
2015-07-01 18:40:20 -07:00
activityList [ i ] = (
2015-09-02 13:00:35 -07:00
< div
key = { 'activityLogEntryKey' + i }
className = 'activity-log__table'
>
2015-08-14 09:09:39 -07:00
< div className = 'activity-log__report' >
2015-10-16 14:21:46 -07:00
< div className = 'report__platform' > < i className = { devicePicture } / > { devicePlatform } < / div >
2015-08-14 09:09:39 -07:00
< div className = 'report__info' >
2015-08-31 11:31:55 -04:00
< div > { ` Last activity: ${ lastAccessTime . toDateString ( ) } , ${ lastAccessTime . toLocaleTimeString ( ) } ` } < / div >
2015-08-14 09:09:39 -07:00
{ moreInfo }
2015-07-01 18:40:20 -07:00
< / div >
< / div >
2015-08-31 11:31:55 -04:00
< div className = 'activity-log__action' >
< button
2015-09-26 17:38:02 -07:00
onClick = { this . submitRevoke . bind ( this , currentSession . id ) }
2015-08-31 11:31:55 -04:00
className = 'btn btn-primary'
>
Logout
< / button >
< / div >
2015-07-01 18:40:20 -07:00
< / div >
) ;
}
2015-08-31 11:31:55 -04:00
let content ;
2015-08-14 09:09:39 -07:00
if ( this . state . sessions . loading ) {
2015-08-31 11:31:55 -04:00
content = < LoadingScreen / > ;
2015-08-14 09:09:39 -07:00
} else {
2015-08-31 11:31:55 -04:00
content = < form role = 'form' > { activityList } < / form > ;
2015-08-14 09:09:39 -07:00
}
2015-07-01 18:40:20 -07:00
return (
2015-10-30 10:45:54 -04:00
< Modal
show = { this . props . show }
onHide = { this . onHide }
bsSize = 'large'
>
< Modal.Header closeButton = { true } >
< Modal.Title > { 'Active Sessions' } < / Modal.Title >
< / Modal.Header >
< Modal.Body ref = 'modalBody' >
2015-11-05 11:06:47 +05:00
< p className = 'session-help-text' > { 'Sessions are created when you log in with your email and password to a new browser on a device. Sessions let you use Mattermost for up to 30 days without having to log in again. If you want to log out sooner, use the \'Logout\' button below to end a session.' } < / p >
2015-10-30 10:45:54 -04:00
{ content }
< / Modal.Body >
< / Modal >
2015-07-01 18:40:20 -07:00
) ;
}
2015-08-31 11:31:55 -04:00
}
2015-10-30 10:45:54 -04:00
ActivityLogModal . propTypes = {
show : React . PropTypes . bool . isRequired ,
onModalDismissed : React . PropTypes . func . isRequired
} ;