Added ability to generate RSS feed URLs from the UI
Moved property sorting into its own componentpull/809/head
parent
2a3017972a
commit
121f5586a6
@ -0,0 +1,14 @@
|
||||
<div>
|
||||
<div style="display: inline-block;">
|
||||
<mat-form-field appearance="outline" style="width: 165px;">
|
||||
<mat-select [(ngModel)]="this.sortProperty" (selectionChange)="emitSortOptionChanged()">
|
||||
<mat-option *ngFor="let sortOption of sortProperties | keyvalue" [value]="sortOption.key">
|
||||
{{sortOption['value']['label']}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="sort-dir-div">
|
||||
<button (click)="toggleModeChange()" mat-icon-button><mat-icon>{{descendingMode ? 'arrow_downward' : 'arrow_upward'}}</mat-icon></button>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,5 @@
|
||||
.sort-dir-div {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
}
|
@ -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<SortPropertyComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ SortPropertyComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(SortPropertyComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -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<unknown>();
|
||||
@Output() descendingModeChange = new EventEmitter<number>();
|
||||
@Output() sortOptionChanged = new EventEmitter<Sort>();
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
<h4 mat-dialog-title><ng-container i18n="Generate RSS URL">Generate RSS URL</ng-container></h4>
|
||||
|
||||
<mat-dialog-content>
|
||||
<div class="container-fluid">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-md-6 mt-2">
|
||||
<mat-form-field class="filter-field">
|
||||
<mat-label i18n="Title filter">Title filter</mat-label>
|
||||
<input [(ngModel)]="titleFilter" matInput (input)="rebuildURL()">
|
||||
<mat-hint i18n="Supports regex">Supports regex</mat-hint>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 mt-2">
|
||||
<mat-form-field class="filter-field">
|
||||
<mat-label><ng-container i18n="File type">File type</ng-container></mat-label>
|
||||
<mat-select color="accent" [(ngModel)]="fileTypeFilter" (selectionChange)="rebuildURL()">
|
||||
<mat-option value="both"><ng-container i18n="Both">Both</ng-container></mat-option>
|
||||
<mat-option value="video_only"><ng-container i18n="Video only">Video only</ng-container></mat-option>
|
||||
<mat-option value="audio_only"><ng-container i18n="Audio only">Audio only</ng-container></mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 mt-2">
|
||||
<mat-form-field class="filter-field">
|
||||
<mat-label><ng-container i18n="User">User</ng-container></mat-label>
|
||||
<mat-select color="accent" [(ngModel)]="userFilter" (selectionChange)="rebuildURL()" [disabled]="!usersList">
|
||||
<mat-option [value]="''"><ng-container i18n="None">None</ng-container></mat-option>
|
||||
<mat-option *ngFor="let user of usersList" [value]="user.uid"><ng-container>{{user.name}}</ng-container></mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 mt-2">
|
||||
<mat-form-field class="filter-field">
|
||||
<mat-label><ng-container i18n="Subscription">Subscription</ng-container></mat-label>
|
||||
<mat-select color="accent" [(ngModel)]="subscriptionFilter" (selectionChange)="rebuildURL()">
|
||||
<mat-option [value]="''"><ng-container i18n="None">None</ng-container></mat-option>
|
||||
<mat-option *ngFor="let sub of postsService.subscriptions" [value]="sub.id"><ng-container>{{sub.name}}</ng-container></mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 mt-2">
|
||||
<app-sort-property (sortOptionChanged)="sortOptionChanged($event)"></app-sort-property>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 mt-2">
|
||||
<mat-form-field class="filter-field">
|
||||
<mat-label i18n="Item limit">Item limit</mat-label>
|
||||
<input type="number" [(ngModel)]="itemLimit" (input)="rebuildURL()" matInput>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-12 mb-4">
|
||||
<mat-checkbox (change)="rebuildURL()" [(ngModel)]="favoriteFilter"><ng-container i18n="Favorited">Favorited</ng-container></mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-form-field style="width: 100%;">
|
||||
<mat-label i18n="URL">URL</mat-label>
|
||||
<input readonly [(ngModel)]="url" matInput>
|
||||
<button mat-icon-button matSuffix (click)="copyURL()">
|
||||
<mat-icon>content_copy</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
</mat-dialog-content>
|
||||
|
||||
<mat-dialog-actions>
|
||||
<button mat-button mat-dialog-close><ng-container i18n="Close">Close</ng-container></button>
|
||||
</mat-dialog-actions>
|
@ -0,0 +1,3 @@
|
||||
.filter-field {
|
||||
width: 80%;
|
||||
}
|
@ -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<GenerateRssUrlComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ GenerateRssUrlComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(GenerateRssUrlComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -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!');
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue