More work on UI

This commit is contained in:
simon987
2019-01-23 19:38:33 -05:00
parent cbd32daf02
commit 1d656099f5
31 changed files with 288 additions and 131 deletions

10
web/angular/src/app/api.service.ts Normal file → Executable file
View File

@@ -12,10 +12,18 @@ export class ApiService {
}
getLogs() {
return this.http.get(this.url + "/logs");
return this.http.post(this.url + "/logs", "{\"level\":\"info\", \"since\":10000}");
}
getProjectStats(id: number) {
return this.http.get(this.url + "/project/stats/" + id)
}
getProjects() {
return this.http.get(this.url + "/project/stats")
}
getProject(id: number) {
return this.http.get(this.url + "/project/get/" + id)
}
}

8
web/angular/src/app/app-routing.module.ts Normal file → Executable file
View File

@@ -2,10 +2,16 @@ import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {LogsComponent} from "./logs/logs.component";
import {ProjectDashboardComponent} from "./project-dashboard/project-dashboard.component";
import {ProjectListComponent} from "./project-list/project-list.component";
import {CreateProjectComponent} from "./create-project/create-project.component";
import {UpdateProjectComponent} from "./update-project/update-project.component";
const routes: Routes = [
{path: "log", component: LogsComponent},
{path: "project", component: ProjectDashboardComponent}
{path: "projects", component: ProjectListComponent},
{path: "project/:id", component: ProjectDashboardComponent},
{path: "project/:id/update", component: UpdateProjectComponent},
{path: "new_project", component: CreateProjectComponent}
];
@NgModule({

0
web/angular/src/app/app.component.css Normal file → Executable file
View File

14
web/angular/src/app/app.component.html Normal file → Executable file
View File

@@ -1,8 +1,12 @@
<mat-toolbar>
<a [routerLink]="''">Index</a>
<a [routerLink]="'log'">Logs</a>
<a [routerLink]="'project'">Project</a>
</mat-toolbar>
<!--<mat-toolbar>-->
<ul>
<li><a [routerLink]="''">Index</a></li>
<li><a [routerLink]="'log'">Logs</a></li>
<li><a [routerLink]="'project'">Project</a></li>
<li><a [routerLink]="'projects'">list</a></li>
<li><a [routerLink]="'new_project'">new project</a></li>
</ul>
<!--</mat-toolbar>-->
<router-outlet></router-outlet>

15
web/angular/src/app/app.module.ts Normal file → Executable file
View File

@@ -7,6 +7,8 @@ import {LogsComponent} from './logs/logs.component';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {
MatAutocompleteModule,
MatButtonModule,
MatCardModule,
MatExpansionModule,
MatFormFieldModule,
@@ -22,12 +24,19 @@ import {
import {ApiService} from "./api.service";
import {HttpClientModule} from "@angular/common/http";
import {ProjectDashboardComponent} from './project-dashboard/project-dashboard.component';
import {ProjectListComponent} from './project-list/project-list.component';
import {CreateProjectComponent} from './create-project/create-project.component';
import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {UpdateProjectComponent} from './update-project/update-project.component';
@NgModule({
declarations: [
AppComponent,
LogsComponent,
ProjectDashboardComponent
ProjectDashboardComponent,
ProjectListComponent,
CreateProjectComponent,
UpdateProjectComponent
],
imports: [
BrowserModule,
@@ -41,6 +50,10 @@ import {ProjectDashboardComponent} from './project-dashboard/project-dashboard.c
MatInputModule,
MatToolbarModule,
MatCardModule,
MatButtonModule,
MatAutocompleteModule,
ReactiveFormsModule,
FormsModule,
MatExpansionModule,
MatTreeModule,
BrowserAnimationsModule,

View File

@@ -0,0 +1,4 @@
.mat-form-field {
width: 100%;
}

View File

@@ -0,0 +1,30 @@
<mat-card>
<mat-card-title>Create new project</mat-card-title>
<mat-card-subtitle></mat-card-subtitle>
<mat-card-content>
<form>
<mat-form-field>
<input type="text" matInput [(ngModel)]="project.name" name="name" placeholder="Name">
</mat-form-field>
<mat-form-field>
<input type="text" matInput [(ngModel)]="project.clone_url" name="clone_url"
placeholder="Git clone url">
</mat-form-field>
<mat-form-field>
<input type="text" matInput [(ngModel)]="project.git_repo" name="clone_url"
placeholder='Full repository name (e.g. "simon987/task_tracker")'>
<mat-hint align="start">Changes on the <strong>master</strong> branch will be tracked if webhooks are
enabled
</mat-hint>
</mat-form-field>
<input type="hidden" name="version" value="{{project.version}}">
</form>
</mat-card-content>
<mat-card-actions>
<button>Create</button>
</mat-card-actions>
</mat-card>

View File

@@ -0,0 +1,20 @@
import {Component, OnInit} from '@angular/core';
import {Project} from "../models/project";
@Component({
selector: 'app-create-project',
templateUrl: './create-project.component.html',
styleUrls: ['./create-project.component.css']
})
export class CreateProjectComponent implements OnInit {
private project = new Project();
constructor() {
this.project.name = "test"
}
ngOnInit() {
}
}

View File

@@ -1,25 +0,0 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {LogsComponent} from './logs.component';
describe('LogsComponent', () => {
let component: LogsComponent;
let fixture: ComponentFixture<LogsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [LogsComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LogsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -40,7 +40,7 @@ export class LogsComponent implements OnInit {
private getLogs() {
this.apiService.getLogs().subscribe(
data => {
this.data.data = _.map(data, (entry) => {
this.data.data = _.map(data["logs"], (entry) => {
return <LogEntry>{
message: entry.message,
timestamp: moment.unix(entry.timestamp).toISOString(),

View File

@@ -0,0 +1,9 @@
export class Project {
public priority: number;
public motd: string;
public name: string;
public clone_url: string;
public git_repo: string;
public version: string;
}

View File

@@ -4,6 +4,7 @@ import * as d3 from "d3"
import * as _ from "lodash"
import {interval} from "rxjs";
import {ApiService} from "../api.service";
import {ActivatedRoute} from "@angular/router";
@Component({
selector: 'app-project-dashboard',
@@ -12,7 +13,9 @@ import {ApiService} from "../api.service";
})
export class ProjectDashboardComponent implements OnInit {
private projectId;
projectStats;
private pieWidth = 360;
private pieHeight = 360;
private pieRadius = Math.min(this.pieWidth, this.pieHeight) / 2;
@@ -47,7 +50,7 @@ export class ProjectDashboardComponent implements OnInit {
private assigneesPath: any;
private assigneesSvg: any;
constructor(private apiService: ApiService) {
constructor(private apiService: ApiService, private route: ActivatedRoute) {
}
setupStatusPieChart() {
@@ -165,7 +168,7 @@ export class ProjectDashboardComponent implements OnInit {
}
getStats() {
this.apiService.getProjectStats(2).subscribe((data) => {
this.apiService.getProjectStats(this.projectId).subscribe((data) => {
this.projectStats = data["stats"];
@@ -259,9 +262,13 @@ export class ProjectDashboardComponent implements OnInit {
this.setupAssigneesPieChart();
this.setupLine();
this.getStats();
interval(1000).subscribe(() => {
this.getStats()
})
this.route.params.subscribe(params => {
this.projectId = params["id"];
this.getStats();
interval(1000).subscribe(() => {
// this.getStats()
})
}
)
}
}

View File

@@ -0,0 +1,19 @@
<mat-card>
<mat-card-header>
<mat-card-title>Projects</mat-card-title>
</mat-card-header>
<mat-card-content>
<mat-accordion>
<mat-expansion-panel *ngFor="let stats of projects">
<mat-expansion-panel-header>
<mat-panel-title>{{stats.project.id}}: {{stats.project.name}}</mat-panel-title>
<mat-panel-description>{{stats.project.motd}}</mat-panel-description>
</mat-expansion-panel-header>
<pre>{{stats.project | json}}</pre>
<div style="display: flex;">
<a [routerLink]="'/project/' + stats.project.id">Dashboard</a>
</div>
</mat-expansion-panel>
</mat-accordion>
</mat-card-content>
</mat-card>

View File

@@ -0,0 +1,24 @@
import {Component, OnInit} from '@angular/core';
import {ApiService} from "../api.service";
@Component({
selector: 'app-project-list',
templateUrl: './project-list.component.html',
styleUrls: ['./project-list.component.css']
})
export class ProjectListComponent implements OnInit {
constructor(private apiService: ApiService) {
}
projects: any[];
ngOnInit() {
this.getProjects()
}
getProjects() {
this.apiService.getProjects().subscribe(data => this.projects = data["stats"]);
}
}

View File

@@ -1,10 +0,0 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"sourceMap": true
},
"exclude": [
"node_modules"
]
}

View File

@@ -0,0 +1,4 @@
.mat-form-field {
width: 100%;
}

View File

@@ -0,0 +1,29 @@
<mat-card>
<mat-card-title>Update project</mat-card-title>
<mat-card-subtitle>Changes are saved in real time</mat-card-subtitle>
<mat-card-content>
<form>
<mat-form-field>
<input type="text" matInput [(ngModel)]="project.name" name="name" placeholder="Name">
</mat-form-field>
<mat-form-field>
<textarea matInput placeholder="Message of the day"></textarea>
</mat-form-field>
<mat-form-field>
<input type="text" matInput [(ngModel)]="project.clone_url" name="clone_url"
placeholder="Git clone url">
</mat-form-field>
<mat-form-field>
<input type="text" matInput [(ngModel)]="project.git_repo" name="clone_url"
placeholder='Full repository name (e.g. "simon987/task_tracker")'>
<mat-hint align="start">Changes on the <strong>master</strong> branch will be tracked if webhooks are
enabled
</mat-hint>
</mat-form-field>
<input type="hidden" name="version" value="{{project.version}}">
</form>
</mat-card-content>
</mat-card>

View File

@@ -0,0 +1,40 @@
import {Component, OnInit} from '@angular/core';
import {Project} from "../models/project";
import {ApiService} from "../api.service";
import {ActivatedRoute} from "@angular/router";
@Component({
selector: 'app-update-project',
templateUrl: './update-project.component.html',
styleUrls: ['./update-project.component.css']
})
export class UpdateProjectComponent implements OnInit {
constructor(private apiService: ApiService, private route: ActivatedRoute) {
}
private project: Project;
private projectId: number;
ngOnInit() {
this.route.params.subscribe(params => {
this.projectId = params["id"];
this.getProject();
})
}
private getProject() {
this.apiService.getProject(this.projectId).subscribe(data => {
this.project = <Project>{
name: data["project"]["name"],
clone_url: data["project"]["clone_url"],
git_repo: data["project"]["git_repo"],
motd: data["project"]["motd"],
priority: data["project"]["priority"],
version: data["project"]["version"]
}
})
}
}