From 244e76a552ef05a5067134b1065d26dd89246d8c Mon Sep 17 00:00:00 2001 From: Rigel Kent Date: Tue, 17 Apr 2018 00:49:04 +0200 Subject: feature: initial syndication feeds support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provides rss 2.0, atom 1.0 and json 1.0 feeds for videos (instance and account-wide) on listings and video-watch views. * still lacks redis caching * still lacks lastBuildDate support * still lacks channel-wide support * still lacks semantic annotation (for licenses, NSFW warnings, etc.) * still lacks love ( ˘ ³˘) * RSS: has MRSS support for torrent lists! * RSS: includes the first torrent in an enclosure * JSON: lists all torrents in the 'attachments' object * ATOM: lacking torrent listing support Advances #23 Partial implementation for the accountId generation in the client, which will need a hotfix to add a way to get the proper account id. --- client/src/app/shared/misc/object-length.pipe.ts | 8 ++++ client/src/app/shared/shared.module.ts | 9 +++++ .../src/app/shared/video/abstract-video-list.html | 2 +- .../src/app/shared/video/abstract-video-list.scss | 7 ++++ client/src/app/shared/video/abstract-video-list.ts | 6 +++ .../src/app/shared/video/video-feed.component.html | 14 +++++++ .../src/app/shared/video/video-feed.component.scss | 19 ++++++++++ .../src/app/shared/video/video-feed.component.ts | 14 +++++++ client/src/app/shared/video/video.service.ts | 43 ++++++++++++++++++++++ 9 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 client/src/app/shared/misc/object-length.pipe.ts create mode 100644 client/src/app/shared/video/video-feed.component.html create mode 100644 client/src/app/shared/video/video-feed.component.scss create mode 100644 client/src/app/shared/video/video-feed.component.ts (limited to 'client/src/app/shared') diff --git a/client/src/app/shared/misc/object-length.pipe.ts b/client/src/app/shared/misc/object-length.pipe.ts new file mode 100644 index 000000000..84d182052 --- /dev/null +++ b/client/src/app/shared/misc/object-length.pipe.ts @@ -0,0 +1,8 @@ +import { Pipe, PipeTransform } from '@angular/core' + +@Pipe({ name: 'myObjectLength' }) +export class ObjectLengthPipe implements PipeTransform { + transform (value: Object) { + return Object.keys(value).length + } +} diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts index eb50d45a9..74730e2aa 100644 --- a/client/src/app/shared/shared.module.ts +++ b/client/src/app/shared/shared.module.ts @@ -10,6 +10,7 @@ import { MarkdownService } from '@app/videos/shared' import { BsDropdownModule } from 'ngx-bootstrap/dropdown' import { ModalModule } from 'ngx-bootstrap/modal' +import { PopoverModule } from 'ngx-bootstrap/popover' import { TabsModule } from 'ngx-bootstrap/tabs' import { TooltipModule } from 'ngx-bootstrap/tooltip' import { BytesPipe, KeysPipe, NgPipesModule } from 'ngx-pipes' @@ -21,11 +22,13 @@ import { EditButtonComponent } from './misc/edit-button.component' import { FromNowPipe } from './misc/from-now.pipe' import { LoaderComponent } from './misc/loader.component' import { NumberFormatterPipe } from './misc/number-formatter.pipe' +import { ObjectLengthPipe } from './misc/object-length.pipe' import { RestExtractor, RestService } from './rest' import { UserService } from './users' import { VideoAbuseService } from './video-abuse' import { VideoBlacklistService } from './video-blacklist' import { VideoMiniatureComponent } from './video/video-miniature.component' +import { VideoFeedComponent } from './video/video-feed.component' import { VideoThumbnailComponent } from './video/video-thumbnail.component' import { VideoService } from './video/video.service' @@ -39,6 +42,7 @@ import { VideoService } from './video/video.service' BsDropdownModule.forRoot(), ModalModule.forRoot(), + PopoverModule.forRoot(), TabsModule.forRoot(), TooltipModule.forRoot(), @@ -50,9 +54,11 @@ import { VideoService } from './video/video.service' LoaderComponent, VideoThumbnailComponent, VideoMiniatureComponent, + VideoFeedComponent, DeleteButtonComponent, EditButtonComponent, NumberFormatterPipe, + ObjectLengthPipe, FromNowPipe, MarkdownTextareaComponent, InfiniteScrollerDirective, @@ -68,6 +74,7 @@ import { VideoService } from './video/video.service' BsDropdownModule, ModalModule, + PopoverModule, TabsModule, TooltipModule, PrimeSharedModule, @@ -77,6 +84,7 @@ import { VideoService } from './video/video.service' LoaderComponent, VideoThumbnailComponent, VideoMiniatureComponent, + VideoFeedComponent, DeleteButtonComponent, EditButtonComponent, MarkdownTextareaComponent, @@ -84,6 +92,7 @@ import { VideoService } from './video/video.service' HelpComponent, NumberFormatterPipe, + ObjectLengthPipe, FromNowPipe ], diff --git a/client/src/app/shared/video/abstract-video-list.html b/client/src/app/shared/video/abstract-video-list.html index 94a38019d..cb04e07b4 100644 --- a/client/src/app/shared/video/abstract-video-list.html +++ b/client/src/app/shared/video/abstract-video-list.html @@ -2,9 +2,9 @@
{{ titlePage }}
+
No results.
-
+ abstract generateSyndicationList () get user () { return this.authService.getUser() diff --git a/client/src/app/shared/video/video-feed.component.html b/client/src/app/shared/video/video-feed.component.html new file mode 100644 index 000000000..7733ef221 --- /dev/null +++ b/client/src/app/shared/video/video-feed.component.html @@ -0,0 +1,14 @@ +
+ + + + +
+ {{ key }} +
+
+
+ \ No newline at end of file diff --git a/client/src/app/shared/video/video-feed.component.scss b/client/src/app/shared/video/video-feed.component.scss new file mode 100644 index 000000000..2efeb405e --- /dev/null +++ b/client/src/app/shared/video/video-feed.component.scss @@ -0,0 +1,19 @@ +@import '_mixins'; + +.video-feed { + a { + @include disable-default-a-behaviour; + + color: black; + } + + .icon { + @include icon(12px); + + &.icon-syndication { + position: relative; + top: -2px; + background-image: url('../../../assets/images/global/syndication.svg'); + } + } +} \ No newline at end of file diff --git a/client/src/app/shared/video/video-feed.component.ts b/client/src/app/shared/video/video-feed.component.ts new file mode 100644 index 000000000..41257ca99 --- /dev/null +++ b/client/src/app/shared/video/video-feed.component.ts @@ -0,0 +1,14 @@ +import { Component, Input, OnChanges, SimpleChanges } from '@angular/core' + +@Component({ + selector: 'my-video-feed', + styleUrls: [ './video-feed.component.scss' ], + templateUrl: './video-feed.component.html' +}) +export class VideoFeedComponent implements OnChanges { + @Input() syndicationItems + + ngOnChanges (changes: SimpleChanges) { + this.syndicationItems = changes.syndicationItems.currentValue + } +} diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts index 0a8894fd9..009155410 100644 --- a/client/src/app/shared/video/video.service.ts +++ b/client/src/app/shared/video/video.service.ts @@ -8,6 +8,7 @@ import { ResultList } from '../../../../../shared/models/result-list.model' import { UserVideoRateUpdate } from '../../../../../shared/models/videos/user-video-rate-update.model' import { UserVideoRate } from '../../../../../shared/models/videos/user-video-rate.model' import { VideoFilter } from '../../../../../shared/models/videos/video-query.type' +import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum' import { VideoRateType } from '../../../../../shared/models/videos/video-rate.type' import { VideoUpdate } from '../../../../../shared/models/videos/video-update.model' import { environment } from '../../../environments/environment' @@ -24,6 +25,7 @@ import { objectToFormData } from '@app/shared/misc/utils' @Injectable() export class VideoService { private static BASE_VIDEO_URL = environment.apiUrl + '/api/v1/videos/' + private static BASE_FEEDS_URL = environment.apiUrl + '/feeds/videos.' constructor ( private authHttp: HttpClient, @@ -115,6 +117,47 @@ export class VideoService { .catch((res) => this.restExtractor.handleError(res)) } + baseFeed () { + const feed = {} + + for (let item in FeedFormat) { + feed[FeedFormat[item]] = VideoService.BASE_FEEDS_URL + item.toLowerCase() + } + + return feed + } + + getFeed ( + filter?: VideoFilter + ) { + let params = this.restService.addRestGetParams(new HttpParams()) + const feed = this.baseFeed() + + if (filter) { + params = params.set('filter', filter) + } + for (let item in feed) { + feed[item] = feed[item] + ((params.toString().length === 0) ? '' : '?') + params.toString() + } + + return feed + } + + getAccountFeed ( + accountId: number, + host?: string + ) { + let params = this.restService.addRestGetParams(new HttpParams()) + const feed = this.baseFeed() + + params = params.set('accountId', accountId.toString()) + for (let item in feed) { + feed[item] = feed[item] + ((params.toString().length === 0) ? '' : '?') + params.toString() + } + + return feed + } + searchVideos ( search: string, videoPagination: ComponentPagination, -- cgit v1.2.3