mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
Merge branch 'feature/189-Warenausgabe/264-Bearbeiten/main' into feature/189-Warenausgabe/main
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<div class="log-entry mt-40" [class.last]="last" [class.first]="first">
|
||||
<span class="timeline-dot"></span>
|
||||
<app-shelf-history-log-header
|
||||
[infoText]="history | historyDtoToInfoText"
|
||||
[statusText]="history | historyDtoToStatusText"
|
||||
></app-shelf-history-log-header>
|
||||
<app-shelf-history-log-body
|
||||
*ngFor="let changes of history.values"
|
||||
[oldStatus]="changes | getStatusFromHistory: 'old'"
|
||||
[newStatus]="changes | getStatusFromHistory: 'new'"
|
||||
[changedBy]="history.changedBy"
|
||||
[caption]="changes.caption"
|
||||
></app-shelf-history-log-body>
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
@import 'variables';
|
||||
|
||||
$offset: 10px;
|
||||
$line-top-offset: 3px;
|
||||
$dot-size: 16px;
|
||||
$dot-size-lg: 20px;
|
||||
$border-size: 1px;
|
||||
$border-size-cover: 2px;
|
||||
|
||||
.log-entry {
|
||||
position: relative;
|
||||
// calculate offset relative to container offset (22px)
|
||||
padding-left: calc(70px - 22px);
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
height: 130%;
|
||||
width: 1px;
|
||||
top: $line-top-offset;
|
||||
left: $offset;
|
||||
border: $border-size solid $isa-light-blue-platinum;
|
||||
background: $isa-light-blue-platinum;
|
||||
}
|
||||
|
||||
&.last:before {
|
||||
height: 30%;
|
||||
border: $border-size-cover solid #fff;
|
||||
background: #fff;
|
||||
left: calc(#{$offset} - #{$border-size-cover});
|
||||
}
|
||||
|
||||
.timeline-dot {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: $offset;
|
||||
background: #fff;
|
||||
width: 2px;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background: $isa-light-blue-platinum;
|
||||
|
||||
top: $line-top-offset;
|
||||
left: calc((#{$dot-size} - #{$line-top-offset}) / -2);
|
||||
border-radius: 50%;
|
||||
width: $dot-size;
|
||||
height: $dot-size;
|
||||
}
|
||||
}
|
||||
|
||||
&.first {
|
||||
.timeline-dot:before {
|
||||
width: $dot-size-lg;
|
||||
height: $dot-size-lg;
|
||||
background: $isa-neutral-info;
|
||||
left: calc(#{$dot-size} / -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import { DebugElement, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { ShelfHistoryLogComponent } from './history-log.component';
|
||||
import { ShelfHistoryLogHeaderComponent } from './log-header';
|
||||
import { ShelfHistoryLogBodyComponent } from './log-body';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { historiesDtoMock, historyDtoMock } from '../../shared/mockdata';
|
||||
import {
|
||||
HistoryDtoToInfoTextPipe,
|
||||
HistoryDtoToStatusTextPipe,
|
||||
GetStatusFromHistoryPipe,
|
||||
} from '../../pages/shelf-history/pipes';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
|
||||
fdescribe('HistoryLogComponent', () => {
|
||||
let fixture: ComponentFixture<ShelfHistoryLogComponent>;
|
||||
let component: ShelfHistoryLogComponent;
|
||||
let debugElement: DebugElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
ShelfHistoryLogComponent,
|
||||
ShelfHistoryLogHeaderComponent,
|
||||
ShelfHistoryLogBodyComponent,
|
||||
HistoryDtoToInfoTextPipe,
|
||||
HistoryDtoToStatusTextPipe,
|
||||
GetStatusFromHistoryPipe,
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ShelfHistoryLogComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement;
|
||||
|
||||
const historyMockWithMultipleLogEntries: HistoryDTO = historiesDtoMock.find(
|
||||
(history) => history.values && history.values.length > 2
|
||||
);
|
||||
component.history = historyMockWithMultipleLogEntries;
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(component instanceof ShelfHistoryLogComponent).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show a header for all history values (log entries)', () => {
|
||||
const header = debugElement.queryAll(
|
||||
By.css('app-shelf-history-log-header')
|
||||
);
|
||||
|
||||
expect(header.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should show an entry for each history value (log entry)', () => {
|
||||
const historyMockWithMultipleLogEntries: HistoryDTO = historiesDtoMock.find(
|
||||
(history) => history.values && history.values.length > 2
|
||||
);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
const entries = debugElement.queryAll(By.css('app-shelf-history-log-body'));
|
||||
|
||||
expect(entries.length).toBe(
|
||||
historyMockWithMultipleLogEntries.values.length
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-history-log',
|
||||
templateUrl: './history-log.component.html',
|
||||
styleUrls: ['./history-log.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfHistoryLogComponent {
|
||||
@Input() first = false;
|
||||
@Input() last = false;
|
||||
@Input() history: HistoryDTO;
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import {
|
||||
HistoryDtoToInfoTextPipe,
|
||||
HistoryDtoToStatusTextPipe,
|
||||
GetStatusFromHistoryPipe,
|
||||
} from '../../pages/shelf-history/pipes';
|
||||
import { IconModule } from '@libs/ui';
|
||||
import { ShelfHistoryLogComponent } from './history-log.component';
|
||||
import { ShelfHistoryLogHeaderComponent } from './log-header';
|
||||
import { ShelfHistoryLogBodyComponent } from './log-body';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, IconModule],
|
||||
declarations: [
|
||||
ShelfHistoryLogComponent,
|
||||
ShelfHistoryLogHeaderComponent,
|
||||
ShelfHistoryLogBodyComponent,
|
||||
HistoryDtoToInfoTextPipe,
|
||||
HistoryDtoToStatusTextPipe,
|
||||
GetStatusFromHistoryPipe,
|
||||
],
|
||||
exports: [
|
||||
ShelfHistoryLogComponent,
|
||||
ShelfHistoryLogHeaderComponent,
|
||||
ShelfHistoryLogBodyComponent,
|
||||
],
|
||||
providers: [],
|
||||
})
|
||||
export class ShelfHistoryLogModule {}
|
||||
@@ -0,0 +1,5 @@
|
||||
// start:ng42.barrel
|
||||
export * from './history-log.component';
|
||||
export * from './history-log.module';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './log-body.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<div class="container isa-mb-20">
|
||||
<ul class="mt-8">
|
||||
<li class="mb-5">
|
||||
{{ caption }} alt:
|
||||
<span class="isa-font-weight-bold ml-5">{{ oldStatus }}</span>
|
||||
</li>
|
||||
<li class="mb-5">
|
||||
{{ caption }} neu:
|
||||
<span class="isa-font-weight-bold ml-5">{{ newStatus }}</span>
|
||||
</li>
|
||||
<li>
|
||||
Geändert von:
|
||||
<span class="isa-font-weight-bold ml-5">{{ changedBy }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -0,0 +1,15 @@
|
||||
@import 'variables';
|
||||
|
||||
.container {
|
||||
font-family: $font-family;
|
||||
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
li {
|
||||
font-size: 16px;
|
||||
line-height: $font-line-height;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
import { ShelfHistoryLogBodyComponent } from './log-body.component';
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
fdescribe('ShelfHistoryLogBodyComponent', () => {
|
||||
let fixture: ComponentFixture<ShelfHistoryLogBodyComponent>;
|
||||
let component: ShelfHistoryLogBodyComponent;
|
||||
let debugElement: DebugElement;
|
||||
|
||||
let oldStatusElement: HTMLSpanElement;
|
||||
let newStatusElement: HTMLSpanElement;
|
||||
let changedByElement: HTMLSpanElement;
|
||||
|
||||
let captionElementOldStatus: HTMLLIElement;
|
||||
let captionElementNewStatus: HTMLLIElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ShelfHistoryLogBodyComponent],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ShelfHistoryLogBodyComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement;
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(component instanceof ShelfHistoryLogBodyComponent).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('Case: No Inputs provided', () => {
|
||||
beforeEach(() => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should show a dash as old status', () => {
|
||||
oldStatusElement = debugElement
|
||||
.queryAll(By.css('li'))[0]
|
||||
.nativeElement.querySelector('span');
|
||||
|
||||
expect(oldStatusElement.textContent).toBe('-');
|
||||
});
|
||||
it('should show a dash new status', () => {
|
||||
newStatusElement = debugElement
|
||||
.queryAll(By.css('li'))[1]
|
||||
.nativeElement.querySelector('span');
|
||||
|
||||
expect(newStatusElement.textContent).toBe('-');
|
||||
});
|
||||
it('should show a dash as new changedBy', () => {
|
||||
changedByElement = debugElement
|
||||
.queryAll(By.css('li'))[2]
|
||||
.nativeElement.querySelector('span');
|
||||
|
||||
expect(newStatusElement.textContent).toBe('-');
|
||||
});
|
||||
it('should show an empty string as caption for old status', () => {
|
||||
captionElementOldStatus = debugElement.queryAll(By.css('li'))[0]
|
||||
.nativeElement;
|
||||
|
||||
expect(captionElementOldStatus.textContent).toContain('alt:');
|
||||
});
|
||||
it('should show an empty string as caption for new status', () => {
|
||||
captionElementNewStatus = debugElement.queryAll(By.css('li'))[1]
|
||||
.nativeElement;
|
||||
|
||||
expect(captionElementNewStatus.textContent).toContain('neu:');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Case: With Inputs provided', () => {
|
||||
beforeEach(() => {
|
||||
component.oldStatus = 'Mock Old Status';
|
||||
component.newStatus = 'Mock New Status';
|
||||
component.changedBy = 'Mock ChangedBy';
|
||||
component.caption = 'Mock Caption';
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should show old status', () => {
|
||||
oldStatusElement = debugElement
|
||||
.queryAll(By.css('li'))[0]
|
||||
.nativeElement.querySelector('span');
|
||||
|
||||
expect(oldStatusElement.textContent).toBe(component.oldStatus);
|
||||
});
|
||||
it('should show new status', () => {
|
||||
newStatusElement = debugElement
|
||||
.queryAll(By.css('li'))[1]
|
||||
.nativeElement.querySelector('span');
|
||||
|
||||
expect(newStatusElement.textContent).toBe(component.newStatus);
|
||||
});
|
||||
it('should show new changedBy', () => {
|
||||
changedByElement = debugElement
|
||||
.queryAll(By.css('li'))[2]
|
||||
.nativeElement.querySelector('span');
|
||||
|
||||
expect(changedByElement.textContent).toBe(component.changedBy);
|
||||
});
|
||||
it('should show caption for old status', () => {
|
||||
captionElementOldStatus = debugElement.queryAll(By.css('li'))[0]
|
||||
.nativeElement;
|
||||
|
||||
expect(captionElementOldStatus.textContent).toContain(
|
||||
`alt: ${component.oldStatus}`
|
||||
);
|
||||
});
|
||||
it('should show caption for new status', () => {
|
||||
captionElementNewStatus = debugElement.queryAll(By.css('li'))[1]
|
||||
.nativeElement;
|
||||
|
||||
expect(captionElementNewStatus.textContent).toContain(
|
||||
`neu: ${component.newStatus}`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-history-log-body',
|
||||
templateUrl: 'log-body.component.html',
|
||||
styleUrls: ['./log-body.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfHistoryLogBodyComponent {
|
||||
@Input() oldStatus = '-';
|
||||
@Input() newStatus = '-';
|
||||
@Input() changedBy = '-';
|
||||
@Input() caption = '';
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './log-header.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<div class="container mb-20">
|
||||
<div class="d-flex flex-column">
|
||||
<h4 class="info-text isa-font-weight-default">{{ infoText }}</h4>
|
||||
<h2 class="status-text isa-font-weight-bold">{{ statusText }}</h2>
|
||||
</div>
|
||||
|
||||
<div class="notification-type">
|
||||
<lib-icon name="Icon_Abholfach" width="17" height="18"></lib-icon>
|
||||
<span class="ml-10 isa-font-weight-emphasis isa-font-color-customer">{{
|
||||
type
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,36 @@
|
||||
@import 'variables';
|
||||
|
||||
:host {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
|
||||
h2,
|
||||
h4 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.info-text,
|
||||
.status-text {
|
||||
line-height: $font-line-height;
|
||||
font-family: $font-family;
|
||||
}
|
||||
|
||||
.info-text {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: $headline-font-size-xs;
|
||||
}
|
||||
|
||||
.notification-type {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 15px;
|
||||
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { ShelfHistoryLogHeaderComponent } from './log-header.component';
|
||||
import { DebugElement, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
fdescribe('ShelfHistoryLogHeaderComponent', () => {
|
||||
let fixture: ComponentFixture<ShelfHistoryLogHeaderComponent>;
|
||||
let component: ShelfHistoryLogHeaderComponent;
|
||||
let debugElement: DebugElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ShelfHistoryLogHeaderComponent],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ShelfHistoryLogHeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement;
|
||||
|
||||
component.infoText = 'Mock Info Text';
|
||||
component.statusText = 'Mock Status Text';
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(component instanceof ShelfHistoryLogHeaderComponent).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should show info text', () => {
|
||||
const infoTextElement: HTMLHeadingElement = debugElement.query(
|
||||
By.css('.info-text')
|
||||
).nativeElement;
|
||||
|
||||
expect(infoTextElement.textContent).toBe(component.infoText);
|
||||
});
|
||||
|
||||
it('should show status text', () => {
|
||||
const statusTextElement: HTMLHeadingElement = debugElement.query(
|
||||
By.css('.status-text')
|
||||
).nativeElement;
|
||||
|
||||
expect(statusTextElement.textContent).toBe(component.statusText);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
|
||||
import { HistoryNotificationType } from '../../../defs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-history-log-header',
|
||||
templateUrl: 'log-header.component.html',
|
||||
styleUrls: ['./log-header.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfHistoryLogHeaderComponent {
|
||||
@Input() infoText: string;
|
||||
@Input() statusText: string;
|
||||
@Input() type: HistoryNotificationType = 'Abholfach';
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export type HistoryNotificationType = 'Abholfach' | 'Benachrichtigung';
|
||||
@@ -1,4 +1,6 @@
|
||||
// start:ng42.barrel
|
||||
export * from './autocomplete-options.model';
|
||||
export * from './history-notification.type';
|
||||
export * from './shelf-primary-filter-options';
|
||||
export * from './shelf-history-log-details.model';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
export interface ShelfHistoryLogDetails {
|
||||
caption?: string;
|
||||
|
||||
property?: string;
|
||||
|
||||
value?: string;
|
||||
|
||||
previousValue?: string;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<div class="header-container">
|
||||
<h2 class="headline isa-text-center isa-font-weight-bold">Historie</h2>
|
||||
<div class="content">
|
||||
<ng-template
|
||||
[ngTemplateOutlet]="headerTemplate || defaultHeaderTemplate"
|
||||
[ngTemplateOutletContext]="{ $implicit: orderItemSubsetId }"
|
||||
></ng-template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template let-orderItemSubsetId #defaultHeaderTemplate>
|
||||
<p class="default-template">
|
||||
Es liegen keine Detailinformation zum Produkt (Bestell-Id:
|
||||
<span>{{ orderItemSubsetId }}</span
|
||||
>) vor.
|
||||
</p>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,18 @@
|
||||
@import 'variables';
|
||||
|
||||
.header-container {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.headline {
|
||||
font-size: $headline-font-size-m;
|
||||
// Calculate margin to fulfill 20px margin offset to top
|
||||
margin-top: calc(20px - 37px);
|
||||
}
|
||||
}
|
||||
|
||||
.default-template {
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { HistoryStateFacade } from '@shelf-store/history';
|
||||
import { ShelfHistoryHeaderComponent } from './history-header.component';
|
||||
|
||||
fdescribe('ShelfHistoryHeaderComponent', () => {
|
||||
let fixture: ComponentFixture<ShelfHistoryHeaderComponent>;
|
||||
let component: ShelfHistoryHeaderComponent;
|
||||
let facade: HistoryStateFacade;
|
||||
|
||||
const id = 123;
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ShelfHistoryHeaderComponent],
|
||||
providers: [
|
||||
{
|
||||
provide: HistoryStateFacade,
|
||||
useValue: jasmine.createSpyObj('historyStateFacade', {
|
||||
reloadHistory: () => {},
|
||||
}),
|
||||
},
|
||||
],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ShelfHistoryHeaderComponent);
|
||||
component = fixture.componentInstance;
|
||||
facade = TestBed.get(HistoryStateFacade);
|
||||
|
||||
component.orderItemSubsetId = id;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(component instanceof ShelfHistoryHeaderComponent).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('updateHistory', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(component, 'updateHistory').and.callThrough();
|
||||
});
|
||||
|
||||
it('should call reloadHistory on the state facade', () => {
|
||||
component.updateHistory();
|
||||
|
||||
expect(facade.reloadHistory).toHaveBeenCalledWith(id);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
import {
|
||||
Component,
|
||||
ChangeDetectionStrategy,
|
||||
Input,
|
||||
TemplateRef,
|
||||
} from '@angular/core';
|
||||
import { HistoryStateFacade } from '@shelf-store/history';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-history-header',
|
||||
templateUrl: 'history-header.component.html',
|
||||
styleUrls: ['./history-header.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfHistoryHeaderComponent {
|
||||
@Input() orderItemSubsetId: number;
|
||||
@Input() headerTemplate: TemplateRef<any>;
|
||||
|
||||
constructor(private historyStateFacade: HistoryStateFacade) {}
|
||||
|
||||
updateHistory() {
|
||||
this.historyStateFacade.reloadHistory(this.orderItemSubsetId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './history-header.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './shelf-history-logs.component';
|
||||
// end:ng42.barrel
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<div class="layout-container">
|
||||
<div class="layout-content">
|
||||
<app-shelf-history-header
|
||||
[orderItemSubsetId]="orderItemSubsetId"
|
||||
></app-shelf-history-header>
|
||||
|
||||
<hr class="isa-content-spacer" />
|
||||
|
||||
<app-shelf-history-log
|
||||
*ngFor="
|
||||
let history of history$ | async;
|
||||
let first = first;
|
||||
let last = last
|
||||
"
|
||||
[history]="history"
|
||||
[first]="first"
|
||||
[last]="last"
|
||||
></app-shelf-history-log>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,56 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { HistoryStateFacade } from '@shelf-store/history';
|
||||
import { ShelfHistoryLogsComponent } from './shelf-history-logs.component';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ShelfHistoryLogModule } from '../../../components/history-log';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FilterHistoriesWithStatusChangePipe } from '../pipes';
|
||||
|
||||
fdescribe('ShelfHistoryLogComponent', () => {
|
||||
let fixture: ComponentFixture<ShelfHistoryLogsComponent>;
|
||||
let component: ShelfHistoryLogsComponent;
|
||||
let facade: jasmine.SpyObj<HistoryStateFacade>;
|
||||
|
||||
const id = 123;
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CommonModule, ShelfHistoryLogModule],
|
||||
declarations: [
|
||||
ShelfHistoryLogsComponent,
|
||||
FilterHistoriesWithStatusChangePipe,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: HistoryStateFacade,
|
||||
useValue: jasmine.createSpyObj('historyStateFacade', {
|
||||
getHistory$: () => {},
|
||||
}),
|
||||
},
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA],
|
||||
})
|
||||
.overrideTemplate(ShelfHistoryLogsComponent, '<div></div>')
|
||||
.compileComponents();
|
||||
|
||||
facade = TestBed.get(HistoryStateFacade);
|
||||
fixture = TestBed.createComponent(ShelfHistoryLogsComponent);
|
||||
component = fixture.componentInstance;
|
||||
|
||||
component.orderItemSubsetId = id;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(component instanceof ShelfHistoryLogsComponent).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('getHistory', () => {
|
||||
it('should call the facade to get the histories', () => {
|
||||
spyOn(component, 'getHistory$').and.callThrough();
|
||||
component.getHistory$();
|
||||
|
||||
expect(facade.getHistory$).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
ChangeDetectionStrategy,
|
||||
Input,
|
||||
} from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
import { HistoryStateFacade } from '@shelf-store/history';
|
||||
|
||||
@Component({
|
||||
selector: 'app-shelf-history-logs',
|
||||
templateUrl: 'shelf-history-logs.component.html',
|
||||
styleUrls: ['./shelf-history-logs.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfHistoryLogsComponent implements OnInit {
|
||||
@Input() orderItemSubsetId: number;
|
||||
history$: Observable<HistoryDTO[]>;
|
||||
|
||||
constructor(private historyStateFacade: HistoryStateFacade) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.history$ = this.getHistory$();
|
||||
}
|
||||
|
||||
getHistory$(): Observable<HistoryDTO[]> {
|
||||
return this.historyStateFacade.getHistory$(this.orderItemSubsetId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { historyDtoMock } from '../../../shared/mockdata';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
import { historyDtoToInfoText } from './history-dto-to-info-text.mapping';
|
||||
|
||||
fdescribe('Mapping: historyDtoToInfoText', () => {
|
||||
const historyMock: HistoryDTO = historyDtoMock;
|
||||
|
||||
it('should return a string containing the date, time and location', () => {
|
||||
const result = historyDtoToInfoText(historyMock);
|
||||
const expected = `02.07.2020 | 10:56 Uhr | München Neuhausen`;
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should only return a string containing date and tiem if no location is present', () => {
|
||||
const { location, ...historyMockWithoutLocation } = historyMock;
|
||||
|
||||
const result = historyDtoToInfoText(historyMockWithoutLocation);
|
||||
const expected = `02.07.2020 | 10:56 Uhr`;
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
|
||||
export function historyDtoToInfoText(history: HistoryDTO): string {
|
||||
const baseDate = new Date(history.changed);
|
||||
const format: Intl.DateTimeFormatOptions = {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
year: 'numeric',
|
||||
};
|
||||
|
||||
const date = baseDate.toLocaleDateString('de', format);
|
||||
const time = `${baseDate.getHours()}:${('0' + baseDate.getMinutes()).slice(
|
||||
-2
|
||||
)} Uhr`;
|
||||
const location = history.location;
|
||||
|
||||
return `${date} | ${time}${location ? ' | ' + location : ''}`;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { historyDtoToStatusText } from './history-dto-to-status-text.mapping';
|
||||
import { historyDtoMock } from '../../../shared/mockdata';
|
||||
|
||||
fdescribe('Mapping: historyDtoToStatusText', () => {
|
||||
it('should return the description as status text', () => {
|
||||
const details = historyDtoMock;
|
||||
|
||||
const result = historyDtoToStatusText(details);
|
||||
const expected = 'Test Description';
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should return a default status if no description is set', () => {
|
||||
const { description, ...details } = historyDtoMock;
|
||||
|
||||
const result = historyDtoToStatusText(details);
|
||||
const expected = 'Status der Bestellung wurde geändert';
|
||||
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
|
||||
export function historyDtoToStatusText(history: HistoryDTO): string {
|
||||
return history.description || 'Status der Bestellung wurde geändert';
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// start:ng42.barrel
|
||||
export * from './history-dto-to-status-text.mapping';
|
||||
export * from './history-dto-to-info-text.mapping';
|
||||
// end:ng42.barrel
|
||||
@@ -0,0 +1,86 @@
|
||||
import { historiesDtoMock } from '../../../shared/mockdata';
|
||||
import { FilterHistoriesWithStatusChangePipe } from './filter-histories-with-status-change.pipe';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
|
||||
fdescribe('Pipe: HistoryDtoToInfoTextPipe', () => {
|
||||
let pipe: FilterHistoriesWithStatusChangePipe;
|
||||
|
||||
const mockHistories: HistoryDTO[] = historiesDtoMock;
|
||||
|
||||
beforeEach(() => {
|
||||
pipe = new FilterHistoriesWithStatusChangePipe();
|
||||
});
|
||||
|
||||
it('should only return histories with a status change', () => {
|
||||
const result = pipe.transform(mockHistories);
|
||||
|
||||
expect(result.length).toBe(2);
|
||||
expect(result).toEqual([
|
||||
{
|
||||
location: 'München Neuhausen',
|
||||
id: 114392259,
|
||||
version: 2,
|
||||
changed: '2020-02-24T14:53:58.9359',
|
||||
changedBy: 'Lorenz Hilpert',
|
||||
changeset: 68359312,
|
||||
historyset: 10896418,
|
||||
values: [
|
||||
{
|
||||
caption: 'Eingetroffen/Versendet',
|
||||
value: '',
|
||||
previousValue: '02.07.2020 10:55:23',
|
||||
},
|
||||
{
|
||||
caption: 'Status',
|
||||
value: 'bestellt',
|
||||
previousValue: 'eingetroffen',
|
||||
},
|
||||
{
|
||||
caption: 'Status Datum',
|
||||
value: '24.02.2020 14:53:58',
|
||||
previousValue: '02.07.2020 10:55:23',
|
||||
},
|
||||
{ caption: 'Abholfach-Nr', value: '', previousValue: '130_0207_1' },
|
||||
{
|
||||
caption: 'Im Abholfach seit',
|
||||
value: '',
|
||||
previousValue: '02.07.2020 10:55:23',
|
||||
},
|
||||
{
|
||||
caption: 'Im Abholfach bis',
|
||||
value: '',
|
||||
previousValue: '16.07.2020 10:55:23',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
location: 'München Neuhausen',
|
||||
id: 114392259,
|
||||
version: 1,
|
||||
changed: '2020-02-24T14:53:57.6544',
|
||||
changedBy: 'Lorenz Hilpert',
|
||||
changeset: 68359310,
|
||||
historyset: 9520697,
|
||||
values: [
|
||||
{ caption: 'Meldenummer', value: '', previousValue: '999' },
|
||||
{
|
||||
caption: 'bestellt bei Lieferant am',
|
||||
value: '',
|
||||
previousValue: '24.02.2020 14:53:58',
|
||||
},
|
||||
{
|
||||
caption: 'vsl. Lieferdatum',
|
||||
value: '25.02.2020 15:00:00',
|
||||
previousValue: '25.02.2020 14:00:00',
|
||||
},
|
||||
{ caption: 'Status', value: 'neu', previousValue: 'bestellt' },
|
||||
{
|
||||
caption: 'Status Datum',
|
||||
value: '24.02.2020 14:53:57',
|
||||
previousValue: '24.02.2020 14:53:58',
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
|
||||
@Pipe({
|
||||
name: 'filterHistoriesWithStatusChange',
|
||||
})
|
||||
export class FilterHistoriesWithStatusChangePipe implements PipeTransform {
|
||||
transform(histories: HistoryDTO[]): HistoryDTO[] {
|
||||
return histories.filter(
|
||||
(history) =>
|
||||
history.values &&
|
||||
history.values.some((value) => value.caption === 'Status')
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { GetStatusFromHistoryPipe } from './get-status-from-history.pipe';
|
||||
import { historyDtoMock, historiesDtoMock } from '../../../shared/mockdata';
|
||||
import { ShelfHistoryLogDetails } from '../../../defs';
|
||||
|
||||
fdescribe('Pipe: GetNewStatusFromHistoryPipe', () => {
|
||||
let pipe: GetStatusFromHistoryPipe;
|
||||
|
||||
beforeEach(() => {
|
||||
pipe = new GetStatusFromHistoryPipe();
|
||||
});
|
||||
|
||||
it('should return the new status value', () => {
|
||||
const historyWithState: ShelfHistoryLogDetails = historiesDtoMock
|
||||
.find((h) => h.values.find((v) => v.caption === 'Status'))
|
||||
.values.find((value) => value && value.caption === 'Status');
|
||||
|
||||
const result = pipe.transform(historyWithState);
|
||||
const expected = 'bestellt';
|
||||
|
||||
expect(result).toBe(expected);
|
||||
|
||||
const historiesWithOtherChanges = historiesDtoMock
|
||||
.find((h) => h.values.find((v) => v.caption === 'vorgemerkt'))
|
||||
.values.find((value) => value && value.caption === 'vorgemerkt');
|
||||
|
||||
const result2 = pipe.transform(historiesWithOtherChanges, 'new');
|
||||
const expected2 = 'ja';
|
||||
|
||||
expect(result2).toBe(expected2);
|
||||
});
|
||||
|
||||
it('should return the old status value', () => {
|
||||
const historyWithState: ShelfHistoryLogDetails = historiesDtoMock
|
||||
.find((h) => h.values.find((v) => v.caption === 'Status'))
|
||||
.values.find((value) => value && value.caption === 'Status');
|
||||
|
||||
const result = pipe.transform(historyWithState, 'old');
|
||||
const expected = 'eingetroffen';
|
||||
|
||||
expect(result).toBe(expected);
|
||||
});
|
||||
|
||||
it('should return a default value if the status string is empty', () => {
|
||||
const historyWithEmptyState: ShelfHistoryLogDetails = historiesDtoMock
|
||||
.find((h) => h.values.find((v) => v.value === ''))
|
||||
.values.find((value) => value && value.value === '');
|
||||
|
||||
const result = pipe.transform(historyWithEmptyState, 'new');
|
||||
expect(result).toBe('-');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { ShelfHistoryLogDetails } from '../../../defs';
|
||||
|
||||
@Pipe({
|
||||
name: 'getStatusFromHistory',
|
||||
})
|
||||
export class GetStatusFromHistoryPipe implements PipeTransform {
|
||||
transform(
|
||||
details: ShelfHistoryLogDetails,
|
||||
statusType: 'new' | 'old' = 'new'
|
||||
): string {
|
||||
const defaultValue = '-';
|
||||
return statusType === 'old'
|
||||
? details.previousValue || defaultValue
|
||||
: details.value || defaultValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { HistoryDtoToStatusTextPipe } from './historyDtoToStatusText.pipe';
|
||||
import * as mapping from '../mappings';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
import { historyDtoMock } from '../../../shared/mockdata';
|
||||
|
||||
fdescribe('Pipe: HistoryDtoToStatusTextPipe', () => {
|
||||
let pipe: HistoryDtoToStatusTextPipe;
|
||||
|
||||
const mockHistory: HistoryDTO = historyDtoMock;
|
||||
const fakeReturnValue = 'mapped result';
|
||||
const historyDtoToStatusTextSpy: jasmine.Spy = jasmine.createSpy(
|
||||
'historyDtoToStatusTextSpy'
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
pipe = new HistoryDtoToStatusTextPipe();
|
||||
spyOnProperty(mapping, 'historyDtoToStatusText').and.returnValue(
|
||||
historyDtoToStatusTextSpy
|
||||
);
|
||||
historyDtoToStatusTextSpy.and.returnValue(fakeReturnValue);
|
||||
});
|
||||
|
||||
it('should call historyDtoToStatusText and return its value', () => {
|
||||
const result = pipe.transform(mockHistory);
|
||||
|
||||
expect(mapping.historyDtoToStatusText).toHaveBeenCalledWith(mockHistory);
|
||||
expect(result).toEqual(fakeReturnValue);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
import { historyDtoToStatusText } from '../mappings';
|
||||
|
||||
@Pipe({
|
||||
name: 'historyDtoToStatusText',
|
||||
})
|
||||
export class HistoryDtoToStatusTextPipe implements PipeTransform {
|
||||
transform(history: HistoryDTO): string {
|
||||
return historyDtoToStatusText(history);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import * as mappings from '../mappings';
|
||||
import { HistoryDtoToInfoTextPipe } from './historyDtoToinfoText.pipe';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
import { historyDtoMock } from '../../../shared/mockdata';
|
||||
|
||||
fdescribe('Pipe: HistoryDtoToInfoTextPipe', () => {
|
||||
let pipe: HistoryDtoToInfoTextPipe;
|
||||
|
||||
const mockHistory: HistoryDTO = historyDtoMock;
|
||||
const fakeReturnValue = 'mapped result';
|
||||
const historyDtoToInfoTextSpy: jasmine.Spy = jasmine.createSpy(
|
||||
'historyDtoToInfoTextSpy'
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
pipe = new HistoryDtoToInfoTextPipe();
|
||||
spyOnProperty(mappings, 'historyDtoToInfoText', 'get').and.returnValue(
|
||||
historyDtoToInfoTextSpy
|
||||
);
|
||||
historyDtoToInfoTextSpy.and.returnValue(fakeReturnValue);
|
||||
});
|
||||
|
||||
it('should call historyDtoToInfoText and return its mapped value', () => {
|
||||
const result = pipe.transform(mockHistory);
|
||||
|
||||
expect(mappings.historyDtoToInfoText).toHaveBeenCalledWith(mockHistory);
|
||||
expect(result).toEqual(fakeReturnValue);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
import { historyDtoToInfoText } from '../mappings';
|
||||
|
||||
@Pipe({
|
||||
name: 'historyDtoToInfoText',
|
||||
})
|
||||
export class HistoryDtoToInfoTextPipe implements PipeTransform {
|
||||
transform(history: HistoryDTO): string {
|
||||
return historyDtoToInfoText(history);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// start:ng42.barrel
|
||||
export * from './historyDtoToinfoText.pipe';
|
||||
export * from './historyDtoToStatusText.pipe';
|
||||
export * from './filter-histories-with-status-change.pipe';
|
||||
export * from './get-status-from-history.pipe';
|
||||
// end:ng42.barrel
|
||||
@@ -1,2 +1,8 @@
|
||||
<pre>{{ history$ | async | json }}</pre>
|
||||
<pre>{{ status$ | async | json }}</pre>
|
||||
<app-shelf-history-logs
|
||||
*ngIf="(status$ | async) === 2; else loading"
|
||||
[orderItemSubsetId]="orderItemSubsetId$ | async"
|
||||
></app-shelf-history-logs>
|
||||
|
||||
<ng-template #loading>
|
||||
<div class="spinner"></div>
|
||||
</ng-template>
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Observable, BehaviorSubject } from 'rxjs';
|
||||
import { filter, map, switchMap } from 'rxjs/operators';
|
||||
import { Observable } from 'rxjs';
|
||||
import {
|
||||
filter,
|
||||
map,
|
||||
switchMap,
|
||||
distinctUntilChanged,
|
||||
tap,
|
||||
shareReplay,
|
||||
} from 'rxjs/operators';
|
||||
import { isNullOrUndefined } from 'util';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
import { HistoryStateFacade } from '@shelf-store/history';
|
||||
@@ -14,8 +21,8 @@ import { OrderHistoryStatus } from '@shelf-store/defs';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ShelfHistoryComponent implements OnInit {
|
||||
history$: Observable<HistoryDTO>;
|
||||
status$: Observable<OrderHistoryStatus>;
|
||||
orderItemSubsetId$: Observable<number>;
|
||||
|
||||
constructor(
|
||||
private activatedRoute: ActivatedRoute,
|
||||
@@ -23,30 +30,29 @@ export class ShelfHistoryComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.history$ = this.getHistory();
|
||||
this.status$ = this.getStatus();
|
||||
this.orderItemSubsetId$ = this.getOrderItemSubsetId$();
|
||||
}
|
||||
|
||||
getHistory() {
|
||||
return this.getOrderItemId$().pipe(
|
||||
switchMap((orderItemId) =>
|
||||
this.historyStateFacade.getHistory$(orderItemId)
|
||||
)
|
||||
);
|
||||
}
|
||||
fetchHistory = (orderItemSubsetId: number) => {
|
||||
this.historyStateFacade.fetchHistory(orderItemSubsetId);
|
||||
};
|
||||
|
||||
getStatus() {
|
||||
return this.getOrderItemId$().pipe(
|
||||
switchMap((orderItemId) =>
|
||||
this.historyStateFacade.getStatus$(orderItemId)
|
||||
return this.getOrderItemSubsetId$().pipe(
|
||||
switchMap((orderItemSubsetId) =>
|
||||
this.historyStateFacade.getStatus$(orderItemSubsetId)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private getOrderItemId$(): Observable<number> {
|
||||
getOrderItemSubsetId$(): Observable<number> {
|
||||
return this.activatedRoute.params.pipe(
|
||||
filter((params) => !isNullOrUndefined(params)),
|
||||
map((params) => Number(params.orderItemId))
|
||||
map((params) => Number(params.orderItemSubsetId)),
|
||||
distinctUntilChanged(),
|
||||
tap(this.fetchHistory),
|
||||
shareReplay()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,25 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ShelfHistoryLogModule } from '../../components/history-log';
|
||||
import { ShelfHistoryComponent } from './shelf-history.component';
|
||||
import { ShelfHistoryLogsComponent } from './history-logs';
|
||||
import { FilterHistoriesWithStatusChangePipe } from './pipes';
|
||||
import { ShelfHistoryHeaderComponent } from './header';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
exports: [ShelfHistoryComponent],
|
||||
declarations: [ShelfHistoryComponent],
|
||||
imports: [CommonModule, ShelfHistoryLogModule],
|
||||
exports: [
|
||||
ShelfHistoryComponent,
|
||||
ShelfHistoryHeaderComponent,
|
||||
ShelfHistoryLogsComponent,
|
||||
FilterHistoriesWithStatusChangePipe,
|
||||
],
|
||||
declarations: [
|
||||
ShelfHistoryComponent,
|
||||
ShelfHistoryHeaderComponent,
|
||||
ShelfHistoryLogsComponent,
|
||||
FilterHistoriesWithStatusChangePipe,
|
||||
],
|
||||
providers: [],
|
||||
})
|
||||
export class ShelfHistoryModule {}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
|
||||
export const historyDtoMock: HistoryDTO = {
|
||||
location: 'München Neuhausen',
|
||||
id: 114392259,
|
||||
version: 5,
|
||||
changed: '2020-07-02T10:56:54.7541',
|
||||
changedBy: 'Günther Schmidlehner',
|
||||
changeset: 69134345,
|
||||
description: 'Test Description',
|
||||
values: [{ caption: 'vorgemerkt', value: 'ja', previousValue: 'nein' }],
|
||||
};
|
||||
|
||||
export const historiesDtoMock: HistoryDTO[] = [
|
||||
{
|
||||
location: 'München Neuhausen',
|
||||
id: 114392259,
|
||||
version: 5,
|
||||
changed: '2020-07-02T10:56:54.7541',
|
||||
changedBy: 'Günther Schmidlehner',
|
||||
changeset: 69134345,
|
||||
values: [{ caption: 'vorgemerkt', value: 'ja', previousValue: 'nein' }],
|
||||
},
|
||||
{
|
||||
location: 'München Neuhausen',
|
||||
id: 114392259,
|
||||
version: 3,
|
||||
changed: '2020-07-02T10:55:23.5543',
|
||||
changedBy: 'Günther Schmidlehner',
|
||||
changeset: 69134341,
|
||||
historyset: 10896420,
|
||||
values: [
|
||||
{ caption: 'Abholfach-Zusatz', value: '', previousValue: 'Extra' },
|
||||
],
|
||||
},
|
||||
{
|
||||
location: 'München Neuhausen',
|
||||
id: 114392259,
|
||||
version: 2,
|
||||
changed: '2020-02-24T14:53:58.9359',
|
||||
changedBy: 'Lorenz Hilpert',
|
||||
changeset: 68359312,
|
||||
historyset: 10896418,
|
||||
values: [
|
||||
{
|
||||
caption: 'Eingetroffen/Versendet',
|
||||
value: '',
|
||||
previousValue: '02.07.2020 10:55:23',
|
||||
},
|
||||
{ caption: 'Status', value: 'bestellt', previousValue: 'eingetroffen' },
|
||||
{
|
||||
caption: 'Status Datum',
|
||||
value: '24.02.2020 14:53:58',
|
||||
previousValue: '02.07.2020 10:55:23',
|
||||
},
|
||||
{ caption: 'Abholfach-Nr', value: '', previousValue: '130_0207_1' },
|
||||
{
|
||||
caption: 'Im Abholfach seit',
|
||||
value: '',
|
||||
previousValue: '02.07.2020 10:55:23',
|
||||
},
|
||||
{
|
||||
caption: 'Im Abholfach bis',
|
||||
value: '',
|
||||
previousValue: '16.07.2020 10:55:23',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
location: 'München Neuhausen',
|
||||
id: 114392259,
|
||||
version: 1,
|
||||
changed: '2020-02-24T14:53:57.6544',
|
||||
changedBy: 'Lorenz Hilpert',
|
||||
changeset: 68359310,
|
||||
historyset: 9520697,
|
||||
values: [
|
||||
{ caption: 'Meldenummer', value: '', previousValue: '999' },
|
||||
{
|
||||
caption: 'bestellt bei Lieferant am',
|
||||
value: '',
|
||||
previousValue: '24.02.2020 14:53:58',
|
||||
},
|
||||
{
|
||||
caption: 'vsl. Lieferdatum',
|
||||
value: '25.02.2020 15:00:00',
|
||||
previousValue: '25.02.2020 14:00:00',
|
||||
},
|
||||
{ caption: 'Status', value: 'neu', previousValue: 'bestellt' },
|
||||
{
|
||||
caption: 'Status Datum',
|
||||
value: '24.02.2020 14:53:57',
|
||||
previousValue: '24.02.2020 14:53:58',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -1,4 +1,5 @@
|
||||
// start:ng42.barrel
|
||||
export * from './historyDto.mock';
|
||||
export * from './filters.mock';
|
||||
export * from './primary-filters.mock';
|
||||
export * from './select-filter-option.mock';
|
||||
|
||||
@@ -34,7 +34,7 @@ export class ShelfNavigationService {
|
||||
}
|
||||
|
||||
navigateToHistory(orderitem: OrderItemListItemDTO) {
|
||||
this.navigateToRoute(`/shelf/history/${orderitem.orderItemId}`, 'Historie');
|
||||
this.navigateToRoute(`shelf/history/${orderitem.orderItemSubsetId}`, `Historie ${orderitem.orderItemSubsetId}`);
|
||||
}
|
||||
|
||||
private replaceRoute(route: string, breadcrumbName: string) {
|
||||
|
||||
@@ -29,7 +29,7 @@ export const routes: Routes = [
|
||||
component: ShelfEditOrderComponent,
|
||||
},
|
||||
{
|
||||
path: 'history/:orderItemId',
|
||||
path: 'history/:orderItemSubsetId',
|
||||
component: ShelfHistoryComponent,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
import { OrderHistoryStatus } from './order-history-status';
|
||||
|
||||
export interface OrderHistory extends HistoryDTO {
|
||||
export interface OrderHistory {
|
||||
id: number;
|
||||
status: OrderHistoryStatus;
|
||||
histories: HistoryDTO[];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { OrderHistory, OrderHistoryStatus } from '../defs';
|
||||
import { props, createAction } from '@ngrx/store';
|
||||
import { StrictHttpResponse, ResponseArgsOfHistoryDTO } from '@swagger/oms';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
|
||||
const prefix = '[CUSTOMER] [SHELF] [HISTORY]';
|
||||
|
||||
@@ -11,7 +12,7 @@ export const initOrderHistory = createAction(
|
||||
|
||||
export const addOrderHistory = createAction(
|
||||
`${prefix} Add Order History`,
|
||||
props<{ id: number; history: OrderHistory }>()
|
||||
props<{ id: number; histories: HistoryDTO[] }>()
|
||||
);
|
||||
|
||||
export const setStatus = createAction(
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { provideMockActions } from '@ngrx/effects/testing';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import {
|
||||
OrderService,
|
||||
ResponseArgsOfHistoryDTO,
|
||||
StrictHttpResponse,
|
||||
} from '@swagger/oms';
|
||||
import { hot, cold } from 'jasmine-marbles';
|
||||
import * as actions from './history.actions';
|
||||
import { HistoryEffects } from './history.effects';
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { TypedAction } from '@ngrx/store/src/models';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
|
||||
fdescribe('HistoryEffects', () => {
|
||||
let historyEffects: HistoryEffects;
|
||||
let actions$: Observable<any>;
|
||||
let orderService: jasmine.SpyObj<OrderService>;
|
||||
|
||||
const id = 123;
|
||||
const httpResponse: StrictHttpResponse<ResponseArgsOfHistoryDTO> = {
|
||||
body: ({
|
||||
result: [
|
||||
{
|
||||
id: 456,
|
||||
name: 'HistoryDTO Name',
|
||||
values: [],
|
||||
},
|
||||
],
|
||||
error: false,
|
||||
} as unknown) as ResponseArgsOfHistoryDTO,
|
||||
ok: true,
|
||||
type: null,
|
||||
clone: null,
|
||||
headers: new HttpHeaders(),
|
||||
status: 200,
|
||||
statusText: 'Okay',
|
||||
url: 'someRandomUrl.de',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
HistoryEffects,
|
||||
provideMockStore({}),
|
||||
{
|
||||
provide: OrderService,
|
||||
useValue: jasmine.createSpyObj('orderService', [
|
||||
'OrderGetOrderItemStatusHistoryResponse',
|
||||
]),
|
||||
},
|
||||
provideMockActions(() => actions$),
|
||||
],
|
||||
});
|
||||
|
||||
historyEffects = TestBed.get(HistoryEffects);
|
||||
orderService = TestBed.get(OrderService);
|
||||
});
|
||||
|
||||
describe('initHistory$', () => {
|
||||
it('should dispatch fetchHistory', () => {
|
||||
const initHistoryAction = actions.initOrderHistory({ id });
|
||||
|
||||
const initHistory$ = hot('-a', { a: initHistoryAction });
|
||||
actions$ = initHistory$;
|
||||
|
||||
const fetchHistory$ = actions.fetchHistory({ id });
|
||||
const expected$ = cold('-b', { b: fetchHistory$ });
|
||||
|
||||
expect(historyEffects.initHistory$).toBeObservable(expected$);
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchHistory$', () => {
|
||||
let fetchHistoryAction: {
|
||||
id: number;
|
||||
} & TypedAction<string>;
|
||||
let fetchHistoryDoneAction: {
|
||||
id: number;
|
||||
response: StrictHttpResponse<ResponseArgsOfHistoryDTO>;
|
||||
} & TypedAction<any>;
|
||||
|
||||
beforeEach(() => {
|
||||
orderService.OrderGetOrderItemStatusHistoryResponse.and.returnValue(
|
||||
of(httpResponse)
|
||||
);
|
||||
|
||||
fetchHistoryAction = actions.fetchHistory({ id });
|
||||
|
||||
fetchHistoryDoneAction = actions.fetchHistoryDone({
|
||||
id,
|
||||
response: httpResponse,
|
||||
});
|
||||
});
|
||||
|
||||
it('should call the orderService OrderGetOrderItemStatusHistoryResponse', () => {
|
||||
const fetchHistory$ = hot('a', { a: fetchHistoryAction });
|
||||
|
||||
actions$ = fetchHistory$;
|
||||
|
||||
const expected$ = cold('b', { b: fetchHistoryDoneAction });
|
||||
|
||||
expect(historyEffects.fetchHistory$).toBeObservable(expected$);
|
||||
|
||||
expect(
|
||||
orderService.OrderGetOrderItemStatusHistoryResponse
|
||||
).toHaveBeenCalledWith({ orderItemSubsetId: id });
|
||||
});
|
||||
|
||||
it('should dispatch fetchHistoryDone', () => {
|
||||
const fetchHistory$ = hot('-a', { a: fetchHistoryAction });
|
||||
|
||||
actions$ = fetchHistory$;
|
||||
|
||||
const expected$ = cold('-b', { b: fetchHistoryDoneAction });
|
||||
|
||||
expect(historyEffects.fetchHistory$).toBeObservable(expected$);
|
||||
|
||||
expect(
|
||||
orderService.OrderGetOrderItemStatusHistoryResponse
|
||||
).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchHistoryDone$', () => {
|
||||
let fetchHistoryDoneAction: {
|
||||
id: number;
|
||||
response: StrictHttpResponse<ResponseArgsOfHistoryDTO>;
|
||||
} & TypedAction<string>;
|
||||
let addOrderHistoryAction: {
|
||||
id: number;
|
||||
histories: HistoryDTO[];
|
||||
} & TypedAction<string>;
|
||||
|
||||
beforeEach(() => {
|
||||
addOrderHistoryAction = actions.addOrderHistory({
|
||||
id,
|
||||
histories: (httpResponse.body.result as unknown) as HistoryDTO[],
|
||||
});
|
||||
});
|
||||
|
||||
it('should dispatch addOrderHistory if the response is ok', () => {
|
||||
fetchHistoryDoneAction = actions.fetchHistoryDone({
|
||||
id,
|
||||
response: httpResponse,
|
||||
});
|
||||
|
||||
const fetchHistoryDone$ = hot('-a', { a: fetchHistoryDoneAction });
|
||||
actions$ = fetchHistoryDone$;
|
||||
|
||||
const expected$ = cold('-b', { b: addOrderHistoryAction });
|
||||
|
||||
expect(historyEffects.fetchHistoryDone$).toBeObservable(expected$);
|
||||
});
|
||||
it('should set an error and dispatch nothing', () => {
|
||||
fetchHistoryDoneAction = actions.fetchHistoryDone({
|
||||
id,
|
||||
response: { ...httpResponse, ok: false } as StrictHttpResponse<
|
||||
ResponseArgsOfHistoryDTO
|
||||
>,
|
||||
});
|
||||
|
||||
const fetchHistoryDone$ = hot('-a', { a: fetchHistoryDoneAction });
|
||||
actions$ = fetchHistoryDone$;
|
||||
|
||||
const expected$ = cold('--');
|
||||
|
||||
expect(historyEffects.fetchHistoryDone$).toBeObservable(expected$);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -5,10 +5,9 @@ import { switchMap, map, catchError, flatMap } from 'rxjs/operators';
|
||||
import {
|
||||
OrderService,
|
||||
StrictHttpResponse,
|
||||
ResponseArgs,
|
||||
ResponseArgsOfHistoryDTO,
|
||||
HistoryDTO,
|
||||
} from '@swagger/oms';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
import { of, NEVER } from 'rxjs';
|
||||
import { OrderHistoryStatus } from '../defs';
|
||||
|
||||
@@ -28,7 +27,9 @@ export class HistoryEffects {
|
||||
ofType(actions.fetchHistory),
|
||||
switchMap((action) =>
|
||||
this.orderService
|
||||
.OrderGetOrderItemHistoryResponse({ orderItemId: action.id })
|
||||
.OrderGetOrderItemStatusHistoryResponse({
|
||||
orderItemSubsetId: action.id,
|
||||
})
|
||||
.pipe(
|
||||
catchError((err) =>
|
||||
of<StrictHttpResponse<ResponseArgsOfHistoryDTO>>(err)
|
||||
@@ -49,11 +50,12 @@ export class HistoryEffects {
|
||||
ofType(actions.fetchHistoryDone),
|
||||
flatMap((action) => {
|
||||
if (action.response.ok) {
|
||||
const history = action.response.body.result[0];
|
||||
const histories = (action.response.body
|
||||
.result as unknown) as HistoryDTO[];
|
||||
return [
|
||||
actions.addOrderHistory({
|
||||
id: action.id,
|
||||
history,
|
||||
histories,
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { HistoryStateFacade } from './history.facade';
|
||||
import * as actions from './history.actions';
|
||||
|
||||
fdescribe('HistoryStateFacade', () => {
|
||||
let facade: HistoryStateFacade;
|
||||
let store: jasmine.SpyObj<Store<any>>;
|
||||
|
||||
const orderItemSubsetId = 123;
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
HistoryStateFacade,
|
||||
{
|
||||
provide: Store,
|
||||
useValue: jasmine.createSpyObj('store', {
|
||||
dispatch: () => {},
|
||||
}),
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
facade = TestBed.get(HistoryStateFacade);
|
||||
store = TestBed.get(Store);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(facade instanceof HistoryStateFacade).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('fetchHistory', () => {
|
||||
it('should dispatch initOrderHistory to get the history for the provided orderItemSubsetId', () => {
|
||||
const initOrderHistoryAction = actions.initOrderHistory({
|
||||
id: orderItemSubsetId,
|
||||
});
|
||||
facade.fetchHistory(orderItemSubsetId);
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith(initOrderHistoryAction);
|
||||
});
|
||||
});
|
||||
|
||||
describe('reloadHistory', () => {
|
||||
it('should dispatch fetchHistory', () => {
|
||||
const fetchHistoryAction = actions.fetchHistory({
|
||||
id: orderItemSubsetId,
|
||||
});
|
||||
facade.reloadHistory(orderItemSubsetId);
|
||||
|
||||
expect(store.dispatch).toHaveBeenCalledWith(fetchHistoryAction);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -5,6 +5,7 @@ import { Dictionary } from '@ngrx/entity';
|
||||
import { Observable } from 'rxjs';
|
||||
import * as selectors from './history.selectors';
|
||||
import * as actions from './history.actions';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class HistoryStateFacade {
|
||||
@@ -14,14 +15,20 @@ export class HistoryStateFacade {
|
||||
|
||||
constructor(private store: Store<any>) {}
|
||||
|
||||
public getHistory$(orderItemId: number): Observable<OrderHistory> {
|
||||
this.store.dispatch(actions.initOrderHistory({ id: orderItemId }));
|
||||
|
||||
return this.store.select(selectors.selectHistory, orderItemId);
|
||||
public fetchHistory(orderItemSubsetId: number): void {
|
||||
this.store.dispatch(actions.initOrderHistory({ id: orderItemSubsetId }));
|
||||
}
|
||||
|
||||
public getStatus$(orderItemId: number): Observable<OrderHistoryStatus> {
|
||||
return this.store.select(selectors.selectStatus, orderItemId);
|
||||
public reloadHistory(orderItemSubsetId: number): void {
|
||||
this.store.dispatch(actions.fetchHistory({ id: orderItemSubsetId }));
|
||||
}
|
||||
|
||||
public getHistory$(orderItemSubsetId: number): Observable<HistoryDTO[]> {
|
||||
return this.store.select(selectors.selectHistory, orderItemSubsetId);
|
||||
}
|
||||
|
||||
public getStatus$(orderItemSubsetId: number): Observable<OrderHistoryStatus> {
|
||||
return this.store.select(selectors.selectStatus, orderItemSubsetId);
|
||||
}
|
||||
|
||||
private getHistories$(): Observable<Dictionary<OrderHistory>> {
|
||||
|
||||
@@ -5,16 +5,14 @@ import {
|
||||
} from './history.state';
|
||||
import { historyReducer } from './history.reducer';
|
||||
import * as actions from './history.actions';
|
||||
import { OrderHistory } from '@shelf-store/defs';
|
||||
import { HistoryDTO } from '@cmf/trade-api';
|
||||
import { OrderHistoryStatus } from '@shelf-store/defs';
|
||||
|
||||
fdescribe('#HistoryStateReducer', () => {
|
||||
const id = 123;
|
||||
const mockOrderHistory: OrderHistory = {
|
||||
...INITIAL_ORDER_HISTORY,
|
||||
name: 'Fake History',
|
||||
id,
|
||||
values: [],
|
||||
};
|
||||
const mockHistories: HistoryDTO[] = [
|
||||
{ name: 'Fake History', id, values: [] },
|
||||
];
|
||||
|
||||
it('should return the initial state if on Init Order action is dispatched', () => {
|
||||
const initialState = INITIAL_HISTORY_STATE;
|
||||
@@ -24,12 +22,24 @@ fdescribe('#HistoryStateReducer', () => {
|
||||
const entity = state.entities[id];
|
||||
|
||||
expect(entity).toEqual({
|
||||
...initialState.entities[id],
|
||||
...INITIAL_ORDER_HISTORY,
|
||||
id,
|
||||
});
|
||||
});
|
||||
|
||||
it('should set status to fetching if fetchHistory action is dispatched (1)', () => {
|
||||
let state: HistoryState;
|
||||
const initialState = INITIAL_HISTORY_STATE;
|
||||
const initAction = actions.initOrderHistory({ id });
|
||||
|
||||
state = historyReducer(initialState, initAction);
|
||||
|
||||
const action = actions.fetchHistory({ id });
|
||||
state = historyReducer(state, action);
|
||||
|
||||
expect(state.entities[id].status).toBe(OrderHistoryStatus.FETCHING);
|
||||
});
|
||||
|
||||
it('should add history and set status to available (2)', () => {
|
||||
let state: HistoryState;
|
||||
const initialState = INITIAL_HISTORY_STATE;
|
||||
@@ -37,12 +47,13 @@ fdescribe('#HistoryStateReducer', () => {
|
||||
const initAction = actions.initOrderHistory({ id });
|
||||
state = historyReducer(initialState, initAction);
|
||||
|
||||
const action = actions.addOrderHistory({ id, history: mockOrderHistory });
|
||||
const action = actions.addOrderHistory({ id, histories: mockHistories });
|
||||
state = historyReducer(state, action);
|
||||
|
||||
const entity = state.entities[id];
|
||||
|
||||
expect(entity.status).toBe(2);
|
||||
expect(entity).toEqual({ ...mockOrderHistory, status: 2 });
|
||||
expect(entity.histories).toEqual(mockHistories);
|
||||
expect(entity.id).toEqual(id);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -31,15 +31,19 @@ export const _historyReducer = createReducer(
|
||||
s
|
||||
)
|
||||
),
|
||||
on(actions.addOrderHistory, (s, a) => {
|
||||
return historyStateAdapter.updateOne(
|
||||
on(actions.addOrderHistory, (s, a) =>
|
||||
historyStateAdapter.updateOne(
|
||||
{
|
||||
id: a.id,
|
||||
changes: { ...a.history, status: OrderHistoryStatus.AVAILABLE },
|
||||
changes: {
|
||||
...s.entities[a.id],
|
||||
histories: a.histories,
|
||||
status: OrderHistoryStatus.AVAILABLE,
|
||||
},
|
||||
},
|
||||
s
|
||||
);
|
||||
}),
|
||||
)
|
||||
),
|
||||
on(actions.setStatus, (s, a) =>
|
||||
historyStateAdapter.updateOne(
|
||||
{
|
||||
@@ -48,6 +52,12 @@ export const _historyReducer = createReducer(
|
||||
},
|
||||
s
|
||||
)
|
||||
),
|
||||
on(actions.fetchHistory, (s, a) =>
|
||||
historyStateAdapter.updateOne(
|
||||
{ id: a.id, changes: { status: OrderHistoryStatus.FETCHING } },
|
||||
s
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
describe('HistoryStateSelectors', () => {
|
||||
describe('selectHistory', () => {
|
||||
it('should return all histories for the provided id', () => {});
|
||||
});
|
||||
});
|
||||
@@ -20,7 +20,8 @@ export const selectHistories = createSelector(
|
||||
|
||||
export const selectHistory = createSelector(
|
||||
selectEntities,
|
||||
(entities: Dictionary<OrderHistory>, id: number) => entities[id]
|
||||
(entities: Dictionary<OrderHistory>, id: number) =>
|
||||
entities[id] && entities[id].histories
|
||||
);
|
||||
|
||||
export const selectStatus = createSelector(
|
||||
|
||||
@@ -10,5 +10,7 @@ export const INITIAL_HISTORY_STATE: HistoryState = {
|
||||
};
|
||||
|
||||
export const INITIAL_ORDER_HISTORY: OrderHistory = {
|
||||
id: undefined,
|
||||
status: OrderHistoryStatus.INIT,
|
||||
histories: [],
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ $font-weight: normal;
|
||||
$font-weight-bold: bold;
|
||||
$font-color-gray: #89949e;
|
||||
$font-weight-emphasis: 600;
|
||||
$font-line-height: 21px;
|
||||
|
||||
$max-content-width: 916px;
|
||||
|
||||
@@ -21,6 +22,7 @@ $isa-customer-light: #a3b4c8;
|
||||
$isa-customer-inactive: #9cb1c6;
|
||||
$isa-customer-active: #1f466c;
|
||||
$isa-neutral-info: #be8100;
|
||||
$isa-light-blue-platinum: #e1ebf5;
|
||||
|
||||
/* LAYOUT */
|
||||
$layout-border-radius: 5px;
|
||||
@@ -55,6 +57,7 @@ $chip-height: 53px;
|
||||
$headline-font-size-l: 26px;
|
||||
$headline-font-size-m: 22px;
|
||||
$headline-font-size-s: 20px;
|
||||
$headline-font-size-xs: 18px;
|
||||
|
||||
/* INPUT */
|
||||
$input-height-size-l: 60px;
|
||||
|
||||
@@ -4,3 +4,10 @@
|
||||
background-color: $content-background-color;
|
||||
border-radius: $content-border-radius;
|
||||
}
|
||||
|
||||
.isa-content-spacer {
|
||||
margin-top: 15px;
|
||||
margin-bottom: 15px;
|
||||
margin-left: -10%;
|
||||
width: 120%;
|
||||
}
|
||||
|
||||
@@ -170,10 +170,26 @@ body {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.ml-10 {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.mb-5 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.mb-12 {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.mb-20 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mb-25 {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.mb-40 {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user