Infinite scroll to list our subscriptions

pull/974/head
Chocobozzz 2018-08-24 10:31:56 +02:00
parent f37dc0dd14
commit aa55a4da42
10 changed files with 67 additions and 67 deletions

View File

@ -1,4 +1,4 @@
<div class="video-channels">
<div class="video-channels" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()">
<div *ngFor="let videoChannel of videoChannels" class="video-channel">
<a [routerLink]="[ '/video-channels', videoChannel.name ]">
<img [src]="videoChannel.avatarUrl" alt="Avatar" />

View File

@ -3,6 +3,7 @@ import { NotificationsService } from 'angular2-notifications'
import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
import { I18n } from '@ngx-translate/i18n-polyfill'
import { UserSubscriptionService } from '@app/shared/user-subscription'
import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
@Component({
selector: 'my-account-subscriptions',
@ -12,6 +13,12 @@ import { UserSubscriptionService } from '@app/shared/user-subscription'
export class MyAccountSubscriptionsComponent implements OnInit {
videoChannels: VideoChannel[] = []
pagination: ComponentPagination = {
currentPage: 1,
itemsPerPage: 10,
totalItems: null
}
constructor (
private userSubscriptionService: UserSubscriptionService,
private notificationsService: NotificationsService,
@ -19,12 +26,27 @@ export class MyAccountSubscriptionsComponent implements OnInit {
) {}
ngOnInit () {
this.userSubscriptionService.listSubscriptions()
.subscribe(
res => this.videoChannels = res.data,
this.loadSubscriptions()
}
error => this.notificationsService.error(this.i18n('Error'), error.message)
)
loadSubscriptions () {
this.userSubscriptionService.listSubscriptions(this.pagination)
.subscribe(
res => {
this.videoChannels = this.videoChannels.concat(res.data)
this.pagination.totalItems = res.total
},
error => this.notificationsService.error(this.i18n('Error'), error.message)
)
}
onNearOfBottom () {
// Last page
if (this.pagination.totalItems <= (this.pagination.currentPage * this.pagination.itemsPerPage)) return
this.pagination.currentPage += 1
this.loadSubscriptions()
}
}

View File

@ -29,10 +29,10 @@
</td>
<td *ngIf="isVideoImportPending(videoImport)">
{{ videoImport.video.name }}
{{ videoImport.video?.name }}
</td>
<td *ngIf="isVideoImportSuccess(videoImport)">
<a [href]="getVideoUrl(videoImport.video)" target="_blank" rel="noopener noreferrer">{{ videoImport.video.name }}</a>
<td *ngIf="isVideoImportSuccess(videoImport) && videoImport.video">
<a [href]="getVideoUrl(videoImport.video)" target="_blank" rel="noopener noreferrer">{{ videoImport.video?.name }}</a>
</td>
<td *ngIf="isVideoImportFailed(videoImport)"></td>
@ -40,7 +40,7 @@
<td>{{ videoImport.createdAt }}</td>
<td class="action-cell">
<my-edit-button *ngIf="isVideoImportSuccess(videoImport)" [routerLink]="getEditVideoUrl(videoImport.video)"></my-edit-button>
<my-edit-button *ngIf="isVideoImportSuccess(videoImport) && videoImport.video" [routerLink]="getEditVideoUrl(videoImport.video)"></my-edit-button>
</td>
</tr>
</ng-template>

View File

@ -1,4 +1,4 @@
<div myInfiniteScroller [autoLoading]="true" (nearOfBottom)="onNearOfBottom()" class="search-result">
<div myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" class="search-result">
<div class="results-header">
<div class="first-line">
<div class="results-counter" *ngIf="pagination.totalItems">

View File

@ -87,9 +87,17 @@ export class SearchComponent implements OnInit, OnDestroy {
.subscribe(
([ videosResult, videoChannelsResult ]) => {
this.videos = this.videos.concat(videosResult.videos)
this.pagination.totalItems = videosResult.totalVideos
this.pagination.totalItems = videosResult.totalVideos + videoChannelsResult.total
this.videoChannels = videoChannelsResult.data
this.videoChannels = this.videoChannels.concat(videoChannelsResult.data)
// Focus on channels
if (this.channelsPerPage !== 10 && this.videos.length < this.pagination.itemsPerPage) {
this.resetPagination()
this.channelsPerPage = 10
this.search()
}
},
error => {
@ -116,8 +124,10 @@ export class SearchComponent implements OnInit, OnDestroy {
private resetPagination () {
this.pagination.currentPage = 1
this.pagination.totalItems = null
this.channelsPerPage = 2
this.videos = []
this.videoChannels = []
}
private updateTitle () {

View File

@ -1,4 +1,4 @@
import { bufferTime, catchError, filter, map, share, switchMap, tap } from 'rxjs/operators'
import { bufferTime, catchError, filter, first, map, share, switchMap } from 'rxjs/operators'
import { HttpClient, HttpParams } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { ResultList } from '../../../../../shared'
@ -8,6 +8,7 @@ import { Observable, ReplaySubject, Subject } from 'rxjs'
import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
import { VideoChannel as VideoChannelServer } from '../../../../../shared/models/videos'
import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
type SubscriptionExistResult = { [ uri: string ]: boolean }
@ -17,7 +18,7 @@ export class UserSubscriptionService {
// Use a replay subject because we "next" a value before subscribing
private existsSubject: Subject<string> = new ReplaySubject(1)
private existsObservable: Observable<SubscriptionExistResult>
private readonly existsObservable: Observable<SubscriptionExistResult>
constructor (
private authHttp: HttpClient,
@ -25,7 +26,6 @@ export class UserSubscriptionService {
private restService: RestService
) {
this.existsObservable = this.existsSubject.pipe(
tap(u => console.log(u)),
bufferTime(500),
filter(uris => uris.length !== 0),
switchMap(uris => this.areSubscriptionExist(uris)),
@ -54,10 +54,15 @@ export class UserSubscriptionService {
)
}
listSubscriptions (): Observable<ResultList<VideoChannel>> {
listSubscriptions (componentPagination: ComponentPagination): Observable<ResultList<VideoChannel>> {
const url = UserSubscriptionService.BASE_USER_SUBSCRIPTIONS_URL
return this.authHttp.get<ResultList<VideoChannelServer>>(url)
const pagination = this.restService.componentPaginationToRestPagination(componentPagination)
let params = new HttpParams()
params = this.restService.addRestGetParams(params, pagination)
return this.authHttp.get<ResultList<VideoChannelServer>>(url, { params })
.pipe(
map(res => VideoChannelService.extractVideoChannels(res)),
catchError(err => this.restExtractor.handleError(err))
@ -67,11 +72,10 @@ export class UserSubscriptionService {
isSubscriptionExists (nameWithHost: string) {
this.existsSubject.next(nameWithHost)
return this.existsObservable
return this.existsObservable.pipe(first())
}
private areSubscriptionExist (uris: string[]): Observable<SubscriptionExistResult> {
console.log(uris)
const url = UserSubscriptionService.BASE_USER_SUBSCRIPTIONS_URL + '/exist'
let params = new HttpParams()

View File

@ -11,7 +11,7 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
@Input() containerHeight: number
@Input() pageHeight: number
@Input() percentLimit = 70
@Input() autoLoading = false
@Input() autoInit = false
@Output() nearOfBottom = new EventEmitter<void>()
@Output() nearOfTop = new EventEmitter<void>()
@ -29,7 +29,7 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
}
ngOnInit () {
if (this.autoLoading === true) return this.initialize()
if (this.autoInit === true) return this.initialize()
}
ngOnDestroy () {

View File

@ -21,7 +21,7 @@
<div
class="comment-threads"
myInfiniteScroller
[autoLoading]="true"
[autoInit]="true"
(nearOfBottom)="onNearOfBottom()"
>
<div #commentHighlightBlock id="highlighted-comment">

View File

@ -169,9 +169,6 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
static loadByActorAndTargetNameAndHostForAPI (actorId: number, targetName: string, targetHost: string, t?: Sequelize.Transaction) {
const actorFollowingPartInclude: IIncludeOptions = {
attributes: {
exclude: unusedActorAttributesForAPI
},
model: ActorModel,
required: true,
as: 'ActorFollowing',
@ -203,7 +200,12 @@ export class ActorFollowModel extends Model<ActorFollowModel> {
actorId
},
include: [
actorFollowingPartInclude
actorFollowingPartInclude,
{
model: ActorModel,
required: true,
as: 'ActorFollower'
}
],
transaction: t
}

View File

@ -49,7 +49,8 @@ export const unusedActorAttributesForAPI = [
'outboxUrl',
'sharedInboxUrl',
'followersUrl',
'followingUrl'
'followingUrl',
'url'
]
@DefaultScope({
@ -322,45 +323,6 @@ export class ActorModel extends Model<ActorModel> {
})
}
static async getActorsFollowerSharedInboxUrls (actors: ActorModel[], t: Sequelize.Transaction) {
const query = {
// attribute: [],
where: {
id: {
[Sequelize.Op.in]: actors.map(a => a.id)
}
},
include: [
{
// attributes: [ ],
model: ActorFollowModel.unscoped(),
required: true,
as: 'ActorFollowers',
where: {
state: 'accepted'
},
include: [
{
attributes: [ 'sharedInboxUrl' ],
model: ActorModel.unscoped(),
as: 'ActorFollower',
required: true
}
]
}
],
transaction: t
}
const hash: { [ id: number ]: string[] } = {}
const res = await ActorModel.findAll(query)
for (const actor of res) {
hash[actor.id] = actor.ActorFollowers.map(follow => follow.ActorFollower.sharedInboxUrl)
}
return hash
}
toFormattedJSON () {
let avatar: Avatar = null
if (this.Avatar) {