mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
62769: Bitstream format registry
This commit is contained in:
@@ -721,19 +721,77 @@
|
||||
"title": "DSpace Angular :: Bitstream Format Registry",
|
||||
"head": "Bitstream Format Registry",
|
||||
"description": "This list of bitstream formats provides information about known formats and their support level.",
|
||||
"formats": {
|
||||
"create": {
|
||||
"new": "Add a new bitstream format",
|
||||
"head": "Create Bitstream format",
|
||||
"success" : {
|
||||
"head": "Success",
|
||||
"content": "The new bitstream format was successfully created."
|
||||
},
|
||||
"failure" : {
|
||||
"head": "Failure",
|
||||
"content": "An error occurred while creating the new bitstream format."
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
"name": "Name",
|
||||
"mimetype": "MIME Type",
|
||||
"supportLevel": {
|
||||
"head": "Support Level",
|
||||
"0": "Unknown",
|
||||
"1": "Known",
|
||||
"2": "Support"
|
||||
"UNKNOWN": "Unknown",
|
||||
"KNOWN": "Known",
|
||||
"SUPPORTED": "Supported"
|
||||
},
|
||||
"internal": "internal"
|
||||
"internal": "internal",
|
||||
"delete": "Delete selected",
|
||||
"return": "Return",
|
||||
"deselect-all": "Deselect all"
|
||||
},
|
||||
"no-items": "No bitstream formats to show."
|
||||
"no-items": "No bitstream formats to show.",
|
||||
"edit": {
|
||||
"head": "Bitstream format: {{ format }}",
|
||||
"shortDescription": {
|
||||
"label": "Name",
|
||||
"hint": "A unique name for this format, (e.g. Microsoft Word XP or Microsoft Word 2000)"
|
||||
},
|
||||
"mimetype": {
|
||||
"label": "MIME Type",
|
||||
"hint": "The MIME type associated with this format, does not have to be unique."
|
||||
},
|
||||
"description": {
|
||||
"label": "Description",
|
||||
"hint": ""
|
||||
},
|
||||
"supportLevel": {
|
||||
"label": "Support level",
|
||||
"hint": "The level of support your institution pledges for this format."
|
||||
},
|
||||
"internal": {
|
||||
"label": "Internal",
|
||||
"hint": "Formats marked as internal are are hidden from the user, and used for administrative purposes."
|
||||
},
|
||||
"extensions": {
|
||||
"label": "File extensions",
|
||||
"hint": "Extensions are file extensions that are used to automatically identify the format of uploaded files. You can enter several extensions for each format."
|
||||
},
|
||||
"success" : {
|
||||
"head": "Success",
|
||||
"content": "The bitstream format was successfully edited."
|
||||
},
|
||||
"failure" : {
|
||||
"head": "Failure",
|
||||
"content": "An error occurred while editing the bitstream format."
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"success":{
|
||||
"head": "Success",
|
||||
"amount": "The following amount of bitstream formats have been successfully deleted: {{ amount }}"
|
||||
},
|
||||
"failure": {
|
||||
"head": "Failure",
|
||||
"amount": "The following amount of bitstream formats could not be deleted: {{ amount }} "
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,14 +2,29 @@ import { MetadataRegistryComponent } from './metadata-registry/metadata-registry
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { MetadataSchemaComponent } from './metadata-schema/metadata-schema.component';
|
||||
import { BitstreamFormatsComponent } from './bitstream-formats/bitstream-formats.component';
|
||||
import { URLCombiner } from '../../core/url-combiner/url-combiner';
|
||||
import { getRegistriesModulePath } from '../admin-routing.module';
|
||||
|
||||
const BITSTREAMFORMATS_MODULE_PATH = 'bitstream-formats';
|
||||
|
||||
export function getBitstreamFormatsModulePath() {
|
||||
return new URLCombiner(getRegistriesModulePath(), BITSTREAMFORMATS_MODULE_PATH).toString();
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{path: 'metadata', component: MetadataRegistryComponent, data: {title: 'admin.registries.metadata.title'}},
|
||||
{ path: 'metadata/:schemaName', component: MetadataSchemaComponent, data: { title: 'admin.registries.schema.title' } },
|
||||
{ path: 'bitstream-formats', component: BitstreamFormatsComponent, data: { title: 'admin.registries.bitstream-formats.title' } },
|
||||
{
|
||||
path: 'metadata/:schemaName',
|
||||
component: MetadataSchemaComponent,
|
||||
data: {title: 'admin.registries.schema.title'}
|
||||
},
|
||||
{
|
||||
path: BITSTREAMFORMATS_MODULE_PATH,
|
||||
loadChildren: './bitstream-formats/bitstream-formats.module#BitstreamFormatsModule',
|
||||
data: {title: 'admin.registries.bitstream-formats.title'}
|
||||
},
|
||||
])
|
||||
]
|
||||
})
|
||||
|
@@ -5,10 +5,10 @@ import { CommonModule } from '@angular/common';
|
||||
import { MetadataSchemaComponent } from './metadata-schema/metadata-schema.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { BitstreamFormatsComponent } from './bitstream-formats/bitstream-formats.component';
|
||||
import { SharedModule } from '../../shared/shared.module';
|
||||
import { MetadataSchemaFormComponent } from './metadata-registry/metadata-schema-form/metadata-schema-form.component';
|
||||
import { MetadataFieldFormComponent } from './metadata-schema/metadata-field-form/metadata-field-form.component';
|
||||
import { BitstreamFormatsModule } from './bitstream-formats/bitstream-formats.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -16,12 +16,12 @@ import {MetadataFieldFormComponent} from './metadata-schema/metadata-field-form/
|
||||
SharedModule,
|
||||
RouterModule,
|
||||
TranslateModule,
|
||||
BitstreamFormatsModule,
|
||||
AdminRegistriesRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
MetadataRegistryComponent,
|
||||
MetadataSchemaComponent,
|
||||
BitstreamFormatsComponent,
|
||||
MetadataSchemaFormComponent,
|
||||
MetadataFieldFormComponent
|
||||
],
|
||||
|
@@ -0,0 +1,11 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12 pb-4">
|
||||
<h2 id="sub-header"
|
||||
class="border-bottom pb-2">{{ 'admin.registries.bitstream-formats.create.new' | translate }}</h2>
|
||||
|
||||
<ds-bitstream-format-form (updatedFormat)="createBitstreamFormat($event)"></ds-bitstream-format-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -0,0 +1,109 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { Router } from '@angular/router';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { RouterStub } from '../../../../shared/testing/router-stub';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service-stub';
|
||||
import { BitstreamFormatDataService } from '../../../../core/data/bitstream-format-data.service';
|
||||
import { RestResponse } from '../../../../core/cache/response.models';
|
||||
import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model';
|
||||
import { BitstreamFormatSupportLevel } from '../../../../core/shared/bitstream-format-support-level';
|
||||
import { ResourceType } from '../../../../core/shared/resource-type';
|
||||
import { AddBitstreamFormatComponent } from './add-bitstream-format.component';
|
||||
|
||||
describe('AddBitstreamFormatComponent', () => {
|
||||
let comp: AddBitstreamFormatComponent;
|
||||
let fixture: ComponentFixture<AddBitstreamFormatComponent>;
|
||||
|
||||
const bitstreamFormat: BitstreamFormat = {
|
||||
uuid: 'test-uuid',
|
||||
id: 'test-uuid',
|
||||
shortDescription: 'Adobe PDF',
|
||||
description: 'Adobe Portable Document Format',
|
||||
mimetype: 'application/pdf',
|
||||
supportLevel: BitstreamFormatSupportLevel.Unknown,
|
||||
internal: false,
|
||||
extensions: ['pdf', 'also-pdf'],
|
||||
type: ResourceType.BitstreamFormat,
|
||||
self: 'self-link'
|
||||
};
|
||||
|
||||
let router;
|
||||
let notificationService: NotificationsServiceStub;
|
||||
let bitstreamFormatDataService: BitstreamFormatDataService;
|
||||
|
||||
const initAsync = () => {
|
||||
router = new RouterStub();
|
||||
notificationService = new NotificationsServiceStub();
|
||||
bitstreamFormatDataService = jasmine.createSpyObj('bitstreamFormatDataService', {
|
||||
createBitstreamFormat: observableOf(new RestResponse(true, 200, 'Success')),
|
||||
clearBitStreamFormatRequests: observableOf(null)
|
||||
});
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()],
|
||||
declarations: [AddBitstreamFormatComponent],
|
||||
providers: [
|
||||
{provide: Router, useValue: router},
|
||||
{provide: NotificationsService, useValue: notificationService},
|
||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService},
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
}).compileComponents();
|
||||
};
|
||||
|
||||
const initBeforeEach = () => {
|
||||
fixture = TestBed.createComponent(AddBitstreamFormatComponent);
|
||||
comp = fixture.componentInstance;
|
||||
|
||||
fixture.detectChanges();
|
||||
};
|
||||
|
||||
describe('createBitstreamFormat success', () => {
|
||||
beforeEach(async(initAsync));
|
||||
beforeEach(initBeforeEach);
|
||||
it('should send the updated form to the service, show a notification and navigate to ', () => {
|
||||
comp.createBitstreamFormat(bitstreamFormat);
|
||||
|
||||
expect(bitstreamFormatDataService.createBitstreamFormat).toHaveBeenCalledWith(bitstreamFormat);
|
||||
expect(notificationService.success).toHaveBeenCalled();
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/admin/registries/bitstream-formats']);
|
||||
|
||||
});
|
||||
});
|
||||
describe('createBitstreamFormat error', () => {
|
||||
beforeEach(async(() => {
|
||||
router = new RouterStub();
|
||||
notificationService = new NotificationsServiceStub();
|
||||
bitstreamFormatDataService = jasmine.createSpyObj('bitstreamFormatDataService', {
|
||||
createBitstreamFormat: observableOf(new RestResponse(false, 400, 'Bad Request')),
|
||||
clearBitStreamFormatRequests: observableOf(null)
|
||||
});
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()],
|
||||
declarations: [AddBitstreamFormatComponent],
|
||||
providers: [
|
||||
{provide: Router, useValue: router},
|
||||
{provide: NotificationsService, useValue: notificationService},
|
||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService},
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
}).compileComponents();
|
||||
}));
|
||||
beforeEach(initBeforeEach);
|
||||
it('should send the updated form to the service, show a notification and navigate to ', () => {
|
||||
comp.createBitstreamFormat(bitstreamFormat);
|
||||
|
||||
expect(bitstreamFormatDataService.createBitstreamFormat).toHaveBeenCalledWith(bitstreamFormat);
|
||||
expect(notificationService.error).toHaveBeenCalled();
|
||||
expect(router.navigate).not.toHaveBeenCalled();
|
||||
|
||||
});
|
||||
});
|
||||
});
|
@@ -0,0 +1,49 @@
|
||||
import { take } from 'rxjs/operators';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component } from '@angular/core';
|
||||
import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model';
|
||||
import { BitstreamFormatDataService } from '../../../../core/data/bitstream-format-data.service';
|
||||
import { RestResponse } from '../../../../core/cache/response.models';
|
||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||
import { getBitstreamFormatsModulePath } from '../../admin-registries-routing.module';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
/**
|
||||
* This component renders the page to create a new bitstream format.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-add-bitstream-format',
|
||||
templateUrl: './add-bitstream-format.component.html',
|
||||
})
|
||||
export class AddBitstreamFormatComponent {
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private notificationService: NotificationsService,
|
||||
private translateService: TranslateService,
|
||||
private bitstreamFormatDataService: BitstreamFormatDataService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new bitstream format based on the provided bitstream format emitted by the form.
|
||||
* When successful, a success notification will be shown and the user will be navigated back to the overview page.
|
||||
* When failed, an error notification will be shown.
|
||||
* @param bitstreamFormat
|
||||
*/
|
||||
createBitstreamFormat(bitstreamFormat: BitstreamFormat) {
|
||||
this.bitstreamFormatDataService.createBitstreamFormat(bitstreamFormat).pipe(take(1)
|
||||
).subscribe((response: RestResponse) => {
|
||||
if (response.isSuccessful) {
|
||||
this.notificationService.success(this.translateService.get('admin.registries.bitstream-formats.create.success.head'),
|
||||
this.translateService.get('admin.registries.bitstream-formats.create.success.content'));
|
||||
this.router.navigate([getBitstreamFormatsModulePath()]);
|
||||
this.bitstreamFormatDataService.clearBitStreamFormatRequests().subscribe();
|
||||
} else {
|
||||
this.notificationService.error(this.translateService.get('admin.registries.bitstream-formats.create.failure.head'),
|
||||
this.translateService.get('admin.registries.bitstream-formats.create.failure.content'));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
import { type } from '../../../shared/ngrx/type';
|
||||
import { BitstreamFormat } from '../../../core/shared/bitstream-format.model';
|
||||
|
||||
/**
|
||||
* For each action type in an action group, make a simple
|
||||
* enum object for all of this group's action types.
|
||||
*
|
||||
* The 'type' utility function coerces strings into string
|
||||
* literal types and runs a simple check to guarantee all
|
||||
* action types in the application are unique.
|
||||
*/
|
||||
export const BitstreamFormatsRegistryActionTypes = {
|
||||
|
||||
SELECT_FORMAT: type('dspace/bitstream-formats-registry/SELECT_FORMAT'),
|
||||
DESELECT_FORMAT: type('dspace/bitstream-formats-registry/DESELECT_FORMAT'),
|
||||
DESELECT_ALL_FORMAT: type('dspace/bitstream-formats-registry/DESELECT_ALL_FORMAT')
|
||||
};
|
||||
|
||||
/* tslint:disable:max-classes-per-file */
|
||||
/**
|
||||
* Used to select a single bitstream format in the bitstream format registry
|
||||
*/
|
||||
export class BitstreamFormatsRegistrySelectAction implements Action {
|
||||
type = BitstreamFormatsRegistryActionTypes.SELECT_FORMAT;
|
||||
|
||||
bitstreamFormat: BitstreamFormat;
|
||||
|
||||
constructor(bitstreamFormat: BitstreamFormat) {
|
||||
this.bitstreamFormat = bitstreamFormat;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to deselect a single bitstream format in the bitstream format registry
|
||||
*/
|
||||
export class BitstreamFormatsRegistryDeselectAction implements Action {
|
||||
type = BitstreamFormatsRegistryActionTypes.DESELECT_FORMAT;
|
||||
|
||||
bitstreamFormat: BitstreamFormat;
|
||||
|
||||
constructor(bitstreamFormat: BitstreamFormat) {
|
||||
this.bitstreamFormat = bitstreamFormat;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to deselect all bitstream formats in the bitstream format registry
|
||||
*/
|
||||
export class BitstreamFormatsRegistryDeselectAllAction implements Action {
|
||||
type = BitstreamFormatsRegistryActionTypes.DESELECT_ALL_FORMAT;
|
||||
}
|
||||
|
||||
/* tslint:enable:max-classes-per-file */
|
||||
|
||||
/**
|
||||
* Export a type alias of all actions in this action group
|
||||
* so that reducers can easily compose action types
|
||||
* These are all the actions to perform on the bitstream format registry state
|
||||
*/
|
||||
export type BitstreamFormatsRegistryAction
|
||||
= BitstreamFormatsRegistrySelectAction
|
||||
| BitstreamFormatsRegistryDeselectAction
|
||||
| BitstreamFormatsRegistryDeselectAllAction
|
@@ -0,0 +1,83 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
import { BitstreamFormat } from '../../../core/shared/bitstream-format.model';
|
||||
import { bitstreamFormatReducer, BitstreamFormatRegistryState } from './bitstream-format.reducers';
|
||||
import {
|
||||
BitstreamFormatsRegistryDeselectAction,
|
||||
BitstreamFormatsRegistryDeselectAllAction,
|
||||
BitstreamFormatsRegistrySelectAction
|
||||
} from './bitstream-format.actions';
|
||||
|
||||
const bitstreamFormat1: BitstreamFormat = new BitstreamFormat();
|
||||
bitstreamFormat1.id = 'test-uuid-1';
|
||||
bitstreamFormat1.shortDescription = 'test-short-1';
|
||||
|
||||
const bitstreamFormat2: BitstreamFormat = new BitstreamFormat();
|
||||
bitstreamFormat2.id = 'test-uuid-2';
|
||||
bitstreamFormat2.shortDescription = 'test-short-2';
|
||||
|
||||
const initialState: BitstreamFormatRegistryState = {
|
||||
selectedBitstreamFormats: []
|
||||
};
|
||||
|
||||
const bitstream1SelectedState: BitstreamFormatRegistryState = {
|
||||
selectedBitstreamFormats: [bitstreamFormat1]
|
||||
};
|
||||
|
||||
const bitstream1and2SelectedState: BitstreamFormatRegistryState = {
|
||||
selectedBitstreamFormats: [bitstreamFormat1, bitstreamFormat2]
|
||||
};
|
||||
|
||||
describe('BitstreamFormatReducer', () => {
|
||||
describe('BitstreamFormatsRegistryActionTypes.SELECT_FORMAT', () => {
|
||||
it('should add the format to the list of selected formats when initial list is empty', () => {
|
||||
const state = initialState;
|
||||
const action = new BitstreamFormatsRegistrySelectAction(bitstreamFormat1);
|
||||
const newState = bitstreamFormatReducer(state, action);
|
||||
|
||||
expect(newState).toEqual(bitstream1SelectedState);
|
||||
});
|
||||
it('should add the format to the list of selected formats when formats are already present', () => {
|
||||
const state = bitstream1SelectedState;
|
||||
const action = new BitstreamFormatsRegistrySelectAction(bitstreamFormat2);
|
||||
const newState = bitstreamFormatReducer(state, action);
|
||||
|
||||
expect(newState).toEqual(bitstream1and2SelectedState);
|
||||
});
|
||||
});
|
||||
describe('BitstreamFormatsRegistryActionTypes.DESELECT_FORMAT', () => {
|
||||
it('should deselect a format', () => {
|
||||
const state = bitstream1and2SelectedState;
|
||||
const action = new BitstreamFormatsRegistryDeselectAction(bitstreamFormat2);
|
||||
const newState = bitstreamFormatReducer(state, action);
|
||||
|
||||
expect(newState).toEqual(bitstream1SelectedState);
|
||||
});
|
||||
});
|
||||
describe('BitstreamFormatsRegistryActionTypes.DESELECT_ALL_FORMAT', () => {
|
||||
it('should deselect all formats', () => {
|
||||
const state = bitstream1and2SelectedState;
|
||||
const action = new BitstreamFormatsRegistryDeselectAllAction();
|
||||
const newState = bitstreamFormatReducer(state, action);
|
||||
|
||||
expect(newState).toEqual(initialState);
|
||||
});
|
||||
});
|
||||
describe('Invalid action', () => {
|
||||
it('should return the current state', () => {
|
||||
const state = initialState;
|
||||
const action = new NullAction();
|
||||
|
||||
const newState = bitstreamFormatReducer(state, action);
|
||||
|
||||
expect(newState).toEqual(state);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
class NullAction implements Action {
|
||||
type = null;
|
||||
|
||||
constructor() {
|
||||
// empty constructor
|
||||
}
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
import { BitstreamFormat } from '../../../core/shared/bitstream-format.model';
|
||||
import {
|
||||
BitstreamFormatsRegistryAction,
|
||||
BitstreamFormatsRegistryActionTypes,
|
||||
BitstreamFormatsRegistryDeselectAction,
|
||||
BitstreamFormatsRegistrySelectAction
|
||||
} from './bitstream-format.actions';
|
||||
|
||||
/**
|
||||
* The bitstream format registry state.
|
||||
* @interface BitstreamFormatRegistryState
|
||||
*/
|
||||
export interface BitstreamFormatRegistryState {
|
||||
selectedBitstreamFormats: BitstreamFormat[];
|
||||
}
|
||||
|
||||
/**
|
||||
* The initial state.
|
||||
*/
|
||||
const initialState: BitstreamFormatRegistryState = {
|
||||
selectedBitstreamFormats: [],
|
||||
};
|
||||
|
||||
/**
|
||||
* Reducer that handles BitstreamFormatsRegistryActions to modify the bitstream format registry state
|
||||
* @param state The current BitstreamFormatRegistryState
|
||||
* @param action The BitstreamFormatsRegistryAction to perform on the state
|
||||
*/
|
||||
export function bitstreamFormatReducer(state = initialState, action: BitstreamFormatsRegistryAction): BitstreamFormatRegistryState {
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
case BitstreamFormatsRegistryActionTypes.SELECT_FORMAT: {
|
||||
return Object.assign({}, state, {
|
||||
selectedBitstreamFormats: [...state.selectedBitstreamFormats, (action as BitstreamFormatsRegistrySelectAction).bitstreamFormat]
|
||||
});
|
||||
}
|
||||
|
||||
case BitstreamFormatsRegistryActionTypes.DESELECT_FORMAT: {
|
||||
return Object.assign({}, state, {
|
||||
selectedBitstreamFormats: state.selectedBitstreamFormats.filter(
|
||||
(selectedBitstreamFormats) => selectedBitstreamFormats !== (action as BitstreamFormatsRegistryDeselectAction).bitstreamFormat
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
case BitstreamFormatsRegistryActionTypes.DESELECT_ALL_FORMAT: {
|
||||
return Object.assign({}, state, {
|
||||
selectedBitstreamFormats: []
|
||||
});
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { BitstreamFormatsResolver } from './bitstream-formats.resolver';
|
||||
import { EditBitstreamFormatComponent } from './edit-bitstream-format/edit-bitstream-format.component';
|
||||
import { BitstreamFormatsComponent } from './bitstream-formats.component';
|
||||
import { AddBitstreamFormatComponent } from './add-bitstream-format/add-bitstream-format.component';
|
||||
|
||||
const BITSTREAMFORMAT_EDIT_PATH = ':id/edit';
|
||||
const BITSTREAMFORMAT_ADD_PATH = 'add';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: BitstreamFormatsComponent
|
||||
},
|
||||
{
|
||||
path: BITSTREAMFORMAT_ADD_PATH,
|
||||
component: AddBitstreamFormatComponent,
|
||||
},
|
||||
{
|
||||
path: BITSTREAMFORMAT_EDIT_PATH,
|
||||
component: EditBitstreamFormatComponent,
|
||||
resolve: {
|
||||
bitstreamFormat: BitstreamFormatsResolver
|
||||
}
|
||||
},
|
||||
])
|
||||
],
|
||||
providers: [
|
||||
BitstreamFormatsResolver,
|
||||
]
|
||||
})
|
||||
export class BitstreamFormatsRoutingModule {
|
||||
|
||||
}
|
@@ -4,11 +4,13 @@
|
||||
|
||||
<h2 id="header" class="border-bottom pb-2">{{'admin.registries.bitstream-formats.head' | translate}}</h2>
|
||||
|
||||
<p id="description" class="pb-2">{{'admin.registries.bitstream-formats.description' | translate}}</p>
|
||||
<p id="description">{{'admin.registries.bitstream-formats.description' | translate}}</p>
|
||||
<p id="create-new" class="pb-2"><a [routerLink]="'add'">{{'admin.registries.bitstream-formats.create.new' | translate}}</a></p>
|
||||
|
||||
|
||||
<ds-pagination
|
||||
*ngIf="(bitstreamFormats | async)?.payload?.totalElements > 0"
|
||||
[paginationOptions]="config"
|
||||
[paginationOptions]="pageConfig"
|
||||
[pageInfoState]="(bitstreamFormats | async)?.payload"
|
||||
[collectionSize]="(bitstreamFormats | async)?.payload?.totalElements"
|
||||
[hideGear]="true"
|
||||
@@ -18,25 +20,38 @@
|
||||
<table id="formats" class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">{{'admin.registries.bitstream-formats.formats.table.name' | translate}}</th>
|
||||
<th scope="col">{{'admin.registries.bitstream-formats.formats.table.mimetype' | translate}}</th>
|
||||
<th scope="col">{{'admin.registries.bitstream-formats.formats.table.supportLevel.head' | translate}}</th>
|
||||
<th scope="col"></th>
|
||||
<th scope="col">{{'admin.registries.bitstream-formats.table.name' | translate}}</th>
|
||||
<th scope="col">{{'admin.registries.bitstream-formats.table.mimetype' | translate}}</th>
|
||||
<th scope="col">{{'admin.registries.bitstream-formats.table.supportLevel.head' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let bitstreamFormat of (bitstreamFormats | async)?.payload?.page">
|
||||
<td>{{bitstreamFormat.shortDescription}}</td>
|
||||
<td>{{bitstreamFormat.mimetype}} <span *ngIf="bitstreamFormat.internal">({{'admin.registries.bitstream-formats.formats.table.internal' | translate}})</span></td>
|
||||
<td>{{'admin.registries.bitstream-formats.formats.table.supportLevel.'+bitstreamFormat.supportLevel | translate}}</td>
|
||||
<td>
|
||||
<label>
|
||||
<input type="checkbox"
|
||||
[checked]="isSelected(bitstreamFormat) | async"
|
||||
(change)="selectBitStreamFormat(bitstreamFormat, $event)"
|
||||
>
|
||||
</label>
|
||||
</td>
|
||||
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.shortDescription}}</a></td>
|
||||
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{bitstreamFormat.mimetype}} <span *ngIf="bitstreamFormat.internal">({{'admin.registries.bitstream-formats.table.internal' | translate}})</span></a></td>
|
||||
<td><a [routerLink]="['/admin/registries/bitstream-formats', bitstreamFormat.id, 'edit']">{{'admin.registries.bitstream-formats.table.supportLevel.'+bitstreamFormat.supportLevel | translate}}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</ds-pagination>
|
||||
<div *ngIf="(bitstreamFormats | async)?.payload?.totalElements == 0" class="alert alert-info" role="alert">
|
||||
{{'admin.registries.bitstream-formats.formats.no-items' | translate}}
|
||||
{{'admin.registries.bitstream-formats.no-items' | translate}}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button *ngIf="(bitstreamFormats | async)?.payload?.page?.length > 0" class="btn btn-primary deselect" (click)="deselectAll()">{{'admin.registries.bitstream-formats.table.deselect-all' | translate}}</button>
|
||||
<button *ngIf="(bitstreamFormats | async)?.payload?.page?.length > 0" type="submit" class="btn btn-danger float-right" (click)="deleteFormats()">{{'admin.registries.bitstream-formats.table.delete' | translate}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -1,6 +1,5 @@
|
||||
import { BitstreamFormatsComponent } from './bitstream-formats.component';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { RegistryService } from '../../../core/registry/registry.service';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list';
|
||||
@@ -13,67 +12,115 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { EnumKeysPipe } from '../../../shared/utils/enum-keys-pipe';
|
||||
import { HostWindowService } from '../../../shared/host-window.service';
|
||||
import { HostWindowServiceStub } from '../../../shared/testing/host-window-service-stub';
|
||||
import { BitstreamFormatDataService } from '../../../core/data/bitstream-format-data.service';
|
||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub';
|
||||
import { BitstreamFormat } from '../../../core/shared/bitstream-format.model';
|
||||
import { ResourceType } from '../../../core/shared/resource-type';
|
||||
import { BitstreamFormatSupportLevel } from '../../../core/shared/bitstream-format-support-level';
|
||||
import { cold, getTestScheduler, hot } from 'jasmine-marbles';
|
||||
import { TestScheduler } from 'rxjs/testing';
|
||||
|
||||
describe('BitstreamFormatsComponent', () => {
|
||||
let comp: BitstreamFormatsComponent;
|
||||
let fixture: ComponentFixture<BitstreamFormatsComponent>;
|
||||
let registryService: RegistryService;
|
||||
const mockFormatsList = [
|
||||
{
|
||||
let bitstreamFormatService;
|
||||
let scheduler: TestScheduler;
|
||||
let notificationsServiceStub;
|
||||
|
||||
const bitstreamFormat1: BitstreamFormat = {
|
||||
uuid: 'test-uuid-1',
|
||||
id: 'test-uuid-1',
|
||||
shortDescription: 'Unknown',
|
||||
description: 'Unknown data format',
|
||||
mimetype: 'application/octet-stream',
|
||||
supportLevel: 0,
|
||||
supportLevel: BitstreamFormatSupportLevel.Unknown,
|
||||
internal: false,
|
||||
extensions: null
|
||||
},
|
||||
{
|
||||
extensions: null,
|
||||
type: ResourceType.BitstreamFormat,
|
||||
self: 'self-link'
|
||||
};
|
||||
const bitstreamFormat2: BitstreamFormat = {
|
||||
uuid: 'test-uuid-2',
|
||||
id: 'test-uuid-2',
|
||||
shortDescription: 'License',
|
||||
description: 'Item-specific license agreed upon to submission',
|
||||
mimetype: 'text/plain; charset=utf-8',
|
||||
supportLevel: 1,
|
||||
supportLevel: BitstreamFormatSupportLevel.Known,
|
||||
internal: true,
|
||||
extensions: null
|
||||
},
|
||||
{
|
||||
extensions: null,
|
||||
type: ResourceType.BitstreamFormat,
|
||||
self: 'self-link'
|
||||
};
|
||||
const bitstreamFormat3: BitstreamFormat = {
|
||||
uuid: 'test-uuid-3',
|
||||
id: 'test-uuid-3',
|
||||
shortDescription: 'CC License',
|
||||
description: 'Item-specific Creative Commons license agreed upon to submission',
|
||||
mimetype: 'text/html; charset=utf-8',
|
||||
supportLevel: 2,
|
||||
supportLevel: BitstreamFormatSupportLevel.Supported,
|
||||
internal: true,
|
||||
extensions: null
|
||||
},
|
||||
{
|
||||
extensions: null,
|
||||
type: ResourceType.BitstreamFormat,
|
||||
self: 'self-link'
|
||||
};
|
||||
const bitstreamFormat4: BitstreamFormat = {
|
||||
uuid: 'test-uuid-4',
|
||||
id: 'test-uuid-4',
|
||||
shortDescription: 'Adobe PDF',
|
||||
description: 'Adobe Portable Document Format',
|
||||
mimetype: 'application/pdf',
|
||||
supportLevel: 0,
|
||||
supportLevel: BitstreamFormatSupportLevel.Unknown,
|
||||
internal: false,
|
||||
extensions: null
|
||||
}
|
||||
];
|
||||
const mockFormats = observableOf(new RemoteData(false, false, true, undefined, new PaginatedList(null, mockFormatsList)));
|
||||
const registryServiceStub = {
|
||||
getBitstreamFormats: () => mockFormats
|
||||
extensions: null,
|
||||
type: ResourceType.BitstreamFormat,
|
||||
self: 'self-link'
|
||||
};
|
||||
|
||||
beforeEach(async(() => {
|
||||
const mockFormatsList: BitstreamFormat[] = [
|
||||
bitstreamFormat1,
|
||||
bitstreamFormat2,
|
||||
bitstreamFormat3,
|
||||
bitstreamFormat4
|
||||
];
|
||||
const mockFormatsRD = new RemoteData(false, false, true, undefined, new PaginatedList(null, mockFormatsList));
|
||||
|
||||
const initAsync = () => {
|
||||
notificationsServiceStub = new NotificationsServiceStub();
|
||||
|
||||
scheduler = getTestScheduler();
|
||||
|
||||
bitstreamFormatService = jasmine.createSpyObj('bitstreamFormatService', {
|
||||
findAll: observableOf(mockFormatsRD),
|
||||
find: observableOf(new RemoteData(false, false, true, undefined, mockFormatsList[0])),
|
||||
getSelectedBitstreamFormats: hot('a', {a: mockFormatsList}),
|
||||
selectBitstreamFormat: {},
|
||||
deselectBitstreamFormat: {},
|
||||
deselectAllBitstreamFormats: {},
|
||||
delete: observableOf(true),
|
||||
clearBitStreamFormatRequests: observableOf('cleared')
|
||||
});
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()],
|
||||
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
|
||||
providers: [
|
||||
{ provide: RegistryService, useValue: registryServiceStub },
|
||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(0) }
|
||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
|
||||
{provide: HostWindowService, useValue: new HostWindowServiceStub(0)},
|
||||
{provide: NotificationsService, useValue: notificationsServiceStub}
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
const initBeforeEach = () => {
|
||||
fixture = TestBed.createComponent(BitstreamFormatsComponent);
|
||||
comp = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
registryService = (comp as any).service;
|
||||
});
|
||||
};
|
||||
|
||||
describe('Bitstream format page content', () => {
|
||||
beforeEach(async(initAsync));
|
||||
beforeEach(initBeforeEach);
|
||||
|
||||
it('should contain four formats', () => {
|
||||
const tbody: HTMLElement = fixture.debugElement.query(By.css('#formats>tbody')).nativeElement;
|
||||
@@ -81,17 +128,172 @@ describe('BitstreamFormatsComponent', () => {
|
||||
});
|
||||
|
||||
it('should contain the correct formats', () => {
|
||||
const unknownName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(1) td:nth-child(1)')).nativeElement;
|
||||
const unknownName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(1) td:nth-child(2)')).nativeElement;
|
||||
expect(unknownName.textContent).toBe('Unknown');
|
||||
|
||||
const licenseName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(2) td:nth-child(1)')).nativeElement;
|
||||
const licenseName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(2) td:nth-child(2)')).nativeElement;
|
||||
expect(licenseName.textContent).toBe('License');
|
||||
|
||||
const ccLicenseName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(3) td:nth-child(1)')).nativeElement;
|
||||
const ccLicenseName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(3) td:nth-child(2)')).nativeElement;
|
||||
expect(ccLicenseName.textContent).toBe('CC License');
|
||||
|
||||
const adobeName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(4) td:nth-child(1)')).nativeElement;
|
||||
const adobeName: HTMLElement = fixture.debugElement.query(By.css('#formats tr:nth-child(4) td:nth-child(2)')).nativeElement;
|
||||
expect(adobeName.textContent).toBe('Adobe PDF');
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectBitStreamFormat', () => {
|
||||
beforeEach(async(initAsync));
|
||||
beforeEach(initBeforeEach);
|
||||
it('should select a bitstreamFormat if it was selected in the event', () => {
|
||||
const event = {target: {checked: true}};
|
||||
|
||||
comp.selectBitStreamFormat(bitstreamFormat1, event);
|
||||
|
||||
expect(bitstreamFormatService.selectBitstreamFormat).toHaveBeenCalledWith(bitstreamFormat1);
|
||||
});
|
||||
it('should deselect a bitstreamFormat if it is deselected in the event', () => {
|
||||
const event = {target: {checked: false}};
|
||||
|
||||
comp.selectBitStreamFormat(bitstreamFormat1, event);
|
||||
|
||||
expect(bitstreamFormatService.deselectBitstreamFormat).toHaveBeenCalledWith(bitstreamFormat1);
|
||||
});
|
||||
it('should be called when a user clicks a checkbox', () => {
|
||||
spyOn(comp, 'selectBitStreamFormat');
|
||||
const unknownFormat = fixture.debugElement.query(By.css('#formats tr:nth-child(1) input'));
|
||||
|
||||
const event = {target: {checked: true}};
|
||||
unknownFormat.triggerEventHandler('change', event);
|
||||
|
||||
expect(comp.selectBitStreamFormat).toHaveBeenCalledWith(bitstreamFormat1, event);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSelected', () => {
|
||||
beforeEach(async(initAsync));
|
||||
beforeEach(initBeforeEach);
|
||||
it('should return an observable of true if the provided bistream is in the list returned by the service', () => {
|
||||
const result = comp.isSelected(bitstreamFormat1);
|
||||
|
||||
expect(result).toBeObservable(cold('b', {b: true}));
|
||||
});
|
||||
it('should return an observable of false if the provided bistream is not in the list returned by the service', () => {
|
||||
const format = new BitstreamFormat();
|
||||
format.uuid = 'new';
|
||||
|
||||
const result = comp.isSelected(format);
|
||||
|
||||
expect(result).toBeObservable(cold('b', {b: false}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('deselectAll', () => {
|
||||
beforeEach(async(initAsync));
|
||||
beforeEach(initBeforeEach);
|
||||
it('should deselect all bitstreamFormats', () => {
|
||||
comp.deselectAll();
|
||||
expect(bitstreamFormatService.deselectAllBitstreamFormats).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should be called when the deselect all button is clicked', () => {
|
||||
spyOn(comp, 'deselectAll');
|
||||
const deselectAllButton = fixture.debugElement.query(By.css('button.deselect'));
|
||||
deselectAllButton.triggerEventHandler('click', null);
|
||||
|
||||
expect(comp.deselectAll).toHaveBeenCalled();
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteFormats success', () => {
|
||||
beforeEach(async(() => {
|
||||
notificationsServiceStub = new NotificationsServiceStub();
|
||||
|
||||
scheduler = getTestScheduler();
|
||||
|
||||
bitstreamFormatService = jasmine.createSpyObj('bitstreamFormatService', {
|
||||
findAll: observableOf(mockFormatsRD),
|
||||
find: observableOf(new RemoteData(false, false, true, undefined, mockFormatsList[0])),
|
||||
getSelectedBitstreamFormats: observableOf(mockFormatsList),
|
||||
selectBitstreamFormat: {},
|
||||
deselectBitstreamFormat: {},
|
||||
deselectAllBitstreamFormats: {},
|
||||
delete: observableOf(true),
|
||||
clearBitStreamFormatRequests: observableOf('cleared')
|
||||
});
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()],
|
||||
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
|
||||
providers: [
|
||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
|
||||
{provide: HostWindowService, useValue: new HostWindowServiceStub(0)},
|
||||
{provide: NotificationsService, useValue: notificationsServiceStub}
|
||||
]
|
||||
}).compileComponents();
|
||||
}
|
||||
));
|
||||
|
||||
beforeEach(initBeforeEach);
|
||||
it('should clear bitstream formats ', () => {
|
||||
comp.deleteFormats();
|
||||
|
||||
expect(bitstreamFormatService.clearBitStreamFormatRequests).toHaveBeenCalled();
|
||||
expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat1);
|
||||
expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat2);
|
||||
expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat3);
|
||||
expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat4);
|
||||
|
||||
expect(notificationsServiceStub.success).toHaveBeenCalledWith('admin.registries.bitstream-formats.delete.success.head',
|
||||
'admin.registries.bitstream-formats.delete.success.amount');
|
||||
expect(notificationsServiceStub.error).not.toHaveBeenCalled();
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteFormats error', () => {
|
||||
beforeEach(async(() => {
|
||||
notificationsServiceStub = new NotificationsServiceStub();
|
||||
|
||||
scheduler = getTestScheduler();
|
||||
|
||||
bitstreamFormatService = jasmine.createSpyObj('bitstreamFormatService', {
|
||||
findAll: observableOf(mockFormatsRD),
|
||||
find: observableOf(new RemoteData(false, false, true, undefined, mockFormatsList[0])),
|
||||
getSelectedBitstreamFormats: observableOf(mockFormatsList),
|
||||
selectBitstreamFormat: {},
|
||||
deselectBitstreamFormat: {},
|
||||
deselectAllBitstreamFormats: {},
|
||||
delete: observableOf(false),
|
||||
clearBitStreamFormatRequests: observableOf('cleared')
|
||||
});
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()],
|
||||
declarations: [BitstreamFormatsComponent, PaginationComponent, EnumKeysPipe],
|
||||
providers: [
|
||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatService},
|
||||
{provide: HostWindowService, useValue: new HostWindowServiceStub(0)},
|
||||
{provide: NotificationsService, useValue: notificationsServiceStub}
|
||||
]
|
||||
}).compileComponents();
|
||||
}
|
||||
));
|
||||
|
||||
beforeEach(initBeforeEach);
|
||||
it('should clear bitstream formats ', () => {
|
||||
comp.deleteFormats();
|
||||
|
||||
expect(bitstreamFormatService.clearBitStreamFormatRequests).toHaveBeenCalled();
|
||||
expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat1);
|
||||
expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat2);
|
||||
expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat3);
|
||||
expect(bitstreamFormatService.delete).toHaveBeenCalledWith(bitstreamFormat4);
|
||||
|
||||
expect(notificationsServiceStub.error).toHaveBeenCalledWith('admin.registries.bitstream-formats.delete.failure.head',
|
||||
'admin.registries.bitstream-formats.delete.failure.amount');
|
||||
expect(notificationsServiceStub.success).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1,10 +1,16 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { RegistryService } from '../../../core/registry/registry.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { BehaviorSubject, combineLatest as observableCombineLatest, Observable, zip } from 'rxjs';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { PaginatedList } from '../../../core/data/paginated-list';
|
||||
import { BitstreamFormat } from '../../../core/registry/mock-bitstream-format.model';
|
||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||
import { BitstreamFormat } from '../../../core/shared/bitstream-format.model';
|
||||
import { BitstreamFormatDataService } from '../../../core/data/bitstream-format-data.service';
|
||||
import { FindAllOptions } from '../../../core/data/request.models';
|
||||
import { map, switchMap, take } from 'rxjs/operators';
|
||||
import { hasValue } from '../../../shared/empty.util';
|
||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
/**
|
||||
* This component renders a list of bitstream formats
|
||||
@@ -13,24 +19,122 @@ import { PaginationComponentOptions } from '../../../shared/pagination/paginatio
|
||||
selector: 'ds-bitstream-formats',
|
||||
templateUrl: './bitstream-formats.component.html'
|
||||
})
|
||||
export class BitstreamFormatsComponent {
|
||||
export class BitstreamFormatsComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* A paginated list of bitstream formats to be shown on the page
|
||||
*/
|
||||
bitstreamFormats: Observable<RemoteData<PaginatedList<BitstreamFormat>>>;
|
||||
|
||||
/**
|
||||
* A BehaviourSubject that keeps track of the pageState used to update the currently displayed bitstreamFormats
|
||||
*/
|
||||
pageState: BehaviorSubject<string>;
|
||||
|
||||
/**
|
||||
* The current pagination configuration for the page used by the FindAll method
|
||||
* Currently simply renders all bitstream formats
|
||||
*/
|
||||
config: FindAllOptions = Object.assign(new FindAllOptions(), {
|
||||
elementsPerPage: 10000
|
||||
});
|
||||
|
||||
/**
|
||||
* The current pagination configuration for the page
|
||||
* Currently simply renders all bitstream formats
|
||||
*/
|
||||
config: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||
pageConfig: PaginationComponentOptions = Object.assign(new PaginationComponentOptions(), {
|
||||
id: 'registry-bitstreamformats-pagination',
|
||||
pageSize: 10000
|
||||
});
|
||||
|
||||
constructor(private registryService: RegistryService) {
|
||||
this.updateFormats();
|
||||
constructor(private notificationsService: NotificationsService,
|
||||
private router: Router,
|
||||
private translateService: TranslateService,
|
||||
private bitstreamFormatService: BitstreamFormatDataService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the currently selected formats from the registry and updates the presented list
|
||||
*/
|
||||
deleteFormats() {
|
||||
this.bitstreamFormatService.clearBitStreamFormatRequests().subscribe();
|
||||
this.bitstreamFormatService.getSelectedBitstreamFormats().pipe(take(1)).subscribe(
|
||||
(formats) => {
|
||||
const tasks$ = [];
|
||||
for (const format of formats) {
|
||||
if (hasValue(format.id)) {
|
||||
tasks$.push(this.bitstreamFormatService.delete(format));
|
||||
}
|
||||
}
|
||||
zip(...tasks$).subscribe((results: boolean[]) => {
|
||||
const successResponses = results.filter((result: boolean) => result);
|
||||
const failedResponses = results.filter((result: boolean) => !result);
|
||||
if (successResponses.length > 0) {
|
||||
this.showNotification(true, successResponses.length);
|
||||
}
|
||||
if (failedResponses.length > 0) {
|
||||
this.showNotification(false, failedResponses.length);
|
||||
}
|
||||
|
||||
this.deselectAll();
|
||||
this.pageState.next('update-on-delete');
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deselects all selecetd bitstream formats
|
||||
*/
|
||||
deselectAll() {
|
||||
this.bitstreamFormatService.deselectAllBitstreamFormats();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given bitstream format is selected in the list (checkbox)
|
||||
* @param bitstreamFormat
|
||||
*/
|
||||
isSelected(bitstreamFormat: BitstreamFormat): Observable<boolean> {
|
||||
return this.bitstreamFormatService.getSelectedBitstreamFormats().pipe(
|
||||
map((bitstreamFormats: BitstreamFormat[]) => {
|
||||
return bitstreamFormats.find((selectedFormat) => selectedFormat.id === bitstreamFormat.id) != null;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects or deselects a bitstream format based on the checkbox state
|
||||
* @param bitstreamFormat
|
||||
* @param event
|
||||
*/
|
||||
selectBitStreamFormat(bitstreamFormat: BitstreamFormat, event) {
|
||||
event.target.checked ?
|
||||
this.bitstreamFormatService.selectBitstreamFormat(bitstreamFormat) :
|
||||
this.bitstreamFormatService.deselectBitstreamFormat(bitstreamFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show notifications for an amount of deleted bitstream formats
|
||||
* @param success Whether or not the notification should be a success message (error message when false)
|
||||
* @param amount The amount of deleted bitstream formats
|
||||
*/
|
||||
private showNotification(success: boolean, amount: number) {
|
||||
const prefix = 'admin.registries.bitstream-formats.delete';
|
||||
const suffix = success ? 'success' : 'failure';
|
||||
|
||||
const messages = observableCombineLatest(
|
||||
this.translateService.get(`${prefix}.${suffix}.head`),
|
||||
this.translateService.get(`${prefix}.${suffix}.amount`, {amount: amount})
|
||||
);
|
||||
messages.subscribe(([head, content]) => {
|
||||
|
||||
if (success) {
|
||||
this.notificationsService.success(head, content);
|
||||
} else {
|
||||
this.notificationsService.error(head, content);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,13 +143,23 @@ export class BitstreamFormatsComponent {
|
||||
*/
|
||||
onPageChange(event) {
|
||||
this.config.currentPage = event;
|
||||
this.pageConfig.currentPage = event;
|
||||
this.updateFormats();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.pageState = new BehaviorSubject('init');
|
||||
this.bitstreamFormats = this.pageState.pipe(
|
||||
switchMap(() => {
|
||||
return this.updateFormats()
|
||||
;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to update the bitstream formats that are shown
|
||||
* Finds all formats based on the current config
|
||||
*/
|
||||
private updateFormats() {
|
||||
this.bitstreamFormats = this.registryService.getBitstreamFormats(this.config);
|
||||
return this.bitstreamFormatService.findAll(this.config);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,30 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { BitstreamFormatsComponent } from './bitstream-formats.component';
|
||||
import { SharedModule } from '../../../shared/shared.module';
|
||||
import { FormatFormComponent } from './format-form/format-form.component';
|
||||
import { EditBitstreamFormatComponent } from './edit-bitstream-format/edit-bitstream-format.component';
|
||||
import { BitstreamFormatsRoutingModule } from './bitstream-formats-routing.module';
|
||||
import { AddBitstreamFormatComponent } from './add-bitstream-format/add-bitstream-format.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
RouterModule,
|
||||
TranslateModule,
|
||||
BitstreamFormatsRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
BitstreamFormatsComponent,
|
||||
EditBitstreamFormatComponent,
|
||||
AddBitstreamFormatComponent,
|
||||
FormatFormComponent
|
||||
],
|
||||
entryComponents: []
|
||||
})
|
||||
export class BitstreamFormatsModule {
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { find } from 'rxjs/operators';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { BitstreamFormat } from '../../../core/shared/bitstream-format.model';
|
||||
import { BitstreamFormatDataService } from '../../../core/data/bitstream-format-data.service';
|
||||
import { hasValue } from '../../../shared/empty.util';
|
||||
|
||||
/**
|
||||
* This class represents a resolver that requests a specific bitstreamFormat before the route is activated
|
||||
*/
|
||||
@Injectable()
|
||||
export class BitstreamFormatsResolver implements Resolve<RemoteData<BitstreamFormat>> {
|
||||
constructor(private bitstreamFormatDataService: BitstreamFormatDataService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Method for resolving an bitstreamFormat based on the parameters in the current route
|
||||
* @param {ActivatedRouteSnapshot} route The current ActivatedRouteSnapshot
|
||||
* @param {RouterStateSnapshot} state The current RouterStateSnapshot
|
||||
* @returns Observable<<RemoteData<BitstreamFormat>> Emits the found bitstreamFormat based on the parameters in the current route,
|
||||
* or an error if something went wrong
|
||||
*/
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<RemoteData<BitstreamFormat>> {
|
||||
return this.bitstreamFormatDataService.findById(route.params.id)
|
||||
.pipe(
|
||||
find((RD) => hasValue(RD.error) || RD.hasSucceeded),
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12 pb-4">
|
||||
<h2 id="sub-header"
|
||||
class="border-bottom pb-2">{{'admin.registries.bitstream-formats.edit.head' | translate:{format: (bitstreamFormatRD$ | async)?.payload.shortDescription} }}</h2>
|
||||
|
||||
<ds-bitstream-format-form [bitstreamFormat]="(bitstreamFormatRD$ | async)?.payload" (updatedFormat)="updateFormat($event)"></ds-bitstream-format-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@@ -0,0 +1,126 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { RouterStub } from '../../../../shared/testing/router-stub';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { RemoteData } from '../../../../core/data/remote-data';
|
||||
import { EditBitstreamFormatComponent } from './edit-bitstream-format.component';
|
||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||
import { NotificationsServiceStub } from '../../../../shared/testing/notifications-service-stub';
|
||||
import { BitstreamFormatDataService } from '../../../../core/data/bitstream-format-data.service';
|
||||
import { RestResponse } from '../../../../core/cache/response.models';
|
||||
import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model';
|
||||
import { BitstreamFormatSupportLevel } from '../../../../core/shared/bitstream-format-support-level';
|
||||
import { ResourceType } from '../../../../core/shared/resource-type';
|
||||
|
||||
describe('EditBitstreamFormatComponent', () => {
|
||||
let comp: EditBitstreamFormatComponent;
|
||||
let fixture: ComponentFixture<EditBitstreamFormatComponent>;
|
||||
|
||||
const bitstreamFormat: BitstreamFormat = {
|
||||
uuid: 'test-uuid',
|
||||
id: 'test-uuid',
|
||||
shortDescription: 'Adobe PDF',
|
||||
description: 'Adobe Portable Document Format',
|
||||
mimetype: 'application/pdf',
|
||||
supportLevel: BitstreamFormatSupportLevel.Unknown,
|
||||
internal: false,
|
||||
extensions: ['pdf', 'also-pdf'],
|
||||
type: ResourceType.BitstreamFormat,
|
||||
self: 'self-link'
|
||||
};
|
||||
|
||||
const routeStub = {
|
||||
data: observableOf({
|
||||
bitstreamFormat: new RemoteData(false, false, true, null, bitstreamFormat)
|
||||
})
|
||||
};
|
||||
|
||||
let router;
|
||||
let notificationService: NotificationsServiceStub;
|
||||
let bitstreamFormatDataService: BitstreamFormatDataService;
|
||||
|
||||
const initAsync = () => {
|
||||
router = new RouterStub();
|
||||
notificationService = new NotificationsServiceStub();
|
||||
bitstreamFormatDataService = jasmine.createSpyObj('bitstreamFormatDataService', {
|
||||
updateBitstreamFormat: observableOf(new RestResponse(true, 200, 'Success'))
|
||||
});
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()],
|
||||
declarations: [EditBitstreamFormatComponent],
|
||||
providers: [
|
||||
{provide: ActivatedRoute, useValue: routeStub},
|
||||
{provide: Router, useValue: router},
|
||||
{provide: NotificationsService, useValue: notificationService},
|
||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService},
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
}).compileComponents();
|
||||
};
|
||||
|
||||
const initBeforeEach = () => {
|
||||
fixture = TestBed.createComponent(EditBitstreamFormatComponent);
|
||||
comp = fixture.componentInstance;
|
||||
|
||||
fixture.detectChanges();
|
||||
};
|
||||
|
||||
describe('init', () => {
|
||||
beforeEach(async(initAsync));
|
||||
beforeEach(initBeforeEach);
|
||||
it('should initialise the bitstreamFormat based on the route', () => {
|
||||
|
||||
comp.bitstreamFormatRD$.subscribe((format: RemoteData<BitstreamFormat>) => {
|
||||
expect(format).toEqual(new RemoteData(false, false, true, null, bitstreamFormat));
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('updateFormat success', () => {
|
||||
beforeEach(async(initAsync));
|
||||
beforeEach(initBeforeEach);
|
||||
it('should send the updated form to the service, show a notification and navigate to ', () => {
|
||||
comp.updateFormat(bitstreamFormat);
|
||||
|
||||
expect(bitstreamFormatDataService.updateBitstreamFormat).toHaveBeenCalledWith(bitstreamFormat);
|
||||
expect(notificationService.success).toHaveBeenCalled();
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/admin/registries/bitstream-formats']);
|
||||
|
||||
});
|
||||
});
|
||||
describe('updateFormat error', () => {
|
||||
beforeEach(async( () => {
|
||||
router = new RouterStub();
|
||||
notificationService = new NotificationsServiceStub();
|
||||
bitstreamFormatDataService = jasmine.createSpyObj('bitstreamFormatDataService', {
|
||||
updateBitstreamFormat: observableOf(new RestResponse(false, 400, 'Bad Request'))
|
||||
});
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), TranslateModule.forRoot(), NgbModule.forRoot()],
|
||||
declarations: [EditBitstreamFormatComponent],
|
||||
providers: [
|
||||
{provide: ActivatedRoute, useValue: routeStub},
|
||||
{provide: Router, useValue: router},
|
||||
{provide: NotificationsService, useValue: notificationService},
|
||||
{provide: BitstreamFormatDataService, useValue: bitstreamFormatDataService},
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
}).compileComponents();
|
||||
}));
|
||||
beforeEach(initBeforeEach);
|
||||
it('should send the updated form to the service, show a notification and navigate to ', () => {
|
||||
comp.updateFormat(bitstreamFormat);
|
||||
|
||||
expect(bitstreamFormatDataService.updateBitstreamFormat).toHaveBeenCalledWith(bitstreamFormat);
|
||||
expect(notificationService.error).toHaveBeenCalled();
|
||||
expect(router.navigate).not.toHaveBeenCalled();
|
||||
|
||||
});
|
||||
});
|
||||
});
|
@@ -0,0 +1,62 @@
|
||||
import { map, take } from 'rxjs/operators';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { RemoteData } from '../../../../core/data/remote-data';
|
||||
import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model';
|
||||
import { BitstreamFormatDataService } from '../../../../core/data/bitstream-format-data.service';
|
||||
import { RestResponse } from '../../../../core/cache/response.models';
|
||||
import { NotificationsService } from '../../../../shared/notifications/notifications.service';
|
||||
import { getBitstreamFormatsModulePath } from '../../admin-registries-routing.module';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
/**
|
||||
* This component renders the edit page of a bitstream format.
|
||||
* The route parameter 'id' is used to request the bitstream format.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-edit-bitstream-format',
|
||||
templateUrl: './edit-bitstream-format.component.html',
|
||||
})
|
||||
export class EditBitstreamFormatComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* The bitstream format wrapped in a remote-data object
|
||||
*/
|
||||
bitstreamFormatRD$: Observable<RemoteData<BitstreamFormat>>;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private notificationService: NotificationsService,
|
||||
private translateService: TranslateService,
|
||||
private bitstreamFormatDataService: BitstreamFormatDataService,
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.bitstreamFormatRD$ = this.route.data.pipe(
|
||||
map((data) => data.bitstreamFormat as RemoteData<BitstreamFormat>)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the bitstream format based on the provided bitstream format emitted by the form.
|
||||
* When successful, a success notification will be shown and the user will be navigated back to the overview page.
|
||||
* When failed, an error notification will be shown.
|
||||
*/
|
||||
updateFormat(bitstreamFormat: BitstreamFormat) {
|
||||
this.bitstreamFormatDataService.updateBitstreamFormat(bitstreamFormat).pipe(take(1)
|
||||
).subscribe((response: RestResponse) => {
|
||||
if (response.isSuccessful) {
|
||||
this.notificationService.success(this.translateService.get('admin.registries.bitstream-formats.edit.success.head'),
|
||||
this.translateService.get('admin.registries.bitstream-formats.edit.success.content'));
|
||||
this.router.navigate([getBitstreamFormatsModulePath()]);
|
||||
} else {
|
||||
this.notificationService.error('admin.registries.bitstream-formats.edit.failure.head',
|
||||
'admin.registries.bitstream-formats.create.edit.content');
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
<ds-form *ngIf="formModel"
|
||||
[formId]="'comcol-form-id'"
|
||||
[formModel]="formModel" (submitForm)="onSubmit()" (cancel)="onCancel()"></ds-form>
|
@@ -0,0 +1,108 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { RouterStub } from '../../../../shared/testing/router-stub';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { FormatFormComponent } from './format-form.component';
|
||||
import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model';
|
||||
import { BitstreamFormatSupportLevel } from '../../../../core/shared/bitstream-format-support-level';
|
||||
import { ResourceType } from '../../../../core/shared/resource-type';
|
||||
import { DynamicCheckboxModel, DynamicFormArrayModel, DynamicInputModel } from '@ng-dynamic-forms/core';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { isEmpty } from '../../../../shared/empty.util';
|
||||
|
||||
describe('FormatFormComponent', () => {
|
||||
let comp: FormatFormComponent;
|
||||
let fixture: ComponentFixture<FormatFormComponent>;
|
||||
|
||||
const router = new RouterStub();
|
||||
|
||||
const bitstreamFormat: BitstreamFormat = {
|
||||
uuid: 'test-uuid',
|
||||
id: 'test-uuid',
|
||||
shortDescription: 'Adobe PDF',
|
||||
description: 'Adobe Portable Document Format',
|
||||
mimetype: 'application/pdf',
|
||||
supportLevel: BitstreamFormatSupportLevel.Unknown,
|
||||
internal: false,
|
||||
extensions: ['pdf', 'also-pdf'],
|
||||
type: ResourceType.BitstreamFormat,
|
||||
self: 'self-link'
|
||||
};
|
||||
|
||||
const submittedBitstreamFormat = new BitstreamFormat();
|
||||
submittedBitstreamFormat.id = bitstreamFormat.id;
|
||||
submittedBitstreamFormat.shortDescription = bitstreamFormat.shortDescription;
|
||||
submittedBitstreamFormat.mimetype = bitstreamFormat.mimetype;
|
||||
submittedBitstreamFormat.description = bitstreamFormat.description;
|
||||
submittedBitstreamFormat.supportLevel = bitstreamFormat.supportLevel;
|
||||
submittedBitstreamFormat.internal = bitstreamFormat.internal;
|
||||
submittedBitstreamFormat.extensions = bitstreamFormat.extensions;
|
||||
|
||||
const initAsync = () => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CommonModule, RouterTestingModule.withRoutes([]), ReactiveFormsModule, FormsModule, TranslateModule.forRoot(), NgbModule.forRoot()],
|
||||
declarations: [FormatFormComponent],
|
||||
providers: [
|
||||
{provide: Router, useValue: router},
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
}).compileComponents();
|
||||
};
|
||||
|
||||
const initBeforeEach = () => {
|
||||
fixture = TestBed.createComponent(FormatFormComponent);
|
||||
comp = fixture.componentInstance;
|
||||
|
||||
comp.bitstreamFormat = bitstreamFormat;
|
||||
fixture.detectChanges();
|
||||
};
|
||||
|
||||
describe('initialise', () => {
|
||||
beforeEach(async(initAsync));
|
||||
beforeEach(initBeforeEach);
|
||||
it('should initialises the values in the form', () => {
|
||||
|
||||
expect((comp.formModel[0] as DynamicInputModel).value).toBe(bitstreamFormat.shortDescription);
|
||||
expect((comp.formModel[1] as DynamicInputModel).value).toBe(bitstreamFormat.mimetype);
|
||||
expect((comp.formModel[2] as DynamicInputModel).value).toBe(bitstreamFormat.description);
|
||||
expect((comp.formModel[3] as DynamicInputModel).value).toBe(bitstreamFormat.supportLevel);
|
||||
expect((comp.formModel[4] as DynamicCheckboxModel).value).toBe(bitstreamFormat.internal);
|
||||
|
||||
const formArray = (comp.formModel[5] as DynamicFormArrayModel);
|
||||
const extensions = [];
|
||||
for (let i = 0; i < formArray.groups.length; i++) {
|
||||
const value = (formArray.get(i).get(0) as DynamicInputModel).value;
|
||||
if (!isEmpty(value)) {
|
||||
extensions.push((formArray.get(i).get(0) as DynamicInputModel).value);
|
||||
}
|
||||
}
|
||||
|
||||
expect(extensions).toEqual(bitstreamFormat.extensions);
|
||||
|
||||
});
|
||||
});
|
||||
describe('onSubmit', () => {
|
||||
beforeEach(async(initAsync));
|
||||
beforeEach(initBeforeEach);
|
||||
|
||||
it('should emit the bitstreamFormat currently present in the form', () => {
|
||||
spyOn(comp.updatedFormat, 'emit');
|
||||
comp.onSubmit();
|
||||
|
||||
expect(comp.updatedFormat.emit).toHaveBeenCalledWith(submittedBitstreamFormat);
|
||||
});
|
||||
});
|
||||
describe('onCancel', () => {
|
||||
beforeEach(async(initAsync));
|
||||
beforeEach(initBeforeEach);
|
||||
|
||||
it('should navigate back to the bitstream overview', () => {
|
||||
comp.onCancel();
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/admin/registries/bitstream-formats']);
|
||||
});
|
||||
});
|
||||
});
|
@@ -0,0 +1,193 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { BitstreamFormat } from '../../../../core/shared/bitstream-format.model';
|
||||
import { BitstreamFormatSupportLevel } from '../../../../core/shared/bitstream-format-support-level';
|
||||
import {
|
||||
DynamicCheckboxModel,
|
||||
DynamicFormArrayModel,
|
||||
DynamicFormControlLayout,
|
||||
DynamicFormControlModel,
|
||||
DynamicFormService,
|
||||
DynamicInputModel,
|
||||
DynamicSelectModel,
|
||||
DynamicTextAreaModel
|
||||
} from '@ng-dynamic-forms/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { getBitstreamFormatsModulePath } from '../../admin-registries-routing.module';
|
||||
import { hasValue, isEmpty } from '../../../../shared/empty.util';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
/**
|
||||
* The component responsible for rendering the form to create/edit a bitstream format
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-bitstream-format-form',
|
||||
templateUrl: './format-form.component.html'
|
||||
})
|
||||
export class FormatFormComponent implements OnInit {
|
||||
|
||||
/**
|
||||
* The current bitstream format
|
||||
* This can either be and existing one or a new one
|
||||
*/
|
||||
@Input() bitstreamFormat: BitstreamFormat = new BitstreamFormat();
|
||||
|
||||
/**
|
||||
* EventEmitter that will emit the updated bitstream format
|
||||
*/
|
||||
@Output() updatedFormat: EventEmitter<BitstreamFormat> = new EventEmitter<BitstreamFormat>();
|
||||
|
||||
/**
|
||||
* The different supported support level of the bitstream format
|
||||
*/
|
||||
supportLevelOptions = [{label: BitstreamFormatSupportLevel.Known, value: BitstreamFormatSupportLevel.Known},
|
||||
{label: BitstreamFormatSupportLevel.Unknown, value: BitstreamFormatSupportLevel.Unknown},
|
||||
{label: BitstreamFormatSupportLevel.Supported, value: BitstreamFormatSupportLevel.Supported}];
|
||||
|
||||
/**
|
||||
* Styling element for repeatable field
|
||||
*/
|
||||
arrayElementLayout: DynamicFormControlLayout = {
|
||||
grid: {
|
||||
group: 'form-row',
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Styling element for element of repeatable field
|
||||
*/
|
||||
arrayInputElementLayout: DynamicFormControlLayout = {
|
||||
grid: {
|
||||
host: 'col'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The form model representing the bitstream format
|
||||
*/
|
||||
formModel: DynamicFormControlModel[] = [
|
||||
new DynamicInputModel({
|
||||
id: 'shortDescription',
|
||||
name: 'shortDescription',
|
||||
label: 'admin.registries.bitstream-formats.edit.shortDescription.label',
|
||||
hint: 'admin.registries.bitstream-formats.edit.shortDescription.hint',
|
||||
required: true,
|
||||
validators: {
|
||||
required: null
|
||||
},
|
||||
errorMessages: {
|
||||
required: 'Please enter a name for this bitstream format'
|
||||
},
|
||||
}),
|
||||
new DynamicInputModel({
|
||||
id: 'mimetype',
|
||||
name: 'mimetype',
|
||||
label: 'admin.registries.bitstream-formats.edit.mimetype.label',
|
||||
hint: 'admin.registries.bitstream-formats.edit.mimetype.hint',
|
||||
|
||||
}),
|
||||
new DynamicTextAreaModel({
|
||||
id: 'description',
|
||||
name: 'description',
|
||||
label: 'admin.registries.bitstream-formats.edit.description.label',
|
||||
hint: 'admin.registries.bitstream-formats.edit.description.hint',
|
||||
|
||||
}),
|
||||
new DynamicSelectModel({
|
||||
id: 'supportLevel',
|
||||
name: 'supportLevel',
|
||||
options: this.supportLevelOptions,
|
||||
label: 'admin.registries.bitstream-formats.edit.supportLevel.label',
|
||||
hint: 'admin.registries.bitstream-formats.edit.supportLevel.hint',
|
||||
value: this.supportLevelOptions[0].value
|
||||
|
||||
}),
|
||||
new DynamicCheckboxModel({
|
||||
id: 'internal',
|
||||
name: 'internal',
|
||||
label: 'Internal',
|
||||
hint: 'admin.registries.bitstream-formats.edit.internal.hint',
|
||||
}),
|
||||
new DynamicFormArrayModel({
|
||||
id: 'extensions',
|
||||
name: 'extensions',
|
||||
label: 'admin.registries.bitstream-formats.edit.extensions.label',
|
||||
groupFactory: () => [
|
||||
new DynamicInputModel({
|
||||
id: 'extension',
|
||||
}, this.arrayInputElementLayout)
|
||||
]
|
||||
}, this.arrayElementLayout),
|
||||
];
|
||||
|
||||
constructor(private dynamicFormService: DynamicFormService,
|
||||
private translateService: TranslateService,
|
||||
private router: Router) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
this.initValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the form based on the provided bitstream format
|
||||
*/
|
||||
initValues() {
|
||||
this.formModel.forEach(
|
||||
(fieldModel: DynamicFormControlModel) => {
|
||||
if (fieldModel.name === 'extensions') {
|
||||
if (hasValue(this.bitstreamFormat.extensions)) {
|
||||
const extenstions = this.bitstreamFormat.extensions;
|
||||
const formArray = (fieldModel as DynamicFormArrayModel);
|
||||
for (let i = 0; i < extenstions.length; i++) {
|
||||
formArray.insertGroup(i).group[0] = new DynamicInputModel({
|
||||
id: `extension-${i}`,
|
||||
value: extenstions[i]
|
||||
}, this.arrayInputElementLayout);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (hasValue(this.bitstreamFormat[fieldModel.name])) {
|
||||
(fieldModel as DynamicInputModel).value = this.bitstreamFormat[fieldModel.name];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an updated bistream format based on the current values in the form
|
||||
* Emits the updated bitstream format trouhg the updatedFormat emitter
|
||||
*/
|
||||
onSubmit() {
|
||||
const updatedBitstreamFormat = Object.assign(new BitstreamFormat(),
|
||||
{
|
||||
id: this.bitstreamFormat.id
|
||||
});
|
||||
|
||||
this.formModel.forEach(
|
||||
(fieldModel: DynamicFormControlModel) => {
|
||||
if (fieldModel.name === 'extensions') {
|
||||
const formArray = (fieldModel as DynamicFormArrayModel);
|
||||
const extensions = [];
|
||||
for (let i = 0; i < formArray.groups.length; i++) {
|
||||
const value = (formArray.get(i).get(0) as DynamicInputModel).value;
|
||||
if (!isEmpty(value)) {
|
||||
extensions.push((formArray.get(i).get(0) as DynamicInputModel).value);
|
||||
}
|
||||
}
|
||||
updatedBitstreamFormat.extensions = extensions;
|
||||
} else {
|
||||
updatedBitstreamFormat[fieldModel.name] = (fieldModel as DynamicInputModel).value;
|
||||
}
|
||||
});
|
||||
this.updatedFormat.emit(updatedBitstreamFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the edit/create action of the bitstream format and navigates back to the bitstream format registry
|
||||
*/
|
||||
onCancel() {
|
||||
this.router.navigate([getBitstreamFormatsModulePath()]);
|
||||
}
|
||||
}
|
@@ -1,11 +1,19 @@
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { URLCombiner } from '../core/url-combiner/url-combiner';
|
||||
import { getAdminModulePath } from '../app-routing.module';
|
||||
|
||||
const REGISTRIES_MODULE_PATH = 'registries';
|
||||
|
||||
export function getRegistriesModulePath() {
|
||||
return new URLCombiner(getAdminModulePath(), REGISTRIES_MODULE_PATH).toString();
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'registries',
|
||||
path: REGISTRIES_MODULE_PATH,
|
||||
loadChildren: './admin-registries/admin-registries.module#AdminRegistriesModule'
|
||||
}
|
||||
])
|
||||
|
@@ -16,6 +16,12 @@ const COMMUNITY_MODULE_PATH = 'communities';
|
||||
export function getCommunityModulePath() {
|
||||
return `/${COMMUNITY_MODULE_PATH}`;
|
||||
}
|
||||
|
||||
const ADMIN_MODULE_PATH = 'admin';
|
||||
export function getAdminModulePath() {
|
||||
return `/${ADMIN_MODULE_PATH}`;
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot([
|
||||
@@ -27,7 +33,7 @@ export function getCommunityModulePath() {
|
||||
{ path: 'mydspace', loadChildren: './+my-dspace-page/my-dspace-page.module#MyDSpacePageModule', canActivate: [AuthenticatedGuard] },
|
||||
{ path: 'search', loadChildren: './+search-page/search-page.module#SearchPageModule' },
|
||||
{ path: 'browse', loadChildren: './+browse-by/browse-by.module#BrowseByModule' },
|
||||
{ path: 'admin', loadChildren: './+admin/admin.module#AdminModule', canActivate: [AuthenticatedGuard] },
|
||||
{ path: ADMIN_MODULE_PATH, loadChildren: './+admin/admin.module#AdminModule', canActivate: [AuthenticatedGuard] },
|
||||
{ path: 'login', loadChildren: './+login-page/login-page.module#LoginPageModule' },
|
||||
{ path: 'logout', loadChildren: './+logout-page/logout-page.module#LogoutPageModule' },
|
||||
{ path: 'submit', loadChildren: './+submit-page/submit-page.module#SubmitPageModule' },
|
||||
|
@@ -23,6 +23,10 @@ import { hasValue } from './shared/empty.util';
|
||||
import { cssVariablesReducer, CSSVariablesState } from './shared/sass-helper/sass-helper.reducer';
|
||||
import { menusReducer, MenusState } from './shared/menu/menu.reducer';
|
||||
import { historyReducer, HistoryState } from './shared/history/history.reducer';
|
||||
import {
|
||||
bitstreamFormatReducer,
|
||||
BitstreamFormatRegistryState
|
||||
} from './+admin/admin-registries/bitstream-formats/bitstream-format.reducers';
|
||||
|
||||
export interface AppState {
|
||||
router: fromRouter.RouterReducerState;
|
||||
@@ -30,6 +34,7 @@ export interface AppState {
|
||||
hostWindow: HostWindowState;
|
||||
forms: FormState;
|
||||
metadataRegistry: MetadataRegistryState;
|
||||
bitstreamFormats: BitstreamFormatRegistryState;
|
||||
notifications: NotificationsState;
|
||||
searchSidebar: SearchSidebarState;
|
||||
searchFilter: SearchFiltersState;
|
||||
@@ -44,6 +49,7 @@ export const appReducers: ActionReducerMap<AppState> = {
|
||||
hostWindow: hostWindowReducer,
|
||||
forms: formReducer,
|
||||
metadataRegistry: metadataRegistryReducer,
|
||||
bitstreamFormats: bitstreamFormatReducer,
|
||||
notifications: notificationsReducer,
|
||||
searchSidebar: sidebarReducer,
|
||||
searchFilter: filterReducer,
|
||||
|
@@ -4,7 +4,7 @@ import { BitstreamFormat } from '../../shared/bitstream-format.model';
|
||||
import { mapsTo } from '../builders/build-decorators';
|
||||
import { IDToUUIDSerializer } from '../id-to-uuid-serializer';
|
||||
import { NormalizedObject } from './normalized-object.model';
|
||||
import { SupportLevel } from './support-level.model';
|
||||
import { BitstreamFormatSupportLevel } from '../../shared/bitstream-format-support-level';
|
||||
|
||||
/**
|
||||
* Normalized model class for a Bitstream Format
|
||||
@@ -35,7 +35,7 @@ export class NormalizedBitstreamFormat extends NormalizedObject<BitstreamFormat>
|
||||
* The level of support the system offers for this Bitstream Format
|
||||
*/
|
||||
@autoserialize
|
||||
supportLevel: SupportLevel;
|
||||
supportLevel: BitstreamFormatSupportLevel;
|
||||
|
||||
/**
|
||||
* True if the Bitstream Format is used to store system information, rather than the content of items in the system
|
||||
@@ -47,7 +47,7 @@ export class NormalizedBitstreamFormat extends NormalizedObject<BitstreamFormat>
|
||||
* String representing this Bitstream Format's file extension
|
||||
*/
|
||||
@autoserialize
|
||||
extensions: string;
|
||||
extensions: string[];
|
||||
|
||||
/**
|
||||
* Identifier for this Bitstream Format
|
||||
|
@@ -87,6 +87,7 @@ import { MyDSpaceResponseParsingService } from './data/mydspace-response-parsing
|
||||
import { ClaimedTaskDataService } from './tasks/claimed-task-data.service';
|
||||
import { PoolTaskDataService } from './tasks/pool-task-data.service';
|
||||
import { TaskResponseParsingService } from './tasks/task-response-parsing.service';
|
||||
import { BitstreamFormatDataService } from './data/bitstream-format-data.service';
|
||||
|
||||
const IMPORTS = [
|
||||
CommonModule,
|
||||
@@ -126,6 +127,7 @@ const PROVIDERS = [
|
||||
ObjectCacheService,
|
||||
PaginationComponentOptions,
|
||||
RegistryService,
|
||||
BitstreamFormatDataService,
|
||||
NormalizedObjectBuildService,
|
||||
RemoteDataBuildService,
|
||||
RequestService,
|
||||
|
293
src/app/core/data/bitstream-format-data.service.spec.ts
Normal file
293
src/app/core/data/bitstream-format-data.service.spec.ts
Normal file
@@ -0,0 +1,293 @@
|
||||
import { BitstreamFormatDataService } from './bitstream-format-data.service';
|
||||
import { RequestEntry } from './request.reducer';
|
||||
import { RestResponse } from '../cache/response.models';
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
import { Action, Store } from '@ngrx/store';
|
||||
import { CoreState } from '../core.reducers';
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
import { cold, getTestScheduler, hot } from 'jasmine-marbles';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { BitstreamFormat } from '../shared/bitstream-format.model';
|
||||
import { async } from '@angular/core/testing';
|
||||
import {
|
||||
BitstreamFormatsRegistryDeselectAction,
|
||||
BitstreamFormatsRegistryDeselectAllAction,
|
||||
BitstreamFormatsRegistrySelectAction
|
||||
} from '../../+admin/admin-registries/bitstream-formats/bitstream-format.actions';
|
||||
import { TestScheduler } from 'rxjs/testing';
|
||||
|
||||
describe('BitstreamFormatDataService', () => {
|
||||
let service: BitstreamFormatDataService;
|
||||
let requestService;
|
||||
let scheduler: TestScheduler;
|
||||
|
||||
const bitstreamFormatsEndpoint = 'https://rest.api/core/bitstream-formats';
|
||||
const bitstreamFormatsIdEndpoint = 'https://rest.api/core/bitstream-formats/format-id';
|
||||
|
||||
const responseCacheEntry = new RequestEntry();
|
||||
responseCacheEntry.response = new RestResponse(true, 200, 'Success');
|
||||
responseCacheEntry.completed = true;
|
||||
|
||||
const store = {
|
||||
dispatch(action: Action) {
|
||||
// Do Nothing
|
||||
}
|
||||
} as Store<CoreState>;
|
||||
|
||||
const objectCache = {} as ObjectCacheService;
|
||||
const halEndpointService = {
|
||||
getEndpoint(linkPath: string): Observable<string> {
|
||||
return cold('a', {a: bitstreamFormatsEndpoint});
|
||||
}
|
||||
} as HALEndpointService;
|
||||
|
||||
const notificationsService = {} as NotificationsService;
|
||||
const http = {} as HttpClient;
|
||||
const comparator = {} as any;
|
||||
const dataBuildService = {} as NormalizedObjectBuildService;
|
||||
const rdbService = {} as RemoteDataBuildService;
|
||||
|
||||
function initTestService(halService) {
|
||||
return new BitstreamFormatDataService(
|
||||
requestService,
|
||||
rdbService,
|
||||
dataBuildService,
|
||||
store,
|
||||
objectCache,
|
||||
halService,
|
||||
notificationsService,
|
||||
http,
|
||||
comparator
|
||||
);
|
||||
}
|
||||
|
||||
describe('getBrowseEndpoint', () => {
|
||||
beforeEach(async(() => {
|
||||
scheduler = getTestScheduler();
|
||||
requestService = jasmine.createSpyObj('requestService', {
|
||||
configure: {},
|
||||
getByHref: observableOf(responseCacheEntry),
|
||||
getByUUID: cold('a', {a: responseCacheEntry}),
|
||||
generateRequestId: 'request-id',
|
||||
removeByHrefSubstring: {}
|
||||
});
|
||||
service = initTestService(halEndpointService);
|
||||
}));
|
||||
it('should get the browse endpoint', () => {
|
||||
const result = service.getBrowseEndpoint();
|
||||
const expected = cold('b', {b: bitstreamFormatsEndpoint});
|
||||
|
||||
expect(result).toBeObservable(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getUpdateEndpoint', () => {
|
||||
beforeEach(async(() => {
|
||||
scheduler = getTestScheduler();
|
||||
requestService = jasmine.createSpyObj('requestService', {
|
||||
configure: {},
|
||||
getByHref: observableOf(responseCacheEntry),
|
||||
getByUUID: cold('a', {a: responseCacheEntry}),
|
||||
generateRequestId: 'request-id',
|
||||
removeByHrefSubstring: {}
|
||||
});
|
||||
service = initTestService(halEndpointService);
|
||||
}));
|
||||
it('should get the update endpoint', () => {
|
||||
const formatId = 'format-id';
|
||||
|
||||
const result = service.getUpdateEndpoint(formatId);
|
||||
const expected = cold('b', {b: bitstreamFormatsIdEndpoint});
|
||||
|
||||
expect(result).toBeObservable(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getCreateEndpoint', () => {
|
||||
beforeEach(async(() => {
|
||||
scheduler = getTestScheduler();
|
||||
requestService = jasmine.createSpyObj('requestService', {
|
||||
configure: {},
|
||||
getByHref: observableOf(responseCacheEntry),
|
||||
getByUUID: cold('a', {a: responseCacheEntry}),
|
||||
generateRequestId: 'request-id',
|
||||
removeByHrefSubstring: {}
|
||||
});
|
||||
service = initTestService(halEndpointService);
|
||||
}));
|
||||
it('should get the create endpoint ', () => {
|
||||
|
||||
const result = service.getCreateEndpoint();
|
||||
const expected = cold('b', {b: bitstreamFormatsEndpoint});
|
||||
|
||||
expect(result).toBeObservable(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateBitstreamFormat', () => {
|
||||
beforeEach(async(() => {
|
||||
scheduler = getTestScheduler();
|
||||
requestService = jasmine.createSpyObj('requestService', {
|
||||
configure: {},
|
||||
getByHref: observableOf(responseCacheEntry),
|
||||
getByUUID: cold('a', {a: responseCacheEntry}),
|
||||
generateRequestId: 'request-id',
|
||||
removeByHrefSubstring: {}
|
||||
});
|
||||
service = initTestService(halEndpointService);
|
||||
}));
|
||||
it('should update the bitstream format', () => {
|
||||
const updatedBistreamFormat = new BitstreamFormat();
|
||||
updatedBistreamFormat.uuid = 'updated-uuid';
|
||||
|
||||
const expected = cold('(b)', {b: new RestResponse(true, 200, 'Success')});
|
||||
const result = service.updateBitstreamFormat(updatedBistreamFormat);
|
||||
|
||||
expect(result).toBeObservable(expected);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('createBitstreamFormat', () => {
|
||||
beforeEach(async(() => {
|
||||
scheduler = getTestScheduler();
|
||||
requestService = jasmine.createSpyObj('requestService', {
|
||||
configure: {},
|
||||
getByHref: observableOf(responseCacheEntry),
|
||||
getByUUID: cold('a', {a: responseCacheEntry}),
|
||||
generateRequestId: 'request-id',
|
||||
removeByHrefSubstring: {}
|
||||
});
|
||||
service = initTestService(halEndpointService);
|
||||
}));
|
||||
it('should create a new bitstream format', () => {
|
||||
const newFormat = new BitstreamFormat();
|
||||
newFormat.uuid = 'new-uuid';
|
||||
|
||||
const expected = cold('(b)', {b: new RestResponse(true, 200, 'Success')});
|
||||
const result = service.createBitstreamFormat(newFormat);
|
||||
|
||||
expect(result).toBeObservable(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('clearBitStreamFormatRequests', () => {
|
||||
beforeEach(async(() => {
|
||||
scheduler = getTestScheduler();
|
||||
requestService = jasmine.createSpyObj('requestService', {
|
||||
configure: {},
|
||||
getByHref: observableOf(responseCacheEntry),
|
||||
getByUUID: cold('a', {a: responseCacheEntry}),
|
||||
generateRequestId: 'request-id',
|
||||
removeByHrefSubstring: {}
|
||||
});
|
||||
const halService = {
|
||||
getEndpoint(linkPath: string): Observable<string> {
|
||||
return observableOf(bitstreamFormatsEndpoint);
|
||||
}
|
||||
} as HALEndpointService;
|
||||
service = initTestService(halService);
|
||||
service.clearBitStreamFormatRequests().subscribe();
|
||||
}));
|
||||
it('should remove the bitstream format hrefs in the request service', () => {
|
||||
expect(requestService.removeByHrefSubstring).toHaveBeenCalledWith(bitstreamFormatsEndpoint);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectBitstreamFormat', () => {
|
||||
beforeEach(async(() => {
|
||||
scheduler = getTestScheduler();
|
||||
requestService = jasmine.createSpyObj('requestService', {
|
||||
configure: {},
|
||||
getByHref: observableOf(responseCacheEntry),
|
||||
getByUUID: cold('a', {a: responseCacheEntry}),
|
||||
generateRequestId: 'request-id',
|
||||
removeByHrefSubstring: {}
|
||||
});
|
||||
service = initTestService(halEndpointService);
|
||||
spyOn(store, 'dispatch');
|
||||
}));
|
||||
it('should add a selected bitstream to the store', () => {
|
||||
const format = new BitstreamFormat();
|
||||
format.uuid = 'uuid';
|
||||
|
||||
service.selectBitstreamFormat(format);
|
||||
expect(store.dispatch).toHaveBeenCalledWith(new BitstreamFormatsRegistrySelectAction(format));
|
||||
});
|
||||
});
|
||||
|
||||
describe('deselectBitstreamFormat', () => {
|
||||
beforeEach(async(() => {
|
||||
scheduler = getTestScheduler();
|
||||
requestService = jasmine.createSpyObj('requestService', {
|
||||
configure: {},
|
||||
getByHref: observableOf(responseCacheEntry),
|
||||
getByUUID: cold('a', {a: responseCacheEntry}),
|
||||
generateRequestId: 'request-id',
|
||||
removeByHrefSubstring: {}
|
||||
});
|
||||
service = initTestService(halEndpointService);
|
||||
spyOn(store, 'dispatch');
|
||||
}));
|
||||
it('should remove a bitstream from the store', () => {
|
||||
const format = new BitstreamFormat();
|
||||
format.uuid = 'uuid';
|
||||
|
||||
service.deselectBitstreamFormat(format);
|
||||
expect(store.dispatch).toHaveBeenCalledWith(new BitstreamFormatsRegistryDeselectAction(format));
|
||||
});
|
||||
});
|
||||
|
||||
describe('deselectAllBitstreamFormats', () => {
|
||||
beforeEach(async(() => {
|
||||
scheduler = getTestScheduler();
|
||||
requestService = jasmine.createSpyObj('requestService', {
|
||||
configure: {},
|
||||
getByHref: observableOf(responseCacheEntry),
|
||||
getByUUID: cold('a', {a: responseCacheEntry}),
|
||||
generateRequestId: 'request-id',
|
||||
removeByHrefSubstring: {}
|
||||
});
|
||||
service = initTestService(halEndpointService);
|
||||
spyOn(store, 'dispatch');
|
||||
|
||||
}));
|
||||
it('should remove all bitstreamFormats from the store', () => {
|
||||
service.deselectAllBitstreamFormats();
|
||||
expect(store.dispatch).toHaveBeenCalledWith(new BitstreamFormatsRegistryDeselectAllAction());
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete', () => {
|
||||
beforeEach(async(() => {
|
||||
scheduler = getTestScheduler();
|
||||
requestService = jasmine.createSpyObj('requestService', {
|
||||
configure: {},
|
||||
getByHref: observableOf(responseCacheEntry),
|
||||
getByUUID: hot('a', {a: responseCacheEntry}),
|
||||
generateRequestId: 'request-id',
|
||||
removeByHrefSubstring: {}
|
||||
});
|
||||
const halService = {
|
||||
getEndpoint(linkPath: string): Observable<string> {
|
||||
return observableOf(bitstreamFormatsEndpoint);
|
||||
}
|
||||
} as HALEndpointService;
|
||||
service = initTestService(halService);
|
||||
}));
|
||||
it('should delete a bitstream format', () => {
|
||||
const format = new BitstreamFormat();
|
||||
format.uuid = 'format-uuid';
|
||||
format.id = 'format-id';
|
||||
|
||||
const expected = cold('(b|)', {b: true});
|
||||
const result = service.delete(format);
|
||||
|
||||
expect(result).toBeObservable(expected);
|
||||
});
|
||||
});
|
||||
});
|
183
src/app/core/data/bitstream-format-data.service.ts
Normal file
183
src/app/core/data/bitstream-format-data.service.ts
Normal file
@@ -0,0 +1,183 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { DataService } from './data.service';
|
||||
import { BitstreamFormat } from '../shared/bitstream-format.model';
|
||||
import { RequestService } from './request.service';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
|
||||
import { createSelector, select, Store } from '@ngrx/store';
|
||||
import { CoreState } from '../core.reducers';
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
|
||||
import { DeleteByIDRequest, FindAllOptions, PostRequest, PutRequest } from './request.models';
|
||||
import { Observable } from 'rxjs';
|
||||
import { find, map, tap } from 'rxjs/operators';
|
||||
import { configureRequest, getResponseFromEntry } from '../shared/operators';
|
||||
import { distinctUntilChanged } from 'rxjs/internal/operators/distinctUntilChanged';
|
||||
import { RestResponse } from '../cache/response.models';
|
||||
import { AppState } from '../../app.reducer';
|
||||
import { BitstreamFormatRegistryState } from '../../+admin/admin-registries/bitstream-formats/bitstream-format.reducers';
|
||||
import {
|
||||
BitstreamFormatsRegistryDeselectAction,
|
||||
BitstreamFormatsRegistryDeselectAllAction,
|
||||
BitstreamFormatsRegistrySelectAction
|
||||
} from '../../+admin/admin-registries/bitstream-formats/bitstream-format.actions';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
import { RequestEntry } from './request.reducer';
|
||||
|
||||
const bitstreamFormatsStateSelector = (state: AppState) => state.bitstreamFormats;
|
||||
const selectedBitstreamFormatSelector = createSelector(bitstreamFormatsStateSelector,
|
||||
(bitstreamFormatRegistryState: BitstreamFormatRegistryState) => bitstreamFormatRegistryState.selectedBitstreamFormats);
|
||||
|
||||
/**
|
||||
* A service responsible for fetching/sending data from/to the REST API on the bitstreamformats endpoint
|
||||
*/
|
||||
@Injectable()
|
||||
export class BitstreamFormatDataService extends DataService<BitstreamFormat> {
|
||||
|
||||
protected linkPath = 'bitstreamformats';
|
||||
protected forceBypassCache = false;
|
||||
|
||||
constructor(
|
||||
protected requestService: RequestService,
|
||||
protected rdbService: RemoteDataBuildService,
|
||||
protected dataBuildService: NormalizedObjectBuildService,
|
||||
protected store: Store<CoreState>,
|
||||
protected objectCache: ObjectCacheService,
|
||||
protected halService: HALEndpointService,
|
||||
protected notificationsService: NotificationsService,
|
||||
protected http: HttpClient,
|
||||
protected comparator: DefaultChangeAnalyzer<BitstreamFormat>) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the endpoint for browsing bitstream formats
|
||||
* @param {FindAllOptions} options
|
||||
* @returns {Observable<string>}
|
||||
*/
|
||||
getBrowseEndpoint(options: FindAllOptions = {}, linkPath?: string): Observable<string> {
|
||||
return this.halService.getEndpoint(this.linkPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the endpoint to update an existing bitstream format
|
||||
* @param formatId
|
||||
*/
|
||||
public getUpdateEndpoint(formatId: string): Observable<string> {
|
||||
return this.getBrowseEndpoint().pipe(
|
||||
map((endpoint: string) => this.getIDHref(endpoint, formatId))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the endpoint to create a new bitstream format
|
||||
*/
|
||||
public getCreateEndpoint(): Observable<string> {
|
||||
return this.getBrowseEndpoint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing bitstreamFormat
|
||||
* @param bitstreamFormat
|
||||
*/
|
||||
updateBitstreamFormat(bitstreamFormat: BitstreamFormat): Observable<RestResponse> {
|
||||
const requestId = this.requestService.generateRequestId();
|
||||
|
||||
this.getUpdateEndpoint(bitstreamFormat.id).pipe(
|
||||
distinctUntilChanged(),
|
||||
map((endpointURL: string) =>
|
||||
new PutRequest(requestId, endpointURL, bitstreamFormat)),
|
||||
configureRequest(this.requestService)).subscribe();
|
||||
|
||||
return this.requestService.getByUUID(requestId).pipe(
|
||||
getResponseFromEntry()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new BitstreamFormat
|
||||
* @param BitstreamFormat
|
||||
*/
|
||||
public createBitstreamFormat(bitstreamFormat: BitstreamFormat): Observable<RestResponse> {
|
||||
const requestId = this.requestService.generateRequestId();
|
||||
|
||||
this.getCreateEndpoint().pipe(
|
||||
map((endpointURL: string) => {
|
||||
return new PostRequest(requestId, endpointURL, bitstreamFormat);
|
||||
}),
|
||||
configureRequest(this.requestService)
|
||||
).subscribe();
|
||||
|
||||
return this.requestService.getByUUID(requestId).pipe(
|
||||
getResponseFromEntry()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache of the list of BitstreamFormats
|
||||
*/
|
||||
public clearBitStreamFormatRequests(): Observable<string> {
|
||||
return this.getBrowseEndpoint().pipe(
|
||||
tap((href: string) => this.requestService.removeByHrefSubstring(href))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the selected BitstreamFormats from the store
|
||||
*/
|
||||
public getSelectedBitstreamFormats(): Observable<BitstreamFormat[]> {
|
||||
return this.store.pipe(select(selectedBitstreamFormatSelector));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a BistreamFormat to the selected BitstreamFormats in the store
|
||||
* @param bitstreamFormat
|
||||
*/
|
||||
public selectBitstreamFormat(bitstreamFormat: BitstreamFormat) {
|
||||
this.store.dispatch(new BitstreamFormatsRegistrySelectAction(bitstreamFormat));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a BistreamFormat from the list of selected BitstreamFormats in the store
|
||||
* @param bitstreamFormat
|
||||
*/
|
||||
public deselectBitstreamFormat(bitstreamFormat: BitstreamFormat) {
|
||||
this.store.dispatch(new BitstreamFormatsRegistryDeselectAction(bitstreamFormat));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all BitstreamFormats from the list of selected BitstreamFormats in the store
|
||||
*/
|
||||
public deselectAllBitstreamFormats() {
|
||||
this.store.dispatch(new BitstreamFormatsRegistryDeselectAllAction());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an existing DSpace Object on the server
|
||||
* @param format The DSpace Object to be removed
|
||||
* Return an observable that emits true when the deletion was successful, false when it failed
|
||||
*/
|
||||
delete(format: BitstreamFormat): Observable<boolean> {
|
||||
const requestId = this.requestService.generateRequestId();
|
||||
|
||||
const hrefObs = this.halService.getEndpoint(this.linkPath).pipe(
|
||||
map((endpoint: string) => this.getIDHref(endpoint, format.id)));
|
||||
|
||||
hrefObs.pipe(
|
||||
find((href: string) => hasValue(href)),
|
||||
map((href: string) => {
|
||||
const request = new DeleteByIDRequest(requestId, href, format.id);
|
||||
this.requestService.configure(request);
|
||||
})
|
||||
).subscribe();
|
||||
|
||||
return this.requestService.getByUUID(requestId).pipe(
|
||||
find((request: RequestEntry) => request.completed),
|
||||
map((request: RequestEntry) => request.response.isSuccessful)
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
export class BitstreamFormat {
|
||||
shortDescription: string;
|
||||
description: string;
|
||||
mimetype: string;
|
||||
supportLevel: number;
|
||||
internal: boolean;
|
||||
extensions: string;
|
||||
}
|
@@ -1,10 +1,10 @@
|
||||
import { autoserialize, autoserializeAs } from 'cerialize';
|
||||
import { PageInfo } from '../shared/page-info.model';
|
||||
import { BitstreamFormat } from '../shared/bitstream-format.model';
|
||||
import { NormalizedBitstreamFormat } from '../cache/models/normalized-bitstream-format.model';
|
||||
|
||||
export class RegistryBitstreamformatsResponse {
|
||||
@autoserializeAs(BitstreamFormat)
|
||||
bitstreamformats: BitstreamFormat[];
|
||||
@autoserializeAs(NormalizedBitstreamFormat)
|
||||
bitstreamformats: NormalizedBitstreamFormat[];
|
||||
|
||||
@autoserialize
|
||||
page: PageInfo;
|
||||
|
@@ -12,7 +12,6 @@ import { PageInfo } from '../shared/page-info.model';
|
||||
import { getMockRequestService } from '../../shared/mocks/mock-request.service';
|
||||
|
||||
import {
|
||||
RegistryBitstreamformatsSuccessResponse,
|
||||
RegistryMetadatafieldsSuccessResponse,
|
||||
RegistryMetadataschemasSuccessResponse,
|
||||
RestResponse
|
||||
@@ -20,7 +19,6 @@ import {
|
||||
import { Component } from '@angular/core';
|
||||
import { RegistryMetadataschemasResponse } from './registry-metadataschemas-response.model';
|
||||
import { RegistryMetadatafieldsResponse } from './registry-metadatafields-response.model';
|
||||
import { RegistryBitstreamformatsResponse } from './registry-bitstreamformats-response.model';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Store, StoreModule } from '@ngrx/store';
|
||||
import { MockStore } from '../../shared/testing/mock-store';
|
||||
@@ -235,35 +233,6 @@ describe('RegistryService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('when requesting bitstreamformats', () => {
|
||||
const queryResponse = Object.assign(new RegistryBitstreamformatsResponse(), {
|
||||
bitstreamformats: mockFieldsList,
|
||||
page: pageInfo
|
||||
});
|
||||
const response = new RegistryBitstreamformatsSuccessResponse(queryResponse, 200, 'OK', pageInfo);
|
||||
const responseEntry = Object.assign(new RequestEntry(), { response: response });
|
||||
|
||||
beforeEach(() => {
|
||||
(registryService as any).requestService.getByHref.and.returnValue(observableOf(responseEntry));
|
||||
/* tslint:disable:no-empty */
|
||||
registryService.getBitstreamFormats(pagination).subscribe((value) => {
|
||||
});
|
||||
/* tslint:enable:no-empty */
|
||||
});
|
||||
|
||||
it('should call getEndpoint on the halService', () => {
|
||||
expect((registryService as any).halService.getEndpoint).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should send out the request on the request service', () => {
|
||||
expect((registryService as any).requestService.configure).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call getByHref on the request service with the correct request url', () => {
|
||||
expect((registryService as any).requestService.getByHref).toHaveBeenCalledWith(endpointWithParams);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when dispatching to the store', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(mockStore, 'dispatch');
|
||||
@@ -276,7 +245,7 @@ describe('RegistryService', () => {
|
||||
|
||||
it('should dispatch a MetadataRegistryEditSchemaAction with the correct schema', () => {
|
||||
expect(mockStore.dispatch).toHaveBeenCalledWith(new MetadataRegistryEditSchemaAction(mockSchemasList[0]));
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when calling cancelEditMetadataSchema', () => {
|
||||
@@ -286,7 +255,7 @@ describe('RegistryService', () => {
|
||||
|
||||
it('should dispatch a MetadataRegistryCancelSchemaAction', () => {
|
||||
expect(mockStore.dispatch).toHaveBeenCalledWith(new MetadataRegistryCancelSchemaAction());
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when calling selectMetadataSchema', () => {
|
||||
@@ -296,7 +265,7 @@ describe('RegistryService', () => {
|
||||
|
||||
it('should dispatch a MetadataRegistrySelectSchemaAction with the correct schema', () => {
|
||||
expect(mockStore.dispatch).toHaveBeenCalledWith(new MetadataRegistrySelectSchemaAction(mockSchemasList[0]));
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when calling deselectMetadataSchema', () => {
|
||||
@@ -306,7 +275,7 @@ describe('RegistryService', () => {
|
||||
|
||||
it('should dispatch a MetadataRegistryDeselectSchemaAction with the correct schema', () => {
|
||||
expect(mockStore.dispatch).toHaveBeenCalledWith(new MetadataRegistryDeselectSchemaAction(mockSchemasList[0]));
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when calling deselectAllMetadataSchema', () => {
|
||||
@@ -316,7 +285,7 @@ describe('RegistryService', () => {
|
||||
|
||||
it('should dispatch a MetadataRegistryDeselectAllSchemaAction', () => {
|
||||
expect(mockStore.dispatch).toHaveBeenCalledWith(new MetadataRegistryDeselectAllSchemaAction());
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when calling editMetadataField', () => {
|
||||
@@ -326,7 +295,7 @@ describe('RegistryService', () => {
|
||||
|
||||
it('should dispatch a MetadataRegistryEditFieldAction with the correct Field', () => {
|
||||
expect(mockStore.dispatch).toHaveBeenCalledWith(new MetadataRegistryEditFieldAction(mockFieldsList[0]));
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when calling cancelEditMetadataField', () => {
|
||||
@@ -336,7 +305,7 @@ describe('RegistryService', () => {
|
||||
|
||||
it('should dispatch a MetadataRegistryCancelFieldAction', () => {
|
||||
expect(mockStore.dispatch).toHaveBeenCalledWith(new MetadataRegistryCancelFieldAction());
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when calling selectMetadataField', () => {
|
||||
@@ -346,7 +315,7 @@ describe('RegistryService', () => {
|
||||
|
||||
it('should dispatch a MetadataRegistrySelectFieldAction with the correct Field', () => {
|
||||
expect(mockStore.dispatch).toHaveBeenCalledWith(new MetadataRegistrySelectFieldAction(mockFieldsList[0]));
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when calling deselectMetadataField', () => {
|
||||
@@ -356,7 +325,7 @@ describe('RegistryService', () => {
|
||||
|
||||
it('should dispatch a MetadataRegistryDeselectFieldAction with the correct Field', () => {
|
||||
expect(mockStore.dispatch).toHaveBeenCalledWith(new MetadataRegistryDeselectFieldAction(mockFieldsList[0]));
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when calling deselectAllMetadataField', () => {
|
||||
@@ -366,7 +335,7 @@ describe('RegistryService', () => {
|
||||
|
||||
it('should dispatch a MetadataRegistryDeselectAllFieldAction', () => {
|
||||
expect(mockStore.dispatch).toHaveBeenCalledWith(new MetadataRegistryDeselectAllFieldAction());
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -409,7 +378,7 @@ describe('RegistryService', () => {
|
||||
result.subscribe((response: RestResponse) => {
|
||||
expect(response.isSuccessful).toBe(true);
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when deleteMetadataField is called', () => {
|
||||
@@ -423,7 +392,7 @@ describe('RegistryService', () => {
|
||||
result.subscribe((response: RestResponse) => {
|
||||
expect(response.isSuccessful).toBe(true);
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('when clearMetadataSchemaRequests is called', () => {
|
||||
|
@@ -5,13 +5,13 @@ import { PaginatedList } from '../data/paginated-list';
|
||||
import { PageInfo } from '../shared/page-info.model';
|
||||
import { MetadataSchema } from '../metadata/metadataschema.model';
|
||||
import { MetadataField } from '../metadata/metadatafield.model';
|
||||
import { BitstreamFormat } from './mock-bitstream-format.model';
|
||||
import {
|
||||
CreateMetadataFieldRequest,
|
||||
CreateMetadataSchemaRequest,
|
||||
DeleteRequest,
|
||||
GetRequest,
|
||||
RestRequest, UpdateMetadataFieldRequest,
|
||||
RestRequest,
|
||||
UpdateMetadataFieldRequest,
|
||||
UpdateMetadataSchemaRequest
|
||||
} from '../data/request.models';
|
||||
import { GenericConstructor } from '../shared/generic-constructor';
|
||||
@@ -21,24 +21,19 @@ import { RemoteDataBuildService } from '../cache/builders/remote-data-build.serv
|
||||
import { RequestService } from '../data/request.service';
|
||||
import { RegistryMetadataschemasResponse } from './registry-metadataschemas-response.model';
|
||||
import {
|
||||
ErrorResponse, MetadatafieldSuccessResponse, MetadataschemaSuccessResponse,
|
||||
RegistryBitstreamformatsSuccessResponse,
|
||||
MetadatafieldSuccessResponse,
|
||||
MetadataschemaSuccessResponse,
|
||||
RegistryMetadatafieldsSuccessResponse,
|
||||
RegistryMetadataschemasSuccessResponse, RestResponse
|
||||
RegistryMetadataschemasSuccessResponse,
|
||||
RestResponse
|
||||
} from '../cache/response.models';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { RegistryMetadatafieldsResponseParsingService } from '../data/registry-metadatafields-response-parsing.service';
|
||||
import { RegistryMetadatafieldsResponse } from './registry-metadatafields-response.model';
|
||||
import { hasValue, hasNoValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util';
|
||||
import { hasNoValue, hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util';
|
||||
import { URLCombiner } from '../url-combiner/url-combiner';
|
||||
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
|
||||
import { RegistryBitstreamformatsResponseParsingService } from '../data/registry-bitstreamformats-response-parsing.service';
|
||||
import { RegistryBitstreamformatsResponse } from './registry-bitstreamformats-response.model';
|
||||
import {
|
||||
configureRequest,
|
||||
getResponseFromEntry,
|
||||
getSucceededRemoteData
|
||||
} from '../shared/operators';
|
||||
import { configureRequest, getResponseFromEntry } from '../shared/operators';
|
||||
import { createSelector, select, Store } from '@ngrx/store';
|
||||
import { AppState } from '../../app.reducer';
|
||||
import { MetadataRegistryState } from '../../+admin/admin-registries/metadata-registry/metadata-registry.reducers';
|
||||
@@ -54,7 +49,7 @@ import {
|
||||
MetadataRegistrySelectFieldAction,
|
||||
MetadataRegistrySelectSchemaAction
|
||||
} from '../../+admin/admin-registries/metadata-registry/metadata-registry.actions';
|
||||
import { distinctUntilChanged, flatMap, map, switchMap, take, tap } from 'rxjs/operators';
|
||||
import { distinctUntilChanged, flatMap, map, take, tap } from 'rxjs/operators';
|
||||
import { DSpaceRESTv2Serializer } from '../dspace-rest-v2/dspace-rest-v2.serializer';
|
||||
import { NormalizedObjectFactory } from '../cache/models/normalized-object-factory';
|
||||
import { ResourceType } from '../shared/resource-type';
|
||||
@@ -76,7 +71,8 @@ export class RegistryService {
|
||||
|
||||
private metadataSchemasPath = 'metadataschemas';
|
||||
private metadataFieldsPath = 'metadatafields';
|
||||
private bitstreamFormatsPath = 'bitstreamformats';
|
||||
|
||||
// private bitstreamFormatsPath = 'bitstreamformats';
|
||||
|
||||
constructor(protected requestService: RequestService,
|
||||
private rdb: RemoteDataBuildService,
|
||||
@@ -215,36 +211,6 @@ export class RegistryService {
|
||||
return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs);
|
||||
}
|
||||
|
||||
public getBitstreamFormats(pagination: PaginationComponentOptions): Observable<RemoteData<PaginatedList<BitstreamFormat>>> {
|
||||
const requestObs = this.getBitstreamFormatsRequestObs(pagination);
|
||||
|
||||
const requestEntryObs = requestObs.pipe(
|
||||
flatMap((request: RestRequest) => this.requestService.getByHref(request.href))
|
||||
);
|
||||
|
||||
const rbrObs: Observable<RegistryBitstreamformatsResponse> = requestEntryObs.pipe(
|
||||
getResponseFromEntry(),
|
||||
map((response: RegistryBitstreamformatsSuccessResponse) => response.bitstreamformatsResponse)
|
||||
);
|
||||
|
||||
const bitstreamformatsObs: Observable<BitstreamFormat[]> = rbrObs.pipe(
|
||||
map((rbr: RegistryBitstreamformatsResponse) => rbr.bitstreamformats)
|
||||
);
|
||||
|
||||
const pageInfoObs: Observable<PageInfo> = requestEntryObs.pipe(
|
||||
getResponseFromEntry(),
|
||||
map((response: RegistryBitstreamformatsSuccessResponse) => response.pageInfo)
|
||||
);
|
||||
|
||||
const payloadObs = observableCombineLatest(bitstreamformatsObs, pageInfoObs).pipe(
|
||||
map(([bitstreamformats, pageInfo]) => {
|
||||
return new PaginatedList(pageInfo, bitstreamformats);
|
||||
})
|
||||
);
|
||||
|
||||
return this.rdb.toRemoteDataObservable(requestEntryObs, payloadObs);
|
||||
}
|
||||
|
||||
public getMetadataSchemasRequestObs(pagination: PaginationComponentOptions): Observable<RestRequest> {
|
||||
return this.halService.getEndpoint(this.metadataSchemasPath).pipe(
|
||||
map((url: string) => {
|
||||
@@ -307,26 +273,6 @@ export class RegistryService {
|
||||
);
|
||||
}
|
||||
|
||||
private getBitstreamFormatsRequestObs(pagination: PaginationComponentOptions): Observable<RestRequest> {
|
||||
return this.halService.getEndpoint(this.bitstreamFormatsPath).pipe(
|
||||
map((url: string) => {
|
||||
const args: string[] = [];
|
||||
args.push(`size=${pagination.pageSize}`);
|
||||
args.push(`page=${pagination.currentPage - 1}`);
|
||||
if (isNotEmpty(args)) {
|
||||
url = new URLCombiner(url, `?${args.join('&')}`).toString();
|
||||
}
|
||||
const request = new GetRequest(this.requestService.generateRequestId(), url);
|
||||
return Object.assign(request, {
|
||||
getResponseParser(): GenericConstructor<ResponseParsingService> {
|
||||
return RegistryBitstreamformatsResponseParsingService;
|
||||
}
|
||||
});
|
||||
}),
|
||||
tap((request: RestRequest) => this.requestService.configure(request)),
|
||||
);
|
||||
}
|
||||
|
||||
public editMetadataSchema(schema: MetadataSchema) {
|
||||
this.store.dispatch(new MetadataRegistryEditSchemaAction(schema));
|
||||
}
|
||||
@@ -340,15 +286,15 @@ export class RegistryService {
|
||||
}
|
||||
|
||||
public selectMetadataSchema(schema: MetadataSchema) {
|
||||
this.store.dispatch(new MetadataRegistrySelectSchemaAction(schema))
|
||||
this.store.dispatch(new MetadataRegistrySelectSchemaAction(schema));
|
||||
}
|
||||
|
||||
public deselectMetadataSchema(schema: MetadataSchema) {
|
||||
this.store.dispatch(new MetadataRegistryDeselectSchemaAction(schema))
|
||||
this.store.dispatch(new MetadataRegistryDeselectSchemaAction(schema));
|
||||
}
|
||||
|
||||
public deselectAllMetadataSchema() {
|
||||
this.store.dispatch(new MetadataRegistryDeselectAllSchemaAction())
|
||||
this.store.dispatch(new MetadataRegistryDeselectAllSchemaAction());
|
||||
}
|
||||
|
||||
public getSelectedMetadataSchemas(): Observable<MetadataSchema[]> {
|
||||
@@ -368,15 +314,15 @@ export class RegistryService {
|
||||
}
|
||||
|
||||
public selectMetadataField(field: MetadataField) {
|
||||
this.store.dispatch(new MetadataRegistrySelectFieldAction(field))
|
||||
this.store.dispatch(new MetadataRegistrySelectFieldAction(field));
|
||||
}
|
||||
|
||||
public deselectMetadataField(field: MetadataField) {
|
||||
this.store.dispatch(new MetadataRegistryDeselectFieldAction(field))
|
||||
this.store.dispatch(new MetadataRegistryDeselectFieldAction(field));
|
||||
}
|
||||
|
||||
public deselectAllMetadataField() {
|
||||
this.store.dispatch(new MetadataRegistryDeselectAllFieldAction())
|
||||
this.store.dispatch(new MetadataRegistryDeselectAllFieldAction());
|
||||
}
|
||||
|
||||
public getSelectedMetadataFields(): Observable<MetadataField[]> {
|
||||
@@ -451,7 +397,7 @@ export class RegistryService {
|
||||
public clearMetadataSchemaRequests(): Observable<string> {
|
||||
return this.halService.getEndpoint(this.metadataSchemasPath).pipe(
|
||||
tap((href: string) => this.requestService.removeByHrefSubstring(href))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -521,7 +467,7 @@ export class RegistryService {
|
||||
public clearMetadataFieldRequests(): Observable<string> {
|
||||
return this.halService.getEndpoint(this.metadataFieldsPath).pipe(
|
||||
tap((href: string) => this.requestService.removeByHrefSubstring(href))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private delete(path: string, id: number): Observable<RestResponse> {
|
||||
@@ -557,9 +503,9 @@ export class RegistryService {
|
||||
);
|
||||
messages.subscribe(([head, content]) => {
|
||||
if (success) {
|
||||
this.notificationsService.success(head, content)
|
||||
this.notificationsService.success(head, content);
|
||||
} else {
|
||||
this.notificationsService.error(head, content)
|
||||
this.notificationsService.error(head, content);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
5
src/app/core/shared/bitstream-format-support-level.ts
Normal file
5
src/app/core/shared/bitstream-format-support-level.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export enum BitstreamFormatSupportLevel {
|
||||
Known = 'KNOWN',
|
||||
Unknown = 'UNKNOWN',
|
||||
Supported = 'SUPPORTED'
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
|
||||
import { CacheableObject } from '../cache/object-cache.reducer';
|
||||
import { ResourceType } from './resource-type';
|
||||
import { BitstreamFormatSupportLevel } from './bitstream-format-support-level';
|
||||
|
||||
/**
|
||||
* Model class for a Bitstream Format
|
||||
@@ -25,7 +25,7 @@ export class BitstreamFormat implements CacheableObject {
|
||||
/**
|
||||
* The level of support the system offers for this Bitstream Format
|
||||
*/
|
||||
supportLevel: number;
|
||||
supportLevel: BitstreamFormatSupportLevel;
|
||||
|
||||
/**
|
||||
* True if the Bitstream Format is used to store system information, rather than the content of items in the system
|
||||
@@ -35,7 +35,7 @@ export class BitstreamFormat implements CacheableObject {
|
||||
/**
|
||||
* String representing this Bitstream Format's file extension
|
||||
*/
|
||||
extensions: string;
|
||||
extensions: string[];
|
||||
|
||||
/**
|
||||
* The link to the rest endpoint where this Bitstream Format can be found
|
||||
@@ -52,4 +52,11 @@ export class BitstreamFormat implements CacheableObject {
|
||||
*/
|
||||
uuid: string;
|
||||
|
||||
/**
|
||||
* Identifier for this Bitstream Format
|
||||
* Note that this ID is unique for bitstream formats,
|
||||
* but might not be unique across different object types
|
||||
*/
|
||||
id: string;
|
||||
|
||||
}
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
<ng-container #componentViewContainer></ng-container>
|
||||
|
||||
<small *ngIf="hasHint" class="text-muted" [innerHTML]="model.hint" [ngClass]="getClass('element', 'hint')"></small>
|
||||
<small *ngIf="hasHint" class="text-muted" [innerHTML]="model.hint | translate" [ngClass]="getClass('element', 'hint')"></small>
|
||||
|
||||
<div *ngIf="showErrorMessages" [ngClass]="[getClass('element', 'errors'), getClass('grid', 'errors')]">
|
||||
<small *ngFor="let message of errorMessages" class="invalid-feedback d-block">{{ message | translate:model.validators }}</small>
|
||||
|
Reference in New Issue
Block a user