diff options
-rw-r--r-- | client/src/app/+my-library/my-history/my-history.component.html | 12 | ||||
-rw-r--r-- | client/src/app/+my-library/my-history/my-history.component.scss | 5 | ||||
-rw-r--r-- | client/src/app/+my-library/my-history/my-history.component.ts | 15 | ||||
-rw-r--r-- | client/src/app/shared/shared-main/users/user-history.service.ts | 8 | ||||
-rw-r--r-- | server/controllers/api/users/my-history.ts | 23 | ||||
-rw-r--r-- | server/middlewares/validators/user-history.ts | 24 | ||||
-rw-r--r-- | server/models/user/user-video-history.ts | 11 | ||||
-rw-r--r-- | server/tests/api/check-params/videos-history.ts | 37 | ||||
-rw-r--r-- | server/tests/api/videos/videos-history.ts | 36 | ||||
-rw-r--r-- | shared/server-commands/videos/history-command.ts | 19 | ||||
-rw-r--r-- | support/doc/api/openapi.yaml | 17 |
11 files changed, 181 insertions, 26 deletions
diff --git a/client/src/app/+my-library/my-history/my-history.component.html b/client/src/app/+my-library/my-history/my-history.component.html index 8e564cf93..14bf01804 100644 --- a/client/src/app/+my-library/my-history/my-history.component.html +++ b/client/src/app/+my-library/my-history/my-history.component.html | |||
@@ -13,9 +13,9 @@ | |||
13 | <label i18n>Track watch history</label> | 13 | <label i18n>Track watch history</label> |
14 | </div> | 14 | </div> |
15 | 15 | ||
16 | <button class="delete-history" (click)="deleteHistory()" i18n> | 16 | <button class="delete-history" (click)="clearAllHistory()" i18n> |
17 | <my-global-icon iconName="delete" aria-hidden="true"></my-global-icon> | 17 | <my-global-icon iconName="delete" aria-hidden="true"></my-global-icon> |
18 | Delete history | 18 | Clear all history |
19 | </button> | 19 | </button> |
20 | </div> | 20 | </div> |
21 | 21 | ||
@@ -30,4 +30,10 @@ | |||
30 | [enableSelection]="false" | 30 | [enableSelection]="false" |
31 | [disabled]="disabled" | 31 | [disabled]="disabled" |
32 | #videosSelection | 32 | #videosSelection |
33 | ></my-videos-selection> | 33 | > |
34 | <ng-template ptTemplate="rowButtons" let-video> | ||
35 | <div class="action-button"> | ||
36 | <my-delete-button i18n-label label="Delete from history" (click)="deleteHistoryElement(video)"></my-delete-button> | ||
37 | </div> | ||
38 | </ng-template> | ||
39 | </my-videos-selection> | ||
diff --git a/client/src/app/+my-library/my-history/my-history.component.scss b/client/src/app/+my-library/my-history/my-history.component.scss index cb8507569..3257b2215 100644 --- a/client/src/app/+my-library/my-history/my-history.component.scss +++ b/client/src/app/+my-library/my-history/my-history.component.scss | |||
@@ -53,6 +53,11 @@ | |||
53 | @include row-blocks($column-responsive: false); | 53 | @include row-blocks($column-responsive: false); |
54 | } | 54 | } |
55 | 55 | ||
56 | .action-button { | ||
57 | display: flex; | ||
58 | align-self: flex-end; | ||
59 | } | ||
60 | |||
56 | @media screen and (max-width: $small-view) { | 61 | @media screen and (max-width: $small-view) { |
57 | .top-buttons { | 62 | .top-buttons { |
58 | grid-template-columns: auto 1fr auto; | 63 | grid-template-columns: auto 1fr auto; |
diff --git a/client/src/app/+my-library/my-history/my-history.component.ts b/client/src/app/+my-library/my-history/my-history.component.ts index 95cfaee41..34efe5558 100644 --- a/client/src/app/+my-library/my-history/my-history.component.ts +++ b/client/src/app/+my-library/my-history/my-history.component.ts | |||
@@ -123,14 +123,25 @@ export class MyHistoryComponent implements OnInit, DisableForReuseHook { | |||
123 | }) | 123 | }) |
124 | } | 124 | } |
125 | 125 | ||
126 | async deleteHistory () { | 126 | deleteHistoryElement (video: Video) { |
127 | this.userHistoryService.deleteUserVideoHistoryElement(video) | ||
128 | .subscribe({ | ||
129 | next: () => { | ||
130 | this.videos = this.videos.filter(v => v.id !== video.id) | ||
131 | }, | ||
132 | |||
133 | error: err => this.notifier.error(err.message) | ||
134 | }) | ||
135 | } | ||
136 | |||
137 | async clearAllHistory () { | ||
127 | const title = $localize`Delete videos history` | 138 | const title = $localize`Delete videos history` |
128 | const message = $localize`Are you sure you want to delete all your videos history?` | 139 | const message = $localize`Are you sure you want to delete all your videos history?` |
129 | 140 | ||
130 | const res = await this.confirmService.confirm(message, title) | 141 | const res = await this.confirmService.confirm(message, title) |
131 | if (res !== true) return | 142 | if (res !== true) return |
132 | 143 | ||
133 | this.userHistoryService.deleteUserVideosHistory() | 144 | this.userHistoryService.clearAllUserVideosHistory() |
134 | .subscribe({ | 145 | .subscribe({ |
135 | next: () => { | 146 | next: () => { |
136 | this.notifier.success($localize`Videos history deleted`) | 147 | this.notifier.success($localize`Videos history deleted`) |
diff --git a/client/src/app/shared/shared-main/users/user-history.service.ts b/client/src/app/shared/shared-main/users/user-history.service.ts index a4841897d..e28bcdca9 100644 --- a/client/src/app/shared/shared-main/users/user-history.service.ts +++ b/client/src/app/shared/shared-main/users/user-history.service.ts | |||
@@ -34,7 +34,13 @@ export class UserHistoryService { | |||
34 | ) | 34 | ) |
35 | } | 35 | } |
36 | 36 | ||
37 | deleteUserVideosHistory () { | 37 | deleteUserVideoHistoryElement (video: Video) { |
38 | return this.authHttp | ||
39 | .delete(UserHistoryService.BASE_USER_VIDEOS_HISTORY_URL + '/' + video.id) | ||
40 | .pipe(catchError(err => this.restExtractor.handleError(err))) | ||
41 | } | ||
42 | |||
43 | clearAllUserVideosHistory () { | ||
38 | return this.authHttp | 44 | return this.authHttp |
39 | .post(UserHistoryService.BASE_USER_VIDEOS_HISTORY_URL + '/remove', {}) | 45 | .post(UserHistoryService.BASE_USER_VIDEOS_HISTORY_URL + '/remove', {}) |
40 | .pipe( | 46 | .pipe( |
diff --git a/server/controllers/api/users/my-history.ts b/server/controllers/api/users/my-history.ts index 2fcb25acf..bc5b40f59 100644 --- a/server/controllers/api/users/my-history.ts +++ b/server/controllers/api/users/my-history.ts | |||
@@ -9,7 +9,8 @@ import { | |||
9 | paginationValidator, | 9 | paginationValidator, |
10 | setDefaultPagination, | 10 | setDefaultPagination, |
11 | userHistoryListValidator, | 11 | userHistoryListValidator, |
12 | userHistoryRemoveValidator | 12 | userHistoryRemoveAllValidator, |
13 | userHistoryRemoveElementValidator | ||
13 | } from '../../../middlewares' | 14 | } from '../../../middlewares' |
14 | import { UserVideoHistoryModel } from '../../../models/user/user-video-history' | 15 | import { UserVideoHistoryModel } from '../../../models/user/user-video-history' |
15 | 16 | ||
@@ -23,10 +24,16 @@ myVideosHistoryRouter.get('/me/history/videos', | |||
23 | asyncMiddleware(listMyVideosHistory) | 24 | asyncMiddleware(listMyVideosHistory) |
24 | ) | 25 | ) |
25 | 26 | ||
27 | myVideosHistoryRouter.delete('/me/history/videos/:videoId', | ||
28 | authenticate, | ||
29 | userHistoryRemoveElementValidator, | ||
30 | asyncMiddleware(removeUserHistoryElement) | ||
31 | ) | ||
32 | |||
26 | myVideosHistoryRouter.post('/me/history/videos/remove', | 33 | myVideosHistoryRouter.post('/me/history/videos/remove', |
27 | authenticate, | 34 | authenticate, |
28 | userHistoryRemoveValidator, | 35 | userHistoryRemoveAllValidator, |
29 | asyncRetryTransactionMiddleware(removeUserHistory) | 36 | asyncRetryTransactionMiddleware(removeAllUserHistory) |
30 | ) | 37 | ) |
31 | 38 | ||
32 | // --------------------------------------------------------------------------- | 39 | // --------------------------------------------------------------------------- |
@@ -45,7 +52,15 @@ async function listMyVideosHistory (req: express.Request, res: express.Response) | |||
45 | return res.json(getFormattedObjects(resultList.data, resultList.total)) | 52 | return res.json(getFormattedObjects(resultList.data, resultList.total)) |
46 | } | 53 | } |
47 | 54 | ||
48 | async function removeUserHistory (req: express.Request, res: express.Response) { | 55 | async function removeUserHistoryElement (req: express.Request, res: express.Response) { |
56 | const user = res.locals.oauth.token.User | ||
57 | |||
58 | await UserVideoHistoryModel.removeUserHistoryElement(user, parseInt(req.params.videoId + '')) | ||
59 | |||
60 | return res.sendStatus(HttpStatusCode.NO_CONTENT_204) | ||
61 | } | ||
62 | |||
63 | async function removeAllUserHistory (req: express.Request, res: express.Response) { | ||
49 | const user = res.locals.oauth.token.User | 64 | const user = res.locals.oauth.token.User |
50 | const beforeDate = req.body.beforeDate || null | 65 | const beforeDate = req.body.beforeDate || null |
51 | 66 | ||
diff --git a/server/middlewares/validators/user-history.ts b/server/middlewares/validators/user-history.ts index f9be26627..541910be5 100644 --- a/server/middlewares/validators/user-history.ts +++ b/server/middlewares/validators/user-history.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { body, query } from 'express-validator' | 2 | import { body, param, query } from 'express-validator' |
3 | import { exists, isDateValid } from '../../helpers/custom-validators/misc' | 3 | import { exists, isDateValid, isIdValid } from '../../helpers/custom-validators/misc' |
4 | import { logger } from '../../helpers/logger' | 4 | import { logger } from '../../helpers/logger' |
5 | import { areValidationErrors } from './shared' | 5 | import { areValidationErrors } from './shared' |
6 | 6 | ||
@@ -18,13 +18,26 @@ const userHistoryListValidator = [ | |||
18 | } | 18 | } |
19 | ] | 19 | ] |
20 | 20 | ||
21 | const userHistoryRemoveValidator = [ | 21 | const userHistoryRemoveAllValidator = [ |
22 | body('beforeDate') | 22 | body('beforeDate') |
23 | .optional() | 23 | .optional() |
24 | .custom(isDateValid).withMessage('Should have a before date that conforms to ISO 8601'), | 24 | .custom(isDateValid).withMessage('Should have a before date that conforms to ISO 8601'), |
25 | 25 | ||
26 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | 26 | (req: express.Request, res: express.Response, next: express.NextFunction) => { |
27 | logger.debug('Checking userHistoryRemoveValidator parameters', { parameters: req.body }) | 27 | logger.debug('Checking userHistoryRemoveAllValidator parameters', { parameters: req.body }) |
28 | |||
29 | if (areValidationErrors(req, res)) return | ||
30 | |||
31 | return next() | ||
32 | } | ||
33 | ] | ||
34 | |||
35 | const userHistoryRemoveElementValidator = [ | ||
36 | param('videoId') | ||
37 | .custom(isIdValid).withMessage('Should have a valid video id'), | ||
38 | |||
39 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
40 | logger.debug('Checking userHistoryRemoveElementValidator parameters', { parameters: req.params }) | ||
28 | 41 | ||
29 | if (areValidationErrors(req, res)) return | 42 | if (areValidationErrors(req, res)) return |
30 | 43 | ||
@@ -36,5 +49,6 @@ const userHistoryRemoveValidator = [ | |||
36 | 49 | ||
37 | export { | 50 | export { |
38 | userHistoryListValidator, | 51 | userHistoryListValidator, |
39 | userHistoryRemoveValidator | 52 | userHistoryRemoveElementValidator, |
53 | userHistoryRemoveAllValidator | ||
40 | } | 54 | } |
diff --git a/server/models/user/user-video-history.ts b/server/models/user/user-video-history.ts index 92f4fe7a1..f4d0889a1 100644 --- a/server/models/user/user-video-history.ts +++ b/server/models/user/user-video-history.ts | |||
@@ -69,6 +69,17 @@ export class UserVideoHistoryModel extends Model<Partial<AttributesOnly<UserVide | |||
69 | }) | 69 | }) |
70 | } | 70 | } |
71 | 71 | ||
72 | static removeUserHistoryElement (user: MUserId, videoId: number) { | ||
73 | const query: DestroyOptions = { | ||
74 | where: { | ||
75 | userId: user.id, | ||
76 | videoId | ||
77 | } | ||
78 | } | ||
79 | |||
80 | return UserVideoHistoryModel.destroy(query) | ||
81 | } | ||
82 | |||
72 | static removeUserHistoryBefore (user: MUserId, beforeDate: string, t: Transaction) { | 83 | static removeUserHistoryBefore (user: MUserId, beforeDate: string, t: Transaction) { |
73 | const query: DestroyOptions = { | 84 | const query: DestroyOptions = { |
74 | where: { | 85 | where: { |
diff --git a/server/tests/api/check-params/videos-history.ts b/server/tests/api/check-params/videos-history.ts index 31a0752c7..82f38b7b4 100644 --- a/server/tests/api/check-params/videos-history.ts +++ b/server/tests/api/check-params/videos-history.ts | |||
@@ -6,6 +6,7 @@ import { HttpStatusCode } from '@shared/models' | |||
6 | import { | 6 | import { |
7 | cleanupTests, | 7 | cleanupTests, |
8 | createSingleServer, | 8 | createSingleServer, |
9 | makeDeleteRequest, | ||
9 | makeGetRequest, | 10 | makeGetRequest, |
10 | makePostBodyRequest, | 11 | makePostBodyRequest, |
11 | makePutBodyRequest, | 12 | makePutBodyRequest, |
@@ -18,6 +19,7 @@ describe('Test videos history API validator', function () { | |||
18 | const myHistoryRemove = myHistoryPath + '/remove' | 19 | const myHistoryRemove = myHistoryPath + '/remove' |
19 | let watchingPath: string | 20 | let watchingPath: string |
20 | let server: PeerTubeServer | 21 | let server: PeerTubeServer |
22 | let videoId: number | ||
21 | 23 | ||
22 | // --------------------------------------------------------------- | 24 | // --------------------------------------------------------------- |
23 | 25 | ||
@@ -28,8 +30,9 @@ describe('Test videos history API validator', function () { | |||
28 | 30 | ||
29 | await setAccessTokensToServers([ server ]) | 31 | await setAccessTokensToServers([ server ]) |
30 | 32 | ||
31 | const { uuid } = await server.videos.upload() | 33 | const { id, uuid } = await server.videos.upload() |
32 | watchingPath = '/api/v1/videos/' + uuid + '/watching' | 34 | watchingPath = '/api/v1/videos/' + uuid + '/watching' |
35 | videoId = id | ||
33 | }) | 36 | }) |
34 | 37 | ||
35 | describe('When notifying a user is watching a video', function () { | 38 | describe('When notifying a user is watching a video', function () { |
@@ -106,7 +109,37 @@ describe('Test videos history API validator', function () { | |||
106 | }) | 109 | }) |
107 | }) | 110 | }) |
108 | 111 | ||
109 | describe('When removing user videos history', function () { | 112 | describe('When removing a specific user video history element', function () { |
113 | let path: string | ||
114 | |||
115 | before(function () { | ||
116 | path = myHistoryPath + '/' + videoId | ||
117 | }) | ||
118 | |||
119 | it('Should fail with an unauthenticated user', async function () { | ||
120 | await makeDeleteRequest({ url: server.url, path, expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | ||
121 | }) | ||
122 | |||
123 | it('Should fail with a bad videoId parameter', async function () { | ||
124 | await makeDeleteRequest({ | ||
125 | url: server.url, | ||
126 | token: server.accessToken, | ||
127 | path: myHistoryRemove + '/hi', | ||
128 | expectedStatus: HttpStatusCode.BAD_REQUEST_400 | ||
129 | }) | ||
130 | }) | ||
131 | |||
132 | it('Should succeed with the correct parameters', async function () { | ||
133 | await makeDeleteRequest({ | ||
134 | url: server.url, | ||
135 | token: server.accessToken, | ||
136 | path, | ||
137 | expectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
138 | }) | ||
139 | }) | ||
140 | }) | ||
141 | |||
142 | describe('When removing all user videos history', function () { | ||
110 | it('Should fail with an unauthenticated user', async function () { | 143 | it('Should fail with an unauthenticated user', async function () { |
111 | await makePostBodyRequest({ url: server.url, path: myHistoryPath + '/remove', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) | 144 | await makePostBodyRequest({ url: server.url, path: myHistoryPath + '/remove', expectedStatus: HttpStatusCode.UNAUTHORIZED_401 }) |
112 | }) | 145 | }) |
diff --git a/server/tests/api/videos/videos-history.ts b/server/tests/api/videos/videos-history.ts index 4e5ba13aa..8648c97f0 100644 --- a/server/tests/api/videos/videos-history.ts +++ b/server/tests/api/videos/videos-history.ts | |||
@@ -17,6 +17,7 @@ const expect = chai.expect | |||
17 | 17 | ||
18 | describe('Test videos history', function () { | 18 | describe('Test videos history', function () { |
19 | let server: PeerTubeServer = null | 19 | let server: PeerTubeServer = null |
20 | let video1Id: number | ||
20 | let video1UUID: string | 21 | let video1UUID: string |
21 | let video2UUID: string | 22 | let video2UUID: string |
22 | let video3UUID: string | 23 | let video3UUID: string |
@@ -34,8 +35,9 @@ describe('Test videos history', function () { | |||
34 | command = server.history | 35 | command = server.history |
35 | 36 | ||
36 | { | 37 | { |
37 | const { uuid } = await server.videos.upload({ attributes: { name: 'video 1' } }) | 38 | const { id, uuid } = await server.videos.upload({ attributes: { name: 'video 1' } }) |
38 | video1UUID = uuid | 39 | video1UUID = uuid |
40 | video1Id = id | ||
39 | } | 41 | } |
40 | 42 | ||
41 | { | 43 | { |
@@ -68,8 +70,8 @@ describe('Test videos history', function () { | |||
68 | }) | 70 | }) |
69 | 71 | ||
70 | it('Should watch the first and second video', async function () { | 72 | it('Should watch the first and second video', async function () { |
71 | await command.wathVideo({ videoId: video2UUID, currentTime: 8 }) | 73 | await command.watchVideo({ videoId: video2UUID, currentTime: 8 }) |
72 | await command.wathVideo({ videoId: video1UUID, currentTime: 3 }) | 74 | await command.watchVideo({ videoId: video1UUID, currentTime: 3 }) |
73 | }) | 75 | }) |
74 | 76 | ||
75 | it('Should return the correct history when listing, searching and getting videos', async function () { | 77 | it('Should return the correct history when listing, searching and getting videos', async function () { |
@@ -122,7 +124,7 @@ describe('Test videos history', function () { | |||
122 | 124 | ||
123 | it('Should have these videos when listing my history', async function () { | 125 | it('Should have these videos when listing my history', async function () { |
124 | video3WatchedDate = new Date() | 126 | video3WatchedDate = new Date() |
125 | await command.wathVideo({ videoId: video3UUID, currentTime: 2 }) | 127 | await command.watchVideo({ videoId: video3UUID, currentTime: 2 }) |
126 | 128 | ||
127 | const body = await command.list() | 129 | const body = await command.list() |
128 | 130 | ||
@@ -150,7 +152,7 @@ describe('Test videos history', function () { | |||
150 | }) | 152 | }) |
151 | 153 | ||
152 | it('Should clear my history', async function () { | 154 | it('Should clear my history', async function () { |
153 | await command.remove({ beforeDate: video3WatchedDate.toISOString() }) | 155 | await command.removeAll({ beforeDate: video3WatchedDate.toISOString() }) |
154 | }) | 156 | }) |
155 | 157 | ||
156 | it('Should have my history cleared', async function () { | 158 | it('Should have my history cleared', async function () { |
@@ -166,7 +168,7 @@ describe('Test videos history', function () { | |||
166 | videosHistoryEnabled: false | 168 | videosHistoryEnabled: false |
167 | }) | 169 | }) |
168 | 170 | ||
169 | await command.wathVideo({ videoId: video2UUID, currentTime: 8, expectedStatus: HttpStatusCode.CONFLICT_409 }) | 171 | await command.watchVideo({ videoId: video2UUID, currentTime: 8, expectedStatus: HttpStatusCode.CONFLICT_409 }) |
170 | }) | 172 | }) |
171 | 173 | ||
172 | it('Should re-enable videos history', async function () { | 174 | it('Should re-enable videos history', async function () { |
@@ -174,7 +176,7 @@ describe('Test videos history', function () { | |||
174 | videosHistoryEnabled: true | 176 | videosHistoryEnabled: true |
175 | }) | 177 | }) |
176 | 178 | ||
177 | await command.wathVideo({ videoId: video1UUID, currentTime: 8 }) | 179 | await command.watchVideo({ videoId: video1UUID, currentTime: 8 }) |
178 | 180 | ||
179 | const body = await command.list() | 181 | const body = await command.list() |
180 | expect(body.total).to.equal(2) | 182 | expect(body.total).to.equal(2) |
@@ -212,6 +214,26 @@ describe('Test videos history', function () { | |||
212 | expect(body.total).to.equal(0) | 214 | expect(body.total).to.equal(0) |
213 | }) | 215 | }) |
214 | 216 | ||
217 | it('Should delete a specific history element', async function () { | ||
218 | { | ||
219 | await command.watchVideo({ videoId: video1UUID, currentTime: 4 }) | ||
220 | await command.watchVideo({ videoId: video2UUID, currentTime: 8 }) | ||
221 | } | ||
222 | |||
223 | { | ||
224 | const body = await command.list() | ||
225 | expect(body.total).to.equal(2) | ||
226 | } | ||
227 | |||
228 | { | ||
229 | await command.removeElement({ videoId: video1Id }) | ||
230 | |||
231 | const body = await command.list() | ||
232 | expect(body.total).to.equal(1) | ||
233 | expect(body.data[0].uuid).to.equal(video2UUID) | ||
234 | } | ||
235 | }) | ||
236 | |||
215 | after(async function () { | 237 | after(async function () { |
216 | await cleanupTests([ server ]) | 238 | await cleanupTests([ server ]) |
217 | }) | 239 | }) |
diff --git a/shared/server-commands/videos/history-command.ts b/shared/server-commands/videos/history-command.ts index 13b7150c1..e9dc63462 100644 --- a/shared/server-commands/videos/history-command.ts +++ b/shared/server-commands/videos/history-command.ts | |||
@@ -3,7 +3,7 @@ import { AbstractCommand, OverrideCommandOptions } from '../shared' | |||
3 | 3 | ||
4 | export class HistoryCommand extends AbstractCommand { | 4 | export class HistoryCommand extends AbstractCommand { |
5 | 5 | ||
6 | wathVideo (options: OverrideCommandOptions & { | 6 | watchVideo (options: OverrideCommandOptions & { |
7 | videoId: number | string | 7 | videoId: number | string |
8 | currentTime: number | 8 | currentTime: number |
9 | }) { | 9 | }) { |
@@ -40,7 +40,22 @@ export class HistoryCommand extends AbstractCommand { | |||
40 | }) | 40 | }) |
41 | } | 41 | } |
42 | 42 | ||
43 | remove (options: OverrideCommandOptions & { | 43 | removeElement (options: OverrideCommandOptions & { |
44 | videoId: number | ||
45 | }) { | ||
46 | const { videoId } = options | ||
47 | const path = '/api/v1/users/me/history/videos/' + videoId | ||
48 | |||
49 | return this.deleteRequest({ | ||
50 | ...options, | ||
51 | |||
52 | path, | ||
53 | implicitToken: true, | ||
54 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
55 | }) | ||
56 | } | ||
57 | |||
58 | removeAll (options: OverrideCommandOptions & { | ||
44 | beforeDate?: string | 59 | beforeDate?: string |
45 | } = {}) { | 60 | } = {}) { |
46 | const { beforeDate } = options | 61 | const { beforeDate } = options |
diff --git a/support/doc/api/openapi.yaml b/support/doc/api/openapi.yaml index 5746d3a47..5bf3f13cc 100644 --- a/support/doc/api/openapi.yaml +++ b/support/doc/api/openapi.yaml | |||
@@ -1476,6 +1476,23 @@ paths: | |||
1476 | schema: | 1476 | schema: |
1477 | $ref: '#/components/schemas/VideoListResponse' | 1477 | $ref: '#/components/schemas/VideoListResponse' |
1478 | 1478 | ||
1479 | /users/me/history/videos/{videoId}: | ||
1480 | delete: | ||
1481 | summary: Delete history element | ||
1482 | security: | ||
1483 | - OAuth2: [] | ||
1484 | tags: | ||
1485 | - My History | ||
1486 | parameters: | ||
1487 | - name: videoId | ||
1488 | in: path | ||
1489 | required: true | ||
1490 | schema: | ||
1491 | $ref: '#/components/schemas/Video/properties/id' | ||
1492 | responses: | ||
1493 | '204': | ||
1494 | description: successful operation | ||
1495 | |||
1479 | /users/me/history/videos/remove: | 1496 | /users/me/history/videos/remove: |
1480 | post: | 1497 | post: |
1481 | summary: Clear video history | 1498 | summary: Clear video history |