diff --git a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
index 5d376f2d4f..30041c3a27 100644
--- a/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
@@ -238,7 +238,7 @@ class ShareAPIControllerTest extends TestCase {
*/
public function createShare($id, $shareType, $sharedWith, $sharedBy, $shareOwner, $path, $permissions,
- $shareTime, $expiration, $parent, $target, $mail_send, $token=null,
+ $shareTime, $expiration, $parent, $target, $mail_send, $note = '', $token=null,
$password=null) {
$share = $this->getMockBuilder(IShare::class)->getMock();
$share->method('getId')->willReturn($id);
@@ -248,6 +248,7 @@ class ShareAPIControllerTest extends TestCase {
$share->method('getShareOwner')->willReturn($shareOwner);
$share->method('getNode')->willReturn($path);
$share->method('getPermissions')->willReturn($permissions);
+ $share->method('getNote')->willReturn($note);
$time = new \DateTime();
$time->setTimestamp($shareTime);
$share->method('getShareTime')->willReturn($time);
@@ -310,7 +311,8 @@ class ShareAPIControllerTest extends TestCase {
null,
6,
'target',
- 0
+ 0,
+ 'personal note'
);
$expected = [
'id' => 100,
@@ -334,6 +336,7 @@ class ShareAPIControllerTest extends TestCase {
'storage' => 101,
'mail_send' => 0,
'uid_file_owner' => 'ownerId',
+ 'note' => 'personal note',
'displayname_file_owner' => 'ownerDisplay',
'mimetype' => 'myMimeType',
];
@@ -352,7 +355,8 @@ class ShareAPIControllerTest extends TestCase {
null,
6,
'target',
- 0
+ 0,
+ 'personal note'
);
$expected = [
'id' => 101,
@@ -376,6 +380,7 @@ class ShareAPIControllerTest extends TestCase {
'storage' => 101,
'mail_send' => 0,
'uid_file_owner' => 'ownerId',
+ 'note' => 'personal note',
'displayname_file_owner' => 'ownerDisplay',
'mimetype' => 'myFolderMimeType',
];
@@ -396,6 +401,7 @@ class ShareAPIControllerTest extends TestCase {
6,
'target',
0,
+ 'personal note',
'token',
'password'
);
@@ -422,6 +428,7 @@ class ShareAPIControllerTest extends TestCase {
'mail_send' => 0,
'url' => 'url',
'uid_file_owner' => 'ownerId',
+ 'note' => 'personal note',
'displayname_file_owner' => 'ownerDisplay',
'mimetype' => 'myFolderMimeType',
];
@@ -455,7 +462,7 @@ class ShareAPIControllerTest extends TestCase {
->willReturn(true);
$this->shareManager
- ->expects($this->once())
+ ->expects($this->any())
->method('getShareById')
->with($share->getFullId(), 'currentUser')
->willReturn($share);
@@ -501,6 +508,8 @@ class ShareAPIControllerTest extends TestCase {
['group', $group],
]));
+ $d = $ocs->getShare($share->getId())->getData()[0];
+
$this->assertEquals($result, $ocs->getShare($share->getId())->getData()[0]);
}
@@ -1810,9 +1819,10 @@ class ShareAPIControllerTest extends TestCase {
->setNode($file)
->setShareTime(new \DateTime('2000-01-01T00:01:02'))
->setTarget('myTarget')
+ ->setNote('personal note')
->setId(42);
- /* User backend down */
+ // User backend down
$result[] = [
[
'id' => 42,
@@ -1836,12 +1846,12 @@ class ShareAPIControllerTest extends TestCase {
'file_target' => 'myTarget',
'share_with' => 'recipient',
'share_with_displayname' => 'recipient',
+ 'note' => 'personal note',
'mail_send' => 0,
'mimetype' => 'myMimeType',
], $share, [], false
];
-
- /* User backend up */
+ // User backend up
$result[] = [
[
'id' => 42,
@@ -1855,6 +1865,7 @@ class ShareAPIControllerTest extends TestCase {
'token' => null,
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'ownerDN',
+ 'note' => 'personal note',
'path' => 'file',
'item_type' => 'file',
'storage_id' => 'storageId',
@@ -1883,9 +1894,9 @@ class ShareAPIControllerTest extends TestCase {
->setNode($file)
->setShareTime(new \DateTime('2000-01-01T00:01:02'))
->setTarget('myTarget')
+ ->setNote('personal note')
->setId(42);
-
- /* User backend down */
+ // User backend down
$result[] = [
[
'id' => 42,
@@ -1899,6 +1910,7 @@ class ShareAPIControllerTest extends TestCase {
'token' => null,
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
+ 'note' => 'personal note',
'path' => 'file',
'item_type' => 'file',
'storage_id' => 'storageId',
@@ -1915,6 +1927,7 @@ class ShareAPIControllerTest extends TestCase {
];
// with existing group
+
$share = \OC::$server->getShareManager()->newShare();
$share->setShareType(\OCP\Share::SHARE_TYPE_GROUP)
->setSharedWith('recipientGroup')
@@ -1924,6 +1937,7 @@ class ShareAPIControllerTest extends TestCase {
->setNode($file)
->setShareTime(new \DateTime('2000-01-01T00:01:02'))
->setTarget('myTarget')
+ ->setNote('personal note')
->setId(42);
$result[] = [
@@ -1939,6 +1953,7 @@ class ShareAPIControllerTest extends TestCase {
'token' => null,
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
+ 'note' => 'personal note',
'path' => 'file',
'item_type' => 'file',
'storage_id' => 'storageId',
@@ -1964,6 +1979,7 @@ class ShareAPIControllerTest extends TestCase {
->setNode($file)
->setShareTime(new \DateTime('2000-01-01T00:01:02'))
->setTarget('myTarget')
+ ->setNote('personal note')
->setId(42);
$result[] = [
[
@@ -1978,6 +1994,7 @@ class ShareAPIControllerTest extends TestCase {
'token' => null,
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
+ 'note' => 'personal note',
'path' => 'file',
'item_type' => 'file',
'storage_id' => 'storageId',
@@ -2004,6 +2021,7 @@ class ShareAPIControllerTest extends TestCase {
->setPassword('mypassword')
->setExpirationDate(new \DateTime('2001-01-02T00:00:00'))
->setToken('myToken')
+ ->setNote('personal note')
->setId(42);
$result[] = [
@@ -2019,6 +2037,7 @@ class ShareAPIControllerTest extends TestCase {
'token' => 'myToken',
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
+ 'note' => 'personal note',
'path' => 'file',
'item_type' => 'file',
'storage_id' => 'storageId',
@@ -2044,6 +2063,7 @@ class ShareAPIControllerTest extends TestCase {
->setNode($folder)
->setShareTime(new \DateTime('2000-01-01T00:01:02'))
->setTarget('myTarget')
+ ->setNote('personal note')
->setId(42);
$result[] = [
@@ -2059,6 +2079,7 @@ class ShareAPIControllerTest extends TestCase {
'token' => null,
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
+ 'note' => 'personal note',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
@@ -2101,6 +2122,7 @@ class ShareAPIControllerTest extends TestCase {
'token' => null,
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
+ 'note' => '',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
@@ -2142,6 +2164,7 @@ class ShareAPIControllerTest extends TestCase {
'token' => null,
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
+ 'note' => '',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
@@ -2183,6 +2206,7 @@ class ShareAPIControllerTest extends TestCase {
'token' => null,
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
+ 'note' => '',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
@@ -2207,6 +2231,7 @@ class ShareAPIControllerTest extends TestCase {
->setPermissions(\OCP\Constants::PERMISSION_READ)
->setShareTime(new \DateTime('2000-01-01T00:01:02'))
->setTarget('myTarget')
+ ->setNote('personal note')
->setId(42);
$result[] = [
@@ -2238,6 +2263,7 @@ class ShareAPIControllerTest extends TestCase {
'token' => null,
'uid_file_owner' => 'owner',
'displayname_file_owner' => 'owner',
+ 'note' => '',
'path' => 'folder',
'item_type' => 'folder',
'storage_id' => 'storageId',
diff --git a/apps/files_sharing/tests/Controller/ShareControllerTest.php b/apps/files_sharing/tests/Controller/ShareControllerTest.php
index fb41787864..a01560d028 100644
--- a/apps/files_sharing/tests/Controller/ShareControllerTest.php
+++ b/apps/files_sharing/tests/Controller/ShareControllerTest.php
@@ -192,6 +192,9 @@ class ShareControllerTest extends \Test\TestCase {
public function testShowShare() {
+
+ $note = 'personal note';
+
$this->shareController->setToken('token');
$owner = $this->getMockBuilder(IUser::class)->getMock();
@@ -210,6 +213,7 @@ class ShareControllerTest extends \Test\TestCase {
$share->setPassword('password')
->setShareOwner('ownerUID')
->setNode($file)
+ ->setNote($note)
->setTarget('/file1.txt');
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
@@ -283,6 +287,7 @@ class ShareControllerTest extends \Test\TestCase {
'shareUrl' => null,
'previewImage' => null,
'previewURL' => 'downloadURL',
+ 'note' => $note
);
$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
diff --git a/apps/sharebymail/lib/ShareByMailProvider.php b/apps/sharebymail/lib/ShareByMailProvider.php
index 1a1855b9c4..73e962e329 100644
--- a/apps/sharebymail/lib/ShareByMailProvider.php
+++ b/apps/sharebymail/lib/ShareByMailProvider.php
@@ -506,6 +506,61 @@ class ShareByMailProvider implements IShareProvider {
return true;
}
+ protected function sendNote(IShare $share) {
+
+ $recipient = $share->getSharedWith();
+
+
+ $filename = $share->getNode()->getName();
+ $initiator = $share->getSharedBy();
+ $note = $share->getNote();
+
+ $initiatorUser = $this->userManager->get($initiator);
+ $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
+ $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
+
+ $plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
+ $htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
+
+ $message = $this->mailer->createMessage();
+
+ $emailTemplate = $this->mailer->createEMailTemplate('shareByMail.sendNote');
+
+ $emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
+ $emailTemplate->addHeader();
+ $emailTemplate->addHeading(htmlspecialchars($htmlHeading), $plainHeading);
+ $emailTemplate->addBodyText(htmlspecialchars($note), $note);
+
+ $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
+ ['token' => $share->getToken()]);
+ $emailTemplate->addBodyButton(
+ $this->l->t('Open »%s«', [$filename]),
+ $link
+ );
+
+ // The "From" contains the sharers name
+ $instanceName = $this->defaults->getName();
+ $senderName = $this->l->t(
+ '%1$s via %2$s',
+ [
+ $initiatorDisplayName,
+ $instanceName
+ ]
+ );
+ $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
+ if ($initiatorEmailAddress !== null) {
+ $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
+ $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
+ } else {
+ $emailTemplate->addFooter();
+ }
+
+ $message->setTo([$recipient]);
+ $message->useTemplate($emailTemplate);
+ $this->mailer->send($message);
+
+ }
+
/**
* send auto generated password to the owner. This happens if the admin enforces
* a password for mail shares and forbid to send the password by mail to the recipient
@@ -662,8 +717,13 @@ class ShareByMailProvider implements IShareProvider {
->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
->set('password', $qb->createNamedParameter($share->getPassword()))
->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
+ ->set('note', $qb->createNamedParameter($share->getNote()))
->execute();
+ if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
+ $this->sendNote($share);
+ }
+
return $share;
}
@@ -904,6 +964,7 @@ class ShareByMailProvider implements IShareProvider {
->setPermissions((int)$data['permissions'])
->setTarget($data['file_target'])
->setMailSend((bool)$data['mail_send'])
+ ->setNote($data['note'])
->setToken($data['token']);
$shareTime = new \DateTime();
diff --git a/apps/sharebymail/tests/ShareByMailProviderTest.php b/apps/sharebymail/tests/ShareByMailProviderTest.php
index 95d746cfb4..f0d99e6026 100644
--- a/apps/sharebymail/tests/ShareByMailProviderTest.php
+++ b/apps/sharebymail/tests/ShareByMailProviderTest.php
@@ -342,15 +342,17 @@ class ShareByMailProviderTest extends TestCase {
$uidOwner = 'user2';
$permissions = 1;
$token = 'token';
+ $note = 'personal note';
$instance = $this->getInstance();
- $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
+ $id = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $note);
$this->share->expects($this->once())->method('getPermissions')->willReturn($permissions + 1);
$this->share->expects($this->once())->method('getShareOwner')->willReturn($uidOwner);
$this->share->expects($this->once())->method('getSharedBy')->willReturn($sharedBy);
+ $this->share->expects($this->any())->method('getNote')->willReturn($note);
$this->share->expects($this->atLeastOnce())->method('getId')->willReturn($id);
$this->assertSame($this->share,
@@ -372,6 +374,7 @@ class ShareByMailProviderTest extends TestCase {
$this->assertSame($uidOwner, $result[0]['uid_owner']);
$this->assertSame($permissions + 1, (int)$result[0]['permissions']);
$this->assertSame($token, $result[0]['token']);
+ $this->assertSame($note, $result[0]['note']);
}
public function testDelete() {
@@ -478,7 +481,7 @@ class ShareByMailProviderTest extends TestCase {
$instance = $this->getInstance(['createShareObject']);
$idMail = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
- $idPublic = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, \OCP\Share::SHARE_TYPE_LINK);
+ $idPublic = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, '', \OCP\Share::SHARE_TYPE_LINK);
$this->assertTrue($idMail !== $idPublic);
@@ -490,9 +493,9 @@ class ShareByMailProviderTest extends TestCase {
}
);
- $this->assertInstanceOf('OCP\Share\IShare',
- $instance->getShareByToken('token')
- );
+ $result = $instance->getShareByToken('token');
+
+ $this->assertInstanceOf('OCP\Share\IShare', $result);
}
/**
@@ -511,7 +514,7 @@ class ShareByMailProviderTest extends TestCase {
$instance = $this->getInstance(['createShareObject']);
$idMail = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token);
- $idPublic = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, "token2", \OCP\Share::SHARE_TYPE_LINK);
+ $idPublic = $this->createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, "token2", '', \OCP\Share::SHARE_TYPE_LINK);
$this->assertTrue($idMail !== $idPublic);
@@ -631,7 +634,7 @@ class ShareByMailProviderTest extends TestCase {
$this->invokePrivate($instance, 'getRawShare', [$id+1]);
}
- private function createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType = \OCP\Share::SHARE_TYPE_EMAIL) {
+ private function createDummyShare($itemType, $itemSource, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $note='', $shareType = \OCP\Share::SHARE_TYPE_EMAIL) {
$qb = $this->connection->getQueryBuilder();
$qb->insert('share')
->setValue('share_type', $qb->createNamedParameter($shareType))
@@ -643,6 +646,7 @@ class ShareByMailProviderTest extends TestCase {
->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
->setValue('permissions', $qb->createNamedParameter($permissions))
->setValue('token', $qb->createNamedParameter($token))
+ ->setValue('note', $qb->createNamedParameter($note))
->setValue('stime', $qb->createNamedParameter(time()));
/*
diff --git a/core/Migrations/Version14000Date20180712153140.php b/core/Migrations/Version14000Date20180712153140.php
new file mode 100644
index 0000000000..268a479eaa
--- /dev/null
+++ b/core/Migrations/Version14000Date20180712153140.php
@@ -0,0 +1,43 @@
+
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
.
+ *
+ */
+
+namespace OC\Core\Migrations;
+
+use OCP\DB\ISchemaWrapper;
+use OCP\Migration\SimpleMigrationStep;
+
+/**
+ * add column for share notes
+ *
+ * Class Version14000Date20180712153140
+ */
+class Version14000Date20180712153140 extends SimpleMigrationStep {
+ public function changeSchema(\OCP\Migration\IOutput $output, \Closure $schemaClosure, array $options) {
+
+ /** @var ISchemaWrapper $schema */
+ $schema = $schemaClosure();
+
+ $table = $schema->getTable('share');
+ $table->addColumn('note', 'text', ['notnull' => false]);
+
+ return $schema;
+ }
+}
diff --git a/core/css/apps.scss b/core/css/apps.scss
index d524dd94bb..86f0e62240 100644
--- a/core/css/apps.scss
+++ b/core/css/apps.scss
@@ -74,6 +74,13 @@ kbd {
/* Navigation: folder like structure */
#app-navigation {
width: $navigation-width;
+ position: sticky;
+ top: $header-height;
+ left: 0;
+ z-index: 1500;
+ overflow-y: auto;
+ overflow-x: hidden;
+ height: calc(100vh - #{$header-height});
box-sizing: border-box;
background-color: var(--color-main-background);
-webkit-user-select: none;
@@ -320,9 +327,6 @@ kbd {
&.hidden {
display: none;
}
- &.without-app-settings {
- padding-bottom: 0;
- }
/**
* Button styling for menu, edit and undo
@@ -581,12 +585,7 @@ kbd {
padding-top: $header-height;
box-sizing: border-box;
position: relative;
- overflow-x: hidden;
display: flex;
- /* trick: scroll #app-content and not the body
- * to avoid double scrollbar with sidebar
- */
- max-height: 100vh;
}
/* APP-CONTENT AND WRAPPER ------------------------------------------ */
@@ -637,17 +636,19 @@ kbd {
min-width: $sidebar-min-width;
max-width: $sidebar-max-width;
display: block;
- position: relative;
+ position: sticky;
+ top: $header-height;
+ right:0;
+ overflow-y: auto;
+ overflow-x: hidden;
+ z-index: 1500;
+ height: calc(100vh - #{$header-height});
background: var(--color-main-background);
border-left: 1px solid var(--color-border);
- overflow-x: hidden;
- overflow-y: auto;
flex-shrink: 0;
- transition: 300ms width ease-in-out,
- 300ms min-width ease-in-out;
+ // no animations possible, use OC.Apps.showAppSidebar
&.disappear {
- width: 0;
- min-width: 0;
+ display: none;
}
}
@@ -880,6 +881,11 @@ $popovericon-size: 16px;
li {
display: flex;
flex: 0 0 auto;
+
+ &.hidden {
+ display: none;
+ }
+
> button,
> a,
> .menuitem {
@@ -895,6 +901,7 @@ $popovericon-size: 16px;
box-shadow: none;
width: 100%;
color: var(--color-main-text);
+ white-space: nowrap;
/* Override the app-navigation li opacity */
opacity: .7 !important;
span[class^='icon-'],
@@ -943,6 +950,7 @@ $popovericon-size: 16px;
width: 150px;
line-height: 1.6em;
padding: 8px 0;
+ white-space: normal;
}
> select {
margin: 0;
diff --git a/core/css/ie.scss b/core/css/ie.scss
new file mode 100644
index 0000000000..ec7f51065e
--- /dev/null
+++ b/core/css/ie.scss
@@ -0,0 +1,11 @@
+
+#app-navigation,
+#app-sidebar {
+ position: fixed !important;
+}
+#app-content {
+ width: $navigation-width !important;
+}
+#app-sidebar.disappear {
+ right: -$sidebar-max-width !important;
+}
\ No newline at end of file
diff --git a/core/css/share.scss b/core/css/share.scss
deleted file mode 100644
index 07489cd55a..0000000000
--- a/core/css/share.scss
+++ /dev/null
@@ -1,204 +0,0 @@
-/**
- * @copyright Copyright (c) 2016, John Molakvoæ
- * @copyright Copyright (c) 2016, Morris Jobke
- * @copyright Copyright (c) 2016, Julia Bode
- * @copyright Copyright (c) 2016, Christoph Wurst
- * @copyright Copyright (c) 2015, Hendrik Leppelsack
- * @copyright Copyright (c) 2015, Jan-Christoph Borchardt
- * @copyright Copyright (c) 2015, Vincent Petry
- * @copyright Copyright (c) 2015, Arthur Schiwon
- * @copyright Copyright (c) 2015, Roeland Jago Douma
- * @copyright Copyright (c) 2015, Morris Jobke
- *
- * @license GNU AGPL version 3 or any later version
- *
- */
-
-/* SHARE TAB STYLING -------------------------------------------------------- */
-.shareTabView {
- .unshare.icon-loading-small {
- margin-top: 1px;
- }
- .shareWithLoading, .linkShare .icon-loading-small {
- display: inline-block !important;
- padding-left: 10px;
- }
- .shareWithLoading {
- position: relative;
- right: 70px;
- top: 2px;
- }
- .icon-loading-small.hidden {
- display: none !important;
- }
- .avatar {
- margin-right: 8px;
- display: inline-block;
- overflow: hidden;
- vertical-align: middle;
- width: 32px;
- height: 32px;
- }
- label {
- font-weight: 400;
- white-space: nowrap;
- }
- input[type='radio'].radio + label {
- margin-left: -1px;
- }
- input[type='checkbox'] {
- margin: 0 3px 0 8px;
- vertical-align: middle;
- }
- input[type='submit'] {
- margin-left: 7px;
- }
- form {
- font-size: 100%;
- margin-left: 0;
- margin-right: 0;
- }
- .error {
- color: var(--color-error);
- border-color: var(--color-error);
- }
- .mailView .icon-mail {
- opacity: 0.5;
- }
-}
-
-.share-autocomplete-item {
- display: flex;
- .autocomplete-item-text {
- margin-left: 10px;
- margin-right: 10px;
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
- line-height: 32px;
- vertical-align: middle;
- }
-}
-
-.ui-autocomplete .autocomplete-note {
- padding: 5px 10px;
- color: rgba(0, 0, 0, .3);
-}
-
-#shareWithList {
- list-style-type: none;
- padding: 8px;
- > li {
- position: relative;
- padding-top: 10px;
- padding-bottom: 10px;
- font-weight: bold;
- line-height: 21px;
- white-space: normal;
- width: 100%;
- }
- .sharingOptionsGroup {
- flex-shrink: 0;
- position: relative;
- .popovermenu {
- right: -11px;
- top: 35px;
- }
- }
-
- .shareOption {
- white-space: nowrap;
- display: inline-block;
- }
- .unshare img {
- vertical-align: text-bottom;
- /* properly align icons */
- }
- label input[type=checkbox] {
- margin-left: 0;
- position: relative;
- }
- .username {
- padding-right: 8px;
- white-space: nowrap;
- text-overflow: ellipsis;
- display: inline-block;
- overflow: hidden;
- vertical-align: middle;
- flex-grow: 5;
- }
-}
-
-#link {
- border-top: 1px solid var(--color-border);
- padding-top: 8px;
- #showPassword img {
- padding-left: 5px;
- width: 12px;
- }
-}
-
-.reshare,
-#link label,
-#expiration label {
- display: inline-block;
- padding: 6px 4px;
-}
-
-.resharerInfoView.subView {
- position: relative;
-}
-
-#defaultExpireMessage, .reshare {
- /* fix shared by text going out of box */
- white-space: normal;
-}
-
-#defaultExpireMessage {
- /* show message on new line */
- display: block;
- padding-left: 4px;
- /* TODO: style the dropdown in a proper way - border-box, etc. */
- width: 90%;
-}
-
-.ui-autocomplete {
- /* limit dropdown height to 4 1/2 entries */
- max-height: 200px;
- overflow-y: auto;
- overflow-x: hidden;
-}
-
-.notCreatable {
- padding-left: 12px;
- padding-top: 12px;
- color: var(--color-text-lighter);
-}
-
-.contactsmenu-popover {
- left: -6px;
- right: auto;
- padding: 3px 6px;
- top: 100%;
- margin-top: 0;
- li.hidden {
- display: none !important;
- }
- &:after {
- left: 8px;
- right: auto;
- }
-}
-
-.popovermenu .datepicker {
- margin-left: 35px;
-}
-
-.popovermenu .passwordField {
- margin-left: 35px;
- width: inherit !important;
-}
-
-.ui-datepicker {
- z-index: 1111 !important;
-}
diff --git a/core/css/styles.scss b/core/css/styles.scss
index 30aa25d183..9652b02e9d 100644
--- a/core/css/styles.scss
+++ b/core/css/styles.scss
@@ -530,6 +530,7 @@ code {
width: auto;
border-radius: var(--border-radius);
border: none;
+ z-index: 500 !important;
.ui-state-default,
.ui-widget-content .ui-state-default,
diff --git a/core/img/actions/public-white.svg b/core/img/actions/public-white.svg
new file mode 100644
index 0000000000..d85defb6a0
--- /dev/null
+++ b/core/img/actions/public-white.svg
@@ -0,0 +1 @@
+
diff --git a/core/js/apps.js b/core/js/apps.js
index b40883e88c..473fec313a 100644
--- a/core/js/apps.js
+++ b/core/js/apps.js
@@ -27,8 +27,9 @@
*/
exports.Apps.showAppSidebar = function($el) {
var $appSidebar = $el || $('#app-sidebar');
- $appSidebar.removeClass('disappear');
- $('#content').addClass('with-app-sidebar').trigger(new $.Event('appresized'));
+ $appSidebar.removeClass('disappear')
+ .show('slide', { direction: 'right' }, 300);
+ $('#app-content').trigger(new $.Event('appresized'));
};
/**
@@ -39,8 +40,11 @@
*/
exports.Apps.hideAppSidebar = function($el) {
var $appSidebar = $el || $('#app-sidebar');
- $appSidebar.addClass('disappear');
- $('#content').removeClass('with-app-sidebar').trigger(new $.Event('appresized'));
+ $appSidebar.hide('slide', { direction: 'right' }, 300,
+ function() {
+ $appSidebar.addClass('disappear');
+ });
+ $('#app-content').trigger(new $.Event('appresized'));
};
/**
diff --git a/core/js/core.json b/core/js/core.json
index 502e3a5797..2ebc2e710e 100644
--- a/core/js/core.json
+++ b/core/js/core.json
@@ -37,7 +37,6 @@
"shareconfigmodel.js",
"shareitemmodel.js",
"sharedialogview.js",
- "sharedialogexpirationview.js",
"sharedialoglinkshareview.js",
"sharedialogresharerinfoview.js",
"sharedialogshareelistview.js",
diff --git a/core/js/merged-share-backend.json b/core/js/merged-share-backend.json
index d39945b8f7..63c3575a66 100644
--- a/core/js/merged-share-backend.json
+++ b/core/js/merged-share-backend.json
@@ -1,11 +1,10 @@
[
- "shareconfigmodel.js",
- "shareitemmodel.js",
- "sharesocialmanager.js",
- "sharedialogresharerinfoview.js",
- "sharedialoglinkshareview.js",
- "sharedialogexpirationview.js",
- "sharedialogshareelistview.js",
- "sharedialogview.js",
- "share.js"
+ "shareconfigmodel.js",
+ "shareitemmodel.js",
+ "sharesocialmanager.js",
+ "sharedialogresharerinfoview.js",
+ "sharedialoglinkshareview.js",
+ "sharedialogshareelistview.js",
+ "sharedialogview.js",
+ "share.js"
]
diff --git a/core/js/sharedialogexpirationview.js b/core/js/sharedialogexpirationview.js
deleted file mode 100644
index a9849ef916..0000000000
--- a/core/js/sharedialogexpirationview.js
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2015
- *
- * This file is licensed under the Affero General Public License version 3
- * or later.
- *
- * See the COPYING-README file.
- *
- */
-
-/* global moment, Handlebars */
-
-(function() {
- if (!OC.Share) {
- OC.Share = {};
- }
-
- var TEMPLATE =
- // currently expiration is only effective for link share.
- // this is about to change in future. Therefore this is not included
- // in the LinkShareView to ease reusing it in future. Then,
- // modifications (getting rid of IDs) are still necessary.
- '{{#if isLinkShare}}' +
- '' +
- '' +
- '' +
- ' ' +
- ' ' +
- '
' +
- ' {{#if isExpirationEnforced}}' +
- // originally the expire message was shown when a default date was set, however it never had text
- '{{defaultExpireMessage}}' +
- ' {{/if}}' +
- '{{/if}}'
- ;
-
- /**
- * @class OCA.Share.ShareDialogExpirationView
- * @member {OC.Share.ShareItemModel} model
- * @member {jQuery} $el
- * @memberof OCA.Sharing
- * @classdesc
- *
- * Represents the expiration part in the GUI of the share dialogue
- *
- */
- var ShareDialogExpirationView = OC.Backbone.View.extend({
- /** @type {string} **/
- id: 'shareDialogLinkShare',
-
- /** @type {OC.Share.ShareConfigModel} **/
- configModel: undefined,
-
- /** @type {Function} **/
- _template: undefined,
-
- /** @type {boolean} **/
- showLink: true,
-
- className: 'hidden',
-
- events: {
- 'change .expirationCheckbox': '_onToggleExpiration',
- 'change .datepicker': '_onChangeExpirationDate'
- },
-
- initialize: function(options) {
- if(!_.isUndefined(options.configModel)) {
- this.configModel = options.configModel;
- } else {
- throw 'missing OC.Share.ShareConfigModel';
- }
-
- var view = this;
- this.configModel.on('change:isDefaultExpireDateEnforced', function() {
- view.render();
- });
-
- this.model.on('change:itemType', function() {
- view.render();
- });
-
- this.model.on('change:linkShare', function() {
- view.render();
- });
- },
-
- _onToggleExpiration: function(event) {
- var $checkbox = $(event.target);
- var state = $checkbox.prop('checked');
- // TODO: slide animation
- this.$el.find('.expirationDateContainer').toggleClass('hidden', !state);
- if (!state) {
- // discard expiration date
- this.model.get('linkShare').expiration = '';
- this.model.saveLinkShare({
- expireDate: ''
- });
- } else {
- this.$el.find('#expirationDate').focus();
- }
- },
-
- _onChangeExpirationDate: function(event) {
- var $target = $(event.target);
- $target.tooltip('hide');
- $target.removeClass('error');
-
- var expiration = moment($target.val(), 'DD-MM-YYYY').format('YYYY-MM-DD');
- this.model.get('linkShare').expiration = expiration;
- this.model.saveLinkShare({
- expiration: expiration
- }, {
- error: function(model, message) {
- if (!message) {
- $target.attr('title', t('core', 'Error setting expiration date'));
- } else {
- $target.attr('title', message);
- }
- $target.tooltip({gravity: 'n'});
- $target.tooltip('show');
- $target.addClass('error');
- }
- });
- },
-
- render: function() {
- var defaultExpireMessage = '';
- var defaultExpireDays = this.configModel.get('defaultExpireDate');
- var isExpirationEnforced = this.configModel.get('isDefaultExpireDateEnforced');
-
- if( (this.model.isFolder() || this.model.isFile())
- && isExpirationEnforced) {
- defaultExpireMessage = t(
- 'core',
- 'The public link will expire no later than {days} days after it is created',
- {'days': defaultExpireDays }
- );
- }
-
- var isExpirationSet = !!this.model.get('linkShare').expiration || isExpirationEnforced;
-
- var expiration;
- if (isExpirationSet) {
- expiration = moment(this.model.get('linkShare').expiration, 'YYYY-MM-DD').format('DD-MM-YYYY');
- }
-
- this.$el.html(this.template({
- cid: this.cid,
- setExpirationLabel: t('core', 'Set expiration date'),
- expirationLabel: t('core', 'Expiration'),
- expirationDatePlaceholder: t('core', 'Expiration date'),
- defaultExpireMessage: defaultExpireMessage,
- isLinkShare: this.model.get('linkShare').isLinkShare,
- isExpirationSet: isExpirationSet,
- isExpirationEnforced: isExpirationEnforced,
- disableCheckbox: isExpirationEnforced && isExpirationSet,
- expirationValue: expiration
- }));
-
- // what if there is another date picker on that page?
- var minDate = new Date();
- var maxDate = null;
- // min date should always be the next day
- minDate.setDate(minDate.getDate()+1);
-
- if(isExpirationSet) {
- if(isExpirationEnforced) {
- // TODO: hack: backend returns string instead of integer
- var shareTime = this.model.get('linkShare').stime;
- if (_.isNumber(shareTime)) {
- shareTime = new Date(shareTime * 1000);
- }
- if (!shareTime) {
- shareTime = new Date(); // now
- }
- shareTime = OC.Util.stripTime(shareTime).getTime();
- maxDate = new Date(shareTime + defaultExpireDays * 24 * 3600 * 1000);
- }
- }
- $.datepicker.setDefaults({
- minDate: minDate,
- maxDate: maxDate
- });
-
- this.$el.find('.datepicker').datepicker({dateFormat : 'dd-mm-yy'});
-
- this.delegateEvents();
-
- return this;
- },
-
- /**
- * @returns {Function} from Handlebars
- * @private
- */
- template: function (data) {
- if (!this._template) {
- this._template = Handlebars.compile(TEMPLATE);
- }
- return this._template(data);
- }
-
- });
-
- OC.Share.ShareDialogExpirationView = ShareDialogExpirationView;
-
-})();
diff --git a/core/js/sharedialoglinkshareview.js b/core/js/sharedialoglinkshareview.js
index 5a78276a49..925d8ed918 100644
--- a/core/js/sharedialoglinkshareview.js
+++ b/core/js/sharedialoglinkshareview.js
@@ -21,71 +21,101 @@
var TEMPLATE =
'{{#if shareAllowed}}' +
- '' +
- '' +
- '' +
- '
' +
- '' +
- '
' +
- '
' +
- '{{#if singleAction}}' +
- '
' +
- '{{else}}' +
- '
' +
- '{{{popoverMenu}}}' +
- '{{/if}}' +
- '
' +
- '{{#if publicUpload}}' +
- '' +
- '' +
- '' +
- '' +
- '
' +
- '' +
- '' +
- '' +
- '' +
- '
' +
- '' +
- '' +
- '' +
- '' +
- '
' +
- '{{/if}}' +
- ' {{#if publicEditing}}' +
- '' +
- ' ' +
- ' ' +
- '' +
- '
' +
- ' {{/if}}' +
- ' {{#if showPasswordCheckBox}}' +
- '' +
- '' +
- ' {{/if}}' +
- '' +
- ' ' +
- ' {{#if showPasswordCheckBox}}' +
- ' ' +
- ' {{else}}' +
- ' ' +
- ' {{/if}}' +
- ' ' +
- '
' +
+ '' +
'{{else}}' +
// FIXME: this doesn't belong in this view
'{{#if noSharingPlaceholder}}{{/if}}' +
'{{/if}}'
;
var TEMPLATE_POPOVER_MENU =
- '