Skip to content

Commit

Permalink
closes #28; fixes #47; This is the first pre-release
Browse files Browse the repository at this point in the history
setInventoryInResDotLocals now selects more relations; simplified getInventoryDetails; fixed server-side deleteInventory; added seperate delete-confirmation-component; inventories are now deleteable; delete-inventory with working redirect; mat-typography in edit-stocks slider annotation; stocks are now deleteable; delete-stock with working redirect; openedOn now works (fixes #47); deleted old confirm-dialog html file in edit-thing folder; things are now deleteable; delete-thing with working redirect; changed boolena === false to (exclamation mark)boolean; moved the delete-confirmation dialog component away from edit-thing component into its own component which is used for all deletion activities; formatted authService; less logging; implemented deleteInventory in inventoryService;
implemented deleteStock in stockService; formatted thingService
  • Loading branch information
Tanja-4732 committed Mar 3, 2019
1 parent 1338fc4 commit 96a59f2
Show file tree
Hide file tree
Showing 15 changed files with 292 additions and 125 deletions.
67 changes: 21 additions & 46 deletions server/controllers/inventoryController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import AuthController from "./authController";
import UserController from "./userController";
import { Thing } from "../models/thingModel";
import { Stock } from "../models/stockModel";

interface InventoryRequest {
name: string;
Expand All @@ -27,8 +28,11 @@ export default class InventoryController {
): Promise<void> {
// log("setting inv");
try {
res.locals.inventory = await InventoryController.getInventoryOrFail(
req.params.inventoryId
const entityManager: EntityManager = getManager();
res.locals.inventory = await entityManager.findOneOrFail(
Inventory,
req.params.inventoryId,
{ relations: ["inventoryUsers", "inventoryUsers.user"] }
);
} catch (error) {
res.status(404).json({
Expand Down Expand Up @@ -114,44 +118,14 @@ export default class InventoryController {
return;
}

const entityManager: EntityManager = getManager();
let inventory: Inventory;
try {
inventory = await entityManager.findOneOrFail(
Inventory,
res.locals.inventory.InventoryId,
{ relations: ["inventoryUsers", "inventoryUsers.user"] }
);
} catch (error) {
res.status(404).json({
status: 404,
error: "The requested inventory couldn't be found"
});
return;
}

// Hide pwd hash user creation date
for (const inventoryUser of inventory.inventoryUsers) {
for (const inventoryUser of res.locals.inventory.inventoryUsers) {
delete inventoryUser.user.saltedPwdHash;
delete inventoryUser.user.createdOn;
}

// Return requested info with 200
res.status(200).json(inventory);
}

/**
* Returns one inventory object based on its id or fails
*/
public static async getInventoryOrFail(
inventoryId: number
): Promise<Inventory> {
const entityManager: EntityManager = getManager();
return await entityManager.findOneOrFail(Inventory, {
where: {
id: inventoryId
}
});
res.status(200).json(res.locals.inventory);
}

/**
Expand Down Expand Up @@ -276,17 +250,14 @@ export default class InventoryController {
req: Request,
res: Response
): Promise<void> {
// Get the inventory object to later be updated on the db
const invToDelete: Inventory = res.locals.inventory;

// Get the entity manager
const entityManager: EntityManager = getManager();

// Check authorization
if (
!(await AuthController.isAuthorized(
res.locals.actingUser,
invToDelete,
res.locals.inventory as Inventory,
InventoryUserAccessRightsEnum.ADMIN
))
) {
Expand All @@ -299,21 +270,25 @@ export default class InventoryController {
}

try {
/* Old code // TODO delete when ready
// Old code // TODO delete when ready
// Delete all InventoryUsers
await entityManager.delete(InventoryUser, {
inventory: invToDelete
inventory: res.locals.inventory as Inventory
});

// Delete all things
await entityManager.delete(Thing, {
Inventory: invToDelete.InventoryId
}); */
Inventory: res.locals.inventory as Inventory
});

/*Remove the inventory.
This should be sufficient because of
the CASCADE option set in the inventoryModel. */
entityManager.remove(invToDelete);
await entityManager.delete(Stock, {
inventory: res.locals.inventory as Inventory
});

// Remove the inventory
await entityManager.delete(Inventory, {
id: (res.locals.inventory as Inventory).id
});
} catch (error) {
res.status(500).json({
status: 500,
Expand Down
31 changes: 16 additions & 15 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import {
MatNativeDateModule,
MatSliderModule,
MatToolbarModule,
MatDialogModule, MatSidenavModule, MatIconModule, MatListModule
MatDialogModule,
MatSidenavModule,
MatIconModule,
MatListModule
} from "@angular/material";

import { AppComponent } from "./app.component";
Expand All @@ -28,20 +31,18 @@ import { AddStockComponent } from "./components/add-stock/add-stock.component";

import { StocksComponent } from "./components/stocks/stocks.component";
import { EditStockComponent } from "./components/edit-stock/edit-stock.component";
import {
EditThingComponent,
DeleteConfirmationDialogComponent
} from "./components/edit-thing/edit-thing.component";
import { EditThingComponent } from "./components/edit-thing/edit-thing.component";
import { LoginComponent } from "./components/login/login.component";
import { RegisterComponent } from "./components/register/register.component";
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
import { InventoriesComponent } from './components/inventories/inventories.component';
import { MainNavComponent } from './components/main-nav/main-nav.component';
import { LayoutModule } from '@angular/cdk/layout';
import { WelcomeComponent } from './components/welcome/welcome.component';
import { EditInventoryComponent } from './components/edit-inventory/edit-inventory.component';
import { AddInventoryComponent } from './components/add-inventory/add-inventory.component';
import { InventoryCardComponent } from './components/inventory-card/inventory-card.component';
import { PageNotFoundComponent } from "./components/page-not-found/page-not-found.component";
import { InventoriesComponent } from "./components/inventories/inventories.component";
import { MainNavComponent } from "./components/main-nav/main-nav.component";
import { LayoutModule } from "@angular/cdk/layout";
import { WelcomeComponent } from "./components/welcome/welcome.component";
import { EditInventoryComponent } from "./components/edit-inventory/edit-inventory.component";
import { AddInventoryComponent } from "./components/add-inventory/add-inventory.component";
import { InventoryCardComponent } from "./components/inventory-card/inventory-card.component";
import { DeleteConfirmationDialogComponent } from "./components/delete-confirmation-dialog/delete-confirmation-dialog.component";

@NgModule({
declarations: [
Expand All @@ -56,14 +57,14 @@ import { InventoryCardComponent } from './components/inventory-card/inventory-ca
EditThingComponent,
LoginComponent,
RegisterComponent,
DeleteConfirmationDialogComponent,
PageNotFoundComponent,
InventoriesComponent,
MainNavComponent,
WelcomeComponent,
EditInventoryComponent,
AddInventoryComponent,
InventoryCardComponent
InventoryCardComponent,
DeleteConfirmationDialogComponent
],
imports: [
BrowserModule,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<h1 mat-dialog-title *ngIf="!!data.inventory">Really delete {{data.inventory.name}}?</h1>
<h1 mat-dialog-title *ngIf="!!data.thing">Really delete {{data.thing.name}}?</h1>
<h1 mat-dialog-title *ngIf="!!data.stock">Really delete #{{data.stock.number}}?</h1>
<div mat-dialog-content class="mat-typography">
<span *ngIf="!!data.inventory">
This will delete all things and categories of this inventory. <br>
All stocks of all of its things will get deleted as well. <br>
</span>
<span *ngIf="!!data.thing">
All of its stocks will get deleted as well. <br>
Categories will not be affected. <br>
</span>
<span *ngIf="!!data.stock">
It has {{data.stock.percentLeft}}% left.
</span>
<br>
This action cannot be undone.
</div>
<div mat-dialog-actions>
<button mat-raised-button [mat-dialog-close]="false" color="primary">No</button> &nbsp;&nbsp;&nbsp;
<button mat-stroked-button [mat-dialog-close]="true" color="warn">Yes</button>
</div>
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { DeleteConfirmationDialogComponent } from './delete-confirmation-dialog.component';

describe('DeleteConfirmationDialogComponent', () => {
let component: DeleteConfirmationDialogComponent;
let fixture: ComponentFixture<DeleteConfirmationDialogComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DeleteConfirmationDialogComponent ]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(DeleteConfirmationDialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Component, OnInit, Inject, Input } from "@angular/core";
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material";

@Component({
selector: "app-delete-confirmation-dialog",
templateUrl: "./delete-confirmation-dialog.component.html",
styleUrls: ["./delete-confirmation-dialog.component.scss"]
})
export class DeleteConfirmationDialogComponent<DialogData> implements OnInit {
constructor(
public dialogRef: MatDialogRef<DeleteConfirmationDialogComponent<DialogData>>,
@Inject(MAT_DIALOG_DATA) public data: DialogData
) {}

ngOnInit(): void {}
}
54 changes: 48 additions & 6 deletions src/app/components/edit-inventory/edit-inventory.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Inventory } from "../../models/inventory/inventory";
import { InventoryService } from "../../services/inventory/inventory.service";
import { ActivatedRoute, Router } from "@angular/router";
import { HttpErrorResponse } from "@angular/common/http";
import { MatDialog, MatDialogRef } from "@angular/material";
import { DeleteConfirmationDialogComponent } from "../delete-confirmation-dialog/delete-confirmation-dialog.component";

@Component({
selector: "app-edit-inventory",
Expand All @@ -14,12 +16,14 @@ export class EditInventoryComponent implements OnInit {
notFound: boolean = false;
loading: boolean = true;
oof: boolean = false;
inventory: Inventory = new Inventory();
inventoryId: number;
reallyDelete: boolean = false;

inventory: Inventory;

constructor(
private is: InventoryService,
private route: ActivatedRoute,
public dialog: MatDialog,
private router: Router
) {}

Expand All @@ -28,12 +32,12 @@ export class EditInventoryComponent implements OnInit {
}

async getInventory(): Promise<void> {
this.inventoryId = this.route.snapshot.params["inventoryId"];
try {
this.inventory = await this.is.getInventory(this.inventoryId);
this.inventory = await this.is.getInventory(
this.route.snapshot.params["inventoryId"]
);
this.loading = false;
} catch (error) {
console.log(error);
if (error instanceof HttpErrorResponse) {
switch (error.status) {
case 401:
Expand Down Expand Up @@ -78,5 +82,43 @@ export class EditInventoryComponent implements OnInit {
}
}

onDeleteInventory(): void {}
onDeleteInventory(): void {
this.deleteInventory().then(() => {
if (this.reallyDelete) {
this.router.navigate(["inventories"]);
}
});
}

async deleteInventory(): Promise<void> {
const dialogRef: MatDialogRef<any> = this.dialog.open(
DeleteConfirmationDialogComponent,
{
data: { inventory: this.inventory }
}
);

this.reallyDelete = await dialogRef.afterClosed().toPromise();

if (this.reallyDelete) {
try {
const res: unknown = await this.is.deleteInventory(this.inventory);
} catch (error) {
// Catch sending-to-the-server errors
this.oof = true;
if (error instanceof HttpErrorResponse) {
switch (error.status) {
case 401:
// Set flag for html change and timeout above
this.unauthorized = true;
break;
case 404:
this.notFound = true;
}
} else {
console.log("Unknown error in add-stock while creating");
}
}
}
}
}
4 changes: 3 additions & 1 deletion src/app/components/edit-stock/edit-stock.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ <h2>Loading stock...</h2>
<i matSuffix class="material-icons">pie_chart</i>
</mat-form-field>
<br>
Or use the slider:
<span class="mat-typography">Or use the slider:</span>
<mat-slider min="0" max="100" step="1" [(value)]="stock.percentLeft"></mat-slider>
<br>
<br>
<button mat-raised-button (click)="onEditStock()" color="accent">Edit stock</button>
&nbsp;
<button mat-raised-button (click)="onDeleteStock()" color="warn">Delete stock</button>
</span>

<div *ngIf="notFound" class="mat-typography">
Expand Down
Loading

0 comments on commit 96a59f2

Please sign in to comment.