Starting the admin panel

This commit is contained in:
Zoe Roux
2021-05-23 23:05:31 +02:00
parent 22a0267191
commit 961220ebb3
16 changed files with 223 additions and 1 deletions
+19
View File
@@ -0,0 +1,19 @@
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { PanelComponent } from "./panel/panel.component";
import { ItemResolver } from "../services/item-resolver.service";
const routes: Routes = [
{path: "admin", component: PanelComponent,
resolve: {
items: ItemResolver.forResource("config/panel"),
config: ItemResolver.forResource("config")
}
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AdminRoutingModule { }
+30
View File
@@ -0,0 +1,30 @@
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { PanelComponent } from './panel/panel.component';
import { RouterModule } from "@angular/router";
import { MatSidenavModule } from "@angular/material/sidenav";
import { MatButtonModule } from "@angular/material/button";
import { OptionComponent } from './option/option.component';
import { SectionComponent } from './section/section.component';
import { MatFormFieldModule } from "@angular/material/form-field";
import { MatInputModule } from "@angular/material/input";
import { MatIconModule } from "@angular/material/icon";
import { MatToolbarModule } from "@angular/material/toolbar";
import { MatTooltipModule } from "@angular/material/tooltip";
@NgModule({
declarations: [PanelComponent, OptionComponent, SectionComponent],
imports: [
CommonModule,
MatSidenavModule,
RouterModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
MatIconModule,
MatToolbarModule,
MatTooltipModule
]
})
export class AdminModule
{ }
@@ -0,0 +1,7 @@
import { Option } from "./option";
export interface ConfigurationSection
{
name: string;
options: Option[]
}
+8
View File
@@ -0,0 +1,8 @@
export interface Option
{
slug: string;
name: string;
description: string;
helpMessage: string;
type: number;
}
@@ -0,0 +1,7 @@
<form>
<mat-form-field class="w-100 mb-2">
<mat-label>{{option.name}}</mat-label>
<input #input matInput value="{{value}}">
<mat-hint align="start">{{option.description}}</mat-hint>
</mat-form-field>
</form>
+44
View File
@@ -0,0 +1,44 @@
import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from "@angular/core";
import { Option } from "../models/option";
import { HttpClient } from "@angular/common/http";
@Component({
selector: "app-option",
templateUrl: "./option.component.html",
styleUrls: ["./option.component.scss"]
})
export class OptionComponent implements OnInit, OnDestroy
{
value: string;
@Input() option: Option;
@Input() config;
@ViewChild("input") input: ElementRef<HTMLInputElement>;
constructor(private http: HttpClient)
{}
ngOnInit(): void
{
this.value = this.getConfig(this.option.slug);
}
getConfig(slug: string): string
{
const sections = slug.split(':');
let conf = this.config;
for (const child of sections)
{
if (conf == null)
throw new Error(`Invalid configuration. No resource at ${slug}`);
conf = conf[child];
}
return conf;
}
async ngOnDestroy()
{
if (this.value == this.input.nativeElement.value)
return;
await this.http.put(`/api/config/${this.option.slug}`, this.input.nativeElement.value);
}
}
+18
View File
@@ -0,0 +1,18 @@
<mat-sidenav-container class="admin-panel" autosize>
<mat-sidenav opened class="sidenav-container" mode="side" fixedInViewport fixedTopGap="64">
<p *ngFor="let item of this.items">{{item.name}}</p>
</mat-sidenav>
<mat-sidenav-content class="content">
<mat-toolbar class="toolbar">
<button mat-icon-button aria-label="Save changes" matTooltip="Save changes">
<mat-icon>save</mat-icon>
</button>
<span>{{getChanges()}} changes</span>
</mat-toolbar>
<div>
<app-section *ngFor="let item of this.items" [section]="item" [config]="config"></app-section>
</div>
</mat-sidenav-content>
</mat-sidenav-container>
+36
View File
@@ -0,0 +1,36 @@
@import "variables";
.admin-panel
{
width: 100%;
height: 100%;
}
.sidenav-container
{
display: flex;
height: 100%;
align-items: center;
justify-content: center;
padding: 20px;
}
.content
{
height: 100%;
padding: 20px;
> div
{
margin-top: $nav-bar-height;
}
}
.toolbar
{
position: fixed;
top: $nav-bar-height;
margin-left: -20px;
margin-right: -20px;
}
+28
View File
@@ -0,0 +1,28 @@
import { Component } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { ConfigurationSection } from "../models/configuration-section";
@Component({
selector: "app-panel",
templateUrl: "./panel.component.html",
styleUrls: ["./panel.component.scss"]
})
export class PanelComponent
{
items: ConfigurationSection[];
config: any;
constructor(private route: ActivatedRoute)
{
this.route.data.subscribe(x =>
{
this.items = x.items;
this.config = x.config;
});
}
getChanges(): number
{
return 0;
}
}
@@ -0,0 +1,4 @@
<h3>{{section.name}}</h3>
<app-option *ngFor="let option of section.options" [option]="option" [config]="config"></app-option>
<br/>
@@ -0,0 +1,13 @@
import { Component, Input } from "@angular/core";
import { ConfigurationSection } from "../models/configuration-section";
@Component({
selector: "app-section",
templateUrl: "./section.component.html",
styleUrls: ["./section.component.scss"]
})
export class SectionComponent
{
@Input() section: ConfigurationSection;
@Input() config: any;
}
+4
View File
@@ -18,6 +18,10 @@
<input placeholder="Search" id="search" type="search" (input)="onUpdateValue($any($event))"/>
</li>
<li class="nav-item icon" routerLink="admin" routerLinkActive="active">
<mat-icon matTooltipPosition="below" matTooltip="Configure Kyoo" >settings</mat-icon>
</li>
<li class="nav-item" *ngIf="!this.isAuthenticated else accountDrop">
<a class="icon" (click)="this.authManager.login()" matTooltipPosition="below" matTooltip="Login">
<mat-icon>account_circle</mat-icon>
+1 -1
View File
@@ -111,7 +111,7 @@ input::-webkit-search-cancel-button
opacity: 0.7;
outline: none;
&:host-context(.hoverEnabled) &:hover, &:focus
&:host-context(.hoverEnabled) &:hover, &:focus, &.active
{
cursor: pointer;
opacity: 1;
+4
View File
@@ -48,6 +48,8 @@ import { ShowGridComponent } from "./components/show-grid/show-grid.component";
import { MatBadgeModule } from "@angular/material/badge";
import { StartupService } from "./services/startup.service";
import { LongPressDirective } from "./misc/long-press.directive";
import { AdminRoutingModule } from "./admin/admin-routing.module";
import { AdminModule } from "./admin/admin.module";
@NgModule({
@@ -77,6 +79,7 @@ import { LongPressDirective } from "./misc/long-press.directive";
BrowserModule,
HttpClientModule,
AuthRoutingModule,
AdminRoutingModule,
AppRoutingModule,
BrowserAnimationsModule,
MatSnackBarModule,
@@ -97,6 +100,7 @@ import { LongPressDirective } from "./misc/long-press.directive";
MatTabsModule,
MatCheckboxModule,
AuthModule,
AdminModule,
MatChipsModule,
MatAutocompleteModule,
MatExpansionModule,