Skip to content

Commit

Permalink
Group view (#572)
Browse files Browse the repository at this point in the history
* create individual group view

* secure group delete button

* fixes

* fixes

* close #580 + UI fixes
  • Loading branch information
rsiminel authored Jan 23, 2025
1 parent e7efa8e commit 804fc51
Show file tree
Hide file tree
Showing 11 changed files with 335 additions and 191 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
* increase size of input field in users page
* add a readonly input field under email for showing the email domain*
* Add "custom_users" key to config file, to be used with various scripts
* Separate global overview from individual group view in admin group management
* Allow accents in user's first and last names


## 1.4.31 (2024-09-27)

* Fix 'Admin' button in 'My projects' page for administrators
Expand Down
1 change: 1 addition & 0 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ app.post('/group/:id', groups);
app.put('/group/:id', groups);
app.delete('/group/:id', groups);
app.get('/group/:id', groups);
app.get('/group/:id/users', groups);
app.get('/user', users);
app.get('/database', database);
app.get('/pending/database', database);
Expand Down
144 changes: 144 additions & 0 deletions manager2/src/app/admin/group/group.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<div class="col-sm-6">
<a routerLink="/admin/group" class="btn btn-primary">Back to groups</a>
</div>

<div class="alert alert-danger" *ngIf="del_err_msg">{{ del_err_msg }}</div>

<div class="card bg-light">
<div class="card bg-light card-header">
<div class="row">
<div class="col-sm-9">
<h4>
Group <strong>{{ group.name }}</strong>
</h4>
</div>
<div class="col-sm-3">
<app-my-delete-confirm
[onConfirm]="deleteGroup"
></app-my-delete-confirm>
</div>
</div>
</div>
<div class="card-body">
<form role="form" class="user-form form-horizontal form-register">
<div class="form-group row">
<div class="col-sm-3">
<label for="group_id" class="col-form-label">Owner</label>
<input
type="text"
placeholder="Owner"
id="group_id"
[ngModelOptions]="{ standalone: true }"
[(ngModel)]="group.owner"
class="form-control"
/>
</div>
<div class="col-sm-9">
<label for="group_desc" class="col-form-label">Description</label>
<input
type="text"
placeholder="Description"
id="group_desc"
[ngModelOptions]="{ standalone: true }"
[(ngModel)]="group.description"
class="form-control"
/>
</div>
</div>
<button
type="button"
class="p-button p-button-sm p-button-primary"
(click)="updateGroup()"
>
Update
</button>
<div class="form-group"></div>
</form>
</div>
</div>

<div class="card bg-light">
<div class="card-header">
<h3>Group tags</h3>
</div>
<div class="card-body">
<app-tag [tag]="group.tags" [user]="group.name" kind="group"></app-tag>
</div>
</div>

<div class="card bg-light">
<div class="card-header">
<h3>Projects associated with {{ group.name }} :</h3>
</div>
<div class="card-body">
<div class="table">
<table class="table table-striped">
<thead>
<th>Project</th>
<th>Owner</th>
</thead>
<tbody>
<tr *ngFor="let project of projects">
<td>
<a routerLink="/admin/project/{{ project.id }}">
<span class="p-button p-button-sm p-button-primary">
{{ project.id }}
</span>
</a>
</td>
<td>
<a routerLink="/user/{{ project.owner }}">
<span class="p-button p-button-sm p-button-primary">
{{ project.owner }}
</span>
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

<div class="card bg-light">
<div class="card-header">
<h3>Users in {{ group.name }} :</h3>
</div>
<div class="card-body">
<div class="alert alert-info" *ngIf="msg">{{ msg }}</div>
<div class="alert alert-danger" *ngIf="err_msg">{{ err_msg }}</div>
<div class="table-responsive table-striped">
<p-table
#dtu
[value]="users"
[paginator]="true"
[rows]="10"
[showCurrentPageReport]="true"
[rowsPerPageOptions]="[10, 25, 50]"
>
<ng-template pTemplate="header">
<tr>
<th>User</th>
<th>Email</th>
<th>In associated project?</th>
<th>Main group?</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-user>
<tr *ngFor="let user of users">
<td>
<a routerLink="/user/{{ user.uid }}">
<span class="p-button p-button-sm p-button-primary">
{{ user.uid }}
</span>
</a>
</td>
<td>{{ user.email }}</td>
<td><span *ngIf="user.temp?.authorized">x</span></td>
<td><span *ngIf="user.group == group.name">x</span></td>
</tr>
</ng-template>
</p-table>
</div>
</div>
</div>
93 changes: 93 additions & 0 deletions manager2/src/app/admin/group/group.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { Component, OnInit, ViewChild } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";
import { Group, GroupsService } from "../groups/groups.service";
import { Project, ProjectsService } from "../projects/projects.service";
import { User } from "../../user/user.service";
import { Table } from "primeng/table";

@Component({
selector: "app-groups",
templateUrl: "./group.component.html"
// styleUrls: ['./group.component.css']
})
export class GroupComponent implements OnInit {
@ViewChild("dtg") tableGroups: Table;
@ViewChild("dtu") tableUsers: Table;

msg: string;
err_msg: string;
del_err_msg: string;
group: Group;
projects: Project[];
users: User[];

constructor(
private route: ActivatedRoute,
private router: Router,
private groupsService: GroupsService,
private projectsService: ProjectsService
) {
this.group = new Group();
this.projects = null;
this.users = null;
}

ngOnDestroy(): void {}

ngAfterViewInit(): void {}

ngOnInit() {
this.deleteGroup = this.deleteGroup.bind(this);
this.route.params.subscribe((params) => {
let group_name = params.id;
this.groupsService.get(group_name).subscribe(
(group) => (this.group = group),
(err) => console.log("failed to get group")
);
this.projectsService.getProjectsInGroup(group_name).subscribe(
(project_list) => (this.projects = project_list),
(err) => console.log("failed to get projects in group")
);
this.groupsService.getUsers(group_name).subscribe(
(user_list) => {
this.users = user_list;
for (var i = 0; i < user_list.length; i++) {
var is_authorized = false;
if (user_list[i].projects) {
for (var j = 0; j < this.projects.length; j++) {
if (user_list[i].projects.indexOf(this.projects[j].id) >= 0) {
is_authorized = true;
break;
}
}
}
this.users[i].temp = {
...this.users[i].temp,
authorized: is_authorized
};
}
},
(err) => console.log("failed to get group's users")
);
});
}

deleteGroup() {
this.groupsService.delete(this.group.name).subscribe(
(resp) =>
this.router.navigate(["/admin/group"], {
queryParams: { deleted: "ok" }
}),
(err) => (this.del_err_msg = err.error.message)
);
}

updateGroup() {
this.msg = "";
this.err_msg = "";
this.groupsService.update(this.group).subscribe(
(resp) => (this.msg = "Group updated"),
(err) => (this.err_msg = err.error.message)
);
}
}
85 changes: 4 additions & 81 deletions manager2/src/app/admin/groups/groups.component.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<div *ngIf="notification" class="alert alert-success">{{notification}}</div>

<div class="card bg-light">
<div class="card-header">
<h3 class="panel-title">Group creation</h3>
Expand All @@ -23,85 +25,6 @@ <h3 class="panel-title">Group creation</h3>
</div>
</div>


<div class="row">
<div class="alert alert-success" *ngIf="rm_grp_msg_ok">{{rm_grp_msg_ok}}</div>
</div>
<div *ngIf="selectedGroup">
<div class="card bg-light">
<div class="card-header">
<h3>Group tags</h3>
</div>
<div class="card-body">
<app-tag [tag]="selectedGroup.tags" [user]="selectedGroup.name" kind="group"></app-tag>
</div>
</div>

<div class="card bg-light">
<div class="card-header">
<h3>Users in group {{selectedGroup.name}}</h3>
</div>
<div class="card-body">
<div class="alert alert-danger" *ngIf="rm_grp_err_msg">{{rm_grp_err_msg}}</div>
<div class="alert alert-info" *ngIf="msg">{{msg}}</div>
<form role="form" class="user-form form-horizontal form-register">
<div class="form-group">
<label for="group_id" class="col-sm-2 col-form-label">Owner</label>
<div class="col-sm-3">
<input placeholder="Owner" id="group_id" type="text" [ngModelOptions]="{standalone: true}" [(ngModel)]="selectedGroup.owner" class="form-control"/>
</div>
<label for="group_desc" class="col-sm-2 col-form-label">Description</label>
<div class="col-sm-6">
<input placeholder="Description" id="group_desc" type="text" [ngModelOptions]="{standalone: true}" [(ngModel)]="selectedGroup.description" class="form-control"/>
</div>
<button type="button" class="p-button p-button-sm p-button-secondary" (click)="updateGroup()">Update</button>
</div>
<div class="form-group">

</div>
</form>
<h5>Projects associated with this group :</h5>
<div class="table">
<table class="table table-striped">
<thead>
<th>Project</th><th>Owner</th>
</thead>
<tbody>
<tr *ngFor="let project of projects">
<td>{{project.id}}</td>
<td>{{project.owner}}</td>
</tr>
</tbody>
</table>
</div>
<br>
<h5>Group members</h5>
<div class="table-responsive table-striped">
<p-table #dtu [value]="users"
[paginator]="true"
[rows]="10"
[showCurrentPageReport]="true"
[rowsPerPageOptions]="[10,25,50]"
>
<ng-template pTemplate="header">
<tr><th>User</th><th>Email</th><th>In associated project?</th><th>Main group?</th></tr>
</ng-template>
<ng-template pTemplate="body" let-user>
<tr>
<td><a routerLink="/user/{{user.uid}}"><span class="p-button p-button-sm p-button-primary">{{user.uid}}</span></a></td>
<td>{{user.email}}</td>
<td><span *ngIf="user.temp?.authorized">x</span></td>
<td><span *ngIf="user.group == selectedGroup.name">x</span></td>
</tr>
</ng-template>
</p-table>
</div>
<button class="p-button p-button-sm p-button-danger" (click)="delete_group()">Delete</button>
</div>
</div>
</div>


<div class="card bg-light">
<div class="card-header">
<h3>Groups</h3>
Expand Down Expand Up @@ -136,9 +59,9 @@ <h3>Groups</h3>
</ng-template>
<ng-template pTemplate="body" let-group>
<tr>
<td (click)="show_group_users(group)" style="cursor: pointer;"><span class="p-button p-button-sm p-button-primary">{{group.name}}</span></td>
<td><a routerLink="/admin/group/{{group.name}}"><span class="p-button p-button-sm p-button-primary">{{group.name}}</span></a></td>
<td>{{group.gid}}</td>
<td>{{group.owner}}</td>
<td><a *ngIf="group.owner" routerLink="/user/{{group.owner}}"><span class="p-button p-button-sm p-button-primary">{{group?.owner}}</span></a></td>
<td>{{group.description}}</td>
<td>{{group.tags ? group.tags.join(", ") : ""}}</td>
</tr>
Expand Down
Loading

0 comments on commit 804fc51

Please sign in to comment.