From 0a7e34f6c8c6e74bddfae7b6b3fd918a96c90695 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20Molakvo=C3=A6=20=28skjnldsv=29?=
 <skjnldsv@protonmail.com>
Date: Wed, 18 Jul 2018 17:42:30 +0200
Subject: [PATCH] Popovermenu migration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
---
 apps/files_sharing/css/sharetabview.scss | 311 ++++++++++++-----------
 core/css/apps.scss                       |   5 +
 core/js/core.json                        |   1 -
 core/js/merged-share-backend.json        |   1 -
 core/js/sharedialognoteview.js           | 149 -----------
 core/js/sharedialogshareelistview.js     |  90 ++++++-
 core/js/sharedialogview.js               |  10 +-
 core/js/shareitemmodel.js                |  13 +
 8 files changed, 271 insertions(+), 309 deletions(-)
 delete mode 100644 core/js/sharedialognoteview.js

diff --git a/apps/files_sharing/css/sharetabview.scss b/apps/files_sharing/css/sharetabview.scss
index 28cae27d405..18897802f48 100644
--- a/apps/files_sharing/css/sharetabview.scss
+++ b/apps/files_sharing/css/sharetabview.scss
@@ -2,164 +2,183 @@
 	min-height: 100px;
 }
 
-.shareTabView .oneline {
-	white-space: nowrap;
-	position: relative;
-}
-
-.shareTabView .shareWithLoading {
-	padding-left: 10px;
-	right: 35px;
-	top: 0px;
-}
-
-.shareTabView .shareWithConfirm,
-.shareTabView .clipboardButton,
-.shareTabView .linkPass .icon-loading-small {
-	position: absolute;
-	right: -7px;
-	top: -2px;
-	padding: 14px;
-}
-
-.shareTabView .shareWithConfirm {
-	opacity: .5;
-}
-
-.shareTabView .shareWithField:focus ~ .shareWithConfirm {
-	opacity: 1;
-}
-
-.shareTabView .linkMore {
-	position: absolute;
-	right: -7px;
-	top: -4px;
-	padding: 14px;
+.shareTabView {
+	.oneline {
+		white-space: nowrap;
+		position: relative;
+	}
+	.shareWithLoading {
+		padding-left: 10px;
+		right: 35px;
+		top: 0px;
+	}
+	.shareWithConfirm,
+	.clipboardButton,
+	.linkPass .icon-loading-small {
+		position: absolute;
+		right: -7px;
+		top: -2px;
+		padding: 14px;
+	}
+	.shareWithConfirm {
+		opacity: 0.5;
+	}
+	.shareWithField:focus ~ .shareWithConfirm {
+		opacity: 1;
+	}
+	.linkMore {
+		position: absolute;
+		right: -7px;
+		top: -4px;
+		padding: 14px;
+	}
+	.popovermenu {
+		&.socialSharingMenu {
+			right: -7px;
+		}
+		.clipboardButton {
+			position: relative;
+			top: initial;
+			right: initial;
+			padding: 0;
+		}
+		.share-add {
+			input.share-note-delete {
+				display: none;
+				border: none;
+				background-color: transparent;
+				width: 44px !important;
+				padding: 0;
+				flex: 0 0 44px;
+				margin-left: auto;
+			}
+		}
+		// note
+		.share-note-form {
+			span.icon-note {
+				position: relative;
+			}
+			textarea.share-note {
+				margin: 0;
+				width: 200px;
+				min-height: 70px;
+				resize: none;
+				+ input.share-note-submit {
+					position: absolute;
+					width: 44px !important;
+					height: 44px;
+					bottom: 0px;
+					right: 10px;
+					margin: 0;
+					background-color: transparent;
+					border: none;
+					opacity: .7;
+					&:hover,
+					&:focus,
+					&:active {
+						opacity: 1;
+					}
+				}
+			}
+		}
+	}
+	label {
+		white-space: nowrap;
+	}
+	input {
+		&[type='checkbox'] {
+			margin: 0 3px 0 8px;
+			vertical-align: middle;
+		}
+		&[type='text'] {
+			&.shareWithField,
+			&.emailField,
+			&.linkText {
+				width: 100%;
+				box-sizing: border-box;
+				padding-right: 32px;
+				text-overflow: ellipsis;
+			}
+		}
+		&[type='password'] {
+			width: 100%;
+			box-sizing: border-box;
+			padding-right: 32px;
+			text-overflow: ellipsis;
+		}
+	}
+	form {
+		font-size: 100%;
+		margin-left: 0;
+		margin-right: 0;
+	}
 }
 
 /* fix the popup menu because the button is shifted and then the menu is not aligned */
-.shareTabView .popovermenu.socialSharingMenu {
-	right: -7px;
-}
-
-.shareTabView .popovermenu .clipboardButton {
-	position: relative;
-	top: initial;
-	right: initial;
-	padding: 0;
-}
-
-.shareTabView label {
-	white-space: nowrap;
-}
-
-.shareTabView input[type="checkbox"] {
-	margin: 0 3px 0 8px;
-	vertical-align: middle;
-}
-
-.shareTabView input[type="text"].shareWithField,
-.shareTabView input[type="text"].emailField,
-.shareTabView input[type="text"].linkText,
-.shareTabView input[type="password"] {
-	width: 100%;
-	box-sizing: border-box;
-	padding-right: 32px;
-	text-overflow: ellipsis;
-}
-
-.shareTabView form {
-	font-size: 100%;
-	margin-left: 0;
-	margin-right: 0;
-}
 
 #shareWithList {
 	list-style-type: none;
 	padding: 0 0 16px;
+	> li {
+		padding-top: 5px;
+		padding-bottom: 5px;
+		white-space: normal;
+		display: inline-flex;
+		align-items: center;
+	}
+	.unshare img {
+		vertical-align: text-bottom;
+		/* properly align icons */
+	}
+	.sharingOptionsGroup {
+		> a .icon {
+			padding: 7px;
+			vertical-align: middle;
+			opacity: 0.5;
+		}
+		.popovermenu:after {
+			right: 3px;
+		}
+	}
+	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;
+	}
+	li .sharingOptionsGroup > .shareOption > label {
+		padding: 6px;
+		margin-right: 8px;
+		vertical-align: text-top;
+	}
 }
 
-#shareWithList > li {
-	padding-top: 5px;
-	padding-bottom: 5px;
-	white-space: normal;
-	display: inline-flex;
-	align-items: center;
-}
-
-#shareWithList .unshare img {
-	vertical-align: text-bottom; /* properly align icons */
-}
-
-#shareWithList .sharingOptionsGroup > a .icon {
-	padding: 7px;
-	vertical-align: middle;
-	opacity: .5;
-}
-
-#shareWithList .sharingOptionsGroup .popovermenu:after {
-	right: 3px;
-}
-
-#shareWithList label input[type=checkbox] {
-	margin-left: 0;
-	position: relative;
-}
-#shareWithList .username {
-	padding-right: 8px;
-	white-space: nowrap;
-	text-overflow: ellipsis;
-	display: inline-block;
-	overflow: hidden;
-	vertical-align: middle;
-}
-#shareWithList li .sharingOptionsGroup > .shareOption > label {
-	padding: 6px;
-	margin-right: 8px;
-	vertical-align: text-top;
-}
-
-.shareTabView .icon-loading-small {
-	display: inline-block;
-	z-index: 1;
-	vertical-align: text-top;
-}
-
-.shareTabView .shareWithList .icon-loading-small:not(.hidden) + span,
-.shareTabView .linkShareView .icon-loading-small:not(.hidden) + input + label:before {
-	/* Hide if loader is visible */
-	display: none !important;
-}
-
-form#newNoteForm,
 .linkShareView {
 	margin-top: 16px;
 }
 
-.shareTabView .linkPass .icon-loading-small {
-	margin-right: 0px;
-}
-
-.shareTabView .icon {
-	background-size: 16px 16px;
-}
-
-
-/* NOTE */
-form#newNoteForm {
-	display: flex;
-	flex-wrap: wrap;
-	.message {
-		flex: 1 1;
-		min-height: 76px;
-		margin-right: 0;
-		border-bottom-right-radius: 0;
-		border-top-right-radius: 0;
+.shareTabView {
+	.linkPass .icon-loading-small {
+		margin-right: 0px;
 	}
-	input {
-		width: 44px;
-		border-bottom-left-radius: 0;
-		border-top-left-radius: 0;
-		margin-left: -1px;
+	.icon {
+		background-size: 16px 16px;
 	}
-}
\ No newline at end of file
+	.icon-loading-small {
+		display: inline-block;
+		z-index: 1;
+		vertical-align: text-top;
+	}
+	.shareWithList .icon-loading-small:not(.hidden) + span,
+	.linkShareView .icon-loading-small:not(.hidden) + input + label:before {
+		/* Hide if loader is visible */
+		display: none !important;
+	}
+}
+
diff --git a/core/css/apps.scss b/core/css/apps.scss
index d524dd94bb7..b294d8c3fee 100644
--- a/core/css/apps.scss
+++ b/core/css/apps.scss
@@ -998,6 +998,11 @@ $popovericon-size: 16px;
 				}
 			}
 		}
+
+		&.hidden {
+			display: none;
+		}
+
 		/* css hack, only first not hidden*/
 		&:not(.hidden):not([style*='display:none']) {
 			&:first-of-type {
diff --git a/core/js/core.json b/core/js/core.json
index 6a6249c294b..502e3a57976 100644
--- a/core/js/core.json
+++ b/core/js/core.json
@@ -38,7 +38,6 @@
 		"shareitemmodel.js",
 		"sharedialogview.js",
 		"sharedialogexpirationview.js",
-		"sharedialognoteview.js",
 		"sharedialoglinkshareview.js",
 		"sharedialogresharerinfoview.js",
 		"sharedialogshareelistview.js",
diff --git a/core/js/merged-share-backend.json b/core/js/merged-share-backend.json
index 48ad5d5340c..d39945b8f79 100644
--- a/core/js/merged-share-backend.json
+++ b/core/js/merged-share-backend.json
@@ -5,7 +5,6 @@
   "sharedialogresharerinfoview.js",
   "sharedialoglinkshareview.js",
   "sharedialogexpirationview.js",
-  "sharedialognoteview.js",
   "sharedialogshareelistview.js",
   "sharedialogview.js",
   "share.js"
diff --git a/core/js/sharedialognoteview.js b/core/js/sharedialognoteview.js
deleted file mode 100644
index 429d9cd942b..00000000000
--- a/core/js/sharedialognoteview.js
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* global moment, Handlebars */
-
-(function() {
-	if (!OC.Share) {
-		OC.Share = {};
-	}
-
-	var TEMPLATE =
-		'	<form id="newNoteForm" data-shareId="{{shareId}}">' +
-		'		<textarea class="message" placeholder="{{placeholder}}">{{note}}</textarea>' +
-		'		<input class="submit icon-confirm has-tooltip" type="submit" value="" title="{{submitText}}"/>' +
-		'	</form>' +
-		'	<div class="error hidden">{{error}}</div>'
-	;
-
-	/**
-	 * @class OCA.Share.ShareDialogNoteView
-	 * @member {OC.Share.ShareItemModel} model
-	 * @member {jQuery} $el
-	 * @memberof OCA.Sharing
-	 * @classdesc
-	 *
-	 * Represents the expiration part in the GUI of the share dialogue
-	 *
-	 */
-	var ShareDialogNoteView = OC.Backbone.View.extend({
-
-		id: 'shareNote',
-
-		className: 'hidden',
-
-		shareId: undefined,
-
-		events: {
-			'submit #newNoteForm': '_onSubmitComment'
-		},
-
-		_onSubmitComment: function(e) {
-			var self = this;
-			var $form = $(e.target);
-			var $submit = $form.find('.submit');
-			var $commentField = $form.find('.message');
-			var $error = $form.siblings('.error');
-			var message = $commentField.val().trim();
-			e.preventDefault();
-
-			if (message.length < 1) {
-				return;
-			}
-
-			$submit.prop('disabled', true);
-			$form.addClass('icon-loading').prop('disabled', true);
-
-			// send data
-			$.ajax({
-				method: 'PUT',
-				url: OC.generateUrl('/ocs/v2.php/apps/files_sharing/api/v1/shares/' + self.shareId),
-				data: { note: message },
-				complete : function() {
-					$submit.prop('disabled', false);
-					$form.removeClass('icon-loading').prop('disabled', false);
-				},
-				error: function() {
-					$error.show();
-					setTimeout(function() {
-						$error.hide();
-					}, 3000);
-				}
-			});
-
-			// update local js object
-			var shares = this.model.get('shares');
-			var share = shares.filter(function (share) {
-				return share.id === self.shareId;
-			});
-			share[0].note = message;
-
-			return message;
-		},
-
-		render: function(shareId) {
-			this.shareId = shareId;
-			var shares = this.model.get('shares');
-			if (!shares) {
-				return;
-			}
-			var share = shares.filter(function (share) {
-				return share.id === shareId;
-			});
-			if (share.length !== 1) {
-				// should not happend
-				return;
-			}
-			this.$el.show();
-			this.$el.html(this.template({
-				note: share[0].note,
-				submitText: t('core', 'Submit the note'),
-				placeholder: t('core', 'Add a note…'),
-				error: t('core', 'An error has occured. Unable to save the note.'),
-				shareId: shareId
-			}));
-
-			this.delegateEvents();
-
-			return this;
-		},
-
-		hide() {
-			this.$el.hide();
-		},
-
-		/**
-		 * @returns {Function} from Handlebars
-		 * @private
-		 */
-		template: function (data) {
-			if (!this._template) {
-				this._template = Handlebars.compile(TEMPLATE);
-			}
-			return this._template(data);
-		}
-
-	});
-
-	OC.Share.ShareDialogNoteView = ShareDialogNoteView;
-
-})();
diff --git a/core/js/sharedialogshareelistview.js b/core/js/sharedialogshareelistview.js
index af4abce17b6..2f561aa66ee 100644
--- a/core/js/sharedialogshareelistview.js
+++ b/core/js/sharedialogshareelistview.js
@@ -121,7 +121,17 @@
 					'</span>' +
 				'</li>' +
 				'<li>' +
-					'<a href="#" class="addnote"><span class="icon-loading-small hidden"></span><span class="icon icon-edit"></span><span>{{addNoteLabel}}</span></a>' +
+					'<a href="#" class="share-add"><span class="icon-loading-small hidden"></span>' +
+					'	<span class="icon icon-edit"></span>' +
+					'	<span>{{addNoteLabel}}</span>' +
+					'	<input type="button" class="share-note-delete icon-delete">' +
+					'</a>' +
+				'</li>' +
+				'<li class="share-note-form hidden">' +
+					'<span class="menuitem icon-note">' +
+					'	<textarea class="share-note">{{shareNote}}</textarea>' +
+					'	<input type="submit" class="icon-confirm share-note-submit" value="" id="add-note-{{shareId}}" />' +
+					'</span>' +
 				'</li>' +
 				'<li>' +
 					'<a href="#" class="unshare"><span class="icon-loading-small hidden"></span><span class="icon icon-delete"></span><span>{{unshareLabel}}</span></a>' +
@@ -161,7 +171,9 @@
 
 		events: {
 			'click .unshare': 'onUnshare',
-			'click .addnote': 'showNoteForm',
+			'click .share-add': 'showNoteForm',
+			'click .share-note-delete': 'deleteNote',
+			'click .share-note-submit': 'updateNote',
 			'click .icon-more': 'onToggleMenu',
 			'click .permissions': 'onPermissionChange',
 			'click .expireDate' : 'onExpireDateChange',
@@ -269,6 +281,7 @@
 				isPasswordSet: hasPassword,
 				secureDropMode: !this.model.hasReadPermission(shareIndex),
 				hasExpireDate: this.model.getExpireDate(shareIndex) !== null,
+				shareNote: this.model.getNote(shareIndex),
 				expireDate: moment(this.model.getExpireDate(shareIndex), 'YYYY-MM-DD').format('DD-MM-YYYY'),
 				passwordPlaceholder: hasPassword ? PASSWORD_PLACEHOLDER : PASSWORD_PLACEHOLDER_MESSAGE,
 			});
@@ -486,7 +499,78 @@
 			var $element = $(event.target);
 			var $li = $element.closest('li[data-share-id]');
 			var shareId = $li.data('share-id');
-			this._noteView.render(shareId);
+			var $menu = $element.closest('li');
+			var $form = $menu.next('li.share-note-form');
+			
+			// show elements
+			$menu.find('.share-note-delete').toggle();
+			$form.toggleClass('hidden');
+		},
+
+		deleteNote(event) {
+			event.preventDefault();
+			event.stopPropagation();
+			var self = this;
+			var $element = $(event.target);
+			var $li = $element.closest('li[data-share-id]');
+			var shareId = $li.data('share-id');
+			var $menu = $element.closest('li');
+			var $form = $menu.next('li.share-note-form');
+
+			console.log($form.find('.share-note'));
+			$form.find('.share-note').val('');
+			
+			self.sendNote('', shareId, $menu);
+		},
+
+		updateNote(event) {
+			event.preventDefault();
+			event.stopPropagation();
+			var self = this;
+			var $element = $(event.target);
+			var $li = $element.closest('li[data-share-id]');
+			var shareId = $li.data('share-id');
+			var $form = $element.closest('li.share-note-form');
+			var $menu = $form.prev('li');
+			var message = $form.find('.share-note').val().trim();
+
+			if (message.length < 1) {
+				return;
+			}
+
+			self.sendNote(message, shareId, $menu);
+
+		},
+
+		sendNote(note, shareId, $menu) {
+			var $form = $menu.next('li.share-note-form');
+			var $submit = $form.find('input.share-note-submit');
+			var $error = $form.find('input.share-note-error');
+
+			$submit.prop('disabled', true);
+			$menu.find('.icon-loading-small').removeClass('hidden');
+			$menu.find('.icon-edit').hide();
+
+			var complete = function() {
+				$submit.prop('disabled', false);
+				$menu.find('.icon-loading-small').addClass('hidden');
+				$menu.find('.icon-edit').show();
+			};
+			var error = function() {
+				$error.show();
+				setTimeout(function() {
+					$error.hide();
+				}, 3000);
+			};
+
+			// send data
+			$.ajax({
+				method: 'PUT',
+				url: OC.generateUrl('/ocs/v2.php/apps/files_sharing/api/v1/shares/' + shareId),
+				data: { note: note },
+				complete : complete,
+				error: error
+			});
 		},
 
 		onUnshare: function(event) {
diff --git a/core/js/sharedialogview.js b/core/js/sharedialogview.js
index 4b5dc80e945..b69bc5026c3 100644
--- a/core/js/sharedialogview.js
+++ b/core/js/sharedialogview.js
@@ -28,7 +28,6 @@
 		'<div class="shareeListView subView"></div>' +
 		'<div class="linkShareView subView"></div>' +
 		'<div class="expirationView subView"></div>' +
-		'<div class="noteView subView"></div>' +
 		'<div class="loading hidden" style="height: 50px"></div>';
 
 	/**
@@ -62,10 +61,7 @@
 
 		/** @type {object} **/
 		expirationView: undefined,
-
-		/** @type {object} **/
-		noteView: undefined,
-
+		
 		/** @type {object} **/
 		shareeListView: undefined,
 
@@ -117,7 +113,6 @@
 				resharerInfoView: 'ShareDialogResharerInfoView',
 				linkShareView: 'ShareDialogLinkShareView',
 				expirationView: 'ShareDialogExpirationView',
-				noteView: 'ShareDialogNoteView',
 				shareeListView: 'ShareDialogShareeListView'
 			};
 
@@ -680,9 +675,6 @@
 			this.expirationView.$el = this.$el.find('.expirationView');
 			this.expirationView.render();
 
-			this.noteView.$el = this.$el.find('.noteView');
-			this.noteView.render();
-
 			this.shareeListView.$el = this.$el.find('.shareeListView');
 			this.shareeListView.render();
 
diff --git a/core/js/shareitemmodel.js b/core/js/shareitemmodel.js
index 93feba9c889..68e55443dd2 100644
--- a/core/js/shareitemmodel.js
+++ b/core/js/shareitemmodel.js
@@ -366,6 +366,10 @@
 			return this._shareExpireDate(shareIndex);
 		},
 
+		getNote: function(shareIndex) {
+			return this._shareNote(shareIndex);
+		},
+
 		/**
 		 * Returns all share entries that only apply to the current item
 		 * (file/folder)
@@ -502,6 +506,15 @@
 			return date2;
 		},
 
+
+		_shareNote: function(shareIndex) {
+			var share = this.get('shares')[shareIndex];
+			if(!_.isObject(share)) {
+				throw "Unknown Share";
+			}
+			return share.note;
+		},
+
 		/**
 		 * @return {int}
 		 */
-- 
GitLab