Compare commits
9 Commits
968ff8349f
...
c060cd9083
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c060cd9083 | ||
|
|
371967380b | ||
|
|
7316343658 | ||
|
|
31c8249516 | ||
|
|
114995d274 | ||
|
|
e8376ccd21 | ||
|
|
52e6eac71d | ||
|
|
36c55b6382 | ||
|
|
c73b299e3e |
@ -15,6 +15,7 @@
|
||||
"@angular/core": "^17.3.0",
|
||||
"@angular/forms": "^17.3.0",
|
||||
"@angular/material": "^17.3.10",
|
||||
"@angular/material-moment-adapter": "^17.3.10",
|
||||
"@angular/platform-browser": "^17.3.0",
|
||||
"@angular/platform-browser-dynamic": "^17.3.0",
|
||||
"@angular/platform-server": "^17.3.0",
|
||||
@ -542,6 +543,19 @@
|
||||
"rxjs": "^6.5.3 || ^7.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/material-moment-adapter": {
|
||||
"version": "17.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-17.3.10.tgz",
|
||||
"integrity": "sha512-R68ssdGMSmVIfpOGaB9vjW5lBh6zH9GboBuaIAqizC/ZAzdEgpmT7qdr3PBCmRPTLTx8Yx9K3rhgRekO79ympw==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": "^17.0.0 || ^18.0.0",
|
||||
"@angular/material": "17.3.10",
|
||||
"moment": "^2.18.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular/platform-browser": {
|
||||
"version": "17.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-17.3.11.tgz",
|
||||
@ -9453,6 +9467,15 @@
|
||||
"mkdirp": "bin/cmd.js"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.30.1",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/mrmime": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
"@angular/core": "^17.3.0",
|
||||
"@angular/forms": "^17.3.0",
|
||||
"@angular/material": "^17.3.10",
|
||||
"@angular/material-moment-adapter": "^17.3.10",
|
||||
"@angular/platform-browser": "^17.3.0",
|
||||
"@angular/platform-browser-dynamic": "^17.3.0",
|
||||
"@angular/platform-server": "^17.3.0",
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
<div class="dd-container">
|
||||
<div class="dd-row input-row">
|
||||
<mat-form-field class="w40p">
|
||||
<mat-label>Geben Sie einen Datumsbereich ein</mat-label>
|
||||
<mat-date-range-input [formGroup]="range" [rangePicker]="picker">
|
||||
<input matStartDate formControlName="start" placeholder="Start date">
|
||||
<input matEndDate formControlName="end" placeholder="End date">
|
||||
</mat-date-range-input>
|
||||
<mat-hint>{{dateFormatString()}}</mat-hint>
|
||||
<mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle>
|
||||
<mat-date-range-picker #picker></mat-date-range-picker>
|
||||
|
||||
@if (range.controls.start.hasError('matStartDateInvalid')) {
|
||||
<mat-error>Ungültiges Startdatum</mat-error>
|
||||
}
|
||||
@if (range.controls.end.hasError('matEndDateInvalid')) {
|
||||
<mat-error>Ungültiges Enddatum</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<button mat-fab extended (click)="create()" class="w20p">
|
||||
<mat-icon>playlist_add</mat-icon>
|
||||
Erstellen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { RepCreateFormComponent } from './rep-create-form.component';
|
||||
|
||||
describe('RepCreateFormComponent', () => {
|
||||
let component: RepCreateFormComponent;
|
||||
let fixture: ComponentFixture<RepCreateFormComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [RepCreateFormComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(RepCreateFormComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,95 @@
|
||||
import { Component, inject, ChangeDetectionStrategy, signal, OnInit, computed } from '@angular/core';
|
||||
import { UserRep } from '../../../models/user-management.api.models';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { UserRepService } from '../../../services/api/user-representation.service';
|
||||
import { GroupUpdateFormComponent } from '../group-update-form/group-update-form.component';
|
||||
import { JsonPipe } from '@angular/common';
|
||||
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { DateAdapter, MAT_DATE_LOCALE, provideNativeDateAdapter } from '@angular/material/core';
|
||||
import { MatDatepickerIntl, MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import Swal from 'sweetalert2';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { provideMomentDateAdapter } from '@angular/material-moment-adapter';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import 'moment/locale/de';
|
||||
|
||||
@Component({
|
||||
selector: 'app-rep-create-form',
|
||||
standalone: true,
|
||||
providers: [
|
||||
provideNativeDateAdapter(),
|
||||
{ provide: MAT_DATE_LOCALE, useValue: 'de-DE' },
|
||||
provideMomentDateAdapter()
|
||||
],
|
||||
imports: [MatFormFieldModule, MatDatepickerModule, FormsModule, ReactiveFormsModule, JsonPipe, MatButtonModule, MatIconModule, MatInputModule],
|
||||
templateUrl: './rep-create-form.component.html',
|
||||
styleUrl: './rep-create-form.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class RepCreateFormComponent implements OnInit {
|
||||
|
||||
readonly userRep: UserRep;
|
||||
readonly afterCreation: (any: any) => any;
|
||||
readonly userRepService: UserRepService = inject(UserRepService);
|
||||
readonly dialogRef: MatDialogRef<GroupUpdateFormComponent> = inject(MatDialogRef<GroupUpdateFormComponent>);
|
||||
readonly range = new FormGroup({
|
||||
start: new FormControl<Date | null>(null),
|
||||
end: new FormControl<Date | null>(null),
|
||||
});
|
||||
private readonly _locale = signal(inject<unknown>(MAT_DATE_LOCALE));
|
||||
private readonly _adapter = inject<DateAdapter<unknown, unknown>>(DateAdapter);
|
||||
private readonly _intl = inject(MatDatepickerIntl);
|
||||
|
||||
constructor() {
|
||||
const dialogData: { userRep: UserRep, afterCreation: (any: any) => any } = inject(MAT_DIALOG_DATA)
|
||||
this.userRep = dialogData.userRep;
|
||||
this.afterCreation = dialogData.afterCreation;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
//update close button label
|
||||
this._intl.closeCalendarLabel = 'Kalender schließen';
|
||||
this._intl.changes.next();
|
||||
|
||||
//set local
|
||||
this._locale.set('de');
|
||||
this._adapter.setLocale(this._locale());
|
||||
}
|
||||
|
||||
readonly dateFormatString = computed(() => {
|
||||
if (this._locale() === 'de-DE') {
|
||||
return 'dd.mm.yyyy';
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
create() {
|
||||
const validFrom = this.range.value.start;
|
||||
const validTo = this.range.value.end;
|
||||
|
||||
if (!validFrom || !validTo) {
|
||||
Swal.fire({
|
||||
icon: "error",
|
||||
title: "Oops...",
|
||||
text: "Bitte geben Sie einen gültigen Datumsbereich ein!",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.userRep.validFrom = validFrom!;
|
||||
this.userRep.validTo = validTo!;
|
||||
|
||||
this.userRepService.create(this.userRep).subscribe({
|
||||
next: (res) => {
|
||||
this.afterCreation({ successful: res });
|
||||
this.dialogRef.close();
|
||||
},
|
||||
error: (error) => {
|
||||
this.afterCreation({ error: error });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -64,6 +64,8 @@ export interface UserRep {
|
||||
userId?: number,
|
||||
repGroupId?: number,
|
||||
groupId?: number,
|
||||
validFrom?: Date,
|
||||
validTo?: Date,
|
||||
addedWho?: string,
|
||||
repUser?: User
|
||||
user?: User,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { AfterViewInit, Component, ViewChild } from '@angular/core';
|
||||
import { AfterViewInit, Component, ViewChild, inject } from '@angular/core';
|
||||
import { GuiColumn, GuiSelectedRow } from '@generic-ui/ngx-grid/gui/grid/src/core/api/gui.grid.public-api';
|
||||
import { UserTableComponent } from '../../components/tables/user-table/user-table.component';
|
||||
import { UserRepTableComponent } from '../../components/tables/user-rep-table/user-rep-table.component';
|
||||
@ -9,6 +9,8 @@ import { MatTabsModule, MatTabGroup } from '@angular/material/tabs';
|
||||
import { env } from '../../../environments/environment';
|
||||
import { BasePageComponent } from '../base-page/base-page.component';
|
||||
import { UserRep } from '../../models/user-management.api.models';
|
||||
import { RepCreateFormComponent } from '../../components/forms/rep-create-form/rep-create-form.component';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@ -28,6 +30,8 @@ export class UserRepresentationComponent extends BasePageComponent implements Af
|
||||
slRepGroupId?: number;
|
||||
slRepId?: number;
|
||||
|
||||
private readonly dialog: MatDialog = inject(MatDialog);
|
||||
|
||||
initWithoutData = () => { }
|
||||
|
||||
constructor(private userRepService: UserRepService) {
|
||||
@ -100,9 +104,12 @@ export class UserRepresentationComponent extends BasePageComponent implements Af
|
||||
userId: this.slUserId,
|
||||
groupId: this.slGroupId,
|
||||
repUserId: this.slRepUserId,
|
||||
validFrom: new Date(),
|
||||
validTo: new Date(new Date().setDate(new Date().getDate() + 7))
|
||||
}
|
||||
this.userRepService.create(newUserRep).subscribe({
|
||||
next: (response) => {
|
||||
|
||||
this.openCreateSheet(newUserRep, res => {
|
||||
if (res.successful) {
|
||||
this.slRepUserId = undefined;
|
||||
|
||||
this.repUsers.safelyUnselectAll()
|
||||
@ -111,8 +118,8 @@ export class UserRepresentationComponent extends BasePageComponent implements Af
|
||||
this.userReps.fetchByUser(this.slUserId)
|
||||
if (this.slGroupId)
|
||||
this.userReps.fetchByGroup(this.slGroupId)
|
||||
},
|
||||
error: (error) => {
|
||||
}
|
||||
else if (res.error) {
|
||||
Swal.fire({
|
||||
icon: "error",
|
||||
title: "Oops...",
|
||||
@ -151,8 +158,9 @@ export class UserRepresentationComponent extends BasePageComponent implements Af
|
||||
groupId: this.slGroupId,
|
||||
repGroupId: this.slRepGroupId,
|
||||
}
|
||||
this.userRepService.create(newUserRep).subscribe({
|
||||
next: (res) => {
|
||||
|
||||
this.openCreateSheet(newUserRep, res => {
|
||||
if (res.successful) {
|
||||
this.slRepGroupId = undefined;
|
||||
this.repUsers.safelyUnselectAll()
|
||||
this.groups.safelyUnselectAll()
|
||||
@ -160,8 +168,8 @@ export class UserRepresentationComponent extends BasePageComponent implements Af
|
||||
this.userReps.fetchByUser(this.slUserId)
|
||||
if (this.slGroupId)
|
||||
this.userReps.fetchByGroup(this.slGroupId)
|
||||
},
|
||||
error: (error) => {
|
||||
}
|
||||
else if (res.error) {
|
||||
Swal.fire({
|
||||
icon: "error",
|
||||
title: "Oops...",
|
||||
@ -204,4 +212,12 @@ export class UserRepresentationComponent extends BasePageComponent implements Af
|
||||
this.slRepId = rows[0].source?.id;
|
||||
}
|
||||
}
|
||||
|
||||
openCreateSheet(userRep: UserRep, afterCreation: (any: any) => any): void {
|
||||
|
||||
this.dialog.open(RepCreateFormComponent, {
|
||||
width: "50rem",
|
||||
data: { userRep: userRep, afterCreation: afterCreation }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,6 +165,14 @@ export const env = {
|
||||
header: "Repr. Benutzer",
|
||||
field: (ur: any) => ur.repUser?.username
|
||||
},
|
||||
{
|
||||
header: "Gültig von",
|
||||
field: (ur: any) => new Date(ur.validFrom).toLocaleDateString('de-DE')
|
||||
},
|
||||
{
|
||||
header: "Gültig bis",
|
||||
field: (ur: any) => new Date(ur.validTo).toLocaleDateString('de-DE')
|
||||
}
|
||||
]
|
||||
},
|
||||
config_url: "/assets/config.json",
|
||||
@ -188,4 +196,4 @@ export const env = {
|
||||
{ value: "en-US", name: "en-US" }
|
||||
]
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@ -100,6 +100,6 @@ code {
|
||||
|
||||
@for $i from 1 through 20 {
|
||||
.w#{$i * 5}p {
|
||||
width: #{$i * 5 + "%"};
|
||||
width: #{$i * 5 + "%"} !important;
|
||||
}
|
||||
}
|
||||
@ -40,6 +40,7 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DigitalData.Core.API" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.20" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.16" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.15">
|
||||
@ -48,6 +49,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.15" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.3.2" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="5.3.11" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
@ -63,7 +65,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="ClientApp\" />
|
||||
<Folder Include="Models\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@ -9,6 +9,7 @@ using DigitalData.Core.API;
|
||||
using DigitalData.UserManager.API.Controllers;
|
||||
using DigitalData.UserManager.Application.Services;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
|
||||
logger.Debug("init main");
|
||||
@ -25,8 +26,16 @@ try {
|
||||
|
||||
builder.Logging.ClearProviders();
|
||||
builder.Host.UseNLog();
|
||||
|
||||
builder.Services.AddControllers();
|
||||
|
||||
builder.Services.AddControllers(opt =>
|
||||
{
|
||||
opt.Conventions.Add(new RemoveIfControllerConvention()
|
||||
.AndIf(c => c.ControllerName == nameof(EncryptionController).Replace("Controller", ""))
|
||||
.AndIf(c => !config.GetValue<bool>("UseEncryptor")));
|
||||
}).AddNewtonsoftJson(options =>
|
||||
{
|
||||
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
|
||||
});
|
||||
|
||||
if (builder.Configuration.GetValue<bool>("UseSwagger"))
|
||||
{
|
||||
|
||||
@ -10,8 +10,8 @@ namespace DigitalData.UserManager.Application.DTOs.UserRep
|
||||
int? GroupId,
|
||||
int? RepUserId,
|
||||
int? RepGroupId,
|
||||
DateTime ValidFrom,
|
||||
DateTime ValidTo,
|
||||
DateTime? ValidFrom,
|
||||
DateTime? ValidTo,
|
||||
string AddedWho,
|
||||
string? ChangedWho,
|
||||
UserReadDto? User,
|
||||
|
||||
@ -20,11 +20,11 @@ namespace DigitalData.UserManager.Domain.Entities
|
||||
|
||||
[Required]
|
||||
[Column("VALID_FROM")]
|
||||
public required DateTime ValidFrom { get; set; }
|
||||
public required DateTime? ValidFrom { get; set; }
|
||||
|
||||
[Required]
|
||||
[Column("VALID_TO")]
|
||||
public required DateTime ValidTo { get; set; }
|
||||
public required DateTime? ValidTo { get; set; }
|
||||
|
||||
[ForeignKey("UserId")]
|
||||
public virtual User? User { get; set; }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user