-
-
-
-
-
- {{sortOption['value']['label']}}
-
-
-
-
-
-
-
-
+
diff --git a/src/app/components/recent-videos/recent-videos.component.scss b/src/app/components/recent-videos/recent-videos.component.scss
index 1226a28..5fb02cf 100644
--- a/src/app/components/recent-videos/recent-videos.component.scss
+++ b/src/app/components/recent-videos/recent-videos.component.scss
@@ -41,12 +41,6 @@
display: inline-block;
}
-.sort-dir-div {
- display: inline-block;
- position: absolute;
- top: 4px;
-}
-
.paginator {
margin-top: 5px;
}
diff --git a/src/app/components/recent-videos/recent-videos.component.ts b/src/app/components/recent-videos/recent-videos.component.ts
index d124cfe..324d2d8 100644
--- a/src/app/components/recent-videos/recent-videos.component.ts
+++ b/src/app/components/recent-videos/recent-videos.component.ts
@@ -1,7 +1,7 @@
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { PostsService } from 'app/posts.services';
import { Router } from '@angular/router';
-import { DatabaseFile, FileType, FileTypeFilter } from '../../../api-types';
+import { DatabaseFile, FileType, FileTypeFilter, Sort } from '../../../api-types';
import { MatPaginator } from '@angular/material/paginator';
import { Subject } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';
@@ -47,33 +47,6 @@ export class RecentVideosComponent implements OnInit {
search_text = '';
searchIsFocused = false;
descendingMode = true;
- sortProperties = {
- 'registered': {
- 'key': 'registered',
- 'label': $localize`Download Date`,
- 'property': 'registered'
- },
- 'upload_date': {
- 'key': 'upload_date',
- 'label': $localize`Upload Date`,
- 'property': 'upload_date'
- },
- 'name': {
- 'key': 'name',
- 'label': $localize`Name`,
- 'property': 'title'
- },
- 'file_size': {
- 'key': 'file_size',
- 'label': $localize`File Size`,
- 'property': 'size'
- },
- 'duration': {
- 'key': 'duration',
- 'label': $localize`Duration`,
- 'property': 'duration'
- }
- };
fileFilters = {
video_only: {
@@ -94,7 +67,7 @@ export class RecentVideosComponent implements OnInit {
selectedFilters = [];
- sortProperty = this.sortProperties['upload_date'];
+ sortProperty = 'registered';
playlists = null;
@@ -109,8 +82,8 @@ export class RecentVideosComponent implements OnInit {
// set filter property to cached value
const cached_sort_property = localStorage.getItem('sort_property');
- if (cached_sort_property && this.sortProperties[cached_sort_property]) {
- this.sortProperty = this.sortProperties[cached_sort_property];
+ if (cached_sort_property) {
+ this.sortProperty = cached_sort_property;
}
// set file type filter to cached value
@@ -189,8 +162,12 @@ export class RecentVideosComponent implements OnInit {
this.searchChangedSubject.next(newvalue);
}
- filterOptionChanged(value: string): void {
- localStorage.setItem('filter_property', value['key']);
+ sortOptionChanged(value: Sort): void {
+ localStorage.setItem('sort_property', value['by']);
+ localStorage.setItem('recent_videos_sort_order', value['order'] === -1 ? 'descending' : 'ascending');
+ this.descendingMode = value['order'] === -1;
+ this.sortProperty = value['by'];
+
this.getAllFiles();
}
@@ -227,18 +204,13 @@ export class RecentVideosComponent implements OnInit {
return this.selectedFilters.includes('favorited');
}
- toggleModeChange(): void {
- this.descendingMode = !this.descendingMode;
- localStorage.setItem('recent_videos_sort_order', this.descendingMode ? 'descending' : 'ascending');
- this.getAllFiles();
- }
// get files
getAllFiles(cache_mode = false): void {
this.normal_files_received = cache_mode;
const current_file_index = (this.paginator?.pageIndex ? this.paginator.pageIndex : 0)*this.pageSize;
- const sort = {by: this.sortProperty['property'], order: this.descendingMode ? -1 : 1};
+ const sort = {by: this.sortProperty, order: this.descendingMode ? -1 : 1};
const range = [current_file_index, current_file_index + this.pageSize];
const fileTypeFilter = this.getFileTypeFilter();
const favoriteFilter = this.getFavoriteFilter();
diff --git a/src/app/components/sort-property/sort-property.component.html b/src/app/components/sort-property/sort-property.component.html
new file mode 100644
index 0000000..a4f055d
--- /dev/null
+++ b/src/app/components/sort-property/sort-property.component.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+ {{sortOption['value']['label']}}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/components/sort-property/sort-property.component.scss b/src/app/components/sort-property/sort-property.component.scss
new file mode 100644
index 0000000..4e67332
--- /dev/null
+++ b/src/app/components/sort-property/sort-property.component.scss
@@ -0,0 +1,5 @@
+.sort-dir-div {
+ display: inline-block;
+ position: absolute;
+ top: 4px;
+}
\ No newline at end of file
diff --git a/src/app/components/sort-property/sort-property.component.spec.ts b/src/app/components/sort-property/sort-property.component.spec.ts
new file mode 100644
index 0000000..19a55ea
--- /dev/null
+++ b/src/app/components/sort-property/sort-property.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SortPropertyComponent } from './sort-property.component';
+
+describe('SortPropertyComponent', () => {
+ let component: SortPropertyComponent;
+ let fixture: ComponentFixture
;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ SortPropertyComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(SortPropertyComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/components/sort-property/sort-property.component.ts b/src/app/components/sort-property/sort-property.component.ts
new file mode 100644
index 0000000..f86fd92
--- /dev/null
+++ b/src/app/components/sort-property/sort-property.component.ts
@@ -0,0 +1,54 @@
+import { Component, Input, EventEmitter, Output } from '@angular/core';
+import { Sort } from 'api-types';
+
+@Component({
+ selector: 'app-sort-property',
+ templateUrl: './sort-property.component.html',
+ styleUrls: ['./sort-property.component.scss']
+})
+export class SortPropertyComponent {
+ sortProperties = {
+ 'registered': {
+ 'key': 'registered',
+ 'label': $localize`Download Date`
+ },
+ 'upload_date': {
+ 'key': 'upload_date',
+ 'label': $localize`Upload Date`
+ },
+ 'title': {
+ 'key': 'title',
+ 'label': $localize`Name`
+ },
+ 'size': {
+ 'key': 'size',
+ 'label': $localize`File Size`
+ },
+ 'duration': {
+ 'key': 'duration',
+ 'label': $localize`Duration`
+ }
+ };
+
+ @Input() sortProperty = 'registered';
+ @Input() descendingMode = true;
+
+ @Output() sortPropertyChange = new EventEmitter();
+ @Output() descendingModeChange = new EventEmitter();
+ @Output() sortOptionChanged = new EventEmitter();
+
+ toggleModeChange(): void {
+ this.descendingMode = !this.descendingMode;
+ this.emitSortOptionChanged();
+ }
+
+ emitSortOptionChanged(): void {
+ if (!this.sortProperty || !this.sortProperties[this.sortProperty]) {
+ return;
+ }
+ this.sortOptionChanged.emit({
+ by: this.sortProperty,
+ order: this.descendingMode ? -1 : 1
+ });
+ }
+}
diff --git a/src/app/dialogs/generate-rss-url/generate-rss-url.component.html b/src/app/dialogs/generate-rss-url/generate-rss-url.component.html
new file mode 100644
index 0000000..1cfefb6
--- /dev/null
+++ b/src/app/dialogs/generate-rss-url/generate-rss-url.component.html
@@ -0,0 +1,67 @@
+Generate RSS URL
+
+
+
+
+
+
+ Title filter
+
+ Supports regex
+
+
+
+
+ File type
+
+ Both
+ Video only
+ Audio only
+
+
+
+
+
+ User
+
+ None
+ {{user.name}}
+
+
+
+
+
+ Subscription
+
+ None
+ {{sub.name}}
+
+
+
+
+
+
+ Item limit
+
+
+
+
+ Favorited
+
+
+
+
+
+ URL
+
+
+
+
+
+
+
+
diff --git a/src/app/dialogs/generate-rss-url/generate-rss-url.component.scss b/src/app/dialogs/generate-rss-url/generate-rss-url.component.scss
new file mode 100644
index 0000000..f220c1f
--- /dev/null
+++ b/src/app/dialogs/generate-rss-url/generate-rss-url.component.scss
@@ -0,0 +1,3 @@
+.filter-field {
+ width: 80%;
+}
\ No newline at end of file
diff --git a/src/app/dialogs/generate-rss-url/generate-rss-url.component.spec.ts b/src/app/dialogs/generate-rss-url/generate-rss-url.component.spec.ts
new file mode 100644
index 0000000..2fe3807
--- /dev/null
+++ b/src/app/dialogs/generate-rss-url/generate-rss-url.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { GenerateRssUrlComponent } from './generate-rss-url.component';
+
+describe('GenerateRssUrlComponent', () => {
+ let component: GenerateRssUrlComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ GenerateRssUrlComponent ]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(GenerateRssUrlComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/dialogs/generate-rss-url/generate-rss-url.component.ts b/src/app/dialogs/generate-rss-url/generate-rss-url.component.ts
new file mode 100644
index 0000000..e9d2ebf
--- /dev/null
+++ b/src/app/dialogs/generate-rss-url/generate-rss-url.component.ts
@@ -0,0 +1,88 @@
+import { Component } from '@angular/core';
+import { Router, UrlSerializer } from '@angular/router';
+import { Sort } from 'api-types';
+import { PostsService } from 'app/posts.services';
+import { Clipboard } from '@angular/cdk/clipboard';
+
+@Component({
+ selector: 'app-generate-rss-url',
+ templateUrl: './generate-rss-url.component.html',
+ styleUrls: ['./generate-rss-url.component.scss']
+})
+export class GenerateRssUrlComponent {
+ usersList = null;
+ userFilter = '';
+ titleFilter = '';
+ subscriptionFilter = '';
+ fileTypeFilter = 'both';
+ itemLimit = null;
+ favoriteFilter = false;
+ url = '';
+ baseURL = `${this.postsService.config.Host.url}:${this.postsService.config.Host.port}/api/rss`
+ sortProperty = 'registered'
+ descendingMode = true
+ constructor(public postsService: PostsService, private router: Router, private serializer: UrlSerializer, private clipboard: Clipboard) {
+ if (postsService.isLoggedIn) {
+ this.usersList = [this.postsService.user];
+ this.userFilter = postsService.user.uid;
+ this.getUsers();
+ }
+ this.url = this.baseURL;
+ this.rebuildURL();
+ }
+
+ getUsers() {
+ this.postsService.getUsers().subscribe(res => {
+ this.usersList = res['users'];
+ console.log(this.usersList)
+ });
+ }
+
+ sortOptionChanged(sort: Sort) {
+ this.descendingMode = sort['order'] === -1;
+ this.sortProperty = sort['by'];
+ this.rebuildURL();
+ }
+
+ rebuildURL() {
+ // code can be cleaned up
+ const params = {};
+
+ if (this.userFilter) {
+ params['uuid'] = encodeURIComponent(this.userFilter);
+ }
+
+ if (this.titleFilter) {
+ params['text_search'] = encodeURIComponent(this.titleFilter);
+ }
+
+ if (this.subscriptionFilter) {
+ params['sub_id'] = encodeURIComponent(this.subscriptionFilter);
+ }
+
+ if (this.itemLimit) {
+ params['range'] = [0, this.itemLimit];
+ }
+
+ if (this.favoriteFilter) {
+ params['favorite_filter'] = this.favoriteFilter;
+ }
+
+ if (this.fileTypeFilter !== 'both') {
+ params['file_type_filter'] = this.fileTypeFilter;
+ }
+
+ if (this.sortProperty !== 'registered' || !this.descendingMode) {
+ params['sort'] = encodeURIComponent(JSON.stringify({by: this.sortProperty, order: this.descendingMode ? -1 : 1}));
+ }
+
+ const tree = this.router.createUrlTree(['..'], { queryParams: params });
+
+ this.url = `${this.baseURL}${this.serializer.serialize(tree)}`;
+ }
+
+ copyURL() {
+ this.clipboard.copy(this.url);
+ this.postsService.openSnackBar('URL copied!');
+ }
+}
diff --git a/src/app/posts.services.ts b/src/app/posts.services.ts
index 88da6c7..c1730c9 100644
--- a/src/app/posts.services.ts
+++ b/src/app/posts.services.ts
@@ -105,7 +105,8 @@ import {
DeleteNotificationRequest,
SetNotificationsToReadRequest,
GetNotificationsResponse,
- UpdateTaskOptionsRequest
+ UpdateTaskOptionsRequest,
+ User
} from '../api-types';
import { isoLangs } from './settings/locales_list';
import { Title } from '@angular/platform-browser';
@@ -134,7 +135,7 @@ export class PostsService implements CanActivate {
// must be reset after logout
isLoggedIn = false;
token = null;
- user = null;
+ user: User = null;
permissions = null;
available_permissions = null;
@@ -828,7 +829,7 @@ export class PostsService implements CanActivate {
return this.http.post(this.path + 'auth/changePassword', {user_uid: user_uid, new_password: new_password}, this.httpOptions);
}
- getUsers() {
+ getUsers(): Observable {
return this.http.post(this.path + 'getUsers', {}, this.httpOptions);
}
diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html
index a704bc7..8e088ce 100644
--- a/src/app/settings/settings.component.html
+++ b/src/app/settings/settings.component.html
@@ -303,7 +303,8 @@
RSS Feed
Enable RSS Feed
Be careful enabling this with multi-user mode! User data may be exposed.
- See documentation here.
+
+ See documentation here.