Merge pull request #14892 from nextcloud/bugfix/noid/collections

Bugfix/noid/collections
This commit is contained in:
Roeland Jago Douma 2019-03-29 10:25:59 +01:00 committed by GitHub
commit fb5eebd33b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 161 additions and 62 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{14:function(e,o,i){"use strict";i.r(o);var n=i(17),l=i(25),r=i(26),s=i.n(r),a=i(27),u={name:"CollaborationView",computed:{fileId:function(){return this.$root.model&&this.$root.model.id?""+this.$root.model.id:null},filename:function(){return this.$root.model&&this.$root.model.name?""+this.$root.model.name:""}},components:{CollectionList:i(54).a}},c=i(53),d=Object(c.a)(u,function(){var t=this.$createElement,e=this._self._c||t;return this.fileId?e("collection-list",{attrs:{type:"file",id:this.fileId,name:this.filename}}):this._e()},[],!1,null,null,null).exports;i.d(o,"Vue",function(){return n.a}),i.d(o,"View",function(){return d}), (window.webpackJsonp=window.webpackJsonp||[]).push([[4],{14:function(e,o,i){"use strict";i.r(o);var n=i(17),l=i(25),r=i(26),s=i.n(r),a=i(27),u={name:"CollaborationView",computed:{fileId:function(){return this.$root.model&&this.$root.model.id?""+this.$root.model.id:null},filename:function(){return this.$root.model&&this.$root.model.name?""+this.$root.model.name:""}},components:{CollectionList:i(30).a}},c=i(56),d=Object(c.a)(u,function(){var t=this.$createElement,e=this._self._c||t;return this.fileId?e("collection-list",{attrs:{type:"file",id:this.fileId,name:this.filename}}):this._e()},[],!1,null,null,null).exports;i.d(o,"Vue",function(){return n.a}),i.d(o,"View",function(){return d}),
/* /*
* @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net> * @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
* *

File diff suppressed because one or more lines are too long

View File

@ -27,13 +27,6 @@
<script> <script>
import { CollectionList } from 'nextcloud-vue-collections' import { CollectionList } from 'nextcloud-vue-collections'
/**
* Those translations will be used by the vue component but they should be shipped with the server
* t('files_sharing', 'Add to a collection')
* t('files_sharing', 'Details')
* t('files_sharing', 'Rename collection')
*/
export default { export default {
name: 'CollaborationView', name: 'CollaborationView',
computed: { computed: {

View File

@ -22,6 +22,7 @@ declare(strict_types=1);
namespace OC\Core\Controller; namespace OC\Core\Controller;
use Exception;
use OCP\AppFramework\Http; use OCP\AppFramework\Http;
use OCP\AppFramework\OCSController; use OCP\AppFramework\OCSController;
use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\Http\DataResponse;
@ -30,6 +31,7 @@ use OCP\Collaboration\Resources\ICollection;
use OCP\Collaboration\Resources\IManager; use OCP\Collaboration\Resources\IManager;
use OCP\Collaboration\Resources\IResource; use OCP\Collaboration\Resources\IResource;
use OCP\Collaboration\Resources\ResourceException; use OCP\Collaboration\Resources\ResourceException;
use OCP\ILogger;
use OCP\IRequest; use OCP\IRequest;
use OCP\IUserSession; use OCP\IUserSession;
@ -37,20 +39,23 @@ class CollaborationResourcesController extends OCSController {
/** @var IManager */ /** @var IManager */
private $manager; private $manager;
/** @var IUserSession */ /** @var IUserSession */
private $userSession; private $userSession;
/** @var ILogger */
private $logger;
public function __construct( public function __construct(
string $appName, string $appName,
IRequest $request, IRequest $request,
IManager $manager, IManager $manager,
IUserSession $userSession IUserSession $userSession,
ILogger $logger
) { ) {
parent::__construct($appName, $request); parent::__construct($appName, $request);
$this->manager = $manager; $this->manager = $manager;
$this->userSession = $userSession; $this->userSession = $userSession;
$this->logger = $logger;
} }
/** /**
@ -81,7 +86,7 @@ class CollaborationResourcesController extends OCSController {
return new DataResponse([], Http::STATUS_NOT_FOUND); return new DataResponse([], Http::STATUS_NOT_FOUND);
} }
return new DataResponse($this->prepareCollection($collection)); return $this->respondCollection($collection);
} }
/** /**
@ -97,7 +102,7 @@ class CollaborationResourcesController extends OCSController {
return new DataResponse([], Http::STATUS_NOT_FOUND); return new DataResponse([], Http::STATUS_NOT_FOUND);
} }
return new DataResponse(array_map([$this, 'prepareCollection'], $collections)); return new DataResponse($this->prepareCollections($collections));
} }
/** /**
@ -126,7 +131,7 @@ class CollaborationResourcesController extends OCSController {
} catch (ResourceException $e) { } catch (ResourceException $e) {
} }
return new DataResponse($this->prepareCollection($collection)); return $this->respondCollection($collection);
} }
/** /**
@ -152,7 +157,7 @@ class CollaborationResourcesController extends OCSController {
$collection->removeResource($resource); $collection->removeResource($resource);
return new DataResponse($this->prepareCollection($collection)); return $this->respondCollection($collection);
} }
/** /**
@ -173,7 +178,7 @@ class CollaborationResourcesController extends OCSController {
return new DataResponse([], Http::STATUS_NOT_FOUND); return new DataResponse([], Http::STATUS_NOT_FOUND);
} }
return new DataResponse(array_map([$this, 'prepareCollection'], $resource->getCollections())); return new DataResponse($this->prepareCollections($resource->getCollections()));
} }
/** /**
@ -202,7 +207,7 @@ class CollaborationResourcesController extends OCSController {
$collection = $this->manager->newCollection($name); $collection = $this->manager->newCollection($name);
$collection->addResource($resource); $collection->addResource($resource);
return new DataResponse($this->prepareCollection($collection)); return $this->respondCollection($collection);
} }
/** /**
@ -221,24 +226,65 @@ class CollaborationResourcesController extends OCSController {
$collection->setName($collectionName); $collection->setName($collectionName);
return $this->respondCollection($collection);
}
protected function respondCollection(ICollection $collection): DataResponse {
try {
return new DataResponse($this->prepareCollection($collection)); return new DataResponse($this->prepareCollection($collection));
} catch (CollectionException $e) {
return new DataResponse([], Http::STATUS_NOT_FOUND);
} catch (Exception $e) {
$this->logger->logException($e);
return new DataResponse([], Http::STATUS_INTERNAL_SERVER_ERROR);
}
}
protected function prepareCollections(array $collections): array {
$result = [];
foreach ($collections as $collection) {
try {
$result[] = $this->prepareCollection($collection);
} catch (CollectionException $e) {
} catch (Exception $e) {
$this->logger->logException($e);
}
}
return $result;
} }
protected function prepareCollection(ICollection $collection): array { protected function prepareCollection(ICollection $collection): array {
if (!$collection->canAccess($this->userSession->getUser())) { if (!$collection->canAccess($this->userSession->getUser())) {
return null; throw new CollectionException('Can not access collection');
} }
return [ return [
'id' => $collection->getId(), 'id' => $collection->getId(),
'name' => $collection->getName(), 'name' => $collection->getName(),
'resources' => array_values(array_filter(array_map([$this, 'prepareResources'], $collection->getResources()))), 'resources' => $this->prepareResources($collection->getResources()),
]; ];
} }
protected function prepareResources(IResource $resource): ?array { protected function prepareResources(array $resources): ?array {
$result = [];
foreach ($resources as $resource) {
try {
$result[] = $this->prepareResource($resource);
} catch (ResourceException $e) {
} catch (Exception $e) {
$this->logger->logException($e);
}
}
return $result;
}
protected function prepareResource(IResource $resource): array {
if (!$resource->canAccess($this->userSession->getUser())) { if (!$resource->canAccess($this->userSession->getUser())) {
return null; throw new ResourceException('Can not access resource');
} }
return $resource->getRichObject(); return $resource->getRichObject();

View File

@ -220,7 +220,7 @@ function i(e,t){var n=["B","KB","MB","GB","TB"],i=e>0?Math.floor(Math.log(e)/Mat
* You should have received a copy of the GNU Affero General Public License * 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/var g={},_={},v={loadScript:function(e,t){var n=e+t;return g.hasOwnProperty(n)?Promise.resolve():(g[n]=!0,new Promise(function(n,i){var r=OC.filePath(e,"js",t),s=document.createElement("script");s.src=r,s.setAttribute("nonce",btoa(OC.requestToken)),s.onload=function(){return n()},s.onerror=function(){return i("Failed to load script from ".concat(r))},document.head.appendChild(s)}))},loadStylesheet:function(e,t){var n=e+t;return _.hasOwnProperty(n)?Promise.resolve():(_[n]=!0,new Promise(function(n,i){var r=OC.filePath(e,"css",t),s=document.createElement("link");s.href=r,s.type="text/css",s.rel="stylesheet",s.onload=function(){return n()},s.onerror=function(){return i("Failed to load stylesheet from ".concat(r))},document.head.appendChild(s)}))}},y={},b={registerType:function(e,t){y[e]=t},trigger:function(e){return y[e].action()},getTypes:function(){return Object.keys(y)},getIcon:function(e){return y[e].typeIconClass||""},getLabel:function(e){return t("files_sharing","Link to a {label}",{label:y[e].typeString||e},1)},getLink:function(e,t){return void 0!==y[e]?y[e].link(t):""}},w=i(3),k=i.n(w),M=i(8);function x(e){var n=(e=e||{}).dismiss||{};u.a.ajax({type:"GET",url:e.url||M.a.linkToOCS("core",2)+"whatsnew?format=json",success:e.success||function(e,i,r){!function(e,n,i,r){if(console.debug("querying Whats New data was successful: "+n),console.debug(e),200!==i.status)return;var s,o,a,l,u=document.createElement("div");u.classList.add("popovermenu","open","whatsNewPopover","menu-left");var c=document.createElement("ul");for(var d in s=document.createElement("li"),(o=document.createElement("span")).className="menuitem",(a=document.createElement("span")).innerText=t("core","New in")+" "+e.ocs.data.product,a.className="caption",o.appendChild(a),(l=document.createElement("span")).className="icon-close",l.onclick=function(){A(e.ocs.data.version,r)},o.appendChild(l),s.appendChild(o),c.appendChild(s),e.ocs.data.whatsNew.regular){var h=e.ocs.data.whatsNew.regular[d];s=document.createElement("li"),(o=document.createElement("span")).className="menuitem",(l=document.createElement("span")).className="icon-checkmark",o.appendChild(l),(a=document.createElement("p")).innerHTML=k.a.escape(h),o.appendChild(a),s.appendChild(o),c.appendChild(s)}k.a.isUndefined(e.ocs.data.changelogURL)||(s=document.createElement("li"),(o=document.createElement("a")).href=e.ocs.data.changelogURL,o.rel="noreferrer noopener",o.target="_blank",(l=document.createElement("span")).className="icon-link",o.appendChild(l),(a=document.createElement("span")).innerText=t("core","View changelog"),o.appendChild(a),s.appendChild(o),c.appendChild(s));u.appendChild(c),document.body.appendChild(u)}(e,i,r,n)},error:e.error||L})}function A(e,t){t=t||{},u.a.ajax({type:"POST",url:t.url||M.a.linkToOCS("core",2)+"whatsnew",data:{version:encodeURIComponent(e)},success:t.success||D,error:t.error||T}),u()(".whatsNewPopover").remove()}function L(e,t,n){console.debug("querying Whats New Data resulted in an error: "+t+n),console.debug(e)}function D(e){}function T(e){console.debug("dismissing Whats New data resulted in an error: "+e)}n.a={AppConfig:a,Comments:r,InitialState:s,Loader:v,WhatsNew:o,Collaboration:b}},function(e,t,n){ */var g={},_={},v={loadScript:function(e,t){var n=e+t;return g.hasOwnProperty(n)?Promise.resolve():(g[n]=!0,new Promise(function(n,i){var r=OC.filePath(e,"js",t),s=document.createElement("script");s.src=r,s.setAttribute("nonce",btoa(OC.requestToken)),s.onload=function(){return n()},s.onerror=function(){return i("Failed to load script from ".concat(r))},document.head.appendChild(s)}))},loadStylesheet:function(e,t){var n=e+t;return _.hasOwnProperty(n)?Promise.resolve():(_[n]=!0,new Promise(function(n,i){var r=OC.filePath(e,"css",t),s=document.createElement("link");s.href=r,s.type="text/css",s.rel="stylesheet",s.onload=function(){return n()},s.onerror=function(){return i("Failed to load stylesheet from ".concat(r))},document.head.appendChild(s)}))}},y={},b={registerType:function(e,t){y[e]=t},trigger:function(e){return y[e].action()},getTypes:function(){return Object.keys(y)},getIcon:function(e){return y[e].typeIconClass||""},getLabel:function(e){return t("core","Link to a {label}",{label:y[e].typeString||e},1)},getLink:function(e,t){return void 0!==y[e]?y[e].link(t):""}},w=i(3),k=i.n(w),M=i(8);function x(e){var n=(e=e||{}).dismiss||{};u.a.ajax({type:"GET",url:e.url||M.a.linkToOCS("core",2)+"whatsnew?format=json",success:e.success||function(e,i,r){!function(e,n,i,r){if(console.debug("querying Whats New data was successful: "+n),console.debug(e),200!==i.status)return;var s,o,a,l,u=document.createElement("div");u.classList.add("popovermenu","open","whatsNewPopover","menu-left");var c=document.createElement("ul");for(var d in s=document.createElement("li"),(o=document.createElement("span")).className="menuitem",(a=document.createElement("span")).innerText=t("core","New in")+" "+e.ocs.data.product,a.className="caption",o.appendChild(a),(l=document.createElement("span")).className="icon-close",l.onclick=function(){A(e.ocs.data.version,r)},o.appendChild(l),s.appendChild(o),c.appendChild(s),e.ocs.data.whatsNew.regular){var h=e.ocs.data.whatsNew.regular[d];s=document.createElement("li"),(o=document.createElement("span")).className="menuitem",(l=document.createElement("span")).className="icon-checkmark",o.appendChild(l),(a=document.createElement("p")).innerHTML=k.a.escape(h),o.appendChild(a),s.appendChild(o),c.appendChild(s)}k.a.isUndefined(e.ocs.data.changelogURL)||(s=document.createElement("li"),(o=document.createElement("a")).href=e.ocs.data.changelogURL,o.rel="noreferrer noopener",o.target="_blank",(l=document.createElement("span")).className="icon-link",o.appendChild(l),(a=document.createElement("span")).innerText=t("core","View changelog"),o.appendChild(a),s.appendChild(o),c.appendChild(s));u.appendChild(c),document.body.appendChild(u)}(e,i,r,n)},error:e.error||L})}function A(e,t){t=t||{},u.a.ajax({type:"POST",url:t.url||M.a.linkToOCS("core",2)+"whatsnew",data:{version:encodeURIComponent(e)},success:t.success||D,error:t.error||T}),u()(".whatsNewPopover").remove()}function L(e,t,n){console.debug("querying Whats New Data resulted in an error: "+t+n),console.debug(e)}function D(e){}function T(e){console.debug("dismissing Whats New data resulted in an error: "+e)}n.a={AppConfig:a,Comments:r,InitialState:s,Loader:v,WhatsNew:o,Collaboration:b}},function(e,t,n){
/*! /*!
* clipboard.js v2.0.4 * clipboard.js v2.0.4
* https://zenorocha.github.io/clipboard.js * https://zenorocha.github.io/clipboard.js

File diff suppressed because one or more lines are too long

View File

@ -32,6 +32,17 @@
**/ **/
let types = {}; let types = {};
/**
* Those translations will be used by the vue component but they should be shipped with the server
* t('core', 'Add to a collection')
* t('core', 'Show details')
* t('core', 'Hide details')
* t('core', 'Rename collection')
* t('core', 'Failed to rename collection')
* t('core', 'Failed to create collection')
* t('core', 'Failed to add resource to collection')
*/
export default { export default {
/** /**
* *
@ -51,7 +62,7 @@ export default {
return types[type].typeIconClass || ''; return types[type].typeIconClass || '';
}, },
getLabel(type) { getLabel(type) {
return t('files_sharing', 'Link to a {label}', { label: types[type].typeString || type }, 1) return t('core', 'Link to a {label}', { label: types[type].typeString || type }, 1)
}, },
getLink(type, id) { getLink(type, id) {
/* TODO: Allow action to be executed instead of href as well */ /* TODO: Allow action to be executed instead of href as well */

View File

@ -138,11 +138,15 @@ class Manager implements IManager {
$query->expr()->eq('a.user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR)) $query->expr()->eq('a.user_id', $query->createNamedParameter($userId, IQueryBuilder::PARAM_STR))
) )
) )
->where($query->expr()->iLike('c.name', $query->createNamedParameter($filter, IQueryBuilder::PARAM_STR))) ->where($query->expr()->eq('a.access', $query->createNamedParameter(1, IQueryBuilder::PARAM_INT)))
->andWhere($query->expr()->eq('a.access', $query->createNamedParameter(1, IQueryBuilder::PARAM_INT)))
->orderBy('c.id') ->orderBy('c.id')
->setMaxResults($limit) ->setMaxResults($limit)
->setFirstResult($start); ->setFirstResult($start);
if ($filter !== '') {
$query->where($query->expr()->iLike('c.name', $query->createNamedParameter('%' . $this->connection->escapeLikeParameter($filter) . '%')));
}
$result = $query->execute(); $result = $query->execute();
$collections = []; $collections = [];
@ -158,7 +162,7 @@ class Manager implements IManager {
$result->closeCursor(); $result->closeCursor();
if (empty($collections) && $foundResults === $limit) { if (empty($collections) && $foundResults === $limit) {
$this->searchCollections($user, $filter, $limit, $start + $limit); return $this->searchCollections($user, $filter, $limit, $start + $limit);
} }
return $collections; return $collections;

13
package-lock.json generated
View File

@ -4812,10 +4812,11 @@
} }
}, },
"nextcloud-vue-collections": { "nextcloud-vue-collections": {
"version": "0.2.0", "version": "0.3.0",
"resolved": "https://registry.npmjs.org/nextcloud-vue-collections/-/nextcloud-vue-collections-0.2.0.tgz", "resolved": "https://registry.npmjs.org/nextcloud-vue-collections/-/nextcloud-vue-collections-0.3.0.tgz",
"integrity": "sha512-LDbJyUZffu8ZIkkXAMXkfqkUK36GaUiuS4IdgoOLe/z9prV/Iic7uwrDME015FsCv9GmfheOs7cfiU6xBIidGA==", "integrity": "sha512-XW95X75XF4fxL9HBNPf4tsPbSjjtFzdCGz8rlh67upA8QBbaLkn9cEiveORlpgBviVPuiCVLQqVfxOWbsZ+dAw==",
"requires": { "requires": {
"lodash": "^4.17.11",
"nextcloud-axios": "^0.1.2", "nextcloud-axios": "^0.1.2",
"nextcloud-vue": "^0.9.0", "nextcloud-vue": "^0.9.0",
"v-tooltip": "^2.0.0-rc.33", "v-tooltip": "^2.0.0-rc.33",
@ -4825,9 +4826,9 @@
}, },
"dependencies": { "dependencies": {
"nextcloud-vue": { "nextcloud-vue": {
"version": "0.9.1", "version": "0.9.5",
"resolved": "https://registry.npmjs.org/nextcloud-vue/-/nextcloud-vue-0.9.1.tgz", "resolved": "https://registry.npmjs.org/nextcloud-vue/-/nextcloud-vue-0.9.5.tgz",
"integrity": "sha512-8Lmout8Y6+zNPHqZ8rV7GcuKRbFpM8EserkvhkXAJYymq9mblz2NkfmOzhOGxhRICfPHnZ/xFUTxUuaSus4p+Q==", "integrity": "sha512-JWioquKIHnmt2O+8eS+7zd5Pg7DuouKKQlVBoLlm7bOPFTZuhn53B3lYiOnL8N/91ba8RnffHmDixz33m7/s8w==",
"requires": { "requires": {
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
"md5": "^2.2.1", "md5": "^2.2.1",

View File

@ -44,7 +44,7 @@
"nextcloud-axios": "^0.1.3", "nextcloud-axios": "^0.1.3",
"nextcloud-password-confirmation": "^0.4.1", "nextcloud-password-confirmation": "^0.4.1",
"nextcloud-vue": "^0.8.0", "nextcloud-vue": "^0.8.0",
"nextcloud-vue-collections": "^0.2.0", "nextcloud-vue-collections": "^0.3.0",
"snap.js": "^2.0.9", "snap.js": "^2.0.9",
"strengthify": "git+https://github.com/MorrisJobke/strengthify.git#0.5.8", "strengthify": "git+https://github.com/MorrisJobke/strengthify.git#0.5.8",
"underscore": "^1.9.1", "underscore": "^1.9.1",