diff options
8 files changed, 47 insertions, 5 deletions
diff --git a/client/src/app/shared/forms/form-validators/video-validators.service.ts b/client/src/app/shared/forms/form-validators/video-validators.service.ts index 81ed0666f..e3f7a0969 100644 --- a/client/src/app/shared/forms/form-validators/video-validators.service.ts +++ b/client/src/app/shared/forms/form-validators/video-validators.service.ts | |||
@@ -16,6 +16,7 @@ export class VideoValidatorsService { | |||
16 | readonly VIDEO_TAGS: BuildFormValidator | 16 | readonly VIDEO_TAGS: BuildFormValidator |
17 | readonly VIDEO_SUPPORT: BuildFormValidator | 17 | readonly VIDEO_SUPPORT: BuildFormValidator |
18 | readonly VIDEO_SCHEDULE_PUBLICATION_AT: BuildFormValidator | 18 | readonly VIDEO_SCHEDULE_PUBLICATION_AT: BuildFormValidator |
19 | readonly VIDEO_ORIGINALLY_PUBLISHED_AT: BuildFormValidator | ||
19 | 20 | ||
20 | constructor (private i18n: I18n) { | 21 | constructor (private i18n: I18n) { |
21 | 22 | ||
@@ -92,5 +93,10 @@ export class VideoValidatorsService { | |||
92 | 'required': this.i18n('A date is required to schedule video update.') | 93 | 'required': this.i18n('A date is required to schedule video update.') |
93 | } | 94 | } |
94 | } | 95 | } |
96 | |||
97 | this.VIDEO_ORIGINALLY_PUBLISHED_AT = { | ||
98 | VALIDATORS: [ ], | ||
99 | MESSAGES: {} | ||
100 | } | ||
95 | } | 101 | } |
96 | } | 102 | } |
diff --git a/client/src/app/shared/video-import/video-import.service.ts b/client/src/app/shared/video-import/video-import.service.ts index 7ae66ddfc..11a7694c8 100644 --- a/client/src/app/shared/video-import/video-import.service.ts +++ b/client/src/app/shared/video-import/video-import.service.ts | |||
@@ -67,6 +67,7 @@ export class VideoImportService { | |||
67 | const description = video.description || null | 67 | const description = video.description || null |
68 | const support = video.support || null | 68 | const support = video.support || null |
69 | const scheduleUpdate = video.scheduleUpdate || null | 69 | const scheduleUpdate = video.scheduleUpdate || null |
70 | const originallyPublishedAt = video.originallyPublishedAt || null | ||
70 | 71 | ||
71 | return { | 72 | return { |
72 | name: video.name, | 73 | name: video.name, |
@@ -83,7 +84,8 @@ export class VideoImportService { | |||
83 | commentsEnabled: video.commentsEnabled, | 84 | commentsEnabled: video.commentsEnabled, |
84 | thumbnailfile: video.thumbnailfile, | 85 | thumbnailfile: video.thumbnailfile, |
85 | previewfile: video.previewfile, | 86 | previewfile: video.previewfile, |
86 | scheduleUpdate | 87 | scheduleUpdate, |
88 | originallyPublishedAt | ||
87 | } | 89 | } |
88 | } | 90 | } |
89 | 91 | ||
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts index 55844f988..5d258891f 100644 --- a/client/src/app/shared/video/video.service.ts +++ b/client/src/app/shared/video/video.service.ts | |||
@@ -81,6 +81,7 @@ export class VideoService implements VideosProvider { | |||
81 | const description = video.description || null | 81 | const description = video.description || null |
82 | const support = video.support || null | 82 | const support = video.support || null |
83 | const scheduleUpdate = video.scheduleUpdate || null | 83 | const scheduleUpdate = video.scheduleUpdate || null |
84 | const originallyPublishedAt = video.originallyPublishedAt || null | ||
84 | 85 | ||
85 | const body: VideoUpdate = { | 86 | const body: VideoUpdate = { |
86 | name: video.name, | 87 | name: video.name, |
@@ -97,7 +98,8 @@ export class VideoService implements VideosProvider { | |||
97 | commentsEnabled: video.commentsEnabled, | 98 | commentsEnabled: video.commentsEnabled, |
98 | thumbnailfile: video.thumbnailfile, | 99 | thumbnailfile: video.thumbnailfile, |
99 | previewfile: video.previewfile, | 100 | previewfile: video.previewfile, |
100 | scheduleUpdate | 101 | scheduleUpdate, |
102 | originallyPublishedAt | ||
101 | } | 103 | } |
102 | 104 | ||
103 | const data = objectToFormData(body) | 105 | const data = objectToFormData(body) |
diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.html b/client/src/app/videos/+video-edit/shared/video-edit.component.html index bd52d686a..23a71a068 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.html +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.html | |||
@@ -114,6 +114,20 @@ | |||
114 | </div> | 114 | </div> |
115 | </div> | 115 | </div> |
116 | 116 | ||
117 | <div class="form-group"> | ||
118 | <label i18n for="originallyPublishedAt">Original publication date</label> | ||
119 | <my-help i18n-preHtml preHtml="This is the date when the content was originally published (e.g. the release date for a film)"></my-help> | ||
120 | <p-calendar | ||
121 | id="originallyPublishedAt" formControlName="originallyPublishedAt" [dateFormat]="calendarDateFormat" | ||
122 | [locale]="calendarLocale" [showTime]="true" [hideOnDateTimeSelect]="true" [monthNavigator]="true" [yearNavigator]="true" [yearRange]="myYearRange" | ||
123 | > | ||
124 | </p-calendar> | ||
125 | |||
126 | <div *ngIf="formErrors.originallyPublishedAt" class="form-error"> | ||
127 | {{ formErrors.originallyPublishedAt }} | ||
128 | </div> | ||
129 | </div> | ||
130 | |||
117 | <my-peertube-checkbox | 131 | <my-peertube-checkbox |
118 | inputName="nsfw" formControlName="nsfw" | 132 | inputName="nsfw" formControlName="nsfw" |
119 | i18n-labelText labelText="This video contains mature or explicit content" | 133 | i18n-labelText labelText="This video contains mature or explicit content" |
diff --git a/client/src/app/videos/+video-edit/shared/video-edit.component.ts b/client/src/app/videos/+video-edit/shared/video-edit.component.ts index 85e015901..d02f18ee9 100644 --- a/client/src/app/videos/+video-edit/shared/video-edit.component.ts +++ b/client/src/app/videos/+video-edit/shared/video-edit.component.ts | |||
@@ -45,6 +45,7 @@ export class VideoEditComponent implements OnInit, OnDestroy { | |||
45 | 45 | ||
46 | calendarLocale: any = {} | 46 | calendarLocale: any = {} |
47 | minScheduledDate = new Date() | 47 | minScheduledDate = new Date() |
48 | myYearRange = '1880:' + (new Date()).getFullYear() | ||
48 | 49 | ||
49 | calendarTimezone: string | 50 | calendarTimezone: string |
50 | calendarDateFormat: string | 51 | calendarDateFormat: string |
@@ -99,7 +100,8 @@ export class VideoEditComponent implements OnInit, OnDestroy { | |||
99 | thumbnailfile: null, | 100 | thumbnailfile: null, |
100 | previewfile: null, | 101 | previewfile: null, |
101 | support: this.videoValidatorsService.VIDEO_SUPPORT, | 102 | support: this.videoValidatorsService.VIDEO_SUPPORT, |
102 | schedulePublicationAt: this.videoValidatorsService.VIDEO_SCHEDULE_PUBLICATION_AT | 103 | schedulePublicationAt: this.videoValidatorsService.VIDEO_SCHEDULE_PUBLICATION_AT, |
104 | originallyPublishedAt: this.videoValidatorsService.VIDEO_ORIGINALLY_PUBLISHED_AT | ||
103 | } | 105 | } |
104 | 106 | ||
105 | this.formValidatorService.updateForm( | 107 | this.formValidatorService.updateForm( |
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 33521a8c1..b26dcabe1 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -188,7 +188,8 @@ async function addVideo (req: express.Request, res: express.Response) { | |||
188 | support: videoInfo.support, | 188 | support: videoInfo.support, |
189 | privacy: videoInfo.privacy, | 189 | privacy: videoInfo.privacy, |
190 | duration: videoPhysicalFile['duration'], // duration was added by a previous middleware | 190 | duration: videoPhysicalFile['duration'], // duration was added by a previous middleware |
191 | channelId: res.locals.videoChannel.id | 191 | channelId: res.locals.videoChannel.id, |
192 | originallyPublishedAt: videoInfo.originallyPublishedAt | ||
192 | } | 193 | } |
193 | const video = new VideoModel(videoData) | 194 | const video = new VideoModel(videoData) |
194 | video.url = getVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object | 195 | video.url = getVideoActivityPubUrl(video) // We use the UUID, so set the URL after building the object |
@@ -325,6 +326,11 @@ async function updateVideo (req: express.Request, res: express.Response) { | |||
325 | if (videoInfoToUpdate.support !== undefined) videoInstance.set('support', videoInfoToUpdate.support) | 326 | if (videoInfoToUpdate.support !== undefined) videoInstance.set('support', videoInfoToUpdate.support) |
326 | if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description) | 327 | if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description) |
327 | if (videoInfoToUpdate.commentsEnabled !== undefined) videoInstance.set('commentsEnabled', videoInfoToUpdate.commentsEnabled) | 328 | if (videoInfoToUpdate.commentsEnabled !== undefined) videoInstance.set('commentsEnabled', videoInfoToUpdate.commentsEnabled) |
329 | if (videoInfoToUpdate.originallyPublishedAt !== undefined && | ||
330 | videoInfoToUpdate.originallyPublishedAt !== null) { | ||
331 | videoInstance.set('originallyPublishedAt', videoInfoToUpdate.originallyPublishedAt) | ||
332 | } | ||
333 | |||
328 | if (videoInfoToUpdate.privacy !== undefined) { | 334 | if (videoInfoToUpdate.privacy !== undefined) { |
329 | const newPrivacy = parseInt(videoInfoToUpdate.privacy.toString(), 10) | 335 | const newPrivacy = parseInt(videoInfoToUpdate.privacy.toString(), 10) |
330 | videoInstance.set('privacy', newPrivacy) | 336 | videoInstance.set('privacy', newPrivacy) |
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts index e6f22e6c5..ce4492a30 100644 --- a/server/helpers/custom-validators/videos.ts +++ b/server/helpers/custom-validators/videos.ts | |||
@@ -13,7 +13,7 @@ import { | |||
13 | VIDEO_STATES | 13 | VIDEO_STATES |
14 | } from '../../initializers' | 14 | } from '../../initializers' |
15 | import { VideoModel } from '../../models/video/video' | 15 | import { VideoModel } from '../../models/video/video' |
16 | import { exists, isArray, isFileValid } from './misc' | 16 | import { exists, isArray, isDateValid, isFileValid } from './misc' |
17 | import { VideoChannelModel } from '../../models/video/video-channel' | 17 | import { VideoChannelModel } from '../../models/video/video-channel' |
18 | import { UserModel } from '../../models/account/user' | 18 | import { UserModel } from '../../models/account/user' |
19 | import * as magnetUtil from 'magnet-uri' | 19 | import * as magnetUtil from 'magnet-uri' |
@@ -115,6 +115,10 @@ function isScheduleVideoUpdatePrivacyValid (value: number) { | |||
115 | ) | 115 | ) |
116 | } | 116 | } |
117 | 117 | ||
118 | function isVideoOriginallyPublishedAtValid (value: string | null) { | ||
119 | return value === null || isDateValid(value) | ||
120 | } | ||
121 | |||
118 | function isVideoFileInfoHashValid (value: string | null | undefined) { | 122 | function isVideoFileInfoHashValid (value: string | null | undefined) { |
119 | return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH) | 123 | return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH) |
120 | } | 124 | } |
@@ -220,6 +224,7 @@ export { | |||
220 | isVideoTagsValid, | 224 | isVideoTagsValid, |
221 | isVideoFPSResolutionValid, | 225 | isVideoFPSResolutionValid, |
222 | isScheduleVideoUpdatePrivacyValid, | 226 | isScheduleVideoUpdatePrivacyValid, |
227 | isVideoOriginallyPublishedAtValid, | ||
223 | isVideoFile, | 228 | isVideoFile, |
224 | isVideoMagnetUriValid, | 229 | isVideoMagnetUriValid, |
225 | isVideoStateValid, | 230 | isVideoStateValid, |
diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts index 051a19e16..194d12c6e 100644 --- a/server/middlewares/validators/videos/videos.ts +++ b/server/middlewares/validators/videos/videos.ts | |||
@@ -14,6 +14,7 @@ import { | |||
14 | } from '../../../helpers/custom-validators/misc' | 14 | } from '../../../helpers/custom-validators/misc' |
15 | import { | 15 | import { |
16 | checkUserCanManageVideo, | 16 | checkUserCanManageVideo, |
17 | isVideoOriginallyPublishedAtValid, | ||
17 | isScheduleVideoUpdatePrivacyValid, | 18 | isScheduleVideoUpdatePrivacyValid, |
18 | isVideoCategoryValid, | 19 | isVideoCategoryValid, |
19 | isVideoChannelOfAccountExist, | 20 | isVideoChannelOfAccountExist, |
@@ -340,6 +341,10 @@ function getCommonVideoAttributes () { | |||
340 | .optional() | 341 | .optional() |
341 | .toBoolean() | 342 | .toBoolean() |
342 | .custom(isBooleanValid).withMessage('Should have comments enabled boolean'), | 343 | .custom(isBooleanValid).withMessage('Should have comments enabled boolean'), |
344 | body('originallyPublishedAt') | ||
345 | .optional() | ||
346 | .customSanitizer(toValueOrNull) | ||
347 | .custom(isVideoOriginallyPublishedAtValid).withMessage('Should have a valid original publication date'), | ||
343 | 348 | ||
344 | body('scheduleUpdate') | 349 | body('scheduleUpdate') |
345 | .optional() | 350 | .optional() |