Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,24 @@ curl -H "OCS-APIRequest: true" \
<name>Homepage</name>
<url>https://localhost/index.php</url>
<lang>en</lang>
<icon>external.svg</icon>
<type>link</type>
<icon>https://localhost/external.svg</icon>
</element>
</data>
</ocs>
```

#### Explanation

| Field | Type | Description |
| ----- | ------ | ---------------------------------------- |
| id | int | Numeric identifier of the site |
| name | string | Name of the site, ready to use |
| url | string | URL that should be framed/linked to |
| lang | string | Language code for which this link is valid (empty string means all languages) |
| type | string | Can be one of `link`, `settings` or `quota`; see [this issue](https://github.com/nextcloud/external/issues/7) for details |
| icon | string | Full URL of the icon that should be shown next to the name of the link |

### Capability

The app registers a capability, so clients can check that before making the actual OCS request:
Expand Down
4 changes: 4 additions & 0 deletions img/settings.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 15 additions & 7 deletions js/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,27 @@
return currentValue === itemValue;
});

Handlebars.registerHelper('getIcons', function() {
return OCA.External.App.availableIcons;
});

Handlebars.registerHelper('getLanguages', function() {
return OCA.External.App.availableLanguages;
});

Handlebars.registerHelper('getTypes', function() {
return OCA.External.App.availableTypes;
});

Handlebars.registerHelper('getIcons', function() {
return OCA.External.App.availableIcons;
});

OCA.External.Models = OCA.External.Models || {};

OCA.External.Models.Site = Backbone.Model.extend({
defaults: {
name: '',
url: '',
icon: '',
lang: ''
lang: '',
type: 'link',
icon: 'external.svg'
},

parse: function(response) {
Expand Down Expand Up @@ -87,6 +92,7 @@
$('#loading_sites').removeClass('icon-loading-small');
self.availableIcons = response.ocs.data.icons;
self.availableLanguages = response.ocs.data.languages;
self.availableTypes = response.ocs.data.types;

if (response.ocs.data.sites.length === 0) {
var $el = $(self._compiledTemplate({
Expand All @@ -105,7 +111,8 @@

var $el = $(self._compiledTemplate({
id: 'undefined',
icon: 'external.svg'
icon: 'external.svg',
type: 'link'
}));
self._attachEvents($el);
self.$list.append($el);
Expand Down Expand Up @@ -157,6 +164,7 @@
name: $site.find('.site-name').val(),
url: $site.find('.site-url').val(),
lang: $site.find('.site-lang').val(),
type: $site.find('.site-type').val(),
icon: $site.find('.site-icon').val()
};

Expand Down
5 changes: 5 additions & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public function registerNavigationEntries() {
$sites = $sitesManager->getSitesByLanguage($server->getL10NFactory()->findLanguage());

foreach ($sites as $id => $site) {
if ($site['type'] !== SitesManager::LINK && $site['type'] !== SitesManager::SETTING) {
continue;
}

$server->getNavigationManager()->add(function() use ($site, $server) {
$url = $server->getURLGenerator();

Expand All @@ -58,6 +62,7 @@ public function registerNavigationEntries() {
'order' => 80 + $site['id'],
'href' => $url->linkToRoute('external.page.showPage', ['id'=> $site['id']]),
'icon' => $image,
'type' => $site['type'],
'name' => $site['name'],
];
});
Expand Down
22 changes: 18 additions & 4 deletions lib/Controller/APIController.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

use OCA\External\Exceptions\IconNotFoundException;
use OCA\External\Exceptions\InvalidNameException;
use OCA\External\Exceptions\InvalidTypeException;
use OCA\External\Exceptions\InvalidURLException;
use OCA\External\Exceptions\LanguageNotFoundException;
use OCA\External\Exceptions\SiteNotFoundException;
Expand Down Expand Up @@ -90,29 +91,39 @@ public function getAdmin() {
$languages = $this->sitesManager->getAvailableLanguages();
array_unshift($languages, ['code' => '', 'name' => $this->l->t('All languages')]);

$types = [
['type' => SitesManager::LINK, 'name' => $this->l->t('Normal')],
['type' => SitesManager::SETTING, 'name' => $this->l->t('Setting')],
['type' => SitesManager::QUOTA, 'name' => $this->l->t('Quota')],
];

return new DataResponse([
'sites' => array_values($this->sitesManager->getSites()),
'icons' => $icons,
'languages' => $languages,
'types' => $types,
]);
}

/**
* @param string $name
* @param string $url
* @param string $lang
* @param string $type
* @param string $icon
* @return DataResponse
*/
public function add($name, $url, $lang, $icon) {
public function add($name, $url, $lang, $type, $icon) {
try {
return new DataResponse($this->sitesManager->addSite($name, $url, $lang, $icon));
return new DataResponse($this->sitesManager->addSite($name, $url, $lang, $type, $icon));
} catch (InvalidNameException $e) {
return new DataResponse($this->l->t('The given name is invalid'), Http::STATUS_BAD_REQUEST);
} catch (InvalidURLException $e) {
return new DataResponse($this->l->t('The given url is invalid'), Http::STATUS_BAD_REQUEST);
} catch (LanguageNotFoundException $e) {
return new DataResponse($this->l->t('The given language does not exist'), Http::STATUS_BAD_REQUEST);
} catch (InvalidTypeException $e) {
return new DataResponse($this->l->t('The given type is invalid'), Http::STATUS_BAD_REQUEST);
} catch (IconNotFoundException $e) {
return new DataResponse($this->l->t('The given icon does not exist'), Http::STATUS_BAD_REQUEST);
}
Expand All @@ -123,12 +134,13 @@ public function add($name, $url, $lang, $icon) {
* @param string $name
* @param string $url
* @param string $lang
* @param string $type
* @param string $icon
* @return DataResponse
*/
public function update($id, $name, $url, $lang, $icon) {
public function update($id, $name, $url, $lang, $type, $icon) {
try {
return new DataResponse($this->sitesManager->updateSite($id, $name, $url, $lang, $icon));
return new DataResponse($this->sitesManager->updateSite($id, $name, $url, $lang, $type, $icon));
} catch (SiteNotFoundException $e) {
return new DataResponse($this->l->t('The site does not exist'), Http::STATUS_NOT_FOUND);
} catch (InvalidNameException $e) {
Expand All @@ -137,6 +149,8 @@ public function update($id, $name, $url, $lang, $icon) {
return new DataResponse($this->l->t('The given url is invalid'), Http::STATUS_BAD_REQUEST);
} catch (LanguageNotFoundException $e) {
return new DataResponse($this->l->t('The given language does not exist'), Http::STATUS_BAD_REQUEST);
} catch (InvalidTypeException $e) {
return new DataResponse($this->l->t('The given type is invalid'), Http::STATUS_BAD_REQUEST);
} catch (IconNotFoundException $e) {
return new DataResponse($this->l->t('The given icon does not exist'), Http::STATUS_BAD_REQUEST);
}
Expand Down
24 changes: 24 additions & 0 deletions lib/Exceptions/InvalidTypeException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
/**
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\External\Exceptions;

class InvalidTypeException extends \UnexpectedValueException {}
46 changes: 40 additions & 6 deletions lib/SitesManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

use OCA\External\Exceptions\IconNotFoundException;
use OCA\External\Exceptions\InvalidNameException;
use OCA\External\Exceptions\InvalidTypeException;
use OCA\External\Exceptions\InvalidURLException;
use OCA\External\Exceptions\LanguageNotFoundException;
use OCA\External\Exceptions\SiteNotFoundException;
Expand All @@ -33,6 +34,10 @@

class SitesManager {

const LINK = 'link';
const SETTING = 'settings';
const QUOTA = 'quota';

/** @var IConfig */
protected $config;

Expand Down Expand Up @@ -96,21 +101,40 @@ public function getSites() {
return $this->getSitesFromOldConfig($sites);
}

$sites = array_map([$this, 'fillSiteArray'], $sites);

return $sites;
}

/**
* Adds default values for new attributes of sites
* @param array $site
* @return array
*/
protected function fillSiteArray(array $site) {
return array_merge([
'icon' => 'external.svg',
'lang' => '',
'type' => self::LINK,
],
$site
);
}

/**
* @param string $name
* @param string $url
* @param string $lang
* @param string $type
* @param string $icon
* @return array
* @throws InvalidNameException
* @throws InvalidURLException
* @throws LanguageNotFoundException
* @throws InvalidTypeException
* @throws IconNotFoundException
*/
public function addSite($name, $url, $lang, $icon) {
public function addSite($name, $url, $lang, $type, $icon) {
$id = 1 + (int) $this->config->getAppValue('external', 'max_site', 0);

if ($name === '') {
Expand All @@ -136,6 +160,10 @@ public function addSite($name, $url, $lang, $icon) {
}
}

if (!in_array($type, [self::LINK, self::SETTING, self::QUOTA], true)) {
throw new InvalidTypeException();
}

$icons = $this->getAvailableIcons();
if ($icon === '') {
$icon = 'external.svg';
Expand All @@ -150,6 +178,7 @@ public function addSite($name, $url, $lang, $icon) {
'name' => $name,
'url' => $url,
'lang' => $lang,
'type' => $type,
'icon' => $icon,
];
$this->config->setAppValue('external', 'sites', json_encode($sites));
Expand All @@ -163,15 +192,17 @@ public function addSite($name, $url, $lang, $icon) {
* @param string $name
* @param string $url
* @param string $lang
* @param string $type
* @param string $icon
* @return array
* @throws SiteNotFoundException
* @throws InvalidNameException
* @throws InvalidURLException
* @throws LanguageNotFoundException
* @throws InvalidTypeException
* @throws IconNotFoundException
*/
public function updateSite($id, $name, $url, $lang, $icon) {
public function updateSite($id, $name, $url, $lang, $type, $icon) {
$sites = $this->getSites();
if (!isset($sites[$id])) {
throw new SiteNotFoundException();
Expand Down Expand Up @@ -200,6 +231,10 @@ public function updateSite($id, $name, $url, $lang, $icon) {
}
}

if (!in_array($type, [self::LINK, self::SETTING, self::QUOTA], true)) {
throw new InvalidTypeException();
}

$icons = $this->getAvailableIcons();
if ($icon === '') {
$icon = 'external.svg';
Expand All @@ -213,6 +248,7 @@ public function updateSite($id, $name, $url, $lang, $icon) {
'name' => $name,
'url' => $url,
'lang' => $lang,
'type' => $type,
'icon' => $icon,
];
$this->config->setAppValue('external', 'sites', json_encode($sites));
Expand Down Expand Up @@ -242,14 +278,12 @@ protected function getSitesFromOldConfig($sites) {

/** @var array[] $sites */
foreach ($sites as $id => $site) {
$fixedSites[$id + 1] = [
$fixedSites[$id + 1] = $this->fillSiteArray([
'id' => $id + 1,
'name' => $site[0],
'url' => $site[1],
// TODO when php7+ is supported: 'icon' => $site[2] ?? 'external.svg',
'icon' => isset($site[2]) ? $site[2] : 'external.svg',
'lang' => '',
];
]);
}

$this->config->setAppValue('external', 'sites', json_encode($fixedSites));
Expand Down
9 changes: 9 additions & 0 deletions templates/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@
{{/if}}
{{/each}}
</select>
<select class="site-type trigger-save">
{{#each (getTypes type)}}
{{#if (isSelected type ../type)}}
<option value="{{type}}" selected="selected">{{name}}</option>
{{else}}
<option value="{{type}}">{{name}}</option>
{{/if}}
{{/each}}
</select>
<img class="svg action delete-button" src="<?php p(image_path('core', 'actions/delete.svg')); ?>" title="<?php p($l->t('Remove site')); ?>" />
<img class="svg action saving hidden" src="<?php p(image_path('core', 'loading-small.gif')); ?>" alt="<?php p($l->t('Saving')); ?>" />
<img class="svg action saved hidden" src="<?php p(image_path('core', 'actions/checkmark-color.svg')); ?>" alt="<?php p($l->t('Saved!')); ?>" />
Expand Down