mirror of
https://github.com/simon987/task_tracker.git
synced 2025-04-18 01:46:45 +00:00
More work on UI
This commit is contained in:
parent
cbd32daf02
commit
1d656099f5
@ -53,6 +53,7 @@ func New() *WebAPI {
|
||||
api.router.POST("/project/create", LogRequestMiddleware(api.ProjectCreate))
|
||||
api.router.GET("/project/get/:id", LogRequestMiddleware(api.ProjectGet))
|
||||
api.router.GET("/project/stats/:id", LogRequestMiddleware(api.ProjectGetStats))
|
||||
api.router.GET("/project/stats", LogRequestMiddleware(api.ProjectGetAllStats))
|
||||
|
||||
api.router.POST("/task/create", LogRequestMiddleware(api.TaskCreate))
|
||||
api.router.GET("/task/get/:project", LogRequestMiddleware(api.TaskGetFromProject))
|
||||
|
@ -33,6 +33,12 @@ type GetProjectStatsResponse struct {
|
||||
Stats *storage.ProjectStats `json:"stats,omitempty"`
|
||||
}
|
||||
|
||||
type GetAllProjectsStatsResponse struct {
|
||||
Ok bool `json:"ok"`
|
||||
Message string `json:"message,omitempty"`
|
||||
Stats *[]storage.ProjectStats `json:"stats,omitempty"`
|
||||
}
|
||||
|
||||
func (api *WebAPI) ProjectCreate(r *Request) {
|
||||
|
||||
createReq := &CreateProjectRequest{}
|
||||
@ -125,3 +131,13 @@ func (api *WebAPI) ProjectGetStats(r *Request) {
|
||||
}, 404)
|
||||
}
|
||||
}
|
||||
|
||||
func (api *WebAPI) ProjectGetAllStats(r *Request) {
|
||||
|
||||
stats := api.Database.GetAllProjectsStats()
|
||||
|
||||
r.OkJson(GetAllProjectsStatsResponse{
|
||||
Ok: true,
|
||||
Stats: stats,
|
||||
})
|
||||
}
|
||||
|
17
setup.sh
17
setup.sh
@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
export INSTALL_DIR="/home/drone/task_tracker"
|
||||
|
||||
mkdir ${INSTALL_DIR} 2> /dev/null
|
||||
|
||||
# Gogs
|
||||
if [[ ! -d "${INSTALL_DIR}/gogs" ]]; then
|
||||
wget "https://dl.gogs.io/0.11.79/gogs_0.11.79_linux_amd64.tar.gz"
|
||||
tar -xzf "gogs_0.11.79_linux_amd64.tar.gz" -C ${INSTALL_DIR}
|
||||
rm "gogs_0.11.79_linux_amd64.tar.gz"
|
||||
fi
|
||||
|
||||
# Postgres
|
||||
su - postgres -c "createuser task_tracker"
|
||||
su - postgres -c "dropdb gogs"
|
||||
su - postgres -c "createdb gogs"
|
@ -1,7 +1,6 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"src/task_tracker/config"
|
||||
@ -44,12 +43,6 @@ func (database *Database) SetupLoggerHook() {
|
||||
func (database *Database) GetLogs(since int64, level logrus.Level) *[]LogEntry {
|
||||
|
||||
db := database.getDB()
|
||||
logs := getLogs(since, level, db)
|
||||
|
||||
return logs
|
||||
}
|
||||
|
||||
func getLogs(since int64, level logrus.Level, db *sql.DB) *[]LogEntry {
|
||||
|
||||
var logs []LogEntry
|
||||
|
||||
|
@ -102,12 +102,6 @@ func scanProject(row *sql.Row) (*Project, error) {
|
||||
func (database *Database) GetProjectWithRepoName(repoName string) *Project {
|
||||
|
||||
db := database.getDB()
|
||||
project := getProjectWithRepoName(repoName, db)
|
||||
return project
|
||||
}
|
||||
|
||||
func getProjectWithRepoName(repoName string, db *sql.DB) *Project {
|
||||
|
||||
row := db.QueryRow(`SELECT * FROM project WHERE LOWER(git_repo)=$1`, strings.ToLower(repoName))
|
||||
|
||||
project, err := scanProject(row)
|
||||
@ -124,10 +118,6 @@ func getProjectWithRepoName(repoName string, db *sql.DB) *Project {
|
||||
func (database *Database) UpdateProject(project *Project) {
|
||||
|
||||
db := database.getDB()
|
||||
updateProject(project, db)
|
||||
}
|
||||
|
||||
func updateProject(project *Project, db *sql.DB) {
|
||||
|
||||
res, err := db.Exec(`UPDATE project
|
||||
SET (priority, name, clone_url, git_repo, version, motd) = ($1,$2,$3,$4,$5,$6) WHERE id=$7`,
|
||||
@ -147,13 +137,6 @@ func updateProject(project *Project, db *sql.DB) {
|
||||
func (database *Database) GetProjectStats(id int64) *ProjectStats {
|
||||
|
||||
db := database.getDB()
|
||||
stats := getProjectStats(id, db)
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
func getProjectStats(id int64, db *sql.DB) *ProjectStats {
|
||||
|
||||
stats := ProjectStats{}
|
||||
|
||||
stats.Project = getProject(id, db)
|
||||
@ -169,7 +152,7 @@ func getProjectStats(id int64, db *sql.DB) *ProjectStats {
|
||||
if err != nil {
|
||||
logrus.WithError(err).WithFields(logrus.Fields{
|
||||
"id": id,
|
||||
}).Warn("???") //todo
|
||||
}).Trace("Get project stats: No task for this project")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -187,3 +170,36 @@ func getProjectStats(id int64, db *sql.DB) *ProjectStats {
|
||||
|
||||
return &stats
|
||||
}
|
||||
|
||||
func (database Database) GetAllProjectsStats() *[]ProjectStats {
|
||||
var statsList []ProjectStats
|
||||
|
||||
db := database.getDB()
|
||||
rows, err := db.Query(`SELECT
|
||||
SUM(CASE WHEN status='new' THEN 1 ELSE 0 END) newCount,
|
||||
SUM(CASE WHEN status='failed' THEN 1 ELSE 0 END) failedCount,
|
||||
SUM(CASE WHEN status='closed' THEN 1 ELSE 0 END) closedCount,
|
||||
p.*
|
||||
FROM task INNER JOIN project p on task.project = p.id
|
||||
GROUP BY p.id`)
|
||||
handleErr(err)
|
||||
|
||||
for rows.Next() {
|
||||
|
||||
stats := ProjectStats{}
|
||||
p := &Project{}
|
||||
err := rows.Scan(&stats.NewTaskCount, &stats.FailedTaskCount, &stats.ClosedTaskCount,
|
||||
&p.Id, &p.Priority, &p.Motd, &p.Name, &p.CloneUrl, &p.GitRepo, &p.Version)
|
||||
handleErr(err)
|
||||
|
||||
stats.Project = p
|
||||
|
||||
statsList = append(statsList, stats)
|
||||
}
|
||||
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"statsList": statsList,
|
||||
}).Trace("Get all projects stats")
|
||||
|
||||
return &statsList
|
||||
}
|
||||
|
@ -20,12 +20,6 @@ type Task struct {
|
||||
func (database *Database) SaveTask(task *Task, project int64) error {
|
||||
|
||||
db := database.getDB()
|
||||
taskErr := saveTask(task, project, db)
|
||||
|
||||
return taskErr
|
||||
}
|
||||
|
||||
func saveTask(task *Task, project int64, db *sql.DB) error {
|
||||
|
||||
res, err := db.Exec(`
|
||||
INSERT INTO task (project, max_retries, recipe, priority)
|
||||
@ -52,12 +46,6 @@ func saveTask(task *Task, project int64, db *sql.DB) error {
|
||||
func (database *Database) GetTask(worker *Worker) *Task {
|
||||
|
||||
db := database.getDB()
|
||||
task := getTask(worker, db)
|
||||
|
||||
return task
|
||||
}
|
||||
|
||||
func getTask(worker *Worker, db *sql.DB) *Task {
|
||||
|
||||
row := db.QueryRow(`
|
||||
UPDATE task
|
||||
@ -111,12 +99,6 @@ func getTaskById(id int64, db *sql.DB) *Task {
|
||||
func (database Database) ReleaseTask(id int64, workerId *uuid.UUID, success bool) bool {
|
||||
|
||||
db := database.getDB()
|
||||
res := releaseTask(workerId, id, success, db)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func releaseTask(workerId *uuid.UUID, id int64, success bool, db *sql.DB) bool {
|
||||
|
||||
var res sql.Result
|
||||
var err error
|
||||
@ -139,15 +121,9 @@ func releaseTask(workerId *uuid.UUID, id int64, success bool, db *sql.DB) bool {
|
||||
return rowsAffected == 1
|
||||
}
|
||||
|
||||
func (database *Database) GetTaskFromProject(worker *Worker, project int64) *Task {
|
||||
func (database *Database) GetTaskFromProject(worker *Worker, projectId int64) *Task {
|
||||
|
||||
db := database.getDB()
|
||||
task := getTaskFromProject(worker, project, db)
|
||||
|
||||
return task
|
||||
}
|
||||
|
||||
func getTaskFromProject(worker *Worker, projectId int64, db *sql.DB) *Task {
|
||||
|
||||
row := db.QueryRow(`
|
||||
UPDATE task
|
||||
@ -158,7 +134,7 @@ func getTaskFromProject(worker *Worker, projectId int64, db *sql.DB) *Task {
|
||||
FROM task
|
||||
INNER JOIN project p on task.project = p.id
|
||||
WHERE assignee IS NULL AND p.id=$2
|
||||
ORDER BY p.priority DESC, task.priority DESC
|
||||
ORDER BY task.priority DESC
|
||||
LIMIT 1
|
||||
)
|
||||
RETURNING id`, worker.Id, projectId)
|
||||
|
@ -21,17 +21,6 @@ type Worker struct {
|
||||
func (database *Database) SaveWorker(worker *Worker) {
|
||||
|
||||
db := database.getDB()
|
||||
saveWorker(worker, db)
|
||||
}
|
||||
|
||||
func (database *Database) GetWorker(id uuid.UUID) *Worker {
|
||||
|
||||
db := database.getDB()
|
||||
worker := getWorker(id, db)
|
||||
return worker
|
||||
}
|
||||
|
||||
func saveWorker(worker *Worker, db *sql.DB) {
|
||||
|
||||
identityId := getOrCreateIdentity(worker.Identity, db)
|
||||
|
||||
@ -45,7 +34,9 @@ func saveWorker(worker *Worker, db *sql.DB) {
|
||||
}).Trace("Database.saveWorker INSERT worker")
|
||||
}
|
||||
|
||||
func getWorker(id uuid.UUID, db *sql.DB) *Worker {
|
||||
func (database *Database) GetWorker(id uuid.UUID) *Worker {
|
||||
|
||||
db := database.getDB()
|
||||
|
||||
worker := &Worker{}
|
||||
var identityId int64
|
||||
|
@ -10,7 +10,6 @@ func BenchmarkCreateTask(b *testing.B) {
|
||||
|
||||
resp := createProject(api.CreateProjectRequest{
|
||||
Name: "BenchmarkCreateTask" + strconv.Itoa(b.N),
|
||||
Priority: 1,
|
||||
GitRepo: "benchmark_test" + strconv.Itoa(b.N),
|
||||
Version: "f09e8c9r0w839x0c43",
|
||||
CloneUrl: "http://localhost",
|
||||
|
0
web/angular/e2e/protractor.conf.js
Normal file → Executable file
0
web/angular/e2e/protractor.conf.js
Normal file → Executable file
0
web/angular/e2e/src/app.e2e-spec.ts
Normal file → Executable file
0
web/angular/e2e/src/app.e2e-spec.ts
Normal file → Executable file
0
web/angular/e2e/src/app.po.ts
Normal file → Executable file
0
web/angular/e2e/src/app.po.ts
Normal file → Executable file
0
web/angular/e2e/tsconfig.e2e.json
Normal file → Executable file
0
web/angular/e2e/tsconfig.e2e.json
Normal file → Executable file
10
web/angular/src/app/api.service.ts
Normal file → Executable file
10
web/angular/src/app/api.service.ts
Normal file → Executable 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
8
web/angular/src/app/app-routing.module.ts
Normal file → Executable 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
0
web/angular/src/app/app.component.css
Normal file → Executable file
14
web/angular/src/app/app.component.html
Normal file → Executable file
14
web/angular/src/app/app.component.html
Normal file → Executable 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
15
web/angular/src/app/app.module.ts
Normal file → Executable 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,
|
||||
|
@ -0,0 +1,4 @@
|
||||
|
||||
.mat-form-field {
|
||||
width: 100%;
|
||||
}
|
@ -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>
|
@ -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() {
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
});
|
||||
});
|
@ -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(),
|
||||
|
9
web/angular/src/app/models/project.ts
Normal file
9
web/angular/src/app/models/project.ts
Normal 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;
|
||||
}
|
@ -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()
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
0
web/angular/src/app/project-list/project-list.component.css
Executable file
0
web/angular/src/app/project-list/project-list.component.css
Executable file
19
web/angular/src/app/project-list/project-list.component.html
Executable file
19
web/angular/src/app/project-list/project-list.component.html
Executable 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>
|
24
web/angular/src/app/project-list/project-list.component.ts
Executable file
24
web/angular/src/app/project-list/project-list.component.ts
Executable 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"]);
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"sourceMap": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
|
||||
.mat-form-field {
|
||||
width: 100%;
|
||||
}
|
@ -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>
|
@ -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"]
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user