Skip to content

Commit

Permalink
Merge branch 'master' of github.com:spethso/Verleihsystem-TTF
Browse files Browse the repository at this point in the history
  • Loading branch information
mee4895 committed Apr 6, 2018
2 parents 5e429be + 027a790 commit 6746d5a
Show file tree
Hide file tree
Showing 22 changed files with 530 additions and 73 deletions.
35 changes: 30 additions & 5 deletions total_tolles_ferleihsystem/api/lending.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from . import api as api
from .. import db

from .models import LENDING_GET, LENDING_POST, LENDING_PUT
from .models import LENDING_GET, LENDING_POST, LENDING_PUT, ID_LIST
from ..db_models.item import Lending, ItemToLending, Item

PATH: str = '/lending'
Expand Down Expand Up @@ -113,15 +113,15 @@ def put(self, lending_id):
"""
Replace a lending object
"""
lending = Lending.query.filter(Lending.id == lending_id).first()
if lending is None:
abort(404, 'Requested lending not found!')

json = request.get_json()
item_ids = json.pop('item_ids')
items = []
item_to_lendings = []

lending = Lending.query.filter(Lending.id == lending_id).first()
if lending is None:
abort(404, 'Requested lending not found!')

for element in item_ids:
item = Item.query.filter(Item.id == element).first()
if item is None:
Expand All @@ -146,4 +146,29 @@ def put(self, lending_id):
message = str(err)
if 'UNIQUE constraint failed' in message:
abort(409, 'Name is not unique!')
abort(500)

@ANS.doc(model=LENDING_GET, body=ID_LIST)
@ANS.response(404, 'Requested lending not found!')
@ANS.response(400, 'Requested item is not part of this lending.')
@api.marshal_with(LENDING_GET)
# pylint: disable=R0201
def post(self, lending_id):
"""
Give back a list of items.
"""
lending = Lending.query.filter(Lending.id == lending_id).first()
if lending is None:
abort(404, 'Requested lending not found!')

ids = request.get_json()["ids"]
try:
for element in ids:
to_delete = ItemToLending.query.filter(ItemToLending.item_id == element).first()
if to_delete is None:
abort(400, "Requested item is not part of this lending:" + str(element))
db.session.delete(to_delete)
db.session.commit()
return lending
except IntegrityError:
abort(500)
4 changes: 4 additions & 0 deletions total_tolles_ferleihsystem/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@
'id': fields.Integer(min=1, example=1),
})

ID_LIST = api.model('IdList', {
'ids': fields.List(fields.Integer(min=1, example=1)),
})

ITEM_LINKS = api.inherit('ItemLinks', WITH_CURIES, {
'self': HaLUrl(UrlData('api.item_item_detail', absolute=True, url_data={'item_id' : 'id'}), required=False),
'tags': HaLUrl(UrlData('api.item_item_item_tags', url_data={'item_id' : 'id'}, absolute=True)),
Expand Down
4 changes: 3 additions & 1 deletion total_tolles_ferleihsystem/db_models/item.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import datetime

from .. import db
from . import STD_STRING_SIZE
from .itemType import ItemType, ItemTypeToAttributeDefinition
Expand Down Expand Up @@ -37,7 +39,7 @@ def update(self, name: str, type_id: int, lending_duration: int=0, visible_for:
@property
def lending_id(self):
"""
The lending_id this item is currently associated with. -1 if not lended.
The lending_id this item is currently associated with. -1 if not lended.
"""
lending_to_item = ItemToLending.query.filter(ItemToLending.item_id == self.id).first()
if lending_to_item is None:
Expand Down
6 changes: 4 additions & 2 deletions total_tolles_ferleihsystem/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { NgModule } from '@angular/core';
import { HomeComponent } from './home/home.component';
import { LoginComponent } from './login/login.component';

import { SearchComponent } from './search/search.component';
import { SearchOverviewComponent } from './search/search-overview.component';

import { StagingComponent } from './staging/staging.component';

import { LendingOverviewComponent } from './lending/lending-overview.component';
import { LendingComponent } from './lending/lending.component';

import { ItemsOverviewComponent } from './items/items-overview.component';
Expand All @@ -27,8 +28,9 @@ import { ModGuard } from './shared/rest/guards/mod.guard';
import { AdminGuard } from './shared/rest/guards/admin.guard';

const routes: Routes = [
{ path: 'search', component: SearchComponent, canActivate: [LoginGuard] },
{ path: 'search', component: SearchOverviewComponent, canActivate: [LoginGuard] },
{ path: 'staging', component: StagingComponent, canActivate: [ModGuard] },
{ path: 'lendings', component: LendingOverviewComponent, canActivate: [ModGuard] },
{ path: 'lendings/:id', component: LendingComponent, canActivate: [ModGuard] },
{ path: 'items', component: ItemsOverviewComponent, canActivate: [LoginGuard] },
{ path: 'items/:id', component: ItemDetailComponent, canActivate: [LoginGuard] },
Expand Down
2 changes: 2 additions & 0 deletions total_tolles_ferleihsystem/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { SearchComponent } from './search/search.component';
import { StagingComponent } from './staging/staging.component';
import { StagedItemComponent } from './staging/staged-item.component';

import { LendingOverviewComponent } from './lending/lending-overview.component';
import { LendingComponent } from './lending/lending.component';
import { ItemLendingComponent } from './lending/item-lending.component';

Expand Down Expand Up @@ -68,6 +69,7 @@ import { AppComponent } from './app.component';
StagingComponent,
StagedItemComponent,

LendingOverviewComponent,
LendingComponent,
ItemLendingComponent,

Expand Down
4 changes: 4 additions & 0 deletions total_tolles_ferleihsystem/src/app/home/home.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@
<i class="f2 fa fa-search"></i>
<a class="f3 black">Search</a>
</div>
<div class="h4 w5 ma2 br3 bg-near-white flex flex-column items-center justify-center grow pointer" *ngIf="jwt.isModerator()" routerLink="/lendings">
<i class="f2 fa fa-address-card"></i>
<a class="f3 black">Lendings</a>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ <h1 class="mv0" title>Edit: {{itemType?.name}}</h1>
<div class="w-100 ph3 pv2" body>
<dynamic-form [objectModel]="'ItemTypePUT'" [startValues]="itemType" (valid)="onValidChange($event)" (data)="onDataChange($event)"></dynamic-form>
<div class="button h2 pv1 ph2 br2 bg-light-silver link bg-animate" [ngClass]="{'hover-bg-light-blue': valid, 'pointer': valid, 'bg-light-red': !valid}" (click)="save($event)" >Save<i class="fa fa-check mr2"></i></div>
<div class="pv2 flex">
<span class="f4 flex-grow-1">Can contain:</span>
<div>
<p class="f4 mb2 mt0" *ngFor="let itemType of canContain">{{itemType.name}} <i class="ml1 fa fa-times grow pointer" (click)="removeCanContain(itemType.id)"></i></p>
<ttf-type-chooser [question]="typeQuestion" [allowDeselect]="true" [(ngModel)]="canContainTypeID"></ttf-type-chooser>
<div class="button h2 pv1 ph2 mt1 br2 bg-light-silver link bg-animate flex items-center justify-around" [ngClass]="{'hover-bg-silver': canContainTypeID >= 0, 'pointer': canContainTypeID >= 0, 'gray': canContainTypeID < 0}" (click)="addCanContain()" ><i class="fa fa-plus mr2"></i></div>
</div>
</div>
</div>
</ttf-box>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Router } from '@angular/router';
import { ApiObject } from '../shared/rest/api-base.service';
import { ApiService } from '../shared/rest/api.service';
import { Subscription } from 'rxjs/Rx';
import { NumberQuestion } from '../shared/forms/question-number';

@Component({
selector: 'ttf-item-type-edit',
Expand All @@ -11,6 +12,9 @@ import { Subscription } from 'rxjs/Rx';
export class ItemTypeEditComponent implements OnChanges {

private subscription: Subscription;
private canContainSubscription: Subscription;

typeQuestion: NumberQuestion = new NumberQuestion();

@Input() itemTypeID: number;

Expand All @@ -22,6 +26,9 @@ export class ItemTypeEditComponent implements OnChanges {
valid: boolean = false;
data: any = {};

canContainTypeID: number;
canContain: ApiObject[];

constructor(private api: ApiService, private router: Router) { }

ngOnChanges(): void {
Expand All @@ -30,6 +37,12 @@ export class ItemTypeEditComponent implements OnChanges {
}
this.subscription = this.api.getItemType(this.itemTypeID).subscribe(data => {
this.itemType = data;
if (this.canContainSubscription != null) {
this.canContainSubscription.unsubscribe();
}
this.canContainSubscription = this.api.getCanContain(this.itemType).subscribe(canContain => {
this.canContain = canContain;
});
});
}

Expand All @@ -41,14 +54,20 @@ export class ItemTypeEditComponent implements OnChanges {
this.data = data;
}

save(event) {
if (this.valid) {
this.api.putItemType(this.itemType.id, this.data);
addCanContain() {
if (this.canContainTypeID != null && this.canContainTypeID >= 0) {
this.api.postCanContain(this.itemType, this.canContainTypeID);
}
}

removeCanContain(id) {
if (this.canContainTypeID != null && this.canContainTypeID >= 0) {
this.api.deleteCanContain(this.itemType, id);
}
}

delete = (() => {
delete = () => {
this.api.deleteItemType(this.itemType.id).take(1).subscribe(() => this.router.navigate(['item-types']));
}).bind(this);
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<div class="flex flex-wrap">
<ttf-box>
<h1 class="mv0" title>Item "{{item?.name}}":</h1>
<h1 class="mv0" title>Item "{{item?.name}}" <span class="i gray underline-hover pointer" routerLink="/lendings/{{item?.lending_id}}" [hidden]="!item?.is_currently_lended">lent</span>:</h1>
<div class="flex" title-right>
<div class="button fc h2 pv1 ph2 br2 ml2 link bg-animate hover-bg-light-silver pointer" [ngClass]="{'bg-silver': edit}" (click)="edit = !edit" [hidden]="!canEdit" title-right>
<i class="fa fa-pencil" [ngClass]="{'fa-inverse': edit}"></i>
</div>
<div class="button fc h2 pv1 ph2 br2 ml2 link bg-animate hover-bg-light-silver pointer" [ngClass]="{'bg-silver': staging.isStaged(itemID)}" (click)="staging.stage(itemID)" title-right>
<div class="button fc h2 pv1 ph2 br2 ml2 link bg-animate hover-bg-light-silver pointer" [ngClass]="{'bg-silver': staging.isStaged(itemID)}" (click)="staging.stage(itemID)" [hidden]="!item?.type.lendable || item?.is_currently_lended" title-right>
<i class="fa fa-cart-plus" [hidden]="staging.isStaged(itemID)"></i>
<i class="fa fa-shopping-cart fa-inverse" [hidden]="!staging.isStaged(itemID)"></i>
</div>
Expand All @@ -14,8 +14,14 @@ <h1 class="mv0" title>Item "{{item?.name}}":</h1>
<p class="f4"><span class="b">Type:</span> <span class="link underline-hover pointer" routerLink="/item-types/{{item?.type?.id}}">{{item?.type?.name}}</span></p>
<p class="f4"><span class="b">Tags:</span> <span *ngFor="let tag of tags; let isLast=last" routerLink="/tags/{{tag.id}}"><span class="link underline-hover pointer">{{tag.name}}</span>{{isLast ? '' : ', '}}</span></p>
<p class="f4"><span class="b">Lending Duration:</span><ttf-lending-duration [duration]="lendingDuration"></ttf-lending-duration></p>
<p class="f4 b">Attributes:</p>
<p class="f5" *ngFor="let attr of attributes"><span class="b">{{attr.attribute_definition?.name}}:</span> {{attr?.value}}</p>
<div [hidden]="attributes?.length === 0">
<p class="f4 b">Attributes:</p>
<p class="f5" *ngFor="let attr of attributes"><span class="b">{{attr.attribute_definition?.name}}:</span> {{attr?.value}}</p>
</div>
<div [hidden]="containedItems?.length === 0">
<p class="f4 b">Contained Items:</p>
<p class="f5" *ngFor="let item of containedItems"><span class="hover-underline pointer" routerLink="/items/{{item.id}}">{{item.name}}</span></p>
</div>
</div>
</ttf-box>

Expand All @@ -27,4 +33,34 @@ <h1 class="mv0" title>Attributes:</h1>
<ttf-attribute-edit *ngFor="let attr of attributeIDs" [itemID]="itemID" [attributeID]="attr"></ttf-attribute-edit>
</div>
</ttf-box>

<ttf-box [hidden]="!edit || !canEdit">
<h1 class="mv0" title>Contained Items:</h1>
<div class="w-100 ph3 pv2" body>
<div class="br2 ba b--black-10 mb2" *ngFor="let itemType of canContain" >
<div class="min-h2 mv0 pv2 ph3 flex items-center justify-between f4 bg-near-white br2 br--top">
<div>
{{itemType.name}}
</div>
<div>
<div class="tooltip tooltip-left button h2 pv1 ph2 ml2 br2 link bg-animate hover-bg-light-silver pointer" data-tooltip="add" (click)="chooseItemType = itemType.id; search.resetSearchData(); chooseItem.open()">
<i class="fa fa-plus"></i>
</div>
</div>
</div>
<div class="ph2 bt b--black-10" [hidden]="containedItemsAsMap.get(itemType.id)?.length < 1">
<p *ngFor="let item of containedItemsAsMap.get(itemType.id)">{{item.name}} <i class="ml1 fa fa-times grow pointer" (click)="removeItemFromContained(item)"></i></p>
</div>
</div>
</div>
</ttf-box>

<ttf-dialog [dialogType]="'info'" #chooseItem>
<h1 class="mv0" title>Choose Item:</h1>
<div class="w-100 ph3 pv2" body>
<ttf-search [asSelector]="true" [restrictToType]="chooseItemType" (selectedChanged)="addItemToContained($event); chooseItem.close()" #search></ttf-search>
</div>
</ttf-dialog>


</div>
56 changes: 51 additions & 5 deletions total_tolles_ferleihsystem/src/app/items/item-detail.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import { Subscription } from 'rxjs/Rx';

import { NavigationService, Breadcrumb } from '../navigation/navigation-service';
import { StagingService } from '../navigation/staging-service';
import { ApiService } from '../shared/rest/api.service';
import { JWTService } from '../shared/rest/jwt.service';
import { Subscription } from 'rxjs/Rx';
import { ApiObject } from '../shared/rest/api-base.service';

@Component({
selector: 'ttf-item-detail',
Expand All @@ -16,15 +19,22 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
private itemSubscription: Subscription;
private attributesSubscription: Subscription;
private tagsSubscription: Subscription;
private containedTypeSubscription: Subscription;
private containedItemsSubscription: Subscription;

edit: boolean = false;

itemID: number;
item;
attributes;
tags;
item: ApiObject;
attributes: ApiObject[];
tags: ApiObject[];
attributeIDs: number[] = [];

canContain: ApiObject[];
containedItems: ApiObject[];
containedItemsAsMap: Map<number, ApiObject[]> = new Map<number, ApiObject[]>();
chooseItemType: number = -1;

constructor(private data: NavigationService, private api: ApiService,
private jwt: JWTService, private staging: StagingService,
private route: ActivatedRoute) { }
Expand Down Expand Up @@ -75,7 +85,29 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
}
this.tagsSubscription = this.api.getTagsForItem(item).subscribe(tags => {
this.tags = tags;
})
});
if (this.containedTypeSubscription != null) {
this.containedTypeSubscription.unsubscribe();
}
this.containedTypeSubscription = this.api.getCanContain(item.type).subscribe(canContain => {
this.canContain = canContain;
});
if (this.containedItemsSubscription != null) {
this.containedItemsSubscription.unsubscribe();
}
this.containedItemsSubscription = this.api.getContainedItems(item).subscribe(containedItems => {
const itemMap = new Map<number, ApiObject[]>();
containedItems.forEach(item => {
let list = itemMap.get(item.type.id);
if (list == null) {
list = [];
itemMap.set(item.type.id, list);
}
list.push(item);
});
this.containedItemsAsMap = itemMap;
this.containedItems = containedItems;
});
});
}

Expand Down Expand Up @@ -116,6 +148,20 @@ export class ItemDetailComponent implements OnInit, OnDestroy {
if (this.tagsSubscription != null) {
this.tagsSubscription.unsubscribe();
}
if (this.containedTypeSubscription != null) {
this.containedTypeSubscription.unsubscribe();
}
if (this.containedItemsSubscription != null) {
this.containedItemsSubscription.unsubscribe();
}
}

addItemToContained = (item: ApiObject) => {
this.api.postContainedItem(this.item, item.id);
}

removeItemFromContained(item: ApiObject) {
this.api.deleteContainedItem(this.item, item.id);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
<ul class="mt0 list">
<li class="min-w2 mb1 hide-child" *ngFor="let item of data?.get(letter)">
<span class="link underline-hover pointer" routerLink="/items/{{item.id}}">{{item.name}}</span>
<ng-container *ngIf="item?.type?.lendable">
<span class="i gray" [hidden]="!item?.is_currently_lended">lent</span>
<ng-container *ngIf="item?.type?.lendable && !item?.is_currently_lended">
<i class="child grow-large fa fa-cart-plus" [hidden]="staging.isStaged(item.id)" (click)="staging.stage(item.id)"></i>
<i class="fa fa-shopping-cart" [hidden]="!staging.isStaged(item.id)"></i>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{{itemLending?.item?.name}} (due: {{itemLending?.due | date:'short'}})
</div>
<div>
<div class="tooltip tooltip-left button h2 pv1 ph2 ml2 br2 link bg-animate hover-bg-light-silver pointer" data-tooltip="return" (click)="staging.remove(itemID)">
<div class="tooltip tooltip-left button h2 pv1 ph2 ml2 br2 link bg-animate hover-bg-light-silver pointer" data-tooltip="return" (click)="return.emit(itemLending?.item?.id)">
<i class="fa fa-reply"></i>
</div>
</div>
Expand Down
Loading

0 comments on commit 6746d5a

Please sign in to comment.