diff options
Diffstat (limited to 'apps')
53 files changed, 792 insertions, 393 deletions
diff --git a/apps/comments/.l10nignore b/apps/comments/.l10nignore new file mode 100644 index 00000000000..8b832897e3f --- /dev/null +++ b/apps/comments/.l10nignore @@ -0,0 +1,2 @@ +# compiled vue templates +js/templates.js diff --git a/apps/comments/js/commentsmodifymenu.js b/apps/comments/js/commentsmodifymenu.js index 4b17cbbfbf0..fd1e3d80bd0 100644 --- a/apps/comments/js/commentsmodifymenu.js +++ b/apps/comments/js/commentsmodifymenu.js @@ -10,20 +10,6 @@ /* global Handlebars */ (function() { - var TEMPLATE_MENU = - '<ul>' + - '{{#each items}}' + - '<li>' + - '<a href="#" class="menuitem action {{name}} permanent" data-action="{{name}}">' + - '{{#if iconClass}}' + - '<span class="icon {{iconClass}}"></span>' + - '{{else}}' + - '<span class="no-icon"></span>' + - '{{/if}}' + - '<span>{{displayName}}</span>' + - '</li>' + - '{{/each}}' + - '</ul>'; /** * Construct a new CommentsModifyMenuinstance @@ -52,8 +38,6 @@ 'click a.action': '_onClickAction' }, - template: Handlebars.compile(TEMPLATE_MENU), - /** * Event handler whenever an action has been clicked within the menu * @@ -74,7 +58,7 @@ * Renders the menu with the currently set items */ render: function() { - this.$el.html(this.template({ + this.$el.html(OCA.Comments.Templates['commentsmodifymenu']({ items: this._scopes })); }, @@ -121,4 +105,4 @@ OCA.Comments = OCA.Comments || {}; OCA.Comments.CommentsModifyMenu = CommentsModifyMenu; -})(OC, OCA);
\ No newline at end of file +})(OC, OCA); diff --git a/apps/comments/js/filesplugin.js b/apps/comments/js/filesplugin.js index 8c5762065a1..939edc8c695 100644 --- a/apps/comments/js/filesplugin.js +++ b/apps/comments/js/filesplugin.js @@ -16,11 +16,6 @@ PROPERTY_COMMENTS_UNREAD: '{' + OC.Files.Client.NS_OWNCLOUD + '}comments-unread' }); - var TEMPLATE_COMMENTS_UNREAD = - '<a class="action action-comment permanent" title="{{countMessage}}" href="#">' + - '<img class="svg" src="{{iconUrl}}"/>' + - '</a>'; - OCA.Comments = _.extend({}, OCA.Comments); if (!OCA.Comments) { /** @@ -39,10 +34,7 @@ ], _formatCommentCount: function(count) { - if (!this._commentsUnreadTemplate) { - this._commentsUnreadTemplate = Handlebars.compile(TEMPLATE_COMMENTS_UNREAD); - } - return this._commentsUnreadTemplate({ + return OCA.Comments.Templates['filesplugin']({ count: count, countMessage: n('comments', '%n unread comment', '%n unread comments', count), iconUrl: OC.imagePath('core', 'actions/comment') diff --git a/apps/comments/js/templates.js b/apps/comments/js/templates.js index a5706baa27e..26ca658c772 100644 --- a/apps/comments/js/templates.js +++ b/apps/comments/js/templates.js @@ -46,6 +46,33 @@ templates['comment'] = template({"1":function(container,depth0,helpers,partials, + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isLong : depth0),{"name":"if","hash":{},"fn":container.program(11, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "</li>\n"; },"useData":true}); +templates['commentsmodifymenu'] = template({"1":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return " <li>\n <a href=\"#\" class=\"menuitem action " + + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + + " permanent\" data-action=\"" + + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + + "\">\n" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.iconClass : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.program(4, data, 0),"data":data})) != null ? stack1 : "") + + " <span>" + + alias4(((helper = (helper = helpers.displayName || (depth0 != null ? depth0.displayName : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"displayName","hash":{},"data":data}) : helper))) + + "</span>\n </a>\n </li>\n"; +},"2":function(container,depth0,helpers,partials,data) { + var helper; + + return " <span class=\"icon " + + container.escapeExpression(((helper = (helper = helpers.iconClass || (depth0 != null ? depth0.iconClass : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"iconClass","hash":{},"data":data}) : helper))) + + "\"></span>\n"; +},"4":function(container,depth0,helpers,partials,data) { + return " <span class=\"no-icon\"></span>\n"; +},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var stack1; + + return "<ul>\n" + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.items : depth0),{"name":"each","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "</ul>\n"; +},"useData":true}); templates['edit_comment'] = template({"1":function(container,depth0,helpers,partials,data) { var helper; @@ -75,6 +102,15 @@ templates['edit_comment'] = template({"1":function(container,depth0,helpers,part + alias4(((helper = (helper = helpers.tag || (depth0 != null ? depth0.tag : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"tag","hash":{},"data":data}) : helper))) + ">\n"; },"useData":true}); +templates['filesplugin'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return "<a class=\"action action-comment permanent\" title=\"" + + alias4(((helper = (helper = helpers.countMessage || (depth0 != null ? depth0.countMessage : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"countMessage","hash":{},"data":data}) : helper))) + + "\" href=\"#\">\n <img class=\"svg\" src=\"" + + alias4(((helper = (helper = helpers.iconUrl || (depth0 != null ? depth0.iconUrl : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"iconUrl","hash":{},"data":data}) : helper))) + + "\"/>\n</a>\n"; +},"useData":true}); templates['view'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; diff --git a/apps/comments/js/templates/commentsmodifymenu.handlebars b/apps/comments/js/templates/commentsmodifymenu.handlebars new file mode 100644 index 00000000000..28f6ffcdde6 --- /dev/null +++ b/apps/comments/js/templates/commentsmodifymenu.handlebars @@ -0,0 +1,14 @@ +<ul> + {{#each items}} + <li> + <a href="#" class="menuitem action {{name}} permanent" data-action="{{name}}"> + {{#if iconClass}} + <span class="icon {{iconClass}}"></span> + {{else}} + <span class="no-icon"></span> + {{/if}} + <span>{{displayName}}</span> + </a> + </li> + {{/each}} +</ul> diff --git a/apps/comments/js/templates/filesplugin.handlebars b/apps/comments/js/templates/filesplugin.handlebars new file mode 100644 index 00000000000..8f3699380be --- /dev/null +++ b/apps/comments/js/templates/filesplugin.handlebars @@ -0,0 +1,3 @@ +<a class="action action-comment permanent" title="{{countMessage}}" href="#"> + <img class="svg" src="{{iconUrl}}"/> +</a> diff --git a/apps/dav/composer/composer/autoload_classmap.php b/apps/dav/composer/composer/autoload_classmap.php index 8b266c156f3..b03e866ab54 100644 --- a/apps/dav/composer/composer/autoload_classmap.php +++ b/apps/dav/composer/composer/autoload_classmap.php @@ -35,6 +35,7 @@ return array( 'OCA\\DAV\\CalDAV\\CalendarObject' => $baseDir . '/../lib/CalDAV/CalendarObject.php', 'OCA\\DAV\\CalDAV\\CalendarRoot' => $baseDir . '/../lib/CalDAV/CalendarRoot.php', 'OCA\\DAV\\CalDAV\\InvitationResponse\\InvitationResponseServer' => $baseDir . '/../lib/CalDAV/InvitationResponse/InvitationResponseServer.php', + 'OCA\\DAV\\CalDAV\\Outbox' => $baseDir . '/../lib/CalDAV/Outbox.php', 'OCA\\DAV\\CalDAV\\Plugin' => $baseDir . '/../lib/CalDAV/Plugin.php', 'OCA\\DAV\\CalDAV\\Principal\\Collection' => $baseDir . '/../lib/CalDAV/Principal/Collection.php', 'OCA\\DAV\\CalDAV\\Principal\\User' => $baseDir . '/../lib/CalDAV/Principal/User.php', diff --git a/apps/dav/composer/composer/autoload_static.php b/apps/dav/composer/composer/autoload_static.php index 09eb4d257cc..0d4c8801382 100644 --- a/apps/dav/composer/composer/autoload_static.php +++ b/apps/dav/composer/composer/autoload_static.php @@ -50,6 +50,7 @@ class ComposerStaticInitDAV 'OCA\\DAV\\CalDAV\\CalendarObject' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarObject.php', 'OCA\\DAV\\CalDAV\\CalendarRoot' => __DIR__ . '/..' . '/../lib/CalDAV/CalendarRoot.php', 'OCA\\DAV\\CalDAV\\InvitationResponse\\InvitationResponseServer' => __DIR__ . '/..' . '/../lib/CalDAV/InvitationResponse/InvitationResponseServer.php', + 'OCA\\DAV\\CalDAV\\Outbox' => __DIR__ . '/..' . '/../lib/CalDAV/Outbox.php', 'OCA\\DAV\\CalDAV\\Plugin' => __DIR__ . '/..' . '/../lib/CalDAV/Plugin.php', 'OCA\\DAV\\CalDAV\\Principal\\Collection' => __DIR__ . '/..' . '/../lib/CalDAV/Principal/Collection.php', 'OCA\\DAV\\CalDAV\\Principal\\User' => __DIR__ . '/..' . '/../lib/CalDAV/Principal/User.php', diff --git a/apps/dav/lib/CalDAV/CalendarHome.php b/apps/dav/lib/CalDAV/CalendarHome.php index 3e645db459f..6700b1b2496 100644 --- a/apps/dav/lib/CalDAV/CalendarHome.php +++ b/apps/dav/lib/CalDAV/CalendarHome.php @@ -29,7 +29,6 @@ use Sabre\CalDAV\Backend\NotificationSupport; use Sabre\CalDAV\Backend\SchedulingSupport; use Sabre\CalDAV\Backend\SubscriptionSupport; use Sabre\CalDAV\Schedule\Inbox; -use Sabre\CalDAV\Schedule\Outbox; use Sabre\CalDAV\Subscriptions\Subscription; use Sabre\DAV\Exception\NotFound; use Sabre\DAV\Exception\MethodNotAllowed; @@ -81,7 +80,7 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome { if ($this->caldavBackend instanceof SchedulingSupport) { $objects[] = new Inbox($this->caldavBackend, $this->principalInfo['uri']); - $objects[] = new Outbox($this->principalInfo['uri']); + $objects[] = new Outbox($this->config, $this->principalInfo['uri']); } // We're adding a notifications node, if it's supported by the backend. @@ -108,7 +107,7 @@ class CalendarHome extends \Sabre\CalDAV\CalendarHome { return new Inbox($this->caldavBackend, $this->principalInfo['uri']); } if ($name === 'outbox' && $this->caldavBackend instanceof SchedulingSupport) { - return new Outbox($this->principalInfo['uri']); + return new Outbox($this->config, $this->principalInfo['uri']); } if ($name === 'notifications' && $this->caldavBackend instanceof NotificationSupport) { return new \Sabre\CalDAv\Notifications\Collection($this->caldavBackend, $this->principalInfo['uri']); diff --git a/apps/dav/lib/CalDAV/Outbox.php b/apps/dav/lib/CalDAV/Outbox.php new file mode 100644 index 00000000000..8f0c57c7890 --- /dev/null +++ b/apps/dav/lib/CalDAV/Outbox.php @@ -0,0 +1,132 @@ +<?php +/** + * @copyright Copyright (c) 2018, Georg Ehrke + * + * @author Georg Ehrke <oc.list@georgehrke.com> + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ +namespace OCA\DAV\CalDAV; + +use OCP\IConfig; +use Sabre\CalDAV\Plugin as CalDAVPlugin; + +/** + * Class Outbox + * + * @package OCA\DAV\CalDAV + */ +class Outbox extends \Sabre\CalDAV\Schedule\Outbox { + + /** @var IConfig */ + private $config; + + /** @var null|bool */ + private $disableFreeBusy = null; + + /** + * Outbox constructor. + * + * @param IConfig $config + * @param string $principalUri + */ + public function __construct(IConfig $config, string $principalUri) { + parent::__construct($principalUri); + $this->config = $config; + } + + /** + * Returns a list of ACE's for this node. + * + * Each ACE has the following properties: + * * 'privilege', a string such as {DAV:}read or {DAV:}write. These are + * currently the only supported privileges + * * 'principal', a url to the principal who owns the node + * * 'protected' (optional), indicating that this ACE is not allowed to + * be updated. + * + * @return array + */ + function getACL() { + // getACL is called so frequently that we cache the config result + if ($this->disableFreeBusy === null) { + $this->disableFreeBusy = ($this->config->getAppValue('dav', 'disableFreeBusy', 'no') === 'yes'); + } + + $commonAcl = [ + [ + 'privilege' => '{DAV:}read', + 'principal' => $this->getOwner(), + 'protected' => true, + ], + [ + 'privilege' => '{DAV:}read', + 'principal' => $this->getOwner() . '/calendar-proxy-read', + 'protected' => true, + ], + [ + 'privilege' => '{DAV:}read', + 'principal' => $this->getOwner() . '/calendar-proxy-write', + 'protected' => true, + ], + ]; + + // schedule-send is an aggregate privilege for: + // - schedule-send-invite + // - schedule-send-reply + // - schedule-send-freebusy + // + // If FreeBusy is disabled, we have to remove the latter privilege + + if ($this->disableFreeBusy) { + return array_merge($commonAcl, [ + [ + 'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send-invite', + 'principal' => $this->getOwner(), + 'protected' => true, + ], + [ + 'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send-invite', + 'principal' => $this->getOwner() . '/calendar-proxy-write', + 'protected' => true, + ], + [ + 'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send-reply', + 'principal' => $this->getOwner(), + 'protected' => true, + ], + [ + 'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send-reply', + 'principal' => $this->getOwner() . '/calendar-proxy-write', + 'protected' => true, + ], + ]); + } + + return array_merge($commonAcl, [ + [ + 'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send', + 'principal' => $this->getOwner(), + 'protected' => true, + ], + [ + 'privilege' => '{' . CalDAVPlugin::NS_CALDAV . '}schedule-send', + 'principal' => $this->getOwner() . '/calendar-proxy-write', + 'protected' => true, + ], + ]); + } +} diff --git a/apps/dav/lib/Connector/Sabre/Principal.php b/apps/dav/lib/Connector/Sabre/Principal.php index feba4d04624..cbfa1bc83e0 100644 --- a/apps/dav/lib/Connector/Sabre/Principal.php +++ b/apps/dav/lib/Connector/Sabre/Principal.php @@ -212,10 +212,9 @@ class Principal implements BackendInterface { protected function searchUserPrincipals(array $searchProperties, $test = 'allof') { $results = []; - // If sharing is disabled (or FreeBusy was disabled on purpose), return the empty array + // If sharing is disabled, return the empty array $shareAPIEnabled = $this->shareManager->shareApiEnabled(); - $disableFreeBusy = $this->config->getAppValue('dav', 'disableFreeBusy', $shareAPIEnabled ? 'no' : 'yes'); - if ($disableFreeBusy === 'yes') { + if (!$shareAPIEnabled) { return []; } @@ -298,10 +297,9 @@ class Principal implements BackendInterface { * @return string */ function findByUri($uri, $principalPrefix) { - // If sharing is disabled (or FreeBusy was disabled on purpose), return the empty array + // If sharing is disabled, return the empty array $shareAPIEnabled = $this->shareManager->shareApiEnabled(); - $disableFreeBusy = $this->config->getAppValue('dav', 'disableFreeBusy', $shareAPIEnabled ? 'no' : 'yes'); - if ($disableFreeBusy === 'yes') { + if (!$shareAPIEnabled) { return null; } diff --git a/apps/dav/lib/Migration/BuildCalendarSearchIndex.php b/apps/dav/lib/Migration/BuildCalendarSearchIndex.php index da4b4f4fe84..22274e36c6b 100644 --- a/apps/dav/lib/Migration/BuildCalendarSearchIndex.php +++ b/apps/dav/lib/Migration/BuildCalendarSearchIndex.php @@ -70,7 +70,7 @@ class BuildCalendarSearchIndex implements IRepairStep { } $query = $this->db->getQueryBuilder(); - $query->select($query->createFunction('MAX(id)')) + $query->select($query->createFunction('MAX(' . $query->getColumnName('id') . ')')) ->from('calendarobjects'); $maxId = (int)$query->execute()->fetchColumn(); diff --git a/apps/dav/tests/unit/CalDAV/OutboxTest.php b/apps/dav/tests/unit/CalDAV/OutboxTest.php new file mode 100644 index 00000000000..be5dc33fc61 --- /dev/null +++ b/apps/dav/tests/unit/CalDAV/OutboxTest.php @@ -0,0 +1,123 @@ +<?php +/** + * @copyright Copyright (c) 2018, Georg Ehrke + * + * @author Georg Ehrke <oc.list@georgehrke.com> + * + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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, version 3, + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +namespace OCA\DAV\Tests\unit\CalDAV; + +use OCA\DAV\CalDAV\Outbox; +use OCP\IConfig; +use Test\TestCase; + +class OutboxTest extends TestCase { + + /** @var IConfig */ + private $config; + + /** @var Outbox */ + private $outbox; + + protected function setUp() { + parent::setUp(); + + $this->config = $this->createMock(IConfig::class); + $this->outbox = new Outbox($this->config, 'user-principal-123'); + } + + public function testGetACLFreeBusyEnabled() { + $this->config->expects($this->once()) + ->method('getAppValue') + ->with('dav', 'disableFreeBusy', 'no') + ->will($this->returnValue('no')); + + $this->assertEquals([ + [ + 'privilege' => '{DAV:}read', + 'principal' => 'user-principal-123', + 'protected' => true, + ], + [ + 'privilege' => '{DAV:}read', + 'principal' => 'user-principal-123/calendar-proxy-read', + 'protected' => true, + ], + [ + 'privilege' => '{DAV:}read', + 'principal' => 'user-principal-123/calendar-proxy-write', + 'protected' => true, + ], + [ + 'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send', + 'principal' => 'user-principal-123', + 'protected' => true, + ], + [ + 'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send', + 'principal' => 'user-principal-123/calendar-proxy-write', + 'protected' => true, + ], + ], $this->outbox->getACL()); + } + + public function testGetACLFreeBusyDisabled() { + $this->config->expects($this->once()) + ->method('getAppValue') + ->with('dav', 'disableFreeBusy', 'no') + ->will($this->returnValue('yes')); + + $this->assertEquals([ + [ + 'privilege' => '{DAV:}read', + 'principal' => 'user-principal-123', + 'protected' => true, + ], + [ + 'privilege' => '{DAV:}read', + 'principal' => 'user-principal-123/calendar-proxy-read', + 'protected' => true, + ], + [ + 'privilege' => '{DAV:}read', + 'principal' => 'user-principal-123/calendar-proxy-write', + 'protected' => true, + ], + [ + 'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send-invite', + 'principal' => 'user-principal-123', + 'protected' => true, + ], + [ + 'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send-invite', + 'principal' => 'user-principal-123/calendar-proxy-write', + 'protected' => true, + ], + [ + 'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send-reply', + 'principal' => 'user-principal-123', + 'protected' => true, + ], + [ + 'privilege' => '{urn:ietf:params:xml:ns:caldav}schedule-send-reply', + 'principal' => 'user-principal-123/calendar-proxy-write', + 'protected' => true, + ], + ], $this->outbox->getACL()); + } +} diff --git a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php index 7e82c446760..01907c85836 100644 --- a/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php +++ b/apps/dav/tests/unit/Connector/Sabre/PrincipalTest.php @@ -283,37 +283,26 @@ class PrincipalTest extends TestCase { /** * @dataProvider searchPrincipalsDataProvider */ - public function testSearchPrincipals($disableFreeBusy, $sharingEnabled, $disableFBSharingCombination, $groupsOnly, $result) { + public function testSearchPrincipals($sharingEnabled, $groupsOnly, $result) { $this->shareManager->expects($this->once()) ->method('shareAPIEnabled') ->will($this->returnValue($sharingEnabled)); - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('dav', 'disableFreeBusy', $sharingEnabled ? 'no' : 'yes') - ->will($this->returnValue($disableFBSharingCombination)); - - if ($disableFreeBusy === 'no') { - if ($sharingEnabled) { - $this->shareManager->expects($this->once()) - ->method('shareWithGroupMembersOnly') - ->will($this->returnValue($groupsOnly)); - - if ($groupsOnly) { - $user = $this->createMock(IUser::class); - $this->userSession->expects($this->once()) - ->method('getUser') - ->will($this->returnValue($user)); - - $this->groupManager->expects($this->at(0)) - ->method('getUserGroupIds') - ->with($user) - ->will($this->returnValue(['group1', 'group2'])); - } - } else { - $this->shareManager->expects($this->never()) - ->method('shareWithGroupMembersOnly'); - $this->groupManager->expects($this->never()) - ->method($this->anything()); + + if ($sharingEnabled) { + $this->shareManager->expects($this->once()) + ->method('shareWithGroupMembersOnly') + ->will($this->returnValue($groupsOnly)); + + if ($groupsOnly) { + $user = $this->createMock(IUser::class); + $this->userSession->expects($this->once()) + ->method('getUser') + ->will($this->returnValue($user)); + + $this->groupManager->expects($this->at(0)) + ->method('getUserGroupIds') + ->with($user) + ->will($this->returnValue(['group1', 'group2'])); } } else { $this->shareManager->expects($this->never()) @@ -322,57 +311,42 @@ class PrincipalTest extends TestCase { ->method($this->anything()); } - $user2 = $this->createMock(IUser::class); $user2->method('getUID')->will($this->returnValue('user2')); $user3 = $this->createMock(IUser::class); $user3->method('getUID')->will($this->returnValue('user3')); - if ($disableFreeBusy === 'no') { - if ($sharingEnabled) { - $this->userManager->expects($this->at(0)) - ->method('getByEmail') - ->with('user') - ->will($this->returnValue([$user2, $user3])); - } else { - $this->userManager->expects($this->never()) - ->method('getByEmail'); - } + if ($sharingEnabled) { + $this->userManager->expects($this->at(0)) + ->method('getByEmail') + ->with('user') + ->will($this->returnValue([$user2, $user3])); } else { $this->userManager->expects($this->never()) ->method('getByEmail'); } - if ($disableFreeBusy === 'no') { - if ($sharingEnabled && $groupsOnly) { - $this->groupManager->expects($this->at(1)) - ->method('getUserGroupIds') - ->with($user2) - ->will($this->returnValue(['group1', 'group3'])); - $this->groupManager->expects($this->at(2)) - ->method('getUserGroupIds') - ->with($user3) - ->will($this->returnValue(['group3', 'group4'])); - } - } else { - $this->groupManager->expects($this->never()) - ->method('getUserGroupIds'); - $this->groupManager->expects($this->never()) - ->method('getUserGroupIds'); + if ($sharingEnabled && $groupsOnly) { + $this->groupManager->expects($this->at(1)) + ->method('getUserGroupIds') + ->with($user2) + ->will($this->returnValue(['group1', 'group3'])); + $this->groupManager->expects($this->at(2)) + ->method('getUserGroupIds') + ->with($user3) + ->will($this->returnValue(['group3', 'group4'])); } + $this->assertEquals($result, $this->connector->searchPrincipals('principals/users', ['{http://sabredav.org/ns}email-address' => 'user'])); } public function searchPrincipalsDataProvider() { return [ - ['yes', true, 'yes', false, []], - ['no', true, 'no', false, ['principals/users/user2', 'principals/users/user3']], - ['yes', true, 'yes', true, []], - ['no', true, 'no', true, ['principals/users/user2']], - ['yes', false, 'yes', false, []], - ['no', false, 'yes', false, []], + [true, false, ['principals/users/user2', 'principals/users/user3']], + [true, true, ['principals/users/user2']], + [false, false, []], ]; } @@ -380,10 +354,6 @@ class PrincipalTest extends TestCase { $this->shareManager->expects($this->once()) ->method('shareApiEnabled') ->will($this->returnValue(false)); - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('dav', 'disableFreeBusy', 'yes') - ->will($this->returnValue('yes')); $this->assertEquals(null, $this->connector->findByUri('mailto:user@foo.com', 'principals/users')); } @@ -391,21 +361,11 @@ class PrincipalTest extends TestCase { /** * @dataProvider findByUriWithGroupRestrictionDataProvider */ - public function testFindByUriWithGroupRestriction($disableFreeBusy, $uri, $email, $expects) { + public function testFindByUriWithGroupRestriction($uri, $email, $expects) { $this->shareManager->expects($this->once()) ->method('shareApiEnabled') ->will($this->returnValue(true)); - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('dav', 'disableFreeBusy', 'no') - ->will($this->returnValue($disableFreeBusy)); - if ($disableFreeBusy === 'yes') { - $this->shareManager->expects($this->never()) - ->method('shareWithGroupMembersOnly'); - $this->userSession->expects($this->never()) - ->method('getUser'); - } else { $this->shareManager->expects($this->once()) ->method('shareWithGroupMembersOnly') ->will($this->returnValue(true)); @@ -441,39 +401,25 @@ class PrincipalTest extends TestCase { ->with($user3) ->will($this->returnValue(['group3', 'group3'])); } - } $this->assertEquals($expects, $this->connector->findByUri($uri, 'principals/users')); } public function findByUriWithGroupRestrictionDataProvider() { return [ - ['yes', 'mailto:user2@foo.bar', 'user2@foo.bar', null], - ['no', 'mailto:user2@foo.bar', 'user2@foo.bar', 'principals/users/user2'], - ['yes', 'mailto:user3@foo.bar', 'user3@foo.bar', null], - ['no', 'mailto:user3@foo.bar', 'user3@foo.bar', null], + ['mailto:user2@foo.bar', 'user2@foo.bar', 'principals/users/user2'], + ['mailto:user3@foo.bar', 'user3@foo.bar', null], ]; } /** * @dataProvider findByUriWithoutGroupRestrictionDataProvider */ - public function testFindByUriWithoutGroupRestriction($disableFreeBusy, $uri, $email, $expects) { + public function testFindByUriWithoutGroupRestriction($uri, $email, $expects) { $this->shareManager->expects($this->once()) ->method('shareApiEnabled') ->will($this->returnValue(true)); - $this->config->expects($this->once()) - ->method('getAppValue') - ->with('dav', 'disableFreeBusy', 'no') - ->will($this->returnValue($disableFreeBusy)); - - if ($disableFreeBusy === 'yes') { - $this->shareManager->expects($this->never()) - ->method('shareWithGroupMembersOnly'); - $this->userManager->expects($this->never()) - ->method('getByEmail'); - } else { $this->shareManager->expects($this->once()) ->method('shareWithGroupMembersOnly') ->will($this->returnValue(false)); @@ -487,17 +433,14 @@ class PrincipalTest extends TestCase { ->method('getByEmail') ->with($email) ->will($this->returnValue([$email === 'user2@foo.bar' ? $user2 : $user3])); - } $this->assertEquals($expects, $this->connector->findByUri($uri, 'principals/users')); } public function findByUriWithoutGroupRestrictionDataProvider() { return [ - ['yes', 'mailto:user2@foo.bar', 'user2@foo.bar', null], - ['yes', 'mailto:user3@foo.bar', 'user3@foo.bar', null], - ['no', 'mailto:user2@foo.bar', 'user2@foo.bar', 'principals/users/user2'], - ['no', 'mailto:user3@foo.bar', 'user3@foo.bar', 'principals/users/user3'], + ['mailto:user2@foo.bar', 'user2@foo.bar', 'principals/users/user2'], + ['mailto:user3@foo.bar', 'user3@foo.bar', 'principals/users/user3'], ]; } } diff --git a/apps/files/.l10nignore b/apps/files/.l10nignore new file mode 100644 index 00000000000..8b832897e3f --- /dev/null +++ b/apps/files/.l10nignore @@ -0,0 +1,2 @@ +# compiled vue templates +js/templates.js diff --git a/apps/files/js/detailsview.js b/apps/files/js/detailsview.js index 2a5d589a730..675e380b52b 100644 --- a/apps/files/js/detailsview.js +++ b/apps/files/js/detailsview.js @@ -102,7 +102,7 @@ this.$el.insertAfter($('#app-content')); } else { if ($appSidebar[0] !== this.el) { - $appSidebar.replaceWith(this.$el) + $appSidebar.replaceWith(this.$el); } } diff --git a/apps/files/js/fileactionsmenu.js b/apps/files/js/fileactionsmenu.js index b8022f13734..c3cd8bf8b70 100644 --- a/apps/files/js/fileactionsmenu.js +++ b/apps/files/js/fileactionsmenu.js @@ -10,24 +10,6 @@ (function() { - var TEMPLATE_MENU = - '<ul>' + - '{{#each items}}' + - '<li>' + - '<a href="#" class="menuitem action action-{{nameLowerCase}} permanent" data-action="{{name}}">' + - '{{#if icon}}<img class="icon" src="{{icon}}"/>' + - '{{else}}'+ - '{{#if iconClass}}' + - '<span class="icon {{iconClass}}"></span>' + - '{{else}}' + - '<span class="no-icon"></span>' + - '{{/if}}' + - '{{/if}}' + - '<span>{{displayName}}</span></a>' + - '</li>' + - '{{/each}}' + - '</ul>'; - /** * Construct a new FileActionsMenu instance * @constructs FileActionsMenu @@ -49,10 +31,7 @@ }, template: function(data) { - if (!OCA.Files.FileActionsMenu._TEMPLATE) { - OCA.Files.FileActionsMenu._TEMPLATE = Handlebars.compile(TEMPLATE_MENU); - } - return OCA.Files.FileActionsMenu._TEMPLATE(data); + return OCA.Files.Templates['fileactionsmenu'](data); }, /** diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index 2089361b6ec..0a6620ab22c 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -310,10 +310,10 @@ breadcrumbOptions.onDrop = _.bind(this._onDropOnBreadCrumb, this); breadcrumbOptions.onOver = function() { self.$el.find('td.filename.ui-droppable').droppable('disable'); - } + }; breadcrumbOptions.onOut = function() { self.$el.find('td.filename.ui-droppable').droppable('enable'); - } + }; } this.breadcrumb = new OCA.Files.BreadCrumb(breadcrumbOptions); diff --git a/apps/files/js/templates.js b/apps/files/js/templates.js index f05959ff985..0511873c8fb 100644 --- a/apps/files/js/templates.js +++ b/apps/files/js/templates.js @@ -81,6 +81,43 @@ templates['file_action_trigger'] = template({"1":function(container,depth0,helpe + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.displayName : depth0),{"name":"if","hash":{},"fn":container.program(8, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + "\n</a>\n"; },"useData":true}); +templates['fileactionsmenu'] = template({"1":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return " <li>\n <a href=\"#\" class=\"menuitem action action-" + + alias4(((helper = (helper = helpers.nameLowerCase || (depth0 != null ? depth0.nameLowerCase : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"nameLowerCase","hash":{},"data":data}) : helper))) + + " permanent\" data-action=\"" + + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + + "\">\n " + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.icon : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.program(4, data, 0),"data":data})) != null ? stack1 : "") + + " <span>" + + alias4(((helper = (helper = helpers.displayName || (depth0 != null ? depth0.displayName : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"displayName","hash":{},"data":data}) : helper))) + + "</span>\n </a>\n </li>\n"; +},"2":function(container,depth0,helpers,partials,data) { + var helper; + + return "<img class=\"icon\" src=\"" + + container.escapeExpression(((helper = (helper = helpers.icon || (depth0 != null ? depth0.icon : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"icon","hash":{},"data":data}) : helper))) + + "\"/>\n"; +},"4":function(container,depth0,helpers,partials,data) { + var stack1; + + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.iconClass : depth0),{"name":"if","hash":{},"fn":container.program(5, data, 0),"inverse":container.program(7, data, 0),"data":data})) != null ? stack1 : ""); +},"5":function(container,depth0,helpers,partials,data) { + var helper; + + return " <span class=\"icon " + + container.escapeExpression(((helper = (helper = helpers.iconClass || (depth0 != null ? depth0.iconClass : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"iconClass","hash":{},"data":data}) : helper))) + + "\"></span>\n"; +},"7":function(container,depth0,helpers,partials,data) { + return " <span class=\"no-icon\"></span>\n"; +},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var stack1; + + return "<ul>\n" + + ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.items : depth0),{"name":"each","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "</ul>\n"; +},"useData":true}); templates['filemultiselectmenu'] = template({"1":function(container,depth0,helpers,partials,data) { var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; diff --git a/apps/files/js/templates/fileactionsmenu.handlebars b/apps/files/js/templates/fileactionsmenu.handlebars new file mode 100644 index 00000000000..d8d1b78fd86 --- /dev/null +++ b/apps/files/js/templates/fileactionsmenu.handlebars @@ -0,0 +1,17 @@ +<ul> + {{#each items}} + <li> + <a href="#" class="menuitem action action-{{nameLowerCase}} permanent" data-action="{{name}}"> + {{#if icon}}<img class="icon" src="{{icon}}"/> + {{else}} + {{#if iconClass}} + <span class="icon {{iconClass}}"></span> + {{else}} + <span class="no-icon"></span> + {{/if}} + {{/if}} + <span>{{displayName}}</span> + </a> + </li> + {{/each}} +</ul> diff --git a/apps/files/tests/js/fileactionsmenuSpec.js b/apps/files/tests/js/fileactionsmenuSpec.js index f171f2848f8..2d31f24a1b3 100644 --- a/apps/files/tests/js/fileactionsmenuSpec.js +++ b/apps/files/tests/js/fileactionsmenuSpec.js @@ -203,7 +203,7 @@ describe('OCA.Files.FileActionsMenu tests', function() { expect(displayNameStub.calledOnce).toEqual(true); expect(displayNameStub.calledWith(menuContext)).toEqual(true); - expect(menu.$el.find('a[data-action=Something]').text()).toEqual('Test'); + expect(menu.$el.find('a[data-action=Something] span:not(.icon)').text()).toEqual('Test'); }); it('uses plain iconClass', function() { fileActions.registerAction({ diff --git a/apps/files_external/.l10nignore b/apps/files_external/.l10nignore new file mode 100644 index 00000000000..3179ed23dd6 --- /dev/null +++ b/apps/files_external/.l10nignore @@ -0,0 +1,2 @@ +# compiled handlebar templates +js/templates.js diff --git a/apps/files_external/js/settings.js b/apps/files_external/js/settings.js index b871fe2f743..2d495281527 100644 --- a/apps/files_external/js/settings.js +++ b/apps/files_external/js/settings.js @@ -10,58 +10,6 @@ (function(){ -// TODO: move to a separate file -var MOUNT_OPTIONS_DROPDOWN_TEMPLATE = - '<div class="popovermenu open">'+ - // FIXME: options are hard-coded for now - ' <ul>'+ - ' <li class="optionRow">'+ - ' <span class="menuitem">'+ - ' <input id="mountOptionsEncrypt" class="checkbox" name="encrypt" type="checkbox" value="true" checked="checked"/>'+ - ' <label for="mountOptionsEncrypt">{{t "files_external" "Enable encryption"}}</label>'+ - ' </span>'+ - ' </li>'+ - ' <li class="optionRow">'+ - ' <span class="menuitem">'+ - ' <input id="mountOptionsPreviews" class="checkbox" name="previews" type="checkbox" value="true" checked="checked"/>'+ - ' <label for="mountOptionsPreviews">{{t "files_external" "Enable previews"}}</label>'+ - ' </span>'+ - ' </li>'+ - ' <li class="optionRow">'+ - ' <span class="menuitem">'+ - ' <input id="mountOptionsSharing" class="checkbox" name="enable_sharing" type="checkbox" value="true"/>'+ - ' <label for="mountOptionsSharing">{{t "files_external" "Enable sharing"}}</label>'+ - ' </span>'+ - ' </li>'+ - ' <li class="optionRow">'+ - ' <span class="menuitem icon-search">'+ - ' <label for="mountOptionsFilesystemCheck">{{t "files_external" "Check for changes"}}</label>'+ - ' <select id="mountOptionsFilesystemCheck" name="filesystem_check_changes" data-type="int">'+ - ' <option value="0">{{t "files_external" "Never"}}</option>'+ - ' <option value="1" selected="selected">{{t "files_external" "Once every direct access"}}</option>'+ - ' </select>'+ - ' </span>'+ - ' </li>'+ - ' <li class="optionRow">'+ - ' <span class="menuitem">'+ - ' <input id="mountOptionsEncoding" class="checkbox" name="encoding_compatibility" type="checkbox" value="true"/>'+ - ' <label for="mountOptionsEncoding">{{mountOptionsEncodingLabel}}</label>'+ - ' </span>'+ - ' </li>'+ - ' <li class="optionRow">' + - ' <span class="menuitem">' + - ' <input id="mountOptionsReadOnly" class="checkbox" name="readonly" type="checkbox" value="true"/>' + - ' <label for="mountOptionsReadOnly">{{t "files_external" "Read only"}}</label>' + - ' </span>' + - ' </li>' + - ' <li class="optionRow persistent">' + - ' <a href="#" class="menuitem remove icon-delete">' + - ' <span>{{t "files_external" "Delete"}}</span>' + - ' </a>' + - ' </li>' + - ' </ul>'+ - '</div>'; - /** * Returns the selection of applicable users in the given configuration row * @@ -514,14 +462,16 @@ MountOptionsDropdown.prototype = { MountOptionsDropdown._last.hide(); } - var template = MountOptionsDropdown._template; - if (!template) { - template = Handlebars.compile(MOUNT_OPTIONS_DROPDOWN_TEMPLATE); - MountOptionsDropdown._template = template; - } - - var $el = $(template({ - mountOptionsEncodingLabel: t('files_external', 'Compatibility with Mac NFD encoding (slow)') + var $el = $(OCA.External.Templates.mountOptionsDropDown({ + mountOptionsEncodingLabel: t('files_external', 'Compatibility with Mac NFD encoding (slow)'), + mountOptionsEncryptLabel: t('files_external', 'Enable encryption'), + mountOptionsPreviewsLabel: t('files_external', 'Enable previews'), + mountOptionsSharingLabel: t('files_external', 'Enable sharing'), + mountOptionsFilesystemCheckLabel: t('files_external', 'Check for changes'), + mountOptionsFilesystemCheckOnce: t('files_external', 'Never'), + mountOptionsFilesystemCheckDA: t('files_external', 'Once every direct access'), + mountOptionsReadOnlyLabel: t('files_external', 'Read only'), + deleteLabel: t('files_external', 'Delete') })); this.$el = $el; diff --git a/apps/files_external/js/statusmanager.js b/apps/files_external/js/statusmanager.js index a65988353af..b8b5e1a9364 100644 --- a/apps/files_external/js/statusmanager.js +++ b/apps/files_external/js/statusmanager.js @@ -392,8 +392,7 @@ OCA.External.StatusManager = { * @param mountData */ showCredentialsDialog: function (mountPoint, mountData) { - var template = Handlebars.compile(OCA.External.StatusManager.credentialsDialogTemplate); - var dialog = $(template({ + var dialog = $(OCA.External.Templates.credentialsDialog({ credentials_text: t('files_external', 'Please enter the credentials for the {mount} mount', { 'mount': mountPoint }), diff --git a/apps/files_external/js/templates.js b/apps/files_external/js/templates.js new file mode 100644 index 00000000000..067b3f5f5d7 --- /dev/null +++ b/apps/files_external/js/templates.js @@ -0,0 +1,37 @@ +(function() { + var template = Handlebars.template, templates = OCA.External.Templates = OCA.External.Templates || {}; +templates['credentialsDialog'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return "<div id=\"files_external_div_form\"><div>\n <div>" + + alias4(((helper = (helper = helpers.credentials_text || (depth0 != null ? depth0.credentials_text : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"credentials_text","hash":{},"data":data}) : helper))) + + "</div>\n <form>\n <input type=\"text\" name=\"username\" placeholder=\"" + + alias4(((helper = (helper = helpers.placeholder_username || (depth0 != null ? depth0.placeholder_username : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"placeholder_username","hash":{},"data":data}) : helper))) + + "\"/>\n <input type=\"password\" name=\"password\" placeholder=\"" + + alias4(((helper = (helper = helpers.placeholder_password || (depth0 != null ? depth0.placeholder_password : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"placeholder_password","hash":{},"data":data}) : helper))) + + "\"/>\n </form>\n </div>\n</div>\n"; +},"useData":true}); +templates['mountOptionsDropDown'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return "<div class=\"popovermenu open\">\n <ul>\n <li class=\"optionRow\">\n <span class=\"menuitem\">\n <input id=\"mountOptionsEncrypt\" class=\"checkbox\" name=\"encrypt\" type=\"checkbox\" value=\"true\" checked=\"checked\"/>\n <label for=\"mountOptionsEncrypt\">" + + alias4(((helper = (helper = helpers.mountOptionsEncryptLabel || (depth0 != null ? depth0.mountOptionsEncryptLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"mountOptionsEncryptLabel","hash":{},"data":data}) : helper))) + + "</label>\n </span>\n </li>\n <li class=\"optionRow\">\n <span class=\"menuitem\">\n <input id=\"mountOptionsPreviews\" class=\"checkbox\" name=\"previews\" type=\"checkbox\" value=\"true\" checked=\"checked\"/>\n <label for=\"mountOptionsPreviews\">" + + alias4(((helper = (helper = helpers.mountOptionsPreviewsLabel || (depth0 != null ? depth0.mountOptionsPreviewsLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"mountOptionsPreviewsLabel","hash":{},"data":data}) : helper))) + + "</label>\n </span>\n </li>\n <li class=\"optionRow\">\n <span class=\"menuitem\">\n <input id=\"mountOptionsSharing\" class=\"checkbox\" name=\"enable_sharing\" type=\"checkbox\" value=\"true\"/>\n <label for=\"mountOptionsSharing\">" + + alias4(((helper = (helper = helpers.mountOptionsSharingLabel || (depth0 != null ? depth0.mountOptionsSharingLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"mountOptionsSharingLabel","hash":{},"data":data}) : helper))) + + "</label>\n </span>\n </li>\n <li class=\"optionRow\">\n <span class=\"menuitem icon-search\">\n <label for=\"mountOptionsFilesystemCheck\">" + + alias4(((helper = (helper = helpers.mountOptionsFilesystemCheckLabel || (depth0 != null ? depth0.mountOptionsFilesystemCheckLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"mountOptionsFilesystemCheckLabel","hash":{},"data":data}) : helper))) + + "</label>\n <select id=\"mountOptionsFilesystemCheck\" name=\"filesystem_check_changes\" data-type=\"int\">\n <option value=\"0\">" + + alias4(((helper = (helper = helpers.mountOptionsFilesystemCheckOnce || (depth0 != null ? depth0.mountOptionsFilesystemCheckOnce : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"mountOptionsFilesystemCheckOnce","hash":{},"data":data}) : helper))) + + "</option>\n <option value=\"1\" selected=\"selected\">" + + alias4(((helper = (helper = helpers.mountOptionsFilesystemCheckDA || (depth0 != null ? depth0.mountOptionsFilesystemCheckDA : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"mountOptionsFilesystemCheckDA","hash":{},"data":data}) : helper))) + + "</option>\n </select>\n </span>\n </li>\n <li class=\"optionRow\">\n <span class=\"menuitem\">\n <input id=\"mountOptionsEncoding\" class=\"checkbox\" name=\"encoding_compatibility\" type=\"checkbox\" value=\"true\"/>\n <label for=\"mountOptionsEncoding\">" + + alias4(((helper = (helper = helpers.mountOptionsEncodingLabel || (depth0 != null ? depth0.mountOptionsEncodingLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"mountOptionsEncodingLabel","hash":{},"data":data}) : helper))) + + "</label>\n </span>\n </li>\n <li class=\"optionRow\">\n <span class=\"menuitem\">\n <input id=\"mountOptionsReadOnly\" class=\"checkbox\" name=\"readonly\" type=\"checkbox\" value=\"true\"/>\n <label for=\"mountOptionsReadOnly\">" + + alias4(((helper = (helper = helpers.mountOptionsReadOnlyLabel || (depth0 != null ? depth0.mountOptionsReadOnlyLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"mountOptionsReadOnlyLabel","hash":{},"data":data}) : helper))) + + "</label>\n </span>\n </li>\n <li class=\"optionRow persistent\">\n <a href=\"#\" class=\"menuitem remove icon-delete\">\n <span>" + + alias4(((helper = (helper = helpers.deleteLabel || (depth0 != null ? depth0.deleteLabel : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"deleteLabel","hash":{},"data":data}) : helper))) + + "</span>\n </a>\n </li>\n </ul>\n</div>\n"; +},"useData":true}); +})();
\ No newline at end of file diff --git a/apps/files_external/js/templates/credentialsDialog.handlebars b/apps/files_external/js/templates/credentialsDialog.handlebars new file mode 100644 index 00000000000..c04ceef096b --- /dev/null +++ b/apps/files_external/js/templates/credentialsDialog.handlebars @@ -0,0 +1,8 @@ +<div id="files_external_div_form"><div> + <div>{{credentials_text}}</div> + <form> + <input type="text" name="username" placeholder="{{placeholder_username}}"/> + <input type="password" name="password" placeholder="{{placeholder_password}}"/> + </form> + </div> +</div> diff --git a/apps/files_external/js/templates/mountOptionsDropDown.handlebars b/apps/files_external/js/templates/mountOptionsDropDown.handlebars new file mode 100644 index 00000000000..09b0d708958 --- /dev/null +++ b/apps/files_external/js/templates/mountOptionsDropDown.handlebars @@ -0,0 +1,48 @@ +<div class="popovermenu open"> + <ul> + <li class="optionRow"> + <span class="menuitem"> + <input id="mountOptionsEncrypt" class="checkbox" name="encrypt" type="checkbox" value="true" checked="checked"/> + <label for="mountOptionsEncrypt">{{mountOptionsEncryptLabel}}</label> + </span> + </li> + <li class="optionRow"> + <span class="menuitem"> + <input id="mountOptionsPreviews" class="checkbox" name="previews" type="checkbox" value="true" checked="checked"/> + <label for="mountOptionsPreviews">{{mountOptionsPreviewsLabel}}</label> + </span> + </li> + <li class="optionRow"> + <span class="menuitem"> + <input id="mountOptionsSharing" class="checkbox" name="enable_sharing" type="checkbox" value="true"/> + <label for="mountOptionsSharing">{{mountOptionsSharingLabel}}</label> + </span> + </li> + <li class="optionRow"> + <span class="menuitem icon-search"> + <label for="mountOptionsFilesystemCheck">{{mountOptionsFilesystemCheckLabel}}</label> + <select id="mountOptionsFilesystemCheck" name="filesystem_check_changes" data-type="int"> + <option value="0">{{mountOptionsFilesystemCheckOnce}}</option> + <option value="1" selected="selected">{{mountOptionsFilesystemCheckDA}}</option> + </select> + </span> + </li> + <li class="optionRow"> + <span class="menuitem"> + <input id="mountOptionsEncoding" class="checkbox" name="encoding_compatibility" type="checkbox" value="true"/> + <label for="mountOptionsEncoding">{{mountOptionsEncodingLabel}}</label> + </span> + </li> + <li class="optionRow"> + <span class="menuitem"> + <input id="mountOptionsReadOnly" class="checkbox" name="readonly" type="checkbox" value="true"/> + <label for="mountOptionsReadOnly">{{mountOptionsReadOnlyLabel}}</label> + </span> + </li> + <li class="optionRow persistent"> + <a href="#" class="menuitem remove icon-delete"> + <span>{{deleteLabel}}</span> + </a> + </li> + </ul> +</div> diff --git a/apps/files_external/list.php b/apps/files_external/list.php index bda484d996e..35ad6e60447 100644 --- a/apps/files_external/list.php +++ b/apps/files_external/list.php @@ -28,6 +28,7 @@ $tmpl = new OCP\Template('files_external', 'list', ''); /* Load Status Manager */ \OCP\Util::addStyle('files_external', 'external'); \OCP\Util::addScript('files_external', 'statusmanager'); +\OCP\Util::addScript('files_external', 'templates.js'); \OCP\Util::addScript('files_external', 'rollingqueue'); OCP\Util::addScript('files_external', 'app'); diff --git a/apps/files_external/templates/settings.php b/apps/files_external/templates/settings.php index b3900aaf93d..1d1fcee1d8a 100644 --- a/apps/files_external/templates/settings.php +++ b/apps/files_external/templates/settings.php @@ -14,7 +14,10 @@ $l->t("Once every direct access"); $l->t('Read only'); - script('files_external', 'settings'); + script('files_external', [ + 'settings', + 'templates' + ]); style('files_external', 'settings'); // load custom JS diff --git a/apps/files_sharing/js/files_drop.js b/apps/files_sharing/js/files_drop.js index 8d1273f1872..d10a61e0dfc 100644 --- a/apps/files_sharing/js/files_drop.js +++ b/apps/files_sharing/js/files_drop.js @@ -9,14 +9,7 @@ */ (function ($) { - var TEMPLATE = - '<li data-toggle="tooltip" title="{{name}}" data-name="{{name}}">' + - '{{#if isUploading}}' + - '<span class="icon-loading-small"></span> {{name}}' + - '{{else}}' + - '<img src="{{iconSrc}}"/> {{name}}' + - '{{/if}}' + - '</li>'; + var Drop = { /** @type {Function} **/ _template: undefined, @@ -130,10 +123,7 @@ * @private */ template: function () { - if (!this._template) { - this._template = Handlebars.compile(TEMPLATE); - } - return this._template; + return OCA.Sharing.Templates['files_drop']; } }; diff --git a/apps/files_sharing/js/sharedfilelist.js b/apps/files_sharing/js/sharedfilelist.js index 3a6de0d5012..19250815bd6 100644 --- a/apps/files_sharing/js/sharedfilelist.js +++ b/apps/files_sharing/js/sharedfilelist.js @@ -232,7 +232,7 @@ promises.push($.ajax(remoteShares)); } if (this._isOverview) { - shares.data.shared_with_me = !shares.data.shared_with_me + shares.data.shared_with_me = !shares.data.shared_with_me; promises.push($.ajax(shares)); } } diff --git a/apps/files_sharing/js/templates.js b/apps/files_sharing/js/templates.js new file mode 100644 index 00000000000..ce7409b4652 --- /dev/null +++ b/apps/files_sharing/js/templates.js @@ -0,0 +1,28 @@ +(function() { + var template = Handlebars.template, templates = OCA.Sharing.Templates = OCA.Sharing.Templates || {}; +templates['files_drop'] = template({"1":function(container,depth0,helpers,partials,data) { + var helper; + + return "\n <span class=\"icon-loading-small\"></span> " + + container.escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"name","hash":{},"data":data}) : helper))) + + "\n"; +},"3":function(container,depth0,helpers,partials,data) { + var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return " <img src=\"" + + alias4(((helper = (helper = helpers.iconSrc || (depth0 != null ? depth0.iconSrc : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"iconSrc","hash":{},"data":data}) : helper))) + + "\"/> " + + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + + "\n"; +},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return "<li data-toggle=\"tooltip\" title=\"" + + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + + "\" data-name=\"" + + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + + "\">\n '" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.isUploading : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.program(3, data, 0),"data":data})) != null ? stack1 : "") + + "</li>\n"; +},"useData":true}); +})();
\ No newline at end of file diff --git a/apps/files_sharing/js/templates/files_drop.handlebars b/apps/files_sharing/js/templates/files_drop.handlebars new file mode 100644 index 00000000000..4dea497f8de --- /dev/null +++ b/apps/files_sharing/js/templates/files_drop.handlebars @@ -0,0 +1,7 @@ +<li data-toggle="tooltip" title="{{name}}" data-name="{{name}}"> + '{{#if isUploading}} + <span class="icon-loading-small"></span> {{name}} + {{else}} + <img src="{{iconSrc}}"/> {{name}} + {{/if}} +</li> diff --git a/apps/files_sharing/lib/Command/CleanupRemoteStorages.php b/apps/files_sharing/lib/Command/CleanupRemoteStorages.php index f269b86ea9f..2175982dfc1 100644 --- a/apps/files_sharing/lib/Command/CleanupRemoteStorages.php +++ b/apps/files_sharing/lib/Command/CleanupRemoteStorages.php @@ -98,7 +98,7 @@ class CleanupRemoteStorages extends Command { public function countFiles($numericId, OutputInterface $output) { $queryBuilder = $this->connection->getQueryBuilder(); - $queryBuilder->select($queryBuilder->createFunction('count(fileid)')) + $queryBuilder->select($queryBuilder->createFunction('COUNT(' . $queryBuilder->getColumnName('fileid') . ')')) ->from('filecache') ->where($queryBuilder->expr()->eq( 'storage', diff --git a/apps/files_sharing/lib/Controller/ShareController.php b/apps/files_sharing/lib/Controller/ShareController.php index 2cc34dde8bb..8e9cc5a9636 100644 --- a/apps/files_sharing/lib/Controller/ShareController.php +++ b/apps/files_sharing/lib/Controller/ShareController.php @@ -387,6 +387,7 @@ class ShareController extends AuthPublicShareController { \OCP\Util::addScript('files', 'file-upload'); \OCP\Util::addStyle('files_sharing', 'publicView'); \OCP\Util::addScript('files_sharing', 'public'); + \OCP\Util::addScript('files_sharing', 'templates'); \OCP\Util::addScript('files_sharing', 'public_note'); \OCP\Util::addScript('files', 'fileactions'); \OCP\Util::addScript('files', 'fileactionsmenu'); diff --git a/apps/files_sharing/lib/SharedStorage.php b/apps/files_sharing/lib/SharedStorage.php index 34a21fcd637..f9c4a85fac6 100644 --- a/apps/files_sharing/lib/SharedStorage.php +++ b/apps/files_sharing/lib/SharedStorage.php @@ -378,10 +378,12 @@ class SharedStorage extends \OC\Files\Storage\Wrapper\Jail implements ISharedSto if (!$storage) { $storage = $this; } + $sourceRoot = $this->getSourceRootInfo(); if ($this->storage instanceof FailedStorage) { return new FailedCache(); } - $this->cache = new \OCA\Files_Sharing\Cache($storage, $this->getSourceRootInfo(), $this->superShare); + + $this->cache = new \OCA\Files_Sharing\Cache($storage, $sourceRoot, $this->superShare); return $this->cache; } diff --git a/apps/files_versions/.l10nignore b/apps/files_versions/.l10nignore new file mode 100644 index 00000000000..8b832897e3f --- /dev/null +++ b/apps/files_versions/.l10nignore @@ -0,0 +1,2 @@ +# compiled vue templates +js/templates.js diff --git a/apps/lookup_server_connector/lib/BackgroundJobs/RetryJob.php b/apps/lookup_server_connector/lib/BackgroundJobs/RetryJob.php index c0fba230a26..5a7212a6522 100644 --- a/apps/lookup_server_connector/lib/BackgroundJobs/RetryJob.php +++ b/apps/lookup_server_connector/lib/BackgroundJobs/RetryJob.php @@ -50,9 +50,15 @@ class RetryJob extends Job { $this->clientService = $clientService; $this->jobList = $jobList; + if ($config->getSystemValue('has_internet_connection', true) === false) { + return; + } + $this->lookupServer = $config->getSystemValue('lookup_server', 'https://lookup.nextcloud.com'); - $this->lookupServer = rtrim($this->lookupServer, '/'); - $this->lookupServer .= '/users'; + if (!empty($this->lookupServer)) { + $this->lookupServer = rtrim($this->lookupServer, '/'); + $this->lookupServer .= '/users'; + } } /** @@ -69,7 +75,7 @@ class RetryJob extends Job { } protected function run($argument) { - if($argument['retryNo'] === 5) { + if ($argument['retryNo'] === 5 || empty($this->lookupServer)) { return; } diff --git a/apps/lookup_server_connector/lib/UpdateLookupServer.php b/apps/lookup_server_connector/lib/UpdateLookupServer.php index ae8fcbd67ca..7902ede8816 100644 --- a/apps/lookup_server_connector/lib/UpdateLookupServer.php +++ b/apps/lookup_server_connector/lib/UpdateLookupServer.php @@ -64,15 +64,25 @@ class UpdateLookupServer { $this->signer = $signer; $this->jobList = $jobList; + if($config->getSystemValue('has_internet_connection', true) === false) { + return; + } + $this->lookupServer = $config->getSystemValue('lookup_server', 'https://lookup.nextcloud.com'); - $this->lookupServer = rtrim($this->lookupServer, '/'); - $this->lookupServer .= '/users'; + if(!empty($this->lookupServer)) { + $this->lookupServer = rtrim($this->lookupServer, '/'); + $this->lookupServer .= '/users'; + } } /** * @param IUser $user */ public function userUpdated(IUser $user) { + if(empty($this->lookupServer)) { + return; + } + $userData = $this->accountManager->getUser($user); $publicData = []; diff --git a/apps/oauth2/.l10nignore b/apps/oauth2/.l10nignore new file mode 100644 index 00000000000..e440b631755 --- /dev/null +++ b/apps/oauth2/.l10nignore @@ -0,0 +1,2 @@ +# compiled vue templates +js/oauth2.js diff --git a/apps/provisioning_api/lib/AppInfo/Application.php b/apps/provisioning_api/lib/AppInfo/Application.php index b7a93d6fb13..7e9e04978fe 100644 --- a/apps/provisioning_api/lib/AppInfo/Application.php +++ b/apps/provisioning_api/lib/AppInfo/Application.php @@ -43,7 +43,7 @@ class Application extends App { return new NewUserMailHelper( $server->query(Defaults::class), $server->getURLGenerator(), - $server->getL10N('settings'), + $server->getL10NFactory(), $server->getMailer(), $server->getSecureRandom(), new TimeFactory(), diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index 9aa32e1186a..27d66a83c81 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -894,16 +894,8 @@ class UsersController extends AUserData { if ($email === '' || $email === null) { throw new OCSException('Email address not available', 101); } - $username = $targetUser->getUID(); - $lang = $this->config->getUserValue($username, 'core', 'lang', 'en'); - if (!$this->l10nFactory->languageExists('settings', $lang)) { - $lang = 'en'; - } - - $l10n = $this->l10nFactory->get('settings', $lang); try { - $this->newUserMailHelper->setL10N($l10n); $emailTemplate = $this->newUserMailHelper->generateTemplate($targetUser, false); $this->newUserMailHelper->sendMail($targetUser, $emailTemplate); } catch(\Exception $e) { diff --git a/apps/provisioning_api/tests/Controller/UsersControllerTest.php b/apps/provisioning_api/tests/Controller/UsersControllerTest.php index adbdb9d8685..57283e11912 100644 --- a/apps/provisioning_api/tests/Controller/UsersControllerTest.php +++ b/apps/provisioning_api/tests/Controller/UsersControllerTest.php @@ -3257,35 +3257,13 @@ class UsersControllerTest extends TestCase { ->expects($this->once()) ->method('getEmailAddress') ->will($this->returnValue('abc@example.org')); - $this->config - ->expects($this->at(0)) - ->method('getUserValue') - ->with('user-id', 'core', 'lang') - ->willReturn('es'); - $l10n = $this->getMockBuilder(IL10N::class) - ->disableOriginalConstructor() - ->getMock(); - $this->l10nFactory - ->expects($this->at(0)) - ->method('languageExists') - ->with('settings', 'es') - ->willReturn(true); - $this->l10nFactory - ->expects($this->at(1)) - ->method('get') - ->with('settings', 'es') - ->willReturn($l10n); $emailTemplate = $this->createMock(IEMailTemplate::class); $this->newUserMailHelper ->expects($this->at(0)) - ->method('setL10N') - ->willReturn($l10n); - $this->newUserMailHelper - ->expects($this->at(1)) ->method('generateTemplate') ->willReturn($emailTemplate); $this->newUserMailHelper - ->expects($this->at(2)) + ->expects($this->at(1)) ->method('sendMail') ->with($targetUser, $emailTemplate); @@ -3327,35 +3305,16 @@ class UsersControllerTest extends TestCase { ->expects($this->once()) ->method('getEmailAddress') ->will($this->returnValue('abc@example.org')); - $this->config - ->expects($this->at(0)) - ->method('getUserValue') - ->with('user-id', 'core', 'lang') - ->willReturn('es'); $l10n = $this->getMockBuilder(IL10N::class) ->disableOriginalConstructor() ->getMock(); - $this->l10nFactory - ->expects($this->at(0)) - ->method('languageExists') - ->with('settings', 'es') - ->willReturn(false); - $this->l10nFactory - ->expects($this->at(1)) - ->method('get') - ->with('settings', 'en') - ->willReturn($l10n); $emailTemplate = $this->createMock(IEMailTemplate::class); $this->newUserMailHelper ->expects($this->at(0)) - ->method('setL10N') - ->willReturn($l10n); - $this->newUserMailHelper - ->expects($this->at(1)) ->method('generateTemplate') ->willReturn($emailTemplate); $this->newUserMailHelper - ->expects($this->at(2)) + ->expects($this->at(1)) ->method('sendMail') ->with($targetUser, $emailTemplate); @@ -3402,35 +3361,13 @@ class UsersControllerTest extends TestCase { ->expects($this->once()) ->method('getEmailAddress') ->will($this->returnValue('abc@example.org')); - $this->config - ->expects($this->at(0)) - ->method('getUserValue') - ->with('user-id', 'core', 'lang') - ->willReturn('es'); - $l10n = $this->getMockBuilder(IL10N::class) - ->disableOriginalConstructor() - ->getMock(); - $this->l10nFactory - ->expects($this->at(0)) - ->method('languageExists') - ->with('settings', 'es') - ->willReturn(true); - $this->l10nFactory - ->expects($this->at(1)) - ->method('get') - ->with('settings', 'es') - ->willReturn($l10n); $emailTemplate = $this->createMock(IEMailTemplate::class); $this->newUserMailHelper ->expects($this->at(0)) - ->method('setL10N') - ->willReturn($l10n); - $this->newUserMailHelper - ->expects($this->at(1)) ->method('generateTemplate') ->willReturn($emailTemplate); $this->newUserMailHelper - ->expects($this->at(2)) + ->expects($this->at(1)) ->method('sendMail') ->with($targetUser, $emailTemplate) ->willThrowException(new \Exception()); diff --git a/apps/theming/lib/Controller/ThemingController.php b/apps/theming/lib/Controller/ThemingController.php index a1fa5e57836..cc8af2cae3e 100644 --- a/apps/theming/lib/Controller/ThemingController.php +++ b/apps/theming/lib/Controller/ThemingController.php @@ -397,6 +397,7 @@ class ThemingController extends Controller { /** * @NoCSRFRequired * @PublicPage + * @NoSameSiteCookieRequired * * @return FileDisplayResponse|NotFoundResponse * @throws NotPermittedException @@ -428,6 +429,7 @@ class ThemingController extends Controller { /** * @NoCSRFRequired * @PublicPage + * @NoSameSiteCookieRequired * * @return DataDownloadResponse */ diff --git a/apps/updatenotification/.l10nignore b/apps/updatenotification/.l10nignore new file mode 100644 index 00000000000..7439adf0658 --- /dev/null +++ b/apps/updatenotification/.l10nignore @@ -0,0 +1,2 @@ +# compiled vue templates +js/updatenotification.js diff --git a/apps/user_ldap/js/wizard/wizardTabAbstractFilter.js b/apps/user_ldap/js/wizard/wizardTabAbstractFilter.js index c9c3aeb241d..0131816e4ee 100644 --- a/apps/user_ldap/js/wizard/wizardTabAbstractFilter.js +++ b/apps/user_ldap/js/wizard/wizardTabAbstractFilter.js @@ -302,7 +302,7 @@ OCA = OCA || {}; if( !view.getFilterItem().$element.val() && view.parsedFilterMode === view.configModel.FILTER_MODE_ASSISTED ) { - view.configModel.requestWizard(view.getFilterItem().keyName) + view.configModel.requestWizard(view.getFilterItem().keyName); } } else if (payload.feature === view.getGroupsItem().featureName) { if(view.manyGroupsSupport && payload.data.length > view._groupElementSwitchThreshold) { diff --git a/apps/user_ldap/lib/Mapping/AbstractMapping.php b/apps/user_ldap/lib/Mapping/AbstractMapping.php index c7d737a7631..c3f09fd6caa 100644 --- a/apps/user_ldap/lib/Mapping/AbstractMapping.php +++ b/apps/user_ldap/lib/Mapping/AbstractMapping.php @@ -311,7 +311,7 @@ abstract class AbstractMapping { */ public function count() { $qb = $this->dbc->getQueryBuilder(); - $query = $qb->select($qb->createFunction('COUNT(`ldap_dn`)')) + $query = $qb->select($qb->createFunction('COUNT(' . $qb->getColumnName('ldap_dn') . ')')) ->from($this->getTableName()); $res = $query->execute(); $count = $res->fetchColumn(); diff --git a/apps/workflowengine/js/admin.js b/apps/workflowengine/js/admin.js index 66e98205db6..d986c5a494a 100644 --- a/apps/workflowengine/js/admin.js +++ b/apps/workflowengine/js/admin.js @@ -108,29 +108,12 @@ */ /** - * @class OCA.WorkflowEngine.TemplateView - * - * a generic template that handles the Handlebars template compile step - * in a method called "template()" - */ - OCA.WorkflowEngine.TemplateView = - OC.Backbone.View.extend({ - _template: null, - template: function(vars) { - if (!this._template) { - this._template = Handlebars.compile($(this.templateId).html()); - } - return this._template(vars); - } - }); - - /** * @class OCA.WorkflowEngine.OperationView * * this creates the view for a single operation */ OCA.WorkflowEngine.OperationView = - OCA.WorkflowEngine.TemplateView.extend({ + OC.Backbone.View.extend({ templateId: '#operation-template', events: { 'change .check-class': 'checkChanged', @@ -150,6 +133,18 @@ errorMessage: '', saving: false, groups: [], + template: function(vars) { + return OCA.WorkflowEngine.Templates['operation'](_.extend( + { + shortRuleDescTXT: t('workflowengine', 'Short rule description'), + addRuleTXT: t('workflowengine', 'Add rule'), + resetTXT: t('workflowengine', 'Reset'), + saveTXT: t('workflowengine', 'Save'), + savingTXT: t('workflowengine', 'Saving…') + }, + vars + )); + }, initialize: function() { // this creates a new copy of the object to definitely have a new reference and being able to reset the model this.originalModel = JSON.parse(JSON.stringify(this.model)); @@ -354,13 +349,21 @@ * this creates the view for configured operations */ OCA.WorkflowEngine.OperationsView = - OCA.WorkflowEngine.TemplateView.extend({ + OC.Backbone.View.extend({ templateId: '#operations-template', collection: null, $el: null, events: { 'click .button-add-operation': 'add' }, + template: function(vars) { + return OCA.WorkflowEngine.Templates['operations'](_.extend( + { + addRuleGroupTXT: t('workflowengine', 'Add rule group') + }, + vars + )); + }, initialize: function(classname) { if (!OCA.WorkflowEngine.availablePlugins.length) { OCA.WorkflowEngine.availablePlugins = OC.Plugins.getPlugins('OCA.WorkflowEngine.CheckPlugins'); diff --git a/apps/workflowengine/js/templates.js b/apps/workflowengine/js/templates.js new file mode 100644 index 00000000000..157d396357d --- /dev/null +++ b/apps/workflowengine/js/templates.js @@ -0,0 +1,109 @@ +(function() { + var template = Handlebars.template, templates = OCA.WorkflowEngine.Templates = OCA.WorkflowEngine.Templates || {}; +templates['operation'] = template({"1":function(container,depth0,helpers,partials,data) { + return " modified"; +},"3":function(container,depth0,helpers,partials,data) { + return " <span class=\"button-delete icon-delete\"></span>\n"; +},"5":function(container,depth0,helpers,partials,data,blockParams,depths) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return " <div class=\"check\" data-id=\"" + + alias4(((helper = (helper = helpers.index || (data && data.index)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"index","hash":{},"data":data}) : helper))) + + "\">\n <select class=\"check-class\">\n" + + ((stack1 = helpers.each.call(alias1,(depths[1] != null ? depths[1].classes : depths[1]),{"name":"each","hash":{},"fn":container.program(6, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " </select>\n <select class=\"check-operator\">\n" + + ((stack1 = helpers.each.call(alias1,(helpers.getOperators || (depth0 && depth0.getOperators) || alias2).call(alias1,(depth0 != null ? depth0["class"] : depth0),{"name":"getOperators","hash":{},"data":data}),{"name":"each","hash":{},"fn":container.program(8, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " </select>\n <input type=\"text\" class=\"check-value\" value=\"" + + alias4(((helper = (helper = helpers.value || (depth0 != null ? depth0.value : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"value","hash":{},"data":data}) : helper))) + + "\">\n <span class=\"button-delete-check icon-delete\"></span>\n </div>\n"; +},"6":function(container,depth0,helpers,partials,data,blockParams,depths) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return " <option value=\"" + + alias4(((helper = (helper = helpers["class"] || (depth0 != null ? depth0["class"] : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"class","hash":{},"data":data}) : helper))) + + "\" " + + ((stack1 = (helpers.selectItem || (depth0 && depth0.selectItem) || alias2).call(alias1,(depth0 != null ? depth0["class"] : depth0),(depths[1] != null ? depths[1]["class"] : depths[1]),{"name":"selectItem","hash":{},"data":data})) != null ? stack1 : "") + + ">" + + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + + "</option>\n"; +},"8":function(container,depth0,helpers,partials,data,blockParams,depths) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression; + + return " <option value=\"" + + alias4(((helper = (helper = helpers.operator || (depth0 != null ? depth0.operator : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"operator","hash":{},"data":data}) : helper))) + + "\" " + + ((stack1 = (helpers.selectItem || (depth0 && depth0.selectItem) || alias2).call(alias1,(depth0 != null ? depth0.operator : depth0),(depths[1] != null ? depths[1].operator : depths[1]),{"name":"selectItem","hash":{},"data":data})) != null ? stack1 : "") + + ">" + + alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper))) + + "</option>\n"; +},"10":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}); + + return ((stack1 = helpers["if"].call(alias1,((stack1 = (depth0 != null ? depth0.operation : depth0)) != null ? stack1.id : stack1),{"name":"if","hash":{},"fn":container.program(11, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " <button class=\"button-save pull-right\">" + + container.escapeExpression(((helper = (helper = helpers.saveTXT || (depth0 != null ? depth0.saveTXT : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(alias1,{"name":"saveTXT","hash":{},"data":data}) : helper))) + + "</button>\n"; +},"11":function(container,depth0,helpers,partials,data) { + var helper; + + return " <button class=\"button-reset pull-right\">" + + container.escapeExpression(((helper = (helper = helpers.resetTXT || (depth0 != null ? depth0.resetTXT : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"resetTXT","hash":{},"data":data}) : helper))) + + "</button>\n"; +},"13":function(container,depth0,helpers,partials,data) { + var helper; + + return " <span class=\"icon-loading-small pull-right\"></span>\n <span class=\"pull-right\">" + + container.escapeExpression(((helper = (helper = helpers.savingTXT || (depth0 != null ? depth0.savingTXT : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"savingTXT","hash":{},"data":data}) : helper))) + + "</span>\n "; +},"15":function(container,depth0,helpers,partials,data) { + var stack1; + + return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.message : depth0),{"name":"if","hash":{},"fn":container.program(16, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : ""); +},"16":function(container,depth0,helpers,partials,data) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}); + + return "\n <span class=\"msg pull-right " + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.errorMessage : depth0),{"name":"if","hash":{},"fn":container.program(17, data, 0),"inverse":container.program(19, data, 0),"data":data})) != null ? stack1 : "") + + "\">\n " + + container.escapeExpression(((helper = (helper = helpers.message || (depth0 != null ? depth0.message : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(alias1,{"name":"message","hash":{},"data":data}) : helper))) + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.errorMessage : depth0),{"name":"if","hash":{},"fn":container.program(21, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\n </span>\n "; +},"17":function(container,depth0,helpers,partials,data) { + return "error"; +},"19":function(container,depth0,helpers,partials,data) { + return "success"; +},"21":function(container,depth0,helpers,partials,data) { + var helper; + + return " " + + container.escapeExpression(((helper = (helper = helpers.errorMessage || (depth0 != null ? depth0.errorMessage : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"errorMessage","hash":{},"data":data}) : helper))); +},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) { + var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression, alias5=container.lambda; + + return "<div class=\"operation" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.hasChanged : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + "\">\n <div class=\"operation-header\">\n <input type=\"text\" class=\"operation-name\" placeholder=\"" + + alias4(((helper = (helper = helpers.shortRuleDescTXT || (depth0 != null ? depth0.shortRuleDescTXT : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"shortRuleDescTXT","hash":{},"data":data}) : helper))) + + "\" value=\"" + + alias4(alias5(((stack1 = (depth0 != null ? depth0.operation : depth0)) != null ? stack1.name : stack1), depth0)) + + "\" />\n <input type=\"text\" class=\"operation-operation\" value=\"" + + alias4(alias5(((stack1 = (depth0 != null ? depth0.operation : depth0)) != null ? stack1.operation : stack1), depth0)) + + "\" />\n" + + ((stack1 = helpers["if"].call(alias1,((stack1 = (depth0 != null ? depth0.operation : depth0)) != null ? stack1.id : stack1),{"name":"if","hash":{},"fn":container.program(3, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " </div>\n\n <div class=\"checks\">\n" + + ((stack1 = helpers.each.call(alias1,((stack1 = (depth0 != null ? depth0.operation : depth0)) != null ? stack1.checks : stack1),{"name":"each","hash":{},"fn":container.program(5, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + " </div>\n <button class=\"button-add\">" + + alias4(((helper = (helper = helpers.addRuleTXT || (depth0 != null ? depth0.addRuleTXT : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"addRuleTXT","hash":{},"data":data}) : helper))) + + "</button>\n" + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.hasChanged : depth0),{"name":"if","hash":{},"fn":container.program(10, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "") + + ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.saving : depth0),{"name":"if","hash":{},"fn":container.program(13, data, 0, blockParams, depths),"inverse":container.program(15, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "") + + "\n</div>\n"; +},"useData":true,"useDepths":true}); +templates['operations'] = template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) { + var helper; + + return "<div class=\"operations\"></div>\n<button class=\"button-add-operation\">" + + container.escapeExpression(((helper = (helper = helpers.addRuleGroupTXT || (depth0 != null ? depth0.addRuleGroupTXT : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"addRuleGroupTXT","hash":{},"data":data}) : helper))) + + "</button>\n"; +},"useData":true}); +})();
\ No newline at end of file diff --git a/apps/workflowengine/js/templates/operation.handlebars b/apps/workflowengine/js/templates/operation.handlebars new file mode 100644 index 00000000000..0899890cef2 --- /dev/null +++ b/apps/workflowengine/js/templates/operation.handlebars @@ -0,0 +1,45 @@ +<div class="operation{{#if hasChanged}} modified{{/if}}"> + <div class="operation-header"> + <input type="text" class="operation-name" placeholder="{{shortRuleDescTXT}}" value="{{operation.name}}" /> + <input type="text" class="operation-operation" value="{{operation.operation}}" /> + {{! delete only makes sense if the operation is already saved }} + {{#if operation.id}} + <span class="button-delete icon-delete"></span> + {{/if}} + </div> + + <div class="checks"> + {{#each operation.checks}} + <div class="check" data-id="{{@index}}"> + <select class="check-class"> + {{#each ../classes}} + <option value="{{class}}" {{{selectItem class ../class}}}>{{name}}</option> + {{/each}} + </select> + <select class="check-operator"> + {{#each (getOperators class)}} + <option value="{{operator}}" {{{selectItem operator ../operator}}}>{{name}}</option> + {{/each}} + </select> + <input type="text" class="check-value" value="{{value}}"> + <span class="button-delete-check icon-delete"></span> + </div> + {{/each}} + </div> + <button class="button-add">{{addRuleTXT}}</button> + {{#if hasChanged}} + {{! reset only makes sense if the operation is already saved }} + {{#if operation.id}} + <button class="button-reset pull-right">{{resetTXT}}</button> + {{/if}} + <button class="button-save pull-right">{{saveTXT}}</button> + {{/if}} + {{#if saving}} + <span class="icon-loading-small pull-right"></span> + <span class="pull-right">{{savingTXT}}</span> + {{else}}{{#if message}} + <span class="msg pull-right {{#if errorMessage}}error{{else}}success{{/if}}"> + {{message}}{{#if errorMessage}} {{errorMessage}}{{/if}} + </span> + {{/if}}{{/if}} +</div> diff --git a/apps/workflowengine/js/templates/operations.handlebars b/apps/workflowengine/js/templates/operations.handlebars new file mode 100644 index 00000000000..14b62ee79a6 --- /dev/null +++ b/apps/workflowengine/js/templates/operations.handlebars @@ -0,0 +1,2 @@ +<div class="operations"></div> +<button class="button-add-operation">{{addRuleGroupTXT}}</button> diff --git a/apps/workflowengine/lib/AppInfo/Application.php b/apps/workflowengine/lib/AppInfo/Application.php index 89d342400c2..0b90a4323e2 100644 --- a/apps/workflowengine/lib/AppInfo/Application.php +++ b/apps/workflowengine/lib/AppInfo/Application.php @@ -64,6 +64,7 @@ class Application extends \OCP\AppFramework\App { script('workflowengine', [ 'admin', + 'templates', // Check plugins 'filemimetypeplugin', diff --git a/apps/workflowengine/templates/admin.php b/apps/workflowengine/templates/admin.php index 26d581aee03..d3faace71f6 100644 --- a/apps/workflowengine/templates/admin.php +++ b/apps/workflowengine/templates/admin.php @@ -39,58 +39,5 @@ <p><?php p($_['description']); ?></p> <?php endif; ?> - <script type="text/template" id="operations-template"> - <div class="operations"></div> - <button class="button-add-operation"><?php p($l->t('Add rule group')); ?></button> - </script> - - <script type="text/template" id="operation-template"> - <div class="operation{{#if hasChanged}} modified{{/if}}"> - <div class="operation-header"> - <input type="text" class="operation-name" placeholder="<?php p($l->t('Short rule description')); ?>" value="{{operation.name}}" /> - <input type="text" class="operation-operation" value="{{operation.operation}}" /> - {{! delete only makes sense if the operation is already saved }} - {{#if operation.id}} - <span class="button-delete icon-delete"></span> - {{/if}} - </div> - - <div class="checks"> - {{#each operation.checks}} - <div class="check" data-id="{{@index}}"> - <select class="check-class"> - {{#each ../classes}} - <option value="{{class}}" {{{selectItem class ../class}}}>{{name}}</option> - {{/each}} - </select> - <select class="check-operator"> - {{#each (getOperators class)}} - <option value="{{operator}}" {{{selectItem operator ../operator}}}>{{name}}</option> - {{/each}} - </select> - <input type="text" class="check-value" value="{{value}}"> - <span class="button-delete-check icon-delete"></span> - </div> - {{/each}} - </div> - <button class="button-add"><?php p($l->t('Add rule')); ?></button> - {{#if hasChanged}} - {{! reset only makes sense if the operation is already saved }} - {{#if operation.id}} - <button class="button-reset pull-right"><?php p($l->t('Reset')); ?></button> - {{/if}} - <button class="button-save pull-right"><?php p($l->t('Save')); ?></button> - {{/if}} - {{#if saving}} - <span class="icon-loading-small pull-right"></span> - <span class="pull-right"><?php p($l->t('Saving…')); ?></span> - {{else}}{{#if message}} - <span class="msg pull-right {{#if errorMessage}}error{{else}}success{{/if}}"> - {{message}}{{#if errorMessage}} {{errorMessage}}{{/if}} - </span> - {{/if}}{{/if}} - </div> - </script> - <div class="rules"><span class="icon-loading-small"></span> <?php p($l->t('Loading…')); ?></div> </div> |