diff --git a/package-lock.json b/package-lock.json
index 063c14cf8d..24fe0a7e1e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,7 +19,7 @@
"@angular/platform-browser-dynamic": "^13.2.6",
"@angular/router": "^13.2.6",
"@ckeditor/ckeditor5-angular": "^2.0.2",
- "@dasch-swiss/dsp-js": "^6.2.2",
+ "@dasch-swiss/dsp-js": "^7.0.0",
"@datadog/browser-rum": "^3.11.0",
"@ngx-translate/core": "^13.0.0",
"@ngx-translate/http-loader": "6.0.0",
@@ -2425,9 +2425,9 @@
}
},
"node_modules/@dasch-swiss/dsp-js": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/@dasch-swiss/dsp-js/-/dsp-js-6.2.2.tgz",
- "integrity": "sha512-ng7vCVdBfcfFn39u8XvVyGcMRyPjMyGCiFHPYdBhmE9AFa2qT0JA5WAGqSF8/gIF24UEhbpzW48m1R37L+sHTw==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@dasch-swiss/dsp-js/-/dsp-js-7.0.0.tgz",
+ "integrity": "sha512-MM58ipXipltAPm0eAdjNZnCc3SzTE5U6HB+VhVGYP24/fk73ptcpMV6It0Axw9XlJNUh/+34DcpqA04l4T2hgA==",
"dependencies": {
"@babel/helper-compilation-targets": "^7.16.7",
"@types/jsonld": "^1.5.6",
@@ -17009,9 +17009,9 @@
}
},
"@dasch-swiss/dsp-js": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/@dasch-swiss/dsp-js/-/dsp-js-6.2.2.tgz",
- "integrity": "sha512-ng7vCVdBfcfFn39u8XvVyGcMRyPjMyGCiFHPYdBhmE9AFa2qT0JA5WAGqSF8/gIF24UEhbpzW48m1R37L+sHTw==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@dasch-swiss/dsp-js/-/dsp-js-7.0.0.tgz",
+ "integrity": "sha512-MM58ipXipltAPm0eAdjNZnCc3SzTE5U6HB+VhVGYP24/fk73ptcpMV6It0Axw9XlJNUh/+34DcpqA04l4T2hgA==",
"requires": {
"@babel/helper-compilation-targets": "^7.16.7",
"@types/jsonld": "^1.5.6",
diff --git a/package.json b/package.json
index b9de77c5fd..94e91937c7 100644
--- a/package.json
+++ b/package.json
@@ -33,7 +33,7 @@
"@angular/platform-browser-dynamic": "^13.2.6",
"@angular/router": "^13.2.6",
"@ckeditor/ckeditor5-angular": "^2.0.2",
- "@dasch-swiss/dsp-js": "^6.2.2",
+ "@dasch-swiss/dsp-js": "^7.0.0",
"@datadog/browser-rum": "^3.11.0",
"@ngx-translate/core": "^13.0.0",
"@ngx-translate/http-loader": "6.0.0",
diff --git a/src/app/main/action/login-form/login-form.component.html b/src/app/main/action/login-form/login-form.component.html
index 5466b9c05e..3ba5c31be1 100644
--- a/src/app/main/action/login-form/login-form.component.html
+++ b/src/app/main/action/login-form/login-form.component.html
@@ -40,7 +40,7 @@
(click)="login()"
type="submit"
class="full-width submit-button"
- [disabled]="!form.valid"
+ [disabled]="!form?.valid"
[class.mat-primary]="!isError"
[class.mat-warn]="isError">
diff --git a/src/app/main/action/login-form/login-form.component.ts b/src/app/main/action/login-form/login-form.component.ts
index 9cea257fc1..a0fbdf5279 100644
--- a/src/app/main/action/login-form/login-form.component.ts
+++ b/src/app/main/action/login-form/login-form.component.ts
@@ -1,8 +1,7 @@
-import { AfterViewInit, Component, ElementRef, EventEmitter, Inject, Input, OnInit, Output, ViewChild } from '@angular/core';
+import { AfterViewInit, Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
-import { ApiResponseData, ApiResponseError, KnoraApiConnection, LoginResponse, LogoutResponse } from '@dasch-swiss/dsp-js';
-import { CacheService } from '../../cache/cache.service';
+import { ApiResponseData, ApiResponseError, KnoraApiConnection, LoginResponse } from '@dasch-swiss/dsp-js';
import { DspApiConnectionToken } from '../../declarations/dsp-api-tokens';
import { ErrorHandlerService } from '../../error/error-handler.service';
import { AuthenticationService } from '../../services/authentication.service';
diff --git a/src/app/main/dialog/dialog.component.html b/src/app/main/dialog/dialog.component.html
index 2c7fbecd97..3c7207ab8b 100644
--- a/src/app/main/dialog/dialog.component.html
+++ b/src/app/main/dialog/dialog.component.html
@@ -408,7 +408,7 @@
diff --git a/src/app/main/dialog/dialog.component.ts b/src/app/main/dialog/dialog.component.ts
index bfb51d3e0a..3e2bbac7e9 100644
--- a/src/app/main/dialog/dialog.component.ts
+++ b/src/app/main/dialog/dialog.component.ts
@@ -1,5 +1,5 @@
-import { Component, Inject, OnInit, ViewChild } from '@angular/core';
-import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { ReadResource } from '@dasch-swiss/dsp-js';
import { PropertyInfoObject } from 'src/app/project/ontology/default-data/default-properties';
import { FilteredResources } from 'src/app/workspace/results/list-view/list-view.component';
@@ -21,6 +21,7 @@ export interface DialogData {
projectCode?: string;
selectedResources?: FilteredResources;
resourceClassDefinition?: string;
+ fullSize?: boolean;
}
export interface ConfirmationWithComment {
@@ -42,7 +43,12 @@ export class DialogComponent implements OnInit {
constructor(
public dialogRef: MatDialogRef,
@Inject(MAT_DIALOG_DATA) public data: DialogData
- ) { }
+ ) {
+ if (this.data.fullSize) {
+ // do not animate the dialog box
+ this.dialogRef.addPanelClass('full-size-dialog');
+ }
+ }
ngOnInit() { }
diff --git a/src/app/main/error/error-handler.service.spec.ts b/src/app/main/error/error-handler.service.spec.ts
index 4084068a60..4c841bd543 100644
--- a/src/app/main/error/error-handler.service.spec.ts
+++ b/src/app/main/error/error-handler.service.spec.ts
@@ -1,24 +1,37 @@
+import { OverlayContainer } from '@angular/cdk/overlay';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
-import { MatDialogModule } from '@angular/material/dialog';
+import { MatDialog, MatDialogModule, MatDialogRef } from '@angular/material/dialog';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { HealthEndpointSystem, MockHealth } from '@dasch-swiss/dsp-js';
+import { of } from 'rxjs';
import { DspApiConnectionToken } from '../declarations/dsp-api-tokens';
+import { DialogComponent } from '../dialog/dialog.component';
import { ErrorHandlerService } from './error-handler.service';
describe('ErrorHandlerService', () => {
+ let httpTestingController: HttpTestingController;
let service: ErrorHandlerService;
+ let overlayContainer: OverlayContainer;
+
+ let dialog: MatDialog;
beforeEach(() => {
const apiEndpointSpyObj = {
v2: {
auth: jasmine.createSpyObj('auth', ['logout'])
+ },
+ system: {
+ healthEndpoint: jasmine.createSpyObj('healthEndpoint', ['getHealthStatus'])
}
};
TestBed.configureTestingModule({
imports: [
BrowserAnimationsModule,
+ HttpClientTestingModule,
MatDialogModule,
MatSnackBarModule
],
@@ -27,12 +40,50 @@ describe('ErrorHandlerService', () => {
provide: DspApiConnectionToken,
useValue: apiEndpointSpyObj
},
+ {
+ provide: MatDialog,
+ useValue: { open: () => of({ id: 1 }) }
+ }
]
});
service = TestBed.inject(ErrorHandlerService);
+
+ httpTestingController = TestBed.inject(HttpTestingController);
+
+ const dspConnSpy = TestBed.inject(DspApiConnectionToken);
+ (dspConnSpy.system.healthEndpoint as jasmine.SpyObj).getHealthStatus.and.callFake(
+ () => {
+ const health = MockHealth.mockStopped();
+ return of(health);
+ }
+ );
+
+ overlayContainer = TestBed.inject(OverlayContainer);
+
+ dialog = TestBed.inject(MatDialog);
+ });
+
+ afterEach(() => {
+ httpTestingController.verify();
+ });
+
+ afterEach(async () => {
+ // angular won't call this for us so we need to do it ourselves to avoid leaks.
+ overlayContainer.ngOnDestroy();
});
it('should be created', () => {
expect(service).toBeTruthy();
});
+
+ it('api is not healthy: should return 503 server error', () => {
+
+ const error = require('../../../assets/test-data/api-error-0.json');
+
+ service.showMessage(error);
+
+ spyOn(dialog, 'open').and.returnValue({ afterClosed: () => of({ id: 1 }) } as MatDialogRef);
+ expect(dialog).toBeDefined();
+
+ });
});
diff --git a/src/app/main/error/error-handler.service.ts b/src/app/main/error/error-handler.service.ts
index c289684f52..6d22c2d4c3 100644
--- a/src/app/main/error/error-handler.service.ts
+++ b/src/app/main/error/error-handler.service.ts
@@ -1,6 +1,6 @@
import { Inject, Injectable } from '@angular/core';
import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
-import { ApiResponseData, ApiResponseError, KnoraApiConnection, LogoutResponse } from '@dasch-swiss/dsp-js';
+import { ApiResponseData, ApiResponseError, HealthResponse, KnoraApiConnection, LogoutResponse } from '@dasch-swiss/dsp-js';
import { StatusMsg } from 'src/assets/http/statusMsg';
import { DspApiConnectionToken } from '../declarations/dsp-api-tokens';
import { DialogComponent } from '../dialog/dialog.component';
@@ -25,9 +25,33 @@ export class ErrorHandlerService {
// in case of (internal) server error
const apiServerError = (error.error && !error.error['response']);
+ const apiResponseMessage = (error.error['response'] ? error.error['response'].error : undefined);
+
if ((error.status > 499 && error.status < 600) || apiServerError) {
- const status = (apiServerError ? 503 : error.status);
+ let status = (apiServerError ? 503 : error.status);
+
+ // check if the api is healthy:
+ this._dspApiConnection.system.healthEndpoint.getHealthStatus().subscribe(
+ (response: ApiResponseData) => {
+ if (response.body.status === 'unhealthy') {
+ const healthError: ApiResponseError = {
+ error: response.body.message,
+ method: response.method,
+ status: 500,
+ url: error.url
+ };
+ status = 500;
+ error = healthError;
+ throw new Error(`ERROR ${status}: Server side error — dsp-api is not healthy`);
+ } else {
+ throw new Error(`ERROR ${status}: Server side error — dsp-api not responding`);
+ }
+ },
+ (healthError: ApiResponseError) => {
+ error = healthError;
+ }
+ );
// open error message in full size view
const dialogConfig: MatDialogConfig = {
@@ -38,7 +62,7 @@ export class ErrorHandlerService {
position: {
top: '0'
},
- data: { mode: 'error', id: status },
+ data: { mode: 'error', id: status, comment: apiResponseMessage, fullSize: true },
disableClose: true
};
@@ -47,7 +71,6 @@ export class ErrorHandlerService {
dialogConfig
);
- throw new Error(`ERROR ${status}: Server side error — dsp-api not responding`);
} else if (error.status === 401 && typeof(error.error) !== 'string') {
// logout if error status is a 401 error and comes from a DSP-JS request
diff --git a/src/app/main/error/error.component.html b/src/app/main/error/error.component.html
index c65a8919a4..dbe0853e2b 100644
--- a/src/app/main/error/error.component.html
+++ b/src/app/main/error/error.component.html
@@ -1,7 +1,6 @@
-
-
+
@@ -9,16 +8,20 @@
ERROR {{status}}
{{errorMessage?.message}}
+
API response:
→ {{comment}}
- Please come back in a few minutes and try to reload the page
+ Please come back in a few minutes and try to reload the page.
+
+
+
diff --git a/src/app/main/error/error.component.spec.ts b/src/app/main/error/error.component.spec.ts
index 12796b4785..bdf2699b3f 100644
--- a/src/app/main/error/error.component.spec.ts
+++ b/src/app/main/error/error.component.spec.ts
@@ -1,18 +1,36 @@
-import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
+import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
+import { MatDialogRef } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { RouterTestingModule } from '@angular/router/testing';
+import { DspApiConnectionToken } from '../declarations/dsp-api-tokens';
import { ErrorComponent } from './error.component';
describe('ErrorComponent', () => {
let component: ErrorComponent;
let fixture: ComponentFixture;
+ const systemEndpointSpyObj = {
+ health: {
+ healthEndpoint: jasmine.createSpyObj('healthEndpoint', ['getHealthStatus'])
+ }
+ };
+
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ErrorComponent],
imports: [
MatIconModule,
RouterTestingModule
+ ],
+ providers: [
+ {
+ provide: MatDialogRef,
+ useValue: {}
+ },
+ {
+ provide: DspApiConnectionToken,
+ useValue: systemEndpointSpyObj
+ },
]
})
.compileComponents();
diff --git a/src/app/main/error/error.component.ts b/src/app/main/error/error.component.ts
index dfdeb90909..81290b2711 100644
--- a/src/app/main/error/error.component.ts
+++ b/src/app/main/error/error.component.ts
@@ -1,6 +1,8 @@
-import { Component, Input, OnInit } from '@angular/core';
+import { Component, Inject, Input, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute } from '@angular/router';
+import { ApiResponseData, ApiResponseError, HealthResponse, KnoraApiConnection } from '@dasch-swiss/dsp-js';
+import { DspApiConnectionToken } from '../declarations/dsp-api-tokens';
export interface ErrorMsg {
status: number;
@@ -19,6 +21,10 @@ export class ErrorComponent implements OnInit {
@Input() status: number;
+ @Input() comment?: string;
+
+ refresh = false;
+
// default error messages
errorMessages: ErrorMsg[] = [
{
@@ -67,6 +73,7 @@ export class ErrorComponent implements OnInit {
errorMessage: ErrorMsg;
constructor(
+ @Inject(DspApiConnectionToken) private _dspApiConnection: KnoraApiConnection,
private _titleService: Title,
private _route: ActivatedRoute
) { }
@@ -99,7 +106,20 @@ export class ErrorComponent implements OnInit {
}
reload() {
- window.location.reload();
+ // get api health status first and reload page only, if the api is running and status is healthy
+ this.refresh = true;
+
+ this._dspApiConnection.system.healthEndpoint.getHealthStatus().subscribe(
+ (response: ApiResponseData) => {
+ if (response.body.status === 'healthy') {
+ window.location.reload();
+ }
+ },
+ (error: ApiResponseError) => {
+ this. refresh = false;
+ }
+ );
+
}
}
diff --git a/src/app/main/header/header.component.ts b/src/app/main/header/header.component.ts
index 2012aabd28..65e0c8e12c 100644
--- a/src/app/main/header/header.component.ts
+++ b/src/app/main/header/header.component.ts
@@ -1,14 +1,17 @@
-import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import { NavigationStart, Router } from '@angular/router';
+import { ApiResponseData, ApiResponseError, HealthResponse, KnoraApiConnection } from '@dasch-swiss/dsp-js';
import { Subscription } from 'rxjs';
import { AppInitService } from 'src/app/app-init.service';
import { DialogComponent } from 'src/app/main/dialog/dialog.component';
import { ComponentCommunicationEventService, Events } from 'src/app/main/services/component-communication-event.service';
import { SearchParams } from 'src/app/workspace/results/list-view/list-view.component';
+import { DspApiConnectionToken } from '../declarations/dsp-api-tokens';
import { DspConfig } from '../declarations/dsp-config';
+import { ErrorHandlerService } from '../error/error-handler.service';
import { NotificationService } from '../services/notification.service';
import { SessionService } from '../services/session.service';
@@ -28,10 +31,12 @@ export class HeaderComponent implements OnInit, OnDestroy {
componentCommsSubscription: Subscription;
constructor(
+ @Inject(DspApiConnectionToken) private _dspApiConnection: KnoraApiConnection,
private _appInitService: AppInitService,
private _componentCommsService: ComponentCommunicationEventService,
private _dialog: MatDialog,
private _domSanitizer: DomSanitizer,
+ private _errorHandler: ErrorHandlerService,
private _matIconRegistry: MatIconRegistry,
private _notification: NotificationService,
private _router: Router,
@@ -46,8 +51,9 @@ export class HeaderComponent implements OnInit, OnDestroy {
// logged-in user? show user menu or login button
this._router.events.forEach((event) => {
+
if (event instanceof NavigationStart) {
- this._session.isSessionValid().subscribe((response) => {
+ this._session.isSessionValid().subscribe((response: boolean) => {
this.session = response;
});
}
diff --git a/src/app/main/services/session.service.ts b/src/app/main/services/session.service.ts
index f7f768c864..dac833fc52 100644
--- a/src/app/main/services/session.service.ts
+++ b/src/app/main/services/session.service.ts
@@ -3,8 +3,7 @@ import {
ApiResponseData,
ApiResponseError,
Constants,
- CredentialsResponse,
- KnoraApiConnection, UserResponse
+ CredentialsResponse, KnoraApiConnection, UserResponse
} from '@dasch-swiss/dsp-js';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
@@ -45,10 +44,10 @@ export class SessionService {
/**
* max session time in milliseconds
- * default value (24h): 86400000
+ * default value (24h = 24 * 60 * 60 * 1000): 86400000
*
*/
- readonly MAX_SESSION_TIME: number = 3600; // 1d = 24 * 60 * 60 * 1000
+ readonly MAX_SESSION_TIME: number = 3600;
constructor(
@Inject(DspApiConnectionToken) private _dspApiConnection: KnoraApiConnection
@@ -100,19 +99,18 @@ export class SessionService {
// check if the session is still valid:
if (session.id + this.MAX_SESSION_TIME <= tsNow) {
- // the internal (dsp-ui) session has expired
+ // the internal session has expired
// check if the api credentials are still valid
return this._dspApiConnection.v2.auth.checkCredentials().pipe(
map((credentials: ApiResponseData | ApiResponseError) => {
const idUpdated = this._updateSessionId(credentials, session, tsNow);
return idUpdated;
- }
- )
+ })
);
} else {
- // the internal (dsp-ui) session is still valid
+ // the internal session is still valid
return of(true);
}
} else {
@@ -130,7 +128,6 @@ export class SessionService {
localStorage.removeItem('session');
}
-
/**
* returns a timestamp represented in seconds
*
diff --git a/src/assets/style/main.scss b/src/assets/style/main.scss
index c394ce0678..ea8babdc00 100644
--- a/src/assets/style/main.scss
+++ b/src/assets/style/main.scss
@@ -196,3 +196,11 @@ button.space-reducer {
.mat-menu-panel {
min-height: 48px !important;
}
+
+.full-size-dialog {
+ transition: unset !important;
+ .mat-dialog-container {
+ transition: none !important;
+ border-radius: 0 !important;
+ }
+}
diff --git a/src/assets/test-data/api-error-0.json b/src/assets/test-data/api-error-0.json
new file mode 100644
index 0000000000..d4fdc60951
--- /dev/null
+++ b/src/assets/test-data/api-error-0.json
@@ -0,0 +1,65 @@
+{
+ "method": "GET",
+ "url": "http://0.0.0.0:3333/admin/users/username/root",
+ "status": 0,
+ "error": {
+ "message": "ajax error",
+ "name": "AjaxError",
+ "xhr": {
+ "__zone_symbol__timeoutfalse": [{
+ "type": "eventTask",
+ "state": "scheduled",
+ "source": "XMLHttpRequest.addEventListener:timeout",
+ "zone": "angular",
+ "runCount": 0
+ }],
+ "__zone_symbol__errorfalse": [{
+ "type": "eventTask",
+ "state": "running",
+ "source": "XMLHttpRequest.addEventListener:error",
+ "zone": "angular",
+ "runCount": 2
+ }],
+ "__zone_symbol__readystatechangefalse": [{
+ "type": "eventTask",
+ "state": "scheduled",
+ "source": "XMLHttpRequest.addEventListener:readystatechange",
+ "zone": "angular",
+ "runCount": 4
+ }],
+ "__zone_symbol__loadfalse": [{
+ "type": "eventTask",
+ "state": "scheduled",
+ "source": "XMLHttpRequest.addEventListener:load",
+ "zone": "angular",
+ "runCount": 0
+ }],
+ "__zone_symbol__xhrSync": false,
+ "__zone_symbol__xhrURL": "http://0.0.0.0:3333/admin/users/username/root",
+ "__zone_symbol__xhrScheduled": true,
+ "__zone_symbol__xhrErrorBeforeScheduled": false,
+ "__zone_symbol__xhrTask": {
+ "type": "macroTask",
+ "state": "notScheduled",
+ "source": "XMLHttpRequest.send",
+ "zone": "angular",
+ "runCount": 0
+ }
+ },
+ "request": {
+ "async": true,
+ "crossDomain": true,
+ "withCredentials": true,
+ "headers": {
+ "Authorization": "Bearer justAnExampleFakeToken"
+ },
+ "method": "GET",
+ "responseType": "json",
+ "timeout": 0,
+ "url": "http://0.0.0.0:3333/admin/users/username/root"
+ },
+ "status": 0,
+ "responseType": "json",
+ "response": null
+ }
+}
diff --git a/src/assets/test-data/api-error-500.json b/src/assets/test-data/api-error-500.json
new file mode 100644
index 0000000000..5a713b2c78
--- /dev/null
+++ b/src/assets/test-data/api-error-500.json
@@ -0,0 +1,73 @@
+{
+ "method": "GET",
+ "url": "http://0.0.0.0:3333/admin/projects",
+ "status": 500,
+ "error": {
+ "message": "ajax error 500",
+ "name": "AjaxError",
+ "xhr": {
+ "__zone_symbol__timeoutfalse": [{
+ "type": "eventTask",
+ "state": "scheduled",
+ "source": "XMLHttpRequest.addEventListener:timeout",
+ "zone": "angular",
+ "runCount": 0
+ }],
+ "__zone_symbol__errorfalse": [{
+ "type": "eventTask",
+ "state": "scheduled",
+ "source": "XMLHttpRequest.addEventListener:error",
+ "zone": "angular",
+ "runCount": 0
+ }],
+ "__zone_symbol__readystatechangefalse": [{
+ "type": "eventTask",
+ "state": "scheduled",
+ "source": "XMLHttpRequest.addEventListener:readystatechange",
+ "zone": "angular",
+ "runCount": 8
+ }],
+ "__zone_symbol__loadfalse": [{
+ "type": "eventTask",
+ "state": "running",
+ "source": "XMLHttpRequest.addEventListener:load",
+ "zone": "angular",
+ "runCount": 2
+ }, {
+ "type": "macroTask",
+ "state": "scheduled",
+ "source": "XMLHttpRequest.send",
+ "zone": "angular",
+ "runCount": 0
+ }],
+ "__zone_symbol__xhrSync": false,
+ "__zone_symbol__xhrURL": "http://0.0.0.0:3333/admin/projects",
+ "__zone_symbol__xhrScheduled": true,
+ "__zone_symbol__xhrErrorBeforeScheduled": false,
+ "__zone_symbol__xhrTask": {
+ "type": "macroTask",
+ "state": "scheduled",
+ "source": "XMLHttpRequest.send",
+ "zone": "angular",
+ "runCount": 0
+ }
+ },
+ "request": {
+ "async": true,
+ "crossDomain": true,
+ "withCredentials": true,
+ "headers": {
+ "Authorization": "Bearer justAnExampleFakeToken"
+ },
+ "method": "GET",
+ "responseType": "json",
+ "timeout": 0,
+ "url": "http://0.0.0.0:3333/admin/projects"
+ },
+ "status": 500,
+ "responseType": "json",
+ "response": {
+ "error": "org.knora.webapi.exceptions.TriplestoreResponseException: Couldn't parse Turtle from triplestore"
+ }
+ }
+}
diff --git a/src/config/config.dev.json b/src/config/config.dev.json
index c34c04532d..8cf4b8685d 100644
--- a/src/config/config.dev.json
+++ b/src/config/config.dev.json
@@ -1,5 +1,5 @@
{
- "dspRelease": "2022.02.01-rc",
+ "dspRelease": "work.in.progress",
"apiProtocol": "http",
"apiHost": "0.0.0.0",
"apiPort": 3333,