diff --git a/src/applications/content-entries-app/entries/bulk-actions/bulk-actions.component.ts b/src/applications/content-entries-app/entries/bulk-actions/bulk-actions.component.ts
index a38d01441f..a9324dbc30 100644
--- a/src/applications/content-entries-app/entries/bulk-actions/bulk-actions.component.ts
+++ b/src/applications/content-entries-app/entries/bulk-actions/bulk-actions.component.ts
@@ -164,7 +164,7 @@ export class BulkActionsComponent implements OnInit, OnDestroy {
this._browserService.setAppStatus({isBusy: false, errorMessage: this._appLocalization.get('applications.content.bulkActions.error')});
}
);
- }
+ };
if (this.selectedEntries.length > environment.modules.contentEntries.bulkActionsLimit){
this._browserService.confirm(
diff --git a/src/applications/content-entries-app/entries/bulk-actions/services/bulk-delete.service.ts b/src/applications/content-entries-app/entries/bulk-actions/services/bulk-delete.service.ts
index 9b9cc5f926..6c9e8ba2d7 100644
--- a/src/applications/content-entries-app/entries/bulk-actions/services/bulk-delete.service.ts
+++ b/src/applications/content-entries-app/entries/bulk-actions/services/bulk-delete.service.ts
@@ -26,7 +26,7 @@ export class BulkDeleteService extends BulkActionBaseService<{}> {
this.transmit(requests, true).subscribe(
result => {
- observer.next({})
+ observer.next({});
observer.complete();
},
error => {
diff --git a/src/applications/content-entries-app/entries/entries-list.component.ts b/src/applications/content-entries-app/entries/entries-list.component.ts
index 8821b4ba7f..501d679510 100644
--- a/src/applications/content-entries-app/entries/entries-list.component.ts
+++ b/src/applications/content-entries-app/entries/entries-list.component.ts
@@ -157,7 +157,6 @@ export class EntriesListComponent implements OnInit, OnDestroy {
);
break;
default:
- alert("Selected Action: " + event.action + "\nEntry ID: " + event.entryID);
break;
}
}
diff --git a/src/applications/content-playlists-app/content-playlists-app.module.ts b/src/applications/content-playlists-app/content-playlists-app.module.ts
index bc719d006c..230458a101 100644
--- a/src/applications/content-playlists-app/content-playlists-app.module.ts
+++ b/src/applications/content-playlists-app/content-playlists-app.module.ts
@@ -30,8 +30,6 @@ import { PopupWidgetModule } from '@kaltura-ng/kaltura-ui/popup-widget';
import { ContentPlaylistsComponent } from './content-playlists.component';
import { PlaylistsComponentsList } from './playlists/playlists-components-list';
import { PlaylistComponentsList } from './playlist/playlist-components-list';
-import { PlaylistsStore } from './playlists/playlists-store/playlists-store.service';
-import { PlaylistStore } from './playlist/playlist-store.service';
import { PlaylistCanDeactivate } from './playlist/playlist-can-deactivate.service';
@NgModule({
@@ -63,12 +61,11 @@ import { PlaylistCanDeactivate } from './playlist/playlist-can-deactivate.servic
PlaylistsComponentsList,
PlaylistComponentsList
],
- exports: [],
- providers: [
- PlaylistsStore,
- PlaylistStore,
- PlaylistCanDeactivate
- ],
+ exports: [
+ ],
+ providers : [
+ PlaylistCanDeactivate
+ ]
})
export class ContentPlaylistsAppModule {
}
diff --git a/src/applications/content-playlists-app/content-playlists-app.routes.ts b/src/applications/content-playlists-app/content-playlists-app.routes.ts
index 4aa40879ed..e5fd772081 100644
--- a/src/applications/content-playlists-app/content-playlists-app.routes.ts
+++ b/src/applications/content-playlists-app/content-playlists-app.routes.ts
@@ -1,5 +1,6 @@
import { Route } from '@angular/router';
+import { ContentPlaylistsComponent } from './content-playlists.component';
import { PlaylistsListComponent } from './playlists/playlists-list.component';
import { PlaylistComponent } from './playlist/playlist.component';
import { PlaylistMetadataComponent } from './playlist/playlist-metadata/playlist-metadata.component';
@@ -8,16 +9,21 @@ import { PlaylistSections } from './playlist/playlist-sections';
import { PlaylistCanDeactivate } from './playlist/playlist-can-deactivate.service';
export const routing: Route[] = [
- {path: '', redirectTo: 'list', pathMatch: 'full'},
- {path: 'list', component: PlaylistsListComponent},
- {path: 'playlist/:id', canDeactivate: [PlaylistCanDeactivate], component: PlaylistComponent,
- data : {
- playlistRoute : true
- },
- children : [
- { path: '', redirectTo: 'content', pathMatch: 'full' },
- { path: 'metadata', component: PlaylistMetadataComponent, data : { sectionKey : PlaylistSections.Metadata } },
- { path: 'content', component: PlaylistContentComponent, data : { sectionKey : PlaylistSections.Content } }
- ]
- }
+ {
+ path: '', component: ContentPlaylistsComponent,
+ children: [
+ { path: '', redirectTo: 'list', pathMatch: 'full' },
+ { path: 'list', component: PlaylistsListComponent },
+ { path: 'playlist/:id', canDeactivate: [PlaylistCanDeactivate], component: PlaylistComponent,
+ data: {
+ playlistRoute: true
+ },
+ children: [
+ { path: '', redirectTo: 'content', pathMatch: 'full'},
+ { path: 'metadata', component: PlaylistMetadataComponent, data: { sectionKey: PlaylistSections.Metadata } },
+ { path: 'content', component: PlaylistContentComponent, data: { sectionKey: PlaylistSections.Content } }
+ ]
+ }
+ ]
+ }
];
diff --git a/src/applications/content-playlists-app/content-playlists.component.ts b/src/applications/content-playlists-app/content-playlists.component.ts
index 296985ecd5..6a3565f0dc 100644
--- a/src/applications/content-playlists-app/content-playlists.component.ts
+++ b/src/applications/content-playlists-app/content-playlists.component.ts
@@ -1,9 +1,11 @@
import { Component } from '@angular/core';
+import { PlaylistsStore } from './playlists/playlists-store/playlists-store.service';
@Component({
selector: 'kPlaylists',
templateUrl: './content-playlists.component.html',
- styleUrls: ['./content-playlists.component.scss']
+ styleUrls: ['./content-playlists.component.scss'],
+ providers: [PlaylistsStore]
})
export class ContentPlaylistsComponent {}
diff --git a/src/applications/content-playlists-app/playlist/playlist-components-list.ts b/src/applications/content-playlists-app/playlist/playlist-components-list.ts
index 473848fc75..400eafd645 100644
--- a/src/applications/content-playlists-app/playlist/playlist-components-list.ts
+++ b/src/applications/content-playlists-app/playlist/playlist-components-list.ts
@@ -3,6 +3,7 @@ import { PlaylistContentComponent } from './playlist-content/playlist-content.co
import { PlaylistSectionsList } from "./playlist-sections-list/playlist-sections-list.component";
import { PlaylistComponent } from './playlist.component';
import { PlaylistDetailsComponent } from './playlist-details/playlist-details.component';
+import { PlaylistEntriesTableComponent } from './playlist-entries-table/playlist-entries-table.component';
import { ModerationPipe } from './pipes/moderation.pipe';
@@ -12,5 +13,6 @@ export const PlaylistComponentsList = [
PlaylistSectionsList,
PlaylistComponent,
PlaylistDetailsComponent,
+ PlaylistEntriesTableComponent,
ModerationPipe
];
diff --git a/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.html b/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.html
index 9b79f008d0..59cc0fab23 100644
--- a/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.html
+++ b/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.html
@@ -1 +1,18 @@
-
{{'applications.content.playlistDetails.sections.content' | translate}}
+
+
+
+
+
+ {{(_playlistStore.entries$ | async)?.totalCount}} {{'applications.content.playlists.playlists' | translate}}
+
+
+
+
diff --git a/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.scss b/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.scss
index e69de29bb2..9a755e91b0 100644
--- a/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.scss
+++ b/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.scss
@@ -0,0 +1,23 @@
+@import 'app-theme/_variables.scss';
+
+.kContentDetails {
+ width: 100%;
+
+ .kPlaylistsTableFilters {
+ width: 100%;
+ height: 66px;
+ background-color: white;
+ flex: 0 0 auto;
+ align-items: center;
+ display: flex;
+
+ .kAddPlaylistBtn {
+ margin-left: 14px;
+ height: 36px;
+ }
+
+ .kSelectedPlaylistsNum{
+ padding-left: 16px;
+ }
+ }
+}
diff --git a/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.ts b/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.ts
index cbea21ec89..75301ddf36 100644
--- a/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.ts
+++ b/src/applications/content-playlists-app/playlist/playlist-content/playlist-content.component.ts
@@ -1,4 +1,5 @@
import { Component, AfterViewInit, OnInit, OnDestroy } from '@angular/core';
+import { PlaylistStore } from '../playlist-store.service';
@Component({
selector: 'kPlaylistContent',
@@ -7,7 +8,7 @@ import { Component, AfterViewInit, OnInit, OnDestroy } from '@angular/core';
})
export class PlaylistContentComponent implements AfterViewInit, OnInit, OnDestroy {
- constructor() {}
+ constructor(public _playlistStore: PlaylistStore) {}
ngOnInit() {}
diff --git a/src/applications/content-playlists-app/playlist/playlist-entries-table/playlist-entries-table.component.html b/src/applications/content-playlists-app/playlist/playlist-entries-table/playlist-entries-table.component.html
new file mode 100644
index 0000000000..4cb30cc84c
--- /dev/null
+++ b/src/applications/content-playlists-app/playlist/playlist-entries-table/playlist-entries-table.component.html
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+

+
+
+
+
+
+ {{entry[col.field]}}
+
+
+
+
+ {{entry[col.field]}}
+
+
+
+
+ {{entry[col.field] | kDate}}
+
+
+
+
+
+ {{entry[col.field]}}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/applications/content-playlists-app/playlist/playlist-entries-table/playlist-entries-table.component.scss b/src/applications/content-playlists-app/playlist/playlist-entries-table/playlist-entries-table.component.scss
new file mode 100644
index 0000000000..3110015b91
--- /dev/null
+++ b/src/applications/content-playlists-app/playlist/playlist-entries-table/playlist-entries-table.component.scss
@@ -0,0 +1,44 @@
+@import 'app-theme/_variables.scss';
+
+.kPlaylistEntriesTable {
+ background-color: white;
+ overflow-y: hidden;
+ position: absolute;
+ padding: 0px;
+
+ .kThumbnailHolder {
+ overflow: hidden;
+ position: relative;
+ width: 80px;
+ height: 46px;
+ background-color: $kGrayscale6;
+ white-space: nowrap;
+ text-align: center;
+ border-radius: 3px;
+ cursor: pointer;
+
+ img {
+ position:absolute;
+ left: -100%;
+ right: -100%;
+ top: -100%;
+ bottom: -100%;
+ margin: auto;
+ width: 80px;
+ height: auto;
+ border-radius: 3px;
+ }
+ }
+
+ .kEntriesTableActions {
+ width: 100%;
+ text-align: center;
+ button {
+ color: grey !important;
+ background-color: rgba(0, 0, 0, 0) !important;
+ border: none !important;
+ font-size: 16px !important;
+ outline: 0;
+ }
+ }
+}
diff --git a/src/applications/content-playlists-app/playlist/playlist-entries-table/playlist-entries-table.component.ts b/src/applications/content-playlists-app/playlist/playlist-entries-table/playlist-entries-table.component.ts
new file mode 100644
index 0000000000..d6e2fc6e64
--- /dev/null
+++ b/src/applications/content-playlists-app/playlist/playlist-entries-table/playlist-entries-table.component.ts
@@ -0,0 +1,60 @@
+import { Component, Input, Output, EventEmitter, AfterViewInit, OnInit, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core';
+import { ISubscription } from 'rxjs/Subscription';
+import { MenuItem, DataTable, Menu } from 'primeng/primeng';
+import { AppLocalization } from '@kaltura-ng/kaltura-common';
+import { AreaBlockerMessage } from '@kaltura-ng/kaltura-ui';
+import { KalturaMediaType } from 'kaltura-typescript-client/types/KalturaMediaType';
+import { KalturaMediaEntry } from 'kaltura-typescript-client/types/KalturaMediaEntry';
+import { KalturaEntryStatus } from 'kaltura-typescript-client/types/KalturaEntryStatus';
+import { PlaylistStore } from "../playlist-store.service";
+
+@Component({
+ selector: 'kPlaylistEntriesTable',
+ templateUrl: './playlist-entries-table.component.html',
+ styleUrls: ['./playlist-entries-table.component.scss']
+})
+export class PlaylistEntriesTableComponent implements AfterViewInit, OnInit, OnDestroy {
+ public _entries: any[] = [];
+ private _deferredEntries : any[];
+ public _deferredLoading = true;
+ public rowTrackBy: Function = (index: number, item: any) => {return item.id};
+
+ @Input() set entries(data: any[]) {
+ if (!this._deferredLoading) {
+ this._entries = [];
+ this.cdRef.detectChanges();
+ this._entries = data;
+ this.cdRef.detectChanges();
+ } else {
+ this._deferredEntries = data
+ }
+ }
+
+ constructor(
+ private appLocalization: AppLocalization,
+ public playlistStore: PlaylistStore,
+ private cdRef: ChangeDetectorRef
+ ) {}
+ ngOnInit() {
+ /*this.playlistStore.entries$
+ .subscribe(response => {
+
+ });*/
+ }
+
+ ngAfterViewInit() {
+ if (this._deferredLoading) {
+ // use timeout to allow the DOM to render before setting the data to the datagrid. This prevents the screen from hanging during datagrid rendering of the data.
+ setTimeout(()=> {
+ this._deferredLoading = false;
+ this._entries = this._deferredEntries;
+ this._deferredEntries = null;
+ }, 0);
+ }
+ }
+
+ ngOnDestroy() {
+
+ }
+}
+
diff --git a/src/applications/content-playlists-app/playlist/playlist-metadata/playlist-metadata.component.scss b/src/applications/content-playlists-app/playlist/playlist-metadata/playlist-metadata.component.scss
index 77e20ac7c2..f2032e8244 100644
--- a/src/applications/content-playlists-app/playlist/playlist-metadata/playlist-metadata.component.scss
+++ b/src/applications/content-playlists-app/playlist/playlist-metadata/playlist-metadata.component.scss
@@ -1,16 +1,14 @@
@import 'app-theme/_variables.scss';
.kMetadataDetails {
- padding: 18px 8px 0 12px;
+ padding: 26px 8px 8px 20px;
overflow-y: auto;
width: 100%;
.kSchemaTitle {
color: $kGrayscale1;
font-size: 18px;
- font-weight: 700;
- padding-top: 30px;
- padding-bottom: 12px;
+ font-weight: bold;
}
/deep/ {
diff --git a/src/applications/content-playlists-app/playlist/playlist-store.service.ts b/src/applications/content-playlists-app/playlist/playlist-store.service.ts
index 89c3008731..d8c3fbd872 100644
--- a/src/applications/content-playlists-app/playlist/playlist-store.service.ts
+++ b/src/applications/content-playlists-app/playlist/playlist-store.service.ts
@@ -14,26 +14,31 @@ import { KalturaTagFilter } from 'kaltura-typescript-client/types/KalturaTagFilt
import { KalturaTaggedObjectType } from 'kaltura-typescript-client/types/KalturaTaggedObjectType';
import { KalturaFilterPager } from 'kaltura-typescript-client/types/KalturaFilterPager';
import { PlaylistSections } from './playlist-sections';
+import { KalturaMultiRequest } from 'kaltura-typescript-client';
+import { PlaylistExecuteAction } from 'kaltura-typescript-client/types/PlaylistExecuteAction';
+import { KalturaBaseEntry } from 'kaltura-typescript-client/types/KalturaBaseEntry';
@Injectable()
export class PlaylistStore implements OnDestroy {
- private _sectionsState = new BehaviorSubject<{
- metadata: {isValid: boolean, isDirty?: boolean},
+ private _sectionsState = new BehaviorSubject<{
+ metadata: {isValid: boolean, isDirty?: boolean},
content: {isValid: boolean, isDirty?: boolean}
- }>({
- metadata: {isValid: true, isDirty: false},
+ }>({
+ metadata: {isValid: true, isDirty: false},
content: {isValid: true, isDirty: false}
- });
- private _loadPlaylistSubscription : ISubscription;
+ });
+ private _loadPlaylistSubscription : ISubscription;
private _sectionToRouteMapping : { [key : number] : string} = {};
- private _activeSection = new BehaviorSubject<{ section: PlaylistSections}>({section: null});
- private _playlist = new BehaviorSubject<{ playlist: KalturaPlaylist}>({playlist: null});
- private _state = new BehaviorSubject<{ isBusy: boolean, error?: { message: string, origin?: 'reload' | 'save'}}>({isBusy: false});
+ private _activeSection = new BehaviorSubject<{ section: PlaylistSections}>({section: null});
+ private _playlist = new BehaviorSubject<{ playlist: KalturaPlaylist}>({playlist: null});
+ private _state = new BehaviorSubject<{ isBusy: boolean, error?: { message: string, origin?: 'reload' | 'save'}}>({isBusy: false});
+ private _entries = new BehaviorSubject({items: [], totalCount: 0});
- public playlist$ = this._playlist.asObservable();
+ public entries$ = this._entries.asObservable();
+ public playlist$ = this._playlist.asObservable();
public activeSection$ = this._activeSection.asObservable();
- public sectionsState$ = this._sectionsState.asObservable();
- public state$ = this._state.asObservable();
+ public sectionsState$ = this._sectionsState.asObservable();
+ public state$ = this._state.asObservable();
private _getPlaylistId() : string
{
@@ -44,19 +49,19 @@ export class PlaylistStore implements OnDestroy {
return this._playlist.getValue().playlist;
}
- constructor(
- private _router: Router,
- private _playlistRoute: ActivatedRoute,
- private _kalturaServerClient: KalturaClient,
- private _appLocalization: AppLocalization,
+ constructor(
+ private _router: Router,
+ private _playlistRoute: ActivatedRoute,
+ private _kalturaServerClient: KalturaClient,
+ private _appLocalization: AppLocalization,
private _browserService : BrowserService
- ) {
- this._mapSections();
+ ) {
+ this._mapSections();
- this._onRouterEvents();
+ this._onRouterEvents();
this._activeSection.next({section: this._playlistRoute.snapshot.firstChild.data.sectionKey});
- }
+ }
public openSection(sectionId: PlaylistSections): void {
const navigatePath = this._sectionToRouteMapping[sectionId];
@@ -82,57 +87,69 @@ export class PlaylistStore implements OnDestroy {
});
}
- private _onRouterEvents() : void {
- this._router.events
- .cancelOnDestroy(this)
- .subscribe(
- event => {
- if (event instanceof NavigationEnd) {
- const currentPlaylistId = this._playlistRoute.snapshot.params.id;
- const playlist = this._playlist.getValue();
- if (!playlist.playlist || (playlist.playlist && playlist.playlist.id !== currentPlaylistId)) {
- this._loadPlaylist(currentPlaylistId);
- } else {
+ private _onRouterEvents() : void {
+ this._router.events
+ .cancelOnDestroy(this)
+ .subscribe(
+ event => {
+ if (event instanceof NavigationEnd) {
+ const currentPlaylistId = this._playlistRoute.snapshot.params.id;
+ const playlist = this._playlist.getValue();
+ if (!playlist.playlist || (playlist.playlist && playlist.playlist.id !== currentPlaylistId)) {
+ this._loadPlaylist(currentPlaylistId);
+ } else {
this._activeSection.next({section: this._playlistRoute.snapshot.firstChild.data.sectionKey});
}
- }
- }
- )
- }
-
- private _loadPlaylist(id : string) : void {
- if (this._loadPlaylistSubscription) {
- this._loadPlaylistSubscription.unsubscribe();
- this._loadPlaylistSubscription = null;
- }
-
- this._state.next({isBusy: true});
-
- this._loadPlaylistSubscription = this._kalturaServerClient.request(new PlaylistGetAction({id}))
- .cancelOnDestroy(this)
- .subscribe(
- response => {
- if (response instanceof KalturaPlaylist) {
- this._playlist.next({playlist: response});
- this._state.next({isBusy: false});
- } else {
- this._state.next({
- isBusy: true,
- error: {
- message: this._appLocalization.get('applications.content.playlistDetails.errors.playlistTypeNotSupported'),
- origin: 'reload'
- }
- });
- }
- },
- error => {
- this._state.next({
- isBusy: true,
- error: {message: error.message, origin: 'reload'}
- });
- }
- );
- }
+ }
+ }
+ )
+ }
+
+ private _loadPlaylist(id : string) : void {
+ if (this._loadPlaylistSubscription) {
+ this._loadPlaylistSubscription.unsubscribe();
+ this._loadPlaylistSubscription = null;
+ }
+
+ this._state.next({isBusy: true});
+
+ this._loadPlaylistSubscription = this._kalturaServerClient.multiRequest(
+ new KalturaMultiRequest(
+ new PlaylistGetAction({id}),
+ new PlaylistExecuteAction({id})
+ ))
+ .cancelOnDestroy(this)
+ .subscribe(
+ data => {
+ data.forEach(response => {
+ if (response.result instanceof KalturaPlaylist) {
+ this._playlist.next({playlist: response.result});
+ this._state.next({isBusy: false});
+ } else if(response.result.length >= 1 && response.result[0] instanceof KalturaBaseEntry) {
+ this._entries.next({
+ items: response.result,
+ totalCount: response.result.length
+ });
+ } else {
+ this._state.next({
+ isBusy: true,
+ error: {
+ message: this._appLocalization.get('applications.content.playlistDetails.errors.playlistTypeNotSupported'),
+ origin: 'reload'
+ }
+ });
+ }
+ });
+ },
+ error => {
+ this._state.next({
+ isBusy: true,
+ error: {message: error.message, origin: 'reload'}
+ });
+ }
+ );
+
+ }
public updateSectionState(section: PlaylistSections, state : {isValid?: boolean, isDirty?: boolean}) : void {
const sections = Object.assign({}, this._sectionsState.getValue());
@@ -177,11 +194,11 @@ export class PlaylistStore implements OnDestroy {
});
} else {
let id: string = this._getPlaylistId(),
- playlist: KalturaPlaylist = new KalturaPlaylist({
- name: this._playlist.getValue().playlist.name,
- description: this._playlist.getValue().playlist.description,
- tags: this._playlist.getValue().playlist.tags
- });
+ playlist: KalturaPlaylist = new KalturaPlaylist({
+ name: this._playlist.getValue().playlist.name,
+ description: this._playlist.getValue().playlist.description,
+ tags: this._playlist.getValue().playlist.tags
+ });
this._state.next({isBusy: true});
this._kalturaServerClient.request(
@@ -315,9 +332,10 @@ export class PlaylistStore implements OnDestroy {
});
}
- ngOnDestroy() {
- this._loadPlaylistSubscription && this._loadPlaylistSubscription.unsubscribe();
- this._state.complete();
- this._playlist.complete();
- }
+ ngOnDestroy() {
+ this._loadPlaylistSubscription && this._loadPlaylistSubscription.unsubscribe();
+ this._state.complete();
+ this._playlist.complete();
+ }
}
+
diff --git a/src/applications/content-playlists-app/playlist/playlist.component.scss b/src/applications/content-playlists-app/playlist/playlist.component.scss
index 393fa90772..16c35ef9fb 100644
--- a/src/applications/content-playlists-app/playlist/playlist.component.scss
+++ b/src/applications/content-playlists-app/playlist/playlist.component.scss
@@ -93,7 +93,6 @@
border-top-right-radius: 3px;
flex: 1 1 auto;
margin-right: 28px;
- padding: 8px;
}
.kPlaylistDetailsPreview {
margin-left: auto;
diff --git a/src/applications/content-playlists-app/playlists/bulk-service/bulk-delete.service.ts b/src/applications/content-playlists-app/playlists/bulk-service/bulk-delete.service.ts
new file mode 100644
index 0000000000..0416dadd0f
--- /dev/null
+++ b/src/applications/content-playlists-app/playlists/bulk-service/bulk-delete.service.ts
@@ -0,0 +1,79 @@
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+import { PlaylistsStore } from '../playlists-store/playlists-store.service';
+import { PlaylistDeleteAction } from 'kaltura-typescript-client/types/PlaylistDeleteAction';
+import { KalturaRequest, KalturaMultiRequest, KalturaMultiResponse } from 'kaltura-typescript-client';
+import { environment } from 'app-environment';
+import { KalturaClient } from '@kaltura-ng/kaltura-client';
+import { BehaviorSubject } from 'rxjs/BehaviorSubject';
+
+@Injectable()
+export class BulkDeleteService {
+ private _stateDelete = new BehaviorSubject<{loading : boolean}>({ loading : false});
+ public stateDelete$ = this._stateDelete.asObservable();
+
+ constructor(
+ public _playlistsStore: PlaylistsStore,
+ public _kalturaServerClient: KalturaClient
+ ) {}
+
+ public deletePlaylist(ids: string[]): Observable{
+ return Observable.create(observer =>{
+ this._stateDelete.next({loading: true});
+ let requests: PlaylistDeleteAction[] = [];
+ if(ids && ids.length > 0) {
+ ids.forEach(id => requests.push(new PlaylistDeleteAction({ id: id })));
+
+ this._transmit(requests, true).subscribe(
+ () => {
+ this._stateDelete.next({loading: false});
+ observer.next({});
+ observer.complete();
+ },
+ error => {
+ this._stateDelete.next({loading: false});
+ observer.error(error);
+ }
+ );
+ } else {
+ this._stateDelete.next({loading: false});
+ observer.next({});
+ observer.complete();
+ }
+ });
+ }
+
+ private _transmit(requests : KalturaRequest[], chunk : boolean) : Observable<{}> {
+ let maxRequestsPerMultiRequest = requests.length;
+ if (chunk){
+ maxRequestsPerMultiRequest = environment.modules.contentPlaylists.bulkActionsLimit;
+ }
+
+ let multiRequests: Observable[] = [];
+ let mr :KalturaMultiRequest = new KalturaMultiRequest();
+
+ let counter = 0;
+ for (let i = 0; i < requests.length; i++){
+ if (counter === maxRequestsPerMultiRequest){
+ multiRequests.push(this._kalturaServerClient.multiRequest(mr));
+ mr = new KalturaMultiRequest();
+ counter = 0;
+ }
+ mr.requests.push(requests[i]);
+ counter++;
+ }
+
+ multiRequests.push(this._kalturaServerClient.multiRequest(mr));
+
+ return Observable.forkJoin(multiRequests)
+ .map(responses => {
+ const mergedResponses = [].concat.apply([], responses);
+ let hasFailure = mergedResponses.filter(function ( response ) {return response.error}).length > 0;
+ if (hasFailure) {
+ throw new Error("error");
+ } else {
+ return {};
+ }
+ });
+ }
+}
diff --git a/src/applications/content-playlists-app/playlists/pipes/playlist-type.pipe.ts b/src/applications/content-playlists-app/playlists/pipes/playlist-type.pipe.ts
index b89a7feea2..073abaeb24 100644
--- a/src/applications/content-playlists-app/playlists/pipes/playlist-type.pipe.ts
+++ b/src/applications/content-playlists-app/playlists/pipes/playlist-type.pipe.ts
@@ -28,7 +28,7 @@ export class PlaylistTypePipe implements PipeTransform {
break;
default:
className = 'kIconUnknown';
- playlistType = this.appLocalization.get("applications.content.playlistType.unknown");;
+ playlistType = this.appLocalization.get("applications.content.playlistType.unknown");
break;
}
}
diff --git a/src/applications/content-playlists-app/playlists/playlists-list.component.html b/src/applications/content-playlists-app/playlists/playlists-list.component.html
index ba42180c8a..63edb790ac 100644
--- a/src/applications/content-playlists-app/playlists/playlists-list.component.html
+++ b/src/applications/content-playlists-app/playlists/playlists-list.component.html
@@ -1,68 +1,70 @@
-
-
-
-
-
- {{(_playlistsStore.playlists$ | async)?.totalCount}} {{'applications.content.playlists.playlists' | translate}}
+
+
+
+
+
+
+ {{(_playlistsStore.playlists$ | async)?.totalCount}} {{'applications.content.playlists.playlists' | translate}}
-
-
-
-
-
-
-
- {{item.label}}
-
-
-
-
-
+
+
+
+
+
+
+
+ {{item.label}}
+
+
+
+
+
-
-
-
+
+
+
+
({ busy : false, errorMessage : null});
- public state$ = this._state.asObservable();
public _blockerMessage: AreaBlockerMessage = null;
- public _msgs: Message[] = [];
+ private _loading: boolean = false;
_filter = {
pageIndex : 0,
@@ -55,8 +50,7 @@ export class PlaylistsListComponent implements OnInit, OnDestroy {
sortDirection : SortDirection.Desc
};
- public showLoader = true;
- public _selectedPlaylists: any[] = [];
+ public _selectedPlaylists: KalturaPlaylist[] = [];
private querySubscription : ISubscription;
public activeFilters: Filter[] = [];
@@ -64,7 +58,8 @@ export class PlaylistsListComponent implements OnInit, OnDestroy {
public _playlistsStore: PlaylistsStore,
private appLocalization: AppLocalization,
private router: Router,
- private _browserService : BrowserService
+ private _browserService : BrowserService,
+ public _bulkDeleteService : BulkDeleteService
) {}
removeTag(tag: Filter){
@@ -107,30 +102,66 @@ export class PlaylistsListComponent implements OnInit, OnDestroy {
message: `
${this.appLocalization.get('applications.content.playlists.confirmDelete', {0:''})}
${this.appLocalization.get('applications.content.playlists.playlistId', { 0: event.playlistID })}
- ${this.appLocalization.get('applications.content.playlists.deleteNote', {0:''})}`,
+ ${this.appLocalization.get('applications.content.playlists.deleteNote', {0:'this', 1:''})}`,
accept: () => {
- this.deletePlaylist(event.playlistID);
+ this.deleteCurrentPlaylist(event.playlistID);
}
}
);
break;
default:
- alert("Selected Action: " + event.action + "\nPlaylist ID: " + event.playlistID);
break;
}
}
- private deletePlaylist(playlistIds: any): void{
- this._state.next({busy: true, errorMessage: null});
- this._blockerMessage = null;
- // Array.isArray(playlistIds)? playlistIds.map(id => id.id) : playlistIds
- this._playlistsStore.deletePlaylist(playlistIds)
+ private deletePlaylist(ids: string[]): void {
+ const execute = () => {
+ this._bulkDeleteService.deletePlaylist(ids)
+ .cancelOnDestroy(this)
+ .subscribe(
+ () => {
+ this._loading = false;
+ this._playlistsStore.reload(true);
+ this.clearSelection();
+ },
+ error => {
+ this._blockerMessage = new AreaBlockerMessage({
+ message: this.appLocalization.get('applications.content.bulkActions.errorPlaylists'),
+ buttons: [{
+ label: this.appLocalization.get('app.common.ok'),
+ action: () => {
+ this._blockerMessage = null;
+ this._loading = false;
+ }
+ }]
+ });
+ }
+ );
+ };
+
+ if(ids.length > environment.modules.contentEntries.bulkActionsLimit) {
+ this._browserService.confirm(
+ {
+ header: this.appLocalization.get('applications.content.bulkActions.note'),
+ message: this.appLocalization.get('applications.content.bulkActions.confirmPlaylsts', {"0": ids.length}),
+ accept: () => {
+ execute();
+ }
+ }
+ );
+ } else{
+ execute();
+ }
+ }
+
+ private deleteCurrentPlaylist(playlistId: string): void {
+ this._loading = true;
+ this._playlistsStore.deletePlaylist(playlistId)
+ .cancelOnDestroy(this)
.subscribe(
- result => {
- this._state.next({busy: false, errorMessage: null});
- this._msgs = [];
- this._msgs.push({severity: 'success', summary: '', detail: this.appLocalization.get('applications.content.playlists.deleted')});
- this.clearSelection();
+ () => {
+ this._loading = false;
+ this._playlistsStore.reload(true);
},
error => {
this._blockerMessage = new AreaBlockerMessage(
@@ -140,14 +171,14 @@ export class PlaylistsListComponent implements OnInit, OnDestroy {
{
label: this.appLocalization.get('app.common.retry'),
action: () => {
- this.deletePlaylist(playlistIds);
+ this.deleteCurrentPlaylist(playlistId);
}
},
{
label: this.appLocalization.get('app.common.cancel'),
action: () => {
this._blockerMessage = null;
- this._state.next({busy: false, errorMessage: null});
+ this._loading = false;
}
}
]
@@ -276,19 +307,20 @@ export class PlaylistsListComponent implements OnInit, OnDestroy {
this._selectedPlaylists = [];
}
- deletePlaylists(selectedPlaylists) {
- let playlistsToDelete = selectedPlaylists.map((playlist, index) => {
- return `${index + 1}: ${playlist.name}`;
- });
+ deletePlaylists(selectedPlaylists: KalturaPlaylist[]) {
+ let playlistsToDelete = selectedPlaylists.map((playlist, index) => `${index + 1}: ${playlist.name}`),
+ playlists: string = selectedPlaylists.length <= 10 ? playlistsToDelete.join(',').replace(/,/gi, '
') + '
' : '';
this._browserService.confirm(
{
header: this.appLocalization.get('applications.content.playlists.deletePlaylist'),
message: `
${this.appLocalization.get('applications.content.playlists.confirmDelete', {0: selectedPlaylists.length > 1 ? 's': ''})}
- ${playlistsToDelete.join(',').replace(/,/gi, '
')}
- ${this.appLocalization.get('applications.content.playlists.deleteNote', {0: selectedPlaylists.length > 1 ? 's': ''})}`,
+ ${playlists}
+ ${this.appLocalization.get('applications.content.playlists.deleteNote', {0: selectedPlaylists.length > 1 ? 'these' : 'this', 1: selectedPlaylists.length > 1 ? 's': ''})}`,
accept: () => {
- // this.deletePlaylist(selectedPlaylists);
+ setTimeout(()=> {
+ this.deletePlaylist(selectedPlaylists.map(playlist => playlist.id));
+ }, 0);
}
}
);
diff --git a/src/applications/content-playlists-app/playlists/playlists-store/playlists-store.service.ts b/src/applications/content-playlists-app/playlists/playlists-store/playlists-store.service.ts
index 6170d7b35c..a99029f327 100644
--- a/src/applications/content-playlists-app/playlists/playlists-store/playlists-store.service.ts
+++ b/src/applications/content-playlists-app/playlists/playlists-store/playlists-store.service.ts
@@ -13,15 +13,14 @@ import { KalturaPlaylistFilter } from 'kaltura-typescript-client/types/KalturaPl
import { KalturaFilterPager } from 'kaltura-typescript-client/types/KalturaFilterPager';
import { KalturaDetachedResponseProfile } from 'kaltura-typescript-client/types/KalturaDetachedResponseProfile';
import { KalturaResponseProfileType } from 'kaltura-typescript-client/types/KalturaResponseProfileType';
+import { PlaylistDeleteAction } from 'kaltura-typescript-client/types/PlaylistDeleteAction';
import 'rxjs/add/operator/subscribeOn';
import 'rxjs/add/operator/map';
import 'rxjs/add/observable/throw';
import { KalturaPlaylist } from 'kaltura-typescript-client/types/KalturaPlaylist';
-import { BrowserService } from "app-shared/kmc-shell/providers/browser.service";
-import { BaseEntryDeleteAction } from 'kaltura-typescript-client/types/BaseEntryDeleteAction';
-import {PlaylistDeleteAction} from "kaltura-typescript-client/types/PlaylistDeleteAction";
+import { BrowserService } from 'app-shared/kmc-shell/providers/browser.service';
export enum SortDirection {
Desc,
@@ -42,8 +41,7 @@ export interface QueryData
@Injectable()
export class PlaylistsStore implements OnDestroy {
- private _playlistsSource = new BehaviorSubject({items: [], totalCount: 0});
- private _playlists = new BehaviorSubject({items: [], totalCount: 0});
+ private _playlistsSource = new BehaviorSubject<{items: KalturaPlaylist[], totalCount: number}>({items: [], totalCount: 0});
private _stateSource = new BehaviorSubject<{loading : boolean, errorMessage : string}>({ loading : false, errorMessage : null});
private _querySource = new BehaviorSubject({
pageIndex: 1,
@@ -55,7 +53,6 @@ export class PlaylistsStore implements OnDestroy {
createdAfter : null
});
private requestSubscription : ISubscription = null;
- private _destoryed: boolean = false;
public playlists$ = this._playlistsSource.asObservable();
public state$ = this._stateSource.asObservable();
@@ -63,7 +60,8 @@ export class PlaylistsStore implements OnDestroy {
constructor(
private kalturaServerClient: KalturaClient,
- private browserService: BrowserService
+ private browserService: BrowserService,
+ public _kalturaServerClient: KalturaClient
) {
const defaultPageSize = this.browserService.getFromLocalStorage("playlists.list.pageSize");
if (defaultPageSize !== null) {
@@ -97,7 +95,6 @@ export class PlaylistsStore implements OnDestroy {
if(this.requestSubscription) {
this.requestSubscription.unsubscribe();
}
- this._destoryed = true;
}
public reload(force : boolean) : void;
@@ -201,33 +198,24 @@ export class PlaylistsStore implements OnDestroy {
}
}
- public deletePlaylist(playlistId: any): Observable{
-
+ public deletePlaylist(id: string) {
return Observable.create(observer => {
let subscription: ISubscription;
- if (playlistId && playlistId.length) {
- subscription = this.kalturaServerClient.request(new PlaylistDeleteAction({id: playlistId})).subscribe(
- () => {
- if (!this._destoryed) {
- this.reload(true);
- }
- observer.next();
- observer.complete();
- },
- error =>{
- observer.error(error);
- }
- );
- } else {
- observer.error(new Error('missing playlistId argument'));
- }
+ subscription = this._kalturaServerClient.request(new PlaylistDeleteAction({id})).subscribe(
+ () => {
+ observer.next();
+ observer.complete();
+ },
+ error =>{
+ observer.error(error);
+ }
+ );
return ()=>{
if (subscription) {
subscription.unsubscribe();
}
}
});
-
}
}
diff --git a/src/environments/environment.ts b/src/environments/environment.ts
index f3a2ad0c51..fa37de617b 100644
--- a/src/environments/environment.ts
+++ b/src/environments/environment.ts
@@ -112,7 +112,8 @@ export const environment = {
"bulkActionsLimit": 50
},
"contentPlaylists" : {
- "createdAtDateRange" : "2005:2030"
+ "createdAtDateRange" : "2005:2030",
+ "bulkActionsLimit": 2
}
},
"entriesShared": {
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 6c00d71e3c..a3ce72522a 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -79,7 +79,7 @@
"addPlaylist": "Add Playlist",
"addEntry": "Add Entry",
"refresh": "Refresh",
- "deleteNote": "Please note: the playlist{{0}} will be permanently deleted from your account."
+ "deleteNote": "Please note: {{0}} playlist{{1}} will be permanently deleted from your account."
},
"filters": {
"activeFilters": "Active Filters:",
@@ -202,9 +202,11 @@
"delete": "Delete",
"apply": "Apply to all selected entries",
"error": "An error occurred during entries update.",
+ "errorPlaylists": "An error occurred during playlists update.",
"updated": "Entries updated successfully",
"note": "Update Note",
"confirm": "Are you sure you want to update {{0}} entries? It could take a while...",
+ "confirmPlaylsts": "Are you sure you want to update {{0}} playlists? It could take a while...",
"deleteEntries": "Delete Entries",
"deleteConfirm": "Are you sure you want to delete the selected entries?",
"deleteNote": "Please note: the selected entries will be permanently deleted from your account."