diff --git a/alfa-client/libs/admin-settings/src/lib/admin-settings.module.ts b/alfa-client/libs/admin-settings/src/lib/admin-settings.module.ts
index 996078e28fafa84a077ffd79ad3810a3a8fb2e86..414a929008988e7cddd1dff320d5c941f3fc1d4a 100644
--- a/alfa-client/libs/admin-settings/src/lib/admin-settings.module.ts
+++ b/alfa-client/libs/admin-settings/src/lib/admin-settings.module.ts
@@ -20,6 +20,9 @@ import { NavigationComponent } from './navigation/navigation.component';
 import { OrganisationseinheitNavigationItemComponent } from './organisationseinheit/organisationseinheit-navigation-item/organisationseinheit-navigation-item.component';
 import KcAdminClient from '@keycloak/keycloak-admin-client';
 import { Environment, ENVIRONMENT_CONFIG } from '@alfa-client/environment-shared';
+import { MoreMenuComponent } from './shared/more-menu/more-menu.component';
+import { MoreItemButtonComponent } from './shared/more-menu/more-item-button/more-item-button.component';
+import { SpinnerComponent } from './shared/spinner/spinner.component';
 
 @NgModule({
   declarations: [
@@ -35,6 +38,9 @@ import { Environment, ENVIRONMENT_CONFIG } from '@alfa-client/environment-shared
     SecondaryButtonComponent,
     OrganisationseinheitNavigationItemComponent,
     OrganisationseinheitListComponent,
+    MoreMenuComponent,
+    MoreItemButtonComponent,
+    SpinnerComponent,
   ],
   imports: [CommonModule, TechSharedModule, RouterModule, ReactiveFormsModule],
   exports: [
diff --git a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.model.ts b/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.model.ts
index 16ab31946760373a9df52b0f0c5ef6dd8ef7590c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.model.ts
+++ b/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.model.ts
@@ -1,22 +0,0 @@
-export interface KeycloakGroup {
-  id: string;
-  name: string;
-  organisationseinheitIds: string[];
-}
-
-export interface KeycloakGroupState {
-  groups: KeycloakGroup[];
-  loading: boolean;
-  updateRequired: boolean;
-}
-
-export enum KeycloakAdminErrorType {
-  NAME_CONFLICT = 'name-conflict',
-  NAME_MISSING = 'name-missing',
-  ID_MISSING = 'id-missing',
-}
-
-export interface KeycloakAdminError {
-  errorType: KeycloakAdminErrorType;
-  detail: string;
-}
diff --git a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.repository.spec.ts b/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.repository.spec.ts
deleted file mode 100644
index f7a19bb2af16a46417459302d5fae8fcdf2e3d35..0000000000000000000000000000000000000000
--- a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.repository.spec.ts
+++ /dev/null
@@ -1,190 +0,0 @@
-import { fakeAsync, TestBed, tick } from '@angular/core/testing';
-import { KeycloakRepository } from './keycloak.repository';
-import KcAdminClient, { NetworkError } from '@keycloak/keycloak-admin-client';
-import { Mock, mock } from '@alfa-client/test-utils';
-import {
-  createGroupRepresentation,
-  createKeycloakAdminError,
-  createKeycloakGroup,
-  createNetworkError,
-} from '../../../test/keycloak/keycloak';
-import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';
-import { KeycloakAdminError, KeycloakAdminErrorType, KeycloakGroup } from './keycloak.model';
-import { TokenProvider } from '@keycloak/keycloak-admin-client/lib/client';
-import { firstValueFrom, of } from 'rxjs';
-import { faker } from '@faker-js/faker';
-import { OAuthService } from 'angular-oauth2-oidc';
-import { Groups } from '@keycloak/keycloak-admin-client/lib/resources/groups';
-
-describe('KeycloakRepository', () => {
-  const accessToken: string = faker.random.alphaNumeric(40);
-  let repository: KeycloakRepository;
-
-  let kcAdminClient: Mock<KcAdminClient>;
-  let oAuthService: Mock<OAuthService>;
-
-  const mockGroupsFunc = (groupsKey: keyof Groups, implementation: jest.Mock) => {
-    kcAdminClient.groups = <any>{
-      [groupsKey]: implementation,
-    };
-  };
-
-  beforeEach(() => {
-    kcAdminClient = mock(KcAdminClient);
-    oAuthService = mock(OAuthService);
-    TestBed.configureTestingModule({
-      providers: [
-        { provide: OAuthService, useValue: oAuthService },
-        { provide: KcAdminClient, useValue: kcAdminClient },
-      ],
-    });
-    oAuthService.getAccessToken.mockReturnValue(accessToken);
-    repository = TestBed.inject(KeycloakRepository);
-  });
-
-  it('should be created', () => {
-    expect(repository).toBeTruthy();
-  });
-
-  describe('registerTokenProvider', () => {
-    it('should register token provider from oauth service', async () => {
-      const tokenProvider: TokenProvider = kcAdminClient.registerTokenProvider.mock.calls[0][0];
-      const token: string = await tokenProvider.getAccessToken();
-      expect(token).toEqual(accessToken);
-    });
-  });
-
-  describe('map group representation', () => {
-    let group: KeycloakGroup = createKeycloakGroup();
-
-    it('should map field "id"', () => {
-      const keycloakGroup: KeycloakGroup = repository.mapGroupRepresentation({ id: group.id });
-
-      expect(keycloakGroup.id).toEqual(group.id);
-    });
-
-    it('should map field "name"', () => {
-      const keycloakGroup: KeycloakGroup = repository.mapGroupRepresentation({ name: group.name });
-
-      expect(keycloakGroup.name).toEqual(group.name);
-    });
-
-    it('should map field "organisationseinheitIds"', () => {
-      const keycloakGroup: KeycloakGroup = repository.mapGroupRepresentation({
-        attributes: { organisationseinheitId: group.organisationseinheitIds },
-      });
-
-      expect(keycloakGroup.organisationseinheitIds).toEqual(group.organisationseinheitIds);
-    });
-
-    it('should map missing organisationseinheitIds to empty list', () => {
-      const keycloakGroup: KeycloakGroup = repository.mapGroupRepresentation({});
-
-      expect(keycloakGroup.organisationseinheitIds).toEqual([]);
-    });
-  });
-
-  describe('find groups', () => {
-    const groups: KeycloakGroup[] = [
-      createKeycloakGroup(),
-      createKeycloakGroup(),
-      createKeycloakGroup(),
-    ];
-
-    const groupReps: GroupRepresentation[] = groups.map(createGroupRepresentation);
-
-    it('should return mapped group search result', async () => {
-      const findMock: jest.Mock = jest.fn().mockReturnValue(Promise.resolve(groupReps));
-      mockGroupsFunc('find', findMock);
-
-      const groupsResult: KeycloakGroup[] = await firstValueFrom(repository.findGroups());
-
-      expect(groupsResult).toEqual(groupsResult);
-    });
-
-    it('should call with brief representation', fakeAsync(() => {
-      const findMock: jest.Mock = jest.fn().mockReturnValue(Promise.resolve(groupReps));
-      mockGroupsFunc('find', findMock);
-
-      repository.findGroups().subscribe();
-      tick();
-
-      expect(findMock).toHaveBeenCalledWith({ briefRepresentation: false });
-    }));
-  });
-
-  describe('create group', () => {
-    const newGroup: KeycloakGroup = createKeycloakGroup();
-
-    it('should call kcAdminClient.groups.create', async () => {
-      const createMock: jest.Mock = jest.fn(() => of({ id: newGroup.id }));
-      mockGroupsFunc('create', createMock);
-
-      await firstValueFrom(repository.createGroup(newGroup.name, newGroup.organisationseinheitIds));
-
-      expect(createMock).toHaveBeenCalledWith({
-        name: newGroup.name,
-        attributes: {
-          organisationseinheitId: newGroup.organisationseinheitIds,
-        },
-      });
-    });
-
-    it('should return mapped group create result', async () => {
-      const createMock: jest.Mock = jest.fn(() => Promise.resolve({ id: newGroup.id }));
-      mockGroupsFunc('create', createMock);
-
-      const newGroupResult: KeycloakGroup = await firstValueFrom(
-        repository.createGroup(newGroup.name, newGroup.organisationseinheitIds),
-      );
-
-      expect(newGroupResult).toEqual(newGroup);
-    });
-
-    it('should map network error', (done) => {
-      const createMock: jest.Mock = jest.fn(() => Promise.reject(createNetworkError(400, '')));
-      mockGroupsFunc('create', createMock);
-
-      const error: KeycloakAdminError = createKeycloakAdminError();
-      repository.mapCreateGroupsNetworkError = jest.fn().mockReturnValue(error);
-
-      repository.createGroup(newGroup.name, newGroup.organisationseinheitIds).subscribe({
-        error: (err) => {
-          expect(err).toBe(error);
-          done();
-        },
-      });
-    });
-  });
-
-  describe('map create groups network error', () => {
-    it('should interpret 409 status as name conflict', () => {
-      const keycloakError: KeycloakAdminError = createKeycloakAdminError(
-        KeycloakAdminErrorType.NAME_CONFLICT,
-      );
-      const networkError: NetworkError = createNetworkError(409, keycloakError.detail);
-
-      const error: KeycloakAdminError = repository.mapCreateGroupsNetworkError(networkError);
-
-      expect(error).toEqual(keycloakError);
-    });
-
-    it('should interpret 400 status as name missing', () => {
-      const keycloakError: KeycloakAdminError = createKeycloakAdminError(
-        KeycloakAdminErrorType.NAME_MISSING,
-      );
-      const networkError: NetworkError = createNetworkError(400, keycloakError.detail);
-
-      const error: KeycloakAdminError = repository.mapCreateGroupsNetworkError(networkError);
-
-      expect(error).toEqual(keycloakError);
-    });
-
-    it('should map missing errorMessage to empty string', () => {
-      const networkError: NetworkError = createNetworkError(500, undefined);
-
-      const error: KeycloakAdminError = repository.mapCreateGroupsNetworkError(networkError);
-      expect(error.detail).toEqual('');
-    });
-  });
-});
diff --git a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.service.spec.ts b/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.service.spec.ts
deleted file mode 100644
index 6fc73174dfaf2d3bc7fc7f9e4237af40231754f3..0000000000000000000000000000000000000000
--- a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.service.spec.ts
+++ /dev/null
@@ -1,190 +0,0 @@
-import { KeycloakService } from './keycloak.service';
-import { KeycloakRepository } from './keycloak.repository';
-import { mock, Mock, useFromMock } from '@alfa-client/test-utils';
-import { createKeycloakGroup } from '../../../test/keycloak/keycloak';
-import { firstValueFrom, lastValueFrom, of } from 'rxjs';
-import { KeycloakGroup, KeycloakGroupState } from './keycloak.model';
-import { cold } from 'jest-marbles';
-import { fakeAsync, tick } from '@angular/core/testing';
-
-describe('KeycloakService', () => {
-  let service: KeycloakService;
-  let repository: Mock<KeycloakRepository>;
-  const sortedNames: string[] = ['BBBB', 'CCCC', 'XXXX'];
-  const sortedGroups: KeycloakGroup[] = sortedNames.map((name) => ({
-    ...createKeycloakGroup(),
-    name,
-  }));
-  const unsortedGroups: KeycloakGroup[] = [sortedGroups[2], sortedGroups[0], sortedGroups[1]];
-
-  beforeEach(() => {
-    repository = mock(KeycloakRepository);
-    service = new KeycloakService(useFromMock(repository));
-  });
-
-  it('should be created', () => {
-    expect(service).toBeTruthy();
-  });
-
-  describe('initial state', () => {
-    it('should have empty group list', () => {
-      expect(service.groupState$.value.groups).toEqual([]);
-    });
-    it('should not be loading', () => {
-      expect(service.groupState$.value.loading).toEqual(false);
-    });
-    it('should be requiring a reload', () => {
-      expect(service.groupState$.value.updateRequired).toEqual(true);
-    });
-  });
-
-  describe('get group state', () => {
-    it('should update if required', async () => {
-      service.updateIfRequired = jest.fn();
-
-      await firstValueFrom(service.getGroupState());
-
-      expect(service.updateIfRequired).toHaveBeenCalled();
-    });
-
-    it('should call find groups', fakeAsync(() => {
-      repository.findGroups.mockReturnValue(of(unsortedGroups));
-
-      service.getGroupState().subscribe();
-      tick();
-
-      expect(repository.findGroups).toHaveBeenCalled();
-    }));
-  });
-
-  describe('update if required', () => {
-    beforeEach(() => {
-      service.updateGroups = jest.fn(() => of([]));
-    });
-
-    it('should call update groups with initial values', () => {
-      service.updateIfRequired();
-
-      expect(service.updateGroups).toHaveBeenCalled();
-    });
-
-    it('should not call update groups if loading', () => {
-      service.setLoading();
-
-      service.updateIfRequired();
-
-      expect(service.updateGroups).not.toHaveBeenCalled();
-    });
-
-    it('should not call update groups if not requiring update', () => {
-      service.groupState$.next({
-        ...service.groupState$.value,
-        updateRequired: false,
-      });
-
-      service.updateIfRequired();
-
-      expect(service.updateGroups).not.toHaveBeenCalled();
-    });
-  });
-
-  describe('update groups', () => {
-    beforeEach(() => {
-      repository.findGroups.mockReturnValue(of(unsortedGroups));
-    });
-
-    it('should set loading', () => {
-      service.updateGroups();
-
-      expect(service.groupState$.value.loading).toBeTruthy();
-    });
-
-    it('should set sorted groups', async () => {
-      await lastValueFrom(service.updateGroups());
-
-      expect(service.groupState$.value.groups).toEqual(sortedGroups);
-    });
-
-    it('should not require update afterward', async () => {
-      await lastValueFrom(service.updateGroups());
-
-      expect(service.groupState$.value.updateRequired).toBeFalsy();
-    });
-  });
-
-  describe('create group', () => {
-    const newTopGroup: KeycloakGroup = {
-      ...createKeycloakGroup(),
-      name: 'AAAA',
-    };
-    const newBottomGroup: KeycloakGroup = {
-      ...createKeycloakGroup(),
-      name: 'ZZZZ',
-    };
-
-    beforeEach(() => {
-      repository.createGroup.mockReturnValue(of(newTopGroup));
-    });
-
-    it('should set loading', () => {
-      service.createGroup(newTopGroup.name, newTopGroup.organisationseinheitIds);
-
-      expect(service.groupState$.value.loading).toBe(true);
-    });
-
-    it('should call repository for save', () => {
-      service.createGroup(newTopGroup.name, newTopGroup.organisationseinheitIds);
-
-      expect(repository.createGroup).toHaveBeenCalledWith(
-        newTopGroup.name,
-        newTopGroup.organisationseinheitIds,
-      );
-    });
-
-    it('should end progress after request completes', () => {
-      repository.createGroup.mockReturnValue(cold('-a|', { a: newTopGroup }));
-
-      const progressObservable = service.createGroup(
-        newTopGroup.name,
-        newTopGroup.organisationseinheitIds,
-      );
-
-      expect(progressObservable).toBeObservable(cold('ab|', { a: true, b: false }));
-    });
-
-    describe('without existing groups', () => {
-      it('should insert group into sorted groups', (done) => {
-        service.createGroup(newTopGroup.name, newTopGroup.organisationseinheitIds).subscribe(() => {
-          const state: KeycloakGroupState = service.groupState$.value;
-          expect(state.groups).toEqual([newTopGroup]);
-          done();
-        });
-      });
-    });
-
-    describe('with existing groups', () => {
-      beforeEach(async () => {
-        repository.findGroups.mockReturnValue(of(unsortedGroups));
-        await firstValueFrom(service.updateGroups());
-      });
-
-      it('should insert top group into sorted groups', async () => {
-        await lastValueFrom(
-          service.createGroup(newTopGroup.name, newTopGroup.organisationseinheitIds),
-        );
-
-        expect(service.groupState$.value.groups).toEqual([newTopGroup, ...sortedGroups]);
-      });
-
-      it('should insert bottom group into sorted groups', async () => {
-        repository.createGroup.mockReturnValue(of(newBottomGroup));
-
-        await lastValueFrom(
-          service.createGroup(newBottomGroup.name, newBottomGroup.organisationseinheitIds),
-        );
-
-        expect(service.groupState$.value.groups).toEqual([...sortedGroups, newBottomGroup]);
-      });
-    });
-  });
-});
diff --git a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.service.ts b/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.service.ts
deleted file mode 100644
index 45e1574289af98628986ad1bf1bc812d6873acda..0000000000000000000000000000000000000000
--- a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.service.ts
+++ /dev/null
@@ -1,74 +0,0 @@
-import { Injectable } from '@angular/core';
-import { KeycloakGroup, KeycloakGroupState } from './keycloak.model';
-import { BehaviorSubject, first, map, Observable, startWith, tap } from 'rxjs';
-import { KeycloakRepository } from './keycloak.repository';
-
-@Injectable({
-  providedIn: 'root',
-})
-export class KeycloakService {
-  readonly groupState$: BehaviorSubject<KeycloakGroupState> = new BehaviorSubject({
-    groups: [],
-    loading: false,
-    updateRequired: true,
-  });
-
-  constructor(private keycloakAdminRepository: KeycloakRepository) {}
-
-  public createGroup(name: string, organisationseinheitIds: string[]): Observable<boolean> {
-    this.setLoading();
-
-    return this.keycloakAdminRepository.createGroup(name, organisationseinheitIds).pipe(
-      tap((group) => {
-        this.addGroupAfterLoading(group);
-      }),
-      map(() => this.groupState$.value.loading),
-      startWith(this.groupState$.value.loading),
-    );
-  }
-
-  private addGroupAfterLoading(group: KeycloakGroup): void {
-    this.setGroupsAfterLoading([...this.groupState$.value.groups, group]);
-  }
-
-  private setGroupsAfterLoading(groups: KeycloakGroup[]): void {
-    this.groupState$.next({
-      loading: false,
-      updateRequired: false,
-      groups: this.sortedGroups(groups),
-    });
-  }
-
-  private sortedGroups(groups: KeycloakGroup[]): KeycloakGroup[] {
-    return [...groups].sort((a, b) => a.name.localeCompare(b.name));
-  }
-
-  public getGroupState(): Observable<KeycloakGroupState> {
-    return this.groupState$.pipe(tap(() => this.updateIfRequired()));
-  }
-
-  updateIfRequired(): void {
-    if (this.isUpdateRequired(this.groupState$.value)) {
-      this.updateGroups().pipe(first()).subscribe();
-    }
-  }
-
-  private isUpdateRequired(state: KeycloakGroupState): boolean {
-    return state.updateRequired && !state.loading;
-  }
-
-  updateGroups(): Observable<KeycloakGroup[]> {
-    this.setLoading();
-
-    return this.keycloakAdminRepository
-      .findGroups()
-      .pipe(tap((groups: KeycloakGroup[]) => this.setGroupsAfterLoading(groups)));
-  }
-
-  setLoading(): void {
-    this.groupState$.next({
-      ...this.groupState$.value,
-      loading: true,
-    });
-  }
-}
diff --git a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.util.spec.ts b/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.util.spec.ts
deleted file mode 100644
index 12db5454b918cd2904d3260c689b5e08e6a46a62..0000000000000000000000000000000000000000
--- a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.util.spec.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { createKeycloakAdminError } from '../../../test/keycloak/keycloak';
-import { KeycloakAdminError, KeycloakAdminErrorType } from './keycloak.model';
-import { getKeycloakAdminErrorMessage, KEYCLOAK_ERROR_MESSAGES } from './keycloak.util';
-
-describe('get keycloak admin error message', () => {
-  it('should map known error message', () => {
-    const nameConflictError: KeycloakAdminError = createKeycloakAdminError(
-      KeycloakAdminErrorType.NAME_CONFLICT,
-    );
-    const expectedMessage: string = KEYCLOAK_ERROR_MESSAGES[nameConflictError.errorType];
-
-    const message: string = getKeycloakAdminErrorMessage(nameConflictError);
-    expect(message).toEqual(expectedMessage);
-  });
-
-  it('should map unknown error message to empty string', () => {
-    const nameConflictError: KeycloakAdminError = createKeycloakAdminError(null);
-
-    const message: string = getKeycloakAdminErrorMessage(nameConflictError);
-    expect(message).toEqual('');
-  });
-});
diff --git a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.util.ts b/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.util.ts
index 3607afae0a2445759b40722ae0256f50f144faad..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.util.ts
+++ b/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.util.ts
@@ -1,16 +0,0 @@
-import { KeycloakAdminError, KeycloakAdminErrorType } from './keycloak.model';
-
-export const KEYCLOAK_ERROR_MESSAGES: { [type: string]: string } = {
-  [KeycloakAdminErrorType.NAME_CONFLICT]: 'Der Name exisitert bereits.',
-  [KeycloakAdminErrorType.NAME_MISSING]: 'Bitte den Namen angeben.',
-  [KeycloakAdminErrorType.ID_MISSING]: 'Bitte mindestens eine Organisationseinheit ID angeben.',
-};
-
-export const KEYCLOAK_CREATE_GROUPS_ERROR_STATUS: { [status: number]: KeycloakAdminErrorType } = {
-  409: KeycloakAdminErrorType.NAME_CONFLICT,
-  400: KeycloakAdminErrorType.NAME_MISSING,
-};
-
-export function getKeycloakAdminErrorMessage(error: KeycloakAdminError): string {
-  return KEYCLOAK_ERROR_MESSAGES[error.errorType] ?? '';
-}
diff --git a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.html b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.html
index b0cdfccd4cd7bb7cf4d0a51633810090039390e2..dbc6d9eddd9d63fb982da496a7a4636210670ce8 100644
--- a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.html
+++ b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.html
@@ -1,24 +1,24 @@
 <h1 class="text-2xl font-bold">Organisationseinheiten</h1>
 <p id="absender-desc" class="p-1">Hinterlegen Sie Name und ID der Organisationseinheiten.</p>
 
-<dialog
-  #NewOrganisationseinheitDialog
-  data-test-id="organisationseinheit-dialog"
-  class="bg-gray-50"
->
-  <admin-organisationseinheit-form
-    data-test-id="organisationseinheit-form"
-    (close)="NewOrganisationseinheitDialog.close()"
-  ></admin-organisationseinheit-form>
-</dialog>
+<admin-organisationseinheit-form
+  data-test-id="organisationseinheit-form"
+></admin-organisationseinheit-form>
 
 <admin-secondary-button
-  (clickEmitter)="NewOrganisationseinheitDialog.showModal()"
+  (clickEmitter)="openDialogForNewGroup()"
   data-test-id="organisationseinheit-open-dialog-button"
   label="Neue Organisationseinheit anlegen"
 >
 </admin-secondary-button>
+<admin-spinner
+  data-test-id="organisationseinheit-spinner"
+  *ngIf="deleteInProgress$ | async"
+></admin-spinner>
 
 <admin-organisationseinheit-list
-  [groups]="(groupState$ | async).groups"
+  [organisationseinheitItems]="organisationseinheitItems$ | async"
+  (editOrganisationseinheit)="edit($event)"
+  (deleteOrganisationseinheit)="delete($event)"
+  data-test-id="organisationseinheit-list"
 ></admin-organisationseinheit-list>
diff --git a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.spec.ts
index 4b714bb4686c6708579c4286169ffe63c78e019e..3d5ccfed1a905798d750cdf3487c8eae5b71c654 100644
--- a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.spec.ts
+++ b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.spec.ts
@@ -6,31 +6,38 @@ import { SecondaryButtonComponent } from '../../shared/secondary-button/secondar
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import {
   dispatchEventFromFixture,
-  getElementFromFixture,
+  existsAsHtmlElement,
   getElementFromFixtureByType,
   mock,
   Mock,
+  notExistsAsHtmlElement,
 } from '@alfa-client/test-utils';
 import { OrganisationseinheitListComponent } from './organisationseinheit-list/organisationseinheit-list.component';
-import { KeycloakService } from '../../keycloak/keycloak.service';
+import { UserService } from '../../user/user.service';
 import { of } from 'rxjs';
 import {
-  createKeycloakGroup,
-  createKeycloakServiceState,
-} from '../../../../test/keycloak/keycloak';
-import { KeycloakGroup } from '../../keycloak/keycloak.model';
+  createOrganisationseinheit,
+  createOrganisationseinheitState,
+} from '../../../../test/user/user';
+import { Organisationseinheit } from '../../user/user.model';
+import { singleCold } from '../../../../../tech-shared/src/lib/resource/marbles';
+import { SpinnerComponent } from '../../shared/spinner/spinner.component';
 
 describe('OrganisationseinheitContainerComponent', () => {
   let component: OrganisationseinheitContainerComponent;
   let fixture: ComponentFixture<OrganisationseinheitContainerComponent>;
 
-  const keycloakService: Mock<KeycloakService> = mock(KeycloakService);
+  const userService: Mock<UserService> = mock(UserService);
 
-  const dialogOpenButtonSelector = getDataTestIdOf('organisationseinheit-open-dialog-button');
-  const dialogSelector = getDataTestIdOf('organisationseinheit-dialog');
-  const formSelector = getDataTestIdOf('organisationseinheit-form');
+  const dialogOpenButtonSelector: string = getDataTestIdOf(
+    'organisationseinheit-open-dialog-button',
+  );
+  const spinnerSelector: string = getDataTestIdOf('organisationseinheit-spinner');
 
-  const groups: KeycloakGroup[] = [createKeycloakGroup()];
+  const organisationseinheitItems: Organisationseinheit[] = [createOrganisationseinheit()];
+
+  let formComponent: OrganisationseinheitFormComponent;
+  let listComponent: OrganisationseinheitListComponent;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
@@ -39,58 +46,87 @@ describe('OrganisationseinheitContainerComponent', () => {
         MockComponent(SecondaryButtonComponent),
         MockComponent(OrganisationseinheitFormComponent),
         MockComponent(OrganisationseinheitListComponent),
+        MockComponent(SpinnerComponent),
       ],
-      providers: [{ provide: KeycloakService, useValue: keycloakService }],
+      providers: [{ provide: UserService, useValue: userService }],
     }).compileComponents();
 
     fixture = TestBed.createComponent(OrganisationseinheitContainerComponent);
     component = fixture.componentInstance;
 
-    keycloakService.getGroupState = jest.fn().mockReturnValue(of(createKeycloakServiceState(groups)));
+    userService.getOrganisationseinheitState = jest
+      .fn()
+      .mockReturnValue(of(createOrganisationseinheitState(organisationseinheitItems)));
+    fixture.detectChanges();
+
+    formComponent = getElementFromFixtureByType(fixture, OrganisationseinheitFormComponent);
+    listComponent = getElementFromFixtureByType(fixture, OrganisationseinheitListComponent);
   });
 
   it('should create', () => {
-    fixture.detectChanges();
-
     expect(component).toBeTruthy();
   });
 
-  it('should pass groups to list component', async () => {
-    fixture.detectChanges();
-    await fixture.whenStable();
+  it('should open form on new organisationseinheit button', () => {
+    formComponent.open = jest.fn();
+
+    dispatchEventFromFixture(fixture, dialogOpenButtonSelector, 'clickEmitter');
+
+    expect(formComponent.open).toHaveBeenCalled();
+  });
+
+  describe('organisationseinheit list', () => {
+    it('should open form for editing on editOrganisationseinheit event', () => {
+      const organisationseinheit: Organisationseinheit = organisationseinheitItems[0];
+      formComponent.openEdit = jest.fn();
+
+      listComponent.editOrganisationseinheit.emit(organisationseinheit);
 
-    const listComponent: OrganisationseinheitListComponent = getElementFromFixtureByType(
-      fixture,
-      OrganisationseinheitListComponent,
-    );
-    expect(listComponent.groups).toEqual(groups);
+      expect(formComponent.openEdit).toHaveBeenCalledWith(organisationseinheit);
+    });
+
+    it('should call deleteOrganisationseinheit form on deleteOrganisationseinheit event', () => {
+      const organisationseinheit: Organisationseinheit = organisationseinheitItems[0];
+      component.delete = jest.fn();
+
+      listComponent.deleteOrganisationseinheit.emit(organisationseinheit);
+
+      expect(component.delete).toHaveBeenCalledWith(organisationseinheit);
+    });
   });
 
-  describe('dialog', () => {
-    it('should initially be closed', () => {
-      const dialogElement: HTMLDialogElement = getElementFromFixture(
-        fixture,
-        dialogOpenButtonSelector,
-      );
-      expect(dialogElement.open).toBeFalsy();
+  describe('delete', () => {
+    const organisationseinheit: Organisationseinheit = organisationseinheitItems[0];
+
+    beforeEach(() => {
+      userService.deleteOrganisationseinheit = jest.fn().mockReturnValue(singleCold(true));
     });
 
-    it('should call showModal on button press', async () => {
-      const dialogElement: HTMLDialogElement = getElementFromFixture(fixture, dialogSelector);
-      dialogElement.showModal = jest.fn();
+    it('should call service method', () => {
+      component.delete(organisationseinheit);
 
-      dispatchEventFromFixture(fixture, dialogOpenButtonSelector, 'clickEmitter');
+      expect(userService.deleteOrganisationseinheit).toHaveBeenCalledWith(organisationseinheit.id);
+    });
+
+    it('should assign delete progress observable', () => {
+      component.delete(organisationseinheit);
 
-      expect(dialogElement.showModal).toHaveBeenCalled();
+      expect(component.deleteInProgress$).toBeObservable(singleCold(true));
     });
+  });
 
-    it('should call close on form close', async () => {
-      const dialogElement: HTMLDialogElement = getElementFromFixture(fixture, dialogSelector);
-      dialogElement.close = jest.fn();
+  describe('spinner', () => {
+    it('should not show if delete in not progress', () => {
+      fixture.detectChanges();
+
+      notExistsAsHtmlElement(fixture, spinnerSelector);
+    });
+    it('should show if delete in progress', () => {
+      component.deleteInProgress$ = of(true);
 
-      dispatchEventFromFixture(fixture, formSelector, 'close');
+      fixture.detectChanges();
 
-      expect(dialogElement.close).toHaveBeenCalled();
+      existsAsHtmlElement(fixture, spinnerSelector);
     });
   });
 });
diff --git a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.ts b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.ts
index 4c2d957e60bdcf15d03822543984d3a7de8cdc86..efa637313dfce71fe1904be3658658cb2dd34518 100644
--- a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.ts
+++ b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-container.component.ts
@@ -1,18 +1,35 @@
-import { Component, OnInit } from '@angular/core';
-import { KeycloakGroupState } from '../../keycloak/keycloak.model';
-import { KeycloakService } from '../../keycloak/keycloak.service';
-import { Observable } from 'rxjs';
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { Organisationseinheit } from '../../user/user.model';
+import { UserService } from '../../user/user.service';
+import { Observable, of } from 'rxjs';
+import { OrganisationseinheitFormComponent } from './organisationseinheit-form/organisationseinheit-form.component';
 
 @Component({
   selector: 'admin-organisationseinheit-container',
   templateUrl: './organisationseinheit-container.component.html',
 })
 export class OrganisationseinheitContainerComponent implements OnInit {
-  groupState$: Observable<KeycloakGroupState>;
+  organisationseinheitItems$: Observable<Organisationseinheit[]>;
+  deleteInProgress$: Observable<boolean> = of(false);
 
-  constructor(private keycloakService: KeycloakService) {}
+  @ViewChild(OrganisationseinheitFormComponent)
+  private form!: OrganisationseinheitFormComponent;
+
+  constructor(private userService: UserService) {}
 
   ngOnInit(): void {
-    this.groupState$ = this.keycloakService.getGroupState();
+    this.organisationseinheitItems$ = this.userService.getOrganisationseinheitItems();
+  }
+
+  public openDialogForNewGroup(): void {
+    this.form.open();
+  }
+
+  public edit(organisationseinheit: Organisationseinheit): void {
+    this.form.openEdit(organisationseinheit);
+  }
+
+  public delete(organisationseinheit: Organisationseinheit): void {
+    this.deleteInProgress$ = this.userService.deleteOrganisationseinheit(organisationseinheit.id);
   }
 }
diff --git a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.html b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.html
index 7bc721fbc795e357bfc0b25e10946a24ff43ac55..8d00b44b3737090091e15a34e731f4168b12b601 100644
--- a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.html
+++ b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.html
@@ -1,29 +1,33 @@
-<button
-  (click)="close.emit()"
-  data-test-id="organisationseinheit-close-button"
-  class="absolute right-3 top-1 text-2xl text-black hover:font-bold active:text-black/80"
->
-  &#x2715;
-</button>
-<form [formGroup]="formService.form" class="m-5 grid grid-cols-1 gap-5">
-  <h1 class="text-2xl">Neue Organisationseinheit anlegen</h1>
-  <text-field
-    label="Name"
-    data-test-id="organisationseinheit-name"
-    [formControlName]="OrganisationseinheitFormService.GROUP_NAME_FIELD"
-  ></text-field>
-  <text-field
-    label="OrganisationseinheitID"
-    data-test-id="organisationseinheit-id"
-    [formControlName]="OrganisationseinheitFormService.ORGANISATIONS_EINHEIT_FIELD"
-  ></text-field>
-
-  <admin-primary-button
-    data-test-id="organisationseinheit-save-button"
-    class="justify-self-end"
-    (clickEmitter)="submit()"
-    [disabled]="submitInProgress$ | async"
-    label="Speichern"
+<dialog #OrganisationseinheitDialog data-test-id="organisationseinheit-dialog" class="bg-gray-50">
+  <button
+    (click)="OrganisationseinheitDialog.close()"
+    data-test-id="organisationseinheit-close-button"
+    class="absolute right-3 top-1 text-2xl text-black hover:font-bold active:text-black/80"
   >
-  </admin-primary-button>
-</form>
+    &#x2715;
+  </button>
+  <form [formGroup]="formService.form" class="m-5 grid grid-cols-1 gap-5">
+    <h1 class="text-2xl" data-test-id="organisationseinheit-form-header">
+      {{ label }}
+    </h1>
+    <text-field
+      label="Name"
+      data-test-id="organisationseinheit-name"
+      [formControlName]="OrganisationseinheitFormService.ORGANISATIONSEINHEIT_NAME_FIELD"
+    ></text-field>
+    <text-field
+      label="OrganisationseinheitID"
+      data-test-id="organisationseinheit-id"
+      [formControlName]="OrganisationseinheitFormService.ORGANISATIONSEINHEIT_IDS_FIELD"
+    ></text-field>
+
+    <admin-primary-button
+      data-test-id="organisationseinheit-save-button"
+      class="justify-self-end"
+      (clickEmitter)="submit()"
+      [submitInProgress]="submitInProgress$ | async"
+      label="Speichern"
+    >
+    </admin-primary-button>
+  </form>
+</dialog>
diff --git a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.spec.ts
index 9311bd9c412b3e296084d0183868f318d4e0b2bf..72226bb29f71728ebf8f242b0bca09593532aeb2 100644
--- a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.spec.ts
+++ b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.spec.ts
@@ -19,18 +19,21 @@ import { PrimaryButtonComponent } from '../../../shared/primary-button/primary-b
 import { TextFieldComponent } from '../../../shared/text-field/text-field.component';
 import { OrganisationseinheitFormservice } from './organisationseinheit.formservice';
 import { of, throwError } from 'rxjs';
-import { KeycloakService } from '../../../keycloak/keycloak.service';
+import { UserService } from '../../../user/user.service';
 import { DebugElement } from '@angular/core';
+import { createOrganisationseinheit } from '../../../../../test/user/user';
+import { Organisationseinheit } from '../../../user/user.model';
 
 describe('OrganisationseinheitFormComponent', () => {
   let component: OrganisationseinheitFormComponent;
   let fixture: ComponentFixture<OrganisationseinheitFormComponent>;
   let form: UntypedFormGroup;
 
-  const keycloakAdminService: Mock<KeycloakService> = mock(KeycloakService);
+  const userService: Mock<UserService> = mock(UserService);
 
   const saveButtonSelector: string = getDataTestIdOf('organisationseinheit-save-button');
   const closeButtonSelector: string = getDataTestIdOf('organisationseinheit-close-button');
+  const headerSelector: string = getDataTestIdOf('organisationseinheit-form-header');
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
@@ -40,13 +43,16 @@ describe('OrganisationseinheitFormComponent', () => {
         MockComponent(TextFieldComponent),
       ],
       imports: [ReactiveFormsModule, FormsModule],
-      providers: [{ provide: KeycloakService, useValue: keycloakAdminService }],
+      providers: [{ provide: UserService, useValue: userService }],
     }).compileComponents();
 
     fixture = TestBed.createComponent(OrganisationseinheitFormComponent);
     component = fixture.componentInstance;
     form = fixture.componentInstance.formService.form;
     fixture.detectChanges();
+
+    component.dialog.showModal = jest.fn();
+    component.dialog.close = jest.fn();
   });
 
   it('should create', () => {
@@ -55,9 +61,13 @@ describe('OrganisationseinheitFormComponent', () => {
 
   describe('form element', () => {
     const fields: string[][] = [
-      [OrganisationseinheitFormservice.GROUP_NAME_FIELD, 'Name', 'organisationseinheit-name'],
       [
-        OrganisationseinheitFormservice.ORGANISATIONS_EINHEIT_FIELD,
+        OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD,
+        'Name',
+        'organisationseinheit-name',
+      ],
+      [
+        OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD,
         'OrganisationseinheitID',
         'organisationseinheit-id',
       ],
@@ -107,7 +117,7 @@ describe('OrganisationseinheitFormComponent', () => {
 
       fixture.detectChanges();
 
-      expect(saveButtonComponent.disabled).toBe(true);
+      expect(saveButtonComponent.submitInProgress).toBe(true);
     });
 
     it('should be enabled while not in progress', () => {
@@ -115,7 +125,7 @@ describe('OrganisationseinheitFormComponent', () => {
 
       fixture.detectChanges();
 
-      expect(saveButtonComponent.disabled).toBe(false);
+      expect(saveButtonComponent.submitInProgress).toBe(false);
     });
   });
 
@@ -145,6 +155,18 @@ describe('OrganisationseinheitFormComponent', () => {
 
       expect(component.handleProgressChange).toHaveBeenCalled();
     }));
+
+    it.each([true, false])('should use submit progress "%s"', (progress) => {
+      component.submitInProgress$ = of(progress);
+
+      fixture.detectChanges();
+
+      const saveButtonComponent: PrimaryButtonComponent = getDebugElementFromFixtureByCss(
+        fixture,
+        saveButtonSelector,
+      ).componentInstance;
+      expect(saveButtonComponent.submitInProgress).toBe(progress);
+    });
   });
 
   describe('handle progress change', () => {
@@ -189,14 +211,14 @@ describe('OrganisationseinheitFormComponent', () => {
 
   describe('complete', () => {
     beforeEach(() => {
-      component.close.emit = jest.fn();
+      component.dialog.close = jest.fn();
       component.formService.reset = jest.fn();
     });
 
-    it('should emit close', () => {
+    it('should close dialog', () => {
       component.complete();
 
-      expect(component.close.emit).toHaveBeenCalled();
+      expect(component.dialog.close).toHaveBeenCalled();
     });
     it('should reset form', () => {
       component.complete();
@@ -206,12 +228,74 @@ describe('OrganisationseinheitFormComponent', () => {
   });
 
   describe('close button', () => {
-    it('should emit close on X click', () => {
-      const closeSpy = jest.spyOn(component.close, 'emit');
+    it('should call to close dialog', () => {
+      component.dialog.close = jest.fn();
 
       dispatchEventFromFixture(fixture, closeButtonSelector, 'click');
 
-      expect(closeSpy).toHaveBeenCalled();
+      expect(component.dialog.close).toHaveBeenCalled();
+    });
+  });
+
+  describe('open', () => {
+    beforeEach(() => {
+      form.markAsTouched();
+    });
+
+    it('should set create label', () => {
+      component.open();
+
+      expect(component.label).toEqual(OrganisationseinheitFormComponent.CREATE_LABEL);
+    });
+
+    it('should open form', () => {
+      component.open();
+
+      expect(component.dialog.showModal).toHaveBeenCalled();
+    });
+
+    it('should reset form', () => {
+      component.formService.reset = jest.fn();
+
+      component.open();
+
+      expect(component.formService.reset).toHaveBeenCalled();
+    });
+  });
+
+  describe('open edit', () => {
+    const organisationseinheit: Organisationseinheit = createOrganisationseinheit();
+
+    it('should set edit label', () => {
+      component.openEdit(organisationseinheit);
+
+      expect(component.label).toEqual(OrganisationseinheitFormComponent.EDIT_LABEL);
+    });
+
+    it('should open dialog', () => {
+      component.open();
+
+      expect(component.dialog.showModal).toHaveBeenCalled();
+    });
+
+    it('should patch form', () => {
+      component.formService.patch = jest.fn();
+
+      component.openEdit(organisationseinheit);
+
+      expect(component.formService.patch).toHaveBeenCalledWith(organisationseinheit);
+    });
+  });
+
+  describe('header', () => {
+    it('should show label text', () => {
+      const text: string = 'test-text';
+      component.label = text;
+
+      fixture.detectChanges();
+
+      const headerElement: HTMLElement = getElementFromFixture(fixture, headerSelector);
+      expect(headerElement.textContent.trim()).toEqual(text);
     });
   });
 });
diff --git a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.ts b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.ts
index 1590d3294714884aff2b7b48dd7d1a7fd37c743f..a751de2bce0712f5d8bc5a1d97b9000fa6ed78ec 100644
--- a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.ts
+++ b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit-form.component.ts
@@ -1,24 +1,30 @@
-import { Component, EventEmitter, OnInit, Output } from '@angular/core';
+import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';
 import { OrganisationseinheitFormservice } from './organisationseinheit.formservice';
 import { Observable, of, tap } from 'rxjs';
+import { Organisationseinheit } from '../../../user/user.model';
 
 @Component({
   selector: 'admin-organisationseinheit-form',
   templateUrl: './organisationseinheit-form.component.html',
   providers: [OrganisationseinheitFormservice],
 })
-export class OrganisationseinheitFormComponent implements OnInit {
+export class OrganisationseinheitFormComponent implements AfterViewInit {
+  static CREATE_LABEL: string = 'Neue Organisationseinheit anlegen';
+  static EDIT_LABEL: string = 'Organisationseinheit bearbeiten';
+
   protected readonly OrganisationseinheitFormService = OrganisationseinheitFormservice;
 
-  @Output()
-  close: EventEmitter<void> = new EventEmitter<void>();
+  @ViewChild('OrganisationseinheitDialog') private dialogRef: ElementRef<HTMLDialogElement>;
+  dialog: HTMLDialogElement;
+
+  submitInProgress$: Observable<boolean> = of(false);
 
-  submitInProgress$: Observable<boolean>;
+  label: string;
 
   constructor(public formService: OrganisationseinheitFormservice) {}
 
-  ngOnInit(): void {
-    this.submitInProgress$ = of(false);
+  ngAfterViewInit(): void {
+    this.dialog = this.dialogRef.nativeElement;
   }
 
   public submit() {
@@ -39,8 +45,20 @@ export class OrganisationseinheitFormComponent implements OnInit {
     }
   }
 
+  public open(): void {
+    this.label = OrganisationseinheitFormComponent.CREATE_LABEL;
+    this.formService.reset();
+    this.dialog.showModal();
+  }
+
+  public openEdit(organisationseinheit: Organisationseinheit): void {
+    this.label = OrganisationseinheitFormComponent.EDIT_LABEL;
+    this.formService.patch(organisationseinheit);
+    this.dialog.showModal();
+  }
+
   complete(): void {
-    this.close.emit();
+    this.dialog.close();
     this.formService.reset();
   }
 }
diff --git a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.spec.ts b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.spec.ts
index 5be2d2ddf68b673f43dffc91df8b8529e65a3f12..8d32f35b1f5ea2631d34035d835b1d02aa1efae9 100644
--- a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.spec.ts
+++ b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.spec.ts
@@ -1,39 +1,41 @@
-import { FormBuilder } from '@angular/forms';
+import { AbstractControl, FormBuilder } from '@angular/forms';
 import { OrganisationseinheitFormservice } from './organisationseinheit.formservice';
 import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
-import { KeycloakService } from '../../../keycloak/keycloak.service';
+import { UserService } from '../../../user/user.service';
 import {
-  createKeycloakAdminError,
-  createKeycloakGroup,
-} from '../../../../../test/keycloak/keycloak';
+  createOrganisationseinheit,
+  createOrganisationseinheitError,
+} from '../../../../../test/user/user';
 import {
-  KeycloakAdminError,
-  KeycloakAdminErrorType,
-  KeycloakGroup,
-} from '../../../keycloak/keycloak.model';
+  Organisationseinheit,
+  OrganisationseinheitError,
+  OrganisationseinheitErrorType,
+} from '../../../user/user.model';
 import { fakeAsync, tick } from '@angular/core/testing';
-import { singleCold } from '../../../../../../tech-shared/src/lib/resource/marbles';
+import { singleCold, singleHot } from 'libs/tech-shared/src/lib/resource/marbles';
 import { lastValueFrom, Observable, throwError } from 'rxjs';
 import { hot } from 'jest-marbles';
-import { getKeycloakAdminErrorMessage } from '../../../keycloak/keycloak.util';
+import { getOrganisationseinheitErrorMessage } from '../../../user/user.util';
+import { KeycloakAdminErrorType } from '../../../keycloak/keycloak.model';
+
+// TODO
+// ID_MISSING = 'id-missing',
+// [KeycloakAdminErrorType.ID_MISSING]: 'Bitte mindestens eine Organisationseinheit ID angeben.',
 
 describe('OrganisationseinheitFormService', () => {
   let formService: OrganisationseinheitFormservice;
-  let group: KeycloakGroup;
-  const keycloakAdminClient: Mock<KeycloakService> = mock(KeycloakService);
+  let organisationseinheit: Organisationseinheit;
+  const userService: Mock<UserService> = mock(UserService);
 
   const formBuilder: FormBuilder = new FormBuilder();
 
   beforeEach(() => {
-    formService = new OrganisationseinheitFormservice(
-      formBuilder,
-      useFromMock(keycloakAdminClient),
-    );
-    group = createKeycloakGroup();
+    formService = new OrganisationseinheitFormservice(formBuilder, useFromMock(userService));
+    organisationseinheit = createOrganisationseinheit();
     formService.form.setValue({
-      [OrganisationseinheitFormservice.GROUP_NAME_FIELD]: group.name,
-      [OrganisationseinheitFormservice.ORGANISATIONS_EINHEIT_FIELD]:
-        group.organisationseinheitIds.join(','),
+      [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: organisationseinheit.name,
+      [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]:
+        organisationseinheit.organisationseinheitIds.join(','),
     });
   });
 
@@ -51,7 +53,7 @@ describe('OrganisationseinheitFormService', () => {
         formService.validate = jest.fn().mockReturnValue(true);
       });
       it('should call handle error with service call observable', fakeAsync(() => {
-        const error: KeycloakAdminError = createKeycloakAdminError();
+        const error: OrganisationseinheitError = createOrganisationseinheitError();
         formService.callService = jest.fn().mockReturnValue(throwError(() => error));
 
         formService.submit().subscribe();
@@ -60,9 +62,9 @@ describe('OrganisationseinheitFormService', () => {
         expect(formService.handleError).toHaveBeenCalledWith(error);
       }));
 
-      it('should emit emit progress as false on error', () => {
-        const error: KeycloakAdminError = createKeycloakAdminError();
-        formService.callService = jest.fn().mockReturnValue(hot('a#', { a: true }, error));
+    it('should emit emit progress as false on error', () => {
+      const error: OrganisationseinheitError = createOrganisationseinheitError();
+      formService.callService = jest.fn().mockReturnValue(hot('a#', { a: true }, error));
 
         const progressObservable: Observable<boolean> = formService.submit();
 
@@ -133,54 +135,128 @@ describe('OrganisationseinheitFormService', () => {
   });
 
   describe('call service', () => {
-    it('should call create group', () => {
-      formService.callService();
+    it('should use create if is not patch', () => {
+      formService.isPatch = jest.fn().mockReturnValue(false);
+      formService.create = jest.fn().mockReturnValue(singleHot(true));
+
+      const progressObservable: Observable<boolean> = formService.callService();
+
+      expect(progressObservable).toBeObservable(singleHot(true));
+    });
+
+    it('should use save if is patch', () => {
+      formService.isPatch = jest.fn().mockReturnValue(true);
+      formService.save = jest.fn().mockReturnValue(singleHot(true));
+
+      const progressObservable: Observable<boolean> = formService.callService();
+
+      expect(progressObservable).toBeObservable(singleHot(true));
+    });
+  });
+
+  describe('is patch', () => {
+    it('should return false without source', () => {
+      formService.source = null;
+
+      const isPatch: boolean = formService.isPatch();
+
+      expect(isPatch).toBeFalsy();
+    });
+    it('should return true with source', () => {
+      formService.source = createOrganisationseinheit();
 
-      expect(keycloakAdminClient.createGroup).toHaveBeenCalledWith(
-        group.name,
-        group.organisationseinheitIds,
+      const isPatch: boolean = formService.isPatch();
+
+      expect(isPatch).toBeTruthy();
+    });
+  });
+
+  describe('create', () => {
+    it('should call create organisationseinheit', () => {
+      formService.create();
+
+      expect(userService.createOrganisationseinheit).toHaveBeenCalledWith(
+        organisationseinheit.name,
+        organisationseinheit.organisationseinheitIds,
       );
     });
 
-    it('should call create group with empty form', () => {
+    it('should call create organisationseinheit with empty form', () => {
       formService.form.setValue({
-        [OrganisationseinheitFormservice.GROUP_NAME_FIELD]: null,
-        [OrganisationseinheitFormservice.ORGANISATIONS_EINHEIT_FIELD]: null,
+        [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: null,
+        [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]: null,
       });
-      formService.callService();
+      formService.create();
 
-      expect(keycloakAdminClient.createGroup).toHaveBeenCalledWith(null, []);
+      expect(userService.createOrganisationseinheit).toHaveBeenCalledWith('', []);
     });
 
-    it('should return progress observable', fakeAsync(() => {
-      keycloakAdminClient.createGroup.mockReturnValue(singleCold(true));
+    it('should return progress observable', () => {
+      userService.createOrganisationseinheit.mockReturnValue(singleCold(true));
 
-      const progressObservable: Observable<boolean> = formService.callService();
+      const progressObservable: Observable<boolean> = formService.create();
 
       expect(progressObservable).toBeObservable(singleCold(true));
-    }));
+    });
+  });
+
+  describe('save', () => {
+    it('should call save organisationseinheit', () => {
+      formService.source = createOrganisationseinheit();
+
+      formService.save();
+
+      expect(userService.saveOrganisationseinheit).toHaveBeenCalledWith({
+        id: formService.source.id,
+        name: organisationseinheit.name,
+        organisationseinheitIds: organisationseinheit.organisationseinheitIds,
+      });
+    });
+
+    it('should call save organisationseinheit with empty form', () => {
+      formService.source = createOrganisationseinheit();
+      formService.form.setValue({
+        [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: null,
+        [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]: null,
+      });
+      formService.save();
+
+      expect(userService.saveOrganisationseinheit).toHaveBeenCalledWith({
+        id: formService.source.id,
+        name: '',
+        organisationseinheitIds: [],
+      });
+    });
+
+    it('should return progress observable', () => {
+      userService.saveOrganisationseinheit.mockReturnValue(singleCold(true));
+
+      const progressObservable: Observable<boolean> = formService.save();
+
+      expect(progressObservable).toBeObservable(singleCold(true));
+    });
   });
 
   describe('handle error', () => {
-    it.each([KeycloakAdminErrorType.NAME_CONFLICT, KeycloakAdminErrorType.NAME_MISSING])(
-      'should set error on name field on %s',
-      (type: KeycloakAdminErrorType) => {
-        const error: KeycloakAdminError = {
-          ...createKeycloakAdminError(),
-          errorType: type,
-        };
-
-        formService.handleError(error);
-        const errorMessage = formService.form.getError(
-          type,
-          OrganisationseinheitFormservice.GROUP_NAME_FIELD,
-        );
-        expect(errorMessage).toEqual(getKeycloakAdminErrorMessage(error));
-      },
-    );
+    it.each([
+      OrganisationseinheitErrorType.NAME_CONFLICT,
+      OrganisationseinheitErrorType.NAME_MISSING,
+    ])('should set error on name field on %s', (type: OrganisationseinheitErrorType) => {
+      const error: OrganisationseinheitError = {
+        ...createOrganisationseinheitError(),
+        errorType: type,
+      };
+
+      formService.handleError(error);
+      const errorMessage = formService.form.getError(
+        type,
+        OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD,
+      );
+      expect(errorMessage).toEqual(getOrganisationseinheitErrorMessage(error));
+    });
 
     it('should not set error on name field for unknown errors', () => {
-      const unknownError: KeycloakAdminError = createKeycloakAdminError(undefined);
+      const unknownError: OrganisationseinheitError = createOrganisationseinheitError(undefined);
 
       formService.handleError(unknownError);
 
@@ -188,6 +264,34 @@ describe('OrganisationseinheitFormService', () => {
     });
   });
 
+  describe('patch', () => {
+    const organisationseinheit: Organisationseinheit = createOrganisationseinheit();
+
+    it('should set source', () => {
+      formService.patch(organisationseinheit);
+
+      expect(formService.source).toBe(organisationseinheit);
+    });
+
+    it('should set name', () => {
+      formService.patch(organisationseinheit);
+
+      const formControl: AbstractControl = formService.form.get(
+        OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD,
+      );
+      expect(formControl.value).toEqual(organisationseinheit.name);
+    });
+
+    it('should set organisationseinheitIds', () => {
+      formService.patch(organisationseinheit);
+
+      const formControl: AbstractControl = formService.form.get(
+        OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD,
+      );
+      expect(formControl.value).toEqual(organisationseinheit.organisationseinheitIds.join(', '));
+    });
+  });
+
   describe('split organisationseinheitIds by comma', () => {
     it('should return', () => {
       const organisationseinheitIds: string[] =
@@ -212,6 +316,12 @@ describe('OrganisationseinheitFormService', () => {
 
       expect(formService.form.reset).toHaveBeenCalled();
     });
+
+    it('should mark as untouched', () => {
+      formService.patch(organisationseinheit);
+
+      expect(formService.form.untouched).toBeTruthy();
+    });
   });
 
   describe('is invalid', () => {
diff --git a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.ts b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.ts
index 72b323f577d55559fb8334b47941fda382bd923a..83441a32c9a29a994490cd1add6c5fa0492538bf 100644
--- a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.ts
+++ b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-form/organisationseinheit.formservice.ts
@@ -1,59 +1,72 @@
 import { Injectable } from '@angular/core';
 import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
-import { KeycloakService } from '../../../keycloak/keycloak.service';
+import { UserService } from '../../../user/user.service';
 import { catchError, Observable, of } from 'rxjs';
 import {
-  KeycloakAdminError,
-  KeycloakAdminErrorType,
-  KeycloakGroup,
-} from '../../../keycloak/keycloak.model';
-import { getKeycloakAdminErrorMessage } from '../../../keycloak/keycloak.util';
+  Organisationseinheit,
+  OrganisationseinheitError,
+  OrganisationseinheitErrorType,
+} from '../../../user/user.model';
+import { getOrganisationseinheitErrorMessage } from '../../../user/user.util';
+import { isNotNil } from '@alfa-client/tech-shared';
 
 @Injectable()
 export class OrganisationseinheitFormservice {
-  public static readonly GROUP_NAME_FIELD: string = 'group';
-  public static readonly ORGANISATIONS_EINHEIT_FIELD: string = 'organisationseinheit';
+  public static readonly ORGANISATIONSEINHEIT_NAME_FIELD: string = 'name';
+  public static readonly ORGANISATIONSEINHEIT_IDS_FIELD: string = 'organisationseinheit';
 
   form: UntypedFormGroup;
 
-  source: KeycloakGroup;
+  source: Organisationseinheit;
 
   constructor(
     private formBuilder: UntypedFormBuilder,
-    private keycloakAdminService: KeycloakService,
+    private userService: UserService,
   ) {
     this.form = this.formBuilder.group({
-      [OrganisationseinheitFormservice.GROUP_NAME_FIELD]: new FormControl(''),
-      [OrganisationseinheitFormservice.ORGANISATIONS_EINHEIT_FIELD]: new FormControl(''),
+      [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: new FormControl(''),
+      [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]: new FormControl(''),
     });
   }
 
   public submit(): Observable<boolean> {
     if (this.validate()) {
-      return this.callService().pipe(
-        catchError((error: KeycloakAdminError) => {
-          this.handleError(error);
-          return of(false);
-        }),
-      );
+    return this.callService().pipe(
+      catchError((error: OrganisationseinheitError) => {
+        this.handleError(error);
+        return of(false);
+      }),
+    );
     } else {
       return of(false);
     }
   }
 
   callService(): Observable<boolean> {
-    return this.keycloakAdminService.createGroup(
-      this.form.get(OrganisationseinheitFormservice.GROUP_NAME_FIELD).value,
+    return this.isPatch() ? this.save() : this.create();
+  }
+
+  create(): Observable<boolean> {
+    return this.userService.createOrganisationseinheit(
+      this.getName(),
       this.getOrganisationseinheitIds(),
     );
   }
 
+  save(): Observable<boolean> {
+    return this.userService.saveOrganisationseinheit({
+      ...this.source,
+      name: this.getName(),
+      organisationseinheitIds: this.getOrganisationseinheitIds(),
+    });
+  }
+
   validate(): boolean {
     let valid: boolean = true;
 
     if (this.getOrganisationseinheitIds().length == 0) {
-      this.setError(OrganisationseinheitFormservice.ORGANISATIONS_EINHEIT_FIELD, {
-        errorType: KeycloakAdminErrorType.ID_MISSING,
+      this.setError(OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD, {
+        errorType: OrganisationseinheitErrorType.ID_MISSING,
         detail: '',
       });
       valid = false;
@@ -62,25 +75,39 @@ export class OrganisationseinheitFormservice {
     return valid;
   }
 
+  private getName(): string {
+    return this.getStringFromPotentiallyEmptyField(
+      OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD,
+    );
+  }
+
   private getOrganisationseinheitIds(): string[] {
     return this.splitOrganisationseinheitIds(
-      this.form.get(OrganisationseinheitFormservice.ORGANISATIONS_EINHEIT_FIELD).value ?? '',
+      this.form.get(OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD).value ?? '',
     );
   }
 
-  handleError(error: KeycloakAdminError): void {
+  private getStringFromPotentiallyEmptyField(fieldName: string): string {
+    return this.form.get(fieldName).value ?? '';
+  }
+
+  public isPatch(): boolean {
+    return isNotNil(this.source);
+  }
+
+  handleError(error: OrganisationseinheitError): void {
     if (
-      error.errorType === KeycloakAdminErrorType.NAME_CONFLICT ||
-      error.errorType === KeycloakAdminErrorType.NAME_MISSING
+      error.errorType === OrganisationseinheitErrorType.NAME_CONFLICT ||
+      error.errorType === OrganisationseinheitErrorType.NAME_MISSING
     ) {
-      this.setError(OrganisationseinheitFormservice.GROUP_NAME_FIELD, error);
+      this.setError(OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD, error);
     }
   }
 
-  private setError(controlName: string, error: KeycloakAdminError): void {
+  private setError(controlName: string, error: OrganisationseinheitError): void {
     const control: AbstractControl = this.form.get(controlName);
     control.setErrors({
-      [error.errorType]: getKeycloakAdminErrorMessage(error),
+      [error.errorType]: getOrganisationseinheitErrorMessage(error),
     });
   }
 
@@ -91,11 +118,21 @@ export class OrganisationseinheitFormservice {
       .filter((organisationseinheitId) => organisationseinheitId.length > 0);
   }
 
+  public patch(organisationseinheit: Organisationseinheit): void {
+    this.source = organisationseinheit;
+    this.form.patchValue({
+      [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_NAME_FIELD]: organisationseinheit.name,
+      [OrganisationseinheitFormservice.ORGANISATIONSEINHEIT_IDS_FIELD]:
+        organisationseinheit.organisationseinheitIds.join(', '),
+    });
+  }
+
   public reset(): void {
     this.form.reset();
+    this.form.markAsUntouched();
   }
 
-  isInvalid(): boolean {
+  public isInvalid(): boolean {
     return this.form.invalid;
   }
 }
diff --git a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.html b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.html
index 2d6ad03ecfb0139a1b0db9099224847d2a3b56e5..f26e6e0c0d028d7d8bf3b224279cf662d80e5603 100644
--- a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.html
+++ b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.html
@@ -1,5 +1,5 @@
 <table
-  *ngIf="groups.length; else emptyMessage"
+  *ngIf="organisationseinheitItems.length; else emptyMessage"
   aria-label="Keycloak-Gruppen mit OrganisationseinheitIDs"
   class="mb-2 mt-2 table-fixed"
   data-test-id="organisationseinheit-table"
@@ -8,18 +8,40 @@
     <th scope="col">Name</th>
     <th scope="col">Attribute</th>
   </tr>
-  <tr *ngFor="let group of groups" [id]="group.id">
+  <tr *ngFor="let organisationseinheit of organisationseinheitItems" [id]="organisationseinheit.id">
     <td
-      [attr.data-test-id]="'organisationseinheit-name-' + group.id | convertForDataTest"
+      [attr.data-test-id]="
+        'organisationseinheit-name-' + organisationseinheit.id | convertForDataTest
+      "
       class="w-96 border border-slate-500 p-2 font-bold"
     >
-      {{ group.name }}
+      {{ organisationseinheit.name }}
     </td>
     <td
-      [attr.data-test-id]="'organisationseinheit-attr-' + group.id | convertForDataTest"
+      [attr.data-test-id]="
+        'organisationseinheit-attr-' + organisationseinheit.id | convertForDataTest
+      "
       class="w-96 border border-slate-500 p-2"
     >
-      OrganisationseinheitID: {{ group.organisationseinheitIds.join(', ') }}
+      OrganisationseinheitID: {{ organisationseinheit.organisationseinheitIds.join(', ') }}
+      <admin-more-menu class="float-right">
+        <admin-more-item-button
+          (clickEmitter)="editOrganisationseinheit.emit(organisationseinheit)"
+          more-menu-item
+          [attr.data-test-id]="
+            'organisationseinheit-edit-' + organisationseinheit.id | convertForDataTest
+          "
+          label="Bearbeiten"
+        ></admin-more-item-button>
+        <admin-more-item-button
+          (clickEmitter)="deleteOrganisationseinheit.emit(organisationseinheit)"
+          more-menu-item
+          [attr.data-test-id]="
+            'organisationseinheit-delete-' + organisationseinheit.id | convertForDataTest
+          "
+          label="Löschen"
+        ></admin-more-item-button>
+      </admin-more-menu>
     </td>
   </tr>
 </table>
diff --git a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.spec.ts
index c99c0dfcb4a2506113973456bcaffde95fb0c6bb..310a0ecbfc5e795d1aa2dc49a22deff2304803c3 100644
--- a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.spec.ts
+++ b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.spec.ts
@@ -2,13 +2,17 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { OrganisationseinheitListComponent } from './organisationseinheit-list.component';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import {
+  dispatchEventFromFixture,
   existsAsHtmlElement,
   getElementFromFixture,
   notExistsAsHtmlElement,
 } from '@alfa-client/test-utils';
-import { createKeycloakGroup } from '../../../../../test/keycloak/keycloak';
-import { KeycloakGroup } from '../../../keycloak/keycloak.model';
+import { createOrganisationseinheit } from '../../../../../test/user/user';
+import { Organisationseinheit } from '../../../user/user.model';
 import { convertForDataTest, ConvertForDataTestPipe } from '@alfa-client/tech-shared';
+import { MockComponent } from 'ng-mocks';
+import { MoreMenuComponent } from '../../../shared/more-menu/more-menu.component';
+import { MoreItemButtonComponent } from '../../../shared/more-menu/more-item-button/more-item-button.component';
 
 describe('OrganisationseinheitListComponent', () => {
   let component: OrganisationseinheitListComponent;
@@ -17,12 +21,20 @@ describe('OrganisationseinheitListComponent', () => {
   const emptyMessageSelector: string = getDataTestIdOf('organisationseinheit-empty-message');
   const tableSelector: string = getDataTestIdOf('organisationseinheit-table');
 
-  const groupCellSelector = (group: KeycloakGroup, cell: string) =>
-    getDataTestIdOf(convertForDataTest(`organisationseinheit-${cell}-${group.id}`));
+  const organisationseinheitElementSelector = (
+    organisationseinheit: Organisationseinheit,
+    cell: string,
+  ) =>
+    getDataTestIdOf(convertForDataTest(`organisationseinheit-${cell}-${organisationseinheit.id}`));
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [OrganisationseinheitListComponent, ConvertForDataTestPipe],
+      declarations: [
+        OrganisationseinheitListComponent,
+        ConvertForDataTestPipe,
+        MockComponent(MoreMenuComponent),
+        MockComponent(MoreItemButtonComponent),
+      ],
     }).compileComponents();
 
     fixture = TestBed.createComponent(OrganisationseinheitListComponent);
@@ -35,7 +47,7 @@ describe('OrganisationseinheitListComponent', () => {
   });
 
   describe('table rows', () => {
-    describe('without groups', () => {
+    describe('without organisationseinheit items', () => {
       it('should show empty message', () => {
         existsAsHtmlElement(fixture, emptyMessageSelector);
       });
@@ -44,10 +56,13 @@ describe('OrganisationseinheitListComponent', () => {
       });
     });
 
-    describe('with groups', () => {
-      const groups: KeycloakGroup[] = [createKeycloakGroup(), createKeycloakGroup()];
+    describe('with organisationseinheit items', () => {
+      const organisationseinheitItems: Organisationseinheit[] = [
+        createOrganisationseinheit(),
+        createOrganisationseinheit(),
+      ];
       beforeEach(() => {
-        component.groups = groups;
+        component.organisationseinheitItems = organisationseinheitItems;
         fixture.detectChanges();
       });
 
@@ -63,22 +78,72 @@ describe('OrganisationseinheitListComponent', () => {
         const rows: HTMLTableRowElement[] = Array.from(tableElement.querySelectorAll('tr[id]'));
         const rowIds: string[] = rows.map((row) => row.id);
 
-        expect(rowIds).toEqual(groups.map((group) => group.id));
+        expect(rowIds).toEqual(
+          organisationseinheitItems.map(
+            (organisationseinheit: Organisationseinheit) => organisationseinheit.id,
+          ),
+        );
       });
 
-      it.each(groups)('should show name of group %#', (group) => {
-        const nameTableCell = getElementFromFixture(fixture, groupCellSelector(group, 'name'));
+      it.each(organisationseinheitItems)(
+        'should show name of organisationseinheit %#',
+        (organisationseinheit: Organisationseinheit) => {
+          const nameTableCell = getElementFromFixture(
+            fixture,
+            organisationseinheitElementSelector(organisationseinheit, 'name'),
+          );
 
-        expect(nameTableCell.textContent.trim()).toBe(group.name);
-      });
+          expect(nameTableCell.textContent.trim()).toBe(organisationseinheit.name);
+        },
+      );
 
-      it.each(groups)('should show organisationseinheitId of group %#', (group) => {
-        const attrTableCell = getElementFromFixture(fixture, groupCellSelector(group, 'attr'));
+      it.each(organisationseinheitItems)(
+        'should show organisationseinheitId of organisationseinheit %#',
+        (organisationseinheit: Organisationseinheit) => {
+          const attrTableCell = getElementFromFixture(
+            fixture,
+            organisationseinheitElementSelector(organisationseinheit, 'attr'),
+          );
 
-        expect(attrTableCell.textContent.trim()).toBe(
-          `OrganisationseinheitID: ${group.organisationseinheitIds.join(', ')}`,
-        );
-      });
+          expect(attrTableCell.textContent.trim()).toBe(
+            `OrganisationseinheitID: ${organisationseinheit.organisationseinheitIds.join(', ')}`,
+          );
+        },
+      );
+
+      it.each(organisationseinheitItems)(
+        'should emit editOrganisationseinheit %# on edit button click ',
+        (organisationseinheit: Organisationseinheit) => {
+          component.editOrganisationseinheit.emit = jest.fn();
+
+          dispatchEventFromFixture(
+            fixture,
+            organisationseinheitElementSelector(organisationseinheit, 'edit'),
+            'clickEmitter',
+          );
+
+          expect(component.editOrganisationseinheit.emit).toHaveBeenCalledWith(
+            organisationseinheit,
+          );
+        },
+      );
+
+      it.each(organisationseinheitItems)(
+        'should emit deleteOrganisationseinheit %# on delete button click ',
+        (organisationseinheit: Organisationseinheit) => {
+          component.deleteOrganisationseinheit.emit = jest.fn();
+
+          dispatchEventFromFixture(
+            fixture,
+            organisationseinheitElementSelector(organisationseinheit, 'delete'),
+            'clickEmitter',
+          );
+
+          expect(component.deleteOrganisationseinheit.emit).toHaveBeenCalledWith(
+            organisationseinheit,
+          );
+        },
+      );
     });
   });
 });
diff --git a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.ts b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.ts
index fb364125ad8d1b1a3d2c12181c3ef413c4de6e92..dadd2f0401682461a67e76f73e79dfc09afb54be 100644
--- a/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.ts
+++ b/alfa-client/libs/admin-settings/src/lib/organisationseinheit/organisationseinheit-container/organisationseinheit-list/organisationseinheit-list.component.ts
@@ -1,5 +1,5 @@
-import { Component, Input } from '@angular/core';
-import { KeycloakGroup } from '../../../keycloak/keycloak.model';
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { Organisationseinheit } from '../../../user/user.model';
 
 @Component({
   selector: 'admin-organisationseinheit-list',
@@ -7,5 +7,11 @@ import { KeycloakGroup } from '../../../keycloak/keycloak.model';
 })
 export class OrganisationseinheitListComponent {
   @Input()
-  groups: KeycloakGroup[] = [];
+  organisationseinheitItems: Organisationseinheit[] = [];
+
+  @Output()
+  editOrganisationseinheit: EventEmitter<Organisationseinheit> = new EventEmitter();
+
+  @Output()
+  deleteOrganisationseinheit: EventEmitter<Organisationseinheit> = new EventEmitter();
 }
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.html b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.html
index 82add9e8852d4c5b04ca474d01084a3d6a8debb7..5ebfbc7da60ca54abbabb4135ce809216b274f88 100644
--- a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.html
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.html
@@ -44,6 +44,7 @@
 
   <admin-primary-button
     (clickEmitter)="submit()"
+    [submitInProgress]="this.submitInProgress$ | async"
     data-test-id="save-button"
     label="Speichern"
   ></admin-primary-button>
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts
index 831b945ca7fc71089ec9ccfef7eb6e661b55a2ec..d8c740a91f8509dcf6be09155f277fdf13b8d457 100644
--- a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.spec.ts
@@ -7,6 +7,7 @@ import {
   existsAsHtmlElement,
   getDebugElementFromFixtureByCss,
   getElementFromFixture,
+  Mock,
   mock,
   notExistsAsHtmlElement,
 } from '@alfa-client/test-utils';
@@ -18,19 +19,19 @@ import { createPostfachResource } from '../../../../../test/postfach/postfach';
 import { createStateResource, ProblemDetail } from '@alfa-client/tech-shared';
 import { PostfachService } from '../../postfach.service';
 import { PostfachResource } from '../../postfach.model';
-import { EMPTY } from 'rxjs';
-import { singleCold } from '../../../../../../tech-shared/src/lib/resource/marbles';
+import { EMPTY, of } from 'rxjs';
 import { createInvalidParam, createProblemDetail } from '../../../../../../tech-shared/test/error';
 import { PrimaryButtonComponent } from '../../../shared/primary-button/primary-button.component';
+import { singleCold } from '../../../../../../tech-shared/src/lib/resource/marbles';
 
 describe('PostfachFormComponent', () => {
   let component: PostfachFormComponent;
   let fixture: ComponentFixture<PostfachFormComponent>;
   let formService: PostfachFormService;
 
-  const postfachService = mock(PostfachService);
+  const postfachService: Mock<PostfachService> = mock(PostfachService);
 
-  const saveButton: string = getDataTestIdOf('save-button');
+  const saveButtonSelector: string = getDataTestIdOf('save-button');
   const invalidMessageSpan: string = getDataTestIdOf('invalid-empty-message-span');
 
   beforeEach(async () => {
@@ -63,7 +64,10 @@ describe('PostfachFormComponent', () => {
 
   describe('set postfachStateResource', () => {
     it('should return resource', () => {
-      const updatePostfachResourceFn = jest.spyOn(component, 'updatePostfachResource');
+      const updatePostfachResourceFn: jest.SpyInstance = jest.spyOn(
+        component,
+        'updatePostfachResource',
+      );
       const postfachResource: PostfachResource = createPostfachResource();
 
       component.postfachStateResource = createStateResource(postfachResource);
@@ -84,7 +88,7 @@ describe('PostfachFormComponent', () => {
   });
 
   describe('Absender section', () => {
-    const fields = [
+    const fields: string[][] = [
       [PostfachFormService.NAME_FIELD, 'Name', 'absender-name'],
       [PostfachFormService.ANSCHRIFT_FIELD, 'Anschrift', 'absender-anschrift'],
       [PostfachFormService.DIENST_FIELD, 'Dienst', 'absender-dienst'],
@@ -139,21 +143,24 @@ describe('PostfachFormComponent', () => {
 
   describe('save button', () => {
     it('should call submit on click', () => {
-      const submitFn = jest.spyOn(formService, 'submit');
+      const submitFn: jest.SpyInstance = jest.spyOn(formService, 'submit');
       postfachService.save.mockReturnValue(EMPTY);
 
-      dispatchEventFromFixture(fixture, saveButton, 'clickEmitter');
+      dispatchEventFromFixture(fixture, saveButtonSelector, 'clickEmitter');
 
       expect(submitFn).toHaveBeenCalled();
     });
 
-    it('should subscribe to submit observable', () => {
-      const observable = singleCold(createStateResource(createPostfachResource()));
-      postfachService.save.mockReturnValue(observable);
+    it.each([true, false])('should use submit progress "%s"', (progress) => {
+      component.submitInProgress$ = of(progress);
 
-      dispatchEventFromFixture(fixture, saveButton, 'clickEmitter');
+      fixture.detectChanges();
 
-      expect(observable).toHaveSubscriptions('^');
+      const saveButtonComponent: PrimaryButtonComponent = getDebugElementFromFixtureByCss(
+        fixture,
+        saveButtonSelector,
+      ).componentInstance;
+      expect(saveButtonComponent.submitInProgress).toBe(progress);
     });
   });
 
@@ -181,4 +188,14 @@ describe('PostfachFormComponent', () => {
       notExistsAsHtmlElement(fixture, invalidMessageSpan);
     });
   });
+
+  describe('submit', () => {
+    it('should assign submit in progress', () => {
+      formService.submitWithProgress = jest.fn().mockReturnValue(singleCold(true));
+
+      component.submit();
+
+      expect(component.submitInProgress$).toBeObservable(singleCold(true));
+    });
+  });
 });
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.ts
index 42ffe73413e4fe9777a95f8bc2f9f6d5567991d6..95f118fa77c60925e3e003441038824edfdf90ac 100644
--- a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.ts
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach-form.component.ts
@@ -2,6 +2,7 @@ import { Component, Input } from '@angular/core';
 import { PostfachFormService } from './postfach.formservice';
 import { isNotNil, StateResource } from '@alfa-client/tech-shared';
 import { PostfachResource } from '../../postfach.model';
+import { Observable, of } from 'rxjs';
 
 @Component({
   selector: 'postfach-form',
@@ -9,6 +10,8 @@ import { PostfachResource } from '../../postfach.model';
   providers: [PostfachFormService],
 })
 export class PostfachFormComponent {
+  submitInProgress$: Observable<boolean> = of(false);
+
   @Input() set postfachStateResource(stateResource: StateResource<PostfachResource>) {
     this.updatePostfachResource(stateResource.resource);
   }
@@ -18,11 +21,12 @@ export class PostfachFormComponent {
       this.formService.patch(postfachRessource.settingBody);
     }
   }
+
   protected readonly PostfachFormService = PostfachFormService;
 
   constructor(public formService: PostfachFormService) {}
 
   public submit(): void {
-    this.formService.submit().subscribe();
+    this.submitInProgress$ = this.formService.submitWithProgress();
   }
 }
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.spec.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.spec.ts
index a93f4bb71c02ede6865695e62e96643a696a8bcc..b96525238955dad42e54fefd87196c1a5b9b6413 100644
--- a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.spec.ts
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.spec.ts
@@ -3,10 +3,13 @@ import { PostfachFormService } from './postfach.formservice';
 import { mock, Mock, useFromMock } from '@alfa-client/test-utils';
 import { PostfachService } from '../../postfach.service';
 import { createPostfach, createPostfachResource } from '../../../../../test/postfach/postfach';
-import { Postfach, PostfachResource } from '../../postfach.model';
-import { of } from 'rxjs';
+import { PostfachResource } from '../../postfach.model';
 import { fakeAsync, tick } from '@angular/core/testing';
 import { createStateResource, StateResource } from '@alfa-client/tech-shared';
+import { Postfach } from '../../postfach.model';
+import { Observable, of } from 'rxjs';
+import { cold } from 'jest-marbles';
+import { createEmptyStateResource } from '@alfa-client/tech-shared';
 
 describe('PostfachFormService', () => {
   let formService: PostfachFormService;
@@ -96,4 +99,19 @@ describe('PostfachFormService', () => {
       });
     });
   });
+
+  describe('submit with progress', () => {
+    it('should assign submit in progress to state resource loading', () => {
+      formService.submit = jest.fn().mockReturnValue(
+        cold('ab', {
+          a: createEmptyStateResource(true),
+          b: createEmptyStateResource(false),
+        }),
+      );
+
+      const progressObservable: Observable<boolean> = formService.submitWithProgress();
+
+      expect(progressObservable).toBeObservable(cold('ab', { a: true, b: false }));
+    });
+  });
 });
diff --git a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.ts b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.ts
index bbe76ad769762ade191f3dda23261e18e4e8b573..8eb84a9e4747faea6e98f7d61fd27e76e9c10c23 100644
--- a/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.ts
+++ b/alfa-client/libs/admin-settings/src/lib/postfach/postfach-container/postfach-form/postfach.formservice.ts
@@ -2,11 +2,12 @@ import {
   AbstractFormService,
   EMPTY_STRING,
   HttpError,
+  ProblemDetail,
   StateResource,
 } from '@alfa-client/tech-shared';
 import { Injectable } from '@angular/core';
 import { FormControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
-import { Observable, switchMap } from 'rxjs';
+import { map, Observable, switchMap } from 'rxjs';
 import { PostfachService } from '../../postfach.service';
 import { Postfach, PostfachResource } from '../../postfach.model';
 import { isNil } from 'lodash-es';
@@ -64,4 +65,12 @@ export class PostfachFormService extends AbstractFormService {
   public get invalidEmpty(): boolean {
     return this.form.invalid;
   }
+
+  public submitWithProgress(): Observable<boolean> {
+    return this.submit().pipe(
+      map(
+        (stateResource: StateResource<PostfachResource | ProblemDetail>) => stateResource.loading,
+      ),
+    );
+  }
 }
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-item-button/more-item-button.component.html b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-item-button/more-item-button.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..26ff86713579d5505c52823e6dacb3e429b627cf
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-item-button/more-item-button.component.html
@@ -0,0 +1,7 @@
+<button
+  (click)="clickEmitter.emit($event)"
+  [disabled]="disabled"
+  class="w-full bg-white px-3 py-2 text-sm font-semibold shadow-sm hover:bg-gray-50 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ozgblue-500 active:bg-ozgblue-200"
+>
+  {{ label }}
+</button>
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-item-button/more-item-button.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-item-button/more-item-button.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eb37c9e2e75a4429b4cd381b4fbe8641bc9a1b2b
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-item-button/more-item-button.component.spec.ts
@@ -0,0 +1,51 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MoreItemButtonComponent } from './more-item-button.component';
+import { dispatchEventFromFixture, getElementFromFixture } from '@alfa-client/test-utils';
+
+describe('MoreItemButtonComponent', () => {
+  let component: MoreItemButtonComponent;
+  let fixture: ComponentFixture<MoreItemButtonComponent>;
+
+  const buttonSelector: string = 'button';
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [MoreItemButtonComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(MoreItemButtonComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  it('should show label', () => {
+    const text: string = 'test-text';
+    component.label = text;
+
+    fixture.detectChanges();
+
+    const buttonElement: HTMLButtonElement = getElementFromFixture(fixture, buttonSelector);
+    expect(buttonElement.textContent.trim()).toEqual(text);
+  });
+
+  it.each([false, true])('should use disabled "%s"', (disabled) => {
+    component.disabled = disabled;
+
+    fixture.detectChanges();
+
+    const buttonElement: HTMLButtonElement = getElementFromFixture(fixture, buttonSelector);
+    expect(buttonElement.disabled).toBe(disabled);
+  });
+
+  it('should emit clickEmitter', () => {
+    component.clickEmitter.emit = jest.fn();
+
+    dispatchEventFromFixture(fixture, buttonSelector, 'click');
+
+    expect(component.clickEmitter.emit).toHaveBeenCalled();
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-item-button/more-item-button.component.ts b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-item-button/more-item-button.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..843abd3d47661e76d184df6109f9c253095499ad
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-item-button/more-item-button.component.ts
@@ -0,0 +1,17 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+@Component({
+  selector: 'admin-more-item-button',
+  templateUrl: './more-item-button.component.html',
+  styles: [],
+})
+export class MoreItemButtonComponent {
+  @Output()
+  clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
+
+  @Input()
+  disabled: boolean;
+
+  @Input()
+  label: string;
+}
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-menu.component.html b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-menu.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..08b802175695977a9b8c23d127932f4873b03ec2
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-menu.component.html
@@ -0,0 +1,23 @@
+<div class="group relative inline-block text-[0px]">
+  <button class="active:bg-ozgblue-`00 rounded-full bg-gray-50 text-base hover:bg-ozgblue-200">
+    <svg
+      xmlns="http://www.w3.org/2000/svg"
+      fill="none"
+      viewBox="0 0 24 24"
+      stroke-width="1.5"
+      stroke="currentColor"
+      class="h-6 w-6 stroke-ozgblue-700"
+    >
+      <path
+        stroke-linecap="round"
+        stroke-linejoin="round"
+        d="M12 6.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5ZM12 12.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5ZM12 18.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Z"
+      />
+    </svg>
+  </button>
+  <div
+    class="absolute z-20 hidden flex-col items-stretch text-base drop-shadow-lg group-focus-within:flex"
+  >
+    <ng-content select="[more-menu-item]" />
+  </div>
+</div>
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-menu.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-menu.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fd081be8ddb9eb66b376e68d7bdc2cba9139d8f2
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-menu.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MoreMenuComponent } from './more-menu.component';
+
+describe('MoreMenuComponent', () => {
+  let component: MoreMenuComponent;
+  let fixture: ComponentFixture<MoreMenuComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [MoreMenuComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(MoreMenuComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-menu.component.ts b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-menu.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..897af6c72e72bf7bfe679079e24fbdb4b46a2304
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/more-menu/more-menu.component.ts
@@ -0,0 +1,8 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'admin-more-menu',
+  templateUrl: './more-menu.component.html',
+  styles: [],
+})
+export class MoreMenuComponent {}
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/primary-button/primary-button.component.html b/alfa-client/libs/admin-settings/src/lib/shared/primary-button/primary-button.component.html
index 2840abed79169e911f76c2aa52ebed1cca1b3272..d5e7731728de024e1aeba9f9dbfaa4c86728fe0d 100644
--- a/alfa-client/libs/admin-settings/src/lib/shared/primary-button/primary-button.component.html
+++ b/alfa-client/libs/admin-settings/src/lib/shared/primary-button/primary-button.component.html
@@ -1,7 +1,26 @@
 <button
   (click)="clickEmitter.emit($event)"
-  [disabled]="disabled"
-  class="rounded-md bg-ozgblue-700 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ozgblue-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ozgblue-800 active:bg-ozgblue-600/90"
+  [disabled]="submitInProgress"
+  type="button"
+  class="me-2 inline-flex items-center rounded-lg bg-ozgblue-700 px-5 py-2.5 text-center text-sm font-medium text-white hover:bg-ozgblue-800 focus:ring-4 focus:ring-ozgblue-300 active:bg-ozgblue-600/90 disabled:bg-ozgblue-600/50 dark:bg-ozgblue-600 dark:hover:bg-ozgblue-700 dark:focus:ring-ozgblue-800"
 >
+  <svg
+    *ngIf="submitInProgress"
+    aria-hidden="true"
+    role="status"
+    class="me-3 inline h-4 w-4 animate-spin text-white"
+    viewBox="0 0 100 101"
+    fill="none"
+    xmlns="http://www.w3.org/2000/svg"
+  >
+    <path
+      d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
+      fill="#E5E7EB"
+    />
+    <path
+      d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
+      fill="currentColor"
+    />
+  </svg>
   {{ label }}
 </button>
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/primary-button/primary-button.component.ts b/alfa-client/libs/admin-settings/src/lib/shared/primary-button/primary-button.component.ts
index 3462bf4ea46402f9b986724df88487936fe133ec..365dd569dae6f5a1cf82c94eab2215c70249b815 100644
--- a/alfa-client/libs/admin-settings/src/lib/shared/primary-button/primary-button.component.ts
+++ b/alfa-client/libs/admin-settings/src/lib/shared/primary-button/primary-button.component.ts
@@ -9,7 +9,7 @@ export class PrimaryButtonComponent {
   clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
 
   @Input()
-  disabled: boolean;
+  submitInProgress: boolean;
 
   @Input()
   label: string;
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/secondary-button/secondary-button.component.html b/alfa-client/libs/admin-settings/src/lib/shared/secondary-button/secondary-button.component.html
index 27f763a1c66fd611e9b6450465ed9115e8b984f4..9129a6ce150aad72c0d6dbf2ee7c8ce7f0b36195 100644
--- a/alfa-client/libs/admin-settings/src/lib/shared/secondary-button/secondary-button.component.html
+++ b/alfa-client/libs/admin-settings/src/lib/shared/secondary-button/secondary-button.component.html
@@ -1,8 +1,7 @@
 <button
   (click)="clickEmitter.emit($event)"
   [disabled]="disabled"
-  class="select-none rounded-lg border border-gray-300 px-6 py-3 text-center align-middle font-sans text-xs font-bold uppercase text-ozgblue-600 transition-all hover:opacity-75 focus:ring focus:ring-gray-300 active:opacity-[0.85] disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none"
-  type="button"
+  class="rounded border border-ozgblue-500 bg-transparent px-4 py-2 font-semibold text-ozgblue-700 hover:border-transparent hover:bg-ozgblue-500 hover:text-white active:bg-ozgblue-500/70"
 >
   {{ label }}
 </button>
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/spinner/spinner.component.html b/alfa-client/libs/admin-settings/src/lib/shared/spinner/spinner.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..44ef993322a3dd799dfd5b807a11a8ed8d08fc3c
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/spinner/spinner.component.html
@@ -0,0 +1,4 @@
+<div
+  class="text-surface inline-block h-8 w-8 animate-spin rounded-full border-4 border-solid border-ozgblue-500 border-e-transparent align-[-0.125em] motion-reduce:animate-[spin_1.5s_linear_infinite] dark:text-white"
+  role="status"
+></div>
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/spinner/spinner.component.spec.ts b/alfa-client/libs/admin-settings/src/lib/shared/spinner/spinner.component.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8c8fd9ebc126388ce720aaadbbfd46d6d29bcd84
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/spinner/spinner.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { SpinnerComponent } from './spinner.component';
+
+describe('SpinnerComponent', () => {
+  let component: SpinnerComponent;
+  let fixture: ComponentFixture<SpinnerComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [SpinnerComponent],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(SpinnerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/shared/spinner/spinner.component.ts b/alfa-client/libs/admin-settings/src/lib/shared/spinner/spinner.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ea1d1c44e703219a43d5a7ee25c4919e14ec8749
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/shared/spinner/spinner.component.ts
@@ -0,0 +1,8 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'admin-spinner',
+  templateUrl: './spinner.component.html',
+  styles: [],
+})
+export class SpinnerComponent {}
diff --git a/alfa-client/libs/admin-settings/src/lib/user/user.model.ts b/alfa-client/libs/admin-settings/src/lib/user/user.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..13a1c2cf616cfae08c6a485a50e3d8f2f47c4a84
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/user/user.model.ts
@@ -0,0 +1,21 @@
+export interface Organisationseinheit {
+  id: string;
+  name: string;
+  organisationseinheitIds: string[];
+}
+
+export interface OrganisationseinheitState {
+  organisationseinheitItems: Organisationseinheit[];
+  loading: boolean;
+  updateRequired: boolean;
+}
+
+export enum OrganisationseinheitErrorType {
+  NAME_CONFLICT = 'name-conflict',
+  NAME_MISSING = 'name-missing',
+}
+
+export interface OrganisationseinheitError {
+  errorType: OrganisationseinheitErrorType;
+  detail: string;
+}
diff --git a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.repository.ts b/alfa-client/libs/admin-settings/src/lib/user/user.repository.service.ts
similarity index 50%
rename from alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.repository.ts
rename to alfa-client/libs/admin-settings/src/lib/user/user.repository.service.ts
index fe50f94d8a7fe52a357bfe11ff608b3caed7c9ce..1ffcf2ad2d2e366b31e85c6041dc930f4e9e70c0 100644
--- a/alfa-client/libs/admin-settings/src/lib/keycloak/keycloak.repository.ts
+++ b/alfa-client/libs/admin-settings/src/lib/user/user.repository.service.ts
@@ -1,16 +1,16 @@
 import { Injectable } from '@angular/core';
-import { KeycloakAdminError, KeycloakGroup } from './keycloak.model';
-import { catchError, from, map, Observable, throwError } from 'rxjs';
+import { Organisationseinheit, OrganisationseinheitError } from './user.model';
+import { catchError, from, map, Observable, OperatorFunction, throwError } from 'rxjs';
 import KcAdminClient, { NetworkError } from '@keycloak/keycloak-admin-client';
 import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';
 import { OAuthService } from 'angular-oauth2-oidc';
 import { TokenProvider } from '@keycloak/keycloak-admin-client/lib/client';
-import { KEYCLOAK_CREATE_GROUPS_ERROR_STATUS } from './keycloak.util';
+import { KEYCLOAK_CREATE_GROUPS_ERROR_STATUS } from './user.util';
 
 @Injectable({
   providedIn: 'root',
 })
-export class KeycloakRepository {
+export class UserRepository {
   constructor(
     private oAuthService: OAuthService,
     private kcAdminClient: KcAdminClient,
@@ -28,15 +28,21 @@ export class KeycloakRepository {
     };
   }
 
-  public findGroups(): Observable<KeycloakGroup[]> {
+  public deleteOrganisationseinheit(id: string): Observable<void> {
+    return from(this.kcAdminClient.groups.del({ id }));
+  }
+
+  public findOrganisationseinheitItems(): Observable<Organisationseinheit[]> {
     return from(this.kcAdminClient.groups.find({ briefRepresentation: false })).pipe(
       map((reps: GroupRepresentation[]) =>
-        reps.map((rep: GroupRepresentation) => this.mapGroupRepresentation(rep)),
+        reps.map((rep: GroupRepresentation) =>
+          this.mapGroupRepresentationToOrganisationseinheit(rep),
+        ),
       ),
     );
   }
 
-  mapGroupRepresentation(group: GroupRepresentation): KeycloakGroup {
+  mapGroupRepresentationToOrganisationseinheit(group: GroupRepresentation): Organisationseinheit {
     return {
       id: group.id,
       name: group.name,
@@ -44,7 +50,22 @@ export class KeycloakRepository {
     };
   }
 
-  public createGroup(name: string, organisationseinheitIds: string[]): Observable<KeycloakGroup> {
+  public saveOrganisationseinheit(organisationseinheit: Organisationseinheit): Observable<void> {
+    return from(
+      this.kcAdminClient.groups.update(
+        { id: organisationseinheit.id },
+        {
+          name: organisationseinheit.name,
+          attributes: { organisationseinheitId: organisationseinheit.organisationseinheitIds },
+        },
+      ),
+    ).pipe(this.rethrowMappedGroupsError());
+  }
+
+  public createOrganisationseinheit(
+    name: string,
+    organisationseinheitIds: string[],
+  ): Observable<Organisationseinheit> {
     return from(
       this.kcAdminClient.groups.create({
         name,
@@ -52,17 +73,21 @@ export class KeycloakRepository {
       }),
     ).pipe(
       map(
-        ({ id }): KeycloakGroup => ({
+        ({ id }): Organisationseinheit => ({
           id,
           name,
           organisationseinheitIds: organisationseinheitIds,
         }),
       ),
-      catchError((err) => throwError(() => this.mapCreateGroupsNetworkError(err))),
+      this.rethrowMappedGroupsError(),
     );
   }
 
-  mapCreateGroupsNetworkError(error: NetworkError): KeycloakAdminError {
+  rethrowMappedGroupsError<T>(): OperatorFunction<T, T> {
+    return catchError((err) => throwError(() => this.mapCreateGroupsNetworkError(err)));
+  }
+
+  mapCreateGroupsNetworkError(error: NetworkError): OrganisationseinheitError {
     return {
       errorType: KEYCLOAK_CREATE_GROUPS_ERROR_STATUS[error.response.status],
       detail: error.responseData['errorMessage'] ?? '',
diff --git a/alfa-client/libs/admin-settings/src/lib/user/user.repository.spec.ts b/alfa-client/libs/admin-settings/src/lib/user/user.repository.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..11f613f9817b70c5b15ff175358b4e0672527314
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/user/user.repository.spec.ts
@@ -0,0 +1,333 @@
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
+import { UserRepository } from './user.repository.service';
+import KcAdminClient, { NetworkError } from '@keycloak/keycloak-admin-client';
+import { Mock, mock } from '@alfa-client/test-utils';
+import {
+  createGroupRepresentation,
+  createNetworkError,
+  createOrganisationseinheit,
+  createOrganisationseinheitError,
+} from '../../../test/user/user';
+import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';
+import {
+  Organisationseinheit,
+  OrganisationseinheitError,
+  OrganisationseinheitErrorType,
+} from './user.model';
+import { TokenProvider } from '@keycloak/keycloak-admin-client/lib/client';
+import { catchError, firstValueFrom, Observable, of, OperatorFunction, throwError } from 'rxjs';
+import { faker } from '@faker-js/faker';
+import { OAuthService } from 'angular-oauth2-oidc';
+import { Groups } from '@keycloak/keycloak-admin-client/lib/resources/groups';
+
+describe('UserRepository', () => {
+  const accessToken: string = faker.random.alphaNumeric(40);
+  const error: OrganisationseinheitError = createOrganisationseinheitError();
+  const networkError: NetworkError = createNetworkError(400, '');
+
+  let repository: UserRepository;
+
+  let kcAdminClient: Mock<KcAdminClient>;
+  let oAuthService: Mock<OAuthService>;
+
+  const mockGroupsFunc = (groupsKey: keyof Groups, implementation: jest.Mock) => {
+    kcAdminClient.groups = <any>{
+      [groupsKey]: implementation,
+    };
+  };
+
+  beforeEach(() => {
+    kcAdminClient = mock(KcAdminClient);
+    oAuthService = mock(OAuthService);
+    TestBed.configureTestingModule({
+      providers: [
+        { provide: OAuthService, useValue: oAuthService },
+        { provide: KcAdminClient, useValue: kcAdminClient },
+      ],
+    });
+    oAuthService.getAccessToken.mockReturnValue(accessToken);
+    repository = TestBed.inject(UserRepository);
+  });
+
+  it('should be created', () => {
+    expect(repository).toBeTruthy();
+  });
+
+  describe('registerTokenProvider', () => {
+    it('should register token provider from oauth service', async () => {
+      const tokenProvider: TokenProvider = kcAdminClient.registerTokenProvider.mock.calls[0][0];
+      const token: string = await tokenProvider.getAccessToken();
+      expect(token).toEqual(accessToken);
+    });
+  });
+
+  describe('map organisationseinheit representation', () => {
+    let expectedOrganisationseinheit: Organisationseinheit = createOrganisationseinheit();
+
+    it('should map field "id"', () => {
+      const organisationseinheit: Organisationseinheit =
+        repository.mapGroupRepresentationToOrganisationseinheit({
+          id: expectedOrganisationseinheit.id,
+        });
+
+      expect(organisationseinheit.id).toEqual(expectedOrganisationseinheit.id);
+    });
+
+    it('should map field "name"', () => {
+      const organisationseinheit: Organisationseinheit =
+        repository.mapGroupRepresentationToOrganisationseinheit({
+          name: expectedOrganisationseinheit.name,
+        });
+
+      expect(organisationseinheit.name).toEqual(expectedOrganisationseinheit.name);
+    });
+
+    it('should map field "organisationseinheitIds"', () => {
+      const organisationseinheit: Organisationseinheit =
+        repository.mapGroupRepresentationToOrganisationseinheit({
+          attributes: {
+            organisationseinheitId: expectedOrganisationseinheit.organisationseinheitIds,
+          },
+        });
+
+      expect(organisationseinheit.organisationseinheitIds).toEqual(
+        expectedOrganisationseinheit.organisationseinheitIds,
+      );
+    });
+
+    it('should map missing organisationseinheitIds to empty list', () => {
+      const organisationseinheit: Organisationseinheit =
+        repository.mapGroupRepresentationToOrganisationseinheit({});
+
+      expect(organisationseinheit.organisationseinheitIds).toEqual([]);
+    });
+  });
+
+  describe('find organisationseinheitItems', () => {
+    const organisationseinheitItems: Organisationseinheit[] = [
+      createOrganisationseinheit(),
+      createOrganisationseinheit(),
+      createOrganisationseinheit(),
+    ];
+
+    const groupReps: GroupRepresentation[] =
+      organisationseinheitItems.map(createGroupRepresentation);
+
+    it('should return mapped organisationseinheit search result', async () => {
+      const findMock: jest.Mock = jest.fn().mockReturnValue(Promise.resolve(groupReps));
+      mockGroupsFunc('find', findMock);
+
+      const groupsResult: Organisationseinheit[] = await firstValueFrom(
+        repository.findOrganisationseinheitItems(),
+      );
+
+      expect(groupsResult).toEqual(groupsResult);
+    });
+
+    it('should call with brief representation', fakeAsync(() => {
+      const findMock: jest.Mock = jest.fn().mockReturnValue(Promise.resolve(groupReps));
+      mockGroupsFunc('find', findMock);
+
+      repository.findOrganisationseinheitItems().subscribe();
+      tick();
+
+      expect(findMock).toHaveBeenCalledWith({ briefRepresentation: false });
+    }));
+  });
+
+  describe('save organisationseinheit', () => {
+    const saveGroup: Organisationseinheit = createOrganisationseinheit();
+
+    it('should call kcAdminClient.groups.save', async () => {
+      const updateMock: jest.Mock = jest.fn(() => of(null));
+      mockGroupsFunc('update', updateMock);
+
+      await firstValueFrom(repository.saveOrganisationseinheit(saveGroup));
+
+      expect(updateMock).toHaveBeenCalledWith(
+        { id: saveGroup.id },
+        {
+          name: saveGroup.name,
+          attributes: {
+            organisationseinheitId: saveGroup.organisationseinheitIds,
+          },
+        },
+      );
+    });
+
+    it('should return organisationseinheit save observable', async () => {
+      const updateMock: jest.Mock = jest.fn(() => Promise.resolve(null));
+      mockGroupsFunc('update', updateMock);
+
+      const voidResult = await firstValueFrom(repository.saveOrganisationseinheit(saveGroup));
+
+      expect(voidResult).toBe(null);
+    });
+
+    it('should pipe rethrowMappedGroupsError', (done) => {
+      const updateMock: jest.Mock = jest.fn(() => Promise.reject(networkError));
+      mockGroupsFunc('update', updateMock);
+      repository.rethrowMappedGroupsError = jest
+        .fn()
+        .mockReturnValue(catchError(() => throwError(() => error)));
+
+      repository.saveOrganisationseinheit(saveGroup).subscribe({
+        error: (err) => {
+          expect(err).toBe(error);
+          done();
+        },
+      });
+    });
+  });
+
+  describe('create organisationseinheit', () => {
+    const newOrganisationseinheit: Organisationseinheit = createOrganisationseinheit();
+
+    it('should call kcAdminClient.groups.create', async () => {
+      const createMock: jest.Mock = jest.fn(() => of({ id: newOrganisationseinheit.id }));
+      mockGroupsFunc('create', createMock);
+
+      await firstValueFrom(
+        repository.createOrganisationseinheit(
+          newOrganisationseinheit.name,
+          newOrganisationseinheit.organisationseinheitIds,
+        ),
+      );
+
+      expect(createMock).toHaveBeenCalledWith({
+        name: newOrganisationseinheit.name,
+        attributes: {
+          organisationseinheitId: newOrganisationseinheit.organisationseinheitIds,
+        },
+      });
+    });
+
+    it('should return mapped organisationseinheit result', async () => {
+      const createMock: jest.Mock = jest.fn(() =>
+        Promise.resolve({ id: newOrganisationseinheit.id }),
+      );
+      mockGroupsFunc('create', createMock);
+
+      const newGroupResult: Organisationseinheit = await firstValueFrom(
+        repository.createOrganisationseinheit(
+          newOrganisationseinheit.name,
+          newOrganisationseinheit.organisationseinheitIds,
+        ),
+      );
+
+      expect(newGroupResult).toEqual(newOrganisationseinheit);
+    });
+
+    it('should pipe rethrowMappedGroupsError', (done) => {
+      const createMock: jest.Mock = jest.fn(() => Promise.reject(networkError));
+      mockGroupsFunc('create', createMock);
+      repository.rethrowMappedGroupsError = jest
+        .fn()
+        .mockReturnValue(catchError(() => throwError(() => error)));
+
+      repository
+        .createOrganisationseinheit(
+          newOrganisationseinheit.name,
+          newOrganisationseinheit.organisationseinheitIds,
+        )
+        .subscribe({
+          error: (err) => {
+            expect(err).toBe(error);
+            done();
+          },
+        });
+    });
+  });
+
+  describe('rethrow mapped groups error', () => {
+    let networkErrorObservable: Observable<never>;
+
+    beforeEach(() => {
+      repository.mapCreateGroupsNetworkError = jest.fn().mockReturnValue(error);
+      networkErrorObservable = throwError(() => networkError);
+    });
+
+    it('should throw mapped error', (done) => {
+      const rethrowOperator: OperatorFunction<never, never> = repository.rethrowMappedGroupsError();
+
+      networkErrorObservable.pipe(rethrowOperator).subscribe({
+        error: (err) => {
+          expect(err).toBe(error);
+          done();
+        },
+      });
+    });
+
+    it('should call mapCreateGroupsNetworkError', (done) => {
+      const rethrowOperator: OperatorFunction<never, never> = repository.rethrowMappedGroupsError();
+
+      networkErrorObservable.pipe(rethrowOperator).subscribe({
+        error: () => {
+          expect(repository.mapCreateGroupsNetworkError).toHaveBeenCalledWith(networkError);
+          done();
+        },
+      });
+    });
+  });
+
+  describe('map create groups network error', () => {
+    it('should interpret 409 status as name conflict', () => {
+      const keycloakError: OrganisationseinheitError = createOrganisationseinheitError(
+        OrganisationseinheitErrorType.NAME_CONFLICT,
+      );
+      const networkError: NetworkError = createNetworkError(409, keycloakError.detail);
+
+      const error: OrganisationseinheitError = repository.mapCreateGroupsNetworkError(networkError);
+
+      expect(error).toEqual(keycloakError);
+    });
+
+    it('should interpret 400 status as name missing', () => {
+      const keycloakError: OrganisationseinheitError = createOrganisationseinheitError(
+        OrganisationseinheitErrorType.NAME_MISSING,
+      );
+      const networkError: NetworkError = createNetworkError(400, keycloakError.detail);
+
+      const error: OrganisationseinheitError = repository.mapCreateGroupsNetworkError(networkError);
+
+      expect(error).toEqual(keycloakError);
+    });
+
+    it('should map missing errorMessage to empty string', () => {
+      const networkError: NetworkError = createNetworkError(500, undefined);
+
+      const error: OrganisationseinheitError = repository.mapCreateGroupsNetworkError(networkError);
+      expect(error.detail).toEqual('');
+    });
+  });
+
+  describe('delete organisationseinheit', () => {
+    const deleteOrganisationseinheit: Organisationseinheit = createOrganisationseinheit();
+
+    it('should call kcAdminClient.groups.del', async () => {
+      const delMock: jest.Mock = jest.fn(() =>
+        Promise.resolve({ id: deleteOrganisationseinheit.id }),
+      );
+      mockGroupsFunc('del', delMock);
+
+      await firstValueFrom(repository.deleteOrganisationseinheit(deleteOrganisationseinheit.id));
+
+      expect(delMock).toHaveBeenCalledWith({
+        id: deleteOrganisationseinheit.id,
+      });
+    });
+
+    it('should return void', async () => {
+      mockGroupsFunc(
+        'del',
+        jest.fn(() => Promise.resolve(null)),
+      );
+
+      const voidResult = await firstValueFrom(
+        repository.deleteOrganisationseinheit(deleteOrganisationseinheit.id),
+      );
+
+      expect(voidResult).toBeNull();
+    });
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/user/user.service.spec.ts b/alfa-client/libs/admin-settings/src/lib/user/user.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..32e15e4bd393873c8d336a918180c714fb66bcb6
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/user/user.service.spec.ts
@@ -0,0 +1,321 @@
+import { UserService } from './user.service';
+import { UserRepository } from './user.repository.service';
+import { mock, Mock, useFromMock } from '@alfa-client/test-utils';
+import {
+  createOrganisationseinheit,
+  createOrganisationseinheitState,
+} from '../../../test/user/user';
+import { firstValueFrom, lastValueFrom, Observable, of } from 'rxjs';
+import { Organisationseinheit } from './user.model';
+import { cold } from 'jest-marbles';
+import { fakeAsync, tick } from '@angular/core/testing';
+import { singleCold } from '../../../../tech-shared/src/lib/resource/marbles';
+
+describe('UserService', () => {
+  let service: UserService;
+  let repository: Mock<UserRepository>;
+  const sortedNames: string[] = ['BBBB', 'CCCC', 'XXXX'];
+  const sortedOrganisationseinheitItems: Organisationseinheit[] = sortedNames.map((name) => ({
+    ...createOrganisationseinheit(),
+    name,
+  }));
+  const unsortedOrganisationseinheitItems: Organisationseinheit[] = [
+    sortedOrganisationseinheitItems[2],
+    sortedOrganisationseinheitItems[0],
+    sortedOrganisationseinheitItems[1],
+  ];
+  let setOrganisationseinheitItemsSpy: jest.SpyInstance;
+  let setLoadingUntilFirstSpy: jest.SpyInstance;
+
+  beforeEach(() => {
+    repository = mock(UserRepository);
+    service = new UserService(useFromMock(repository));
+    setOrganisationseinheitItemsSpy = jest.spyOn(service, 'setOrganisationseinheit');
+    setLoadingUntilFirstSpy = jest.spyOn(service, 'setLoadingUntilFirst');
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+
+  describe('initial state', () => {
+    it('should have empty group list', () => {
+      expect(service.organisationseinheitState$.value.organisationseinheitItems).toEqual([]);
+    });
+    it('should not be loading', () => {
+      expect(service.organisationseinheitState$.value.loading).toEqual(false);
+    });
+    it('should be requiring a reload', () => {
+      expect(service.organisationseinheitState$.value.updateRequired).toEqual(true);
+    });
+  });
+
+  describe('get group state', () => {
+    it('should update if required', async () => {
+      service.updateIfRequired = jest.fn();
+
+      await firstValueFrom(service.getOrganisationseinheitState());
+
+      expect(service.updateIfRequired).toHaveBeenCalled();
+    });
+
+    it('should call find groups', fakeAsync(() => {
+      repository.findOrganisationseinheitItems.mockReturnValue(
+        of(unsortedOrganisationseinheitItems),
+      );
+
+      service.getOrganisationseinheitState().subscribe();
+      tick();
+
+      expect(repository.findOrganisationseinheitItems).toHaveBeenCalled();
+    }));
+  });
+
+  describe('update if required', () => {
+    beforeEach(() => {
+      service.updateOrganisationseinheitItems = jest.fn(() => of([]));
+    });
+
+    it('should call update groups with initial values', () => {
+      service.updateIfRequired();
+
+      expect(service.updateOrganisationseinheitItems).toHaveBeenCalled();
+    });
+
+    it('should not call update groups if loading', () => {
+      service.setLoading();
+
+      service.updateIfRequired();
+
+      expect(service.updateOrganisationseinheitItems).not.toHaveBeenCalled();
+    });
+
+    it('should not call update groups if not requiring update', () => {
+      service.setUpdateRequired(false);
+
+      service.updateIfRequired();
+
+      expect(service.updateOrganisationseinheitItems).not.toHaveBeenCalled();
+    });
+  });
+
+  describe('update groups', () => {
+    beforeEach(() => {
+      repository.findOrganisationseinheitItems.mockReturnValue(
+        of(unsortedOrganisationseinheitItems),
+      );
+    });
+
+    it('should set loading', () => {
+      service.updateOrganisationseinheitItems();
+
+      expect(service.organisationseinheitState$.value.loading).toBeTruthy();
+    });
+
+    it('should set sorted groups', async () => {
+      await lastValueFrom(service.updateOrganisationseinheitItems());
+
+      expect(service.organisationseinheitState$.value.organisationseinheitItems).toEqual(
+        sortedOrganisationseinheitItems,
+      );
+    });
+
+    it('should not require update afterward', async () => {
+      await lastValueFrom(service.updateOrganisationseinheitItems());
+
+      expect(service.organisationseinheitState$.value.updateRequired).toBeFalsy();
+    });
+  });
+
+  describe('save organisationseinheit', () => {
+    const saveGroup: Organisationseinheit = {
+      ...createOrganisationseinheit(),
+      id: sortedOrganisationseinheitItems[0].id,
+    };
+
+    beforeEach(() => {
+      repository.saveOrganisationseinheit.mockReturnValue(of(null));
+    });
+
+    it('should use set loading until first', fakeAsync(() => {
+      service.saveOrganisationseinheit(saveGroup).subscribe();
+      tick();
+
+      expect(setLoadingUntilFirstSpy).toHaveBeenCalled();
+    }));
+
+    it('should call repository for save', fakeAsync(() => {
+      service.saveOrganisationseinheit(saveGroup).subscribe();
+      tick();
+
+      expect(repository.saveOrganisationseinheit).toHaveBeenCalledWith(saveGroup);
+    }));
+
+    it('should set organisationseinheit items with updated organisationseinheit', fakeAsync(() => {
+      service.setOrganisationseinheit(sortedOrganisationseinheitItems);
+      setOrganisationseinheitItemsSpy.mockClear();
+
+      service.saveOrganisationseinheit(saveGroup).subscribe();
+      tick();
+
+      expect(setOrganisationseinheitItemsSpy).toHaveBeenCalledWith([
+        saveGroup,
+        ...sortedOrganisationseinheitItems.slice(1),
+      ]);
+    }));
+  });
+
+  describe('create organisationseinheit', () => {
+    const organisationseinheit: Organisationseinheit = createOrganisationseinheit();
+
+    beforeEach(() => {
+      repository.createOrganisationseinheit.mockReturnValue(of(organisationseinheit));
+    });
+
+    it('should use set loading until first', () => {
+      service.createOrganisationseinheit(
+        organisationseinheit.name,
+        organisationseinheit.organisationseinheitIds,
+      );
+
+      expect(setLoadingUntilFirstSpy).toHaveBeenCalled();
+    });
+
+    it('should call repository for save', () => {
+      service.createOrganisationseinheit(
+        organisationseinheit.name,
+        organisationseinheit.organisationseinheitIds,
+      );
+
+      expect(repository.createOrganisationseinheit).toHaveBeenCalledWith(
+        organisationseinheit.name,
+        organisationseinheit.organisationseinheitIds,
+      );
+    });
+
+    it('should set organisationseinheit items with new group', fakeAsync(() => {
+      service.setOrganisationseinheit(sortedOrganisationseinheitItems);
+      setOrganisationseinheitItemsSpy.mockClear();
+
+      service
+        .createOrganisationseinheit(
+          organisationseinheit.name,
+          organisationseinheit.organisationseinheitIds,
+        )
+        .subscribe();
+      tick();
+
+      expect(setOrganisationseinheitItemsSpy).toHaveBeenCalledWith([
+        ...sortedOrganisationseinheitItems,
+        organisationseinheit,
+      ]);
+    }));
+  });
+
+  describe('set organisationseinheit items', () => {
+    it('should sort groups by name', async () => {
+      service.setOrganisationseinheit(unsortedOrganisationseinheitItems);
+
+      expect(service.organisationseinheitState$.value.organisationseinheitItems).toEqual(
+        sortedOrganisationseinheitItems,
+      );
+    });
+  });
+
+  describe('delete group', () => {
+    const deleteGroup: Organisationseinheit = unsortedOrganisationseinheitItems[1];
+
+    beforeEach(async () => {
+      repository.deleteOrganisationseinheit.mockReturnValue(of(null));
+      service.organisationseinheitState$.next({
+        ...service.organisationseinheitState$.value,
+        organisationseinheitItems: sortedOrganisationseinheitItems,
+      });
+    });
+
+    it('should use set loading until first', () => {
+      const setLoadingUntilFirstSpy: jest.SpyInstance = jest.spyOn(service, 'setLoadingUntilFirst');
+      service.deleteOrganisationseinheit(deleteGroup.id);
+
+      expect(setLoadingUntilFirstSpy).toHaveBeenCalled();
+    });
+
+    it('should call repository', () => {
+      service.deleteOrganisationseinheit(deleteGroup.id);
+
+      expect(repository.deleteOrganisationseinheit).toHaveBeenCalledWith(deleteGroup.id);
+    });
+
+    describe('which exists', () => {
+      it('should not have group in list after delete', fakeAsync(() => {
+        service.deleteOrganisationseinheit(deleteGroup.id).subscribe();
+        tick();
+
+        expect(service.organisationseinheitState$.value.organisationseinheitItems).not.toContain(
+          deleteGroup,
+        );
+      }));
+    });
+
+    describe('which does not exist', () => {
+      it('should have no effect', fakeAsync(() => {
+        service.deleteOrganisationseinheit('unknown-id').subscribe();
+        tick();
+
+        expect(service.organisationseinheitState$.value.organisationseinheitItems).toEqual(
+          sortedOrganisationseinheitItems,
+        );
+      }));
+    });
+  });
+
+  describe('set loading until first', () => {
+    it('should set loading', () => {
+      service.setLoadingUntilFirst(of(null), () => {});
+
+      expect(service.organisationseinheitState$.value.loading).toBe(true);
+    });
+
+    it('should unset loading', fakeAsync(() => {
+      service.setLoadingUntilFirst(of(null), () => {}).subscribe();
+      tick();
+
+      expect(service.organisationseinheitState$.value.loading).toBe(false);
+    }));
+
+    it('should emit loading before first and emit loading after first', () => {
+      const delayedNull = cold('-a|', { a: null });
+
+      const progressObservable = service.setLoadingUntilFirst(delayedNull, () => {});
+
+      expect(progressObservable).toBeObservable(cold('a(b|)', { a: true, b: false }));
+    });
+
+    it('should call tap function', fakeAsync(() => {
+      const tapFunction: jest.Mock = jest.fn();
+      const value: string = 'abc';
+      const delayedNull: Observable<string> = of(value);
+
+      service.setLoadingUntilFirst(delayedNull, tapFunction).subscribe();
+      tick();
+
+      expect(tapFunction).toHaveBeenCalledWith(value);
+    }));
+  });
+
+  describe('get organisationseinheit items', () => {
+    it('should return items of state', () => {
+      const organisationseinheitItems: Organisationseinheit[] = [
+        createOrganisationseinheit(),
+        createOrganisationseinheit(),
+      ];
+      service.getOrganisationseinheitState = jest
+        .fn()
+        .mockReturnValue(singleCold(createOrganisationseinheitState(organisationseinheitItems)));
+
+      const itemsObservable: Observable<Organisationseinheit[]> =
+        service.getOrganisationseinheitItems();
+      expect(itemsObservable).toBeObservable(singleCold(organisationseinheitItems));
+    });
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/user/user.service.ts b/alfa-client/libs/admin-settings/src/lib/user/user.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..21b5dfc8ebefe44762cd5fc4f657a28f83ffc9f7
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/user/user.service.ts
@@ -0,0 +1,143 @@
+import { Injectable } from '@angular/core';
+import { Organisationseinheit, OrganisationseinheitState } from './user.model';
+import { BehaviorSubject, first, map, Observable, startWith, tap } from 'rxjs';
+import { UserRepository } from './user.repository.service';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class UserService {
+  readonly organisationseinheitState$: BehaviorSubject<OrganisationseinheitState> =
+    new BehaviorSubject({
+      organisationseinheitItems: [],
+      loading: false,
+      updateRequired: true,
+    });
+
+  constructor(private userRepository: UserRepository) {}
+
+  public saveOrganisationseinheit(organisationseinheit: Organisationseinheit): Observable<boolean> {
+    return this.setLoadingUntilFirst(
+      this.userRepository.saveOrganisationseinheit(organisationseinheit),
+      () => {
+        this.updateExistingOrganisationseinheit(organisationseinheit);
+      },
+    );
+  }
+
+  private updateExistingOrganisationseinheit(organisationseinheit: Organisationseinheit): void {
+    this.setOrganisationseinheit([
+      organisationseinheit,
+      ...this.organisationseinheitState$.value.organisationseinheitItems.filter(
+        (otherOrganisationseinheit: Organisationseinheit) =>
+          otherOrganisationseinheit.id !== organisationseinheit.id,
+      ),
+    ]);
+  }
+
+  public createOrganisationseinheit(
+    name: string,
+    organisationseinheitIds: string[],
+  ): Observable<boolean> {
+    return this.setLoadingUntilFirst(
+      this.userRepository.createOrganisationseinheit(name, organisationseinheitIds),
+      (organisationseinheit: Organisationseinheit) => {
+        this.addOrganisationseinheit(organisationseinheit);
+      },
+    );
+  }
+
+  public deleteOrganisationseinheit(id: string): Observable<boolean> {
+    return this.setLoadingUntilFirst(this.userRepository.deleteOrganisationseinheit(id), () =>
+      this.removeOrganisationseinheit(id),
+    );
+  }
+
+  private removeOrganisationseinheit(id: string): void {
+    this.setOrganisationseinheit(
+      this.organisationseinheitState$.value.organisationseinheitItems.filter(
+        (organisationseinheit: Organisationseinheit) => organisationseinheit.id !== id,
+      ),
+    );
+  }
+
+  setLoadingUntilFirst<T>(
+    action: Observable<T>,
+    tapFunction: (value: T) => void,
+  ): Observable<boolean> {
+    this.setLoading();
+
+    return action.pipe(
+      first(),
+      tap(tapFunction),
+      tap(() => this.setLoading(false)),
+      map(() => this.organisationseinheitState$.value.loading),
+      startWith(this.organisationseinheitState$.value.loading),
+    );
+  }
+
+  private addOrganisationseinheit(organisationseinheit: Organisationseinheit): void {
+    this.setOrganisationseinheit([
+      ...this.organisationseinheitState$.value.organisationseinheitItems,
+      organisationseinheit,
+    ]);
+  }
+
+  setOrganisationseinheit(organisationseinheitItems: Organisationseinheit[]): void {
+    this.organisationseinheitState$.next({
+      ...this.organisationseinheitState$.value,
+      organisationseinheitItems: this.sortedOrganisationseinheitItems(organisationseinheitItems),
+    });
+  }
+
+  private sortedOrganisationseinheitItems(
+    organisationseinheitItems: Organisationseinheit[],
+  ): Organisationseinheit[] {
+    return [...organisationseinheitItems].sort((a, b) => a.name.localeCompare(b.name));
+  }
+
+  public getOrganisationseinheitState(): Observable<OrganisationseinheitState> {
+    return this.organisationseinheitState$.pipe(tap(() => this.updateIfRequired()));
+  }
+
+  updateIfRequired(): void {
+    if (this.isUpdateRequired(this.organisationseinheitState$.value)) {
+      this.updateOrganisationseinheitItems().pipe(first()).subscribe();
+    }
+  }
+
+  private isUpdateRequired(state: OrganisationseinheitState): boolean {
+    return state.updateRequired && !state.loading;
+  }
+
+  updateOrganisationseinheitItems(): Observable<Organisationseinheit[]> {
+    this.setLoading();
+
+    return this.userRepository.findOrganisationseinheitItems().pipe(
+      tap(() => this.setUpdateRequired(false)),
+      tap((organisationseinheitItems: Organisationseinheit[]) =>
+        this.setOrganisationseinheit(organisationseinheitItems),
+      ),
+    );
+  }
+
+  setUpdateRequired(updateRequired: boolean = true) {
+    this.organisationseinheitState$.next({
+      ...this.organisationseinheitState$.value,
+      updateRequired,
+    });
+  }
+
+  setLoading(loading: boolean = true): void {
+    this.organisationseinheitState$.next({
+      ...this.organisationseinheitState$.value,
+      loading,
+    });
+  }
+
+  public getOrganisationseinheitItems(): Observable<Organisationseinheit[]> {
+    return this.getOrganisationseinheitState().pipe(
+      map((state: OrganisationseinheitState) => state.organisationseinheitItems),
+    );
+  }
+}
diff --git a/alfa-client/libs/admin-settings/src/lib/user/user.util.spec.ts b/alfa-client/libs/admin-settings/src/lib/user/user.util.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0459c56f17adff420dc85eef851f297c9d0ec93e
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/user/user.util.spec.ts
@@ -0,0 +1,22 @@
+import { createOrganisationseinheitError } from '../../../test/user/user';
+import { OrganisationseinheitError, OrganisationseinheitErrorType } from './user.model';
+import { getOrganisationseinheitErrorMessage, KEYCLOAK_ERROR_MESSAGES } from './user.util';
+
+describe('get organisationseinheit error message', () => {
+  it('should map known error message', () => {
+    const nameConflictError: OrganisationseinheitError = createOrganisationseinheitError(
+      OrganisationseinheitErrorType.NAME_CONFLICT,
+    );
+    const expectedMessage: string = KEYCLOAK_ERROR_MESSAGES[nameConflictError.errorType];
+
+    const message: string = getOrganisationseinheitErrorMessage(nameConflictError);
+    expect(message).toEqual(expectedMessage);
+  });
+
+  it('should map unknown error message to empty string', () => {
+    const nameConflictError: OrganisationseinheitError = createOrganisationseinheitError(null);
+
+    const message: string = getOrganisationseinheitErrorMessage(nameConflictError);
+    expect(message).toEqual('');
+  });
+});
diff --git a/alfa-client/libs/admin-settings/src/lib/user/user.util.ts b/alfa-client/libs/admin-settings/src/lib/user/user.util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ac5daa3cb50772102f200277a078d48c081ac123
--- /dev/null
+++ b/alfa-client/libs/admin-settings/src/lib/user/user.util.ts
@@ -0,0 +1,17 @@
+import { OrganisationseinheitError, OrganisationseinheitErrorType } from './user.model';
+
+export const KEYCLOAK_ERROR_MESSAGES: { [type: string]: string } = {
+  [OrganisationseinheitErrorType.NAME_CONFLICT]: 'Der Name exisitert bereits.',
+  [OrganisationseinheitErrorType.NAME_MISSING]: 'Bitte den Namen angeben.',
+};
+
+export const KEYCLOAK_CREATE_GROUPS_ERROR_STATUS: {
+  [status: number]: OrganisationseinheitErrorType;
+} = {
+  409: OrganisationseinheitErrorType.NAME_CONFLICT,
+  400: OrganisationseinheitErrorType.NAME_MISSING,
+};
+
+export function getOrganisationseinheitErrorMessage(error: OrganisationseinheitError): string {
+  return KEYCLOAK_ERROR_MESSAGES[error.errorType] ?? '';
+}
diff --git a/alfa-client/libs/admin-settings/test/keycloak/keycloak.ts b/alfa-client/libs/admin-settings/test/user/user.ts
similarity index 50%
rename from alfa-client/libs/admin-settings/test/keycloak/keycloak.ts
rename to alfa-client/libs/admin-settings/test/user/user.ts
index 4768bf195787418df3f2cf45bbd4a8d590edc0bf..6668ac960823f7ae965dfefed7d37a883eb9116f 100644
--- a/alfa-client/libs/admin-settings/test/keycloak/keycloak.ts
+++ b/alfa-client/libs/admin-settings/test/user/user.ts
@@ -1,14 +1,14 @@
 import {
-  KeycloakAdminError,
-  KeycloakAdminErrorType,
-  KeycloakGroup,
-  KeycloakGroupState,
-} from '../../src/lib/keycloak/keycloak.model';
+  Organisationseinheit,
+  OrganisationseinheitError,
+  OrganisationseinheitErrorType,
+  OrganisationseinheitState,
+} from '../../src/lib/user/user.model';
 import { faker } from '@faker-js/faker';
 import type GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';
 import { NetworkError } from '@keycloak/keycloak-admin-client';
 
-export function createKeycloakGroup(): KeycloakGroup {
+export function createOrganisationseinheit(): Organisationseinheit {
   return {
     id: faker.random.alphaNumeric(16),
     name: faker.name.jobTitle(),
@@ -17,30 +17,30 @@ export function createKeycloakGroup(): KeycloakGroup {
 }
 
 export function createGroupRepresentation(
-  group: KeycloakGroup = createKeycloakGroup(),
+  organisationseinheit: Organisationseinheit = createOrganisationseinheit(),
 ): GroupRepresentation {
   return {
-    id: group.id,
-    name: group.name,
+    id: organisationseinheit.id,
+    name: organisationseinheit.name,
     attributes: {
-      organisationseinheitId: group.organisationseinheitIds,
+      organisationseinheitId: organisationseinheit.organisationseinheitIds,
     },
   };
 }
 
-export function createKeycloakServiceState(
-  groups: KeycloakGroup[] = [createKeycloakGroup()],
-): KeycloakGroupState {
+export function createOrganisationseinheitState(
+  organisationseinheitItems: Organisationseinheit[] = [createOrganisationseinheit()],
+): OrganisationseinheitState {
   return {
-    groups,
+    organisationseinheitItems: organisationseinheitItems,
     loading: false,
     updateRequired: false,
   };
 }
 
-export function createKeycloakAdminError(
-  errorType: KeycloakAdminErrorType = KeycloakAdminErrorType.NAME_MISSING,
-): KeycloakAdminError {
+export function createOrganisationseinheitError(
+  errorType: OrganisationseinheitErrorType = OrganisationseinheitErrorType.NAME_MISSING,
+): OrganisationseinheitError {
   return {
     errorType,
     detail: faker.lorem.sentence(10),
diff --git a/alfa-client/libs/api-root-shared/src/lib/api-root.service.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.service.ts
index e6af890e2510944a0dde237518a76a098df012de..838ea15956d589a0d0e71a65a7e2f02fc306aca9 100644
--- a/alfa-client/libs/api-root-shared/src/lib/api-root.service.ts
+++ b/alfa-client/libs/api-root-shared/src/lib/api-root.service.ts
@@ -54,9 +54,6 @@ export class ApiRootService {
       filter((apiRootStateResource: StateResource<ApiRootResource>) =>
         this.shouldEmit(apiRootStateResource),
       ),
-      tap((apiRootStateResource: StateResource<ApiRootResource>) => {
-        if (isDevMode()) console.debug('APIROOT SERVICE - GET - EMIT: ', apiRootStateResource);
-      }),
       startWith(createEmptyStateResource<ApiRootResource>(true)),
     );
   }
diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
index 972537e77f7862ce5da10ffd868c3ffa529d2060..edf33922bdf3321e33dd6da63e5e73dd0d86f1d7 100644
--- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts
@@ -206,11 +206,14 @@ describe('BescheidService', () => {
     const vorgangWithEingangResource: VorgangWithEingangResource =
       createVorgangWithEingangResource();
     const bescheidResource: BescheidResource = createBescheidResource();
-    const commandStateResource: StateResource<CommandResource> = createCommandStateResource();
+    const vorgangAbschliessenCommandStateResource: StateResource<CommandResource> =
+      createCommandStateResource();
 
     beforeEach(() => {
-      service.vorgangAbschliesen = jest.fn().mockReturnValue(of(createCommandStateResource()));
-      service.deleteBescheid = jest.fn().mockReturnValue(of(commandStateResource));
+      service.vorgangAbschliesen = jest
+        .fn()
+        .mockReturnValue(of(vorgangAbschliessenCommandStateResource));
+      service.deleteBescheid = jest.fn().mockReturnValue(of(createCommandStateResource));
     });
 
     it('should Bescheiderstellung überspringen', (done) => {
@@ -227,6 +230,10 @@ describe('BescheidService', () => {
     });
 
     it('should Bescheid löschen', (done) => {
+      service.vorgangAbschliesen = jest
+        .fn()
+        .mockReturnValue(of(createCommandStateResource([CommandLinkRel.EFFECTED_RESOURCE])));
+
       const command$: Observable<StateResource<CommandResource>> =
         service.bescheidLoeschenUndErstellungUeberspringen(
           vorgangWithEingangResource,
@@ -239,14 +246,29 @@ describe('BescheidService', () => {
       });
     });
 
-    it('should emit delete bescheid command', () => {
+    it('should not Bescheid löschen', (done) => {
+      service.vorgangAbschliesen = jest.fn().mockReturnValue(of(createCommandStateResource()));
+
       const command$: Observable<StateResource<CommandResource>> =
         service.bescheidLoeschenUndErstellungUeberspringen(
           vorgangWithEingangResource,
           bescheidResource,
         );
 
-      expect(command$).toBeObservable(cold('(a|)', { a: commandStateResource }));
+      command$.subscribe(() => {
+        expect(service.deleteBescheid).not.toHaveBeenCalledWith(bescheidResource);
+        done();
+      });
+    });
+
+    it('should emit vorgang abschliessen command', () => {
+      const command$: Observable<StateResource<CommandResource>> =
+        service.bescheidLoeschenUndErstellungUeberspringen(
+          vorgangWithEingangResource,
+          bescheidResource,
+        );
+
+      expect(command$).toBeObservable(cold('(a|)', { a: vorgangAbschliessenCommandStateResource }));
     });
   });
 
diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
index 73338e50f814496947c94341c78c13a149e78ff1..d875344cb9a5f0bf53c2304d82cbdff838242081 100644
--- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
+++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts
@@ -81,7 +81,7 @@ export class BescheidService {
     bescheidResource: BescheidResource,
   ): Observable<StateResource<CommandResource>> {
     return this.vorgangAbschliesen(vorgangWithEingangResource).pipe(
-      switchMap(() => this.deleteBescheid(bescheidResource)),
+      onCommandSuccessfullyDone(() => this.deleteBescheid(bescheidResource)),
     );
   }
 
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts
index 92e807edf17a80df5d90cc31e73f26a06bf97f47..3311716c86977541f2d114b2ef74d8b5db0cdd38 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.spec.ts
@@ -16,9 +16,9 @@ import { singleCold, singleHot } from './marbles';
 import { HttpErrorResponse } from '@angular/common/http';
 import { createProblemDetail } from 'libs/tech-shared/test/error';
 import { HttpError, ProblemDetail } from '../tech.model';
+import { cold } from 'jest-marbles';
 
 import * as ResourceUtil from './resource.util';
-import { cold } from 'jest-marbles';
 
 describe('ResourceService', () => {
   let service: ResourceService<Resource, Resource>;
@@ -475,14 +475,6 @@ describe('ResourceService', () => {
       service.loadResource = jest.fn();
     });
 
-    it('should throw error if stateresource is empty', () => {
-      service.stateResource.next(createEmptyStateResource());
-
-      expect(() => service.refresh()).toThrowError(
-        'No stateresource exists which can be refreshed.',
-      );
-    });
-
     it('should set reload true on statresource', () => {
       service.stateResource.next(createStateResource(createDummyResource()));
 
diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts
index 191966e2a8c7a4797e4b0f4b7008e7845f2a86e9..c14a661395d83c8b9ff53fd4286ff4a2f7d2211d 100644
--- a/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts
+++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.service.ts
@@ -54,9 +54,6 @@ export class ResourceService<B extends Resource, T extends Resource> {
       ),
       filter(([stateResource]) => !this.shouldFilter(stateResource)),
       map(([stateResource]) => stateResource),
-      tap((stateResource: StateResource<T>) => {
-        if (isDevMode()) console.debug('RESOURCE SERVICE - GET - EMIT:', stateResource);
-      }),
       startWith(createEmptyStateResource<T>(true)),
     );
   }
@@ -174,17 +171,9 @@ export class ResourceService<B extends Resource, T extends Resource> {
   }
 
   public refresh(): void {
-    this.verifyStateResource();
     this.stateResource.next({ ...this.stateResource.value, reload: true });
   }
 
-  private verifyStateResource(): void {
-    throwErrorOn(
-      isNull(this.getStateResource()),
-      'No stateresource exists which can be refreshed.',
-    );
-  }
-
   public canEdit(): boolean {
     return this.hasLinkRel(this.config.editLinkRel);
   }
diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts
index 62cba4d267093de5a9b242dbb478fb1a87dbac12..b9522ba3a35c7996c4ab026c6d1fd3d3088dc1f7 100644
--- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts
+++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-dialog/ozgcloud-dialog.service.ts
@@ -21,7 +21,7 @@ export class OzgcloudDialogService {
     );
   }
 
-  public open<T, D>(component: ComponentType<T>, data?: D): DialogRef<T> {
+  public open<T, D = undefined>(component: ComponentType<T>, data?: D): DialogRef<T> {
     return this.openDialog(component, this.buildDialogConfigWithData(data));
   }
 
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.model.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.model.ts
index cdaaba160035bd674b9b97b2560b716ba44c1e4f..c44625133f9a8739e215b4d72d33be87fbad044f 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.model.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/bescheiden.model.ts
@@ -5,7 +5,3 @@ export interface BescheidenDialogData {
   vorgangWithEingangResource: VorgangWithEingangResource;
   bescheidDraftResource?: BescheidResource;
 }
-
-export interface BescheiderstellungUeberspringenDialogData {
-  vorgangWithEingangResource: VorgangWithEingangResource;
-}
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-button/vorgang-detail-bescheiden-ueberspringen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-button/vorgang-detail-bescheiden-ueberspringen-button.component.spec.ts
index 5bd380e629b34379a00163a4d56479c2bb80a254..8edecfa1d44635b483abadfbcc1597d2f469fedf 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-button/vorgang-detail-bescheiden-ueberspringen-button.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-button/vorgang-detail-bescheiden-ueberspringen-button.component.spec.ts
@@ -3,25 +3,15 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { VorgangDetailBescheidenUeberspringenButtonComponent } from './vorgang-detail-bescheiden-ueberspringen-button.component';
 import { OzgcloudDialogService } from '@alfa-client/ui';
 import { VorgangDetailBescheidenUeberspringenDialogComponent } from '../vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component';
-import { BescheiderstellungUeberspringenDialogData } from '@alfa-client/vorgang-detail';
-import { BescheidenFormService } from '../../../bescheiden.formservice';
-import { createVorgangWithEingangResource } from '../../../../../../../../vorgang-shared/test/vorgang';
-import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 
 describe('VorgangDetailBescheidenUeberspringenButtonComponent', () => {
   let component: VorgangDetailBescheidenUeberspringenButtonComponent;
   let fixture: ComponentFixture<VorgangDetailBescheidenUeberspringenButtonComponent>;
 
   let ozgcloudDialogService: Mock<OzgcloudDialogService>;
-  let formService: Mock<BescheidenFormService>;
-  let vorgangWithEingangResource: VorgangWithEingangResource;
 
   beforeEach(async () => {
     ozgcloudDialogService = mock(OzgcloudDialogService);
-    formService = mock(BescheidenFormService);
-
-    vorgangWithEingangResource = createVorgangWithEingangResource();
-    formService.getVorgangWithEingangResource.mockReturnValue(vorgangWithEingangResource);
 
     await TestBed.configureTestingModule({
       declarations: [VorgangDetailBescheidenUeberspringenButtonComponent],
@@ -30,10 +20,6 @@ describe('VorgangDetailBescheidenUeberspringenButtonComponent', () => {
           provide: OzgcloudDialogService,
           useValue: ozgcloudDialogService,
         },
-        {
-          provide: BescheidenFormService,
-          useValue: formService,
-        },
       ],
     }).compileComponents();
 
@@ -52,7 +38,6 @@ describe('VorgangDetailBescheidenUeberspringenButtonComponent', () => {
 
       expect(ozgcloudDialogService.open).toHaveBeenCalledWith(
         VorgangDetailBescheidenUeberspringenDialogComponent,
-        { vorgangWithEingangResource } as BescheiderstellungUeberspringenDialogData,
       );
     });
   });
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-button/vorgang-detail-bescheiden-ueberspringen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-button/vorgang-detail-bescheiden-ueberspringen-button.component.ts
index 63b182124b45070ea84e6285feef13589053240a..29a02d750bfd143fee955ab724941638130a71b6 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-button/vorgang-detail-bescheiden-ueberspringen-button.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-button/vorgang-detail-bescheiden-ueberspringen-button.component.ts
@@ -2,8 +2,6 @@ import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { Component, Input } from '@angular/core';
 import { OzgcloudDialogService } from '@alfa-client/ui';
 import { VorgangDetailBescheidenUeberspringenDialogComponent } from '../vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component';
-import { BescheidenFormService } from '../../../bescheiden.formservice';
-import { BescheiderstellungUeberspringenDialogData } from '@alfa-client/vorgang-detail';
 
 @Component({
   selector: 'alfa-vorgang-detail-bescheiden-ueberspringen-button',
@@ -13,17 +11,11 @@ import { BescheiderstellungUeberspringenDialogData } from '@alfa-client/vorgang-
 export class VorgangDetailBescheidenUeberspringenButtonComponent {
   @Input() vorgang: VorgangWithEingangResource;
 
-  constructor(
-    private readonly ozgcloudDialogService: OzgcloudDialogService,
-    private formService: BescheidenFormService,
-  ) {}
+  constructor(private readonly ozgcloudDialogService: OzgcloudDialogService) {}
 
   public onClick(): void {
-    this.ozgcloudDialogService.open<
+    this.ozgcloudDialogService.open<VorgangDetailBescheidenUeberspringenDialogComponent>(
       VorgangDetailBescheidenUeberspringenDialogComponent,
-      BescheiderstellungUeberspringenDialogData
-    >(VorgangDetailBescheidenUeberspringenDialogComponent, {
-      vorgangWithEingangResource: this.formService.getVorgangWithEingangResource(),
-    });
+    );
   }
 }
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.spec.ts
index 3519995184aa0e2cdc205aa5121a80eadc943021..6f137b513da74467310382a6be5cee0dc96095dd 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.spec.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.spec.ts
@@ -1,13 +1,12 @@
 import { Mock, mock } from '@alfa-client/test-utils';
-import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';
-import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
+import { DialogRef } from '@angular/cdk/dialog';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { VorgangDetailBescheidenUeberspringenDialogComponent } from './vorgang-detail-bescheiden-ueberspringen-dialog.component';
 import { MockComponent } from 'ng-mocks';
 import { OzgcloudDialogService, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui';
 import { MatIcon } from '@angular/material/icon';
 import { BescheidService } from '@alfa-client/bescheid-shared';
-import { createVorgangWithEingangResource } from '../../../../../../../../vorgang-shared/test/vorgang';
-import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
+import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared';
 import { createCommandResource } from '../../../../../../../../command-shared/test/command';
 import { of } from 'rxjs';
 import { cold } from 'jest-marbles';
@@ -18,7 +17,7 @@ import {
 } from '@alfa-client/tech-shared';
 import { CommandLinkRel } from '../../../../../../../../command-shared/src/lib/command.linkrel';
 import { CommandResource } from '@alfa-client/command-shared';
-import { BescheiderstellungUeberspringenDialogData } from '../../../bescheiden.model';
+import { createVorgangWithEingangResource } from '../../../../../../../../vorgang-shared/test/vorgang';
 
 describe('VorgangDetailBescheidenUeberspringenButtonComponent', () => {
   let component: VorgangDetailBescheidenUeberspringenDialogComponent;
@@ -27,16 +26,13 @@ describe('VorgangDetailBescheidenUeberspringenButtonComponent', () => {
   let dialogRef: Mock<DialogRef>;
   let bescheidService: Mock<BescheidService>;
   let ozgcloudDialogService: Mock<OzgcloudDialogService>;
-  let dialogData: BescheiderstellungUeberspringenDialogData;
-  let vorgangWithEingangResource: VorgangWithEingangResource;
+  let vorgangService: Mock<VorgangService>;
 
   beforeEach(async () => {
     dialogRef = mock(DialogRef);
     bescheidService = mock(BescheidService);
     ozgcloudDialogService = mock(OzgcloudDialogService);
-
-    vorgangWithEingangResource = createVorgangWithEingangResource();
-    dialogData = { vorgangWithEingangResource };
+    vorgangService = mock(VorgangService);
 
     await TestBed.configureTestingModule({
       declarations: [
@@ -58,8 +54,8 @@ describe('VorgangDetailBescheidenUeberspringenButtonComponent', () => {
           useValue: ozgcloudDialogService,
         },
         {
-          provide: DIALOG_DATA,
-          useValue: dialogData,
+          provide: VorgangService,
+          useValue: vorgangService,
         },
       ],
     }).compileComponents();
@@ -82,23 +78,36 @@ describe('VorgangDetailBescheidenUeberspringenButtonComponent', () => {
   });
 
   describe('onConfirm', () => {
+    let vorgangWithEingangResource: VorgangWithEingangResource;
     const successfullyDoneCommandStateResource: StateResource<CommandResource> =
       createStateResource(createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]));
 
     beforeEach(() => {
+      vorgangWithEingangResource = createVorgangWithEingangResource();
+      vorgangService.getVorgangWithEingang.mockReturnValue(
+        of(createStateResource(vorgangWithEingangResource)),
+      );
       bescheidService.bescheidErstellungUeberspringen.mockReturnValue(
         of(successfullyDoneCommandStateResource),
       );
     });
 
-    it('should call bescheid service erstellung ueberspringen', fakeAsync(() => {
+    it('should get vorgang with eingang', () => {
       component.onConfirm();
-      tick();
 
-      expect(bescheidService.bescheidErstellungUeberspringen).toHaveBeenCalledWith(
-        vorgangWithEingangResource,
-      );
-    }));
+      expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled();
+    });
+
+    it('should call bescheid service erstellung ueberspringen', (done) => {
+      component.onConfirm();
+
+      component.bescheiderstellungUeberspringen$.subscribe(() => {
+        expect(bescheidService.bescheidErstellungUeberspringen).toHaveBeenCalledWith(
+          vorgangWithEingangResource,
+        );
+        done();
+      });
+    });
 
     it('should close all dialogs on success', (done) => {
       component.onConfirm();
diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.ts
index 9344ce4fdbaa22268d9f5815f5846a61bcbd4b34..fb622547196d4f327516babdc437e18d60c80581 100644
--- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.ts
+++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-bescheiden/vorgang-detail-bescheiden-steps/vorgang-detail-bescheiden-steps-content/vorgang-detail-bescheiden-ueberspringen-dialog/vorgang-detail-bescheiden-ueberspringen-dialog.component.ts
@@ -1,11 +1,11 @@
-import { Component, Inject } from '@angular/core';
-import { DIALOG_DATA, DialogRef } from '@angular/cdk/dialog';
+import { Component } from '@angular/core';
+import { DialogRef } from '@angular/cdk/dialog';
 import { OzgcloudDialogService } from '@alfa-client/ui';
 import { BescheidService } from '@alfa-client/bescheid-shared';
-import { Observable } from 'rxjs';
+import { filter, first, Observable, switchMap } from 'rxjs';
 import { CommandResource, onCommandSuccessfullyDone } from '@alfa-client/command-shared';
-import { StateResource } from '@alfa-client/tech-shared';
-import { BescheiderstellungUeberspringenDialogData } from '../../../bescheiden.model';
+import { isLoaded, StateResource } from '@alfa-client/tech-shared';
+import { VorgangService } from '@alfa-client/vorgang-shared';
 
 @Component({
   selector: 'alfa-vorgang-detail-bescheiden-ueberspringen-dialog',
@@ -18,7 +18,7 @@ export class VorgangDetailBescheidenUeberspringenDialogComponent {
     private readonly dialogRef: DialogRef,
     private readonly bescheidService: BescheidService,
     private readonly ozgcloudDialogService: OzgcloudDialogService,
-    @Inject(DIALOG_DATA) private readonly dialogData: BescheiderstellungUeberspringenDialogData,
+    private readonly vorgangService: VorgangService,
   ) {}
 
   public onClose(): void {
@@ -26,9 +26,17 @@ export class VorgangDetailBescheidenUeberspringenDialogComponent {
   }
 
   public onConfirm(): void {
-    this.bescheiderstellungUeberspringen$ = this.bescheidService
-      .bescheidErstellungUeberspringen(this.dialogData.vorgangWithEingangResource)
-      .pipe(onCommandSuccessfullyDone(() => this.ozgcloudDialogService.closeAll()));
+    this.bescheiderstellungUeberspringen$ = this.vorgangService.getVorgangWithEingang().pipe(
+      filter((stateResource) => isLoaded(stateResource)),
+      first(),
+      switchMap((stateResource) =>
+        this.bescheidService.bescheidErstellungUeberspringen(stateResource.resource).pipe(
+          onCommandSuccessfullyDone(() => {
+            this.ozgcloudDialogService.closeAll();
+          }),
+        ),
+      ),
+    );
   }
 
   public onCancel(): void {
diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.ts
index ca986c4d819a82b3eb10d046044a38b40eebe449..a9edc7a1382e7771c7ffaf00424c8b04ee2722e1 100644
--- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.ts
+++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.ts
@@ -72,9 +72,6 @@ export class VorgangService {
           );
       }),
       map(([vorgangWithEingang]) => vorgangWithEingang),
-      tap((vorgangWithEingang: StateResource<VorgangWithEingangResource>) => {
-        if (isDevMode()) console.debug('VORGANG SERVICE - GET - EMIT: ', vorgangWithEingang);
-      }),
       startWith(createEmptyStateResource<VorgangWithEingangResource>(true)),
     );
   }