diff --git a/appinfo/routes.php b/appinfo/routes.php index 205c35391..388bdd1dc 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -24,6 +24,7 @@ ['name' => 'Endpoint#listNotifications', 'url' => '/api/{apiVersion}/notifications', 'verb' => 'GET', 'requirements' => ['apiVersion' => 'v(1|2)']], ['name' => 'Endpoint#getNotification', 'url' => '/api/{apiVersion}/notifications/{id}', 'verb' => 'GET', 'requirements' => ['apiVersion' => 'v(1|2)', 'id' => '\d+']], ['name' => 'Endpoint#deleteNotification', 'url' => '/api/{apiVersion}/notifications/{id}', 'verb' => 'DELETE', 'requirements' => ['apiVersion' => 'v(1|2)', 'id' => '\d+']], + ['name' => 'Endpoint#deleteAllNotifications', 'url' => '/api/{apiVersion}/notifications', 'verb' => 'DELETE', 'requirements' => ['apiVersion' => 'v(1|2)']], ['name' => 'Push#registerDevice', 'url' => '/api/{apiVersion}/push', 'verb' => 'POST', 'requirements' => ['apiVersion' => 'v2']], ['name' => 'Push#removeDevice', 'url' => '/api/{apiVersion}/push', 'verb' => 'DELETE', 'requirements' => ['apiVersion' => 'v2']], ], diff --git a/css/styles.scss b/css/styles.scss index 433524d6a..dc5e7b629 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -44,6 +44,24 @@ } } + .dismiss-all { + display: flex; + opacity: 0.5; + padding: 10px; + margin-left: auto; + margin-right: auto; + + &:hover, + .icon-close { + opacity: 1; + cursor: pointer; + } + + .icon-close { + margin-right: 5px; + } + } + /* Menu arrow */ &:after { right: 101px; diff --git a/docs/ocs-endpoint-v2.md b/docs/ocs-endpoint-v2.md index 5b2038bc8..4518114d1 100644 --- a/docs/ocs-endpoint-v2.md +++ b/docs/ocs-endpoint-v2.md @@ -23,6 +23,7 @@ In order to find out if notifications is installed/enabled on the server you can "list", "get", "delete", + "delete-all", "icons", "rich-strings" ] @@ -150,3 +151,10 @@ In order to get a single notification, you can send a GET request against `/ocs/ In order to delete a notification, you can send a DELETE request against `/ocs/v2.php/apps/notifications/api/v2/notifications/{id}` + + +## Deleting all notifications for a user + +In order to delete all notifications, you can send a DELETE request against `/ocs/v2.php/apps/notifications/api/v2/notifications` + +**Note:** This endpoint was added for Nextcloud 14, so check for the `delete-all` capability first. diff --git a/js-src/components/root.vue b/js-src/components/root.vue index 1706e5efd..053c37a9a 100644 --- a/js-src/components/root.vue +++ b/js-src/components/root.vue @@ -5,7 +5,10 @@
- + +
+ {{ t('notifications', 'Dismiss all notifications') }} +

{{ t('notifications', 'No notifications') }}

@@ -54,6 +57,18 @@ }, methods: { + onDismissAll: function() { + $.ajax({ + url: OC.linkToOCS('apps/notifications/api/v2', 2) + 'notifications', + type: 'DELETE', + success: function () { + this.notifications = []; + }.bind(this), + error: function () { + OC.Notification.showTemporary(t('notifications', 'Failed to dismiss all notifications')); + } + }); + }, onRemove: function(index) { this.notifications.splice(index, 1); } diff --git a/lib/Capabilities.php b/lib/Capabilities.php index 6b832f628..0c0fd3ff9 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -42,6 +42,7 @@ public function getCapabilities() { 'list', 'get', 'delete', + 'delete-all', 'icons', 'rich-strings', ], diff --git a/lib/Controller/EndpointController.php b/lib/Controller/EndpointController.php index 3c430a7ea..f84b6d527 100644 --- a/lib/Controller/EndpointController.php +++ b/lib/Controller/EndpointController.php @@ -157,6 +157,16 @@ public function deleteNotification($id = 0) { return new DataResponse(); } + /** + * @NoAdminRequired + * + * @return DataResponse + */ + public function deleteAllNotifications(): DataResponse { + $this->handler->deleteByUser($this->getCurrentUser()); + return new DataResponse(); + } + /** * Get an Etag for the notification ids * diff --git a/lib/Handler.php b/lib/Handler.php index cba6e13d1..d9fa2c576 100644 --- a/lib/Handler.php +++ b/lib/Handler.php @@ -91,6 +91,21 @@ public function delete(INotification $notification) { $sql->execute(); } + /** + * Delete the notification of a given user + * + * @param string $user + */ + public function deleteByUser(string $user) { + $notification = $this->manager->createNotification(); + try { + $notification->setUser($user); + } catch (\InvalidArgumentException $e) { + return; + } + $this->delete($notification); + } + /** * Delete the notification matching the given id * diff --git a/tests/Integration/features/bootstrap/FeatureContext.php b/tests/Integration/features/bootstrap/FeatureContext.php index 6ea471bf8..aa00f345b 100644 --- a/tests/Integration/features/bootstrap/FeatureContext.php +++ b/tests/Integration/features/bootstrap/FeatureContext.php @@ -214,6 +214,16 @@ public function deleteNotification($toDelete, $api) { $this->sendingTo('DELETE', '/apps/notifications/api/' . $api . '/notifications/' . $this->deletedNotification); } + /** + * @Then /^delete all notifications on (v\d+)$/ + * + * @param string $api + */ + public function deleteAllNotification($api) { + PHPUnit_Framework_Assert::assertNotEmpty($this->notificationIds); + $this->sendingTo('DELETE', '/apps/notifications/api/' . $api . '/notifications'); + } + /** * @Then /^status code is ([0-9]*)$/ * diff --git a/tests/Integration/features/delete-notifications-v1.feature b/tests/Integration/features/delete-notifications-v1.feature index 51167710c..37adaf75e 100644 --- a/tests/Integration/features/delete-notifications-v1.feature +++ b/tests/Integration/features/delete-notifications-v1.feature @@ -40,3 +40,12 @@ Feature: delete-notifications And delete last notification on v1 And status code is 200 And user "test1" has 2 notifications on v1 missing the last one + + Scenario: Delete all notifications + Given user "test1" has notifications + Given user "test1" has notifications + Given user "test1" has notifications + Then user "test1" has 3 notifications on v2 + And delete all notifications on v2 + And status code is 200 + And user "test1" has 0 notifications on v2 diff --git a/tests/Integration/features/delete-notifications-v2.feature b/tests/Integration/features/delete-notifications-v2.feature index 51fbab61a..c3b7b5808 100644 --- a/tests/Integration/features/delete-notifications-v2.feature +++ b/tests/Integration/features/delete-notifications-v2.feature @@ -40,3 +40,12 @@ Feature: delete-notifications And delete last notification on v2 And status code is 200 And user "test1" has 2 notifications on v2 missing the last one + + Scenario: Delete all notifications + Given user "test1" has notifications + Given user "test1" has notifications + Given user "test1" has notifications + Then user "test1" has 3 notifications on v1 + And delete all notifications on v1 + And status code is 200 + And user "test1" has 0 notifications on v1 diff --git a/tests/Unit/AppInfo/RoutesTest.php b/tests/Unit/AppInfo/RoutesTest.php index 4e584321a..d47226501 100644 --- a/tests/Unit/AppInfo/RoutesTest.php +++ b/tests/Unit/AppInfo/RoutesTest.php @@ -32,11 +32,11 @@ */ class RoutesTest extends TestCase { public function testRoutes() { - $routes = include(__DIR__ . '/../../../appinfo/routes.php'); + $routes = include __DIR__ . '/../../../appinfo/routes.php'; $this->assertInternalType('array', $routes); $this->assertCount(1, $routes); $this->assertArrayHasKey('ocs', $routes); $this->assertInternalType('array', $routes['ocs']); - $this->assertCount(5, $routes['ocs']); + $this->assertCount(6, $routes['ocs']); } } diff --git a/tests/Unit/CapabilitiesTest.php b/tests/Unit/CapabilitiesTest.php index 802d2b9e1..c08509e70 100644 --- a/tests/Unit/CapabilitiesTest.php +++ b/tests/Unit/CapabilitiesTest.php @@ -35,6 +35,7 @@ public function testGetCapabilities() { 'list', 'get', 'delete', + 'delete-all', 'icons', 'rich-strings', ], diff --git a/tests/Unit/Controller/EndpointControllerTest.php b/tests/Unit/Controller/EndpointControllerTest.php index 64c170279..3d7c1f61b 100644 --- a/tests/Unit/Controller/EndpointControllerTest.php +++ b/tests/Unit/Controller/EndpointControllerTest.php @@ -400,6 +400,23 @@ public function testDeleteNotificationNoId() { $this->assertSame(Http::STATUS_NOT_FOUND, $response->getStatus()); } + /** + * @dataProvider dataDeleteNotification + * @param int $_ + * @param string $username + */ + public function testDeleteAllNotifications($_, $username) { + $controller = $this->getController([], $username); + + $this->handler->expects($this->once()) + ->method('deleteByUser') + ->with($username); + + $response = $controller->deleteAllNotifications(); + $this->assertInstanceOf(DataResponse::class, $response); + $this->assertSame(Http::STATUS_OK, $response->getStatus()); + } + public function dataNotificationToArray() { return [ ['v1', 42, 'app1', 'user1', 1234, 'type1', 42, 'subject1', '', [], 'message1', 'richMessage 1', ['richMessage param'], 'link1', 'icon1', [], []], diff --git a/tests/Unit/bootstrap.php b/tests/Unit/bootstrap.php index a5941d050..20fa3603a 100644 --- a/tests/Unit/bootstrap.php +++ b/tests/Unit/bootstrap.php @@ -32,8 +32,4 @@ // Fix for "Autoload path not allowed: .../notifications/tests/testcase.php" \OC_App::loadApp('notifications'); -if(!class_exists('PHPUnit_Framework_TestCase')) { - require_once('PHPUnit/Autoload.php'); -} - OC_Hook::clear();