<div>
<p-multiSelect
- inputId="instanceCategories" [options]="categoryItems" formControlName="categories" showToggleAll="false"
+ inputId="instanceCategories" [options]="categoryItems" formControlName="categories" [showToggleAll]="false"
[defaultLabel]="getDefaultCategoryLabel()" [selectedItemsLabel]="getSelectedCategoryLabel()"
emptyFilterMessage="No results found" i18n-emptyFilterMessage
></p-multiSelect>
<div>
<p-multiSelect
- inputId="instanceLanguages" [options]="languageItems" formControlName="languages" showToggleAll="false"
+ inputId="instanceLanguages" [options]="languageItems" formControlName="languages" [showToggleAll]="false"
[defaultLabel]="getDefaultLanguageLabel()" [selectedItemsLabel]="getSelectedLanguageLabel()"
emptyFilterMessage="No results found" i18n-emptyFilterMessage
></p-multiSelect>
<div class="caption">
<input
type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
- (keyup)="onSearch($event.target.value)"
+ (keyup)="onSearch($event)"
>
</div>
</ng-template>
<div>
<input
type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
- (keyup)="onSearch($event.target.value)"
+ (keyup)="onSearch($event)"
>
</div>
</div>
</div>
<div class="search-bar">
- <input type="text" (input)="onSearchChange($event.target.value)" i18n-placeholder placeholder="Search..."/>
+ <input type="text" (input)="onSearchChange($event)" i18n-placeholder placeholder="Search..."/>
</div>
<div class="alert alert-info" i18n *ngIf="pluginInstalled">
this.reloadPlugins()
}
- onSearchChange (search: string) {
- this.searchSubject.next(search)
+ onSearchChange (event: Event) {
+ const target = event.target as HTMLInputElement
+
+ this.searchSubject.next(target.value)
}
reloadPlugins () {
<div>
<input
type="text" name="table-filter" id="table-filter" i18n-placeholder placeholder="Filter..."
- (keyup)="onSearch($event.target.value)"
+ (keyup)="onSearch($event)"
>
</div>
</div>
<div>
<p-multiSelect
- inputId="videoLanguages" [options]="languageItems" formControlName="videoLanguages" showToggleAll="true"
+ inputId="videoLanguages" [options]="languageItems" formControlName="videoLanguages" [showToggleAll]="true"
[defaultLabel]="getDefaultVideoLanguageLabel()" [selectedItemsLabel]="getSelectedVideoLanguageLabel()"
emptyFilterMessage="No results found" i18n-emptyFilterMessage
></p-multiSelect>
</div>
<my-user-notifications
- [ignoreLoadingBar]="true" [infiniteScroll]="false" itemsPerPage="10"
+ [ignoreLoadingBar]="true" [infiniteScroll]="false" [itemsPerPage]="10"
[markAllAsReadSubject]="markAllAsReadSubject" (notificationsLoaded)="onNotificationLoaded()"
></my-user-notifications>
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',
[(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"
></tag-input>
</div>
[(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"
></tag-input>
</div>
</div>
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)
}
@Input() label: string
@Input() theme: DropdownTheme = 'grey'
- getActions () {
- if (this.actions.length !== 0 && Array.isArray(this.actions[0])) return this.actions
+ getActions (): DropdownAction<T>[][] {
+ if (this.actions.length !== 0 && Array.isArray(this.actions[0])) return this.actions as DropdownAction<T>[][]
- return [ this.actions ]
+ return [ this.actions as DropdownAction<T>[] ]
}
areActionsDisplayed (actions: Array<DropdownAction<T> | DropdownAction<T>[]>, entry: T): boolean {
export class EditButtonComponent {
@Input() label: string
- @Input() routerLink: string[] = []
+ @Input() routerLink: string[] | string = []
}
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
allowedExtensionsMessage = ''
private serverConfig: ServerConfig
- private file: File
+ private file: Blob
constructor (
private sanitizer: DomSanitizer,
this.allowedExtensionsMessage = this.videoImageExtensions.join(', ')
}
- onFileChanged (file: File) {
+ onFileChanged (file: Blob) {
this.file = file
this.propagateChange(this.file)
})
}
- 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
</button>
<button class="dropdown-item dropdown-item-neutral" i18n>Subscribe with a Mastodon account:</button>
- <my-remote-subscribe showHelp="true" [uri]="uri"></my-remote-subscribe>
+ <my-remote-subscribe [showHelp]="true" [uri]="uri"></my-remote-subscribe>
<div class="dropdown-divider"></div>
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,
actions: {
routerLink: string
- iconName: string
+ iconName: GlobalIconName
label: string
}[] = []
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',
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
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',
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
@Input() video: Video
@Input() nsfw = false
@Input() routerLink: any[]
- @Input() queryParams: any[]
+ @Input() queryParams: { [ p: string ]: any }
@Input() displayWatchLaterPlaylist: boolean
@Input() inWatchLaterPlaylist: boolean
<tag-input
[validators]="tagValidators" [errorMessages]="tagValidatorsMessages"
i18n-placeholder placeholder="+ Tag" i18n-secondaryPlaceholder secondaryPlaceholder="Enter a new tag"
- formControlName="tags" maxItems="5" modelAsStrings="true"
+ formControlName="tags" [maxItems]="5" [modelAsStrings]="true"
></tag-input>
</div>
</ng-template>
</my-help>
- <my-markdown-textarea truncate="250" formControlName="description" markdownVideo="true"></my-markdown-textarea>
+ <my-markdown-textarea [truncate]="250" formControlName="description" [markdownVideo]="true"></my-markdown-textarea>
<div *ngIf="formErrors.description" class="form-error">
{{ formErrors.description }}
@Input() parentComments: VideoComment[]
@Input() focusOnInit = false
- @Output() commentCreated = new EventEmitter<VideoCommentCreate>()
+ @Output() commentCreated = new EventEmitter<VideoComment>()
@Output() cancel = new EventEmitter()
@ViewChild('visitorModal', { static: true }) visitorModal: NgbModal
this.addingComment = true
const commentCreate: VideoCommentCreate = this.form.value
- let obs: Observable<any>
+ let obs: Observable<VideoComment>
if (this.parentComment) {
obs = this.addCommentReply(commentCreate)
--- /dev/null
+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[]
+}
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'
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',
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'
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 {
const url = `${VideoCommentService.BASE_VIDEO_URL + videoId}/comment-threads/${threadId}`
return this.authHttp
- .get(url)
+ .get<VideoCommentThreadTreeServerModel>(url)
.pipe(
- map(tree => this.extractVideoCommentTree(tree as VideoCommentThreadTree)),
+ map(tree => this.extractVideoCommentTree(tree)),
catchError(err => this.restExtractor.handleError(err))
)
}
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
}
}
-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'
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',
<ngb-tab i18n-title title="QR-Code" id="qrcode">
<ng-template ngbTabContent>
<div class="tab-content">
- <qrcode [qrdata]="getVideoUrl()" size="256" level="Q"></qrcode>
+ <qrcode [qrdata]="getVideoUrl()" [size]="256" level="Q"></qrcode>
</div>
</ng-template>
</ngb-tab>
},
"angularCompilerOptions": {
"strictInjectionParameters": true,
- "fullTemplateTypeCheck": true
+ "fullTemplateTypeCheck": true,
+ "strictTemplates": true
}
}
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