2014-08-14 17:48:38 +04:00
/* global Handlebars */
Handlebars . registerHelper ( 'score' , function ( ) {
if ( this . score ) {
2016-10-27 18:41:15 +03:00
var score = Math . round ( this . score * 10 ) ;
2016-03-11 20:41:32 +03:00
var imageName = 'rating/s' + score + '.svg' ;
2015-07-07 18:29:54 +03:00
2014-08-14 17:48:38 +04:00
return new Handlebars . SafeString ( '<img src="' + OC . imagePath ( 'core' , imageName ) + '">' ) ;
}
return new Handlebars . SafeString ( '' ) ;
} ) ;
2015-03-30 16:58:20 +03:00
Handlebars . registerHelper ( 'level' , function ( ) {
if ( typeof this . level !== 'undefined' ) {
if ( this . level === 200 ) {
2015-05-30 14:39:12 +03:00
return new Handlebars . SafeString ( '<span class="official icon-checkmark">' + t ( 'settings' , 'Official' ) + '</span>' ) ;
2015-03-30 16:58:20 +03:00
}
}
} ) ;
2011-08-23 03:40:13 +04:00
2012-08-04 22:12:18 +04:00
OC . Settings = OC . Settings || { } ;
OC . Settings . Apps = OC . Settings . Apps || {
2016-12-15 19:07:07 +03:00
markedOptions : { } ,
2014-08-14 17:48:38 +04:00
setupGroupsSelect : function ( $elements ) {
OC . Settings . setupGroupsSelect ( $elements , {
2014-09-09 20:00:53 +04:00
placeholder : t ( 'core' , 'All' )
} ) ;
} ,
2014-01-17 17:05:39 +04:00
2014-08-14 17:48:38 +04:00
State : {
currentCategory : null ,
2017-04-23 23:10:17 +03:00
currentCategoryElements : null ,
2016-12-05 12:38:38 +03:00
apps : null ,
$updateNotification : null ,
availableUpdates : 0
2014-08-14 17:48:38 +04:00
} ,
loadCategories : function ( ) {
2015-01-16 14:23:02 +03:00
if ( this . _loadCategoriesCall ) {
this . _loadCategoriesCall . abort ( ) ;
}
2014-08-14 17:48:38 +04:00
var categories = [
2017-03-28 23:17:31 +03:00
{ displayName : t ( 'settings' , 'Enabled apps' ) , ident : 'enabled' , id : '0' } ,
{ displayName : t ( 'settings' , 'Disabled apps' ) , ident : 'disabled' , id : '1' } ,
{ displayName : t ( 'settings' , 'Your apps' ) , ident : 'installed' , id : '2' }
2014-08-14 17:48:38 +04:00
] ;
var source = $ ( "#categories-template" ) . html ( ) ;
var template = Handlebars . compile ( source ) ;
var html = template ( categories ) ;
$ ( '#apps-categories' ) . html ( html ) ;
2015-10-20 13:02:08 +03:00
OC . Settings . Apps . loadCategory ( $ ( '#app-navigation' ) . attr ( 'data-category' ) ) ;
2014-08-14 17:48:38 +04:00
2015-01-16 14:23:02 +03:00
this . _loadCategoriesCall = $ . ajax ( OC . generateUrl ( 'settings/apps/categories' ) , {
2014-08-14 17:48:38 +04:00
data : { } ,
type : 'GET' ,
success : function ( jsondata ) {
var html = template ( jsondata ) ;
$ ( '#apps-categories' ) . html ( html ) ;
$ ( '#app-category-' + OC . Settings . Apps . State . currentCategory ) . addClass ( 'active' ) ;
} ,
complete : function ( ) {
$ ( '#app-navigation' ) . removeClass ( 'icon-loading' ) ;
2014-05-26 00:14:46 +04:00
}
2014-08-14 17:48:38 +04:00
} ) ;
2014-01-17 17:05:39 +04:00
2014-08-14 17:48:38 +04:00
} ,
2014-01-17 17:05:39 +04:00
2014-08-14 17:48:38 +04:00
loadCategory : function ( categoryId ) {
if ( OC . Settings . Apps . State . currentCategory === categoryId ) {
return ;
2013-01-21 23:40:23 +04:00
}
2015-01-16 14:23:02 +03:00
if ( this . _loadCategoryCall ) {
this . _loadCategoryCall . abort ( ) ;
}
2017-04-25 00:13:46 +03:00
$ ( '#app-content' ) . addClass ( 'icon-loading' ) ;
2014-08-14 17:48:38 +04:00
$ ( '#apps-list' )
2015-03-24 12:27:00 +03:00
. removeClass ( 'hidden' )
2014-08-14 17:48:38 +04:00
. html ( '' ) ;
2015-03-24 12:27:00 +03:00
$ ( '#apps-list-empty' ) . addClass ( 'hidden' ) ;
2014-08-14 17:48:38 +04:00
$ ( '#app-category-' + OC . Settings . Apps . State . currentCategory ) . removeClass ( 'active' ) ;
$ ( '#app-category-' + categoryId ) . addClass ( 'active' ) ;
OC . Settings . Apps . State . currentCategory = categoryId ;
2016-12-05 12:38:38 +03:00
OC . Settings . Apps . State . availableUpdates = 0 ;
2013-01-21 23:40:23 +04:00
2016-12-05 12:38:38 +03:00
this . _loadCategoryCall = $ . ajax ( OC . generateUrl ( 'settings/apps/list?category={categoryId}' , {
2014-08-14 17:48:38 +04:00
categoryId : categoryId
} ) , {
type : 'GET' ,
2015-03-24 12:27:00 +03:00
success : function ( apps ) {
2017-04-23 23:10:17 +03:00
OC . Settings . Apps . State . currentCategoryElements = apps . apps ;
2015-07-02 18:15:14 +03:00
var appListWithIndex = _ . indexBy ( apps . apps , 'id' ) ;
OC . Settings . Apps . State . apps = appListWithIndex ;
var appList = _ . map ( appListWithIndex , function ( app ) {
2015-05-20 14:43:20 +03:00
// default values for missing fields
return _ . extend ( { level : 0 } , app ) ;
} ) ;
2017-04-23 23:10:17 +03:00
var source ;
if ( categoryId === 'enabled' || categoryId === 'disabled' || categoryId === 'installed' || categoryId === 'app-bundles' ) {
2017-01-21 19:06:26 +03:00
source = $ ( "#app-template-installed" ) . html ( ) ;
$ ( '#apps-list' ) . addClass ( 'installed' ) ;
} else {
source = $ ( "#app-template" ) . html ( ) ;
$ ( '#apps-list' ) . removeClass ( 'installed' ) ;
}
2014-08-14 17:48:38 +04:00
var template = Handlebars . compile ( source ) ;
2015-05-20 14:43:20 +03:00
if ( appList . length ) {
appList . sort ( function ( a , b ) {
2017-01-21 19:10:08 +03:00
if ( a . active !== b . active ) {
return ( a . active ? - 1 : 1 )
} else {
var levelDiff = b . level - a . level ;
if ( levelDiff === 0 ) {
return OC . Util . naturalSortCompare ( a . name , b . name ) ;
}
return levelDiff ;
2015-05-20 14:43:20 +03:00
}
2015-03-30 16:58:20 +03:00
} ) ;
var firstExperimental = false ;
2015-05-20 14:43:20 +03:00
_ . each ( appList , function ( app ) {
2015-03-30 16:58:20 +03:00
if ( app . level === 0 && firstExperimental === false ) {
firstExperimental = true ;
OC . Settings . Apps . renderApp ( app , template , null , true ) ;
} else {
OC . Settings . Apps . renderApp ( app , template , null , false ) ;
}
2016-12-05 12:38:38 +03:00
if ( app . update ) {
var $update = $ ( '#app-' + app . id + ' .update' ) ;
$update . removeClass ( 'hidden' ) ;
$update . val ( t ( 'settings' , 'Update to %s' ) . replace ( /%s/g , app . update ) ) ;
OC . Settings . Apps . State . availableUpdates ++ ;
}
2015-03-24 12:27:00 +03:00
} ) ;
2016-12-05 12:38:38 +03:00
if ( OC . Settings . Apps . State . availableUpdates > 0 ) {
OC . Settings . Apps . State . $updateNotification = OC . Notification . show ( n ( 'settings' , 'You have %n app update pending' , 'You have %n app updates pending' , OC . Settings . Apps . State . availableUpdates ) ) ;
}
2015-03-24 12:27:00 +03:00
} else {
$ ( '#apps-list' ) . addClass ( 'hidden' ) ;
2015-10-20 11:58:07 +03:00
$ ( '#apps-list-empty' ) . removeClass ( 'hidden' ) . find ( 'h2' ) . text ( t ( 'settings' , 'No apps found for your version' ) ) ;
2015-03-24 12:27:00 +03:00
}
2015-03-30 16:58:20 +03:00
2016-07-13 10:59:08 +03:00
$ ( '.enable.needs-download' ) . tooltip ( {
title : t ( 'settings' , 'The app will be downloaded from the app store' ) ,
placement : 'bottom' ,
container : 'body'
} ) ;
2016-04-11 17:48:07 +03:00
2016-07-13 10:59:08 +03:00
$ ( '.app-level .official' ) . tooltip ( {
title : t ( 'settings' , 'Official apps are developed by and within the community. They offer central functionality and are ready for production use.' ) ,
placement : 'bottom' ,
container : 'body'
} ) ;
$ ( '.app-level .approved' ) . tooltip ( {
title : t ( 'settings' , 'Approved apps are developed by trusted developers and have passed a cursory security check. They are actively maintained in an open code repository and their maintainers deem them to be stable for casual to normal use.' ) ,
placement : 'bottom' ,
container : 'body'
} ) ;
$ ( '.app-level .experimental' ) . tooltip ( {
title : t ( 'settings' , 'This app is not checked for security issues and is new or known to be unstable. Install at your own risk.' ) ,
placement : 'bottom' ,
container : 'body'
} ) ;
2014-08-14 17:48:38 +04:00
} ,
complete : function ( ) {
2017-04-25 00:13:46 +03:00
$ ( '#app-content' ) . removeClass ( 'icon-loading' ) ;
2014-08-14 17:48:38 +04:00
}
} ) ;
} ,
2015-03-30 16:58:20 +03:00
renderApp : function ( app , template , selector , firstExperimental ) {
2014-08-14 17:48:38 +04:00
if ( ! template ) {
var source = $ ( "#app-template" ) . html ( ) ;
template = Handlebars . compile ( source ) ;
}
if ( typeof app === 'string' ) {
app = OC . Settings . Apps . State . apps [ app ] ;
2014-05-31 19:50:39 +04:00
}
2015-03-30 16:58:20 +03:00
app . firstExperimental = firstExperimental ;
2014-05-31 19:50:39 +04:00
2016-01-22 13:38:11 +03:00
if ( ! app . preview ) {
2017-04-25 01:20:12 +03:00
app . preview = OC . imagePath ( 'core' , 'places/default-app-icon' ) ;
2016-01-22 13:38:11 +03:00
app . previewAsIcon = true ;
}
2016-09-30 12:15:56 +03:00
if ( _ . isArray ( app . author ) ) {
2016-10-11 11:23:45 +03:00
var authors = [ ] ;
_ . each ( app . author , function ( author ) {
if ( typeof author === 'string' ) {
authors . push ( author ) ;
} else {
authors . push ( author [ '@value' ] ) ;
}
} ) ;
app . author = authors . join ( ', ' ) ;
2016-11-11 16:11:19 +03:00
} else if ( typeof app . author !== 'string' ) {
app . author = app . author [ '@value' ] ;
2016-09-30 12:15:56 +03:00
}
2016-09-30 15:41:19 +03:00
// Parse markdown in app description
2017-01-13 20:46:41 +03:00
app . description = DOMPurify . sanitize (
marked ( app . description . trim ( ) , OC . Settings . Apps . markedOptions ) ,
{
SAFE _FOR _JQUERY : true ,
ALLOWED _TAGS : [
'strong' ,
'p' ,
'a' ,
'ul' ,
2017-01-16 17:00:54 +03:00
'ol' ,
2017-01-13 20:46:41 +03:00
'li' ,
'em' ,
2017-01-16 17:00:54 +03:00
'del' ,
2017-01-13 20:46:41 +03:00
'blockquote'
]
}
) ;
2016-09-30 15:41:19 +03:00
2014-08-14 17:48:38 +04:00
var html = template ( app ) ;
if ( selector ) {
selector . html ( html ) ;
2012-08-05 01:48:09 +04:00
} else {
2014-08-14 17:48:38 +04:00
$ ( '#apps-list' ) . append ( html ) ;
2012-08-05 01:48:09 +04:00
}
2014-08-14 17:48:38 +04:00
var page = $ ( '#app-' + app . id ) ;
2015-10-21 11:50:06 +03:00
// image loading kung-fu (IE doesn't properly scale SVGs, so disable app icons)
if ( app . preview && ! OC . Util . isIE ( ) ) {
2014-08-14 17:48:38 +04:00
var currentImage = new Image ( ) ;
currentImage . src = app . preview ;
2014-04-18 16:29:45 +04:00
2016-08-17 17:04:53 +03:00
currentImage . onload = function ( ) {
2017-04-25 01:20:12 +03:00
/* Trigger color inversion for placeholder image too */
if ( app . previewAsIcon ) {
page . find ( '.app-image' )
. append ( OC . Settings . Apps . imageUrl ( app . preview , false ) )
. removeClass ( 'icon-loading' ) ;
} else {
page . find ( '.app-image' )
. append ( OC . Settings . Apps . imageUrl ( app . preview , app . fromAppStore ) )
. removeClass ( 'icon-loading' ) ;
}
2016-08-17 17:04:53 +03:00
} ;
}
2016-08-11 10:29:57 +03:00
2014-08-14 17:48:38 +04:00
// set group select properly
2014-04-28 15:27:32 +04:00
if ( OC . Settings . Apps . isType ( app , 'filesystem' ) || OC . Settings . Apps . isType ( app , 'prelogin' ) ||
2016-01-14 17:22:36 +03:00
OC . Settings . Apps . isType ( app , 'authentication' ) || OC . Settings . Apps . isType ( app , 'logging' ) ||
OC . Settings . Apps . isType ( app , 'prevent_group_restriction' ) ) {
2014-08-14 17:48:38 +04:00
page . find ( ".groups-enable" ) . hide ( ) ;
2016-04-19 16:13:37 +03:00
page . find ( ".groups-enable__checkbox" ) . prop ( 'checked' , false ) ;
2014-04-28 15:27:32 +04:00
} else {
2015-04-02 16:47:48 +03:00
page . find ( '#group_select' ) . val ( ( app . groups || [ ] ) . join ( '|' ) ) ;
2014-04-28 15:27:32 +04:00
if ( app . active ) {
if ( app . groups . length ) {
2014-08-14 17:48:38 +04:00
OC . Settings . Apps . setupGroupsSelect ( page . find ( '#group_select' ) ) ;
2016-04-19 16:13:37 +03:00
page . find ( ".groups-enable__checkbox" ) . prop ( 'checked' , true ) ;
2014-04-28 15:27:32 +04:00
} else {
2016-04-19 16:13:37 +03:00
page . find ( ".groups-enable__checkbox" ) . prop ( 'checked' , false ) ;
2014-04-28 15:27:32 +04:00
}
2014-08-14 17:48:38 +04:00
page . find ( ".groups-enable" ) . show ( ) ;
2014-04-28 15:27:32 +04:00
} else {
2014-08-14 17:48:38 +04:00
page . find ( ".groups-enable" ) . hide ( ) ;
2014-04-28 15:27:32 +04:00
}
2014-04-18 16:29:45 +04:00
}
2012-08-05 01:48:09 +04:00
} ,
2014-08-14 17:48:38 +04:00
2016-08-11 10:29:57 +03:00
/ * *
* Returns the image for apps listing
2016-08-14 22:19:33 +03:00
* url : the url of the image
* appfromstore : bool to check whether the app is fetched from store or not .
2016-08-11 10:29:57 +03:00
* /
2016-08-14 22:19:33 +03:00
imageUrl : function ( url , appfromstore ) {
2017-01-21 19:06:26 +03:00
var img ;
2016-08-14 22:19:33 +03:00
if ( appfromstore ) {
2017-04-05 23:12:49 +03:00
img = '<svg viewBox="0 0 72 72">' ;
2016-10-31 19:08:11 +03:00
img += '<image x="0" y="0" width="72" height="72" preserveAspectRatio="xMinYMin meet" xlink:href="' + url + '" class="app-icon" /></svg>' ;
2016-08-14 22:19:33 +03:00
} else {
2017-01-21 19:06:26 +03:00
img = '<svg width="32" height="32" viewBox="0 0 32 32">' ;
img += '<image x="0" y="0" width="32" height="32" preserveAspectRatio="xMinYMin meet" filter="url(#invertIcon)" xlink:href="' + url + '?v=' + oc _config . version + '" class="app-icon"></image></svg>' ;
2016-08-14 22:19:33 +03:00
}
2016-08-11 10:29:57 +03:00
return img ;
} ,
2014-08-14 17:48:38 +04:00
isType : function ( app , type ) {
return app . types && app . types . indexOf ( type ) !== - 1 ;
} ,
2015-07-07 18:29:54 +03:00
/ * *
* Checks the server health .
*
* If the promise fails , the server is broken .
*
* @ return { Promise } promise
* /
_checkServerHealth : function ( ) {
return $ . get ( OC . generateUrl ( 'apps/files' ) ) ;
} ,
2017-04-23 23:10:17 +03:00
enableAppBundle : function ( bundleId , active , element , groups ) {
if ( OC . PasswordConfirmation . requiresPasswordConfirmation ( ) ) {
OC . PasswordConfirmation . requirePasswordConfirmation ( _ . bind ( this . enableAppBundle , this , bundleId , active , element , groups ) ) ;
return ;
}
var bundles = OC . Settings . Apps . State . currentCategoryElements ;
bundles . forEach ( function ( bundle ) {
if ( bundle [ 'id' ] === bundleId ) {
OC . Settings . Apps . enableApp ( bundle [ 'apps' ] , active , element , groups ) ;
}
} ) ;
} ,
2014-08-14 17:48:38 +04:00
enableApp : function ( appId , active , element , groups ) {
2016-12-05 17:10:32 +03:00
if ( OC . PasswordConfirmation . requiresPasswordConfirmation ( ) ) {
OC . PasswordConfirmation . requirePasswordConfirmation ( _ . bind ( this . enableApp , this , appId , active , element , groups ) ) ;
return ;
}
2015-07-07 18:29:54 +03:00
var self = this ;
2014-08-14 17:48:38 +04:00
OC . Settings . Apps . hideErrorMessage ( appId ) ;
2014-04-18 16:29:45 +04:00
groups = groups || [ ] ;
2014-08-14 17:48:38 +04:00
var appItem = $ ( 'div#app-' + appId + '' ) ;
2014-04-18 16:29:45 +04:00
if ( active && ! groups . length ) {
2017-02-23 09:02:38 +03:00
element . val ( t ( 'settings' , 'Disabling app …' ) ) ;
2014-08-14 17:48:38 +04:00
$ . post ( OC . filePath ( 'settings' , 'ajax' , 'disableapp.php' ) , { appid : appId } , function ( result ) {
2013-04-17 17:32:03 +04:00
if ( ! result || result . status !== 'success' ) {
2013-08-06 19:19:18 +04:00
if ( result . data && result . data . message ) {
2014-08-14 17:48:38 +04:00
OC . Settings . Apps . showErrorMessage ( appId , result . data . message ) ;
appItem . data ( 'errormsg' , result . data . message ) ;
2013-08-06 19:19:18 +04:00
} else {
2014-08-14 17:48:38 +04:00
OC . Settings . Apps . showErrorMessage ( appId , t ( 'settings' , 'Error while disabling app' ) ) ;
appItem . data ( 'errormsg' , t ( 'settings' , 'Error while disabling app' ) ) ;
2013-08-06 19:19:18 +04:00
}
2013-08-18 15:49:34 +04:00
element . val ( t ( 'settings' , 'Disable' ) ) ;
2014-08-14 17:48:38 +04:00
appItem . addClass ( 'appwarning' ) ;
} else {
2015-09-05 04:24:18 +03:00
OC . Settings . Apps . rebuildNavigation ( ) ;
2014-08-14 17:48:38 +04:00
appItem . data ( 'active' , false ) ;
appItem . data ( 'groups' , '' ) ;
2013-09-20 22:29:15 +04:00
element . data ( 'active' , false ) ;
2014-08-14 17:48:38 +04:00
appItem . removeClass ( 'active' ) ;
2012-08-05 01:48:09 +04:00
element . val ( t ( 'settings' , 'Enable' ) ) ;
2014-08-14 17:48:38 +04:00
element . parent ( ) . find ( ".groups-enable" ) . hide ( ) ;
element . parent ( ) . find ( '#group_select' ) . hide ( ) . val ( null ) ;
OC . Settings . Apps . State . apps [ appId ] . active = false ;
2012-08-05 01:48:09 +04:00
}
} , 'json' ) ;
} else {
2015-07-07 18:29:54 +03:00
// TODO: display message to admin to not refresh the page!
// TODO: lock UI to prevent further operations
2017-02-23 09:02:38 +03:00
element . val ( t ( 'settings' , 'Enabling app …' ) ) ;
2017-04-23 23:10:17 +03:00
var appIdArray = [ ] ;
if ( typeof appId === 'string' ) {
appIdArray = [ appId ] ;
} else {
appIdArray = appId ;
}
$ . post ( OC . filePath ( 'settings' , 'ajax' , 'enableapp.php' ) , { appIds : appIdArray , groups : groups } , function ( result ) {
2013-04-17 17:32:03 +04:00
if ( ! result || result . status !== 'success' ) {
2013-08-06 19:19:18 +04:00
if ( result . data && result . data . message ) {
2014-08-14 17:48:38 +04:00
OC . Settings . Apps . showErrorMessage ( appId , result . data . message ) ;
appItem . data ( 'errormsg' , result . data . message ) ;
2013-08-06 19:19:18 +04:00
} else {
2014-08-14 17:48:38 +04:00
OC . Settings . Apps . showErrorMessage ( appId , t ( 'settings' , 'Error while enabling app' ) ) ;
appItem . data ( 'errormsg' , t ( 'settings' , 'Error while disabling app' ) ) ;
2013-08-06 19:19:18 +04:00
}
element . val ( t ( 'settings' , 'Enable' ) ) ;
2014-08-14 17:48:38 +04:00
appItem . addClass ( 'appwarning' ) ;
2013-08-06 19:19:18 +04:00
} else {
2015-07-07 18:29:54 +03:00
self . _checkServerHealth ( ) . done ( function ( ) {
if ( result . data . update _required ) {
OC . Settings . Apps . showReloadMessage ( ) ;
2015-10-02 13:15:07 +03:00
2015-07-07 18:29:54 +03:00
setTimeout ( function ( ) {
location . reload ( ) ;
} , 5000 ) ;
}
2015-10-02 13:15:07 +03:00
2015-07-07 18:29:54 +03:00
OC . Settings . Apps . rebuildNavigation ( ) ;
appItem . data ( 'active' , true ) ;
element . data ( 'active' , true ) ;
appItem . addClass ( 'active' ) ;
element . val ( t ( 'settings' , 'Disable' ) ) ;
var app = OC . Settings . Apps . State . apps [ appId ] ;
app . active = true ;
2014-08-14 17:48:38 +04:00
2015-07-07 18:29:54 +03:00
if ( OC . Settings . Apps . isType ( app , 'filesystem' ) || OC . Settings . Apps . isType ( app , 'prelogin' ) ||
OC . Settings . Apps . isType ( app , 'authentication' ) || OC . Settings . Apps . isType ( app , 'logging' ) ) {
2016-04-19 16:13:37 +03:00
element . parent ( ) . find ( ".groups-enable" ) . prop ( 'checked' , true ) ;
2015-07-07 18:29:54 +03:00
element . parent ( ) . find ( ".groups-enable" ) . hide ( ) ;
element . parent ( ) . find ( '#group_select' ) . hide ( ) . val ( null ) ;
2014-05-06 14:41:06 +04:00
} else {
2015-07-07 18:29:54 +03:00
element . parent ( ) . find ( "#groups-enable" ) . show ( ) ;
if ( groups ) {
appItem . data ( 'groups' , JSON . stringify ( groups ) ) ;
} else {
appItem . data ( 'groups' , '' ) ;
}
2014-05-06 14:41:06 +04:00
}
2015-07-07 18:29:54 +03:00
} ) . fail ( function ( ) {
// server borked, emergency disable app
$ . post ( OC . webroot + '/index.php/disableapp' , { appid : appId } , function ( ) {
OC . Settings . Apps . showErrorMessage (
appId ,
t ( 'settings' , 'Error: this app cannot be enabled because it makes the server unstable' )
) ;
appItem . data ( 'errormsg' , t ( 'settings' , 'Error while enabling app' ) ) ;
element . val ( t ( 'settings' , 'Enable' ) ) ;
appItem . addClass ( 'appwarning' ) ;
} ) . fail ( function ( ) {
OC . Settings . Apps . showErrorMessage (
appId ,
t ( 'settings' , 'Error: could not disable broken app' )
) ;
appItem . data ( 'errormsg' , t ( 'settings' , 'Error while disabling broken app' ) ) ;
element . val ( t ( 'settings' , 'Enable' ) ) ;
} ) ;
} ) ;
2012-08-05 01:48:09 +04:00
}
2013-03-23 15:19:43 +04:00
} , 'json' )
2014-08-14 17:48:38 +04:00
. fail ( function ( ) {
OC . Settings . Apps . showErrorMessage ( appId , t ( 'settings' , 'Error while enabling app' ) ) ;
appItem . data ( 'errormsg' , t ( 'settings' , 'Error while enabling app' ) ) ;
appItem . data ( 'active' , false ) ;
appItem . addClass ( 'appwarning' ) ;
element . val ( t ( 'settings' , 'Enable' ) ) ;
} ) ;
2012-08-05 01:48:09 +04:00
}
} ,
2014-08-14 17:48:38 +04:00
updateApp : function ( appId , element ) {
var oldButtonText = element . val ( ) ;
2013-02-01 03:51:00 +04:00
element . val ( t ( 'settings' , 'Updating....' ) ) ;
2014-08-14 17:48:38 +04:00
OC . Settings . Apps . hideErrorMessage ( appId ) ;
$ . post ( OC . filePath ( 'settings' , 'ajax' , 'updateapp.php' ) , { appid : appId } , function ( result ) {
2013-04-17 17:32:03 +04:00
if ( ! result || result . status !== 'success' ) {
2015-03-11 11:59:56 +03:00
if ( result . data && result . data . message ) {
OC . Settings . Apps . showErrorMessage ( appId , result . data . message ) ;
} else {
OC . Settings . Apps . showErrorMessage ( appId , t ( 'settings' , 'Error while updating app' ) ) ;
}
2014-08-14 17:48:38 +04:00
element . val ( oldButtonText ) ;
2013-01-21 23:40:23 +04:00
}
else {
element . val ( t ( 'settings' , 'Updated' ) ) ;
element . hide ( ) ;
2016-12-05 12:38:38 +03:00
var $update = $ ( '#app-' + appId + ' .update' ) ;
$update . addClass ( 'hidden' ) ;
var $version = $ ( '#app-' + appId + ' .app-version' ) ;
$version . text ( OC . Settings . Apps . State . apps [ appId ] [ 'update' ] ) ;
if ( OC . Settings . Apps . State . $updateNotification ) {
OC . Notification . hide ( OC . Settings . Apps . State . $updateNotification ) ;
}
OC . Settings . Apps . State . availableUpdates -- ;
if ( OC . Settings . Apps . State . availableUpdates > 0 ) {
OC . Settings . Apps . State . $updateNotification = OC . Notification . show ( n ( 'settings' , 'You have %n app update pending' , 'You have %n app updates pending' , OC . Settings . Apps . State . availableUpdates ) ) ;
}
2013-01-21 23:40:23 +04:00
}
} , 'json' ) ;
} ,
2014-08-14 17:48:38 +04:00
uninstallApp : function ( appId , element ) {
2016-12-05 17:10:32 +03:00
if ( OC . PasswordConfirmation . requiresPasswordConfirmation ( ) ) {
OC . PasswordConfirmation . requirePasswordConfirmation ( _ . bind ( this . uninstallApp , this , appId , element ) ) ;
return ;
}
2014-08-14 17:48:38 +04:00
OC . Settings . Apps . hideErrorMessage ( appId ) ;
2017-03-29 02:41:53 +03:00
element . val ( t ( 'settings' , 'Removing …' ) ) ;
2014-08-14 17:48:38 +04:00
$ . post ( OC . filePath ( 'settings' , 'ajax' , 'uninstallapp.php' ) , { appid : appId } , function ( result ) {
2014-05-31 19:50:39 +04:00
if ( ! result || result . status !== 'success' ) {
2017-03-29 02:41:53 +03:00
OC . Settings . Apps . showErrorMessage ( appId , t ( 'settings' , 'Error while removing app' ) ) ;
element . val ( t ( 'settings' , 'Remove' ) ) ;
2014-05-31 19:50:39 +04:00
} else {
2015-09-05 04:24:18 +03:00
OC . Settings . Apps . rebuildNavigation ( ) ;
2017-01-23 18:29:16 +03:00
element . parents ( '#apps-list > .section' ) . fadeOut ( function ( ) {
this . remove ( ) ;
2014-08-14 17:48:38 +04:00
} ) ;
2014-05-31 19:50:39 +04:00
}
} , 'json' ) ;
} ,
2013-01-21 23:40:23 +04:00
2015-09-05 04:24:18 +03:00
rebuildNavigation : function ( ) {
$ . getJSON ( OC . filePath ( 'settings' , 'ajax' , 'navigationdetect.php' ) ) . done ( function ( response ) {
2017-03-03 15:00:37 +03:00
if ( response . status === 'success' ) {
2017-03-03 17:09:08 +03:00
var addedApps = { } ;
2017-03-03 15:00:37 +03:00
var navEntries = response . nav _entries ;
2015-09-05 04:24:18 +03:00
var container = $ ( '#apps ul' ) ;
2017-03-03 15:00:37 +03:00
// remove disabled apps
for ( var i = 0 ; i < navEntries . length ; i ++ ) {
2012-10-26 22:12:14 +04:00
var entry = navEntries [ i ] ;
2017-03-03 17:09:08 +03:00
if ( container . children ( 'li[data-id="' + entry . id + '"]' ) . length === 0 ) {
addedApps [ entry . id ] = true ;
}
2017-03-03 15:00:37 +03:00
}
container . children ( 'li[data-id]' ) . each ( function ( index , el ) {
2017-03-03 17:09:08 +03:00
var id = $ ( el ) . data ( 'id' ) ;
// remove all apps that are not in the correct order
2017-04-25 18:25:28 +03:00
if ( ! navEntries [ index ] || ( navEntries [ index ] && navEntries [ index ] . id !== $ ( el ) . data ( 'id' ) ) ) {
2017-03-03 15:00:37 +03:00
$ ( el ) . remove ( ) ;
2017-03-03 17:09:08 +03:00
$ ( '#appmenu li[data-id=' + id + ']' ) . remove ( ) ;
2017-03-03 15:00:37 +03:00
}
} ) ;
2012-10-26 22:12:14 +04:00
2017-04-25 18:25:28 +03:00
var previousEntry = { } ;
2017-03-03 15:00:37 +03:00
// add enabled apps to #navigation and #appmenu
for ( var i = 0 ; i < navEntries . length ; i ++ ) {
var entry = navEntries [ i ] ;
if ( container . children ( 'li[data-id="' + entry . id + '"]' ) . length === 0 ) {
var li = $ ( '<li></li>' ) ;
2012-10-26 22:12:14 +04:00
li . attr ( 'data-id' , entry . id ) ;
2017-04-25 18:25:28 +03:00
var img = '<svg width="16" height="16" viewBox="0 0 16 16">' ;
2016-08-01 22:48:06 +03:00
img += '<defs><filter id="invert"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" /></filter></defs>' ;
2017-04-25 18:25:28 +03:00
img += '<image x="0" y="0" width="16" height="16" preserveAspectRatio="xMinYMin meet" filter="url(#invert)" xlink:href="' + entry . icon + '" class="app-icon" /></svg>' ;
2017-03-03 15:00:37 +03:00
var a = $ ( '<a></a>' ) . attr ( 'href' , entry . href ) ;
var filename = $ ( '<span></span>' ) ;
2015-04-23 22:39:59 +03:00
var loading = $ ( '<div class="icon-loading-dark"></div>' ) . css ( 'display' , 'none' ) ;
2013-04-12 16:45:59 +04:00
filename . text ( entry . name ) ;
a . prepend ( filename ) ;
2015-04-23 22:39:59 +03:00
a . prepend ( loading ) ;
2013-02-03 19:02:25 +04:00
a . prepend ( img ) ;
2012-10-26 22:12:14 +04:00
li . append ( a ) ;
2014-02-26 13:34:38 +04:00
2017-03-03 17:09:08 +03:00
$ ( '#navigation li[data-id=' + previousEntry . id + ']' ) . after ( li ) ;
2014-02-26 13:34:38 +04:00
// draw attention to the newly added app entry
// by flashing it twice
2017-03-03 17:09:08 +03:00
if ( addedApps [ entry . id ] ) {
$ ( '#header .menutoggle' )
. animate ( { opacity : 0.5 } )
. animate ( { opacity : 1 } )
. animate ( { opacity : 0.5 } )
. animate ( { opacity : 1 } )
. animate ( { opacity : 0.75 } ) ;
2017-03-03 15:00:37 +03:00
}
2017-03-03 17:09:08 +03:00
}
2017-03-03 15:00:37 +03:00
2017-04-25 18:25:28 +03:00
if ( $ ( '#appmenu' ) . children ( 'li[data-id="' + entry . id + '"]' ) . length === 0 ) {
2017-03-03 15:00:37 +03:00
var li = $ ( '<li></li>' ) ;
li . attr ( 'data-id' , entry . id ) ;
var img = '<img src="' + entry . icon + '" class="app-icon">' ;
var a = $ ( '<a></a>' ) . attr ( 'href' , entry . href ) ;
var filename = $ ( '<span></span>' ) ;
var loading = $ ( '<div class="icon-loading-dark"></div>' ) . css ( 'display' , 'none' ) ;
filename . text ( entry . name ) ;
a . prepend ( filename ) ;
a . prepend ( loading ) ;
a . prepend ( img ) ;
li . append ( a ) ;
2017-03-03 17:09:08 +03:00
$ ( '#appmenu li[data-id=' + previousEntry . id + ']' ) . after ( li ) ;
if ( addedApps [ entry . id ] ) {
li . animate ( { opacity : 0.5 } )
. animate ( { opacity : 1 } )
. animate ( { opacity : 0.5 } )
. animate ( { opacity : 1 } ) ;
}
2012-10-26 22:12:14 +04:00
}
2017-03-03 17:09:08 +03:00
previousEntry = entry ;
2012-10-26 22:12:14 +04:00
}
2015-09-05 04:24:18 +03:00
2017-04-25 18:25:28 +03:00
$ ( window ) . trigger ( 'resize' ) ;
2012-10-26 22:12:14 +04:00
}
} ) ;
2013-08-18 15:49:34 +04:00
} ,
2014-08-14 17:48:38 +04:00
showErrorMessage : function ( appId , message ) {
$ ( 'div#app-' + appId + ' .warning' )
. show ( )
. text ( message ) ;
2014-04-28 15:27:32 +04:00
} ,
2014-08-14 17:48:38 +04:00
hideErrorMessage : function ( appId ) {
$ ( 'div#app-' + appId + ' .warning' )
. hide ( )
. text ( '' ) ;
2015-01-18 16:52:19 +03:00
} ,
2015-10-15 17:15:42 +03:00
showReloadMessage : function ( ) {
2015-10-02 15:12:29 +03:00
OC . dialogs . info (
t (
'settings' ,
2015-10-06 12:34:06 +03:00
'The app has been enabled but needs to be updated. You will be redirected to the update page in 5 seconds.'
2015-10-02 15:12:29 +03:00
) ,
t ( 'settings' , 'App update' ) ,
2015-10-15 17:15:42 +03:00
function ( ) {
2015-10-02 15:12:29 +03:00
window . location . reload ( ) ;
} ,
true
) ;
} ,
2016-10-11 11:35:02 +03:00
/ * *
* Splits the query by spaces and tries to find all substring in the app
* @ param { string } string
* @ param { string } query
* @ returns { boolean }
* /
_search : function ( string , query ) {
var keywords = query . split ( ' ' ) ,
stringLower = string . toLowerCase ( ) ,
found = true ;
_ . each ( keywords , function ( keyword ) {
found = found && stringLower . indexOf ( keyword ) !== - 1 ;
} ) ;
return found ;
} ,
2015-01-18 16:52:19 +03:00
filter : function ( query ) {
2015-10-15 18:00:00 +03:00
var $appList = $ ( '#apps-list' ) ,
$emptyList = $ ( '#apps-list-empty' ) ;
2015-10-20 11:58:07 +03:00
$appList . removeClass ( 'hidden' ) ;
$appList . find ( '.section' ) . removeClass ( 'hidden' ) ;
$emptyList . addClass ( 'hidden' ) ;
2015-10-15 17:31:28 +03:00
if ( query === '' ) {
return ;
}
2015-10-20 11:58:07 +03:00
2015-01-18 16:52:19 +03:00
query = query . toLowerCase ( ) ;
2015-10-15 17:31:28 +03:00
$appList . find ( '.section' ) . addClass ( 'hidden' ) ;
2015-01-18 16:52:19 +03:00
2015-10-15 17:31:28 +03:00
// App Name
2015-01-18 16:52:19 +03:00
var apps = _ . filter ( OC . Settings . Apps . State . apps , function ( app ) {
2016-10-11 11:35:02 +03:00
return OC . Settings . Apps . _search ( app . name , query ) ;
2015-01-18 16:52:19 +03:00
} ) ;
2016-01-07 18:33:25 +03:00
// App ID
apps = apps . concat ( _ . filter ( OC . Settings . Apps . State . apps , function ( app ) {
2016-10-11 11:35:02 +03:00
return OC . Settings . Apps . _search ( app . id , query ) ;
2016-01-07 18:33:25 +03:00
} ) ) ;
2015-10-15 17:31:28 +03:00
// App Description
2015-01-18 16:52:19 +03:00
apps = apps . concat ( _ . filter ( OC . Settings . Apps . State . apps , function ( app ) {
2016-10-11 11:35:02 +03:00
return OC . Settings . Apps . _search ( app . description , query ) ;
2015-01-18 16:52:19 +03:00
} ) ) ;
2015-10-15 17:31:28 +03:00
// Author Name
apps = apps . concat ( _ . filter ( OC . Settings . Apps . State . apps , function ( app ) {
2016-11-11 16:11:19 +03:00
var authors = [ ] ;
2016-09-30 12:15:56 +03:00
if ( _ . isArray ( app . author ) ) {
2016-10-11 11:23:45 +03:00
_ . each ( app . author , function ( author ) {
if ( typeof author === 'string' ) {
authors . push ( author ) ;
} else {
authors . push ( author [ '@value' ] ) ;
if ( ! _ . isUndefined ( author [ '@attributes' ] [ 'homepage' ] ) ) {
authors . push ( author [ '@attributes' ] [ 'homepage' ] ) ;
}
if ( ! _ . isUndefined ( author [ '@attributes' ] [ 'mail' ] ) ) {
authors . push ( author [ '@attributes' ] [ 'mail' ] ) ;
}
}
} ) ;
2016-10-11 11:35:02 +03:00
return OC . Settings . Apps . _search ( authors . join ( ' ' ) , query ) ;
2016-11-11 16:11:19 +03:00
} else if ( typeof app . author !== 'string' ) {
authors . push ( app . author [ '@value' ] ) ;
if ( ! _ . isUndefined ( app . author [ '@attributes' ] [ 'homepage' ] ) ) {
authors . push ( app . author [ '@attributes' ] [ 'homepage' ] ) ;
}
if ( ! _ . isUndefined ( app . author [ '@attributes' ] [ 'mail' ] ) ) {
authors . push ( app . author [ '@attributes' ] [ 'mail' ] ) ;
}
return OC . Settings . Apps . _search ( authors . join ( ' ' ) , query ) ;
2016-09-30 12:15:56 +03:00
}
2016-10-11 11:35:02 +03:00
return OC . Settings . Apps . _search ( app . author , query ) ;
2015-10-15 17:31:28 +03:00
} ) ) ;
// App status
if ( t ( 'settings' , 'Official' ) . toLowerCase ( ) . indexOf ( query ) !== - 1 ) {
apps = apps . concat ( _ . filter ( OC . Settings . Apps . State . apps , function ( app ) {
return app . level === 200 ;
} ) ) ;
}
if ( t ( 'settings' , 'Approved' ) . toLowerCase ( ) . indexOf ( query ) !== - 1 ) {
apps = apps . concat ( _ . filter ( OC . Settings . Apps . State . apps , function ( app ) {
return app . level === 100 ;
} ) ) ;
}
if ( t ( 'settings' , 'Experimental' ) . toLowerCase ( ) . indexOf ( query ) !== - 1 ) {
apps = apps . concat ( _ . filter ( OC . Settings . Apps . State . apps , function ( app ) {
return app . level !== 100 && app . level !== 200 ;
} ) ) ;
}
2015-01-18 16:52:19 +03:00
apps = _ . uniq ( apps , function ( app ) { return app . id ; } ) ;
2015-10-15 18:00:00 +03:00
if ( apps . length === 0 ) {
$appList . addClass ( 'hidden' ) ;
$emptyList . removeClass ( 'hidden' ) ;
2016-03-31 16:26:37 +03:00
$emptyList . removeClass ( 'hidden' ) . find ( 'h2' ) . text ( t ( 'settings' , 'No apps found for {query}' , {
2015-10-20 11:58:07 +03:00
query : query
} ) ) ;
2015-10-15 18:00:00 +03:00
} else {
_ . each ( apps , function ( app ) {
$ ( '#app-' + app . id ) . removeClass ( 'hidden' ) ;
} ) ;
2015-01-18 16:52:19 +03:00
2015-10-15 18:00:00 +03:00
$ ( '#searchresults' ) . hide ( ) ;
}
2015-02-23 17:29:25 +03:00
} ,
2014-08-14 17:48:38 +04:00
2015-10-26 19:05:31 +03:00
_onPopState : function ( params ) {
params = _ . extend ( {
category : 'enabled'
} , params ) ;
OC . Settings . Apps . loadCategory ( params . category ) ;
} ,
2015-02-23 17:29:25 +03:00
/ * *
* Initializes the apps list
* /
initialize : function ( $el ) {
2016-12-15 19:07:07 +03:00
var renderer = new marked . Renderer ( ) ;
renderer . link = function ( href , title , text ) {
try {
var prot = decodeURIComponent ( unescape ( href ) )
. replace ( /[^\w:]/g , '' )
. toLowerCase ( ) ;
} catch ( e ) {
return '' ;
}
if ( prot . indexOf ( 'http:' ) !== 0 && prot . indexOf ( 'https:' ) !== 0 ) {
return '' ;
}
2017-01-13 20:30:43 +03:00
var out = '<a href="' + href + '" rel="noreferrer noopener"' ;
2016-12-15 19:07:07 +03:00
if ( title ) {
out += ' title="' + title + '"' ;
}
out += '>' + text + '</a>' ;
return out ;
} ;
renderer . image = function ( href , title , text ) {
if ( text ) {
return text ;
}
return title ;
} ;
renderer . blockquote = function ( quote ) {
return quote ;
} ;
OC . Settings . Apps . markedOptions = {
renderer : renderer ,
gfm : false ,
highlight : false ,
tables : false ,
breaks : false ,
pedantic : false ,
sanitize : true ,
smartLists : true ,
smartypants : false
} ;
2015-02-23 17:29:25 +03:00
OC . Plugins . register ( 'OCA.Search' , OC . Settings . Apps . Search ) ;
OC . Settings . Apps . loadCategories ( ) ;
2015-10-26 19:05:31 +03:00
OC . Util . History . addOnPopStateHandler ( _ . bind ( this . _onPopState , this ) ) ;
2012-08-04 22:12:18 +04:00
2015-02-23 17:29:25 +03:00
$ ( document ) . on ( 'click' , 'ul#apps-categories li' , function ( ) {
var categoryId = $ ( this ) . data ( 'categoryId' ) ;
OC . Settings . Apps . loadCategory ( categoryId ) ;
2015-10-26 19:05:31 +03:00
OC . Util . History . pushState ( {
category : categoryId
} ) ;
2015-10-15 17:50:31 +03:00
$ ( '#searchbox' ) . val ( '' ) ;
2015-02-23 17:29:25 +03:00
} ) ;
2012-08-04 22:12:18 +04:00
2015-03-06 18:28:38 +03:00
$ ( document ) . on ( 'click' , '.app-description-toggle-show' , function ( ) {
$ ( this ) . addClass ( 'hidden' ) ;
$ ( this ) . siblings ( '.app-description-toggle-hide' ) . removeClass ( 'hidden' ) ;
$ ( this ) . siblings ( '.app-description-container' ) . slideDown ( ) ;
} ) ;
$ ( document ) . on ( 'click' , '.app-description-toggle-hide' , function ( ) {
$ ( this ) . addClass ( 'hidden' ) ;
$ ( this ) . siblings ( '.app-description-toggle-show' ) . removeClass ( 'hidden' ) ;
$ ( this ) . siblings ( '.app-description-container' ) . slideUp ( ) ;
} ) ;
2015-02-23 17:29:25 +03:00
$ ( document ) . on ( 'click' , '#apps-list input.enable' , function ( ) {
var appId = $ ( this ) . data ( 'appid' ) ;
var element = $ ( this ) ;
var active = $ ( this ) . data ( 'active' ) ;
2014-08-14 17:48:38 +04:00
2017-04-23 23:10:17 +03:00
var category = $ ( '#app-navigation' ) . attr ( 'data-category' ) ;
if ( category === 'app-bundles' ) {
OC . Settings . Apps . enableAppBundle ( appId , active , element ) ;
} else {
OC . Settings . Apps . enableApp ( appId , active , element ) ;
}
2015-02-23 17:29:25 +03:00
} ) ;
2014-08-14 17:48:38 +04:00
2015-02-23 17:29:25 +03:00
$ ( document ) . on ( 'click' , '#apps-list input.uninstall' , function ( ) {
var appId = $ ( this ) . data ( 'appid' ) ;
var element = $ ( this ) ;
2014-08-14 17:48:38 +04:00
2015-02-23 17:29:25 +03:00
OC . Settings . Apps . uninstallApp ( appId , element ) ;
} ) ;
2014-08-14 17:48:38 +04:00
2015-02-23 17:29:25 +03:00
$ ( document ) . on ( 'click' , '#apps-list input.update' , function ( ) {
var appId = $ ( this ) . data ( 'appid' ) ;
var element = $ ( this ) ;
2014-08-14 17:48:38 +04:00
2015-02-23 17:29:25 +03:00
OC . Settings . Apps . updateApp ( appId , element ) ;
} ) ;
2014-08-14 17:48:38 +04:00
2015-02-23 17:29:25 +03:00
$ ( document ) . on ( 'change' , '#group_select' , function ( ) {
var element = $ ( this ) . parent ( ) . find ( 'input.enable' ) ;
var groups = $ ( this ) . val ( ) ;
if ( groups && groups !== '' ) {
2015-03-24 14:56:42 +03:00
groups = groups . split ( '|' ) ;
2015-02-23 17:29:25 +03:00
} else {
groups = [ ] ;
}
2012-08-04 22:12:18 +04:00
2015-02-23 17:29:25 +03:00
var appId = element . data ( 'appid' ) ;
if ( appId ) {
OC . Settings . Apps . enableApp ( appId , false , element , groups ) ;
OC . Settings . Apps . State . apps [ appId ] . groups = groups ;
}
} ) ;
2014-04-18 16:29:45 +04:00
2015-10-31 19:02:30 +03:00
$ ( document ) . on ( 'change' , ".groups-enable__checkbox" , function ( ) {
var $select = $ ( this ) . closest ( '.section' ) . find ( '#group_select' ) ;
2015-02-23 17:29:25 +03:00
$select . val ( '' ) ;
2014-04-18 16:29:45 +04:00
2015-02-23 17:29:25 +03:00
if ( this . checked ) {
OC . Settings . Apps . setupGroupsSelect ( $select ) ;
} else {
$select . select2 ( 'destroy' ) ;
}
2014-08-14 17:48:38 +04:00
2015-02-23 17:29:25 +03:00
$select . change ( ) ;
} ) ;
2014-08-14 17:48:38 +04:00
2015-03-30 16:58:20 +03:00
$ ( document ) . on ( 'click' , '#enable-experimental-apps' , function ( ) {
2015-10-15 17:15:42 +03:00
var state = $ ( this ) . prop ( 'checked' ) ;
2015-03-30 16:58:20 +03:00
$ . ajax ( OC . generateUrl ( 'settings/apps/experimental' ) , {
data : { state : state } ,
type : 'POST' ,
success : function ( ) {
location . reload ( ) ;
}
} ) ;
} ) ;
2015-02-23 17:29:25 +03:00
}
} ;
2014-08-14 17:48:38 +04:00
2015-02-23 17:29:25 +03:00
OC . Settings . Apps . Search = {
attach : function ( search ) {
search . setFilter ( 'settings' , OC . Settings . Apps . filter ) ;
}
} ;
$ ( document ) . ready ( function ( ) {
// HACK: FIXME: use plugin approach
if ( ! window . TESTING ) {
OC . Settings . Apps . initialize ( $ ( '#apps-list' ) ) ;
}
2011-08-10 14:20:43 +04:00
} ) ;