diff --git a/ogWebconsole/src/app/components/ogdhcp/add-clients-to-subnet/add-clients-to-subnet.component.ts b/ogWebconsole/src/app/components/ogdhcp/add-clients-to-subnet/add-clients-to-subnet.component.ts
index 19d83fb..9d9423d 100644
--- a/ogWebconsole/src/app/components/ogdhcp/add-clients-to-subnet/add-clients-to-subnet.component.ts
+++ b/ogWebconsole/src/app/components/ogdhcp/add-clients-to-subnet/add-clients-to-subnet.component.ts
@@ -7,6 +7,7 @@ import { FormControl } from '@angular/forms';
import { ToastrService } from 'ngx-toastr';
import { OperationResultDialogComponent } from "../operation-result-dialog/operation-result-dialog.component";
import { ConfigService } from '@services/config.service';
+import { DataService as GroupsDataService } from "../../groups/services/data.service";
@Component({
selector: 'app-add-clients-to-subnet',
@@ -23,15 +24,7 @@ export class AddClientsToSubnetComponent implements OnInit {
unitControl = new FormControl();
childUnitControl = new FormControl();
allSelected: boolean = false;
- unitSearchText: string = '';
- getFilteredUnits(): any[] {
- if (!this.unitSearchText) {
- return this.units;
- }
- const searchText = this.unitSearchText.toLowerCase();
- return this.units.filter(unit => unit.displayName.toLowerCase().includes(searchText));
- }
constructor(
private http: HttpClient,
@@ -39,6 +32,7 @@ export class AddClientsToSubnetComponent implements OnInit {
private toastService: ToastrService,
public dialog: MatDialog,
private configService: ConfigService,
+ private groupsDataService: GroupsDataService,
@Inject(MAT_DIALOG_DATA) public data: { subnetUuid: string, subnetName: string }
) {
this.baseUrl = this.configService.apiUrl;
@@ -55,26 +49,20 @@ export class AddClientsToSubnetComponent implements OnInit {
const rawUnits = response['hydra:member'];
this.units = rawUnits.map((unit: any) => ({
...unit,
- displayName: this.buildFullDisplayName(unit, rawUnits)
+ name: unit.name,
+ path: this.groupsDataService.getOrganizationalUnitPath(unit, rawUnits)
}));
- this.units.sort((a, b) => a.displayName.localeCompare(b.displayName));
+ this.units.sort((a, b) => {
+ const pathA = a.path || a.name;
+ const pathB = b.path || b.name;
+ return pathA.localeCompare(pathB);
+ });
this.loading = false;
},
error => console.error(this.translate.instant('errorFetchingOrganizationalUnits1'), error)
);
}
- private buildFullDisplayName(unit: any, allUnits: any[]): string {
- let hierarchy = unit.name;
- let currentParent = unit.parent;
-
- while (currentParent) {
- hierarchy = `${currentParent.name} / ${hierarchy}`;
- const fullParent = allUnits.find((u: any) => u['@id'] === currentParent['@id']);
- currentParent = fullParent ? fullParent.parent : null;
- }
- return hierarchy;
- }
loadChildUnits(event: any) {
this.http.get
(`${this.baseUrl}/clients?organizationalUnit.id=${event.value.id}&exists[subnet]=false`).subscribe(
diff --git a/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.css b/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.css
new file mode 100644
index 0000000..f8a4299
--- /dev/null
+++ b/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.css
@@ -0,0 +1,11 @@
+:host {
+ display: block;
+ width: 100%;
+}
+.full-width {
+ width: 100%;
+}
+.unit-name {
+ line-height: normal;
+ padding-top: 4px;
+}
diff --git a/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.html b/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.html
new file mode 100644
index 0000000..12791ac
--- /dev/null
+++ b/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.html
@@ -0,0 +1,21 @@
+
+ {{ label | translate }}
+
+
+ {{ getSelectedName() }}
+
+
+
+
+ @for (unit of filteredUnits; track (unit.id || unit['@id'])) {
+
+ {{ unit.name }}
+ @if (unit.path) {
+ {{ unit.path }}
+ }
+
+ }
+
+
diff --git a/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.spec.ts b/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.spec.ts
new file mode 100644
index 0000000..f3493e6
--- /dev/null
+++ b/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { OuSelectComponent } from './ou-select.component';
+
+describe('OuSelectComponent', () => {
+ let component: OuSelectComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [OuSelectComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(OuSelectComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.ts b/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.ts
new file mode 100644
index 0000000..11b4e90
--- /dev/null
+++ b/ogWebconsole/src/app/components/shared/ou-select/ou-select.component.ts
@@ -0,0 +1,77 @@
+import { Component, Input, Output, EventEmitter, forwardRef } from '@angular/core';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+
+@Component({
+ selector: 'app-ou-select',
+ templateUrl: './ou-select.component.html',
+ styleUrls: ['./ou-select.component.css'],
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => OuSelectComponent),
+ multi: true
+ }
+ ]
+})
+export class OuSelectComponent implements ControlValueAccessor {
+ @Input() units: any[] = [];
+ @Input() multiple = false;
+ @Input() required = false;
+ @Input() disabled = false;
+ @Input() label: string = 'labelOrganizationalUnit';
+
+ @Output() selectionChange = new EventEmitter();
+
+ value: any = null;
+ searchText: string = '';
+
+ get filteredUnits() {
+ if (!this.searchText) {
+ return this.units;
+ }
+ const lower = this.searchText.toLowerCase();
+ return this.units.filter(unit =>
+ unit.name.toLowerCase().includes(lower) ||
+ (unit.path && unit.path.toLowerCase().includes(lower))
+ );
+ }
+
+ onOpened() {
+ this.searchText = '';
+ }
+
+ onChange = (val: any) => {};
+ onTouched = () => {};
+
+ writeValue(val: any): void {
+ this.value = val;
+ }
+
+ registerOnChange(fn: any): void {
+ this.onChange = fn;
+ }
+
+ registerOnTouched(fn: any): void {
+ this.onTouched = fn;
+ }
+
+ setDisabledState?(isDisabled: boolean): void {
+ this.disabled = isDisabled;
+ }
+
+ onSelectionChange(event: any) {
+ this.value = event.value;
+ this.onChange(this.value);
+ this.selectionChange.emit(event);
+ this.onTouched();
+ }
+
+ getSelectedName(): string {
+ if (this.multiple) {
+ if (!this.value || !Array.isArray(this.value)) return '';
+ return this.units.filter(u => this.value.includes(u.id || u['@id'])).map(u => u.name).join(', ');
+ } else {
+ return this.units.find(u => (u.id || u['@id']) === this.value)?.name || '';
+ }
+ }
+}