diff --git a/src/app/app-root/admin-starter/admin-starter.component.html b/src/app/app-root/admin-starter/admin-starter.component.html
index f8c4e18e07e499c3e9a2c8eb87ce5215009004c3..fce919ea22ba017d1904748ca6cffd48a95467e8 100644
--- a/src/app/app-root/admin-starter/admin-starter.component.html
+++ b/src/app/app-root/admin-starter/admin-starter.component.html
@@ -6,13 +6,13 @@
         Sie sind mit Administrator-Funktionen angemeldet. Aktuell sind keine Studien für Sie freigegeben.
       </p>
       <button mat-raised-button color="primary" (click)="buttonGotoWorkspaceAdmin(ws)"
-              *ngFor="let ws of (mds.loginData$ | async)?.workspaces">
+              *ngFor="let ws of workspaces">
         {{ws.name}}
       </button>
     </div>
   </mat-card-content>
   <mat-card-actions>
-    <button mat-raised-button color="foreground" *ngIf="(mds.loginData$ | async)?.isSuperadmin" [routerLink]="['/superadmin']">System-Admin</button>
+    <button mat-raised-button color="foreground" *ngIf="mds.isSuperAdmin" [routerLink]="['/superadmin']">System-Admin</button>
     <button mat-raised-button color="foreground" (click)="resetLogin()">Neu anmelden</button>
   </mat-card-actions>
 </mat-card>
diff --git a/src/app/app-root/admin-starter/admin-starter.component.ts b/src/app/app-root/admin-starter/admin-starter.component.ts
index e9904c89f798e6365e333bb13a3957d7ac9c56d1..c49e095507e1d1c9613ef2f5e8c57c646643f96a 100644
--- a/src/app/app-root/admin-starter/admin-starter.component.ts
+++ b/src/app/app-root/admin-starter/admin-starter.component.ts
@@ -1,18 +1,35 @@
-import { Component } from '@angular/core';
+import {Component, OnInit} from '@angular/core';
 import {MainDataService} from "../../maindata.service";
-import {WorkspaceData} from "../../app.interfaces";
 import {Router} from "@angular/router";
 
+interface WorkspaceData {
+  id: string;
+  name: string;
+}
+
 @Component({
   templateUrl: './admin-starter.component.html',
 })
-export class AdminStarterComponent {
+
+export class AdminStarterComponent implements OnInit {
+  workspaces: WorkspaceData[] = [];
+  isSuperAdmin = false;
 
   constructor(
     private router: Router,
     public mds: MainDataService
   ) { }
 
+  ngOnInit() {
+    const workspaces = this.mds.workspaces;
+    for (let wsId of Object.keys(workspaces)) {
+      this.workspaces.push({
+        id: wsId,
+        name: workspaces[wsId],
+      })
+    }
+  }
+
   buttonGotoWorkspaceAdmin(ws: WorkspaceData) {
     this.router.navigateByUrl('/admin/' + ws.id.toString() + '/files');
   }
diff --git a/src/app/app-root/login/login.component.ts b/src/app/app-root/login/login.component.ts
index ad34ace69eea024a697400bb2e826b0cef261bbf..28a6356d4c07d8f7d5587939065e1629ee3410c9 100644
--- a/src/app/app-root/login/login.component.ts
+++ b/src/app/app-root/login/login.component.ts
@@ -59,17 +59,16 @@ export class LoginComponent  implements OnInit, OnDestroy {
           if ((loginData as LoginData).customTexts) {
             this.cts.addCustomTexts((loginData as LoginData).customTexts);
           }
-          this.mds.setNewLoginData(loginData as LoginData);
+          this.mds.setAuthData(loginData as LoginData);
 
           if (this.returnTo) {
             this.router.navigateByUrl(this.returnTo);
           } else {
-            const loginDataCleaned = this.mds.loginData$.getValue();
-            if (loginDataCleaned.adminToken.length > 0) {
+            if (this.mds.adminToken) {
               this.router.navigate(['../admin-starter'], {relativeTo: this.route});
-            } else if (loginDataCleaned.loginToken.length > 0) {
+            } else if (this.mds.loginToken) {
               this.router.navigate(['../code-input'], {relativeTo: this.route});
-            } else if (loginDataCleaned.personToken.length > 0) {
+            } else if (this.mds.personToken) {
               this.router.navigate(['../test-starter'], {relativeTo: this.route});
             } else {
               this.mds.appError$.next({
diff --git a/src/app/app-routing-guards.ts b/src/app/app-routing-guards.ts
index 2ba5fb0d6e004049db3cc032ed34a40328ad51d6..2faef97ab733f09c360b5d726a6832b8ba3647c6 100644
--- a/src/app/app-routing-guards.ts
+++ b/src/app/app-routing-guards.ts
@@ -14,5 +14,6 @@ export class AdminRouteActivateGuard implements CanActivate {
     next: ActivatedRouteSnapshot,
     state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
 
+    return true;
   }
 }
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 812657c438ab17e7a0ffa78aeab09787b485fb0c..8952f27ee6410be62940c8d7ad8d91d1adee13af 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -13,6 +13,7 @@ const routes: Routes = [
   {path: '', redirectTo: 'r', pathMatch: 'full'},
   {path: 'r', component: AppRootComponent,
     children: [
+      {path: '', redirectTo: 'login', pathMatch: 'full'},
       {path: 'login/:returnTo', component: LoginComponent},
       {path: 'about', component: AboutComponent},
       {path: 'check-starter', component: SysCheckStarterComponent},
diff --git a/src/app/app.interceptor.ts b/src/app/app.interceptor.ts
index fce9c80aa618271ae5a4d0f4fcb084a7823705f5..063f8c2c19016f73436f2eaa1c00e3d7885a7d87 100644
--- a/src/app/app.interceptor.ts
+++ b/src/app/app.interceptor.ts
@@ -11,25 +11,14 @@ export class AuthInterceptor implements HttpInterceptor {
   intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
 
     if (request.headers.get('AuthToken') !== null) {
-      return  next.handle(request);
+      return next.handle(request);
     }
 
-    const loginData = this.mds.loginData$.getValue();
-
-    let authData;
-    if (loginData === null) {
-      authData = {
-        l: '',
-        p: '',
-        at: ''
-      };
-    } else {
-      authData = {
-        l: loginData.loginToken,
-        p: loginData.personToken,
-        at: loginData.adminToken
-      };
-    }
+    const authData = {
+      l: this.mds.loginToken,
+      p: this.mds.personToken,
+      at: this.mds.adminToken
+    };
     const requestA = request.clone({
       setHeaders: {
         AuthToken: JSON.stringify(authData)
diff --git a/src/app/app.interfaces.ts b/src/app/app.interfaces.ts
index fddbc07419beeb9be4c3067fe58138107548ce01..000c661825b4308340d8299dd2bb94c6583e1d4f 100644
--- a/src/app/app.interfaces.ts
+++ b/src/app/app.interfaces.ts
@@ -20,7 +20,7 @@ export enum AuthType {
 }
 
 export interface AccessRightList {
-  [key: string]: string[];
+  [key: string]: string;
 }
 
 export interface AuthData {
diff --git a/src/app/maindata.service.ts b/src/app/maindata.service.ts
index 8f5326227a3d85f31dcb3d684994f6b447b4c1db..d46841f8af716f45d0265dec249cfe9077d61e1b 100644
--- a/src/app/maindata.service.ts
+++ b/src/app/maindata.service.ts
@@ -1,13 +1,16 @@
-import { BackendService } from './backend.service';
-import { BehaviorSubject, Subject, forkJoin } from 'rxjs';
-import { Injectable } from '@angular/core';
-import {AppError, LoginData} from './app.interfaces';
-import { CustomtextService, ServerError } from 'iqb-components';
-import { appconfig, customtextKeySeparator, CustomTextsDefList } from './app.config';
+import {BackendService} from './backend.service';
+import {BehaviorSubject, forkJoin, Subject} from 'rxjs';
+import {Injectable} from '@angular/core';
+import {AccessRightList, AppError, AuthData, AuthType, LoginData} from './app.interfaces';
+import {CustomtextService, ServerError} from 'iqb-components';
+import {appconfig, customtextKeySeparator, CustomTextsDefList} from './app.config';
+
+const localStorageAuthDataKey = 'iqb-tc';
 
 @Injectable({
   providedIn: 'root'
 })
+
 export class MainDataService {
   private static get defaultLoginData(): LoginData {
     return {
@@ -37,11 +40,77 @@ export class MainDataService {
   public postMessage$ = new Subject<MessageEvent>();
 
   public get adminToken(): string {
-    const myLoginData = this.loginData$.getValue();
-    if (myLoginData) {
-      return myLoginData.adminToken;
+    const authData = MainDataService.getAuthDataFromLocalStorage();
+    if (authData) {
+      if (authData.token) {
+        if (authData.authTypes.indexOf(AuthType.ADMIN) >= 0) {
+          return authData.token;
+        }
+      }
+    }
+    return '';
+  }
+  public get isSuperAdmin(): boolean {
+    const authData = MainDataService.getAuthDataFromLocalStorage();
+    if (authData) {
+      if (authData.token) {
+        if (authData.authTypes.indexOf(AuthType.SUPERADMIN) >= 0) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+  public get loginToken(): string {
+    const authData = MainDataService.getAuthDataFromLocalStorage();
+    if (authData) {
+      if (authData.token) {
+        if (authData.authTypes.indexOf(AuthType.LOGIN) >= 0) {
+          return authData.token;
+        }
+      }
+    }
+    return '';
+  }
+  public get personToken(): string {
+    const authData = MainDataService.getAuthDataFromLocalStorage();
+    if (authData) {
+      if (authData.token) {
+        if (authData.authTypes.indexOf(AuthType.PERSON) >= 0) {
+          return authData.token;
+        }
+      }
+    }
+    return '';
+  }
+
+  public get workspaces(): AccessRightList {
+    const authData = MainDataService.getAuthDataFromLocalStorage();
+    if (authData) {
+      if (authData.token) {
+        if (authData.authTypes.indexOf(AuthType.ADMIN) >= 0) {
+          return authData.accessRights;
+        }
+      }
+    }
+    return {};
+  }
+
+  private static getAuthDataFromLocalStorage(): AuthData {
+    const storageEntry = localStorage.getItem(localStorageAuthDataKey);
+    if (storageEntry !== null) {
+      if (storageEntry.length > 0) {
+        return JSON.parse(storageEntry as string);
+      }
+    }
+    return null;
+  }
+
+  private static setAuthDataToLocalStorage(authData: AuthData = null) {
+    if (authData) {
+      localStorage.setItem(localStorageAuthDataKey, JSON.stringify(authData));
     } else {
-      return '';
+      localStorage.removeItem(localStorageAuthDataKey);
     }
   }
 
@@ -55,10 +124,60 @@ export class MainDataService {
   }
 
   decrementDelayedProcessesCount() {
-    this.delayedProcessesCount$.next(this.delayedProcessesCount$.getValue() - 1);
+    const dpc = this.delayedProcessesCount$.getValue();
+    if (dpc > 0) {
+      this.delayedProcessesCount$.next(dpc - 1);
+    }
   }
 
-
+  setAuthData(loginData: LoginData = null) {
+    if (loginData) {
+      const authData = <AuthData>{
+        token: '',
+        authTypes: [],
+        displayName: '',
+        accessRights: {}
+      };
+      if (loginData.adminToken) {
+        authData.token = loginData.adminToken;
+        authData.displayName = loginData.name;
+        authData.authTypes.push(AuthType.ADMIN);
+        if (loginData.isSuperadmin) {
+          authData.authTypes.push(AuthType.SUPERADMIN);
+        }
+        for (let ws of loginData.workspaces) {
+          authData.accessRights[ws.id.toString()] = ws.name;
+        }
+        MainDataService.setAuthDataToLocalStorage(authData);
+      } else if (loginData.loginToken) {
+        authData.token = loginData.loginToken;
+        authData.displayName = loginData.name;
+        authData.authTypes.push(AuthType.LOGIN);
+        MainDataService.setAuthDataToLocalStorage(authData);
+      } else if (loginData.personToken) {
+        authData.token = loginData.personToken;
+        authData.displayName = loginData.name;
+        authData.authTypes.push(AuthType.PERSON);
+        if (loginData.code) {
+          const bookletList = loginData.booklets[loginData.code];
+          if (bookletList) {
+            for (let b of bookletList) {
+              authData.accessRights[b] = b;
+            }
+          }
+        } else {
+          for (let b of loginData.booklets[0]) {
+            authData.accessRights[b] = b;
+          }
+        }
+        MainDataService.setAuthDataToLocalStorage(authData);
+      } else {
+        MainDataService.setAuthDataToLocalStorage();
+      }
+    } else {
+      MainDataService.setAuthDataToLocalStorage();
+    }
+  }
 
   // ensures consistency
   setNewLoginData(logindata?: LoginData) {
@@ -163,12 +282,6 @@ export class MainDataService {
     return myLoginData.bookletLabel;
   }
 
-  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-  getPersonToken(): string {
-    const myLoginData = this.loginData$.getValue();
-    return myLoginData.personToken;
-  }
-
   public addCustomtextsFromDefList(customtextList: CustomTextsDefList) {
     const myCustomTexts: {[key: string]: string} = {};
     for (const ct of Object.keys(customtextList.defList)) {
diff --git a/src/app/superadmin/users/users.component.html b/src/app/superadmin/users/users.component.html
index 8fb6918e50d2e2c64195e33dbbf57924cb1a19da..7650653c7e6e95690b7f2546e835205c12114bd3 100644
--- a/src/app/superadmin/users/users.component.html
+++ b/src/app/superadmin/users/users.component.html
@@ -1,8 +1,4 @@
 <div class="columnhost" fxLayout="row" fxLayoutAlign="space-between start">
-  <div class="spinner" *ngIf="dataLoading">
-      <mat-spinner></mat-spinner>
-  </div>
-
   <!-- ============================================= -->
   <div class="objectlist" fxLayout="column" fxFlex="50">
     <div fxLayout="row">
@@ -23,7 +19,7 @@
       </button>
     </div>
 
-    <mat-table *ngIf="isSuperadmin" [dataSource]="objectsDatasource" matSort>
+    <mat-table [dataSource]="objectsDatasource" matSort>
       <ng-container matColumnDef="selectCheckbox">
         <mat-header-cell *matHeaderCellDef fxFlex="70px">
           <mat-checkbox (change)="$event ? masterToggle() : null"
@@ -51,7 +47,7 @@
   </div>
 
   <!-- ============================================= -->
-  <div *ngIf="isSuperadmin" fxLayout="column" fxFlex="40">
+  <div fxLayout="column" fxFlex="40">
 
     <div *ngIf="selectedUser < 0">
       <div>Zugriffsrechte für Arbeitsbereich(e):</div>
diff --git a/src/app/superadmin/users/users.component.ts b/src/app/superadmin/users/users.component.ts
index 196cb9057e8a55031576805cbbaaf2cb5d418a3d..5cc1cff63a818d50e7944ac963afdbe28242f893 100644
--- a/src/app/superadmin/users/users.component.ts
+++ b/src/app/superadmin/users/users.component.ts
@@ -2,7 +2,7 @@ import { NewpasswordComponent } from './newpassword/newpassword.component';
 import { NewuserComponent } from './newuser/newuser.component';
 import { BackendService } from '../backend.service';
 import { MatTableDataSource } from '@angular/material/table';
-import { ViewChild, OnDestroy } from '@angular/core';
+import { ViewChild } from '@angular/core';
 
 import { Component, OnInit } from '@angular/core';
 import { MatDialog } from '@angular/material/dialog';
@@ -12,9 +12,8 @@ import { FormGroup } from '@angular/forms';
 import { SelectionModel } from '@angular/cdk/collections';
 import {
   ConfirmDialogComponent, ConfirmDialogData, MessageDialogComponent,
-  MessageDialogData, MessageType
+  MessageDialogData, MessageType, ServerError
 } from 'iqb-components';
-import { Subscription } from 'rxjs';
 import { MainDataService } from 'src/app/maindata.service';
 import {IdRoleData, UserData} from "../superadmin.interfaces";
 import {SuperadminPasswordRequestComponent} from "../superadmin-password-request/superadmin-password-request.component";
@@ -24,20 +23,17 @@ import {SuperadminPasswordRequestComponent} from "../superadmin-password-request
   templateUrl: './users.component.html',
   styleUrls: ['./users.component.css']
 })
-export class UsersComponent implements OnInit, OnDestroy {
-  public isSuperadmin = false;
-  public dataLoading = false;
+export class UsersComponent implements OnInit {
   public objectsDatasource: MatTableDataSource<UserData>;
   public displayedColumns = ['selectCheckbox', 'name'];
   private tableselectionCheckbox = new SelectionModel<UserData>(true, []);
   private tableselectionRow = new SelectionModel<UserData>(false, []);
-  private selectedUser = -1;
+  public selectedUser = -1;
   private selectedUserName = '';
 
   private pendingWorkspaceChanges = false;
   public WorkspacelistDatasource: MatTableDataSource<IdRoleData>;
   public displayedWorkspaceColumns = ['selectCheckbox', 'label'];
-  private logindataSubscription: Subscription = null;
 
   @ViewChild(MatSort) sort: MatSort;
 
@@ -65,10 +61,7 @@ export class UsersComponent implements OnInit, OnDestroy {
   }
 
   ngOnInit() {
-    this.logindataSubscription = this.mds.loginData$.subscribe(ld => {
-      this.isSuperadmin = ld.isSuperadmin;
-      this.updateObjectList();
-    });
+    this.updateObjectList();
   }
 
   // ***********************************************************************************
@@ -80,6 +73,7 @@ export class UsersComponent implements OnInit, OnDestroy {
     dialogRef.afterClosed().subscribe(result => {
       if (typeof result !== 'undefined') {
         if (result !== false) {
+          this.mds.incrementDelayedProcessesCount();
           this.bs.addUser((<FormGroup>result).get('name').value,
               (<FormGroup>result).get('pw').value).subscribe(
                 respOk => {
@@ -89,6 +83,7 @@ export class UsersComponent implements OnInit, OnDestroy {
                   } else {
                     this.snackBar.open('Konnte Nutzer nicht hinzufügen', 'Fehler', {duration: 1000});
                   }
+                  this.mds.decrementDelayedProcessesCount();
                 });
         }
       }
@@ -131,7 +126,7 @@ export class UsersComponent implements OnInit, OnDestroy {
           passwdDialogRef.afterClosed().subscribe(result => {
             if (typeof result !== 'undefined') {
               if (result !== false) {
-                this.dataLoading = true;
+                this.mds.incrementDelayedProcessesCount();
                 this.bs.setSuperUserStatus(
                   selectedRows[0]['id'],
                   userObject.is_superadmin === '0',
@@ -142,7 +137,7 @@ export class UsersComponent implements OnInit, OnDestroy {
                     } else {
                       this.snackBar.open('Konnte Status nicht ändern', 'Fehler', {duration: 1000});
                     }
-                    this.dataLoading = false;
+                    this.mds.decrementDelayedProcessesCount();
                   });
               }
             }
@@ -175,7 +170,7 @@ export class UsersComponent implements OnInit, OnDestroy {
       dialogRef.afterClosed().subscribe(result => {
         if (typeof result !== 'undefined') {
           if (result !== false) {
-            this.dataLoading = true;
+            this.mds.incrementDelayedProcessesCount();
             this.bs.changePassword(selectedRows[0]['id'],
                 (<FormGroup>result).get('pw').value).subscribe(
                   respOk => {
@@ -184,7 +179,7 @@ export class UsersComponent implements OnInit, OnDestroy {
                     } else {
                       this.snackBar.open('Konnte Kennwort nicht ändern', 'Fehler', {duration: 1000});
                     }
-                    this.dataLoading = false;
+                    this.mds.decrementDelayedProcessesCount();
                   });
           }
         }
@@ -226,7 +221,7 @@ export class UsersComponent implements OnInit, OnDestroy {
       dialogRef.afterClosed().subscribe(result => {
         if (result !== false) {
           // =========================================================
-          this.dataLoading = true;
+          this.mds.incrementDelayedProcessesCount();
           const usersToDelete = [];
           selectedRows.forEach((r: UserData) => usersToDelete.push(r.id));
           this.bs.deleteUsers(usersToDelete).subscribe(
@@ -234,12 +229,11 @@ export class UsersComponent implements OnInit, OnDestroy {
               if (respOk !== false) {
                 this.snackBar.open('Nutzer gelöscht', '', {duration: 1000});
                 this.updateObjectList();
-                this.dataLoading = false;
               } else {
                 this.snackBar.open('Konnte Nutzer nicht löschen', 'Fehler', {duration: 2000});
-                this.dataLoading = false;
               }
-          });
+              this.mds.decrementDelayedProcessesCount();
+            });
         }
       });
     }
@@ -249,11 +243,19 @@ export class UsersComponent implements OnInit, OnDestroy {
   updateWorkspaceList() {
     this.pendingWorkspaceChanges = false;
     if (this.selectedUser > -1) {
-      this.dataLoading = true;
+      this.mds.incrementDelayedProcessesCount();
       this.bs.getWorkspacesByUser(this.selectedUser).subscribe(dataresponse => {
+        if (dataresponse instanceof ServerError) {
+          this.mds.appError$.next({
+            label: (dataresponse as ServerError).labelNice,
+            description: (dataresponse as ServerError).labelSystem,
+            category: "PROBLEM"
+          });
+        } else {
           this.WorkspacelistDatasource = new MatTableDataSource(dataresponse);
-          this.dataLoading = false;
-        });
+        }
+        this.mds.decrementDelayedProcessesCount()
+      })
     } else {
       this.WorkspacelistDatasource = null;
     }
@@ -271,7 +273,7 @@ export class UsersComponent implements OnInit, OnDestroy {
   saveWorkspaces() {
     this.pendingWorkspaceChanges = false;
     if (this.selectedUser > -1) {
-      this.dataLoading = true;
+      this.mds.incrementDelayedProcessesCount();
       this.bs.setWorkspacesByUser(this.selectedUser, this.WorkspacelistDatasource.data).subscribe(
         respOk => {
           if (respOk !== false) {
@@ -279,7 +281,7 @@ export class UsersComponent implements OnInit, OnDestroy {
           } else {
             this.snackBar.open('Konnte Zugriffsrechte nicht ändern', 'Fehler', {duration: 2000});
           }
-          this.dataLoading = false;
+          this.mds.decrementDelayedProcessesCount();
         });
     } else {
       this.WorkspacelistDatasource = null;
@@ -288,18 +290,22 @@ export class UsersComponent implements OnInit, OnDestroy {
 
   // ***********************************************************************************
   updateObjectList() {
-    if (this.isSuperadmin) {
-      this.dataLoading = true;
-      this.tableselectionCheckbox.clear();
-      this.tableselectionRow.clear();
-      this.bs.getUsers().subscribe(dataresponse => {
-        console.log(dataresponse);
-          this.objectsDatasource = new MatTableDataSource(dataresponse);
-          this.objectsDatasource.sort = this.sort;
-          this.dataLoading = false;
-        }
-      );
-    }
+    this.mds.incrementDelayedProcessesCount();
+    this.tableselectionCheckbox.clear();
+    this.tableselectionRow.clear();
+    this.bs.getUsers().subscribe(dataresponse => {
+      if (dataresponse instanceof ServerError) {
+        this.mds.appError$.next({
+          label: (dataresponse as ServerError).labelNice,
+          description: (dataresponse as ServerError).labelSystem,
+          category: "PROBLEM"
+        });
+      } else {
+        this.objectsDatasource = new MatTableDataSource(dataresponse);
+        this.objectsDatasource.sort = this.sort;
+      }
+      this.mds.decrementDelayedProcessesCount();
+    });
   }
 
   isAllSelected() {
@@ -317,11 +323,4 @@ export class UsersComponent implements OnInit, OnDestroy {
   selectRow(row) {
     this.tableselectionRow.select(row);
   }
-
-  // % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
-  ngOnDestroy() {
-    if (this.logindataSubscription !== null) {
-      this.logindataSubscription.unsubscribe();
-    }
-  }
 }
diff --git a/src/app/superadmin/workspaces/workspaces.component.html b/src/app/superadmin/workspaces/workspaces.component.html
index 42e9e3cf8b132892820d0bc71cce327c08b327d4..9c62182bc765904d40e8495d7f555dedab121f29 100644
--- a/src/app/superadmin/workspaces/workspaces.component.html
+++ b/src/app/superadmin/workspaces/workspaces.component.html
@@ -1,9 +1,4 @@
 <div class="columnhost" fxLayout="row" fxLayoutAlign="space-between start">
-  <div class="spinner" *ngIf="dataLoading">
-      <mat-spinner></mat-spinner>
-  </div>
-
-  <!-- ============================================= -->
   <div class="objectlist" fxLayout="column" fxFlex="50">
     <div fxLayout="row">
         <button mat-raised-button (click)="addObject()" matTooltip="Arbeitsbereich hinzufügen" matTooltipPosition="above">
@@ -18,7 +13,7 @@
         </button>
     </div>
 
-    <mat-table *ngIf="isSuperadmin" [dataSource]="objectsDatasource" matSort>
+    <mat-table [dataSource]="objectsDatasource" matSort>
       <ng-container matColumnDef="selectCheckbox">
         <mat-header-cell *matHeaderCellDef fxFlex="70px">
           <mat-checkbox (change)="$event ? masterToggle() : null"
@@ -46,7 +41,7 @@
   </div>
 
   <!-- ============================================= -->
-  <div *ngIf="isSuperadmin" fxLayout="column" fxFlex="40">
+  <div fxLayout="column" fxFlex="40">
 
     <div *ngIf="selectedWorkspaceId == 0">
       <div>Zugriffsberechtigte für Arbeitsbereich:</div>
diff --git a/src/app/superadmin/workspaces/workspaces.component.ts b/src/app/superadmin/workspaces/workspaces.component.ts
index 885f1168f9a362a5bbf8e21066f1a2a66f56da5a..6f3c29c140b569d17ed71839635728c7fbd66166 100644
--- a/src/app/superadmin/workspaces/workspaces.component.ts
+++ b/src/app/superadmin/workspaces/workspaces.component.ts
@@ -2,8 +2,7 @@ import { EditworkspaceComponent } from './editworkspace/editworkspace.component'
 import { NewworkspaceComponent } from './newworkspace/newworkspace.component';
 import { BackendService } from '../backend.service';
 import { MatTableDataSource } from '@angular/material/table';
-import { ViewChild, OnDestroy } from '@angular/core';
-
+import { ViewChild } from '@angular/core';
 import { Component, OnInit } from '@angular/core';
 import { MatDialog } from '@angular/material/dialog';
 import { MatSnackBar } from '@angular/material/snack-bar';
@@ -14,7 +13,6 @@ import {
   ConfirmDialogComponent, ConfirmDialogData,
   MessageDialogComponent, MessageDialogData, MessageType
 } from 'iqb-components';
-import { Subscription } from 'rxjs';
 import { MainDataService } from 'src/app/maindata.service';
 import {IdAndName, IdRoleData} from "../superadmin.interfaces";
 
@@ -22,17 +20,13 @@ import {IdAndName, IdRoleData} from "../superadmin.interfaces";
   templateUrl: './workspaces.component.html',
   styleUrls: ['./workspaces.component.css']
 })
-export class WorkspacesComponent implements OnInit, OnDestroy {
-  public isSuperadmin = false;
-  public dataLoading = false;
+export class WorkspacesComponent implements OnInit {
   public objectsDatasource: MatTableDataSource<IdAndName>;
   public displayedColumns = ['selectCheckbox', 'name'];
   private tableselectionCheckbox = new SelectionModel <IdAndName>(true, []);
   private tableselectionRow = new SelectionModel <IdAndName>(false, []);
-  private selectedWorkspaceId = 0;
+  public selectedWorkspaceId = 0;
   private selectedWorkspaceName = '';
-  private logindataSubscription: Subscription = null;
-
   private pendingUserChanges = false;
   public UserlistDatasource: MatTableDataSource<IdRoleData>;
   public displayedUserColumns = ['selectCheckbox', 'name'];
@@ -62,10 +56,7 @@ export class WorkspacesComponent implements OnInit, OnDestroy {
   }
 
   ngOnInit() {
-    this.logindataSubscription = this.mds.loginData$.subscribe(ld => {
-      this.isSuperadmin = ld.isSuperadmin;
-      this.updateObjectList();
-    });
+    this.updateObjectList();
   }
 
   // ***********************************************************************************
@@ -80,17 +71,17 @@ export class WorkspacesComponent implements OnInit, OnDestroy {
     dialogRef.afterClosed().subscribe(result => {
       if (typeof result !== 'undefined') {
         if (result !== false) {
-          this.dataLoading = true;
+          this.mds.incrementDelayedProcessesCount();
           this.bs.addWorkspace((<FormGroup>result).get('name').value).subscribe(
-                respOk => {
-                  if (respOk !== false) {
-                    this.snackBar.open('Arbeitsbereich hinzugefügt', '', {duration: 1000});
-                    this.updateObjectList();
-                  } else {
-                    this.snackBar.open('Konnte Arbeitsbereich nicht hinzufügen', 'Fehler', {duration: 1000});
-                  }
-                  this.dataLoading = false;
-                });
+            respOk => {
+              if (respOk !== false) {
+                this.snackBar.open('Arbeitsbereich hinzugefügt', '', {duration: 1000});
+                this.updateObjectList();
+              } else {
+                this.snackBar.open('Konnte Arbeitsbereich nicht hinzufügen', 'Fehler', {duration: 1000});
+              }
+              this.mds.decrementDelayedProcessesCount();
+            });
         }
       }
     });
@@ -119,7 +110,7 @@ export class WorkspacesComponent implements OnInit, OnDestroy {
       dialogRef.afterClosed().subscribe(result => {
         if (typeof result !== 'undefined') {
           if (result !== false) {
-            this.dataLoading = true;
+            this.mds.incrementDelayedProcessesCount();
             this.bs.renameWorkspace(selectedRows[0].id,
                 (<FormGroup>result).get('name').value).subscribe(
                   respOk => {
@@ -129,7 +120,7 @@ export class WorkspacesComponent implements OnInit, OnDestroy {
                     } else {
                       this.snackBar.open('Konnte Arbeitsbereich nicht ändern', 'Fehler', {duration: 2000});
                     }
-                    this.dataLoading = false;
+                    this.mds.decrementDelayedProcessesCount();
                   });
           }
         }
@@ -171,7 +162,7 @@ export class WorkspacesComponent implements OnInit, OnDestroy {
       dialogRef.afterClosed().subscribe(result => {
         if (result !== false) {
           // =========================================================
-          this.dataLoading = true;
+          this.mds.incrementDelayedProcessesCount();
           const workspacesToDelete = [];
           selectedRows.forEach((r: IdAndName) => workspacesToDelete.push(r.id));
           this.bs.deleteWorkspaces(workspacesToDelete).subscribe(
@@ -179,11 +170,10 @@ export class WorkspacesComponent implements OnInit, OnDestroy {
               if (respOk !== false) {
                 this.snackBar.open('Arbeitsbereich/e gelöscht', '', {duration: 1000});
                 this.updateObjectList();
-                this.dataLoading = false;
               } else {
                 this.snackBar.open('Konnte Arbeitsbereich/e nicht löschen', 'Fehler', {duration: 1000});
-                this.dataLoading = false;
               }
+              this.mds.decrementDelayedProcessesCount();
           });
         }
       });
@@ -194,11 +184,11 @@ export class WorkspacesComponent implements OnInit, OnDestroy {
   updateUserList() {
     this.pendingUserChanges = false;
     if (this.selectedWorkspaceId > 0) {
-      this.dataLoading = true;
+      this.mds.incrementDelayedProcessesCount();
       this.bs.getUsersByWorkspace(this.selectedWorkspaceId).subscribe(dataresponse => {
-          this.UserlistDatasource = new MatTableDataSource(dataresponse);
-          this.dataLoading = false;
-        });
+        this.UserlistDatasource = new MatTableDataSource(dataresponse);
+        this.mds.decrementDelayedProcessesCount();
+      });
     } else {
       this.UserlistDatasource = null;
     }
@@ -216,7 +206,7 @@ export class WorkspacesComponent implements OnInit, OnDestroy {
   saveUsers() {
     this.pendingUserChanges = false;
     if (this.selectedWorkspaceId > 0) {
-      this.dataLoading = true;
+      this.mds.incrementDelayedProcessesCount();
       this.bs.setUsersByWorkspace(this.selectedWorkspaceId, this.UserlistDatasource.data).subscribe(
         respOk => {
           if (respOk !== false) {
@@ -224,7 +214,7 @@ export class WorkspacesComponent implements OnInit, OnDestroy {
           } else {
             this.snackBar.open('Konnte Zugriffsrechte nicht ändern', 'Fehler', {duration: 2000});
           }
-          this.dataLoading = false;
+          this.mds.decrementDelayedProcessesCount();
         });
     } else {
       this.UserlistDatasource = null;
@@ -233,17 +223,14 @@ export class WorkspacesComponent implements OnInit, OnDestroy {
 
   // ***********************************************************************************
   updateObjectList() {
-    if (this.isSuperadmin) {
-      this.dataLoading = true;
-      this.bs.getWorkspaces().subscribe(dataresponse => {
-          this.objectsDatasource = new MatTableDataSource(dataresponse);
-          this.objectsDatasource.sort = this.sort;
-          this.tableselectionCheckbox.clear();
-          this.tableselectionRow.clear();
-          this.dataLoading = false;
-        }
-      );
-    }
+    this.mds.incrementDelayedProcessesCount();
+    this.bs.getWorkspaces().subscribe(dataresponse => {
+      this.objectsDatasource = new MatTableDataSource(dataresponse);
+      this.objectsDatasource.sort = this.sort;
+      this.tableselectionCheckbox.clear();
+      this.tableselectionRow.clear();
+      this.mds.decrementDelayedProcessesCount();
+    });
   }
 
   isAllSelected() {
@@ -261,11 +248,4 @@ export class WorkspacesComponent implements OnInit, OnDestroy {
   selectRow(row) {
     this.tableselectionRow.select(row);
   }
-
-  // % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
-  ngOnDestroy() {
-    if (this.logindataSubscription !== null) {
-      this.logindataSubscription.unsubscribe();
-    }
-  }
 }
diff --git a/src/app/workspace-admin/backend.service.ts b/src/app/workspace-admin/backend.service.ts
index d092983c3ade64497b8e6ac382efceba6f9c623a..cafe10923b55d06c2095fb53528b7de62c7eb88e 100644
--- a/src/app/workspace-admin/backend.service.ts
+++ b/src/app/workspace-admin/backend.service.ts
@@ -5,6 +5,7 @@ import { HttpClient } from '@angular/common/http';
 import { Observable } from 'rxjs';
 import { catchError } from 'rxjs/operators';
 import { ErrorHandler, ServerError } from 'iqb-components';
+import {WorkspaceDataService} from "./workspacedata.service";
 
 @Injectable({
   providedIn: 'root'
@@ -14,79 +15,80 @@ export class BackendService {
 
   constructor(
     @Inject('SERVER_URL') private readonly serverUrl: string,
+    private wds: WorkspaceDataService,
     private http: HttpClient
   ) {
   }
 
 
-  getFiles(workspaceId: number): Observable<GetFileResponseData[] | ServerError> {
+  getFiles(): Observable<GetFileResponseData[] | ServerError> {
 
     return this.http
-      .get<GetFileResponseData[]>(this.serverUrl + `workspace/${workspaceId}/files`)
+      .get<GetFileResponseData[]>(this.serverUrl + `workspace/${this.wds.wsId}/files`)
       .pipe(catchError(ErrorHandler.handle));
   }
 
-  deleteFiles(workspaceId: number, filesToDelete: Array<string>): Observable<FileDeletionReport | ServerError> {
+  deleteFiles(filesToDelete: Array<string>): Observable<FileDeletionReport | ServerError> {
 
     return this.http
-      .request<FileDeletionReport>('delete', this.serverUrl + `workspace/${workspaceId}/files`, {body: {f: filesToDelete}})
+      .request<FileDeletionReport>('delete', this.serverUrl + `workspace/${this.wds.wsId}/files`, {body: {f: filesToDelete}})
       .pipe(catchError(ErrorHandler.handle));
   }
 
-  checkWorkspace(workspaceId: number): Observable<CheckWorkspaceResponseData | ServerError> {
+  checkWorkspace(): Observable<CheckWorkspaceResponseData | ServerError> {
 
     return this.http
-      .get<CheckWorkspaceResponseData>(this.serverUrl + `workspace/${workspaceId}/validation`, {})
+      .get<CheckWorkspaceResponseData>(this.serverUrl + `workspace/${this.wds.wsId}/validation`, {})
       .pipe(catchError(ErrorHandler.handle));
   }
 
-  getResultData(workspaceId: number): Observable<ResultData[]> {
+  getResultData(): Observable<ResultData[]> {
 
     return this.http
-      .get<ResultData[]>(this.serverUrl + `workspace/${workspaceId}/results`, {})
+      .get<ResultData[]>(this.serverUrl + `workspace/${this.wds.wsId}/results`, {})
       .pipe(catchError(() => []));
   }
 
-  getResponses(workspaceId: number, groups: string[]): Observable<UnitResponse[]> {
+  getResponses(groups: string[]): Observable<UnitResponse[]> {
 
     return this.http
-      .get<UnitResponse[]>(this.serverUrl + `workspace/${workspaceId}/responses`, {params: {groups: groups.join(',')}})
+      .get<UnitResponse[]>(this.serverUrl + `workspace/${this.wds.wsId}/responses`, {params: {groups: groups.join(',')}})
       .pipe(catchError(() => []));
   }
 
-  getLogs(workspaceId: number, groups: string[]): Observable<LogData[]> {
+  getLogs(groups: string[]): Observable<LogData[]> {
 
     return this.http
-      .get<LogData[]>(this.serverUrl + `workspace/${workspaceId}/logs`, {params: {groups: groups.join(',')}})
+      .get<LogData[]>(this.serverUrl + `workspace/${this.wds.wsId}/logs`, {params: {groups: groups.join(',')}})
       .pipe(catchError(() => []));
   }
 
-  getReviews(workspaceId: number, groups: string[]): Observable<ReviewData[]> {
+  getReviews(groups: string[]): Observable<ReviewData[]> {
 
     return this.http
-      .get<ReviewData[]>(this.serverUrl + `workspace/${workspaceId}/reviews`, {params: {groups: groups.join(',')}})
+      .get<ReviewData[]>(this.serverUrl + `workspace/${this.wds.wsId}/reviews`, {params: {groups: groups.join(',')}})
       .pipe(catchError(() => []));
   }
 
-  deleteData(workspaceId: number, groups: string[]): Observable<boolean | ServerError> {
+  deleteData(groups: string[]): Observable<boolean | ServerError> {
 
     return this.http
-      .request<boolean>('delete', this.serverUrl + `workspace/${workspaceId}/responses`, {body: {groups: groups}})
+      .request<boolean>('delete', this.serverUrl + `workspace/${this.wds.wsId}/responses`, {body: {groups: groups}})
       .pipe(catchError(ErrorHandler.handle));
   }
 
-  getSysCheckReportList(workspaceId: number): Observable<SysCheckStatistics[] | ServerError> {
+  getSysCheckReportList(): Observable<SysCheckStatistics[] | ServerError> {
 
     return this.http
-      .get<ReviewData[]>(this.serverUrl + `workspace/${workspaceId}/sys-check/reports/overview`)
+      .get<ReviewData[]>(this.serverUrl + `workspace/${this.wds.wsId}/sys-check/reports/overview`)
       .pipe(catchError(() => []));
   }
 
-  getSysCheckReport(workspaceId: number, reports: string[], enclosure: string, columnDelimiter: string, lineEnding: string)
+  getSysCheckReport(reports: string[], enclosure: string, columnDelimiter: string, lineEnding: string)
     : Observable<Blob|ServerError> {
 
     return this.http
-      .get(this.serverUrl + `workspace/${workspaceId}/sys-check/reports`,
+      .get(this.serverUrl + `workspace/${this.wds.wsId}/sys-check/reports`,
         {
           params: {
             checkIds: reports.join(','),
@@ -102,17 +104,17 @@ export class BackendService {
       .pipe(catchError(ErrorHandler.handle));
   }
 
-  deleteSysCheckReports(workspaceId: number, checkIds: string[]): Observable <FileDeletionReport|ServerError> {
+  deleteSysCheckReports(checkIds: string[]): Observable <FileDeletionReport|ServerError> {
 
     return this.http
-      .request<FileDeletionReport>('delete', this.serverUrl + `workspace/${workspaceId}/sys-check/reports`, {body: {checkIds: checkIds}})
+      .request<FileDeletionReport>('delete', this.serverUrl + `workspace/${this.wds.wsId}/sys-check/reports`, {body: {checkIds: checkIds}})
       .pipe(catchError(ErrorHandler.handle));
   }
 
-  downloadFile(workspaceId: number, fileType: string, fileName: string): Observable<Blob|ServerError> {
+  downloadFile(fileType: string, fileName: string): Observable<Blob|ServerError> {
 
     return this.http
-      .get(this.serverUrl + `workspace/${workspaceId}/file/${fileType}/${fileName}`, {responseType: 'blob'})
+      .get(this.serverUrl + `workspace/${this.wds.wsId}/file/${fileType}/${fileName}`, {responseType: 'blob'})
       .pipe(catchError(ErrorHandler.handle));
   }
 }
diff --git a/src/app/workspace-admin/files/files.component.html b/src/app/workspace-admin/files/files.component.html
index 34fa536f5628895698c06c40cf71877d4d4dedb4..dc91133db8451b90ad7fbc0d8274dd22ffe90467 100644
--- a/src/app/workspace-admin/files/files.component.html
+++ b/src/app/workspace-admin/files/files.component.html
@@ -1,8 +1,4 @@
 <div class="columnhost">
-  <div class="spinner" *ngIf="dataLoading">
-      <mat-spinner></mat-spinner>
-  </div>
-
   <!-- ============================================= -->
   <div class="filelist">
     <mat-table #table [dataSource]="serverfiles" matSort>
diff --git a/src/app/workspace-admin/files/files.component.ts b/src/app/workspace-admin/files/files.component.ts
index 06ced970feba139dffbcfabf5535e2b66962ad7a..d0d011979861def380271fe9d2ed67471e9565a8 100644
--- a/src/app/workspace-admin/files/files.component.ts
+++ b/src/app/workspace-admin/files/files.component.ts
@@ -3,11 +3,10 @@ import { WorkspaceDataService } from '../workspacedata.service';
 import { GetFileResponseData, CheckWorkspaceResponseData } from '../workspace.interfaces';
 import { ConfirmDialogComponent, ConfirmDialogData, MessageDialogComponent,
   MessageDialogData, MessageType, ServerError } from 'iqb-components';
-import { Subscription } from 'rxjs';
 import { MatTableDataSource } from '@angular/material/table';
 import { MatSnackBar } from '@angular/material/snack-bar';
 import {BackendService, FileDeletionReport} from '../backend.service';
-import { Component, OnInit, Inject, OnDestroy } from '@angular/core';
+import { Component, OnInit, Inject } from '@angular/core';
 import { ViewChild } from '@angular/core';
 import { MatDialog } from '@angular/material/dialog';
 import { MatSort } from '@angular/material/sort';
@@ -17,11 +16,9 @@ import { saveAs } from 'file-saver';
   templateUrl: './files.component.html',
   styleUrls: ['./files.component.css']
 })
-export class FilesComponent implements OnInit, OnDestroy {
+export class FilesComponent implements OnInit {
   public serverfiles: MatTableDataSource<GetFileResponseData>;
   public displayedColumns = ['checked', 'filename', 'typelabel', 'filesize', 'filedatetime'];
-  public dataLoading = false;
-  private workspaceIdSubscription: Subscription = null;
 
   // for fileupload
   public uploadUrl = '';
@@ -42,17 +39,11 @@ export class FilesComponent implements OnInit, OnDestroy {
     public confirmDialog: MatDialog,
     public messsageDialog: MatDialog,
     public snackBar: MatSnackBar
-  ) {
-    this.wds.workspaceId$.subscribe(workspaceId => {
-      this.uploadUrl = this.serverUrl + `workspace/${workspaceId}/file`;
-    });
-    this.uploadUrl = this.serverUrl + "workspace/" + this.wds.ws + '/file';
-  }
+  ) { }
 
   ngOnInit() {
-    this.workspaceIdSubscription = this.wds.workspaceId$.subscribe(() => {
-      this.updateFileList((this.wds.ws <= 0) || (this.mds.adminToken.length === 0));
-    });
+    this.uploadUrl = `${this.serverUrl}workspace/${this.wds.wsId}/file`;
+    this.updateFileList();
   }
 
   // ***********************************************************************************
@@ -96,12 +87,15 @@ export class FilesComponent implements OnInit, OnDestroy {
         dialogRef.afterClosed().subscribe(result => {
           if (result !== false) {
             // =========================================================
-            this.dataLoading = true;
-            this.bs.deleteFiles(this.wds.ws, filesToDelete).subscribe((fileDeletionReport: FileDeletionReport|ServerError) => {
+            this.mds.incrementDelayedProcessesCount();
+            this.bs.deleteFiles(filesToDelete).subscribe((fileDeletionReport: FileDeletionReport|ServerError) => {
               if (fileDeletionReport instanceof ServerError) {
-                this.wds.setNewErrorMsg(fileDeletionReport as ServerError);
+                this.mds.appError$.next({
+                  label: (fileDeletionReport as ServerError).labelNice,
+                  description: (fileDeletionReport as ServerError).labelSystem,
+                  category: "PROBLEM"
+                });
               } else {
-
                 const message = [];
                 if (fileDeletionReport.deleted.length > 0) {
                   message.push(fileDeletionReport.deleted.length + ' Dateien erfolgreich gelöscht.');
@@ -109,12 +103,10 @@ export class FilesComponent implements OnInit, OnDestroy {
                 if (fileDeletionReport.not_allowed.length > 0) {
                   message.push(fileDeletionReport.not_allowed.length + ' Dateien konnten nicht gelöscht werden.');
                 }
-
                 this.snackBar.open(message.join('<br>'), message.length > 1 ? 'Achtung' : '',  {duration: 1000});
-
                 this.updateFileList();
-                this.wds.setNewErrorMsg();
               }
+              this.mds.decrementDelayedProcessesCount();
             });
             // =========================================================
           }
@@ -141,16 +133,19 @@ export class FilesComponent implements OnInit, OnDestroy {
     if (empty || this.wds.wsRole === 'MO') {
       this.serverfiles = new MatTableDataSource([]);
     } else {
-      this.dataLoading = true;
-      this.bs.getFiles(this.wds.ws).subscribe(
+      this.mds.incrementDelayedProcessesCount();
+      this.bs.getFiles().subscribe(
         (filedataresponse: GetFileResponseData[]) => {
           this.serverfiles = new MatTableDataSource(filedataresponse);
           this.serverfiles.sort = this.sort;
-          this.dataLoading = false;
-          this.wds.setNewErrorMsg();
+          this.mds.decrementDelayedProcessesCount();
         }, (err: ServerError) => {
-          this.wds.setNewErrorMsg(err);
-          this.dataLoading = false;
+          this.mds.appError$.next({
+            label: err.labelNice,
+            description: err.labelSystem,
+            category: "PROBLEM"
+          });
+          this.mds.decrementDelayedProcessesCount();
         }
       );
     }
@@ -159,17 +154,20 @@ export class FilesComponent implements OnInit, OnDestroy {
 
   download(element: GetFileResponseData): void {
 
-    this.dataLoading = true;
-    this.bs.downloadFile(this.wds.ws, element.type, element.filename)
+    this.mds.incrementDelayedProcessesCount();
+    this.bs.downloadFile(element.type, element.filename)
       .subscribe(
         (fileData: Blob|ServerError) => {
           if (fileData instanceof ServerError) {
-            this.wds.setNewErrorMsg(fileData);
-            this.dataLoading = false;
+            this.mds.appError$.next({
+              label: (fileData as ServerError).labelNice,
+              description: (fileData as ServerError).labelSystem,
+              category: "PROBLEM"
+            });
+            this.mds.decrementDelayedProcessesCount();
           } else {
             saveAs(fileData, element.filename);
-            this.wds.setNewErrorMsg();
-            this.dataLoading = false;
+            this.mds.decrementDelayedProcessesCount();
           }
         }
       );
@@ -181,26 +179,21 @@ export class FilesComponent implements OnInit, OnDestroy {
     this.checkWarnings = [];
     this.checkInfos = [];
 
-    this.dataLoading = true;
-    this.bs.checkWorkspace(this.wds.ws).subscribe(
+    this.mds.incrementDelayedProcessesCount();
+    this.bs.checkWorkspace().subscribe(
       (checkResponse: CheckWorkspaceResponseData) => {
         this.checkErrors = checkResponse.errors;
         this.checkWarnings = checkResponse.warnings;
         this.checkInfos = checkResponse.infos;
-        this.wds.setNewErrorMsg();
-
-        this.dataLoading = false;
+        this.mds.decrementDelayedProcessesCount();
       }, (err: ServerError) => {
-        this.wds.setNewErrorMsg(err);
-        this.dataLoading = false;
+        this.mds.appError$.next({
+          label: err.labelNice,
+          description: err.labelSystem,
+          category: "PROBLEM"
+        });
+        this.mds.decrementDelayedProcessesCount();
       }
     );
   }
-
-  // % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
-  ngOnDestroy() {
-    if (this.workspaceIdSubscription !== null) {
-      this.workspaceIdSubscription.unsubscribe();
-    }
-  }
 }
diff --git a/src/app/workspace-admin/results/results.component.html b/src/app/workspace-admin/results/results.component.html
index 6f5c106a753c2a320b11b1f176d2b8b19da3d702..ab74cc95766ec2979e32c87b058c627596f7b054 100644
--- a/src/app/workspace-admin/results/results.component.html
+++ b/src/app/workspace-admin/results/results.component.html
@@ -1,7 +1,4 @@
 <div class="columnhost" fxLayout="column">
-  <div class="spinner" *ngIf="dataLoading">
-    <mat-spinner></mat-spinner>
-  </div>
   <div fxLayout="row">
     <button mat-raised-button (click)="downloadResponsesCSV()" [disabled]="!tableselectionCheckbox.hasValue()"
         matTooltip="Download markierte Gruppen als CSV für Excel" matTooltipPosition="above">
diff --git a/src/app/workspace-admin/results/results.component.ts b/src/app/workspace-admin/results/results.component.ts
index ee8e19cc464427d310f928bef24ff4d9f60f3e04..8ff72ef4a318a43bd648aee3681cec3641a8ba4f 100644
--- a/src/app/workspace-admin/results/results.component.ts
+++ b/src/app/workspace-admin/results/results.component.ts
@@ -1,7 +1,7 @@
 import { LogData } from '../workspace.interfaces';
 import { WorkspaceDataService } from '../workspacedata.service';
-import { ConfirmDialogComponent, ConfirmDialogData } from 'iqb-components';
-import { Component, OnInit, ViewChild, OnDestroy } from '@angular/core';
+import {ConfirmDialogComponent, ConfirmDialogData, ServerError} from 'iqb-components';
+import { Component, OnInit, ViewChild } from '@angular/core';
 import { BackendService } from '../backend.service';
 import { MatDialog } from '@angular/material/dialog';
 import { MatSnackBar } from '@angular/material/snack-bar';
@@ -10,20 +10,18 @@ import { MatTableDataSource } from '@angular/material/table';
 import { SelectionModel } from '@angular/cdk/collections';
 import { saveAs } from 'file-saver';
 import { ResultData, UnitResponse, ReviewData } from '../workspace.interfaces';
-import { Subscription } from 'rxjs';
+import {MainDataService} from "../../maindata.service";
 
 
 @Component({
   templateUrl: './results.component.html',
   styleUrls: ['./results.component.css']
 })
-export class ResultsComponent implements OnInit, OnDestroy {
+export class ResultsComponent implements OnInit {
   displayedColumns: string[] = ['selectCheckbox', 'groupname', 'bookletsStarted', 'num_units_min', 'num_units_max', 'num_units_mean', 'lastchange'];
   public resultDataSource = new MatTableDataSource<ResultData>([]);
   // prepared for selection if needed sometime
   public tableselectionCheckbox = new SelectionModel<ResultData>(true, []);
-  public dataLoading = false;
-  private workspaceIdSubscription: Subscription = null;
 
   @ViewChild(MatSort, { static: true }) sort: MatSort;
 
@@ -31,13 +29,12 @@ export class ResultsComponent implements OnInit, OnDestroy {
     private bs: BackendService,
     public wds: WorkspaceDataService,
     private deleteConfirmDialog: MatDialog,
+    private mds: MainDataService,
     public snackBar: MatSnackBar
   ) { }
 
   ngOnInit() {
-    this.workspaceIdSubscription = this.wds.workspaceId$.subscribe(() => {
-      this.updateTable();
-    });
+    this.updateTable();
   }
 
   updateTable() {
@@ -45,12 +42,19 @@ export class ResultsComponent implements OnInit, OnDestroy {
     if (this.wds.wsRole === 'MO') {
       this.resultDataSource = new MatTableDataSource<ResultData>([]);
     } else {
-      this.dataLoading = true;
-      this.bs.getResultData(this.wds.ws).subscribe(
+      this.mds.incrementDelayedProcessesCount();
+      this.bs.getResultData().subscribe(
         (resultData: ResultData[]) => {
-          this.dataLoading = false;
+          this.mds.decrementDelayedProcessesCount();
           this.resultDataSource = new MatTableDataSource<ResultData>(resultData);
           this.resultDataSource.sort = this.sort;
+        }, (err: ServerError) => {
+          this.mds.appError$.next({
+            label: err.labelNice,
+            description: err.labelSystem,
+            category: "PROBLEM"
+          });
+          this.mds.decrementDelayedProcessesCount();
         }
       );
     }
@@ -71,12 +75,12 @@ export class ResultsComponent implements OnInit, OnDestroy {
   // 444444444444444444444444444444444444444444444444444444444444444444444444444444444444444
   downloadResponsesCSV() {
     if (this.tableselectionCheckbox.selected.length > 0) {
-      this.dataLoading = true;
+      this.mds.incrementDelayedProcessesCount();
       const selectedGroups: string[] = [];
       this.tableselectionCheckbox.selected.forEach(element => {
         selectedGroups.push(element.groupname);
       });
-      this.bs.getResponses(this.wds.ws, selectedGroups).subscribe(
+      this.bs.getResponses(selectedGroups).subscribe(
       (responseData: UnitResponse[]) => {
         if (responseData.length > 0) {
           const columnDelimiter = ';';
@@ -126,20 +130,27 @@ export class ResultsComponent implements OnInit, OnDestroy {
           this.snackBar.open('Keine Daten verfügbar.', 'Fehler', {duration: 3000});
         }
         this.tableselectionCheckbox.clear();
-        this.dataLoading = false;
-    });
+        this.mds.decrementDelayedProcessesCount();
+      }, (err: ServerError) => {
+          this.mds.appError$.next({
+            label: err.labelNice,
+            description: err.labelSystem,
+            category: "PROBLEM"
+          });
+          this.mds.decrementDelayedProcessesCount();
+      });
     }
   }
 
   // 444444444444444444444444444444444444444444444444444444444444444444444444444444444444444
   downloadReviewsCSV() {
     if (this.tableselectionCheckbox.selected.length > 0) {
-      this.dataLoading = true;
+      this.mds.incrementDelayedProcessesCount();
       const selectedGroups: string[] = [];
       this.tableselectionCheckbox.selected.forEach(element => {
         selectedGroups.push(element.groupname);
       });
-      this.bs.getReviews(this.wds.ws, selectedGroups).subscribe(
+      this.bs.getReviews(selectedGroups).subscribe(
       (responseData: ReviewData[]) => {
         if (responseData.length > 0) {
           // collect categories
@@ -188,7 +199,14 @@ export class ResultsComponent implements OnInit, OnDestroy {
           this.snackBar.open('Keine Daten verfügbar.', 'Fehler', {duration: 3000});
         }
         this.tableselectionCheckbox.clear();
-        this.dataLoading = false;
+        this.mds.decrementDelayedProcessesCount();
+      }, (err: ServerError) => {
+          this.mds.appError$.next({
+            label: err.labelNice,
+            description: err.labelSystem,
+            category: "PROBLEM"
+          });
+          this.mds.decrementDelayedProcessesCount();
       });
     }
   }
@@ -196,12 +214,12 @@ export class ResultsComponent implements OnInit, OnDestroy {
   // 444444444444444444444444444444444444444444444444444444444444444444444444444444444444444
   downloadLogsCSV() {
     if (this.tableselectionCheckbox.selected.length > 0) {
-      this.dataLoading = true;
+      this.mds.incrementDelayedProcessesCount();
       const selectedGroups: string[] = [];
       this.tableselectionCheckbox.selected.forEach(element => {
         selectedGroups.push(element.groupname);
       });
-      this.bs.getLogs(this.wds.ws, selectedGroups).subscribe(
+      this.bs.getLogs(selectedGroups).subscribe(
       (responseData: LogData[]) => {
         if (responseData.length > 0) {
           const columnDelimiter = ';';
@@ -222,7 +240,14 @@ export class ResultsComponent implements OnInit, OnDestroy {
           this.snackBar.open('Keine Daten verfügbar.', 'Fehler', {duration: 3000});
         }
         this.tableselectionCheckbox.clear();
-        this.dataLoading = false;
+        this.mds.decrementDelayedProcessesCount();
+      }, (err: ServerError) => {
+          this.mds.appError$.next({
+            label: err.labelNice,
+            description: err.labelSystem,
+            category: "PROBLEM"
+          });
+          this.mds.decrementDelayedProcessesCount();
       });
     }
   }
@@ -254,21 +279,21 @@ export class ResultsComponent implements OnInit, OnDestroy {
       dialogRef.afterClosed().subscribe(result => {
         if (result !== false) {
           // =========================================================
-          this.dataLoading = true;
-          this.bs.deleteData(this.wds.ws, selectedGroups).subscribe(() => {
+          this.mds.incrementDelayedProcessesCount();
+          this.bs.deleteData(selectedGroups).subscribe(() => {
               this.tableselectionCheckbox.clear();
-              this.dataLoading = false;
+              this.mds.decrementDelayedProcessesCount();
               // TODO refresh list!
+          }, (err: ServerError) => {
+            this.mds.appError$.next({
+              label: err.labelNice,
+              description: err.labelSystem,
+              category: "PROBLEM"
             });
-          }
-        });
-    }
-  }
-
-  // % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
-  ngOnDestroy() {
-    if (this.workspaceIdSubscription !== null) {
-      this.workspaceIdSubscription.unsubscribe();
+            this.mds.decrementDelayedProcessesCount();
+          });
+        }
+      });
     }
   }
 }
diff --git a/src/app/workspace-admin/syscheck/syscheck.component.html b/src/app/workspace-admin/syscheck/syscheck.component.html
index efec8749ba166abf4e3abf465ac7c1893b66a9f2..37712264c7f206a43da0861a27c3312400718163 100644
--- a/src/app/workspace-admin/syscheck/syscheck.component.html
+++ b/src/app/workspace-admin/syscheck/syscheck.component.html
@@ -1,7 +1,4 @@
 <div class="columnhost" fxLayout="column">
-  <div class="spinner" *ngIf="dataLoading">
-    <mat-spinner></mat-spinner>
-  </div>
   <div fxLayout="row" fxLayoutGap="10px">
     <button mat-raised-button (click)="downloadReportsCSV()" [disabled]="!tableselectionCheckbox.hasValue()"
         matTooltip="Download Berichte als CSV für Excel" matTooltipPosition="above">
diff --git a/src/app/workspace-admin/syscheck/syscheck.component.ts b/src/app/workspace-admin/syscheck/syscheck.component.ts
index b075f597791043cfabd84f9409064164afe5f253..960d7b1cb03cf35e981400ae9f34ad8d942aa292 100644
--- a/src/app/workspace-admin/syscheck/syscheck.component.ts
+++ b/src/app/workspace-admin/syscheck/syscheck.component.ts
@@ -8,7 +8,7 @@ import { MatTableDataSource } from '@angular/material/table';
 import { SelectionModel } from '@angular/cdk/collections';
 import { saveAs } from 'file-saver';
 import { SysCheckStatistics } from '../workspace.interfaces';
-import { WorkspaceDataService } from '../workspacedata.service';
+import {MainDataService} from "../../maindata.service";
 
 
 @Component({
@@ -20,14 +20,13 @@ export class SyscheckComponent implements OnInit {
   public resultDataSource = new MatTableDataSource<SysCheckStatistics>([]);
   // prepared for selection if needed sometime
   public tableselectionCheckbox = new SelectionModel<SysCheckStatistics>(true, []);
-  public dataLoading = false;
 
   @ViewChild(MatSort, { static: true }) sort: MatSort;
 
   constructor(
     private bs: BackendService,
     private deleteConfirmDialog: MatDialog,
-    public wds: WorkspaceDataService,
+    private mds: MainDataService,
     public snackBar: MatSnackBar
   ) {
   }
@@ -37,13 +36,20 @@ export class SyscheckComponent implements OnInit {
   }
 
   updateTable() {
-    this.dataLoading = true;
+    this.mds.incrementDelayedProcessesCount();
     this.tableselectionCheckbox.clear();
-    this.bs.getSysCheckReportList(this.wds.ws).subscribe(
+    this.bs.getSysCheckReportList().subscribe(
       (resultData: SysCheckStatistics[]) => {
-        this.dataLoading = false;
+        this.mds.decrementDelayedProcessesCount();
         this.resultDataSource = new MatTableDataSource<SysCheckStatistics>(resultData);
         this.resultDataSource.sort = this.sort;
+      }, (err: ServerError) => {
+        this.mds.appError$.next({
+          label: err.labelNice,
+          description: err.labelSystem,
+          category: "PROBLEM"
+        });
+        this.mds.decrementDelayedProcessesCount();
       }
     );
   }
@@ -62,15 +68,14 @@ export class SyscheckComponent implements OnInit {
 
 
   downloadReportsCSV() {
-
     if (this.tableselectionCheckbox.selected.length > 0) {
-      this.dataLoading = true;
+      this.mds.incrementDelayedProcessesCount();
       const selectedReports: string[] = [];
       this.tableselectionCheckbox.selected.forEach(element => {
         selectedReports.push(element.id);
       });
       // TODO determine OS dependent line ending char and use this
-      this.bs.getSysCheckReport(this.wds.ws, selectedReports, ';', '"', '\n').subscribe(
+      this.bs.getSysCheckReport(selectedReports, ';', '"', '\n').subscribe(
       (reportData: Blob) => {
         if (reportData.size > 0) {
           saveAs(reportData, 'iqb-testcenter-syscheckreports.csv');
@@ -78,8 +83,15 @@ export class SyscheckComponent implements OnInit {
           this.snackBar.open('Keine Daten verfügbar.', 'Fehler', {duration: 3000});
         }
         this.tableselectionCheckbox.clear();
-        this.dataLoading = false;
-    });
+        this.mds.decrementDelayedProcessesCount();
+      }, (err: ServerError) => {
+          this.mds.appError$.next({
+            label: err.labelNice,
+            description: err.labelSystem,
+            category: "PROBLEM"
+          });
+          this.mds.decrementDelayedProcessesCount();
+      });
     }
   }
 
@@ -108,16 +120,17 @@ export class SyscheckComponent implements OnInit {
       });
 
       dialogRef.afterClosed().subscribe(result => {
-
         if (result !== false) {
-
-          this.dataLoading = true;
-          this.bs.deleteSysCheckReports(this.wds.ws, selectedReports).subscribe((fileDeletionReport) => {
-
+          this.mds.incrementDelayedProcessesCount();
+          this.bs.deleteSysCheckReports(selectedReports).subscribe((fileDeletionReport) => {
             if (fileDeletionReport instanceof ServerError) {
-              this.wds.setNewErrorMsg(fileDeletionReport as ServerError);
+              this.mds.appError$.next({
+                label: (fileDeletionReport as ServerError).labelNice,
+                description: (fileDeletionReport as ServerError).labelSystem,
+                category: "PROBLEM"
+              });
+              this.mds.decrementDelayedProcessesCount();
             } else {
-
               const message = [];
               if (fileDeletionReport.deleted.length > 0) {
                 message.push(fileDeletionReport.deleted.length + ' Dateien erfolgreich gelöscht.');
@@ -125,11 +138,9 @@ export class SyscheckComponent implements OnInit {
               if (fileDeletionReport.not_allowed.length > 0) {
                 message.push(fileDeletionReport.not_allowed.length + ' Dateien konnten nicht gelöscht werden.');
               }
-
               this.snackBar.open(message.join('<br>'), message.length > 1 ? 'Achtung' : '', {duration: 1000});
-
               this.updateTable();
-              this.wds.setNewErrorMsg();
+              this.mds.decrementDelayedProcessesCount();
             }
           });
         }
diff --git a/src/app/workspace-admin/workspace.component.ts b/src/app/workspace-admin/workspace.component.ts
index 3958ab13f6ac91b3d8f3915e181c4d71ae02594c..78d2fbb04c760084d163a296195d8759fa144ccc 100644
--- a/src/app/workspace-admin/workspace.component.ts
+++ b/src/app/workspace-admin/workspace.component.ts
@@ -11,7 +11,6 @@ import { Component, OnInit, OnDestroy } from '@angular/core';
 })
 export class WorkspaceComponent implements OnInit, OnDestroy {
   private routingSubscription: Subscription = null;
-  private logindataSubscription: Subscription = null;
 
   constructor(
     private route: ActivatedRoute,
@@ -21,22 +20,17 @@ export class WorkspaceComponent implements OnInit, OnDestroy {
 
   ngOnInit() {
     this.routingSubscription = this.route.params.subscribe(params => {
-      const ws = Number(params['ws']);
-      this.wds.setWorkspace(ws);
-    });
-
-    this.logindataSubscription = this.mds.loginData$.subscribe(() => {
-      this.wds.setWorkspace(this.wds.ws);
+      this.wds.wsId = params['ws'];
+      const wsList = this.mds.workspaces;
+      if (wsList && wsList[this.wds.wsId]) {
+        this.wds.wsName = wsList[this.wds.wsId];
+      }
     });
   }
 
-
   ngOnDestroy() {
     if (this.routingSubscription !== null) {
       this.routingSubscription.unsubscribe();
     }
-    if (this.logindataSubscription !== null) {
-      this.logindataSubscription.unsubscribe();
-    }
   }
 }
diff --git a/src/app/workspace-admin/workspacedata.service.ts b/src/app/workspace-admin/workspacedata.service.ts
index 1ad6f0061db1c0b221e74806862009147d89211e..e9b641ddb12fc40edda26414aaa8e62678c3f7b4 100644
--- a/src/app/workspace-admin/workspacedata.service.ts
+++ b/src/app/workspace-admin/workspacedata.service.ts
@@ -1,7 +1,4 @@
-import { BehaviorSubject } from 'rxjs';
 import { Injectable } from '@angular/core';
-import { ServerError } from 'iqb-components';
-import { MainDataService } from "../maindata.service";
 
 @Injectable({
   providedIn: 'root'
@@ -9,50 +6,13 @@ import { MainDataService } from "../maindata.service";
 
 @Injectable()
 export class WorkspaceDataService {
-  public workspaceId$ = new BehaviorSubject<number>(-1);
-  public globalErrorMsg$ = new BehaviorSubject<ServerError>(null);
+  public wsId = '';
+  public wsRole = 'RW';
+  public wsName = '';
 
-  public get ws(): number {
-    return this.workspaceId$.getValue();
-  }
-  private _wsRole = '';
-  public get wsRole(): string {
-    return this._wsRole;
-  }
-  private _wsName = '';
-  public get wsName(): string {
-    return this._wsName;
-  }
   public navLinks = [
     {path: 'files', label: 'Dateien'},
     {path: 'syscheck', label: 'System-Check Berichte'},
     {path: 'results', label: 'Ergebnisse/Antworten'}
   ];
-
-  constructor(
-    private mds: MainDataService
-  ) {}
-
-  setNewErrorMsg(err: ServerError = null) {
-    this.globalErrorMsg$.next(err);
-  }
-
-  setWorkspace(newId: number) {
-    this._wsName = '';
-    this._wsRole = '';
-    if (newId > 0) {
-      const myLoginData = this.mds.loginData$.getValue();
-      if ((myLoginData !== null) && (myLoginData.workspaces.length > 0)) {
-        for (let i = 0; i < myLoginData.workspaces.length; i++) {
-          if (myLoginData.workspaces[i].id == newId) {
-            this._wsName = myLoginData.workspaces[i].name;
-            this._wsRole = myLoginData.workspaces[i].role;
-            break;
-          }
-        }
-      }
-    }
-
-    this.workspaceId$.next(newId);
-  }
 }