Skip to content
This repository was archived by the owner on Sep 10, 2025. It is now read-only.

Commit fc3c08f

Browse files
committed
Further enhanced design and added some qol enhancements
1 parent 7cd372a commit fc3c08f

25 files changed

+180
-117
lines changed

EEDU-Backend/src/main/java/de/gaz/eedu/DataLoader.java

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import de.gaz.eedu.user.AccountType;
44
import de.gaz.eedu.user.UserEntity;
55
import de.gaz.eedu.user.UserService;
6-
import de.gaz.eedu.user.UserStatus;
76
import de.gaz.eedu.user.group.GroupEntity;
87
import de.gaz.eedu.user.group.GroupService;
98
import de.gaz.eedu.user.group.model.GroupCreateModel;
@@ -12,6 +11,7 @@
1211
import de.gaz.eedu.user.privileges.PrivilegeService;
1312
import de.gaz.eedu.user.privileges.SystemPrivileges;
1413
import de.gaz.eedu.user.privileges.model.PrivilegeCreateModel;
14+
import de.gaz.eedu.user.privileges.model.PrivilegeModel;
1515
import de.gaz.eedu.user.theming.ThemeCreateModel;
1616
import de.gaz.eedu.user.theming.ThemeEntity;
1717
import de.gaz.eedu.user.theming.ThemeService;
@@ -34,9 +34,12 @@
3434
import java.util.Objects;
3535
import java.util.Set;
3636
import java.util.stream.Collectors;
37-
import java.util.stream.Stream;
3837

39-
@Component @RequiredArgsConstructor @Slf4j @Getter(AccessLevel.PROTECTED) public class DataLoader implements CommandLineRunner
38+
@Component
39+
@RequiredArgsConstructor
40+
@Slf4j
41+
@Getter(AccessLevel.PROTECTED)
42+
public class DataLoader implements CommandLineRunner
4043
{
4144
private final UserService userService;
4245
private final GroupService groupService;
@@ -50,8 +53,8 @@
5053

5154
@Override @Transactional public void run(@NotNull String... args)
5255
{
53-
54-
if (userService.getRepository().findByLoginName("root").isEmpty())
56+
createDefaultPrivileges();
57+
if (getUserService().getRepository().findByLoginName("root").isEmpty())
5558
{
5659
createDefaultUser();
5760
}
@@ -72,11 +75,10 @@ private void createDefaultUser()
7275
{
7376
String randomPassword = randomPassword();
7477

75-
createDefaultPrivileges();
7678
createDefaultGroup();
7779

7880
// skip adding root user when testing
79-
if(Objects.equals(getEnvironment().getActiveProfiles()[0], "test")) { return; }
81+
if (Objects.equals(getEnvironment().getActiveProfiles()[0], "test")) {return;}
8082

8183
UserEntity userEntity = createDefaultUser(createDefaultTheme());
8284
setPassword(userEntity, randomPassword);
@@ -98,13 +100,23 @@ private void setPassword(@NotNull UserEntity userEntity, @NotNull String randomP
98100
{
99101
CredentialMethod password = CredentialMethod.PASSWORD;
100102
int bitMask = CredentialMethod.bitMask(password);
101-
CredentialCreateModel credential = new CredentialCreateModel(userEntity.getId(), password, bitMask, randomPassword);
103+
CredentialCreateModel credential = new CredentialCreateModel(
104+
userEntity.getId(),
105+
password,
106+
bitMask,
107+
randomPassword);
102108
getCredentialService().createEntity(Set.of(credential));
103109
}
104110

105111
private void createDefaultPrivileges()
106112
{
107-
getPrivilegeService().createEntity(Arrays.stream(SystemPrivileges.values()).map(privilege ->
113+
Set<String> existingPrivileges = getPrivilegeService().findAll().stream().map(PrivilegeModel::id).collect(
114+
Collectors.toUnmodifiableSet());
115+
getPrivilegeService().createEntity(Arrays.stream(SystemPrivileges.values()).filter(current ->
116+
{
117+
String privilegeName = current.toString();
118+
return !existingPrivileges.contains(privilegeName);
119+
}).map(privilege ->
108120
{
109121
String privilegeName = privilege.toString();
110122
return new PrivilegeCreateModel(privilegeName);
@@ -113,17 +125,19 @@ private void createDefaultPrivileges()
113125

114126
private void createDefaultGroup()
115127
{
116-
getGroupService().createEntity(AccountType.groupSet().stream().map(
117-
(currentGroup) -> new GroupCreateModel(currentGroup, new String[0])
118-
).collect(Collectors.toSet()));
128+
getGroupService().createEntity(AccountType.groupSet().stream().map((currentGroup) -> new GroupCreateModel(
129+
currentGroup,
130+
new String[0])).collect(Collectors.toSet()));
119131
}
120132

121133
private @NotNull ThemeEntity createDefaultTheme()
122134
{
123-
ThemeCreateModel defaultDark = new ThemeCreateModel("defaultDark",
135+
ThemeCreateModel defaultDark = new ThemeCreateModel(
136+
"defaultDark",
124137
new byte[]{Byte.MIN_VALUE + 5, Byte.MIN_VALUE + 5, Byte.MIN_VALUE + 5},
125138
new byte[]{Byte.MIN_VALUE + 10, Byte.MIN_VALUE + 10, Byte.MIN_VALUE + 10});
126-
ThemeCreateModel defaultLight = new ThemeCreateModel("defaultLight",
139+
ThemeCreateModel defaultLight = new ThemeCreateModel(
140+
"defaultLight",
127141
new byte[]{Byte.MIN_VALUE + 255, Byte.MIN_VALUE + 255, Byte.MIN_VALUE + 255},
128142
new byte[]{Byte.MIN_VALUE + 235, Byte.MIN_VALUE + 235, Byte.MIN_VALUE + 235});
129143

@@ -140,10 +154,8 @@ private void createDefaultGroup()
140154
"root", // first id
141155
"root", // last id
142156
"root", // login id
143-
AccountType.ADMINISTRATOR,
144-
true, // enabled
145-
themeEntity.getId(),
146-
new String[] { } // groups
157+
AccountType.ADMINISTRATOR, true, // enabled
158+
themeEntity.getId(), new String[]{} // groups
147159
))).getFirst());
148160
}
149161

EEDU-Backend/src/main/java/de/gaz/eedu/course/CourseEntity.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public class CourseEntity implements EntityModelRelation<Long, CourseModel>
5555
@OneToMany(mappedBy = "course") @JsonManagedReference @Getter(AccessLevel.NONE) @Cascade(org.hibernate.annotations.CascadeType.ALL)
5656
private final Set<AppointmentEntryEntity> appointments = new HashSet<>();
5757
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Setter(AccessLevel.NONE) private Long id; // ID is final
58+
@Column(length = 50, nullable = false)
5859
private String name;
5960
@ManyToOne @JsonManagedReference @JoinColumn(name = "class_room_id", referencedColumnName = "id")
6061
@Getter(AccessLevel.NONE) @Setter(AccessLevel.NONE) private @Nullable ClassRoomEntity classRoom;

EEDU-Backend/src/main/java/de/gaz/eedu/course/classroom/ClassRoomEntity.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
@Table(name = "class_room_entity")
3535
public class ClassRoomEntity implements EntityModelRelation<String, ClassRoomModel>
3636
{
37+
@Column(length = 20, nullable = false)
3738
@Id @Setter(AccessLevel.NONE) private String id;
3839

3940
@OneToMany(mappedBy = "classRoom") @JsonBackReference @Getter(AccessLevel.PRIVATE) private final Set<UserEntity> users = new HashSet<>();

EEDU-Backend/src/main/java/de/gaz/eedu/course/subject/SubjectEntity.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
import de.gaz.eedu.course.CourseEntity;
55
import de.gaz.eedu.course.subject.model.SubjectModel;
66
import de.gaz.eedu.entity.model.EntityModelRelation;
7-
import jakarta.persistence.CascadeType;
8-
import jakarta.persistence.Entity;
9-
import jakarta.persistence.Id;
10-
import jakarta.persistence.OneToMany;
7+
import jakarta.persistence.*;
118
import lombok.*;
129
import org.jetbrains.annotations.Contract;
1310
import org.jetbrains.annotations.NotNull;
@@ -45,6 +42,7 @@ public class SubjectEntity implements EntityModelRelation<String, SubjectModel>
4542
@JsonBackReference @OneToMany(mappedBy = "subject", cascade = CascadeType.REMOVE)
4643
// delete courses if subject is deleted.
4744
private final Set<CourseEntity> courses = new HashSet<>();
45+
@Column(length = 50, nullable = false)
4846
@Id @Getter @Setter(AccessLevel.NONE) private String id;
4947

5048
@Override public @NotNull SubjectModel toModel()

EEDU-Backend/src/main/resources/schema.sql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ CREATE TABLE IF NOT EXISTS file_entity_tags
2323
-- Classes, Courses and Subjects --
2424
CREATE TABLE IF NOT EXISTS class_room_entity
2525
(
26-
id VARCHAR(255) PRIMARY KEY NOT NULL
26+
id VARCHAR(20) PRIMARY KEY NOT NULL
2727
);
2828

2929
CREATE TABLE IF NOT EXISTS subject_entity
@@ -38,10 +38,10 @@ CREATE TABLE IF NOT EXISTS room_entity
3838
CREATE TABLE IF NOT EXISTS course_entity
3939
(
4040
id BIGINT PRIMARY KEY AUTO_INCREMENT,
41-
name VARCHAR(255) NOT NULL,
41+
name VARCHAR(50) NOT NULL,
4242
subject_id VARCHAR(50) NOT NULL,
4343
repository_id BIGINT NOT NULL,
44-
class_room_id VARCHAR(255) NULL,
44+
class_room_id VARCHAR(20) NULL,
4545
FOREIGN KEY (subject_id) REFERENCES subject_entity (id),
4646
FOREIGN KEY (repository_id) REFERENCES file_entity (id),
4747
FOREIGN KEY (class_room_id) REFERENCES class_room_entity (id)
@@ -103,7 +103,7 @@ CREATE TABLE IF NOT EXISTS user_entity
103103
locked BIT NOT NULL,
104104
theme_id BIGINT NULL,
105105
status TINYINT NULL,
106-
class_room_id VARCHAR(255) NULL,
106+
class_room_id VARCHAR(20) NULL,
107107
FOREIGN KEY (theme_id) REFERENCES theme_entity (id),
108108
FOREIGN KEY (class_room_id) REFERENCES class_room_entity (id)
109109
);

EEDU-Frontend/src/app/common/abstract-list/abstract-list.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
[checked]="isSelected(value)"
3232
[icon]="loadIcon(value)"
3333
[title]="loadTitle(value)"
34-
[show]="true"
34+
[show]="selectionType() === SelectionType.MULTIPLE"
3535
(keyboardEvent)="handleKeyDown($event, value)"
3636
(onToggle)="toggle(value)">
3737
</single-checkbox>

EEDU-Frontend/src/app/common/abstract-list/abstract-list.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,6 @@ export class AbstractList<T> {
157157
protected unselectAll(): void {
158158
this._selection.clear();
159159
}
160+
161+
protected readonly SelectionType = SelectionType;
160162
}

EEDU-Frontend/src/app/common/abstract-list/checkboxes/single-check-box.component.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,35 @@
11
import {Component, EventEmitter, input, InputSignal, Output} from '@angular/core';
22
import {MatIcon} from "@angular/material/icon";
33
import {MatListItemTitle} from "@angular/material/list";
4-
import {NgIf} from "@angular/common";
4+
import {NgIf, NgTemplateOutlet} from "@angular/common";
55
import {MatCheckbox} from "@angular/material/checkbox";
66

77
@Component({
88
selector: 'single-checkbox', template: `
99
<a matListItemTitle>
10+
11+
<ng-template #text>
12+
<a class="title">
13+
<mat-icon *ngIf="icon()">{{ icon() }}</mat-icon>
14+
{{ title() }}
15+
</a>
16+
</ng-template>
17+
1018
<mat-checkbox
1119
*ngIf="show()"
1220
[checked]="checked()"
1321
(click)="$event.stopPropagation()"
1422
(change)="onToggle.emit()"
1523
(keydown)="keyboardEvent.emit($event)">
16-
<a class="title">
17-
<mat-icon class="icon" *ngIf="icon()">{{ icon() }}</mat-icon>
18-
{{ title() }}
19-
</a>
24+
<ng-container *ngTemplateOutlet="text"></ng-container>
2025
</mat-checkbox>
26+
27+
<div *ngIf="!show()">
28+
<ng-container *ngTemplateOutlet="text"></ng-container>
29+
</div>
30+
2131
</a>
22-
`, styles: '.title { user-select: none }', imports: [MatCheckbox, NgIf, MatListItemTitle, MatIcon]
32+
`, styles: '.title { user-select: none }', imports: [MatCheckbox, NgIf, MatListItemTitle, MatIcon, NgTemplateOutlet]
2333
})
2434
export class SingleCheckBoxComponent {
2535
@Output() public readonly keyboardEvent: EventEmitter<KeyboardEvent> = new EventEmitter<KeyboardEvent>;

EEDU-Frontend/src/app/common/selection-input/selection-input.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,13 @@ const type: Type<SelectionInput<any>> = forwardRef((): typeof SelectionInput =>
7878
MatAutocomplete,
7979
MatOption,
8080
FormsModule,
81+
MatIcon,
8182
MatLabel,
8283
NgIf,
8384
MatChipGrid,
8485
MatChipRow,
85-
MatIcon,
8686
MatChipInput,
87-
MatChipRemove
87+
MatChipRemove,
8888
],
8989
providers: [
9090
{ provide: NG_VALUE_ACCESSOR, useExisting: type, multi: true },

EEDU-Frontend/src/app/entity/create-entity/simple-create-dialog/simple-create-dialog.component.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121
</mat-card-content>
2222
<mat-card-actions align="end">
2323
<button class="close-button" mat-button mat-dialog-close type="button">Cancel</button>
24-
<button [disabled]="form.invalid" mat-stroked-button type="submit">Submit</button>
24+
<button [disabled]="form.invalid"
25+
color="primary" mat-stroked-button type="submit">
26+
Submit
27+
</button>
2528
</mat-card-actions>
2629
</abstract-general-card>
2730
</form>

0 commit comments

Comments
 (0)