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.
2016-03-14 08:50:46 -04:00
import $ from 'jquery' ;
import UserStore from 'stores/user_store.jsx' ;
2016-04-21 22:37:01 -07:00
import Client from 'utils/web_client.jsx' ;
2016-03-14 08:50:46 -04:00
import * as AsyncClient from 'utils/async_client.jsx' ;
import { Modal } from 'react-bootstrap' ;
2015-11-19 21:12:56 -05:00
import LoadingScreen from './loading_screen.jsx' ;
2016-03-14 08:50:46 -04:00
import * as Utils from 'utils/utils.jsx' ;
2015-07-01 18:40:20 -07:00
2016-03-14 08:50:46 -04:00
import { FormattedMessage , FormattedTime , FormattedDate } from 'react-intl' ;
import React from 'react' ;
2016-01-30 18:10:04 -03: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
2016-05-12 07:50:53 -04:00
const state = this . getStateFromStores ( ) ;
2015-10-05 09:58:42 -04:00
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 ,
2016-05-12 07:50:53 -04:00
( ) => {
2015-07-01 18:40:20 -07:00
AsyncClient . getSessions ( ) ;
2015-08-31 11:31:55 -04:00
} ,
2016-05-12 07:50:53 -04:00
( err ) => {
const 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 ) ;
2016-05-12 07:50:53 -04:00
}
2015-07-01 18:40:20 -07:00
) ;
2015-08-31 11:31:55 -04:00
}
2015-10-05 09:58:42 -04:00
onShow ( ) {
AsyncClient . getSessions ( ) ;
2016-03-23 04:06:08 +05:00
if ( ! Utils . isMobile ( ) ) {
$ ( '.modal-body' ) . perfectScrollbar ( ) ;
2015-10-30 10:45:54 -04:00
}
2015-10-05 09:58:42 -04:00
}
onHide ( ) {
this . setState ( { moreInfo : [ ] } ) ;
2015-11-10 11:54:43 -05:00
this . props . onHide ( ) ;
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-11-17 16:10:16 -05:00
if ( this . props . show ) {
this . onShow ( ) ;
}
}
componentDidUpdate ( prevProps ) {
if ( this . props . show && ! prevProps . show ) {
this . onShow ( ) ;
}
2015-10-30 10:45:54 -04:00
}
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 ( ) ;
2015-11-12 11:19:59 -05:00
if ( ! Utils . areObjectsEqual ( 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 ) {
2016-05-12 07:50:53 -04:00
const 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' ;
2016-01-27 10:07:26 -05:00
} else if ( currentSession . device _id && currentSession . device _id . indexOf ( 'apple:' ) === 0 ) {
2016-01-26 21:04:29 -05:00
devicePicture = 'fa fa-apple' ;
2016-01-30 18:10:04 -03:00
devicePlatform = (
< FormattedMessage
id = 'activity_log_modal.iphoneNativeApp'
defaultMessage = 'iPhone Native App'
/ >
) ;
2016-01-27 10:07:26 -05:00
} else if ( currentSession . device _id && currentSession . device _id . indexOf ( 'android:' ) === 0 ) {
2016-01-30 18:10:04 -03:00
devicePlatform = (
< FormattedMessage
id = 'activity_log_modal.androidNativeApp'
defaultMessage = 'Android Native App'
/ >
) ;
2016-01-26 21:04:29 -05:00
devicePicture = 'fa fa-android' ;
2016-01-24 23:49:01 -05: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 ) {
2016-01-30 18:10:04 -03:00
devicePlatform = (
< FormattedMessage
id = 'activity_log_modal.android'
defaultMessage = 'Android'
/ >
) ;
2015-10-16 14:21:46 -07:00
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 >
2016-01-30 18:10:04 -03:00
< div >
< FormattedMessage
id = 'activity_log.firstTime'
defaultMessage = 'First time active: {date}, {time}'
values = { {
2016-02-08 07:26:10 -05:00
date : (
< FormattedDate
value = { firstAccessTime }
day = '2-digit'
month = 'long'
year = 'numeric'
/ >
) ,
time : (
< FormattedTime
value = { firstAccessTime }
hour = '2-digit'
minute = '2-digit'
/ >
)
2016-01-30 18:10:04 -03:00
} }
/ >
< / div >
< div >
< FormattedMessage
id = 'activity_log.os'
defaultMessage = 'OS: {os}'
values = { {
os : currentSession . props . os
} }
/ >
< / div >
< div >
< FormattedMessage
id = 'activity_log.browser'
defaultMessage = 'Browser: {browser}'
values = { {
browser : currentSession . props . browser
} }
/ >
< / div >
< div >
< FormattedMessage
id = 'activity_log.sessionId'
defaultMessage = 'Session ID: {id}'
values = { {
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 ) }
>
2016-01-30 18:10:04 -03:00
< FormattedMessage
id = 'activity_log.moreInfo'
defaultMessage = 'More info'
/ >
2015-08-31 11:31:55 -04:00
< / 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' >
2016-02-22 08:31:10 -05:00
< div className = 'report__platform' > < i className = { devicePicture } / > { devicePlatform } < / div >
2015-08-14 09:09:39 -07:00
< div className = 'report__info' >
2016-01-30 18:10:04 -03:00
< div >
< FormattedMessage
id = 'activity_log.lastActivity'
defaultMessage = 'Last activity: {date}, {time}'
values = { {
2016-02-08 07:26:10 -05:00
date : (
< FormattedDate
value = { lastAccessTime }
day = '2-digit'
month = 'long'
year = 'numeric'
/ >
) ,
time : (
< FormattedTime
value = { lastAccessTime }
hour = '2-digit'
minute = '2-digit'
/ >
)
2016-01-30 18:10:04 -03:00
} }
/ >
< / 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'
>
2016-01-30 18:10:04 -03:00
< FormattedMessage
id = 'activity_log.logout'
defaultMessage = 'Logout'
/ >
2015-08-31 11:31:55 -04:00
< / 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 ) {
2016-02-22 08:31:10 -05: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 } >
2016-01-30 18:10:04 -03:00
< Modal.Title >
< FormattedMessage
id = 'activity_log.activeSessions'
defaultMessage = 'Active Sessions'
/ >
< / Modal.Title >
2015-10-30 10:45:54 -04:00
< / Modal.Header >
< Modal.Body ref = 'modalBody' >
2016-01-30 18:10:04 -03:00
< p className = 'session-help-text' >
< FormattedMessage
id = 'activity_log.sessionsDescription'
2016-02-24 12:09:36 -08:00
defaultMessage = "Sessions are created when you log in to a new browser on a device. Sessions let you use Mattermost without having to log in again for a time period specified by the System Admin. If you want to log out sooner, use the 'Logout' button below to end a session."
2016-01-30 18:10:04 -03:00
/ >
< / 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 ,
2015-11-10 11:54:43 -05:00
onHide : React . PropTypes . func . isRequired
2015-10-30 10:45:54 -04:00
} ;