diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html index d806ea355..b09614061 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html @@ -41,7 +41,7 @@
@@ -53,7 +53,7 @@
diff --git a/client/src/app/+admin/follows/followers-list/followers-list.component.html b/client/src/app/+admin/follows/followers-list/followers-list.component.html index 6b5f3b450..c532b5f32 100644 --- a/client/src/app/+admin/follows/followers-list/followers-list.component.html +++ b/client/src/app/+admin/follows/followers-list/followers-list.component.html @@ -6,7 +6,7 @@
diff --git a/client/src/app/+admin/follows/following-list/following-list.component.html b/client/src/app/+admin/follows/following-list/following-list.component.html index 5a252eda9..01aba0c11 100644 --- a/client/src/app/+admin/follows/following-list/following-list.component.html +++ b/client/src/app/+admin/follows/following-list/following-list.component.html @@ -7,7 +7,7 @@
diff --git a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html index 6ec6301b1..5f18028c9 100644 --- a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html +++ b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.html @@ -3,7 +3,7 @@
diff --git a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts index e08ded3f1..dc59e759b 100644 --- a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts +++ b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts @@ -70,8 +70,10 @@ export class PluginSearchComponent implements OnInit { this.reloadPlugins() } - onSearchChange (search: string) { - this.searchSubject.next(search) + onSearchChange (event: Event) { + const target = event.target as HTMLInputElement + + this.searchSubject.next(target.value) } reloadPlugins () { diff --git a/client/src/app/+admin/users/user-list/user-list.component.html b/client/src/app/+admin/users/user-list/user-list.component.html index ca05bac19..249883efc 100644 --- a/client/src/app/+admin/users/user-list/user-list.component.html +++ b/client/src/app/+admin/users/user-list/user-list.component.html @@ -25,7 +25,7 @@
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html index 17d8cde06..51a672734 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html +++ b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html @@ -28,7 +28,7 @@
diff --git a/client/src/app/menu/avatar-notification.component.html b/client/src/app/menu/avatar-notification.component.html index 7975afba5..df2a102a3 100644 --- a/client/src/app/menu/avatar-notification.component.html +++ b/client/src/app/menu/avatar-notification.component.html @@ -30,7 +30,7 @@
diff --git a/client/src/app/menu/avatar-notification.component.ts b/client/src/app/menu/avatar-notification.component.ts index 989a11849..c447f031c 100644 --- a/client/src/app/menu/avatar-notification.component.ts +++ b/client/src/app/menu/avatar-notification.component.ts @@ -6,7 +6,6 @@ import { Notifier, UserNotificationSocket } from '@app/core' import { NgbPopover } from '@ng-bootstrap/ng-bootstrap' import { NavigationEnd, Router } from '@angular/router' import { filter } from 'rxjs/operators' -import { UserNotificationsComponent } from '@app/shared' @Component({ selector: 'my-avatar-notification', diff --git a/client/src/app/search/search-filters.component.html b/client/src/app/search/search-filters.component.html index c275285d5..60680c7bd 100644 --- a/client/src/app/search/search-filters.component.html +++ b/client/src/app/search/search-filters.component.html @@ -146,7 +146,7 @@ [(ngModel)]="advancedSearch.tagsAllOf" name="tagsAllOf" id="tagsAllOf" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages" i18n-placeholder placeholder="+ Tag" i18n-secondaryPlaceholder secondaryPlaceholder="Enter a tag" - maxItems="5" modelAsStrings="true" + [maxItems]="5" [modelAsStrings]="true" > @@ -159,7 +159,7 @@ [(ngModel)]="advancedSearch.tagsOneOf" name="tagsOneOf" id="tagsOneOf" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages" i18n-placeholder placeholder="+ Tag" i18n-secondaryPlaceholder secondaryPlaceholder="Enter a tag" - maxItems="5" modelAsStrings="true" + [maxItems]="5" [modelAsStrings]="true" > diff --git a/client/src/app/search/search.component.ts b/client/src/app/search/search.component.ts index dfd8d8823..075994dd3 100644 --- a/client/src/app/search/search.component.ts +++ b/client/src/app/search/search.component.ts @@ -141,7 +141,8 @@ export class SearchComponent implements OnInit, OnDestroy { return this.advancedSearch.size() } - removeVideoFromArray (video: Video) { + // Add VideoChannel for typings, but the template already checks "video" argument is a video + removeVideoFromArray (video: Video | VideoChannel) { this.results = this.results.filter(r => !this.isVideo(r) || r.id !== video.id) } diff --git a/client/src/app/shared/buttons/action-dropdown.component.ts b/client/src/app/shared/buttons/action-dropdown.component.ts index a8b3ab16c..6649b092a 100644 --- a/client/src/app/shared/buttons/action-dropdown.component.ts +++ b/client/src/app/shared/buttons/action-dropdown.component.ts @@ -34,10 +34,10 @@ export class ActionDropdownComponent { @Input() label: string @Input() theme: DropdownTheme = 'grey' - getActions () { - if (this.actions.length !== 0 && Array.isArray(this.actions[0])) return this.actions + getActions (): DropdownAction[][] { + if (this.actions.length !== 0 && Array.isArray(this.actions[0])) return this.actions as DropdownAction[][] - return [ this.actions ] + return [ this.actions as DropdownAction[] ] } areActionsDisplayed (actions: Array | DropdownAction[]>, entry: T): boolean { diff --git a/client/src/app/shared/buttons/edit-button.component.ts b/client/src/app/shared/buttons/edit-button.component.ts index 1fe4f7b30..9cfe1a3bb 100644 --- a/client/src/app/shared/buttons/edit-button.component.ts +++ b/client/src/app/shared/buttons/edit-button.component.ts @@ -8,5 +8,5 @@ import { Component, Input } from '@angular/core' export class EditButtonComponent { @Input() label: string - @Input() routerLink: string[] = [] + @Input() routerLink: string[] | string = [] } diff --git a/client/src/app/shared/forms/markdown-textarea.component.ts b/client/src/app/shared/forms/markdown-textarea.component.ts index 19cd37573..cbcfdfe78 100644 --- a/client/src/app/shared/forms/markdown-textarea.component.ts +++ b/client/src/app/shared/forms/markdown-textarea.component.ts @@ -21,7 +21,7 @@ import { MarkdownService } from '@app/shared/renderer' export class MarkdownTextareaComponent implements ControlValueAccessor, OnInit { @Input() content = '' - @Input() classes: string[] = [] + @Input() classes: string[] | { [klass: string]: any[] | any } = [] @Input() textareaWidth = '100%' @Input() textareaHeight = '150px' @Input() previewColumn = false diff --git a/client/src/app/shared/images/preview-upload.component.ts b/client/src/app/shared/images/preview-upload.component.ts index f56f5b1f8..85a2173e9 100644 --- a/client/src/app/shared/images/preview-upload.component.ts +++ b/client/src/app/shared/images/preview-upload.component.ts @@ -26,7 +26,7 @@ export class PreviewUploadComponent implements OnInit, ControlValueAccessor { allowedExtensionsMessage = '' private serverConfig: ServerConfig - private file: File + private file: Blob constructor ( private sanitizer: DomSanitizer, @@ -49,7 +49,7 @@ export class PreviewUploadComponent implements OnInit, ControlValueAccessor { this.allowedExtensionsMessage = this.videoImageExtensions.join(', ') } - onFileChanged (file: File) { + onFileChanged (file: Blob) { this.file = file this.propagateChange(this.file) diff --git a/client/src/app/shared/rest/rest-table.ts b/client/src/app/shared/rest/rest-table.ts index f44643c0f..a33e99e25 100644 --- a/client/src/app/shared/rest/rest-table.ts +++ b/client/src/app/shared/rest/rest-table.ts @@ -65,8 +65,9 @@ export abstract class RestTable { }) } - onSearch (search: string) { - this.searchStream.next(search) + onSearch (event: Event) { + const target = event.target as HTMLInputElement + this.searchStream.next(target.value) } protected abstract loadData (): void diff --git a/client/src/app/shared/user-subscription/subscribe-button.component.html b/client/src/app/shared/user-subscription/subscribe-button.component.html index f08c88f3c..85b3d1fdb 100644 --- a/client/src/app/shared/user-subscription/subscribe-button.component.html +++ b/client/src/app/shared/user-subscription/subscribe-button.component.html @@ -55,7 +55,7 @@ - + diff --git a/client/src/app/shared/video/abstract-video-list.ts b/client/src/app/shared/video/abstract-video-list.ts index c2fe6f754..2f5f82aa3 100644 --- a/client/src/app/shared/video/abstract-video-list.ts +++ b/client/src/app/shared/video/abstract-video-list.ts @@ -14,6 +14,7 @@ import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' import { I18n } from '@ngx-translate/i18n-polyfill' import { isLastMonth, isLastWeek, isToday, isYesterday } from '@shared/core-utils/miscs/date' import { ServerConfig } from '@shared/models' +import { GlobalIconName } from '@app/shared/images/global-icon.component' enum GroupDate { UNKNOWN = 0, @@ -61,7 +62,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor actions: { routerLink: string - iconName: string + iconName: GlobalIconName label: string }[] = [] diff --git a/client/src/app/shared/video/modals/video-blacklist.component.ts b/client/src/app/shared/video/modals/video-blacklist.component.ts index f0c70a365..bdd9c7b99 100644 --- a/client/src/app/shared/video/modals/video-blacklist.component.ts +++ b/client/src/app/shared/video/modals/video-blacklist.component.ts @@ -1,12 +1,12 @@ import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' import { Notifier, RedirectService } from '@app/core' import { VideoBlacklistService } from '../../../shared/video-blacklist' -import { VideoDetails } from '../../../shared/video/video-details.model' import { I18n } from '@ngx-translate/i18n-polyfill' import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' import { FormReactive, VideoBlacklistValidatorsService } from '@app/shared/forms' +import { Video } from '@app/shared/video/video.model' @Component({ selector: 'my-video-blacklist', @@ -14,7 +14,7 @@ import { FormReactive, VideoBlacklistValidatorsService } from '@app/shared/forms styleUrls: [ './video-blacklist.component.scss' ] }) export class VideoBlacklistComponent extends FormReactive implements OnInit { - @Input() video: VideoDetails = null + @Input() video: Video = null @ViewChild('modal', { static: true }) modal: NgbModal diff --git a/client/src/app/shared/video/modals/video-report.component.ts b/client/src/app/shared/video/modals/video-report.component.ts index 1d368ff17..ee991fade 100644 --- a/client/src/app/shared/video/modals/video-report.component.ts +++ b/client/src/app/shared/video/modals/video-report.component.ts @@ -1,13 +1,13 @@ import { Component, Input, OnInit, ViewChild } from '@angular/core' import { Notifier } from '@app/core' import { FormReactive } from '../../../shared/forms' -import { VideoDetails } from '../../../shared/video/video-details.model' import { I18n } from '@ngx-translate/i18n-polyfill' import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' import { VideoAbuseValidatorsService } from '@app/shared/forms/form-validators/video-abuse-validators.service' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' import { VideoAbuseService } from '@app/shared/video-abuse' +import { Video } from '@app/shared/video/video.model' @Component({ selector: 'my-video-report', @@ -15,7 +15,7 @@ import { VideoAbuseService } from '@app/shared/video-abuse' styleUrls: [ './video-report.component.scss' ] }) export class VideoReportComponent extends FormReactive implements OnInit { - @Input() video: VideoDetails = null + @Input() video: Video = null @ViewChild('modal', { static: true }) modal: NgbModal diff --git a/client/src/app/shared/video/video-thumbnail.component.ts b/client/src/app/shared/video/video-thumbnail.component.ts index 2420ec715..111b4c8bb 100644 --- a/client/src/app/shared/video/video-thumbnail.component.ts +++ b/client/src/app/shared/video/video-thumbnail.component.ts @@ -12,7 +12,7 @@ export class VideoThumbnailComponent { @Input() video: Video @Input() nsfw = false @Input() routerLink: any[] - @Input() queryParams: any[] + @Input() queryParams: { [ p: string ]: any } @Input() displayWatchLaterPlaylist: boolean @Input() inWatchLaterPlaylist: boolean 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 e40649d95..6d72e5765 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 @@ -29,7 +29,7 @@ @@ -44,7 +44,7 @@ - +
{{ formErrors.description }} diff --git a/client/src/app/videos/+video-watch/comment/video-comment-add.component.ts b/client/src/app/videos/+video-watch/comment/video-comment-add.component.ts index 1be96ad9e..a8c432653 100644 --- a/client/src/app/videos/+video-watch/comment/video-comment-add.component.ts +++ b/client/src/app/videos/+video-watch/comment/video-comment-add.component.ts @@ -25,7 +25,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit { @Input() parentComments: VideoComment[] @Input() focusOnInit = false - @Output() commentCreated = new EventEmitter() + @Output() commentCreated = new EventEmitter() @Output() cancel = new EventEmitter() @ViewChild('visitorModal', { static: true }) visitorModal: NgbModal @@ -96,7 +96,7 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit { this.addingComment = true const commentCreate: VideoCommentCreate = this.form.value - let obs: Observable + let obs: Observable if (this.parentComment) { obs = this.addCommentReply(commentCreate) diff --git a/client/src/app/videos/+video-watch/comment/video-comment-thread-tree.model.ts b/client/src/app/videos/+video-watch/comment/video-comment-thread-tree.model.ts new file mode 100644 index 000000000..1566d7369 --- /dev/null +++ b/client/src/app/videos/+video-watch/comment/video-comment-thread-tree.model.ts @@ -0,0 +1,7 @@ +import { VideoCommentThreadTree as VideoCommentThreadTreeServerModel } from '../../../../../../shared/models/videos/video-comment.model' +import { VideoComment } from '@app/videos/+video-watch/comment/video-comment.model' + +export class VideoCommentThreadTree implements VideoCommentThreadTreeServerModel { + comment: VideoComment + children: VideoCommentThreadTree[] +} diff --git a/client/src/app/videos/+video-watch/comment/video-comment.component.ts b/client/src/app/videos/+video-watch/comment/video-comment.component.ts index 61f9335d1..f7eca45fd 100644 --- a/client/src/app/videos/+video-watch/comment/video-comment.component.ts +++ b/client/src/app/videos/+video-watch/comment/video-comment.component.ts @@ -1,6 +1,5 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core' import { User, UserRight } from '../../../../../../shared/models/users' -import { VideoCommentThreadTree } from '../../../../../../shared/models/videos/video-comment.model' import { AuthService } from '@app/core/auth' import { AccountService } from '@app/shared/account/account.service' import { Video } from '@app/shared/video/video.model' @@ -10,6 +9,7 @@ import { Account } from '@app/shared/account/account.model' import { Notifier } from '@app/core' import { UserService } from '@app/shared' import { Actor } from '@app/shared/actor/actor.model' +import { VideoCommentThreadTree } from '@app/videos/+video-watch/comment/video-comment-thread-tree.model' @Component({ selector: 'my-video-comment', diff --git a/client/src/app/videos/+video-watch/comment/video-comment.model.ts b/client/src/app/videos/+video-watch/comment/video-comment.model.ts index aaeb0ea9c..171fc4acc 100644 --- a/client/src/app/videos/+video-watch/comment/video-comment.model.ts +++ b/client/src/app/videos/+video-watch/comment/video-comment.model.ts @@ -1,5 +1,5 @@ import { Account as AccountInterface } from '../../../../../../shared/models/actors' -import { VideoComment as VideoCommentServerModel } from '../../../../../../shared/models/videos/video-comment.model' +import { VideoComment as VideoCommentServerModel, VideoCommentCreate } from '../../../../../../shared/models/videos/video-comment.model' import { Actor } from '@app/shared/actor/actor.model' import { getAbsoluteAPIUrl } from '@app/shared/misc/utils' diff --git a/client/src/app/videos/+video-watch/comment/video-comment.service.ts b/client/src/app/videos/+video-watch/comment/video-comment.service.ts index a81e5236a..0b0715390 100644 --- a/client/src/app/videos/+video-watch/comment/video-comment.service.ts +++ b/client/src/app/videos/+video-watch/comment/video-comment.service.ts @@ -7,13 +7,14 @@ import { FeedFormat, ResultList } from '../../../../../../shared/models' import { VideoComment as VideoCommentServerModel, VideoCommentCreate, - VideoCommentThreadTree + VideoCommentThreadTree as VideoCommentThreadTreeServerModel } from '../../../../../../shared/models/videos/video-comment.model' import { environment } from '../../../../environments/environment' import { RestExtractor, RestService } from '../../../shared/rest' import { ComponentPaginationLight } from '../../../shared/rest/component-pagination.model' import { CommentSortField } from '../../../shared/video/sort-field.type' import { VideoComment } from './video-comment.model' +import { VideoCommentThreadTree } from '@app/videos/+video-watch/comment/video-comment-thread-tree.model' @Injectable() export class VideoCommentService { @@ -76,9 +77,9 @@ export class VideoCommentService { const url = `${VideoCommentService.BASE_VIDEO_URL + videoId}/comment-threads/${threadId}` return this.authHttp - .get(url) + .get(url) .pipe( - map(tree => this.extractVideoCommentTree(tree as VideoCommentThreadTree)), + map(tree => this.extractVideoCommentTree(tree)), catchError(err => this.restExtractor.handleError(err)) ) } @@ -138,12 +139,12 @@ export class VideoCommentService { return { data: comments, total: totalComments } } - private extractVideoCommentTree (tree: VideoCommentThreadTree) { - if (!tree) return tree + private extractVideoCommentTree (tree: VideoCommentThreadTreeServerModel) { + if (!tree) return tree as VideoCommentThreadTree tree.comment = new VideoComment(tree.comment) tree.children.forEach(c => this.extractVideoCommentTree(c)) - return tree + return tree as VideoCommentThreadTree } } diff --git a/client/src/app/videos/+video-watch/comment/video-comments.component.ts b/client/src/app/videos/+video-watch/comment/video-comments.component.ts index 47720b0ea..750c09c47 100644 --- a/client/src/app/videos/+video-watch/comment/video-comments.component.ts +++ b/client/src/app/videos/+video-watch/comment/video-comments.component.ts @@ -1,8 +1,7 @@ -import { Component, ElementRef, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChild, Output, EventEmitter } from '@angular/core' +import { Component, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core' import { ActivatedRoute } from '@angular/router' import { ConfirmService, Notifier } from '@app/core' import { Subject, Subscription } from 'rxjs' -import { VideoCommentThreadTree } from '../../../../../../shared/models/videos/video-comment.model' import { AuthService } from '../../../core/auth' import { ComponentPagination, hasMoreItems } from '../../../shared/rest/component-pagination.model' import { User } from '../../../shared/users' @@ -13,6 +12,7 @@ import { VideoCommentService } from './video-comment.service' import { I18n } from '@ngx-translate/i18n-polyfill' import { Syndication } from '@app/shared/video/syndication.model' import { HooksService } from '@app/core/plugins/hooks.service' +import { VideoCommentThreadTree } from '@app/videos/+video-watch/comment/video-comment-thread-tree.model' @Component({ selector: 'my-video-comments', diff --git a/client/src/app/videos/+video-watch/modal/video-share.component.html b/client/src/app/videos/+video-watch/modal/video-share.component.html index 549a9f30e..593dd8529 100644 --- a/client/src/app/videos/+video-watch/modal/video-share.component.html +++ b/client/src/app/videos/+video-watch/modal/video-share.component.html @@ -42,7 +42,7 @@
- +
diff --git a/client/tsconfig.json b/client/tsconfig.json index c4f2d6a6a..fbdeb6d5d 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -37,6 +37,7 @@ }, "angularCompilerOptions": { "strictInjectionParameters": true, - "fullTemplateTypeCheck": true + "fullTemplateTypeCheck": true, + "strictTemplates": true } } diff --git a/shared/models/plugins/register-server-setting.model.ts b/shared/models/plugins/register-server-setting.model.ts index 65a181705..45d79228d 100644 --- a/shared/models/plugins/register-server-setting.model.ts +++ b/shared/models/plugins/register-server-setting.model.ts @@ -1,7 +1,7 @@ export interface RegisterServerSettingOptions { name: string label: string - type: 'input' + type: 'input' | 'input-checkbox' | 'input-textarea' // If the setting is not private, anyone can view its value (client code included) // If the setting is private, only server-side hooks can access it