Skip to content

Commit 4d1f710

Browse files
authored
Merge pull request #18707 from nextcloud/enh/pending_shares_overview
A pending shares overview
2 parents 782901e + 445274c commit 4d1f710

File tree

9 files changed

+178
-3
lines changed

9 files changed

+178
-3
lines changed

apps/files/css/files.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
}
130130
.nav-icon-sharingin,
131131
.nav-icon-sharingout,
132+
.nav-icon-pendingshares,
132133
.nav-icon-shareoverview {
133134
@include icon-color('share', 'files', $color-black);
134135
}

apps/files/tests/Controller/ViewControllerTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,13 @@ public function testIndexWithRegularBrowser() {
288288
'order' => 19,
289289
'name' => \OC::$server->getL10N('files_sharing')->t('Deleted shares'),
290290
],
291+
[
292+
'id' => 'pendingshares',
293+
'appname' => 'files_sharing',
294+
'script' => 'list.php',
295+
'order' => 19,
296+
'name' => \OC::$server->getL10N('files_sharing')->t('Pending shares'),
297+
],
291298
],
292299
'active' => false,
293300
'icon' => '',
@@ -348,6 +355,10 @@ public function testIndexWithRegularBrowser() {
348355
'id' => 'deletedshares',
349356
'content' => null,
350357
],
358+
'pendingshares' => [
359+
'id' => 'pendingshares',
360+
'content' => null
361+
],
351362
'shareoverview' => [
352363
'id' => 'shareoverview',
353364
'content' => null,

apps/files_sharing/appinfo/routes.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@
7575
'url' => '/api/v1/shares',
7676
'verb' => 'POST',
7777
],
78+
[
79+
'name' => 'ShareAPI#pendingShares',
80+
'url' => '/api/v1/shares/pending',
81+
'verb' => 'GET',
82+
],
7883
[
7984
'name' => 'ShareAPI#getShare',
8085
'url' => '/api/v1/shares/{id}',

apps/files_sharing/js/app.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ OCA.Sharing.App = {
2222
_inFileList: null,
2323
_outFileList: null,
2424
_overviewFileList: null,
25+
_pendingFileList: null,
2526

2627
initSharingIn: function($el) {
2728
if (this._inFileList) {
@@ -129,6 +130,33 @@ OCA.Sharing.App = {
129130
return this._deletedFileList
130131
},
131132

133+
initSharingPening: function($el) {
134+
if (this._pendingFileList) {
135+
return this._pendingFileList
136+
}
137+
this._pendingFileList = new OCA.Sharing.FileList(
138+
$el,
139+
{
140+
id: 'shares.pending',
141+
showPending: true,
142+
sharedWithUser: true,
143+
fileActions: this._acceptShareAction(),
144+
config: OCA.Files.App.getFilesConfig(),
145+
// The file list is created when a "show" event is handled, so
146+
// it should be marked as "shown" like it would have been done
147+
// if handling the event with the file list already created.
148+
shown: true,
149+
}
150+
)
151+
152+
this._extendFileList(this._pendingFileList)
153+
this._pendingFileList.appName = t('files_sharing', 'Pending shares')
154+
this._pendingFileList.$el.find('#emptycontent').html('<div class="icon-share"></div>'
155+
+ '<h2>' + t('files_sharing', 'No pending shares') + '</h2>'
156+
+ '<p>' + t('files_sharing', 'Shares you have received but not confirmed will show up here') + '</p>')
157+
return this._pendingFileList
158+
},
159+
132160
initShareingOverview: function($el) {
133161
if (this._overviewFileList) {
134162
return this._overviewFileList
@@ -178,6 +206,12 @@ OCA.Sharing.App = {
178206
}
179207
},
180208

209+
removeSharingPending: function() {
210+
if (this._pendingFileList) {
211+
this._pendingFileList.$fileList.empty()
212+
}
213+
},
214+
181215
removeSharingOverview: function() {
182216
if (this._overviewFileList) {
183217
this._overviewFileList.$fileList.empty()
@@ -249,6 +283,47 @@ OCA.Sharing.App = {
249283
return fileActions
250284
},
251285

286+
_acceptShareAction: function() {
287+
const fileActions = new OCA.Files.FileActions()
288+
fileActions.registerAction({
289+
name: 'Accept share',
290+
displayName: t('files_sharing', 'Accept share'),
291+
mime: 'all',
292+
permissions: OC.PERMISSION_ALL,
293+
iconClass: 'icon-checkmark',
294+
type: OCA.Files.FileActions.TYPE_INLINE,
295+
actionHandler: function(fileName, context) {
296+
const shareId = context.$file.data('shareId')
297+
$.post(OC.linkToOCS('apps/files_sharing/api/v1/shares/pending', 2) + shareId)
298+
.success(function(result) {
299+
context.fileList.remove(context.fileInfoModel.attributes.name)
300+
}).fail(function() {
301+
OC.Notification.showTemporary(t('files_sharing', 'Something happened. Unable to accept the share.'))
302+
})
303+
},
304+
})
305+
fileActions.registerAction({
306+
name: 'Reject share',
307+
displayName: t('files_sharing', 'Reject share'),
308+
mime: 'all',
309+
permissions: OC.PERMISSION_ALL,
310+
iconClass: 'icon-close',
311+
type: OCA.Files.FileActions.TYPE_INLINE,
312+
actionHandler: function(fileName, context) {
313+
const shareId = context.$file.data('shareId')
314+
$.ajax({
315+
url: OC.linkToOCS('apps/files_sharing/api/v1/shares', 2) + shareId,
316+
type: 'DELETE',
317+
}).success(function(result) {
318+
context.fileList.remove(context.fileInfoModel.attributes.name)
319+
}).fail(function() {
320+
OC.Notification.showTemporary(t('files_sharing', 'Something happened. Unable to reject the share.'))
321+
})
322+
},
323+
})
324+
return fileActions
325+
},
326+
252327
_onActionsUpdated: function(ev) {
253328
_.each([this._inFileList, this._outFileList, this._linkFileList], function(list) {
254329
if (!list) {
@@ -297,6 +372,12 @@ $(document).ready(function() {
297372
$('#app-content-deletedshares').on('hide', function() {
298373
OCA.Sharing.App.removeSharingDeleted()
299374
})
375+
$('#app-content-pendingshares').on('show', function(e) {
376+
OCA.Sharing.App.initSharingPening($(e.target))
377+
})
378+
$('#app-content-pendingshares').on('hide', function() {
379+
OCA.Sharing.App.removeSharingPending()
380+
})
300381
$('#app-content-shareoverview').on('show', function(e) {
301382
OCA.Sharing.App.initShareingOverview($(e.target))
302383
})

apps/files_sharing/js/dist/files_sharing.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/files_sharing/js/dist/files_sharing.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/files_sharing/js/sharedfilelist.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
_sharedWithUser: false,
4040
_linksOnly: false,
4141
_showDeleted: false,
42+
_showPending: false,
4243
_clientSideSort: true,
4344
_allowSelection: false,
4445
_isOverview: false,
@@ -62,6 +63,9 @@
6263
if (options && options.showDeleted) {
6364
this._showDeleted = true
6465
}
66+
if (options && options.showPending) {
67+
this._showPending = true
68+
}
6569
if (options && options.isOverview) {
6670
this._isOverview = true
6771
}
@@ -87,7 +91,7 @@
8791
var permission = parseInt($tr.attr('data-permissions')) | OC.PERMISSION_DELETE
8892
$tr.attr('data-permissions', permission)
8993
}
90-
if (this._showDeleted) {
94+
if (this._showDeleted || this._showPending) {
9195
var permission = fileData.permissions
9296
$tr.attr('data-share-permissions', permission)
9397
}
@@ -196,6 +200,18 @@
196200
}
197201
}
198202

203+
var pendingShares = {
204+
url: OC.linkToOCS('apps/files_sharing/api/v1/shares', 2) + 'pending',
205+
/* jshint camelcase: false */
206+
data: {
207+
format: 'json'
208+
},
209+
type: 'GET',
210+
beforeSend: function(xhr) {
211+
xhr.setRequestHeader('OCS-APIREQUEST', 'true')
212+
}
213+
}
214+
199215
var shares = {
200216
url: OC.linkToOCS('apps/files_sharing/api/v1') + 'shares',
201217
/* jshint camelcase: false */
@@ -227,6 +243,8 @@
227243
// and make sure we have 2 promises
228244
if (this._showDeleted) {
229245
promises.push($.ajax(deletedShares))
246+
} else if (this._showPending) {
247+
promises.push($.ajax(pendingShares))
230248
} else {
231249
promises.push($.ajax(shares))
232250

apps/files_sharing/lib/AppInfo/Application.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,15 @@ protected function setupSharingMenus() {
278278
'name' => $l->t('Deleted shares'),
279279
]);
280280

281+
array_push($sharingSublistArray, [
282+
'id' => 'pendingshares',
283+
'appname' => 'files_sharing',
284+
'script' => 'list.php',
285+
'order' => 19,
286+
'name' => $l->t('Pending shares'),
287+
]);
288+
289+
281290
// show_Quick_Access stored as string
282291
\OCA\Files\App::getNavigationManager()->add([
283292
'id' => 'shareoverview',

apps/files_sharing/lib/Controller/ShareAPIController.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,56 @@ public function updateShare(
10791079
return new DataResponse($this->formatShare($share));
10801080
}
10811081

1082+
/**
1083+
* @NoAdminRequired
1084+
*/
1085+
public function pendingShares(): DataResponse {
1086+
$pendingShares = [];
1087+
1088+
$shareTypes = [
1089+
IShare::TYPE_USER,
1090+
IShare::TYPE_GROUP
1091+
];
1092+
1093+
foreach ($shareTypes as $shareType) {
1094+
$shares = $this->shareManager->getSharedWith($this->currentUser, $shareType, null, -1, 0);
1095+
1096+
foreach ($shares as $share) {
1097+
if ($share->getStatus() === IShare::STATUS_PENDING || $share->getStatus() === IShare::STATUS_REJECTED) {
1098+
$pendingShares[] = $share;
1099+
}
1100+
}
1101+
}
1102+
1103+
$result = array_filter(array_map(function (IShare $share) {
1104+
$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
1105+
$nodes = $userFolder->getById($share->getNodeId());
1106+
if (empty($nodes)) {
1107+
// fallback to guessing the path
1108+
$node = $userFolder->get($share->getTarget());
1109+
if ($node === null || $share->getTarget() === '') {
1110+
return null;
1111+
}
1112+
} else {
1113+
$node = $nodes[0];
1114+
}
1115+
1116+
try {
1117+
$formattedShare = $this->formatShare($share, $node);
1118+
$formattedShare['status'] = $share->getStatus();
1119+
$formattedShare['path'] = $share->getNode()->getName();
1120+
$formattedShare['permissions'] = 0;
1121+
return $formattedShare;
1122+
} catch (NotFoundException $e) {
1123+
return null;
1124+
}
1125+
}, $pendingShares), function ($entry) {
1126+
return $entry !== null;
1127+
});
1128+
1129+
return new DataResponse($result);
1130+
}
1131+
10821132
/**
10831133
* @NoAdminRequired
10841134
*

0 commit comments

Comments
 (0)