Add & list dimensions

This commit is contained in:
Michał Romaszkin 2020-12-10 23:34:22 +01:00
parent c0f0196153
commit a720e80dd9
15 changed files with 180 additions and 37 deletions

View File

@ -2045,6 +2045,14 @@
"tslib": "^2.0.0" "tslib": "^2.0.0"
} }
}, },
"@ngrx/entity": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/@ngrx/entity/-/entity-10.1.0.tgz",
"integrity": "sha512-KN72pcBYfK9SgF3Dq2zMKLmPAGtr3e2+gURR45Ph0v13diaw4tgjbQYR4aplrXtR4+5AHwdmtafZ28VPp99PvA==",
"requires": {
"tslib": "^2.0.0"
}
},
"@ngrx/router-store": { "@ngrx/router-store": {
"version": "10.0.1", "version": "10.0.1",
"resolved": "https://registry.npmjs.org/@ngrx/router-store/-/router-store-10.0.1.tgz", "resolved": "https://registry.npmjs.org/@ngrx/router-store/-/router-store-10.0.1.tgz",

View File

@ -21,6 +21,7 @@
"@nebular/eva-icons": "5.0.0", "@nebular/eva-icons": "5.0.0",
"@nebular/theme": "^5.0.0", "@nebular/theme": "^5.0.0",
"@ngrx/effects": "^10.0.1", "@ngrx/effects": "^10.0.1",
"@ngrx/entity": "^10.1.0",
"@ngrx/router-store": "^10.0.1", "@ngrx/router-store": "^10.0.1",
"@ngrx/store": "^10.0.1", "@ngrx/store": "^10.0.1",
"@ngrx/store-devtools": "^10.0.1", "@ngrx/store-devtools": "^10.0.1",

View File

@ -1,9 +1,20 @@
import { createAction, props } from '@ngrx/store'; import { createAction, props } from '@ngrx/store';
import { create } from 'domain';
import { Dimension } from '../reducers/dimension.reducers'; import { Dimension } from '../reducers/dimension.reducers';
export const getDimensions = createAction('[Dimension] Get Dimmnsions'); export const getDimensions = createAction('[Dimension] Get Dimmnsions');
export const getDimensionSuccess = createAction( export const getDimensionSuccess = createAction(
'[Dimension] Get Dimensions Success', '[Dimension] Get Dimensions Success',
props<{ dimensions: Array<Dimension> }>() props<{ dimensions: Array<Dimension> }>()
); );
export const addNewDimension = createAction(
'[Dimension] Add Dimension',
props<{ dimension: Dimension }>()
);
export const addNewDimensionSuccess = createAction(
'[Dimension] Add Dimension Success'
);
export const removeDimension = createAction(
'[Dimension] Remove Dimension',
props<{ id: number }>()
);

View File

@ -2,13 +2,15 @@ import { Injectable } from '@angular/core';
import { Actions, ofType, createEffect } from '@ngrx/effects'; import { Actions, ofType, createEffect } from '@ngrx/effects';
import { State } from '../reducers'; import { State } from '../reducers';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { flatMap, catchError, map, concatMap } from 'rxjs/operators'; import { flatMap, catchError, map } from 'rxjs/operators';
import { EMPTY, of } from 'rxjs'; import { EMPTY, of } from 'rxjs';
import { import {
getDimensions, getDimensions,
getDimensionSuccess, getDimensionSuccess,
addNewDimension,
} from '../actions/dimension.actions'; } from '../actions/dimension.actions';
import { DimensionsService } from '../services/dimensions.service'; import { DimensionsService } from '../services/dimensions.service';
import { addNewDimensionSuccess } from '../actions/dimension.actions';
@Injectable() @Injectable()
export class DimmensionEffects { export class DimmensionEffects {
@ -17,15 +19,30 @@ export class DimmensionEffects {
private dimensionService: DimensionsService private dimensionService: DimensionsService
) {} ) {}
getDimmension$ = createEffect(() => getDimmensions$ = createEffect(() =>
this.actions$.pipe( this.actions$.pipe(
ofType(getDimensions), ofType(getDimensions),
flatMap(() => flatMap(() =>
this.dimensionService.getDimensions().pipe( this.dimensionService.getDimensions().pipe(
map((result) => getDimensionSuccess({ dimensions: result })), map((result) => {
console.log(result);
return getDimensionSuccess({ dimensions: result });
}),
catchError(() => EMPTY) catchError(() => EMPTY)
) )
) )
) )
); );
addDimension$ = createEffect(() =>
this.actions$.pipe(
ofType(addNewDimension),
flatMap((action) => {
console.log(action.dimension);
return this.dimensionService
.addDimension(action.dimension)
.pipe(map(() => addNewDimensionSuccess()));
})
)
);
} }

View File

@ -7,7 +7,14 @@
class="dialog__body" class="dialog__body"
id="dimensionForm" id="dimensionForm"
> >
<input nbInput placeholder="Nazwa wymiaru" formControlName="name" /> <input
nbInput
placeholder="Nazwa wymiaru"
formControlName="name"
[status]="
name.invalid && (name.dirty || name.touched) ? 'danger' : 'basic'
"
/>
<button nbButton status="info" (click)="addCategory()" type="button"> <button nbButton status="info" (click)="addCategory()" type="button">
Dodaj nową kategorię Dodaj nową kategorię
</button> </button>
@ -26,7 +33,13 @@
: 'basic' : 'basic'
" "
/> />
<button nbButton nbSuffix ghost type="button"> <button
nbButton
nbSuffix
ghost
type="button"
(click)="removeCategory(i)"
>
<nb-icon icon="minus-outline" pack="eva"></nb-icon> <nb-icon icon="minus-outline" pack="eva"></nb-icon>
</button> </button>
</nb-form-field> </nb-form-field>

View File

@ -1,5 +1,14 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { FormBuilder, FormArray, Validators } from '@angular/forms'; import {
FormBuilder,
FormArray,
Validators,
FormControl,
} from '@angular/forms';
import { NbToastrService, NbDialogRef } from '@nebular/theme';
import { Store } from '@ngrx/store';
import { State } from 'src/app/reducers';
import { addNewDimension } from 'src/app/actions/dimension.actions';
@Component({ @Component({
selector: 'add-dimension-dialog', selector: 'add-dimension-dialog',
@ -7,7 +16,12 @@ import { FormBuilder, FormArray, Validators } from '@angular/forms';
styleUrls: ['./add-dimension-dialog.component.scss'], styleUrls: ['./add-dimension-dialog.component.scss'],
}) })
export class AddDimensionDialogComponent { export class AddDimensionDialogComponent {
constructor(private fb: FormBuilder) {} constructor(
private fb: FormBuilder,
private toastService: NbToastrService,
private store: Store<State>,
protected dialogRef: NbDialogRef<AddDimensionDialogComponent>
) {}
dimensionForm = this.fb.group({ dimensionForm = this.fb.group({
name: ['', Validators.required], name: ['', Validators.required],
@ -18,11 +32,30 @@ export class AddDimensionDialogComponent {
return this.dimensionForm.get('categories') as FormArray; return this.dimensionForm.get('categories') as FormArray;
} }
get name() {
return this.dimensionForm.get('name') as FormControl;
}
addCategory() { addCategory() {
this.categories.push(this.fb.control('', Validators.required)); this.categories.push(this.fb.control('', Validators.required));
} }
removeCategory(index: number) {
this.categories.removeAt(index);
}
onSubmit() { onSubmit() {
this.dimensionForm.markAllAsTouched(); this.dimensionForm.markAllAsTouched();
if (!this.dimensionForm.invalid) {
this.store.dispatch(
addNewDimension({ dimension: this.dimensionForm.value })
);
this.toastService.success('', 'Pomyślnie dodano nowy wymiar!');
this.dialogRef.close();
} else {
this.toastService.danger('', 'Wystąpił błąd przy wprowadzaniu danych', {
icon: 'alert-triangle-outline',
});
}
} }
} }

View File

@ -49,7 +49,9 @@ export class AvailableForumsComponent implements OnInit {
} }
delete() { delete() {
this.dialogService.open(DeleteDialogComponent); this.dialogService.open(DeleteDialogComponent, {
context: { type: 'plik' },
});
} }
openForum(id: string) { openForum(id: string) {

View File

@ -1,7 +1,7 @@
<nb-card> <nb-card>
<nb-card-header>Czy chcesz usunąć wybrany plik?</nb-card-header> <nb-card-header>Czy chcesz usunąć wybrany {{ type }}?</nb-card-header>
<nb-card-body class="dialog__buttons" <nb-card-body class="dialog__buttons"
><button nbButton status="danger">Potwierdź</button> ><button nbButton status="danger" (click)="close(true)">Potwierdź</button>
<button nbButton status="info">Anuluj</button> <button nbButton status="info" (click)="close(false)">Anuluj</button>
</nb-card-body> </nb-card-body>
</nb-card> </nb-card>

View File

@ -1,8 +1,15 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { NbDialogRef } from '@nebular/theme';
@Component({ @Component({
selector: 'delete-dialog', selector: 'delete-dialog',
templateUrl: './delete-dialog.component.html', templateUrl: './delete-dialog.component.html',
styleUrls: ['./delete-dialog.component.scss'], styleUrls: ['./delete-dialog.component.scss'],
}) })
export class DeleteDialogComponent {} export class DeleteDialogComponent {
constructor(private dialogRef: NbDialogRef<DeleteDialogComponent>) {}
type: string;
close(value: boolean) {
this.dialogRef.close(value);
}
}

View File

@ -1,7 +1,22 @@
<nb-card accent="success"> <nb-card accent="success" class="dimension">
<nb-card-header class="h5">Moje wymiary</nb-card-header> <nb-card-header class="h5">Moje wymiary</nb-card-header>
<nb-list *ngIf="(data$ | async)?.length === 0; else empty"> <nb-list *ngIf="(data$ | async)?.length !== 0; else empty">
<nb-list-item *ngFor="let item of data$ | async"></nb-list-item> <nb-list-item
*ngFor="let item of data$ | async; let i = index"
class="dimension__list"
>
<div>
<span class="subtitle dimension__name">{{ item.name }}</span>
</div>
<div>
<nb-icon
icon="close-outline"
status="danger"
class="dimension__close"
(click)="removeDimension(i)"
></nb-icon>
</div>
</nb-list-item>
</nb-list> </nb-list>
</nb-card> </nb-card>

View File

@ -0,0 +1,12 @@
.dimension {
&__list {
display: flex;
align-items: center;
justify-content: space-between;
}
&__name,
&__close {
cursor: pointer;
}
}

View File

@ -4,9 +4,11 @@ import { Store } from '@ngrx/store';
import { State } from '../../reducers'; import { State } from '../../reducers';
import { getDimensions } from '../../actions/dimension.actions'; import { getDimensions } from '../../actions/dimension.actions';
import { Dimension } from 'src/app/reducers/dimension.reducers'; import { Dimension } from 'src/app/reducers/dimension.reducers';
import { removeDimension } from 'src/app/actions/dimension.actions';
import { selectDimensions } from '../../selectors/dimension.selectors'; import { selectDimensions } from '../../selectors/dimension.selectors';
import { NbDialogService } from '@nebular/theme'; import { NbDialogService } from '@nebular/theme';
import { AddDimensionDialogComponent } from '../add-dimension-dialog/add-dimension-dialog.component'; import { AddDimensionDialogComponent } from '../add-dimension-dialog/add-dimension-dialog.component';
import { DeleteDialogComponent } from '../delete-dialog/delete-dialog.component';
@Component({ @Component({
selector: 'manage-dimensions', selector: 'manage-dimensions',
@ -25,6 +27,14 @@ export class ManageDimensionsComponent implements OnInit {
this.store.dispatch(getDimensions()); this.store.dispatch(getDimensions());
} }
removeDimension(id: number) {
this.dialogService
.open(DeleteDialogComponent, { context: { type: 'wymiar' } })
.onClose.subscribe(
(res: boolean) => res && this.store.dispatch(removeDimension({ id }))
);
}
openAddDialog(): void { openAddDialog(): void {
this.dialogService.open(AddDimensionDialogComponent); this.dialogService.open(AddDimensionDialogComponent);
} }

View File

@ -1,27 +1,37 @@
import { Action, createReducer, on } from '@ngrx/store'; import { Action, createReducer, on } from '@ngrx/store';
import { getDimensionSuccess } from '../actions/dimension.actions'; import {
getDimensionSuccess,
addNewDimension,
removeDimension,
} from '../actions/dimension.actions';
import { createEntityAdapter, EntityAdapter, EntityState } from '@ngrx/entity';
export interface Dimension { export interface Dimension {
id: number; name: string;
categories: Array<string>; categories: Array<string>;
} }
export interface DimensionsState { export interface DimensionsState extends EntityState<Dimension> {
availableDimensions: Array<Dimension>; selectedDimension: number | null;
currentDimmension: Dimension;
} }
export const initialState: DimensionsState = { export const adapter: EntityAdapter<Dimension> = createEntityAdapter<Dimension>();
availableDimensions: [],
currentDimmension: {} as Dimension, export const initialState: DimensionsState = adapter.getInitialState({
}; selectedDimension: null,
});
const _dimensionsReducer = createReducer( const _dimensionsReducer = createReducer(
initialState, initialState,
on(getDimensionSuccess, (state, { dimensions }) => ({ on(addNewDimension, (state, { dimension }) =>
...state, adapter.addOne(dimension, state)
availableDimensions: dimensions, ),
})) on(getDimensionSuccess, (state, { dimensions }) =>
adapter.setAll(dimensions, state)
),
on(removeDimension, (state, { id }) =>
adapter.removeOne(id.toString(), state)
)
); );
export function dimensionsReducer( export function dimensionsReducer(

View File

@ -1,12 +1,11 @@
import { createSelector, createFeatureSelector } from '@ngrx/store'; import { createSelector, createFeatureSelector } from '@ngrx/store';
import { State } from '../reducers'; import { State } from '../reducers';
import { DimensionsState } from '../reducers/dimension.reducers'; import { DimensionsState, adapter } from '../reducers/dimension.reducers';
export const selectFeature = createFeatureSelector<State, DimensionsState>( export const selectFeature = createFeatureSelector<State, DimensionsState>(
'dimension' 'dimension'
); );
export const selectDimensions = createSelector( const { selectAll } = adapter.getSelectors();
selectFeature,
(state: DimensionsState) => state.availableDimensions export const selectDimensions = createSelector(selectFeature, selectAll);
);

View File

@ -11,8 +11,13 @@ export class DimensionsService {
getDimensions(): Observable<Array<Dimension>> { getDimensions(): Observable<Array<Dimension>> {
return this.http return this.http
.get<any>('http://127.0.0.1:8000/dimension/') .get<any>('http://127.0.0.1:8000/dimension/')
.pipe( .pipe(map((res) => res.data));
map((result) => (result.statusCode === '200' ? result.data : EMPTY)) }
);
addDimension(dimension: Dimension): Observable<any> {
const body = JSON.stringify(dimension);
return this.http.post<any>('http://127.0.0.1:8000/dimension/', body, {
responseType: 'json',
});
} }
} }