summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--settings/controller/appsettingscontroller.php47
-rw-r--r--settings/js/apps.js78
-rw-r--r--settings/templates/apps.php4
-rw-r--r--settings/tests/js/appsSpec.js70
-rw-r--r--tests/settings/controller/AppSettingsControllerTest.php41
5 files changed, 206 insertions, 34 deletions
diff --git a/settings/controller/appsettingscontroller.php b/settings/controller/appsettingscontroller.php
index f5cb043da20..bde00df062f 100644
--- a/settings/controller/appsettingscontroller.php
+++ b/settings/controller/appsettingscontroller.php
@@ -42,6 +42,8 @@ use OCP\IConfig;
* @package OC\Settings\Controller
*/
class AppSettingsController extends Controller {
+ const CAT_ENABLED = 0;
+ const CAT_DISABLED = 1;
/** @var \OCP\IL10N */
private $l10n;
@@ -95,12 +97,41 @@ class AppSettingsController extends Controller {
}
/**
+ * @param string|int $category
+ * @return int
+ */
+ protected function getCategory($category) {
+ if (is_string($category)) {
+ foreach ($this->listCategories() as $cat) {
+ if (isset($cat['ident']) && $cat['ident'] === $category) {
+ $category = (int) $cat['id'];
+ break;
+ }
+ }
+
+ // Didn't find the category, falling back to enabled
+ if (is_string($category)) {
+ $category = self::CAT_ENABLED;
+ }
+ }
+ return (int) $category;
+ }
+
+ /**
* @NoCSRFRequired
+ * @param string $category
* @return TemplateResponse
*/
- public function viewApps() {
+ public function viewApps($category = '') {
+ $categoryId = $this->getCategory($category);
+ if ($categoryId === self::CAT_ENABLED) {
+ // Do not use an arbitrary input string, because we put the category in html
+ $category = 'enabled';
+ }
+
$params = [];
$params['experimentalEnabled'] = $this->config->getSystemValue('appstore.experimental.enabled', false);
+ $params['category'] = $category;
$this->navigationManager->setActiveEntry('core_apps');
$templateResponse = new TemplateResponse($this->appName, 'apps', $params, 'user');
@@ -121,8 +152,8 @@ class AppSettingsController extends Controller {
return $this->cache->get('listCategories');
}
$categories = [
- ['id' => 0, 'displayName' => (string)$this->l10n->t('Enabled')],
- ['id' => 1, 'displayName' => (string)$this->l10n->t('Not enabled')],
+ ['id' => self::CAT_ENABLED, 'ident' => 'enabled', 'displayName' => (string)$this->l10n->t('Enabled')],
+ ['id' => self::CAT_DISABLED, 'ident' => 'disabled', 'displayName' => (string)$this->l10n->t('Not enabled')],
];
if($this->ocsClient->isAppStoreEnabled()) {
@@ -130,9 +161,12 @@ class AppSettingsController extends Controller {
$ocs = $this->ocsClient->getCategories(\OC_Util::getVersion());
if ($ocs) {
foreach($ocs as $k => $v) {
+ $name = str_replace('ownCloud ', '', $v);
+ $ident = str_replace(' ', '-', urlencode(strtolower($name)));
$categories[] = [
'id' => $k,
- 'displayName' => str_replace('ownCloud ', '', $v)
+ 'ident' => $ident,
+ 'displayName' => $name,
];
}
}
@@ -146,12 +180,13 @@ class AppSettingsController extends Controller {
/**
* Get all available apps in a category
*
- * @param int $category
+ * @param string $category
* @param bool $includeUpdateInfo Should we check whether there is an update
* in the app store?
* @return array
*/
- public function listApps($category = 0, $includeUpdateInfo = true) {
+ public function listApps($category = '', $includeUpdateInfo = true) {
+ $category = $this->getCategory($category);
$cacheName = 'listApps-' . $category . '-' . (int) $includeUpdateInfo;
if(!is_null($this->cache->get($cacheName))) {
diff --git a/settings/js/apps.js b/settings/js/apps.js
index 987153b778c..9ffa74c7d93 100644
--- a/settings/js/apps.js
+++ b/settings/js/apps.js
@@ -40,7 +40,8 @@ OC.Settings.Apps = OC.Settings.Apps || {
}
var categories = [
- {displayName: 'Enabled', id: '0'}
+ {displayName: t('settings', 'Enabled'), ident: 'enabled', id: '0'},
+ {displayName: t('settings', 'Not enabled'), ident: 'disabled', id: '1'}
];
var source = $("#categories-template").html();
@@ -48,7 +49,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
var html = template(categories);
$('#apps-categories').html(html);
- OC.Settings.Apps.loadCategory(0);
+ OC.Settings.Apps.loadCategory($('#app-navigation').attr('data-category'));
this._loadCategoriesCall = $.ajax(OC.generateUrl('settings/apps/categories'), {
data:{},
@@ -115,7 +116,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
});
} else {
$('#apps-list').addClass('hidden');
- $('#apps-list-empty').removeClass('hidden');
+ $('#apps-list-empty').removeClass('hidden').find('h2').text(t('settings', 'No apps found for your version'));
}
$('.app-level .official').tipsy({fallback: t('settings', 'Official apps are developed by and within the ownCloud community. They offer functionality central to ownCloud and are ready for production use.')});
@@ -398,14 +399,14 @@ OC.Settings.Apps = OC.Settings.Apps || {
.text('');
},
- showReloadMessage: function(appId) {
+ showReloadMessage: function() {
OC.dialogs.info(
t(
'settings',
'The app has been enabled but needs to be updated. You will be redirected to the update page in 5 seconds.'
),
t('settings','App update'),
- function (result) {
+ function () {
window.location.reload();
},
true
@@ -413,24 +414,74 @@ OC.Settings.Apps = OC.Settings.Apps || {
},
filter: function(query) {
+ var $appList = $('#apps-list'),
+ $emptyList = $('#apps-list-empty');
+ $appList.removeClass('hidden');
+ $appList.find('.section').removeClass('hidden');
+ $emptyList.addClass('hidden');
+
+ if (query === '') {
+ return;
+ }
+
query = query.toLowerCase();
- $('#apps-list').find('.section').addClass('hidden');
+ $appList.find('.section').addClass('hidden');
+ // App Name
var apps = _.filter(OC.Settings.Apps.State.apps, function (app) {
return app.name.toLowerCase().indexOf(query) !== -1;
});
+ // App Description
apps = apps.concat(_.filter(OC.Settings.Apps.State.apps, function (app) {
return app.description.toLowerCase().indexOf(query) !== -1;
}));
+ // Author Name
+ apps = apps.concat(_.filter(OC.Settings.Apps.State.apps, function (app) {
+ return app.author.toLowerCase().indexOf(query) !== -1;
+ }));
+
+ // 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;
+ }));
+ }
+
apps = _.uniq(apps, function(app){return app.id;});
- _.each(apps, function (app) {
- $('#app-' + app.id).removeClass('hidden');
- });
+ if (apps.length === 0) {
+ $appList.addClass('hidden');
+ $emptyList.removeClass('hidden');
+ $emptyList.removeClass('hidden').find('h2').text(t('settings', 'No apps found for "{query}"', {
+ query: query
+ }));
+ } else {
+ _.each(apps, function (app) {
+ $('#app-' + app.id).removeClass('hidden');
+ });
- $('#searchresults').hide();
+ $('#searchresults').hide();
+ }
+ },
+
+ _onPopState: function(params) {
+ params = _.extend({
+ category: 'enabled'
+ }, params);
+
+ OC.Settings.Apps.loadCategory(params.category);
},
/**
@@ -439,10 +490,15 @@ OC.Settings.Apps = OC.Settings.Apps || {
initialize: function($el) {
OC.Plugins.register('OCA.Search', OC.Settings.Apps.Search);
OC.Settings.Apps.loadCategories();
+ OC.Util.History.addOnPopStateHandler(_.bind(this._onPopState, this));
$(document).on('click', 'ul#apps-categories li', function () {
var categoryId = $(this).data('categoryId');
OC.Settings.Apps.loadCategory(categoryId);
+ OC.Util.History.pushState({
+ category: categoryId
+ });
+ $('#searchbox').val('');
});
$(document).on('click', '.app-description-toggle-show', function () {
@@ -508,7 +564,7 @@ OC.Settings.Apps = OC.Settings.Apps || {
});
$(document).on('click', '#enable-experimental-apps', function () {
- var state = $(this).prop('checked')
+ var state = $(this).prop('checked');
$.ajax(OC.generateUrl('settings/apps/experimental'), {
data: {state: state},
type: 'POST',
diff --git a/settings/templates/apps.php b/settings/templates/apps.php
index 7e6c151fa65..bb01d991e5e 100644
--- a/settings/templates/apps.php
+++ b/settings/templates/apps.php
@@ -24,7 +24,7 @@ script(
?>
<script id="categories-template" type="text/x-handlebars-template">
{{#each this}}
- <li id="app-category-{{id}}" data-category-id="{{id}}" tabindex="0">
+ <li id="app-category-{{ident}}" data-category-id="{{ident}}" tabindex="0">
<a>{{displayName}}</a>
</li>
{{/each}}
@@ -127,7 +127,7 @@ script(
</div>
</script>
-<div id="app-navigation" class="icon-loading">
+<div id="app-navigation" class="icon-loading" data-category="<?php p($_['category']);?>">
<ul id="apps-categories">
</ul>
diff --git a/settings/tests/js/appsSpec.js b/settings/tests/js/appsSpec.js
index 907d441ff4d..d2ca1fb5c8b 100644
--- a/settings/tests/js/appsSpec.js
+++ b/settings/tests/js/appsSpec.js
@@ -24,6 +24,7 @@ describe('OC.Settings.Apps tests', function() {
beforeEach(function() {
var $el = $('<div id="apps-list"></div>' +
+ '<div id="apps-list-empty" class="hidden"></div>' +
'<div id="app-template">' +
// dummy template for testing
'<div id="app-{{id}}" data-id="{{id}}" class="section">{{name}}</div>' +
@@ -59,22 +60,33 @@ describe('OC.Settings.Apps tests', function() {
beforeEach(function() {
loadApps([
- {id: 'appone', name: 'App One', description: 'The first app'},
- {id: 'apptwo', name: 'App Two', description: 'The second app'},
- {id: 'appthree', name: 'App Three', description: 'Third app'},
- {id: 'somestuff', name: 'Some Stuff', description: 'whatever'}
+ {id: 'appone', name: 'App One', description: 'The first app', author: 'author1', level: 200},
+ {id: 'apptwo', name: 'App Two', description: 'The second app', author: 'author2', level: 100},
+ {id: 'appthree', name: 'App Three', description: 'Third app', author: 'author3', level: 0},
+ {id: 'somestuff', name: 'Some Stuff', description: 'whatever', author: 'author4', level: 0}
]);
});
- it('does not filter when no query passed', function() {
- Apps.filter('');
- expect(getResultsFromDom().length).toEqual(4);
- });
it('returns no results when query does not match anything', function() {
+ expect(getResultsFromDom().length).toEqual(4);
+ expect($('#apps-list:not(.hidden)').length).toEqual(1);
+ expect($('#apps-list-empty:not(.hidden)').length).toEqual(0);
+
Apps.filter('absurdity');
expect(getResultsFromDom().length).toEqual(0);
+ expect($('#apps-list:not(.hidden)').length).toEqual(0);
+ expect($('#apps-list-empty:not(.hidden)').length).toEqual(1);
+
+ Apps.filter('');
+ expect(getResultsFromDom().length).toEqual(4);
+ expect($('#apps-list:not(.hidden)').length).toEqual(1);
+ expect($('#apps-list-empty:not(.hidden)').length).toEqual(0);
+ expect(getResultsFromDom().length).toEqual(4);
});
it('returns relevant results when query matches name', function() {
+ expect($('#apps-list:not(.hidden)').length).toEqual(1);
+ expect($('#apps-list-empty:not(.hidden)').length).toEqual(0);
+
var results;
Apps.filter('app');
results = getResultsFromDom();
@@ -82,6 +94,9 @@ describe('OC.Settings.Apps tests', function() {
expect(results[0]).toEqual('appone');
expect(results[1]).toEqual('apptwo');
expect(results[2]).toEqual('appthree');
+
+ expect($('#apps-list:not(.hidden)').length).toEqual(1);
+ expect($('#apps-list-empty:not(.hidden)').length).toEqual(0);
});
it('returns relevant result when query matches name', function() {
var results;
@@ -97,6 +112,45 @@ describe('OC.Settings.Apps tests', function() {
expect(results.length).toEqual(1);
expect(results[0]).toEqual('somestuff');
});
+ it('returns relevant results when query matches author name', function() {
+ var results;
+ Apps.filter('author');
+ results = getResultsFromDom();
+ expect(results.length).toEqual(4);
+ expect(results[0]).toEqual('appone');
+ expect(results[1]).toEqual('apptwo');
+ expect(results[2]).toEqual('appthree');
+ expect(results[3]).toEqual('somestuff');
+ });
+ it('returns relevant result when query matches author name', function() {
+ var results;
+ Apps.filter('thor3');
+ results = getResultsFromDom();
+ expect(results.length).toEqual(1);
+ expect(results[0]).toEqual('appthree');
+ });
+ it('returns relevant result when query matches level name', function() {
+ var results;
+ Apps.filter('Offic');
+ results = getResultsFromDom();
+ expect(results.length).toEqual(1);
+ expect(results[0]).toEqual('appone');
+ });
+ it('returns relevant result when query matches level name', function() {
+ var results;
+ Apps.filter('Appro');
+ results = getResultsFromDom();
+ expect(results.length).toEqual(1);
+ expect(results[0]).toEqual('apptwo');
+ });
+ it('returns relevant result when query matches level name', function() {
+ var results;
+ Apps.filter('Exper');
+ results = getResultsFromDom();
+ expect(results.length).toEqual(2);
+ expect(results[0]).toEqual('appthree');
+ expect(results[1]).toEqual('somestuff');
+ });
});
describe('loading categories', function() {
diff --git a/tests/settings/controller/AppSettingsControllerTest.php b/tests/settings/controller/AppSettingsControllerTest.php
index d6379deb9c8..09595d05661 100644
--- a/tests/settings/controller/AppSettingsControllerTest.php
+++ b/tests/settings/controller/AppSettingsControllerTest.php
@@ -132,10 +132,12 @@ class AppSettingsControllerTest extends TestCase {
$expected = [
[
'id' => 0,
+ 'ident' => 'enabled',
'displayName' => 'Enabled',
],
[
'id' => 1,
+ 'ident' => 'disabled',
'displayName' => 'Not enabled',
],
];
@@ -157,27 +159,33 @@ class AppSettingsControllerTest extends TestCase {
$expected = [
[
'id' => 0,
+ 'ident' => 'enabled',
'displayName' => 'Enabled',
],
[
'id' => 1,
+ 'ident' => 'disabled',
'displayName' => 'Not enabled',
],
[
'id' => 0,
+ 'ident' => 'tools',
'displayName' => 'Tools',
],
[
'id' => 1,
- 'displayName' => 'Awesome Games',
+ 'ident' => 'games',
+ 'displayName' => 'Games',
],
[
'id' => 2,
- 'displayName' => 'PIM',
+ 'ident' => 'productivity',
+ 'displayName' => 'Productivity',
],
[
'id' => 3,
- 'displayName' => 'Papershop',
+ 'ident' => 'multimedia',
+ 'displayName' => 'Multimedia',
],
];
@@ -201,9 +209,9 @@ class AppSettingsControllerTest extends TestCase {
->will($this->returnValue(
[
'ownCloud Tools',
- 'Awesome Games',
- 'ownCloud PIM',
- 'Papershop',
+ 'Games',
+ 'ownCloud Productivity',
+ 'Multimedia',
]
));
@@ -223,9 +231,28 @@ class AppSettingsControllerTest extends TestCase {
$policy = new ContentSecurityPolicy();
$policy->addAllowedImageDomain('https://apps.owncloud.com');
- $expected = new TemplateResponse('settings', 'apps', ['experimentalEnabled' => false], 'user');
+ $expected = new TemplateResponse('settings', 'apps', ['experimentalEnabled' => false, 'category' => 'enabled'], 'user');
$expected->setContentSecurityPolicy($policy);
$this->assertEquals($expected, $this->appSettingsController->viewApps());
}
+
+ public function testViewAppsNotEnabled() {
+ $this->config
+ ->expects($this->once())
+ ->method('getSystemValue')
+ ->with('appstore.experimental.enabled', false);
+ $this->navigationManager
+ ->expects($this->once())
+ ->method('setActiveEntry')
+ ->with('core_apps');
+
+ $policy = new ContentSecurityPolicy();
+ $policy->addAllowedImageDomain('https://apps.owncloud.com');
+
+ $expected = new TemplateResponse('settings', 'apps', ['experimentalEnabled' => false, 'category' => 'disabled'], 'user');
+ $expected->setContentSecurityPolicy($policy);
+
+ $this->assertEquals($expected, $this->appSettingsController->viewApps('disabled'));
+ }
}