diff --git a/apps/files_encryption/img/app.svg b/apps/files_encryption/img/app.svg
new file mode 100644
index 00000000000..1157c71c66e
--- /dev/null
+++ b/apps/files_encryption/img/app.svg
@@ -0,0 +1,51 @@
+
+
\ No newline at end of file
diff --git a/apps/files_external/img/app.svg b/apps/files_external/img/app.svg
new file mode 100644
index 00000000000..df1bfd163ff
--- /dev/null
+++ b/apps/files_external/img/app.svg
@@ -0,0 +1,212 @@
+
+
diff --git a/apps/files_sharing/img/app.svg b/apps/files_sharing/img/app.svg
new file mode 100644
index 00000000000..d64e44b70b0
--- /dev/null
+++ b/apps/files_sharing/img/app.svg
@@ -0,0 +1,54 @@
+
+
diff --git a/apps/files_trashbin/img/app.svg b/apps/files_trashbin/img/app.svg
new file mode 100644
index 00000000000..b749f9879e6
--- /dev/null
+++ b/apps/files_trashbin/img/app.svg
@@ -0,0 +1,54 @@
+
+
diff --git a/apps/files_versions/img/app.svg b/apps/files_versions/img/app.svg
new file mode 100644
index 00000000000..862b0a6885e
--- /dev/null
+++ b/apps/files_versions/img/app.svg
@@ -0,0 +1,103 @@
+
+
diff --git a/apps/user_ldap/img/app.svg b/apps/user_ldap/img/app.svg
new file mode 100644
index 00000000000..63a065afdc7
--- /dev/null
+++ b/apps/user_ldap/img/app.svg
@@ -0,0 +1,61 @@
+
+
diff --git a/apps/user_webdavauth/img/app.svg b/apps/user_webdavauth/img/app.svg
new file mode 100644
index 00000000000..63a065afdc7
--- /dev/null
+++ b/apps/user_webdavauth/img/app.svg
@@ -0,0 +1,61 @@
+
+
diff --git a/core/img/rating/s0.png b/core/img/rating/s0.png
new file mode 100644
index 00000000000..9d5014106e5
Binary files /dev/null and b/core/img/rating/s0.png differ
diff --git a/core/img/rating/s1.png b/core/img/rating/s1.png
index 9d5014106e5..6846c8771f5 100644
Binary files a/core/img/rating/s1.png and b/core/img/rating/s1.png differ
diff --git a/core/img/rating/s10.png b/core/img/rating/s10.png
index b9c190f8ce7..c674569c389 100644
Binary files a/core/img/rating/s10.png and b/core/img/rating/s10.png differ
diff --git a/core/img/rating/s11.png b/core/img/rating/s11.png
deleted file mode 100644
index c674569c389..00000000000
Binary files a/core/img/rating/s11.png and /dev/null differ
diff --git a/core/img/rating/s2.png b/core/img/rating/s2.png
index 6846c8771f5..2f132cc5fa1 100644
Binary files a/core/img/rating/s2.png and b/core/img/rating/s2.png differ
diff --git a/core/img/rating/s3.png b/core/img/rating/s3.png
index 2f132cc5fa1..55e917f92e6 100644
Binary files a/core/img/rating/s3.png and b/core/img/rating/s3.png differ
diff --git a/core/img/rating/s4.png b/core/img/rating/s4.png
index 55e917f92e6..fa76c311c69 100644
Binary files a/core/img/rating/s4.png and b/core/img/rating/s4.png differ
diff --git a/core/img/rating/s5.png b/core/img/rating/s5.png
index fa76c311c69..8856309f838 100644
Binary files a/core/img/rating/s5.png and b/core/img/rating/s5.png differ
diff --git a/core/img/rating/s6.png b/core/img/rating/s6.png
index 8856309f838..4112e14fde2 100644
Binary files a/core/img/rating/s6.png and b/core/img/rating/s6.png differ
diff --git a/core/img/rating/s7.png b/core/img/rating/s7.png
index 4112e14fde2..ce25cf58df9 100644
Binary files a/core/img/rating/s7.png and b/core/img/rating/s7.png differ
diff --git a/core/img/rating/s8.png b/core/img/rating/s8.png
index ce25cf58df9..3197f23785f 100644
Binary files a/core/img/rating/s8.png and b/core/img/rating/s8.png differ
diff --git a/core/img/rating/s9.png b/core/img/rating/s9.png
index 3197f23785f..b9c190f8ce7 100644
Binary files a/core/img/rating/s9.png and b/core/img/rating/s9.png differ
diff --git a/core/templates/layout.user.php b/core/templates/layout.user.php
index 04cb6eb9def..9445175efcf 100644
--- a/core/templates/layout.user.php
+++ b/core/templates/layout.user.php
@@ -119,7 +119,7 @@
- class="active">
diff --git a/lib/private/app.php b/lib/private/app.php
index a356139044c..95a8a7302d9 100644
--- a/lib/private/app.php
+++ b/lib/private/app.php
@@ -815,7 +815,7 @@ class OC_App {
* Lists all apps, this is used in apps.php
* @return array
*/
- public static function listAllApps() {
+ public static function listAllApps($onlyLocal = false) {
$installedApps = OC_App::getAllApps();
//TODO which apps do we want to blacklist and how do we integrate
@@ -823,6 +823,7 @@ class OC_App {
$blacklist = array('files'); //we don't want to show configuration for these
$appList = array();
+ $l = \OC::$server->getL10N('core');
foreach ($installedApps as $app) {
if (array_search($app, $blacklist) === false) {
@@ -849,24 +850,36 @@ class OC_App {
if(isset($info['shipped']) and ($info['shipped'] == 'true')) {
$info['internal'] = true;
- $info['internallabel'] = 'Internal App';
- $info['internalclass'] = '';
+ $info['internallabel'] = $l->t('Recommended');
+ $info['internalclass'] = 'recommendedapp';
$info['removable'] = false;
} else {
$info['internal'] = false;
- $info['internallabel'] = '3rd Party';
- $info['internalclass'] = 'externalapp';
$info['removable'] = true;
}
$info['update'] = OC_Installer::isUpdateAvailable($app);
- $info['preview'] = OC_Helper::imagePath('settings', 'trans.png');
+ $appIcon = self::getAppPath($app) . '/img/' . $app.'.svg';
+ if (file_exists($appIcon)) {
+ $info['preview'] = OC_Helper::imagePath($app, $app.'.svg');
+ $info['previewAsIcon'] = true;
+ } else {
+ $appIcon = self::getAppPath($app) . '/img/app.svg';
+ if (file_exists($appIcon)) {
+ $info['preview'] = OC_Helper::imagePath($app, 'app.svg');
+ $info['previewAsIcon'] = true;
+ }
+ }
$info['version'] = OC_App::getAppVersion($app);
$appList[] = $info;
}
}
- $remoteApps = OC_App::getAppstoreApps();
+ if ($onlyLocal) {
+ $remoteApps = array();
+ } else {
+ $remoteApps = OC_App::getAppstoreApps();
+ }
if ($remoteApps) {
// Remove duplicates
foreach ($appList as $app) {
@@ -898,9 +911,11 @@ class OC_App {
}
// priority 3: recommended
- if ($a['internalclass'] != $b['internalclass']) {
- $aTemp = ($a['internalclass'] == 'recommendedapp' ? 1 : 0);
- $bTemp = ($b['internalclass'] == 'recommendedapp' ? 1 : 0);
+ $internalClassA = isset($a['internalclass']) ? $a['internalclass'] : '';
+ $internalClassB = isset($b['internalclass']) ? $b['internalclass'] : '';
+ if ($internalClassA != $internalClassB) {
+ $aTemp = ($internalClassA == 'recommendedapp' ? 1 : 0);
+ $bTemp = ($internalClassB == 'recommendedapp' ? 1 : 0);
return ($bTemp - $aTemp);
}
@@ -917,63 +932,40 @@ class OC_App {
* @return array, multi-dimensional array of apps.
* Keys: id, name, type, typename, personid, license, detailpage, preview, changed, description
*/
- public static function getAppstoreApps($filter = 'approved') {
- $categoryNames = OC_OCSClient::getCategories();
- if (is_array($categoryNames)) {
- // Check that categories of apps were retrieved correctly
- if (!$categories = array_keys($categoryNames)) {
+ public static function getAppstoreApps($filter = 'approved', $category = null) {
+ $categories = array($category);
+ if (is_null($category)) {
+ $categoryNames = OC_OCSClient::getCategories();
+ if (is_array($categoryNames)) {
+ // Check that categories of apps were retrieved correctly
+ if (!$categories = array_keys($categoryNames)) {
+ return false;
+ }
+ } else {
return false;
}
+ }
- $page = 0;
- $remoteApps = OC_OCSClient::getApplications($categories, $page, $filter);
- $app1 = array();
- $i = 0;
- foreach ($remoteApps as $app) {
- $app1[$i] = $app;
- $app1[$i]['author'] = $app['personid'];
- $app1[$i]['ocs_id'] = $app['id'];
- $app1[$i]['internal'] = $app1[$i]['active'] = 0;
- $app1[$i]['update'] = false;
- $app1[$i]['groups'] = false;
- $app1[$i]['removable'] = false;
- if ($app['label'] == 'recommended') {
- $app1[$i]['internallabel'] = 'Recommended';
- $app1[$i]['internalclass'] = 'recommendedapp';
- } else {
- $app1[$i]['internallabel'] = '3rd Party';
- $app1[$i]['internalclass'] = 'externalapp';
- }
-
-
- // rating img
- if ($app['score'] < 5) {
- $img = OC_Helper::imagePath( "core", "rating/s1.png" );
- } elseif ($app['score'] < 15) {
- $img = OC_Helper::imagePath( "core", "rating/s2.png" );
- } elseif($app['score'] < 25) {
- $img = OC_Helper::imagePath( "core", "rating/s3.png" );
- } elseif($app['score'] < 35) {
- $img = OC_Helper::imagePath( "core", "rating/s4.png" );
- } elseif($app['score'] < 45) {
- $img = OC_Helper::imagePath( "core", "rating/s5.png" );
- } elseif($app['score'] < 55) {
- $img = OC_Helper::imagePath( "core", "rating/s6.png" );
- } elseif($app['score'] < 65) {
- $img = OC_Helper::imagePath( "core", "rating/s7.png" );
- } elseif($app['score'] < 75) {
- $img = OC_Helper::imagePath( "core", "rating/s8.png" );
- } elseif($app['score'] < 85) {
- $img = OC_Helper::imagePath( "core", "rating/s9.png" );
- } elseif($app['score'] < 95) {
- $img = OC_Helper::imagePath( "core", "rating/s10.png" );
- } elseif($app['score'] < 100) {
- $img = OC_Helper::imagePath( "core", "rating/s11.png" );
- }
-
- $app1[$i]['score'] = '
Score: ' . $app['score'] . '%';
- $i++;
+ $page = 0;
+ $remoteApps = OC_OCSClient::getApplications($categories, $page, $filter);
+ $app1 = array();
+ $i = 0;
+ $l = \OC::$server->getL10N('core');
+ foreach ($remoteApps as $app) {
+ $app1[$i] = $app;
+ $app1[$i]['author'] = $app['personid'];
+ $app1[$i]['ocs_id'] = $app['id'];
+ $app1[$i]['internal'] = $app1[$i]['active'] = 0;
+ $app1[$i]['update'] = false;
+ $app1[$i]['groups'] = false;
+ $app1[$i]['score'] = $app['score'];
+ $app1[$i]['removable'] = false;
+ if ($app['label'] == 'recommended') {
+ $app1[$i]['internallabel'] = $l->t('Recommended');
+ $app1[$i]['internalclass'] = 'recommendedapp';
}
+
+ $i++;
}
if (empty($app1)) {
diff --git a/lib/private/installer.php b/lib/private/installer.php
index 02e2190aaf2..cd1d8ce392f 100644
--- a/lib/private/installer.php
+++ b/lib/private/installer.php
@@ -201,11 +201,10 @@ class OC_Installer{
/**
* update an app by it's id
* @param integer $ocsid
- * @param bool $isShipped
* @return bool
* @throws Exception
*/
- public static function updateAppByOCSId($ocsid, $isShipped=false) {
+ public static function updateAppByOCSId($ocsid) {
$appdata = OC_OCSClient::getApplication($ocsid);
$download = OC_OCSClient::getApplicationDownload($ocsid, 1);
diff --git a/lib/private/ocsclient.php b/lib/private/ocsclient.php
index dc147dea0c9..8ceb43f4c1f 100644
--- a/lib/private/ocsclient.php
+++ b/lib/private/ocsclient.php
@@ -142,9 +142,11 @@ class OC_OCSClient{
$app['license']=(string)$tmp[$i]->license;
$app['detailpage']=(string)$tmp[$i]->detailpage;
$app['preview']=(string)$tmp[$i]->smallpreviewpic1;
+ $app['preview-full']=(string)$tmp[$i]->previewpic1;
$app['changed']=strtotime($tmp[$i]->changed);
$app['description']=(string)$tmp[$i]->description;
$app['score']=(string)$tmp[$i]->score;
+ $app['downloads'] = $tmp[$i]->downloads;
$apps[]=$app;
}
diff --git a/settings/ajax/apps/categories.php b/settings/ajax/apps/categories.php
new file mode 100644
index 00000000000..3bde28be99b
--- /dev/null
+++ b/settings/ajax/apps/categories.php
@@ -0,0 +1,30 @@
+
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+OC_JSON::checkAdminUser();
+
+$l = OC_L10N::get('settings');
+
+$categories = array(
+ array('id' => 0, 'displayName' => (string)$l->t('Enabled') ),
+ array('id' => 1, 'displayName' => (string)$l->t('Not enabled') ),
+);
+
+if(OC_Config::getValue('appstoreenabled', true)) {
+ $categories[] = array('id' => 2, 'displayName' => (string)$l->t('Recommended') );
+ // apps from external repo via OCS
+ $ocs = OC_OCSClient::getCategories();
+ foreach($ocs as $k => $v) {
+ $categories[] = array(
+ 'id' => $k,
+ 'displayName' => str_replace('ownCloud ', '', $v)
+ );
+ }
+}
+
+OCP\JSON::success($categories);
diff --git a/settings/ajax/apps/index.php b/settings/ajax/apps/index.php
new file mode 100644
index 00000000000..24fba8be312
--- /dev/null
+++ b/settings/ajax/apps/index.php
@@ -0,0 +1,65 @@
+
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+OC_JSON::checkAdminUser();
+
+$l = OC_L10N::get('settings');
+
+$category = intval($_GET['category']);
+$apps = array();
+
+switch($category) {
+ // installed apps
+ case 0:
+ $apps = \OC_App::listAllApps(true);
+ $apps = array_filter($apps, function($app) {
+ return $app['active'];
+ });
+ break;
+ // not-installed apps
+ case 1:
+ $apps = \OC_App::listAllApps(true);
+ $apps = array_filter($apps, function($app) {
+ return !$app['active'];
+ });
+ break;
+ default:
+ if ($category === 2) {
+ $apps = \OC_App::getAppstoreApps('approved');
+ $apps = array_filter($apps, function($app) {
+ return isset($app['internalclass']) && $app['internalclass'] === 'recommendedapp';
+ });
+ } else {
+ $apps = \OC_App::getAppstoreApps('approved', $category);
+ }
+ if (!$apps) {
+ $apps = array();
+ }
+ usort($apps, function ($a, $b) {
+ $a = (int)$a['score'];
+ $b = (int)$b['score'];
+ if ($a === $b) {
+ return 0;
+ }
+ return ($a > $b) ? -1 : 1;
+ });
+ break;
+}
+
+// fix groups to be an array
+$apps = array_map(function($app){
+ $groups = array();
+ if (is_string($app['groups'])) {
+ $groups = json_decode($app['groups']);
+ }
+ $app['groups'] = $groups;
+ $app['canUnInstall'] = !$app['active'] && $app['removable'];
+ return $app;
+}, $apps);
+
+OCP\JSON::success(array("apps" => $apps));
diff --git a/settings/ajax/apps/ocs.php b/settings/ajax/apps/ocs.php
deleted file mode 100644
index aad0690e01c..00000000000
--- a/settings/ajax/apps/ocs.php
+++ /dev/null
@@ -1,68 +0,0 @@
-
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
- */
-
-OC_JSON::checkAdminUser();
-
-$l = \OC::$server->getL10N('settings');
-
-if(OC_Config::getValue('appstoreenabled', true)==false) {
- OCP\JSON::success(array('type' => 'external', 'data' => array()));
-}
-
-$enabledApps=OC_App::getEnabledApps();
-
-if(is_null($enabledApps)) {
- OCP\JSON::error(array('data' => array('message' => $l->t('Unable to load list from App Store'))));
-}
-
-$apps=array();
-
-// apps from external repo via OCS
-$categoryNames=OC_OCSClient::getCategories();
-if(is_array($categoryNames)) {
- $categories=array_keys($categoryNames);
- $page=0;
- $filter='approved';
- $externalApps=OC_OCSClient::getApplications($categories, $page, $filter);
- foreach($externalApps as $app) {
- // show only external apps that aren't enabled yet
- $local=false;
- foreach($enabledApps as $a) {
- if($a === $app['name']) {
- $local=true;
- }
- }
-
- if(!$local) {
- if($app['preview'] === '') {
- $pre=OC_Helper::imagePath('settings', 'trans.png');
- } else {
- $pre=$app['preview'];
- }
- if($app['label'] === 'recommended') {
- $label='3rd Party';
- } else {
- $label='Recommended';
- }
- $apps[]=array(
- 'name'=>$app['name'],
- 'id'=>$app['id'],
- 'active'=>false,
- 'description'=>$app['description'],
- 'author'=>$app['personid'],
- 'license'=>$app['license'],
- 'preview'=>$pre,
- 'internal'=>false,
- 'internallabel'=>$label,
- 'update'=>false,
- );
- }
- }
-}
-
-OCP\JSON::success(array('type' => 'external', 'data' => $apps));
diff --git a/settings/ajax/updateapp.php b/settings/ajax/updateapp.php
index 6375a41024a..3e28c65285d 100644
--- a/settings/ajax/updateapp.php
+++ b/settings/ajax/updateapp.php
@@ -12,30 +12,33 @@ if (!array_key_exists('appid', $_POST)) {
OCP\JSON::error(array(
'message' => 'No AppId given!'
));
- exit;
+ return;
}
$appId = $_POST['appid'];
if (!is_numeric($appId)) {
- $appId = OC_Appconfig::getValue($appId, 'ocsid', null);
- $isShipped = OC_App::isShipped($appId);
-
+ $appId = \OC::$server->getAppConfig()->getValue($appId, 'ocsid', null);
if ($appId === null) {
OCP\JSON::error(array(
'message' => 'No OCS-ID found for app!'
));
exit;
}
-} else {
- $isShipped = false;
}
$appId = OC_App::cleanAppId($appId);
-\OC_Config::setValue('maintenance', true);
-$result = OC_Installer::updateAppByOCSId($appId, $isShipped);
-\OC_Config::setValue('maintenance', false);
+$config = \OC::$server->getConfig();
+$config->setSystemValue('maintenance', true);
+try {
+ $result = OC_Installer::updateAppByOCSId($appId);
+ $config->setSystemValue('maintenance', false);
+} catch(Exception $ex) {
+ $config->setSystemValue('maintenance', false);
+ OC_JSON::error(array("data" => array( "message" => $ex->getMessage() )));
+ return;
+}
if($result !== false) {
OC_JSON::success(array('data' => array('appid' => $appId)));
diff --git a/settings/apps.php b/settings/apps.php
index b725c87b0ab..2d6f3c4c697 100644
--- a/settings/apps.php
+++ b/settings/apps.php
@@ -25,21 +25,14 @@ OC_Util::checkAdminUser();
\OC::$server->getSession()->close();
// Load the files we need
-OCP\Util::addStyle('settings', 'settings' );
-OCP\Util::addScript('settings', 'settings');
-OCP\Util::addScript('core', 'select2/select2');
-OCP\Util::addStyle('core', 'select2/select2');
-OC_App::setActiveNavigationEntry( "core_apps" );
-
-$combinedApps = OC_App::listAllApps();
+\OCP\Util::addScript('handlebars-v1.3.0');
+\OCP\Util::addScript("settings", "settings");
+\OCP\Util::addStyle("settings", "settings");
+\OCP\Util::addScript('core', 'select2/select2');
+\OCP\Util::addStyle('core', 'select2/select2');
+\OCP\Util::addScript("settings", "apps");
+\OC_App::setActiveNavigationEntry( "core_apps" );
$tmpl = new OC_Template( "settings", "apps", "user" );
-
-$tmpl->assign('apps', $combinedApps);
-
-$appid = (isset($_GET['appid'])?strip_tags($_GET['appid']):'');
-
-$tmpl->assign('appid', $appid);
-
$tmpl->printPage();
diff --git a/settings/css/settings.css b/settings/css/settings.css
index 581904591d0..bc6001ddf8e 100644
--- a/settings/css/settings.css
+++ b/settings/css/settings.css
@@ -128,7 +128,11 @@ input.userFilter {width: 200px;}
.ie8 table.hascontrols{border-collapse:collapse;width: 100%;}
.ie8 table.hascontrols tbody tr{border-collapse:collapse;border: 1px solid #ddd !important;}
+
+
+
/* APPS */
+
.appinfo { margin: 1em 40px; }
#app-navigation {
padding-bottom: 0px;
@@ -139,11 +143,62 @@ input.userFilter {width: 200px;}
#app-navigation.appwarning:hover {
background: #fbb;
}
-small.externalapp { color:#FFF; background-color:#BBB; font-weight:bold; font-size: 0.6em; margin: 0; padding: 0.1em 0.2em; border-radius: 3px;}
-small.recommendedapp { color:#FFF; background-color:#888; font-weight:bold; font-size: 0.6em; margin: 0; padding: 0.1em 0.2em; border-radius: 3px;}
-small.externalapp.list, small.recommendedapp.list { position: absolute; right: 10px; top: 12px; }
+
+.recommendedapp {
+ font-size: 11px;
+ background-position: left center;
+ padding-left: 18px;
+ vertical-align: top;
+}
span.version { margin-left:1em; margin-right:1em; color:#555; }
+#app-navigation .app-external,
+.app-version,
+.recommendedapp {
+ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
+ filter: alpha(opacity=50);
+ opacity: .5;
+}
+
+#apps-list {
+ position: relative;
+ height: 100%;
+}
+.section {
+ position: relative;
+}
+.app-image {
+ float: left;
+ padding-right: 10px;
+ width: 80px;
+ height: 80px;
+}
+.app-image img {
+ max-width: 80px;
+ max-height: 80px;
+}
+.app-image-icon img {
+ background-color: #ccc;
+ width: 60px;
+ padding: 10px;
+ border-radius: 3px;
+}
+.app-name,
+.app-version,
+.app-score,
+.recommendedapp {
+ display: inline-block;
+}
+.app-description {
+ clear: both;
+}
+.app-description pre {
+ white-space: pre-line;
+}
+
+#app-category-2 {
+ border-bottom: 1px solid #e8e8e8;
+}
/* Transition to complete width! */
.app:hover, .app:active { max-width: inherit; }
diff --git a/settings/js/apps-custom.php b/settings/js/apps-custom.php
deleted file mode 100644
index 2b2f256b39f..00000000000
--- a/settings/js/apps-custom.php
+++ /dev/null
@@ -1,26 +0,0 @@
-
- * This file is licensed under the Affero General Public License version 3 or
- * later.
- * See the COPYING-README file.
- */
-
-// Check if admin user
-OC_Util::checkAdminUser();
-
-// Set the content type to JS
-header('Content-type: application/javascript');
-
-// Disallow caching
-header("Cache-Control: no-cache, must-revalidate");
-header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
-
-$combinedApps = OC_App::listAllApps();
-
-foreach($combinedApps as $app) {
- echo("appData_".$app['id']."=".json_encode($app));
- echo("\n");
-}
-
-echo ("var appid =".json_encode($_GET['appid']).";");
diff --git a/settings/js/apps.js b/settings/js/apps.js
index 22bac1eaf3e..328c57db8ed 100644
--- a/settings/js/apps.js
+++ b/settings/js/apps.js
@@ -1,225 +1,235 @@
-/**
- * Copyright (c) 2011, Robin Appelman
- * Copyright (c) 2012, Thomas Tanghus
- * This file is licensed under the Affero General Public License version 3 or later.
- * See the COPYING-README file.
- */
+/* global Handlebars */
+
+Handlebars.registerHelper('score', function() {
+ if(this.score) {
+ var score = Math.round( this.score / 10 );
+ var imageName = 'rating/s' + score + '.png';
+
+ return new Handlebars.SafeString('
');
+ }
+ return new Handlebars.SafeString('');
+});
OC.Settings = OC.Settings || {};
OC.Settings.Apps = OC.Settings.Apps || {
- setupGroupsSelect: function() {
- OC.Settings.setupGroupsSelect($('#group_select'), {
+ setupGroupsSelect: function($elements) {
+ OC.Settings.setupGroupsSelect($elements, {
placeholder: t('core', 'All')
});
},
- loadApp:function(app) {
- var page = $('#app-content');
- page.find('p.license').show();
- page.find('span.name').text(app.name);
- page.find('small.externalapp').text(app.internallabel);
- if (app.version) {
- page.find('span.version').text(app.version);
- } else {
- page.find('span.version').text('');
- }
- page.find('span.score').html(app.score);
- page.find('p.description').text(app.description);
- page.find('img.preview').attr('src', app.preview);
- if (app.preview && app.preview.length) {
- page.find('img.preview').show();
- } else {
- page.find('img.preview').hide();
- }
- page.find('small.externalapp').attr('style', 'visibility:visible');
- page.find('span.author').text(app.author);
-
- // FIXME licenses of downloaded apps go into app.licence, licenses of not-downloaded apps into app.license
- var appLicense = '';
- if (typeof(app.licence) !== 'undefined') {
- appLicense = app.licence;
- } else if (typeof(app.license) !== 'undefined') {
- appLicense = app.license;
- }
- page.find('span.licence').text(appLicense);
-
- var userDocumentation = false;
- var adminDocumentation = false;
- if (typeof(app.documentation) !== 'undefined') {
- if (typeof(app.documentation.user) !== 'undefined') {
- userDocumentation = true;
- page.find('span.userDocumentation').html("" + t('settings', 'User Documentation') + "");
- page.find('p.documentation').show();
- }
- else {
- page.find('span.userDocumentation').empty();
- userDocumentation = false;
- }
- if (typeof(app.documentation.admin) !== 'undefined') {
- adminDocumentation = true;
- page.find('span.adminDocumentation').html("" + t('settings', 'Admin Documentation') + "");
- page.find('p.documentation').show();
- }
- else {
- page.find('span.adminDocumentation').empty();
- adminDocumentation = false;
- }
- if(userDocumentation && adminDocumentation) {
- page.find('span.comma').remove();
- page.find('span.userDocumentation').after(', ');
- }
- else {
- page.find('span.comma').remove();
+ State: {
+ currentCategory: null,
+ apps: null
+ },
+
+ loadCategories: function() {
+ var categories = [
+ {displayName: 'Enabled', id: '0'}
+ ];
+
+ var source = $("#categories-template").html();
+ var template = Handlebars.compile(source);
+ var html = template(categories);
+ $('#apps-categories').html(html);
+
+ OC.Settings.Apps.loadCategory(0);
+
+ $.ajax(OC.generateUrl('settings/apps/categories'), {
+ 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');
}
- }
- else {
- page.find('p.documentation').hide();
- }
+ });
- if (typeof(app.website) !== 'undefined') {
- page.find('p.website').show();
- page.find('a#websitelink').attr('href', app.website);
- }
+ },
- if (app.update !== false) {
- page.find('input.update').show();
- page.find('input.update').data('appid', app.id);
- page.find('input.update').attr('value',t('settings', 'Update to {appversion}', {appversion:app.update}));
- } else {
- page.find('input.update').hide();
+ loadCategory: function(categoryId) {
+ if (OC.Settings.Apps.State.currentCategory === categoryId) {
+ return;
}
+ $('#apps-list')
+ .addClass('icon-loading')
+ .html('');
+ $('#app-category-' + OC.Settings.Apps.State.currentCategory).removeClass('active');
+ $('#app-category-' + categoryId).addClass('active');
+ OC.Settings.Apps.State.currentCategory = categoryId;
- if (app.removable !== false && app.active === false) {
- page.find('a.uninstall').show();
- page.find('a.uninstall').data('appid', app.id);
- page.find('a.uninstall').attr('value', t('settings', 'Uninstall App'));
- } else {
- page.find('a.uninstall').hide();
+ $.ajax(OC.generateUrl('settings/apps/list?category={categoryId}', {
+ categoryId: categoryId
+ }), {
+ data:{},
+ type:'GET',
+ success:function (apps) {
+ OC.Settings.Apps.State.apps = _.indexBy(apps.apps, 'id');
+ var source = $("#app-template").html();
+ var template = Handlebars.compile(source);
+
+ _.each(apps.apps, function(app) {
+ OC.Settings.Apps.renderApp(app, template, null);
+ });
+ },
+ complete: function() {
+ $('#apps-list').removeClass('icon-loading');
+ }
+ });
+ },
+
+ renderApp: function(app, template, selector) {
+ if (!template) {
+ var source = $("#app-template").html();
+ template = Handlebars.compile(source);
+ }
+ if (typeof app === 'string') {
+ app = OC.Settings.Apps.State.apps[app];
}
- page.find('input.enable').show();
- page.find('input.enable').val((app.active) ? t('settings', 'Disable') : t('settings', 'Enable'));
- page.find('input.enable').data('appid', app.id);
- page.find('input.enable').data('active', app.active);
- if (app.internal === false) {
- page.find('span.score').show();
- page.find('p.appstore').show();
- page.find('a#appstorelink').attr('href', 'http://apps.owncloud.com/content/show.php?content=' + app.id);
- page.find('small.externalapp').hide();
+ var html = template(app);
+ if (selector) {
+ selector.html(html);
} else {
- page.find('p.appslink').hide();
- page.find('span.score').hide();
+ $('#apps-list').append(html);
}
- if (typeof($('#app-navigation ul li[data-id="'+app.id+'"]').data('errormsg')) !== "undefined") {
- page.find(".warning").show();
- page.find(".warning").text($('#app-navigation ul li[data-id="'+app.id+'"]').data('errormsg'));
- } else {
- page.find(".warning").hide();
+
+ var page = $('#app-' + app.id);
+
+ // image loading kung-fu
+ if (app.preview) {
+ var currentImage = new Image();
+ currentImage.src = app.preview;
+
+ currentImage.onload = function() {
+ page.find('.app-image')
+ .append(this)
+ .fadeIn();
+ };
}
+ // set group select properly
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')) {
- page.find("#groups_enable").hide();
- page.find("label[for='groups_enable']").hide();
- page.find("#groups_enable").attr('checked', null);
+ page.find(".groups-enable").hide();
+ page.find("label[for='groups_enable-"+app.id+"']").hide();
+ page.find(".groups-enable").attr('checked', null);
} else {
+ page.find('#group_select').val((app.groups || []).join(','));
if (app.active) {
if (app.groups.length) {
- OC.Settings.Apps.setupGroupsSelect();
- $('#group_select').select2('val', app.groups || []);
- page.find("#groups_enable").attr('checked','checked');
+ OC.Settings.Apps.setupGroupsSelect(page.find('#group_select'));
+ page.find(".groups-enable").attr('checked','checked');
} else {
- page.find("#groups_enable").attr('checked', null);
+ page.find(".groups-enable").attr('checked', null);
}
- page.find("#groups_enable").show();
- page.find("label[for='groups_enable']").show();
+ page.find(".groups-enable").show();
+ page.find("label[for='groups_enable-"+app.id+"']").show();
} else {
- page.find("#groups_enable").hide();
- page.find("label[for='groups_enable']").hide();
+ page.find(".groups-enable").hide();
+ page.find("label[for='groups_enable-"+app.id+"']").hide();
}
}
},
- enableApp:function(appid, active, element, groups) {
+
+ isType: function(app, type){
+ return app.types && app.types.indexOf(type) !== -1;
+ },
+
+ enableApp:function(appId, active, element, groups) {
+ OC.Settings.Apps.hideErrorMessage(appId);
groups = groups || [];
- var appitem=$('#app-navigation ul li[data-id="'+appid+'"]');
+ var appItem = $('div#app-'+appId+'');
element.val(t('settings','Please wait....'));
if(active && !groups.length) {
- $.post(OC.filePath('settings','ajax','disableapp.php'),{appid:appid},function(result) {
+ $.post(OC.filePath('settings','ajax','disableapp.php'),{appid:appId},function(result) {
if(!result || result.status !== 'success') {
if (result.data && result.data.message) {
- OC.Settings.Apps.showErrorMessage(result.data.message);
- appitem.data('errormsg', result.data.message);
+ OC.Settings.Apps.showErrorMessage(appId, result.data.message);
+ appItem.data('errormsg', result.data.message);
} else {
- OC.Settings.Apps.showErrorMessage(t('settings', 'Error while disabling app'));
- appitem.data('errormsg', t('settings', 'Error while disabling app'));
+ OC.Settings.Apps.showErrorMessage(appId, t('settings', 'Error while disabling app'));
+ appItem.data('errormsg', t('settings', 'Error while disabling app'));
}
element.val(t('settings','Disable'));
- appitem.addClass('appwarning');
- }
- else {
- appitem.data('active',false);
- appitem.data('groups', '');
+ appItem.addClass('appwarning');
+ } else {
+ appItem.data('active',false);
+ appItem.data('groups', '');
element.data('active',false);
- OC.Settings.Apps.removeNavigation(appid);
- appitem.removeClass('active');
+ OC.Settings.Apps.removeNavigation(appId);
+ appItem.removeClass('active');
element.val(t('settings','Enable'));
- element.parent().find("#groups_enable").hide();
- element.parent().find("label[for='groups_enable']").hide();
- var app = OC.get('appData_' + appid);
- app.active = false;
+ element.parent().find(".groups-enable").hide();
+ element.parent().find("#groups_enable-"+appId).hide();
+ element.parent().find("label[for='groups_enable-"+appId+"']").hide();
+ element.parent().find('#group_select').hide().val(null);
+ OC.Settings.Apps.State.apps[appId].active = false;
}
},'json');
} else {
- $.post(OC.filePath('settings','ajax','enableapp.php'),{appid: appid, groups: groups},function(result) {
+ $.post(OC.filePath('settings','ajax','enableapp.php'),{appid: appId, groups: groups},function(result) {
if(!result || result.status !== 'success') {
if (result.data && result.data.message) {
- OC.Settings.Apps.showErrorMessage(result.data.message);
- appitem.data('errormsg', result.data.message);
+ OC.Settings.Apps.showErrorMessage(appId, result.data.message);
+ appItem.data('errormsg', result.data.message);
} else {
- OC.Settings.Apps.showErrorMessage(t('settings', 'Error while enabling app'));
- appitem.data('errormsg', t('settings', 'Error while disabling app'));
+ OC.Settings.Apps.showErrorMessage(appId, t('settings', 'Error while enabling app'));
+ appItem.data('errormsg', t('settings', 'Error while disabling app'));
}
element.val(t('settings','Enable'));
- appitem.addClass('appwarning');
+ appItem.addClass('appwarning');
} else {
- OC.Settings.Apps.addNavigation(appid);
- appitem.data('active',true);
+ OC.Settings.Apps.addNavigation(appId);
+ appItem.data('active',true);
element.data('active',true);
- appitem.addClass('active');
+ appItem.addClass('active');
element.val(t('settings','Disable'));
- var app = OC.get('appData_' + appid);
+ var app = OC.Settings.Apps.State.apps[appId];
app.active = true;
+
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')) {
- element.parent().find("#groups_enable").hide();
- element.parent().find("label[for='groups_enable']").hide();
+ element.parent().find(".groups-enable").attr('checked', null);
+ element.parent().find("#groups_enable-"+appId).hide();
+ element.parent().find("label[for='groups_enable-"+appId+"']").hide();
+ element.parent().find(".groups-enable").hide();
+ element.parent().find("#groups_enable-"+appId).hide();
+ element.parent().find("label[for='groups_enable-"+appId+"']").hide();
+ element.parent().find('#group_select').hide().val(null);
} else {
- element.parent().find("#groups_enable").show();
- element.parent().find("label[for='groups_enable']").show();
+ element.parent().find("#groups_enable-"+appId).show();
+ element.parent().find("label[for='groups_enable-"+appId+"']").show();
if (groups) {
- appitem.data('groups', JSON.stringify(groups));
+ appItem.data('groups', JSON.stringify(groups));
} else {
- appitem.data('groups', '');
+ appItem.data('groups', '');
}
}
}
},'json')
- .fail(function() {
- OC.Settings.Apps.showErrorMessage(t('settings', 'Error while enabling app'));
- appitem.data('errormsg', t('settings', 'Error while enabling app'));
- appitem.data('active',false);
- appitem.addClass('appwarning');
- OC.Settings.Apps.removeNavigation(appid);
- element.val(t('settings','Enable'));
- });
+ .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');
+ OC.Settings.Apps.removeNavigation(appId);
+ element.val(t('settings','Enable'));
+ });
}
},
- updateApp:function(appid, element) {
+
+ updateApp:function(appId, element) {
+ var oldButtonText = element.val();
element.val(t('settings','Updating....'));
- $.post(OC.filePath('settings','ajax','updateapp.php'),{appid:appid},function(result) {
+ OC.Settings.Apps.hideErrorMessage(appId);
+ $.post(OC.filePath('settings','ajax','updateapp.php'),{appid:appId},function(result) {
if(!result || result.status !== 'success') {
- OC.Settings.Apps.showErrorMessage(t('settings','Error while updating app'),t('settings','Error'));
- element.val(t('settings','Update'));
+ OC.Settings.Apps.showErrorMessage(appId, t('settings','Error while updating app'));
+ element.val(oldButtonText);
}
else {
element.val(t('settings','Updated'));
@@ -227,42 +237,25 @@ OC.Settings.Apps = OC.Settings.Apps || {
}
},'json');
},
- uninstallApp:function(appid, element) {
+
+ uninstallApp:function(appId, element) {
+ OC.Settings.Apps.hideErrorMessage(appId);
element.val(t('settings','Uninstalling ....'));
- $.post(OC.filePath('settings','ajax','uninstallapp.php'),{appid:appid},function(result) {
+ $.post(OC.filePath('settings','ajax','uninstallapp.php'),{appid:appId},function(result) {
if(!result || result.status !== 'success') {
- OC.Settings.Apps.showErrorMessage(t('settings','Error while uninstalling app'),t('settings','Error'));
+ OC.Settings.Apps.showErrorMessage(appId, t('settings','Error while uninstalling app'));
element.val(t('settings','Uninstall'));
} else {
- OC.Settings.Apps.removeNavigation(appid);
- var appItem = $('#app-navigation li').filterAttr('data-id', appid);
- appItem.removeClass('active');
+ OC.Settings.Apps.removeNavigation(appId);
+ element.parent().fadeOut(function() {
+ element.remove();
+ });
}
},'json');
},
- insertApp:function(appdata) {
- var applist = $('#app-navigation ul li');
- var app =
- $(''
- + ''
- + appdata.name+'3rd party');
- app.data('app', appdata);
- var added = false;
- applist.each(function() {
- if(!parseInt($(this).data('installed')) && $(this).find('a').text().toLowerCase() > appdata.name.toLowerCase()) {
- $(this).before(app);
- added = true;
- return false; // dang, remember this to get out of loop
- }
- });
- if(!added) {
- applist.last().after(app);
- }
- return app;
- },
- removeNavigation: function(appid){
- $.getJSON(OC.filePath('settings', 'ajax', 'navigationdetect.php'), {app: appid}).done(function(response){
+ removeNavigation: function(appId){
+ $.getJSON(OC.filePath('settings', 'ajax', 'navigationdetect.php'), {app: appId}).done(function(response){
if(response.status === 'success'){
var navIds=response.nav_ids;
for(var i=0; i< navIds.length; i++){
@@ -310,107 +303,87 @@ OC.Settings.Apps = OC.Settings.Apps || {
.animate({opacity: 1})
.animate({opacity: 0.75});
- if (!SVGSupport() && entry.icon.match(/\.svg$/i)) {
+ if (!OC.Util.hasSVGSupport() && entry.icon.match(/\.svg$/i)) {
$(img).addClass('svg');
- replaceSVG();
+ OC.Util.replaceSVG();
}
}
}
}
});
},
- showErrorMessage: function(message) {
- $('.appinfo .warning').show();
- $('.appinfo .warning').text(message);
+
+ showErrorMessage: function(appId, message) {
+ $('div#app-'+appId+' .warning')
+ .show()
+ .text(message);
},
- isType: function(app, type){
- return app.types && app.types.indexOf(type) !== -1;
+
+ hideErrorMessage: function(appId) {
+ $('div#app-'+appId+' .warning')
+ .hide()
+ .text('');
}
+
};
-$(document).ready(function(){
- $('#app-navigation ul li').each(function(index,li){
- var app = OC.get('appData_'+$(li).data('id'));
- if (app) {
- app.groups= $(li).data('groups') || [];
- }
- $(li).data('app',app);
- $(this).find('span.hidden').remove();
- });
- $('#app-navigation ul li').keydown(function(event) {
- if (event.which === 13 || event.which === 32) {
- $(event.target).click();
- }
- return false;
- });
+$(document).ready(function () {
+ OC.Settings.Apps.loadCategories();
- $(document).on('click', '#app-navigation', function(event){
- var tgt = $(event.target);
- if (tgt.is('li') || tgt.is('a')) {
- var item = tgt.is('li') ? $(tgt) : $(tgt).parent();
- var app = item.data('app');
- OC.Settings.Apps.loadApp(app);
- $('#app-navigation .selected').removeClass('selected');
- item.addClass('selected');
- }
- return false;
+ $(document).on('click', 'ul#apps-categories li', function () {
+ var categoryId = $(this).data('categoryId');
+ OC.Settings.Apps.loadCategory(categoryId);
});
- $('#app-content input.enable').click(function(){
+
+ $(document).on('click', '#apps-list input.enable', function () {
+ var appId = $(this).data('appid');
var element = $(this);
- var appid=$(this).data('appid');
- var active=$(this).data('active');
- if(appid) {
- OC.Settings.Apps.enableApp(appid, active, element);
- }
+ var active = $(this).data('active');
+
+ OC.Settings.Apps.enableApp(appId, active, element);
});
- $('#app-content input.update').click(function(){
+
+ $(document).on('click', '#apps-list input.uninstall', function () {
+ var appId = $(this).data('appid');
var element = $(this);
- var appid=$(this).data('appid');
- if(appid) {
- OC.Settings.Apps.updateApp(appid, element);
- }
+
+ OC.Settings.Apps.uninstallApp(appId, element);
});
- $('#app-content a.uninstall').click(function(){
+
+ $(document).on('click', '#apps-list input.update', function () {
+ var appId = $(this).data('appid');
var element = $(this);
- var appid=$(this).data('appid');
- if(appid) {
- OC.Settings.Apps.uninstallApp(appid, element);
- }
+
+ OC.Settings.Apps.updateApp(appId, element);
});
- $('#group_select').change(function(ev) {
- var element = $('#app-content input.enable');
- // getting an array of values from select2
- var groups = ev.val || [];
- var appid = element.data('appid');
- if (appid) {
- OC.Settings.Apps.enableApp(appid, false, element, groups);
- var li = $('[data-id="'+appid+'"]');
- var app = OC.get('appData_' + $(li).data('id'));
- app.groups = groups;
- li.data('groups', groups);
- li.attr('data-groups', JSON.stringify(groups));
+ $(document).on('change', '#group_select', function() {
+ var element = $(this).parent().find('input.enable');
+ var groups = $(this).val();
+ if (groups && groups !== '') {
+ groups = groups.split(',');
+ } else {
+ groups = [];
}
- });
- if(appid) {
- var item = $('#app-navigation ul li[data-id="'+appid+'"]');
- if(item) {
- item.trigger('click');
- item.addClass('active');
- $('#app-navigation').animate({scrollTop: item.offset().top-70}, 'slow','swing');
+ var appId = element.data('appid');
+ if (appId) {
+ OC.Settings.Apps.enableApp(appId, false, element, groups);
+ OC.Settings.Apps.State.apps[appId].groups = groups;
}
- }
+ });
- $("#groups_enable").change(function() {
- var $select = $('#group_select');
+ $(document).on('change', ".groups-enable", function() {
+ var $select = $(this).parent().find('#group_select');
$select.val('');
+
if (this.checked) {
- OC.Settings.Apps.setupGroupsSelect();
- }
- else {
+ OC.Settings.Apps.setupGroupsSelect($select);
+ } else {
$select.select2('destroy');
}
+
$select.change();
});
+
});
diff --git a/settings/js/old-apps.js b/settings/js/old-apps.js
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/settings/routes.php b/settings/routes.php
index 25a8b1da7e0..d942e540360 100644
--- a/settings/routes.php
+++ b/settings/routes.php
@@ -69,10 +69,12 @@ $this->create('settings_cert_post', '/settings/ajax/addRootCertificate')
$this->create('settings_cert_remove', '/settings/ajax/removeRootCertificate')
->actionInclude('settings/ajax/removeRootCertificate.php');
// apps
-$this->create('settings_ajax_apps_ocs', '/settings/ajax/apps/ocs.php')
- ->actionInclude('settings/ajax/apps/ocs.php');
$this->create('settings_ajax_enableapp', '/settings/ajax/enableapp.php')
->actionInclude('settings/ajax/enableapp.php');
+$this->create('settings_ajax_load_app_categories', '/settings/apps/categories')
+ ->actionInclude('settings/ajax/apps/categories.php');
+$this->create('settings_ajax_load_apps', '/settings/apps/list')
+ ->actionInclude('settings/ajax/apps/index.php');
$this->create('settings_ajax_disableapp', '/settings/ajax/disableapp.php')
->actionInclude('settings/ajax/disableapp.php');
$this->create('settings_ajax_updateapp', '/settings/ajax/updateapp.php')
@@ -81,8 +83,6 @@ $this->create('settings_ajax_uninstallapp', '/settings/ajax/uninstallapp.php')
->actionInclude('settings/ajax/uninstallapp.php');
$this->create('settings_ajax_navigationdetect', '/settings/ajax/navigationdetect.php')
->actionInclude('settings/ajax/navigationdetect.php');
-$this->create('apps_custom', '/settings/js/apps-custom.js')
- ->actionInclude('settings/js/apps-custom.php');
// admin
$this->create('settings_ajax_getlog', '/settings/ajax/getlog.php')
->actionInclude('settings/ajax/getlog.php');
diff --git a/settings/templates/apps.php b/settings/templates/apps.php
index 5199d3fd7c7..1ad37000f39 100644
--- a/settings/templates/apps.php
+++ b/settings/templates/apps.php
@@ -1,65 +1,82 @@
-
- * This file is licensed under the Affero General Public License version 3 or later.
- * See the COPYING-README file.
- */?>
-
-
+
-
- data-id="" data-groups=""
-
- data-type="" data-installed="1">
-
- '.OC_Util::sanitizeHTML($app['internallabel']).'') ?>
-
-
-
-
-
- t('More Apps'));?> …
-
-
-
-
-
-
-
t('Select an App'));?>
-
-
-
+
+
+
+