2016-06-23 19:26:01 +03:00
/* global Handlebars, moment */
2016-05-18 13:03:22 +03:00
/ * *
* @ author Christoph Wurst < christoph @ owncloud . com >
*
* @ copyright Copyright ( c ) 2016 , ownCloud , Inc .
* @ license AGPL - 3.0
*
* This code is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License , version 3 ,
* as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License , version 3 ,
* along with this program . If not , see < http : //www.gnu.org/licenses/>
*
* /
2016-07-18 20:39:03 +03:00
( function ( OC , _ , $ , Handlebars , moment ) {
2016-05-18 13:03:22 +03:00
'use strict' ;
OC . Settings = OC . Settings || { } ;
var TEMPLATE _TOKEN =
2016-05-19 12:20:22 +03:00
'<tr data-id="{{id}}">'
2016-08-03 16:57:06 +03:00
+ '<td class="has-tooltip" title="{{title}}">'
+ '<span class="token-name">{{name}}</span>'
+ '</td>'
2016-06-17 16:11:31 +03:00
+ '<td><span class="last-activity has-tooltip" title="{{lastActivityTime}}">{{lastActivity}}</span></td>'
2016-11-14 20:19:27 +03:00
+ '<td class="more">'
+ '{{#if showMore}}<a class="icon icon-more"/>{{/if}}'
+ '<div class="popovermenu bubble open menu configure">'
2016-08-03 13:03:18 +03:00
+ '{{#if canScope}}'
2016-11-14 20:19:27 +03:00
+ '<input class="filesystem checkbox" type="checkbox" id="{{id}}_filesystem" {{#if scope.filesystem}}checked{{/if}}/>'
+ '<label for="{{id}}_filesystem">' + t ( 'core' , 'Allow filesystem access' ) + '</label><br/>'
2016-08-03 13:03:18 +03:00
+ '{{/if}}'
2016-06-27 16:23:52 +03:00
+ '{{#if canDelete}}'
2016-11-14 20:19:27 +03:00
+ '<a class="icon icon-delete has-tooltip" title="' + t ( 'core' , 'Disconnect' ) + '">' + t ( 'core' , 'Revoke' ) + '</a>'
2016-06-27 16:23:52 +03:00
+ '{{/if}}'
2016-11-14 20:19:27 +03:00
+ '</div>'
2016-08-03 13:03:18 +03:00
+ '</td>'
2016-05-18 19:25:05 +03:00
+ '<tr>' ;
2016-05-18 13:03:22 +03:00
2016-06-23 19:26:01 +03:00
var SubView = OC . Backbone . View . extend ( {
2016-05-18 13:03:22 +03:00
collection : null ,
2016-05-19 12:20:22 +03:00
/ * *
* token type
* - 0 : browser
* - 1 : device
*
* @ see OC \ Authentication \ Token \ IToken
* /
2016-05-18 13:03:22 +03:00
type : 0 ,
2016-05-19 12:20:22 +03:00
_template : undefined ,
2016-07-18 20:39:03 +03:00
template : function ( data ) {
2016-05-19 12:20:22 +03:00
if ( _ . isUndefined ( this . _template ) ) {
this . _template = Handlebars . compile ( TEMPLATE _TOKEN ) ;
}
return this . _template ( data ) ;
} ,
2016-07-18 20:39:03 +03:00
initialize : function ( options ) {
2016-05-18 13:03:22 +03:00
this . type = options . type ;
this . collection = options . collection ;
2016-05-19 12:20:22 +03:00
this . on ( this . collection , 'change' , this . render ) ;
2016-05-18 13:03:22 +03:00
} ,
2016-05-19 12:20:22 +03:00
2016-07-18 20:39:03 +03:00
render : function ( ) {
2016-05-18 13:03:22 +03:00
var _this = this ;
2016-05-19 12:20:22 +03:00
var list = this . $ ( '.token-list' ) ;
2016-07-18 20:39:03 +03:00
var tokens = this . collection . filter ( function ( token ) {
2016-08-03 17:24:12 +03:00
return token . get ( 'type' ) === _this . type ;
2016-05-18 13:03:22 +03:00
} ) ;
list . html ( '' ) ;
2016-05-19 12:20:22 +03:00
// Show header only if there are tokens to show
this . _toggleHeader ( tokens . length > 0 ) ;
2016-07-18 20:39:03 +03:00
tokens . forEach ( function ( token ) {
2016-08-03 13:03:18 +03:00
var viewData = this . _formatViewData ( token ) ;
2016-05-18 19:25:05 +03:00
var html = _this . template ( viewData ) ;
2016-05-19 12:20:22 +03:00
var $html = $ ( html ) ;
2016-06-17 16:11:31 +03:00
$html . find ( '.has-tooltip' ) . tooltip ( { container : 'body' } ) ;
2016-05-19 12:20:22 +03:00
list . append ( $html ) ;
2016-07-18 20:39:03 +03:00
} . bind ( this ) ) ;
2016-05-18 13:03:22 +03:00
} ,
2016-05-19 12:20:22 +03:00
2016-07-18 20:39:03 +03:00
toggleLoading : function ( state ) {
2016-05-19 12:20:22 +03:00
this . $ ( '.token-list' ) . toggleClass ( 'icon-loading' , state ) ;
} ,
2016-07-18 20:39:03 +03:00
_toggleHeader : function ( show ) {
2016-05-19 12:20:22 +03:00
this . $ ( '.hidden-when-empty' ) . toggleClass ( 'hidden' , ! show ) ;
2016-07-18 20:39:03 +03:00
} ,
2016-08-03 13:03:18 +03:00
_formatViewData : function ( token ) {
var viewData = token . toJSON ( ) ;
2016-07-18 20:39:03 +03:00
var ts = viewData . lastActivity * 1000 ;
viewData . lastActivity = OC . Util . relativeModifiedDate ( ts ) ;
viewData . lastActivityTime = OC . Util . formatDate ( ts , 'LLL' ) ;
2016-08-03 17:24:12 +03:00
viewData . canScope = token . get ( 'type' ) === 1 ;
2016-11-14 20:19:27 +03:00
viewData . showMore = viewData . canScope || viewData . canDelete ;
2016-07-18 20:39:03 +03:00
// preserve title for cases where we format it further
viewData . title = viewData . name ;
// pretty format sync client user agent
2016-07-18 23:48:13 +03:00
var matches = viewData . name . match ( /Mozilla\/5\.0 \((\w+)\) (?:mirall|csyncoC)\/(\d+\.\d+\.\d+)/ ) ;
var userAgentMap = {
2016-11-14 14:35:23 +03:00
ie : /(?:MSIE|Trident|Trident\/7.0; rv)[ :](\d+)/ ,
2016-07-18 23:48:13 +03:00
// Microsoft Edge User Agent from https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
edge : /^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Chrome\/[0-9.]+ (?:Mobile Safari|Safari)\/[0-9.]+ Edge\/[0-9.]+$/ ,
// Firefox User Agent from https://developer.mozilla.org/en-US/docs/Web/HTTP/Gecko_user_agent_string_reference
firefox : /^Mozilla\/5\.0 \([^)]*(Windows|OS X|Linux)[^)]+\) Gecko\/[0-9.]+ Firefox\/(\d+)(?:\.\d)?$/ ,
// Chrome User Agent from https://developer.chrome.com/multidevice/user-agent
chrome : /^Mozilla\/5\.0 \([^)]*(Windows|OS X|Linux)[^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Chrome\/(\d+)[0-9.]+ (?:Mobile Safari|Safari)\/[0-9.]+$/ ,
// Safari User Agent from http://www.useragentstring.com/pages/Safari/
2016-07-20 15:13:23 +03:00
safari : /^Mozilla\/5\.0 \([^)]*(Windows|OS X)[^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\)(?: Version\/([0-9]+)[0-9.]+)? Safari\/[0-9.A-Z]+$/ ,
2016-07-18 23:48:13 +03:00
// Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent
androidChrome : /Android.*(?:; (.*) Build\/).*Chrome\/(\d+)[0-9.]+/ ,
iphone : / *CPU +iPhone +OS +(\d+)_\d+ +like +Mac +OS +X */ ,
iosClient : /^Mozilla\/5\.0 \(iOS\) ownCloud\-iOS.*$/ ,
androidClient : /^Mozilla\/5\.0 \(Android\) ownCloud\-android.*$/ ,
// DAVdroid/1.2 (2016/07/03; dav4android; okhttp3) Android/6.0.1
2016-07-20 16:49:01 +03:00
davDroid : /DAVdroid\/([0-9.]+)/ ,
// Mozilla/5.0 (U; Linux; Maemo; Jolla; Sailfish; like Android 4.3) AppleWebKit/538.1 (KHTML, like Gecko) WebPirate/2.0 like Mobile Safari/538.1 (compatible)
webPirate : /(Sailfish).*WebPirate\/(\d+)/ ,
// Mozilla/5.0 (Maemo; Linux; U; Jolla; Sailfish; Mobile; rv:31.0) Gecko/31.0 Firefox/31.0 SailfishBrowser/1.0
sailfishBrowser : /(Sailfish).*SailfishBrowser\/(\d+)/
2016-07-18 23:48:13 +03:00
} ;
var nameMap = {
ie : t ( 'setting' , 'Internet Explorer' ) ,
edge : t ( 'setting' , 'Edge' ) ,
firefox : t ( 'setting' , 'Firefox' ) ,
chrome : t ( 'setting' , 'Google Chrome' ) ,
safari : t ( 'setting' , 'Safari' ) ,
androidChrome : t ( 'setting' , 'Google Chrome for Android' ) ,
iphone : t ( 'setting' , 'iPhone' ) ,
iosClient : t ( 'setting' , 'iOS Client' ) ,
androidClient : t ( 'setting' , 'Android Client' ) ,
2016-07-20 16:49:01 +03:00
davDroid : 'DAVdroid' ,
webPirate : 'WebPirate' ,
sailfishBrowser : 'SailfishBrowser'
2016-07-18 23:48:13 +03:00
} ;
2016-07-18 20:39:03 +03:00
if ( matches ) {
2016-07-18 23:48:13 +03:00
viewData . name = t ( 'settings' , 'Sync client - {os}' , {
2016-07-18 20:39:03 +03:00
os : matches [ 1 ] ,
version : matches [ 2 ]
2016-07-18 23:48:13 +03:00
} ) ;
}
for ( var client in userAgentMap ) {
if ( matches = viewData . title . match ( userAgentMap [ client ] ) ) {
if ( matches [ 2 ] && matches [ 1 ] ) { // version number and os
viewData . name = nameMap [ client ] + ' ' + matches [ 2 ] + ' - ' + matches [ 1 ] ;
} else if ( matches [ 1 ] ) { // only version number
viewData . name = nameMap [ client ] + ' ' + matches [ 1 ] ;
} else {
viewData . name = nameMap [ client ] ;
}
}
2016-07-18 20:39:03 +03:00
}
if ( viewData . current ) {
2016-07-18 23:48:13 +03:00
viewData . name = t ( 'settings' , 'This session' ) ;
2016-07-18 20:39:03 +03:00
}
return viewData ;
2016-05-18 19:25:05 +03:00
}
2016-05-18 13:03:22 +03:00
} ) ;
2016-06-23 19:26:01 +03:00
var AuthTokenView = OC . Backbone . View . extend ( {
2016-05-18 13:03:22 +03:00
collection : null ,
2016-05-19 12:20:22 +03:00
2016-05-18 19:25:05 +03:00
_views : [ ] ,
2016-05-19 12:20:22 +03:00
2016-05-18 19:25:05 +03:00
_form : undefined ,
2016-05-19 12:20:22 +03:00
2016-05-18 19:25:05 +03:00
_tokenName : undefined ,
2016-05-19 12:20:22 +03:00
2016-06-16 11:54:03 +03:00
_addAppPasswordBtn : undefined ,
2016-05-19 12:20:22 +03:00
2016-05-18 19:25:05 +03:00
_result : undefined ,
2016-05-19 12:20:22 +03:00
2016-06-24 16:31:48 +03:00
_newAppLoginName : undefined ,
2016-06-16 11:54:03 +03:00
_newAppPassword : undefined ,
2016-05-19 12:20:22 +03:00
2016-08-10 09:58:57 +03:00
_newAppId : undefined ,
2016-06-16 11:54:03 +03:00
_hideAppPasswordBtn : undefined ,
2016-05-19 12:20:22 +03:00
2016-05-18 19:25:05 +03:00
_addingToken : false ,
2016-05-19 12:20:22 +03:00
2016-07-18 20:39:03 +03:00
initialize : function ( options ) {
2016-05-18 13:03:22 +03:00
this . collection = options . collection ;
var tokenTypes = [ 0 , 1 ] ;
var _this = this ;
2016-07-18 20:39:03 +03:00
_ . each ( tokenTypes , function ( type ) {
2016-06-16 11:54:03 +03:00
var el = type === 0 ? '#sessions' : '#apppasswords' ;
2016-05-18 19:25:05 +03:00
_this . _views . push ( new SubView ( {
2016-05-19 12:20:22 +03:00
el : el ,
2016-05-18 13:03:22 +03:00
type : type ,
collection : _this . collection
} ) ) ;
2016-05-19 12:20:22 +03:00
var $el = $ ( el ) ;
$el . on ( 'click' , 'a.icon-delete' , _ . bind ( _this . _onDeleteToken , _this ) ) ;
2016-11-14 20:19:27 +03:00
$el . on ( 'click' , '.icon-more' , _ . bind ( _this . _onConfigureToken , _this ) ) ;
2016-08-03 16:57:06 +03:00
$el . on ( 'change' , 'input.filesystem' , _ . bind ( _this . _onSetTokenScope , _this ) ) ;
2016-05-18 13:03:22 +03:00
} ) ;
2016-05-18 19:25:05 +03:00
2016-06-16 11:54:03 +03:00
this . _form = $ ( '#app-password-form' ) ;
this . _tokenName = $ ( '#app-password-name' ) ;
this . _addAppPasswordBtn = $ ( '#add-app-password' ) ;
this . _addAppPasswordBtn . click ( _ . bind ( this . _addAppPassword , this ) ) ;
2016-05-18 19:25:05 +03:00
2016-06-16 11:54:03 +03:00
this . _result = $ ( '#app-password-result' ) ;
2016-06-24 16:31:48 +03:00
this . _newAppLoginName = $ ( '#new-app-login-name' ) ;
2016-06-24 18:00:59 +03:00
this . _newAppLoginName . on ( 'focus' , _ . bind ( this . _onNewTokenLoginNameFocus , this ) ) ;
2016-06-16 11:54:03 +03:00
this . _newAppPassword = $ ( '#new-app-password' ) ;
this . _newAppPassword . on ( 'focus' , _ . bind ( this . _onNewTokenFocus , this ) ) ;
this . _hideAppPasswordBtn = $ ( '#app-password-hide' ) ;
this . _hideAppPasswordBtn . click ( _ . bind ( this . _hideToken , this ) ) ;
2016-08-10 10:10:39 +03:00
2016-11-16 17:36:44 +03:00
this . _result . find ( '.clipboardButton' ) . tooltip ( { placement : 'bottom' , title : t ( 'core' , 'Copy' ) , trigger : 'hover' } ) ;
2016-08-10 10:10:39 +03:00
// Clipboard!
var clipboard = new Clipboard ( '.clipboardButton' ) ;
clipboard . on ( 'success' , function ( e ) {
var $input = $ ( e . trigger ) ;
2016-11-16 17:36:44 +03:00
$input . tooltip ( 'hide' )
. attr ( 'data-original-title' , t ( 'core' , 'Copied!' ) )
. tooltip ( 'fixTitle' )
. tooltip ( { placement : 'bottom' , trigger : 'manual' } )
. tooltip ( 'show' ) ;
2016-08-10 10:10:39 +03:00
_ . delay ( function ( ) {
2016-11-16 17:36:44 +03:00
$input . tooltip ( 'hide' )
. attr ( 'data-original-title' , t ( 'core' , 'Copy' ) )
. tooltip ( 'fixTitle' ) ;
2016-08-10 10:10:39 +03:00
} , 3000 ) ;
} ) ;
clipboard . on ( 'error' , function ( e ) {
var $input = $ ( e . trigger ) ;
var actionMsg = '' ;
if ( /iPhone|iPad/i . test ( navigator . userAgent ) ) {
actionMsg = t ( 'core' , 'Not supported!' ) ;
} else if ( /Mac/i . test ( navigator . userAgent ) ) {
actionMsg = t ( 'core' , 'Press ⌘-C to copy.' ) ;
} else {
actionMsg = t ( 'core' , 'Press Ctrl-C to copy.' ) ;
}
2016-11-16 17:36:44 +03:00
$input . tooltip ( 'hide' )
. attr ( 'data-original-title' , actionMsg )
. tooltip ( 'fixTitle' )
. tooltip ( { placement : 'bottom' , trigger : 'manual' } )
. tooltip ( 'show' ) ;
2016-08-10 10:10:39 +03:00
_ . delay ( function ( ) {
2016-11-16 17:36:44 +03:00
$input . tooltip ( 'hide' )
. attr ( 'data-original-title' , t ( 'core' , 'Copy' ) )
. tooltip ( 'fixTitle' ) ;
2016-08-10 10:10:39 +03:00
} , 3000 ) ;
} ) ;
2016-05-18 13:03:22 +03:00
} ,
2016-05-19 12:20:22 +03:00
2016-07-18 20:39:03 +03:00
render : function ( ) {
_ . each ( this . _views , function ( view ) {
2016-05-18 13:03:22 +03:00
view . render ( ) ;
2016-05-18 19:25:05 +03:00
view . toggleLoading ( false ) ;
2016-05-18 13:03:22 +03:00
} ) ;
} ,
2016-05-19 12:20:22 +03:00
2016-07-18 20:39:03 +03:00
reload : function ( ) {
2016-05-18 19:25:05 +03:00
var _this = this ;
2016-07-18 20:39:03 +03:00
_ . each ( this . _views , function ( view ) {
2016-05-18 19:25:05 +03:00
view . toggleLoading ( true ) ;
} ) ;
2016-05-18 13:03:22 +03:00
var loadingTokens = this . collection . fetch ( ) ;
2016-07-18 20:39:03 +03:00
$ . when ( loadingTokens ) . done ( function ( ) {
2016-05-18 13:03:22 +03:00
_this . render ( ) ;
} ) ;
2016-07-18 20:39:03 +03:00
$ . when ( loadingTokens ) . fail ( function ( ) {
2016-05-18 19:25:05 +03:00
OC . Notification . showTemporary ( t ( 'core' , 'Error while loading browser sessions and device tokens' ) ) ;
} ) ;
} ,
2016-05-19 12:20:22 +03:00
2016-07-18 20:39:03 +03:00
_addAppPassword : function ( ) {
2016-09-19 18:13:30 +03:00
if ( OC . PasswordConfirmation . requiresPasswordConfirmation ( ) ) {
OC . PasswordConfirmation . requirePasswordConfirmation ( _ . bind ( this . _addAppPassword , this ) ) ;
return ;
}
2016-05-18 19:25:05 +03:00
var _this = this ;
this . _toggleAddingToken ( true ) ;
var deviceName = this . _tokenName . val ( ) ;
var creatingToken = $ . ajax ( OC . generateUrl ( '/settings/personal/authtokens' ) , {
method : 'POST' ,
data : {
name : deviceName
}
} ) ;
2016-07-18 20:39:03 +03:00
$ . when ( creatingToken ) . done ( function ( resp ) {
2016-08-10 09:58:57 +03:00
// We can delete token we add
resp . deviceToken . canDelete = true ;
2016-05-18 19:25:05 +03:00
_this . collection . add ( resp . deviceToken ) ;
_this . render ( ) ;
2016-06-24 18:00:59 +03:00
_this . _newAppLoginName . val ( resp . loginName ) ;
2016-06-16 11:54:03 +03:00
_this . _newAppPassword . val ( resp . token ) ;
2016-08-10 09:58:57 +03:00
_this . _newAppId = resp . deviceToken . id ;
2016-05-18 19:25:05 +03:00
_this . _toggleFormResult ( false ) ;
2016-06-16 11:54:03 +03:00
_this . _newAppPassword . select ( ) ;
2016-05-18 19:25:05 +03:00
_this . _tokenName . val ( '' ) ;
} ) ;
2016-07-18 20:39:03 +03:00
$ . when ( creatingToken ) . fail ( function ( ) {
2016-05-18 19:25:05 +03:00
OC . Notification . showTemporary ( t ( 'core' , 'Error while creating device token' ) ) ;
} ) ;
2016-07-18 20:39:03 +03:00
$ . when ( creatingToken ) . always ( function ( ) {
2016-05-18 19:25:05 +03:00
_this . _toggleAddingToken ( false ) ;
} ) ;
} ,
2016-05-19 12:20:22 +03:00
2016-07-18 20:39:03 +03:00
_onNewTokenLoginNameFocus : function ( ) {
2016-06-24 18:00:59 +03:00
this . _newAppLoginName . select ( ) ;
} ,
2016-07-18 20:39:03 +03:00
_onNewTokenFocus : function ( ) {
2016-06-16 11:54:03 +03:00
this . _newAppPassword . select ( ) ;
2016-05-19 12:20:22 +03:00
} ,
2016-07-18 20:39:03 +03:00
_hideToken : function ( ) {
2016-05-18 19:25:05 +03:00
this . _toggleFormResult ( true ) ;
} ,
2016-05-19 12:20:22 +03:00
2016-07-18 20:39:03 +03:00
_toggleAddingToken : function ( state ) {
2016-05-18 19:25:05 +03:00
this . _addingToken = state ;
2016-06-16 11:54:03 +03:00
this . _addAppPasswordBtn . toggleClass ( 'icon-loading-small' , state ) ;
2016-05-18 19:25:05 +03:00
} ,
2016-05-19 12:20:22 +03:00
2016-08-03 16:57:06 +03:00
_onConfigureToken : function ( event ) {
var $target = $ ( event . target ) ;
var $row = $target . closest ( 'tr' ) ;
$row . toggleClass ( 'active' ) ;
var id = $row . data ( 'id' ) ;
} ,
2016-07-18 20:39:03 +03:00
_onDeleteToken : function ( event ) {
2016-05-19 12:20:22 +03:00
var $target = $ ( event . target ) ;
var $row = $target . closest ( 'tr' ) ;
var id = $row . data ( 'id' ) ;
2016-08-10 09:58:57 +03:00
if ( id === this . _newAppId ) {
this . _toggleFormResult ( true ) ;
}
2016-05-19 12:20:22 +03:00
var token = this . collection . get ( id ) ;
if ( _ . isUndefined ( token ) ) {
// Ignore event
return ;
}
var destroyingToken = token . destroy ( ) ;
2016-06-23 19:30:45 +03:00
$row . find ( '.icon-delete' ) . tooltip ( 'hide' ) ;
2016-05-19 12:20:22 +03:00
var _this = this ;
2016-07-18 20:39:03 +03:00
$ . when ( destroyingToken ) . fail ( function ( ) {
2016-05-19 12:20:22 +03:00
OC . Notification . showTemporary ( t ( 'core' , 'Error while deleting the token' ) ) ;
} ) ;
2016-07-18 20:39:03 +03:00
$ . when ( destroyingToken ) . always ( function ( ) {
2016-05-19 12:20:22 +03:00
_this . render ( ) ;
} ) ;
} ,
2016-08-03 16:57:06 +03:00
_onSetTokenScope : function ( event ) {
var $target = $ ( event . target ) ;
var $row = $target . closest ( 'tr' ) ;
var id = $row . data ( 'id' ) ;
var token = this . collection . get ( id ) ;
if ( _ . isUndefined ( token ) ) {
// Ignore event
return ;
}
var scope = token . get ( 'scope' ) ;
scope . filesystem = $target . is ( ":checked" ) ;
token . set ( 'scope' , scope ) ;
token . save ( ) ;
} ,
2016-07-18 20:39:03 +03:00
_toggleFormResult : function ( showForm ) {
2016-08-10 10:17:14 +03:00
if ( showForm ) {
this . _result . slideUp ( ) ;
this . _form . slideDown ( ) ;
} else {
this . _form . slideUp ( ) ;
this . _result . slideDown ( ) ;
}
2016-05-18 13:03:22 +03:00
}
} ) ;
OC . Settings . AuthTokenView = AuthTokenView ;
2016-06-23 19:26:01 +03:00
} ) ( OC , _ , $ , Handlebars , moment ) ;