diff --git a/api/auth.go b/api/auth.go
index 0155545..f729b03 100644
--- a/api/auth.go
+++ b/api/auth.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"github.com/Sirupsen/logrus"
"github.com/simon987/task_tracker/storage"
+ "strconv"
)
const MinPasswordLength = 8
@@ -31,6 +32,12 @@ type AccountDetails struct {
Manager *storage.Manager `json:"manager,omitempty"`
}
+type GetAllManagersResponse struct {
+ Ok bool `json:"ok"`
+ Message string `json:"message,omitempty"`
+ Managers *[]storage.Manager `json:"managers"`
+}
+
func (r *RegisterRequest) isValid() bool {
return MinUsernameLength <= len(r.Username) &&
len(r.Username) <= MaxUsernameLength &&
@@ -158,3 +165,100 @@ func (api *WebAPI) AccountDetails(r *Request) {
})
}
}
+
+func (api *WebAPI) GetAllManagers(r *Request) {
+
+ sess := api.Session.StartFasthttp(r.Ctx)
+ manager := sess.Get("manager")
+
+ if manager == nil {
+ r.Json(GetAllManagersResponse{
+ Ok: false,
+ Message: "Unauthorized",
+ }, 401)
+ return
+ }
+
+ managers := api.Database.GetAllManagers()
+
+ r.OkJson(GetAllManagersResponse{
+ Ok: true,
+ Managers: managers,
+ })
+}
+
+func (api *WebAPI) PromoteManager(r *Request) {
+
+ id, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
+ if err != nil || id <= 0 {
+ r.Json(CreateProjectResponse{
+ Ok: false,
+ Message: "Invalid manager id",
+ }, 400)
+ return
+ }
+
+ sess := api.Session.StartFasthttp(r.Ctx)
+ manager := sess.Get("manager")
+
+ if !manager.(*storage.Manager).WebsiteAdmin || manager.(*storage.Manager).Id == id {
+ r.Json(GetAllManagersResponse{
+ Ok: false,
+ Message: "Unauthorized",
+ }, 401)
+ return
+ }
+
+ if !manager.(*storage.Manager).WebsiteAdmin {
+ r.Json(GetAllManagersResponse{
+ Ok: false,
+ Message: "Unauthorized",
+ }, 403)
+ return
+ }
+
+ api.Database.UpdateManager(&storage.Manager{
+ Id: id,
+ WebsiteAdmin: true,
+ })
+
+ r.Ctx.Response.SetStatusCode(204)
+}
+
+func (api *WebAPI) DemoteManager(r *Request) {
+
+ id, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
+ if err != nil || id <= 0 {
+ r.Json(CreateProjectResponse{
+ Ok: false,
+ Message: "Invalid manager id",
+ }, 400)
+ return
+ }
+
+ sess := api.Session.StartFasthttp(r.Ctx)
+ manager := sess.Get("manager")
+
+ if manager == nil {
+ r.Json(GetAllManagersResponse{
+ Ok: false,
+ Message: "Unauthorized",
+ }, 401)
+ return
+ }
+
+ if !manager.(*storage.Manager).WebsiteAdmin || manager.(*storage.Manager).Id == id {
+ r.Json(GetAllManagersResponse{
+ Ok: false,
+ Message: "Unauthorized",
+ }, 403)
+ return
+ }
+
+ api.Database.UpdateManager(&storage.Manager{
+ Id: id,
+ WebsiteAdmin: false,
+ })
+
+ r.Ctx.Response.SetStatusCode(204)
+}
diff --git a/api/main.go b/api/main.go
index 7adaf4d..0d0f813 100644
--- a/api/main.go
+++ b/api/main.go
@@ -106,6 +106,9 @@ func New() *WebAPI {
api.router.POST("/login", LogRequestMiddleware(api.Login))
api.router.GET("/logout", LogRequestMiddleware(api.Logout))
api.router.GET("/account", LogRequestMiddleware(api.AccountDetails))
+ api.router.GET("/manager/list", LogRequestMiddleware(api.GetAllManagers))
+ api.router.GET("/manager/promote/:id", LogRequestMiddleware(api.PromoteManager))
+ api.router.GET("/manager/demote/:id", LogRequestMiddleware(api.DemoteManager))
api.router.NotFound = func(ctx *fasthttp.RequestCtx) {
diff --git a/main/main.go b/main/main.go
index 0730f96..a9c3500 100644
--- a/main/main.go
+++ b/main/main.go
@@ -3,15 +3,14 @@ package main
import (
"github.com/simon987/task_tracker/api"
"github.com/simon987/task_tracker/config"
- "github.com/simon987/task_tracker/storage"
"math/rand"
"time"
)
func tmpDebugSetup() {
- db := storage.Database{}
- db.Reset()
+ //db := storage.Database{}
+ //db.Reset()
}
diff --git a/schema.sql b/schema.sql
index 4bbc6a0..551c00e 100755
--- a/schema.sql
+++ b/schema.sql
@@ -69,7 +69,7 @@ CREATE TABLE manager
(
id SERIAL PRIMARY KEY,
register_time INTEGER NOT NULL,
- website_admin BOOLEAN NOT NULL,
+ tracker_admin BOOLEAN NOT NULL,
username TEXT UNIQUE NOT NULL,
password BYTEA NOT NULL
);
@@ -117,7 +117,7 @@ CREATE OR REPLACE FUNCTION on_manager_insert() RETURNS TRIGGER AS
$$
BEGIN
IF NEW.id = 1 THEN
- UPDATE manager SET website_admin= TRUE WHERE id = 1;
+ UPDATE manager SET tracker_admin= TRUE WHERE id = 1;
end if;
RETURN NEW;
END;
diff --git a/storage/auth.go b/storage/auth.go
index 441848e..1a5f3f4 100644
--- a/storage/auth.go
+++ b/storage/auth.go
@@ -17,21 +17,22 @@ const (
)
type Manager struct {
- Id int `json:"id"`
+ Id int64 `json:"id"`
Username string `json:"username"`
- WebsiteAdmin bool `json:"website_admin"`
+ WebsiteAdmin bool `json:"tracker_admin"`
+ RegisterTime int64 `json:"register_time"`
}
func (database *Database) ValidateCredentials(username []byte, password []byte) (*Manager, error) {
db := database.getDB()
- row := db.QueryRow(`SELECT id, password, website_admin FROM manager WHERE username=$1`,
+ row := db.QueryRow(`SELECT id, password, tracker_admin, register_time FROM manager WHERE username=$1`,
username)
manager := &Manager{}
var passwordHash []byte
- err := row.Scan(&manager.Id, &passwordHash, &manager.WebsiteAdmin)
+ err := row.Scan(&manager.Id, &passwordHash, &manager.WebsiteAdmin, &manager.RegisterTime)
if err != nil {
logrus.WithError(err).WithFields(logrus.Fields{
"username": username,
@@ -66,11 +67,11 @@ func (database *Database) SaveManager(manager *Manager, password []byte) error {
hash.Write([]byte(manager.Username))
hashedPassword := hash.Sum(nil)
- row := db.QueryRow(`INSERT INTO manager (username, password, website_admin, register_time)
- VALUES ($1,$2,$3, extract(epoch from now() at time zone 'utc')) RETURNING ID`,
+ row := db.QueryRow(`INSERT INTO manager (username, password, tracker_admin, register_time)
+ VALUES ($1,$2,$3, extract(epoch from now() at time zone 'utc')) RETURNING ID, register_time`,
manager.Username, hashedPassword, manager.WebsiteAdmin)
- err := row.Scan(&manager.Id)
+ err := row.Scan(&manager.Id, &manager.RegisterTime)
if err != nil {
logrus.WithError(err).WithFields(logrus.Fields{
"username": manager,
@@ -92,16 +93,16 @@ func (database *Database) UpdateManager(manager *Manager) {
db := database.getDB()
- res, err := db.Exec(`UPDATE manager SET website_admin=$1 WHERE id=$2`,
+ res, err := db.Exec(`UPDATE manager SET tracker_admin=$1 WHERE id=$2`,
manager.WebsiteAdmin, manager.Id)
handleErr(err)
rowsAffected, _ := res.RowsAffected()
- logrus.WithError(err).WithFields(logrus.Fields{
+ logrus.WithFields(logrus.Fields{
"rowsAffected": rowsAffected,
"manager": manager,
- }).Warning("Database.UpdateManager UPDATE")
+ }).Trace("Database.UpdateManager UPDATE")
}
func (database *Database) UpdateManagerPassword(manager *Manager, newPassword []byte) {
@@ -119,10 +120,10 @@ func (database *Database) UpdateManagerPassword(manager *Manager, newPassword []
rowsAffected, _ := res.RowsAffected()
- logrus.WithError(err).WithFields(logrus.Fields{
+ logrus.WithFields(logrus.Fields{
"rowsAffected": rowsAffected,
"id": manager.Id,
- }).Warning("Database.UpdateManagerPassword UPDATE")
+ }).Trace("Database.UpdateManagerPassword UPDATE")
}
func (database *Database) ManagerHasRoleOn(manager *Manager, projectId int64) ManagerRole {
@@ -140,3 +141,20 @@ func (database *Database) ManagerHasRoleOn(manager *Manager, projectId int64) Ma
return role
}
+
+func (database *Database) GetAllManagers() *[]Manager {
+
+ db := database.getDB()
+
+ rows, _ := db.Query(`SELECT id, register_time, tracker_admin, username FROM manager`)
+
+ managers := make([]Manager, 0)
+
+ for rows.Next() {
+ m := Manager{}
+ _ = rows.Scan(&m.Id, &m.RegisterTime, &m.WebsiteAdmin, &m.Username)
+ managers = append(managers, m)
+ }
+
+ return &managers
+}
diff --git a/test/schema.sql b/test/schema.sql
index af5a490..0ba5633 100755
--- a/test/schema.sql
+++ b/test/schema.sql
@@ -69,7 +69,7 @@ CREATE TABLE manager
(
id SERIAL PRIMARY KEY,
register_time INTEGER NOT NULL,
- website_admin BOOLEAN NOT NULL,
+ tracker_admin BOOLEAN NOT NULL,
username TEXT UNIQUE NOT NULL,
password BYTEA NOT NULL
);
@@ -116,7 +116,7 @@ CREATE OR REPLACE FUNCTION on_manager_insert() RETURNS TRIGGER AS
$$
BEGIN
IF NEW.id = 1 THEN
- UPDATE manager SET website_admin= TRUE WHERE id = 1;
+ UPDATE manager SET tracker_admin= TRUE WHERE id = 1;
end if;
RETURN NEW;
END;
diff --git a/web/angular/src/app/account-details/account-details.component.html b/web/angular/src/app/account-details/account-details.component.html
index f9e4878..d17fb77 100644
--- a/web/angular/src/app/account-details/account-details.component.html
+++ b/web/angular/src/app/account-details/account-details.component.html
@@ -13,6 +13,10 @@
{{"account.username" | translate}}:
{{authService.account.username}}
+
+ {{"account.register_time" | translate}}:
+ {{moment.unix(authService.account.register_time).utc().format("YYYY-MM-DD HH:mm:ss UTC")}}
+
diff --git a/web/angular/src/app/account-details/account-details.component.ts b/web/angular/src/app/account-details/account-details.component.ts
index 8ace18e..02c8886 100644
--- a/web/angular/src/app/account-details/account-details.component.ts
+++ b/web/angular/src/app/account-details/account-details.component.ts
@@ -1,6 +1,8 @@
import {Component, OnInit} from '@angular/core';
import {AuthService} from "../auth.service";
+import * as moment from "moment"
+
@Component({
selector: 'app-account-details',
templateUrl: './account-details.component.html',
@@ -8,6 +10,8 @@ import {AuthService} from "../auth.service";
})
export class AccountDetailsComponent implements OnInit {
+ public moment = moment;
+
constructor(public authService: AuthService) {
}
diff --git a/web/angular/src/app/api.service.ts b/web/angular/src/app/api.service.ts
index cc9429c..06c27db 100755
--- a/web/angular/src/app/api.service.ts
+++ b/web/angular/src/app/api.service.ts
@@ -69,4 +69,16 @@ export class ApiService {
return this.http.get(this.url + `/project/requests/${project}`)
}
+ getAllManagers() {
+ return this.http.get(this.url + "/manager/list")
+ }
+
+ promote(managerId: number) {
+ return this.http.get(this.url + `/manager/promote/${managerId}`)
+ }
+
+ demote(managerId: number) {
+ return this.http.get(this.url + `/manager/demote/${managerId}`)
+ }
+
}
diff --git a/web/angular/src/app/app-routing.module.ts b/web/angular/src/app/app-routing.module.ts
index cf5a1fe..65f4b76 100755
--- a/web/angular/src/app/app-routing.module.ts
+++ b/web/angular/src/app/app-routing.module.ts
@@ -12,6 +12,7 @@ import {LoginComponent} from "./login/login.component";
import {AccountDetailsComponent} from "./account-details/account-details.component";
import {WorkerDashboardComponent} from "./worker-dashboard/worker-dashboard.component";
import {ProjectPermsComponent} from "./project-perms/project-perms.component";
+import {ManagerListComponent} from "./manager-list/manager-list.component";
const routes: Routes = [
{path: "log", component: LogsComponent},
@@ -22,7 +23,8 @@ const routes: Routes = [
{path: "project/:id/update", component: UpdateProjectComponent},
{path: "project/:id/perms", component: ProjectPermsComponent},
{path: "new_project", component: CreateProjectComponent},
- {path: "workers", component: WorkerDashboardComponent}
+ {path: "workers", component: WorkerDashboardComponent},
+ {path: "manager_list", component: ManagerListComponent}
];
@NgModule({
diff --git a/web/angular/src/app/app.component.html b/web/angular/src/app/app.component.html
index c33d0e3..51230dc 100755
--- a/web/angular/src/app/app.component.html
+++ b/web/angular/src/app/app.component.html
@@ -11,6 +11,10 @@
+
diff --git a/web/angular/src/app/app.module.ts b/web/angular/src/app/app.module.ts
index 5d6eb95..98cb5a0 100755
--- a/web/angular/src/app/app.module.ts
+++ b/web/angular/src/app/app.module.ts
@@ -48,6 +48,7 @@ import {LoginComponent} from './login/login.component';
import {AccountDetailsComponent} from './account-details/account-details.component';
import {WorkerDashboardComponent} from './worker-dashboard/worker-dashboard.component';
import {ProjectPermsComponent} from './project-perms/project-perms.component';
+import {ManagerListComponent} from './manager-list/manager-list.component';
export function createTranslateLoader(http: HttpClient) {
@@ -68,6 +69,7 @@ export function createTranslateLoader(http: HttpClient) {
AccountDetailsComponent,
WorkerDashboardComponent,
ProjectPermsComponent,
+ ManagerListComponent,
],
imports: [
BrowserModule,
diff --git a/web/angular/src/app/auth.service.ts b/web/angular/src/app/auth.service.ts
index 5aec366..ac16069 100644
--- a/web/angular/src/app/auth.service.ts
+++ b/web/angular/src/app/auth.service.ts
@@ -60,6 +60,7 @@ export class AuthService {
.subscribe(() =>
this.apiService.getAccountDetails()
.subscribe((data: any) => {
+ this.logged = true;
this.account = data.manager;
this.router.navigateByUrl("/account");
}),
diff --git a/web/angular/src/app/create-project/create-project.component.html b/web/angular/src/app/create-project/create-project.component.html
index 1757192..f9575ff 100644
--- a/web/angular/src/app/create-project/create-project.component.html
+++ b/web/angular/src/app/create-project/create-project.component.html
@@ -11,7 +11,7 @@
{{ "project.clone_url" | translate}}
-
@@ -23,7 +23,9 @@
-
+
{{"project.public" | translate}}
diff --git a/web/angular/src/app/create-project/create-project.component.ts b/web/angular/src/app/create-project/create-project.component.ts
index 457163e..ff32cbc 100644
--- a/web/angular/src/app/create-project/create-project.component.ts
+++ b/web/angular/src/app/create-project/create-project.component.ts
@@ -3,6 +3,7 @@ import {Project} from "../models/project";
import {ApiService} from "../api.service";
import {MessengerService} from "../messenger.service";
import {Router} from "@angular/router";
+import {AuthService} from "../auth.service";
@Component({
@@ -16,14 +17,21 @@ export class CreateProjectComponent implements OnInit {
constructor(private apiService: ApiService,
private messengerService: MessengerService,
+ public authService: AuthService,
private router: Router) {
- this.project.name = "test";
- this.project.public = true;
}
ngOnInit() {
}
+ cloneUrlChange() {
+ let tokens = this.project.clone_url.split("/");
+
+ if (tokens.length > 2) {
+ this.project.git_repo = tokens[tokens.length - 2] + "/" + tokens[tokens.length - 1]
+ }
+ }
+
onSubmit() {
this.apiService.createProject(this.project).subscribe(
data => {
diff --git a/web/angular/src/app/logs/logs.component.css b/web/angular/src/app/logs/logs.component.css
index 31932f5..2a9d42e 100644
--- a/web/angular/src/app/logs/logs.component.css
+++ b/web/angular/src/app/logs/logs.component.css
@@ -1,5 +1,5 @@
.table-container {
- height: 600px;
+ /*height: 600px;*/
}
.mat-table {
diff --git a/web/angular/src/app/logs/logs.component.html b/web/angular/src/app/logs/logs.component.html
index 5e82737..d971fd1 100644
--- a/web/angular/src/app/logs/logs.component.html
+++ b/web/angular/src/app/logs/logs.component.html
@@ -1,56 +1,63 @@
-
-
-
-
-
- {{"logs.fatal" | translate}}
- {{"logs.panic" | translate}}
- {{"logs.error" | translate}}
- {{"logs.warn" | translate}}
- {{"logs.info" | translate}}
- {{"logs.debug" | translate}}
- {{"logs.trace" | translate}}
-
+
+
+ {{"logs.title" | translate}}
+ {{"logs.subtitle" | translate}}
+
+
+
+
+
+
+ {{"logs.fatal" | translate}}
+ {{"logs.panic" | translate}}
+ {{"logs.error" | translate}}
+ {{"logs.warn" | translate}}
+ {{"logs.info" | translate}}
+ {{"logs.debug" | translate}}
+ {{"logs.trace" | translate}}
+
-
- refresh
-
-
+
+ refresh
+
+
-
+
-
- {{"logs.level" | translate}}
- {{("logs." + entry.level) | translate}}
-
-
- {{"logs.time" | translate}}
- {{entry.timestamp}}
-
-
- {{"logs.message" | translate}}
- {{entry.message}}
-
-
- {{"logs.data" | translate}}
-
- {{entry.data}}
-
-
+
+ {{"logs.level" | translate}}
+ {{("logs." + entry.level) | translate}}
+
+
+ {{"logs.time" | translate}}
+ {{entry.timestamp}}
+
+
+ {{"logs.message" | translate}}
+ {{entry.message}}
+
+
+ {{"logs.data" | translate}}
+
+ {{entry.data}}
+
+
-
-
-
+
+
+
-
-
-
+
+
+
+
diff --git a/web/angular/src/app/logs/logs.component.ts b/web/angular/src/app/logs/logs.component.ts
index a354bb8..70de835 100644
--- a/web/angular/src/app/logs/logs.component.ts
+++ b/web/angular/src/app/logs/logs.component.ts
@@ -39,7 +39,7 @@ export class LogsComponent implements OnInit {
this.getLogs(Number(event.value))
}
- private refresh() {
+ public refresh() {
this.getLogs(this.filterLevel)
}
diff --git a/web/angular/src/app/manager-list/manager-list.component.css b/web/angular/src/app/manager-list/manager-list.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/web/angular/src/app/manager-list/manager-list.component.html b/web/angular/src/app/manager-list/manager-list.component.html
new file mode 100644
index 0000000..3a5cad9
--- /dev/null
+++ b/web/angular/src/app/manager-list/manager-list.component.html
@@ -0,0 +1,53 @@
+
+
+
+ {{"manager_list.title" | translate}}
+ {{"manager_list.subtitle" | translate}}
+
+
+
+
+
+
+
+ {{"manager_list.username" | translate}}
+ {{manager.username}}
+
+
+ {{"manager_list.role" | translate}}
+
+
+ supervisor_account
+
+
+
+
+ {{"manager_list.register_time" | translate}}
+
+ {{moment.unix(manager.register_time).utc().format("UTC YYYY-MM-DD HH:mm:ss")}}
+
+
+
+ {{"manager_list.actions" | translate}}
+
+ {{"manager_list.promote" | translate}}
+ {{"manager_list.demote" | translate}}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/web/angular/src/app/manager-list/manager-list.component.ts b/web/angular/src/app/manager-list/manager-list.component.ts
new file mode 100644
index 0000000..6f7c0ab
--- /dev/null
+++ b/web/angular/src/app/manager-list/manager-list.component.ts
@@ -0,0 +1,70 @@
+import {Component, OnInit, ViewChild} from '@angular/core';
+import {ApiService} from "../api.service";
+import {MessengerService} from "../messenger.service";
+import {TranslateService} from "@ngx-translate/core";
+import {MatPaginator, MatSort, MatTableDataSource} from "@angular/material";
+
+import * as moment from "moment"
+import {AuthService} from "../auth.service";
+
+@Component({
+ selector: 'app-manager-list',
+ templateUrl: './manager-list.component.html',
+ styleUrls: ['./manager-list.component.css']
+})
+export class ManagerListComponent implements OnInit {
+
+ managers = [];
+ data;
+ moment = moment;
+ cols = ['username', 'tracker_admin', 'register_time', 'actions'];
+
+ @ViewChild(MatPaginator) paginator: MatPaginator;
+ @ViewChild(MatSort) sort: MatSort;
+
+ constructor(private apiService: ApiService,
+ private messengerService: MessengerService,
+ private translate: TranslateService,
+ private authService: AuthService
+ ) {
+ this.data = new MatTableDataSource()
+ }
+
+ ngOnInit() {
+ this.getManagers();
+ this.data.paginator = this.paginator;
+ this.data.sort = this.sort;
+ }
+
+ canPromote(manager: Manager) {
+ return !manager.tracker_admin
+ }
+
+ canDemote(manager: Manager) {
+ return manager.tracker_admin && manager.username != this.authService.account.username
+ }
+
+ public promote(manager: Manager) {
+ this.apiService.promote(manager.id)
+ .subscribe(() => this.getManagers())
+ }
+
+ public demote(manager: Manager) {
+ this.apiService.demote(manager.id)
+ .subscribe(() => this.getManagers())
+ }
+
+ private getManagers() {
+ this.apiService.getAllManagers()
+ .subscribe(data => {
+ this.data.data = data["managers"]
+ },
+ error => {
+ if (error && (error.status == 401 || error.status == 403)) {
+ console.log(error.error.message);
+ this.translate.get("manager_list.unauthorized")
+ .subscribe(t => this.messengerService.show(t));
+ }
+ })
+ }
+}
diff --git a/web/angular/src/app/models/manager.ts b/web/angular/src/app/models/manager.ts
index f759998..617c786 100644
--- a/web/angular/src/app/models/manager.ts
+++ b/web/angular/src/app/models/manager.ts
@@ -1,5 +1,6 @@
interface Manager {
id: number;
username: string
- website_admin: boolean;
+ tracker_admin: boolean
+ register_time: number
}
diff --git a/web/angular/src/app/project-list/project-list.component.html b/web/angular/src/app/project-list/project-list.component.html
index d5b812d..ad6ace5 100755
--- a/web/angular/src/app/project-list/project-list.component.html
+++ b/web/angular/src/app/project-list/project-list.component.html
@@ -18,9 +18,11 @@
timeline{{"projects.dashboard" | translate}}
-
+
build{{"project.update" | translate}}
-
+
perm_identity
{{"project.perms" | translate}}
diff --git a/web/angular/src/app/project-list/project-list.component.ts b/web/angular/src/app/project-list/project-list.component.ts
index 99f3273..9213fa1 100755
--- a/web/angular/src/app/project-list/project-list.component.ts
+++ b/web/angular/src/app/project-list/project-list.component.ts
@@ -1,6 +1,7 @@
import {Component, OnInit} from '@angular/core';
import {ApiService} from "../api.service";
import {Project} from "../models/project";
+import {AuthService} from "../auth.service";
@Component({
selector: 'app-project-list',
@@ -9,7 +10,8 @@ import {Project} from "../models/project";
})
export class ProjectListComponent implements OnInit {
- constructor(private apiService: ApiService) {
+ constructor(private apiService: ApiService,
+ public authService: AuthService) {
}
projects: Project[];
diff --git a/web/angular/src/app/project-perms/project-perms.component.css b/web/angular/src/app/project-perms/project-perms.component.css
index 1ba73fb..8c169ea 100644
--- a/web/angular/src/app/project-perms/project-perms.component.css
+++ b/web/angular/src/app/project-perms/project-perms.component.css
@@ -1,10 +1,3 @@
-.unauthorized {
- text-align: center;
- color: #616161;
- min-height: 3em;
- margin-top: 2em !important;
-}
-
.text-mono {
font-family: Hack, Courier, "Courier New", monospace;
color: #ff4081;
diff --git a/web/angular/src/app/project-perms/project-perms.component.html b/web/angular/src/app/project-perms/project-perms.component.html
index ea88f98..64543a0 100644
--- a/web/angular/src/app/project-perms/project-perms.component.html
+++ b/web/angular/src/app/project-perms/project-perms.component.html
@@ -16,7 +16,8 @@
{{w.alias}}
Id={{w.id}}, {{"perms.created" | translate}}
- {{moment.unix(w.created).format("YYYY-MM-DD HH:mm:ss UTC")}}
+ {{moment.unix(w.created).utc().format("UTC YYYY-MM-DD HH:mm:ss")}}
diff --git a/web/angular/src/app/project-perms/project-perms.component.ts b/web/angular/src/app/project-perms/project-perms.component.ts
index 8c4ebec..48fd1c9 100644
--- a/web/angular/src/app/project-perms/project-perms.component.ts
+++ b/web/angular/src/app/project-perms/project-perms.component.ts
@@ -54,7 +54,7 @@ export class ProjectPermsComponent implements OnInit {
})
}
- private refresh() {
+ public refresh() {
this.getProjectRequests()
}
}
diff --git a/web/angular/src/app/worker-dashboard/worker-dashboard.component.ts b/web/angular/src/app/worker-dashboard/worker-dashboard.component.ts
index 5550b69..b27b579 100644
--- a/web/angular/src/app/worker-dashboard/worker-dashboard.component.ts
+++ b/web/angular/src/app/worker-dashboard/worker-dashboard.component.ts
@@ -20,7 +20,7 @@ export class WorkerDashboardComponent implements OnInit {
this.refresh()
}
- private refresh() {
+ public refresh() {
this.apiService.getWorkerStats()
.subscribe((data: any) => {
this.updateChart(data.stats)
diff --git a/web/angular/src/assets/i18n/en.json b/web/angular/src/assets/i18n/en.json
index 27aa80c..1dc3680 100644
--- a/web/angular/src/assets/i18n/en.json
+++ b/web/angular/src/assets/i18n/en.json
@@ -7,9 +7,12 @@
"new_project": "New Project",
"login": "Login",
"worker_dashboard": "Workers",
- "account": "Account"
+ "account": "Account",
+ "manager_list": "Managers"
},
"logs": {
+ "title": "Logs",
+ "subtitle": "",
"filter": "Filter",
"time": "Time (UTC)",
"level": "Level",
@@ -43,7 +46,8 @@
"login": "Login",
"new_account": "Create account",
"account": "Account details",
- "workers": "Workers"
+ "workers": "Workers",
+ "manager_list": "Managers"
},
"project": {
"name": "Project name",
@@ -82,7 +86,8 @@
"title": "Account details",
"subtitle": "toto: subtitle",
"username": "Username",
- "logout": "Logout"
+ "logout": "Logout",
+ "register_time": "Register date"
},
"workers": {
"title": "Completed tasks per worker",
@@ -100,5 +105,17 @@
"messenger": {
"close": "Close",
"unauthorized": "Unauthorized"
+ },
+ "manager_list": {
+ "title": "Manager list",
+ "subtitle": "",
+ "username": "Username",
+ "role": "Role",
+ "tracker_admin": "Tracker administrator",
+ "actions": "Actions",
+ "unauthorized": "You are not authorized to access this page",
+ "promote": "Promote",
+ "demote": "Demote",
+ "register_time": "Register date"
}
}
diff --git a/web/angular/src/assets/i18n/fr.json b/web/angular/src/assets/i18n/fr.json
index 347f101..c4f2b64 100644
--- a/web/angular/src/assets/i18n/fr.json
+++ b/web/angular/src/assets/i18n/fr.json
@@ -2,14 +2,17 @@
"nav": {
"title": "task_tracker (fr)",
"lang_select": "Langue",
- "logs": "Journal",
+ "logs": "Journaux",
"project_list": "Projets",
"new_project": "Nouveau projet",
"login": "Ouvrir un session",
"worker_dashboard": "Workers",
- "account": "Compte"
+ "account": "Compte",
+ "manager_list": "Managers"
},
"logs": {
+ "title": "Journaux",
+ "subtitle": "",
"filter": "Filtrer",
"time": "Date (UTC)",
"level": "Niveau",
@@ -44,7 +47,8 @@
"login": "Ouverture de session",
"new_account": "Création de compte",
"account": "Compte",
- "workers": "Workers"
+ "workers": "Workers",
+ "manager_list": "Managers"
},
"project": {
"name": "Nom du projet",
@@ -84,7 +88,8 @@
"title": "Détails du compte",
"subtitle": "toto: sous-titre",
"username": "Nom d'utilisateur",
- "logout": "Fermer la session"
+ "logout": "Fermer la session",
+ "register_time": "Date de création"
},
"workers": {
"title": "Tâches complétés par worker",
@@ -102,6 +107,18 @@
"messenger": {
"close": "Fermer",
"unauthorized": "Non autorisé"
+ },
+ "manager_list": {
+ "title": "Liste ",
+ "subtitle": "",
+ "username": "Nom d'utilisateur",
+ "role": "Rôle",
+ "tracker_admin": "Administrateur",
+ "actions": "Actions",
+ "unauthorized": "Vou n'êtes pas authorisé à accéder à cette page",
+ "promote": "Promouvoir",
+ "demote": "Rétrograder",
+ "register_time": "Date d'inscription"
}
}
diff --git a/web/angular/src/styles.css b/web/angular/src/styles.css
index af08975..e7c1faf 100644
--- a/web/angular/src/styles.css
+++ b/web/angular/src/styles.css
@@ -17,7 +17,7 @@ body {
padding-left: 15px;
margin-right: auto;
margin-left: auto;
- margin-top: 15px;
+ margin-top: 30px;
}
@media (min-width: 576px) {
@@ -86,3 +86,11 @@ pre {
.hidden {
display: none !important;
}
+
+.unauthorized {
+ text-align: center;
+ color: #616161;
+ min-height: 3em;
+ margin-top: 2em !important;
+}
+