mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-30 19:40:05 -07:00
feat: got the features page working
This commit is contained in:
parent
d6b5b85ba2
commit
669ac65d66
9 changed files with 92 additions and 28 deletions
|
@ -17,7 +17,11 @@ export class FeatureService extends ServiceHelpers {
|
|||
return this.http.get<IFeatureEnablement[]>(this.url, {headers: this.headers});
|
||||
}
|
||||
|
||||
public update(feature: IFeatureEnablement): Observable<IFeatureEnablement[]> {
|
||||
return this.http.post<IFeatureEnablement[]>(this.url, JSON.stringify(feature), {headers: this.headers});
|
||||
public enable(feature: IFeatureEnablement): Observable<IFeatureEnablement[]> {
|
||||
return this.http.post<IFeatureEnablement[]>(`${this.url}enable`, JSON.stringify(feature), {headers: this.headers});
|
||||
}
|
||||
|
||||
public disable(feature: IFeatureEnablement): Observable<IFeatureEnablement[]> {
|
||||
return this.http.post<IFeatureEnablement[]>(`${this.url}disable`, JSON.stringify(feature), {headers: this.headers});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,21 +3,18 @@
|
|||
<div class="small-middle-container">
|
||||
<legend>Features</legend>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="mat-table">
|
||||
<div class="mat-row" *ngFor="let feature of features">
|
||||
<div class="mat-cell">{{feature.name}}</div>
|
||||
<div class="mat-cell">
|
||||
<span *ngIf="feature.enabled">
|
||||
<i class="fas fa-check-circle" style="color:green;"></i>
|
||||
</span>
|
||||
<span *ngIf="!feature.enabled">
|
||||
<i class="fas fa-times-circle" style="color:red;"></i>
|
||||
</span>
|
||||
<div class="row" style="margin-top:3em">
|
||||
<div class="col">
|
||||
<div *ngFor="let feature of features">
|
||||
<div class="row">
|
||||
<div class="col-1">
|
||||
<mat-slide-toggle [checked]="feature.enabled" (change)="updateFeature($event, feature)" id="enable"></mat-slide-toggle>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<h3>{{feature.name}}</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,5 @@
|
|||
.small-middle-container {
|
||||
margin: auto;
|
||||
width: 95%;
|
||||
margin-top: 10px;
|
||||
}
|
|
@ -2,10 +2,12 @@
|
|||
|
||||
import { FeaturesFacade } from "../../state/features";
|
||||
import { IFeatureEnablement } from "../../interfaces";
|
||||
import { MatSlideToggleChange } from "@angular/material/slide-toggle";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./features.component.html"
|
||||
templateUrl: "./features.component.html",
|
||||
styleUrls: ["./features.component.scss"]
|
||||
})
|
||||
export class FeaturesComponent implements OnInit {
|
||||
|
||||
|
@ -14,10 +16,17 @@ export class FeaturesComponent implements OnInit {
|
|||
constructor(private readonly featuresFacade: FeaturesFacade) { }
|
||||
|
||||
public async ngOnInit() {
|
||||
this.featuresFacade.features$().subscribe(x => this.features = x);
|
||||
this.featuresFacade.features$().subscribe(x => {
|
||||
this.features = x;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public enableFeature(feature: IFeatureEnablement) {
|
||||
firstValueFrom(this.featuresFacade.update(feature));
|
||||
public updateFeature(change: MatSlideToggleChange, feature: IFeatureEnablement) {
|
||||
if (change.checked) {
|
||||
firstValueFrom(this.featuresFacade.enable(feature));
|
||||
} else {
|
||||
firstValueFrom(this.featuresFacade.disable(feature));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<button mat-button [matMenuTriggerFor]="configurationmenu"><i class="fas fa-wrench" aria-hidden="true"></i> Configuration</button>
|
||||
<mat-menu #configurationmenu="matMenu">
|
||||
<button mat-menu-item [routerLink]="['/Settings/Ombi']"><i class="far fa-grin-stars icon-spacing"></i> General</button>
|
||||
<button mat-menu-item [routerLink]="['/Settings/Features']"><i class="fas fa-rocket icon-spacing"></i> Control Features</button>
|
||||
<button mat-menu-item [routerLink]="['/Settings/Customization']"><i class="fas fa-paint-brush icon-spacing"></i> Customization</button>
|
||||
<button mat-menu-item [routerLink]="['/Settings/LandingPage']"><i class="far fa-file icon-spacing"></i> Landing Page</button>
|
||||
<button mat-menu-item [routerLink]="['/Settings/Issues']"><i class="fas fa-exclamation-triangle icon-spacing"></i> Issues</button>
|
||||
|
|
|
@ -3,8 +3,13 @@ import { IFeatureEnablement } from "../../interfaces";
|
|||
export class LoadFeatures {
|
||||
public static readonly type = '[Features] LoadAll';
|
||||
}
|
||||
export class UpdateFeature {
|
||||
public static readonly type = '[Features] Update';
|
||||
export class EnableFeature {
|
||||
public static readonly type = '[Features] Enable';
|
||||
|
||||
constructor(public feature: IFeatureEnablement) { }
|
||||
}
|
||||
export class DisableFeature {
|
||||
public static readonly type = '[Features] Disable';
|
||||
|
||||
constructor(public feature: IFeatureEnablement) { }
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { LoadFeatures, UpdateFeature } from "./features.actions";
|
||||
import { DisableFeature, EnableFeature, LoadFeatures } from "./features.actions";
|
||||
|
||||
import { FeaturesSelectors } from "./features.selectors";
|
||||
import { IFeatureEnablement } from "../../interfaces";
|
||||
|
@ -15,7 +15,9 @@ export class FeaturesFacade {
|
|||
|
||||
public features$ = (): Observable<IFeatureEnablement[]> => this.store.select(FeaturesSelectors.features);
|
||||
|
||||
public update = (feature: IFeatureEnablement): Observable<unknown> => this.store.dispatch(new UpdateFeature(feature));
|
||||
public enable = (feature: IFeatureEnablement): Observable<unknown> => this.store.dispatch(new EnableFeature(feature));
|
||||
|
||||
public disable = (feature: IFeatureEnablement): Observable<unknown> => this.store.dispatch(new DisableFeature(feature));
|
||||
|
||||
public loadFeatures = (): Observable<unknown> => this.store.dispatch(new LoadFeatures());
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Action, State, StateContext } from "@ngxs/store";
|
||||
import { LoadFeatures, UpdateFeature } from "./features.actions";
|
||||
import { DisableFeature, EnableFeature, LoadFeatures } from "./features.actions";
|
||||
|
||||
import { FEATURES_STATE_TOKEN } from "./types";
|
||||
import { FeatureService } from "../../services/feature.service";
|
||||
|
@ -24,9 +24,16 @@ export class FeatureState {
|
|||
);
|
||||
}
|
||||
|
||||
@Action(UpdateFeature)
|
||||
public update({ setState }: StateContext<IFeatureEnablement[]>, { feature }: UpdateFeature): Observable<IFeatureEnablement[]> {
|
||||
return this.featuresService.update(feature).pipe(
|
||||
@Action(EnableFeature)
|
||||
public enable({ setState }: StateContext<IFeatureEnablement[]>, { feature }: EnableFeature): Observable<IFeatureEnablement[]> {
|
||||
return this.featuresService.enable(feature).pipe(
|
||||
tap((result) => setState(result))
|
||||
);
|
||||
}
|
||||
|
||||
@Action(DisableFeature)
|
||||
public disable({ setState }: StateContext<IFeatureEnablement[]>, { feature }: DisableFeature): Observable<IFeatureEnablement[]> {
|
||||
return this.featuresService.disable(feature).pipe(
|
||||
tap((result) => setState(result))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Ombi.Attributes;
|
||||
using Ombi.Core.Settings;
|
||||
using Ombi.Settings.Settings.Models;
|
||||
using System.Collections;
|
||||
|
@ -24,6 +25,39 @@ namespace Ombi.Controllers.V2
|
|||
return PopulateFeatures(features?.Features ?? new List<FeatureEnablement>());
|
||||
}
|
||||
|
||||
[HttpPost("enable")]
|
||||
[Admin]
|
||||
public async Task<List<FeatureEnablement>> Enable([FromBody] FeatureEnablement feature)
|
||||
{
|
||||
var featureSettings = await _features.GetSettingsAsync();
|
||||
var features = PopulateFeatures(featureSettings?.Features ?? new List<FeatureEnablement>());
|
||||
var featureToUpdate = features.First(x => x.Name.Equals(feature.Name));
|
||||
featureToUpdate.Enabled = true;
|
||||
|
||||
featureSettings.Features = features;
|
||||
|
||||
await _features.SaveSettingsAsync(featureSettings);
|
||||
|
||||
return PopulateFeatures(featureSettings?.Features ?? new List<FeatureEnablement>());
|
||||
}
|
||||
|
||||
[HttpPost("disable")]
|
||||
[Admin]
|
||||
public async Task<List<FeatureEnablement>> Disable([FromBody] FeatureEnablement feature)
|
||||
{
|
||||
var featureSettings = await _features.GetSettingsAsync();
|
||||
var features = PopulateFeatures(featureSettings?.Features ?? new List<FeatureEnablement>());
|
||||
var featureToUpdate = features.First(x => x.Name.Equals(feature.Name));
|
||||
featureToUpdate.Enabled = false;
|
||||
|
||||
featureSettings.Features = features;
|
||||
|
||||
await _features.SaveSettingsAsync(featureSettings);
|
||||
|
||||
return PopulateFeatures(featureSettings?.Features ?? new List<FeatureEnablement>());
|
||||
}
|
||||
|
||||
|
||||
private List<FeatureEnablement> PopulateFeatures(List<FeatureEnablement> existingFeatures)
|
||||
{
|
||||
var supported = GetSupportedFeatures().ToList();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue