diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts new file mode 100644 index 0000000..793ca88 --- /dev/null +++ b/src/app/admin/admin-routing.module.ts @@ -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 { } diff --git a/src/app/admin/admin.module.ts b/src/app/admin/admin.module.ts new file mode 100644 index 0000000..47ea991 --- /dev/null +++ b/src/app/admin/admin.module.ts @@ -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 +{ } diff --git a/src/app/admin/models/configuration-section.ts b/src/app/admin/models/configuration-section.ts new file mode 100644 index 0000000..baf9ea8 --- /dev/null +++ b/src/app/admin/models/configuration-section.ts @@ -0,0 +1,7 @@ +import { Option } from "./option"; + +export interface ConfigurationSection +{ + name: string; + options: Option[] +} diff --git a/src/app/admin/models/option.ts b/src/app/admin/models/option.ts new file mode 100644 index 0000000..f5ba219 --- /dev/null +++ b/src/app/admin/models/option.ts @@ -0,0 +1,8 @@ +export interface Option +{ + slug: string; + name: string; + description: string; + helpMessage: string; + type: number; +} diff --git a/src/app/admin/option/option.component.html b/src/app/admin/option/option.component.html new file mode 100644 index 0000000..f0ce924 --- /dev/null +++ b/src/app/admin/option/option.component.html @@ -0,0 +1,7 @@ +
+ + {{option.name}} + + {{option.description}} + +
diff --git a/src/app/admin/option/option.component.scss b/src/app/admin/option/option.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/admin/option/option.component.ts b/src/app/admin/option/option.component.ts new file mode 100644 index 0000000..acf48dd --- /dev/null +++ b/src/app/admin/option/option.component.ts @@ -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; + + 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); + } +} diff --git a/src/app/admin/panel/panel.component.html b/src/app/admin/panel/panel.component.html new file mode 100644 index 0000000..e27cd03 --- /dev/null +++ b/src/app/admin/panel/panel.component.html @@ -0,0 +1,18 @@ + + +

{{item.name}}

+
+ + + + + {{getChanges()}} changes + +
+ +
+
+ +
diff --git a/src/app/admin/panel/panel.component.scss b/src/app/admin/panel/panel.component.scss new file mode 100644 index 0000000..8a254ca --- /dev/null +++ b/src/app/admin/panel/panel.component.scss @@ -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; +} diff --git a/src/app/admin/panel/panel.component.ts b/src/app/admin/panel/panel.component.ts new file mode 100644 index 0000000..8f232c9 --- /dev/null +++ b/src/app/admin/panel/panel.component.ts @@ -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; + } +} diff --git a/src/app/admin/section/section.component.html b/src/app/admin/section/section.component.html new file mode 100644 index 0000000..007a125 --- /dev/null +++ b/src/app/admin/section/section.component.html @@ -0,0 +1,4 @@ +

{{section.name}}

+ + +
diff --git a/src/app/admin/section/section.component.scss b/src/app/admin/section/section.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/admin/section/section.component.ts b/src/app/admin/section/section.component.ts new file mode 100644 index 0000000..adab3a5 --- /dev/null +++ b/src/app/admin/section/section.component.ts @@ -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; +} diff --git a/src/app/app.component.html b/src/app/app.component.html index 4a226de..d7348a3 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -18,6 +18,10 @@ + +