]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Add buttons in playlist page
authorChocobozzz <me@florianbigard.com>
Fri, 7 Aug 2020 14:29:30 +0000 (16:29 +0200)
committerChocobozzz <me@florianbigard.com>
Mon, 10 Aug 2020 07:43:44 +0000 (09:43 +0200)
To delete/edit/share the playlist

13 files changed:
client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.html
client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.scss
client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts
client/src/app/+my-account/my-account.module.ts
client/src/app/+videos/+video-watch/video-watch.component.html
client/src/app/+videos/+video-watch/video-watch.component.ts
client/src/app/+videos/+video-watch/video-watch.module.ts
client/src/app/shared/shared-share-modal/index.ts [new file with mode: 0644]
client/src/app/shared/shared-share-modal/shared-share-modal.module.ts [new file with mode: 0644]
client/src/app/shared/shared-share-modal/video-share.component.html [moved from client/src/app/+videos/+video-watch/modal/video-share.component.html with 96% similarity]
client/src/app/shared/shared-share-modal/video-share.component.scss [moved from client/src/app/+videos/+video-watch/modal/video-share.component.scss with 100% similarity]
client/src/app/shared/shared-share-modal/video-share.component.ts [moved from client/src/app/+videos/+video-watch/modal/video-share.component.ts with 93% similarity]
client/src/sass/application.scss

index 2bfdf5c436cc026193c711aaeba1457925d5bcfe..09b4c8a1ba3c460912bd4097a94a1a07cdc8ddb5 100644 (file)
@@ -5,10 +5,33 @@
       *ngIf="playlist" [playlist]="playlist" [toManage]="false" [displayChannel]="true"
       [displayDescription]="true" [displayPrivacy]="true"
     ></my-video-playlist-miniature>
+
+    <div class="playlist-buttons">
+      <button (click)="showShareModal()" class="action-button share-button">
+        <my-global-icon iconName="share" aria-hidden="true"></my-global-icon>
+        <span class="icon-text" i18n>Share</span>
+      </button>
+
+      <my-action-dropdown
+        *ngIf="isRegularPlaylist(playlist)"
+        [entry]="playlist" [actions]="playlistActions" label="More"
+      ></my-action-dropdown>
+    </div>
+
   </div>
 
   <div class="playlist-elements col-xs-12 col-md-7 col-xl-9">
-    <div i18n class="no-results" *ngIf="pagination.totalItems === 0">No videos in this playlist.</div>
+    <div class="no-results" *ngIf="pagination.totalItems === 0">
+      <div i18n>No videos in this playlist.</div>
+
+      <div i18n>
+        Browse videos on PeerTube to add them in your playlist.
+      </div>
+
+      <div i18n>
+        See the <a target="_blank" href="https://docs.joinpeertube.org/#/use-library?id=playlist">documentation</a> for more information.
+      </div>
+    </div>
 
     <div
       class="videos" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()"
@@ -24,3 +47,5 @@
     </div>
   </div>
 </div>
+
+<my-video-share #videoShareModal [playlist]="playlist"></my-video-share>
index 4531e475a151bbe1721eb05ee5215e25ed0931c2..3e9b57c355281c4e33607ee4e59ab3dcac50594d 100644 (file)
@@ -10,7 +10,9 @@
   padding: 10px;
 
   display: flex;
+  flex-direction: column;
   justify-content: center;
+  align-items: center;
 
   /* fix ellipsis dots background color */
   ::ng-deep .miniature-name::after {
   }
 }
 
+.playlist-buttons {
+  display:flex;
+  margin: 30px 0 10px 0;
+
+  .share-button {
+    @include peertube-button;
+    @include button-with-icon(17px, 3px, -1px);
+    @include grey-button;
+    @include apply-svg-color(pvar(--actionButtonColor));
+
+    margin-right: 10px;
+  }
+}
+
 // Thanks Angular CDK <3 https://material.angular.io/cdk/drag-drop/examples
 .cdk-drag-preview {
   box-sizing: border-box;
index 0add81c38cd4a1e4f82c92561a0360c07d053e7f..e278d9ed2f69526c729dd1e15d422d95118f5a77 100644 (file)
@@ -1,9 +1,13 @@
 import { Subject, Subscription } from 'rxjs'
 import { CdkDragDrop } from '@angular/cdk/drag-drop'
-import { Component, OnDestroy, OnInit } from '@angular/core'
-import { ActivatedRoute } from '@angular/router'
-import { ComponentPagination, Notifier, ScreenService } from '@app/core'
+import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'
+import { ActivatedRoute, Router } from '@angular/router'
+import { ComponentPagination, ConfirmService, Notifier, ScreenService } from '@app/core'
+import { DropdownAction } from '@app/shared/shared-main'
+import { VideoShareComponent } from '@app/shared/shared-share-modal'
 import { VideoPlaylist, VideoPlaylistElement, VideoPlaylistService } from '@app/shared/shared-video-playlist'
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { VideoPlaylistType } from '@shared/models'
 
 @Component({
   selector: 'my-account-video-playlist-elements',
@@ -11,9 +15,13 @@ import { VideoPlaylist, VideoPlaylistElement, VideoPlaylistService } from '@app/
   styleUrls: [ './my-account-video-playlist-elements.component.scss' ]
 })
 export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestroy {
+  @ViewChild('videoShareModal') videoShareModal: VideoShareComponent
+
   playlistElements: VideoPlaylistElement[] = []
   playlist: VideoPlaylist
 
+  playlistActions: DropdownAction<VideoPlaylist>[][] = []
+
   pagination: ComponentPagination = {
     currentPage: 1,
     itemsPerPage: 10,
@@ -27,12 +35,30 @@ export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestro
 
   constructor (
     private notifier: Notifier,
+    private i18n: I18n,
+    private router: Router,
+    private confirmService: ConfirmService,
     private route: ActivatedRoute,
     private screenService: ScreenService,
     private videoPlaylistService: VideoPlaylistService
   ) {}
 
   ngOnInit () {
+    this.playlistActions = [
+      [
+        {
+          label: this.i18n('Update playlist'),
+          iconName: 'edit',
+          linkBuilder: playlist => [ '/my-account', 'video-playlists', 'update', playlist.uuid ]
+        },
+        {
+          label: this.i18n('Delete playlist'),
+          iconName: 'delete',
+          handler: playlist => this.deleteVideoPlaylist(playlist)
+        }
+      ]
+    ]
+
     this.paramsSub = this.route.params.subscribe(routeParams => {
       this.videoPlaylistId = routeParams[ 'videoPlaylistId' ]
       this.loadElements()
@@ -90,6 +116,38 @@ export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestro
     return elem.id
   }
 
+  isRegularPlaylist (playlist: VideoPlaylist) {
+    return playlist?.type.id === VideoPlaylistType.REGULAR
+  }
+
+  showShareModal () {
+    this.videoShareModal.show()
+  }
+
+  async deleteVideoPlaylist (videoPlaylist: VideoPlaylist) {
+    const res = await this.confirmService.confirm(
+      this.i18n(
+        'Do you really want to delete {{playlistDisplayName}}?',
+        { playlistDisplayName: videoPlaylist.displayName }
+      ),
+      this.i18n('Delete')
+    )
+    if (res === false) return
+
+    this.videoPlaylistService.removeVideoPlaylist(videoPlaylist)
+      .subscribe(
+        () => {
+          this.router.navigate([ '/my-account', 'video-playlists' ])
+
+          this.notifier.success(
+            this.i18n('Playlist {{playlistDisplayName}} deleted.', { playlistDisplayName: videoPlaylist.displayName })
+          )
+        },
+
+        error => this.notifier.error(error.message)
+      )
+  }
+
   /**
    * Returns null to not have drag and drop delay.
    * In small views, where elements are about 100% wide,
index bf5a4fc8a2e09d9b992fd976a602a0453d982844..5f7ed4d2fc63ad218c325fd432ad1cd5eba5c276 100644 (file)
@@ -8,6 +8,7 @@ import { SharedFormModule } from '@app/shared/shared-forms'
 import { SharedGlobalIconModule } from '@app/shared/shared-icons'
 import { SharedMainModule } from '@app/shared/shared-main'
 import { SharedModerationModule } from '@app/shared/shared-moderation'
+import { SharedShareModal } from '@app/shared/shared-share-modal'
 import { SharedUserInterfaceSettingsModule } from '@app/shared/shared-user-settings'
 import { SharedUserSubscriptionModule } from '@app/shared/shared-user-subscription/shared-user-subscription.module'
 import { SharedVideoMiniatureModule } from '@app/shared/shared-video-miniature'
@@ -53,7 +54,8 @@ import { MyAccountComponent } from './my-account.component'
     SharedVideoPlaylistModule,
     SharedUserInterfaceSettingsModule,
     SharedGlobalIconModule,
-    SharedAbuseListModule
+    SharedAbuseListModule,
+    SharedShareModal
   ],
 
   declarations: [
index 2588b9af573aca4cefc6f71883b6eb942b067dca..4279437d23688e6716098b91af2b5f730e8fe14b 100644 (file)
                       <my-global-icon iconName="download" aria-hidden="true"></my-global-icon>
                       <span class="icon-text d-none d-sm-inline" i18n>DOWNLOAD</span>
                     </button>
-                  
+
                     <my-video-download #videoDownloadModal></my-video-download>
                   </ng-container>
+
                   <ng-container *ngIf="isUserLoggedIn()">
                     <my-video-actions-dropdown
                       placement="bottom auto" buttonDirection="horizontal" [buttonStyled]="true" [video]="video" [videoCaptions]="videoCaptions"
index 33f998282628d844d5c0156e0b3f1479953aef58..a53af210a991bd5750c5b6873d388c4b3bd729f1 100644 (file)
@@ -8,12 +8,14 @@ import { AuthService, AuthUser, ConfirmService, MarkdownService, Notifier, RestE
 import { HooksService } from '@app/core/plugins/hooks.service'
 import { RedirectService } from '@app/core/routing/redirect.service'
 import { isXPercentInViewport, scrollToTop } from '@app/helpers'
-import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
 import { Video, VideoCaptionService, VideoDetails, VideoService } from '@app/shared/shared-main'
+import { VideoShareComponent } from '@app/shared/shared-share-modal'
 import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription'
+import { VideoDownloadComponent } from '@app/shared/shared-video-miniature'
 import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist'
 import { MetaService } from '@ngx-meta/core'
 import { I18n } from '@ngx-translate/i18n-polyfill'
+import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
 import { ServerConfig, UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '@shared/models'
 import { getStoredP2PEnabled, getStoredTheater } from '../../../assets/player/peertube-player-local-storage'
 import {
@@ -26,10 +28,8 @@ import {
 } from '../../../assets/player/peertube-player-manager'
 import { isWebRTCDisabled, timeToInt } from '../../../assets/player/utils'
 import { environment } from '../../../environments/environment'
-import { VideoShareComponent } from './modal/video-share.component'
 import { VideoSupportComponent } from './modal/video-support.component'
 import { VideoWatchPlaylistComponent } from './video-watch-playlist.component'
-import { VideoDownloadComponent } from '@app/shared/shared-video-miniature'
 
 @Component({
   selector: 'my-video-watch',
index 5821dc2b7325b2ea04dc36c8b3af3988a7f12e9f..612bbccc4488e3eb26199ea2544ed4544b1721fd 100644 (file)
@@ -1,19 +1,17 @@
-import { QRCodeModule } from 'angularx-qrcode'
 import { NgModule } from '@angular/core'
 import { SharedFormModule } from '@app/shared/shared-forms'
 import { SharedGlobalIconModule } from '@app/shared/shared-icons'
 import { SharedMainModule } from '@app/shared/shared-main'
 import { SharedModerationModule } from '@app/shared/shared-moderation'
+import { SharedShareModal } from '@app/shared/shared-share-modal'
 import { SharedUserSubscriptionModule } from '@app/shared/shared-user-subscription'
 import { SharedVideoCommentModule } from '@app/shared/shared-video-comment'
 import { SharedVideoMiniatureModule } from '@app/shared/shared-video-miniature'
 import { SharedVideoPlaylistModule } from '@app/shared/shared-video-playlist'
-import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'
 import { VideoCommentService } from '../../shared/shared-video-comment/video-comment.service'
 import { VideoCommentAddComponent } from './comment/video-comment-add.component'
 import { VideoCommentComponent } from './comment/video-comment.component'
 import { VideoCommentsComponent } from './comment/video-comments.component'
-import { VideoShareComponent } from './modal/video-share.component'
 import { VideoSupportComponent } from './modal/video-support.component'
 import { RecommendationsModule } from './recommendations/recommendations.module'
 import { TimestampRouteTransformerDirective } from './timestamp-route-transformer.directive'
@@ -25,8 +23,6 @@ import { VideoWatchComponent } from './video-watch.component'
 @NgModule({
   imports: [
     VideoWatchRoutingModule,
-    NgbTooltipModule,
-    QRCodeModule,
     RecommendationsModule,
 
     SharedMainModule,
@@ -36,14 +32,14 @@ import { VideoWatchComponent } from './video-watch.component'
     SharedUserSubscriptionModule,
     SharedModerationModule,
     SharedGlobalIconModule,
-    SharedVideoCommentModule
+    SharedVideoCommentModule,
+    SharedShareModal
   ],
 
   declarations: [
     VideoWatchComponent,
     VideoWatchPlaylistComponent,
 
-    VideoShareComponent,
     VideoSupportComponent,
     VideoCommentsComponent,
     VideoCommentAddComponent,
diff --git a/client/src/app/shared/shared-share-modal/index.ts b/client/src/app/shared/shared-share-modal/index.ts
new file mode 100644 (file)
index 0000000..e13c08a
--- /dev/null
@@ -0,0 +1,3 @@
+export * from './video-share.component'
+
+export * from './shared-share-modal.module'
diff --git a/client/src/app/shared/shared-share-modal/shared-share-modal.module.ts b/client/src/app/shared/shared-share-modal/shared-share-modal.module.ts
new file mode 100644 (file)
index 0000000..e269eec
--- /dev/null
@@ -0,0 +1,27 @@
+import { QRCodeModule } from 'angularx-qrcode'
+import { NgModule } from '@angular/core'
+import { SharedFormModule } from '../shared-forms'
+import { SharedGlobalIconModule } from '../shared-icons'
+import { SharedMainModule } from '../shared-main/shared-main.module'
+import { VideoShareComponent } from './video-share.component'
+
+@NgModule({
+  imports: [
+    QRCodeModule,
+
+    SharedMainModule,
+    SharedFormModule,
+    SharedGlobalIconModule
+  ],
+
+  declarations: [
+    VideoShareComponent
+  ],
+
+  exports: [
+    VideoShareComponent
+  ],
+
+  providers: [ ]
+})
+export class SharedShareModal { }
similarity index 96%
rename from client/src/app/+videos/+video-watch/modal/video-share.component.html
rename to client/src/app/shared/shared-share-modal/video-share.component.html
index 946e8d8ca02de5b89e2619366723c2c9a0195a2b..4174458b541292e188a0ed01cbfe1679ab97342c 100644 (file)
@@ -7,8 +7,8 @@
 
   <div class="modal-body">
 
-    <div class="playlist" *ngIf="hasPlaylist()">
-      <div class="title-page title-page-single" i18n>Share the playlist</div>
+    <div class="playlist" *ngIf="playlist">
+      <div class="title-page title-page-single" i18n *ngIf="video">Share the playlist</div>
 
       <div ngbNav #nav="ngbNav" class="nav-tabs" [(activeId)]="activePlaylistId">
 
@@ -53,7 +53,7 @@
 
       <div class="filters">
 
-        <div class="form-group">
+        <div class="form-group" *ngIf="video">
           <my-peertube-checkbox inputName="includeVideoInPlaylist" [(ngModel)]="includeVideoInPlaylist" i18n-labelText
             labelText="Share the playlist at this video position"></my-peertube-checkbox>
         </div>
@@ -62,8 +62,8 @@
     </div>
 
 
-    <div class="video">
-      <div class="title-page title-page-single" *ngIf="hasPlaylist()" i18n>Share the video</div>
+    <div class="video" *ngIf="video">
+      <div class="title-page title-page-single" *ngIf="playlist" i18n>Share the video</div>
 
       <div ngbNav #nav="ngbNav" class="nav-tabs" [(activeId)]="activeVideoId">
 
similarity index 93%
rename from client/src/app/+videos/+video-watch/modal/video-share.component.ts
rename to client/src/app/shared/shared-share-modal/video-share.component.ts
index d9171fe0ecbc04ddc5d8ceff0c7f94735b1ddb45..8d8e8a3a59507df5ee4b1134fc9376e7ade1bb1b 100644 (file)
@@ -1,9 +1,9 @@
 import { Component, ElementRef, Input, ViewChild } from '@angular/core'
-import { buildVideoOrPlaylistEmbed, buildVideoLink, buildPlaylistLink } from '../../../../assets/player/utils'
-import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
-import { VideoCaption } from '@shared/models'
 import { VideoDetails } from '@app/shared/shared-main'
 import { VideoPlaylist } from '@app/shared/shared-video-playlist'
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
+import { VideoCaption } from '@shared/models'
+import { buildPlaylistLink, buildVideoLink, buildVideoOrPlaylistEmbed } from '../../../assets/player/utils'
 
 type Customizations = {
   startAtCheckbox: boolean
@@ -51,7 +51,7 @@ export class VideoShareComponent {
 
   show (currentVideoTimestamp?: number, currentPlaylistPosition?: number) {
     let subtitle: string
-    if (this.videoCaptions.length !== 0) {
+    if (this.videoCaptions && this.videoCaptions.length !== 0) {
       subtitle = this.videoCaptions[0].language.id
     }
 
@@ -60,7 +60,7 @@ export class VideoShareComponent {
       startAt: currentVideoTimestamp ? Math.floor(currentVideoTimestamp) : 0,
 
       stopAtCheckbox: false,
-      stopAt: this.video.duration,
+      stopAt: this.video?.duration,
 
       subtitleCheckbox: false,
       subtitle,
@@ -118,10 +118,6 @@ export class VideoShareComponent {
     return this.activeVideoId === 'embed'
   }
 
-  hasPlaylist () {
-    return !!this.playlist
-  }
-
   private getPlaylistOptions (baseUrl?: string) {
     return {
       baseUrl,
index cdf0ee9928e9f44e99fad87967cb6fe70f76a6ab..f4e4d897718dd5fb7b7b507b6ce4fcb606ec3df8 100644 (file)
@@ -282,6 +282,7 @@ table {
   max-height: 500px;
 
   display: flex;
+  flex-direction: column;
   align-items: center;
   justify-content: center;
   font-size: 16px;