Skip to content

Commit 195eca4

Browse files
feat(preview): tree structure
1 parent 1ce9252 commit 195eca4

File tree

6 files changed

+229
-27
lines changed

6 files changed

+229
-27
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {it, inject, beforeEachProviders} from 'angular2/testing';
2+
3+
import {ItemComponent} from './item.component';
4+
5+
describe('ItemComponent', () => {
6+
beforeEachProviders(() => [
7+
ItemComponent
8+
]);
9+
10+
it('should be initialised', inject([ItemComponent], (component) => {
11+
expect(component.item).not.toBeDefined();
12+
}));
13+
});

src/app/build/shop/preview/item.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import {DDragonDirective} from '../../../misc/ddragon.directive';
66
selector: 'item',
77
directives: [DDragonDirective],
88
template: `
9-
<img [ddragon]="'item/' + item.image.full">
10-
<p class="gold">{{item.gold.total ? item.gold.total : ''}}</p>`
9+
<img [ddragon]="'item/' + item?.image?.full">
10+
<p class="gold">{{item?.gold?.total ? item?.gold?.total : ''}}</p>`
1111
})
1212

1313
export class ItemComponent {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import {it, inject, beforeEach, beforeEachProviders} from 'angular2/testing';
2+
3+
import {ItemsFromComponent} from './items-from.component';
4+
5+
describe('ItemsFromComponent', () => {
6+
beforeEachProviders(() => [
7+
ItemsFromComponent
8+
]);
9+
10+
it('should be initialised', inject([ItemsFromComponent], (component) => {
11+
expect(component.items).not.toBeDefined();
12+
expect(component.itemSelected).toBeDefined();
13+
expect(component.itemPicked).toBeDefined();
14+
}));
15+
16+
it('should emit itemSelected event', inject([ItemsFromComponent], (component) => {
17+
spyOn(component.itemSelected, 'emit');
18+
expect(component.itemSelected.emit).not.toHaveBeenCalled();
19+
component.selectItem({});
20+
expect(component.itemSelected.emit).toHaveBeenCalled();
21+
}));
22+
23+
it('should emit itemPicked event', inject([ItemsFromComponent], (component) => {
24+
spyOn(component.itemPicked, 'emit');
25+
expect(component.itemPicked.emit).not.toHaveBeenCalled();
26+
let result = component.pickItem({});
27+
expect(result).toBeFalsy();
28+
expect(component.itemPicked.emit).toHaveBeenCalled();
29+
}));
30+
});
Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,32 @@
11
import {Component, Input, Output, EventEmitter} from 'angular2/core';
2+
import {NgFor, NgIf} from 'angular2/common';
23

34
import {ItemComponent} from './item.component';
45
import {ItemBundle} from './item-bundle';
56

67
@Component({
78
selector: 'items-from',
8-
directives: [ItemComponent, ItemsFromComponent],
9+
directives: [NgFor, NgIf, ItemComponent, ItemsFromComponent],
910
template: `
10-
<template ngFor #bundle [ngForOf]="items">
11-
<div>
12-
<item [item]="bundle.item" [attr.title]="bundle.item.name" (click)="leftClick(bundle.item)"></item>
13-
<items-from [items]="bundle.children" (itemPicked)="leftClick($event)"></items-from>
14-
</div>
15-
</template>`
11+
<div *ngFor="#bundle of items">
12+
<hr class="up">
13+
<item [item]="bundle.item" [attr.title]="bundle.item.name" (click)="selectItem(bundle.item)" (contextmenu)="pickItem(bundle.item)"></item>
14+
<hr *ngIf="bundle.children" class="down">
15+
<items-from [items]="bundle.children" (itemSelected)="itemSelected" (itemPicked)="itemPicked"></items-from>
16+
</div>`
1617
})
1718

1819
export class ItemsFromComponent {
1920
@Input() items: Array<ItemBundle>;
21+
@Output() itemSelected: EventEmitter<any> = new EventEmitter<any>();
2022
@Output() itemPicked: EventEmitter<any> = new EventEmitter<any>();
2123

22-
leftClick(item: Object) {
23-
this.itemPicked.next(item);
24+
private selectItem(item: Object) {
25+
this.itemSelected.emit(item);
26+
}
27+
28+
private pickItem(item: Object) {
29+
this.itemPicked.emit(item);
30+
return false; // stop context menu from appearing
2431
}
2532
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import {it, inject, beforeEach, beforeEachProviders} from 'angular2/testing';
2+
3+
import {PreviewComponent} from './preview.component';
4+
5+
describe('PreviewComponent', () => {
6+
beforeEachProviders(() => [
7+
PreviewComponent
8+
]);
9+
10+
let item1 = { id: 1, from: ['2', '3'] };
11+
let item2 = { id: 2, from: ['4'], into: ['1'] };
12+
let item3 = { id: 3, from: ['4', '5'], into: ['1'] };
13+
let item4 = { id: 4, into: ['2', '3'] };
14+
let item5 = { id: 5, into: ['3'] };
15+
16+
let items = [
17+
item1, item2, item3, item4, item5
18+
];
19+
20+
beforeEach(inject([PreviewComponent], (component) => {
21+
component.items = items;
22+
}));
23+
24+
it('should be initialised', inject([PreviewComponent], (component) => {
25+
expect(component.item).not.toBeDefined();
26+
expect(component.items).toHaveEqualContent(items);
27+
expect(component.itemPicked).toBeDefined();
28+
expect(component.itemsFrom).toBeDefined();
29+
expect(component.itemsInto).toBeDefined();
30+
}));
31+
32+
33+
it('should update on changes', inject([PreviewComponent], (component) => {
34+
spyOn(component, 'getItemsFrom');
35+
spyOn(component, 'getItemsInto');
36+
expect(component.getItemsFrom).not.toHaveBeenCalled();
37+
expect(component.getItemsInto).not.toHaveBeenCalled();
38+
component.item = item2;
39+
console.log(component.items);
40+
component.ngOnChanges();
41+
expect(component.getItemsFrom).toHaveBeenCalled();
42+
expect(component.getItemsInto).toHaveBeenCalled();
43+
}));
44+
45+
it('should update on select', inject([PreviewComponent], (component) => {
46+
spyOn(component, 'ngOnChanges');
47+
expect(component.ngOnChanges).not.toHaveBeenCalled();
48+
component.selectItem(item4);
49+
expect(component.item).toBe(item4);
50+
expect(component.ngOnChanges).toHaveBeenCalled();
51+
}));
52+
53+
54+
it('should not update when there is no item', inject([PreviewComponent], (component) => {
55+
component.itemsFrom = 'test';
56+
component.itemsInto = 'test';
57+
component.ngOnChanges();
58+
expect(component.itemsFrom).toHaveEqualContent('test');
59+
expect(component.itemsInto).toHaveEqualContent('test');
60+
}));
61+
62+
63+
it('should get from-items', inject([PreviewComponent], (component) => {
64+
let result = component.getItemsFrom(item1);
65+
expect(result).toHaveEqualContent([
66+
{
67+
item: item2, children: [
68+
{ item: item4, children: undefined }
69+
]
70+
},
71+
{
72+
item: item3, children: [
73+
{ item: item4, children: undefined }, { item: item5, children: undefined }
74+
]
75+
}
76+
]);
77+
}));
78+
79+
it('should get into-items', inject([PreviewComponent], (component) => {
80+
let result = component.getItemsInto(item4);
81+
expect(result).toHaveEqualContent([item2, item3]);
82+
}));
83+
84+
85+
it('should emit itemPicked event when an item is picked', inject([PreviewComponent], (component) => {
86+
spyOn(component.itemPicked, 'emit');
87+
expect(component.itemPicked.emit).not.toHaveBeenCalled();
88+
let result = component.pickItem(item4);
89+
expect(result).toBeFalsy();
90+
expect(component.itemPicked.emit).toHaveBeenCalled();
91+
}));
92+
93+
94+
it('should not get items when there are no items', inject([PreviewComponent], (component) => {
95+
component.items = undefined;
96+
let result = component.getItems([1]);
97+
expect(result).not.toBeDefined();
98+
}));
99+
});

src/assets/css/build.css

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
}
55

66
.title img {
7+
width: 90px;
78
height: 90px;
89
}
910

@@ -180,8 +181,9 @@ mastery > div:not(.enabled) .rank {
180181
}
181182

182183
mastery > div > img {
183-
border: 2px solid #777;
184+
width: 48px;
184185
height: 48px;
186+
border: 2px solid #777;
185187
}
186188

187189
mastery .description {
@@ -264,11 +266,11 @@ shop .right-container {
264266
}
265267

266268
shop .middle {
267-
width: 70%;
269+
min-width: 70%;
268270
}
269271

270272
shop .right {
271-
width: 30%;
273+
min-width: 30%;
272274
}
273275

274276

@@ -388,6 +390,7 @@ item .gold {
388390
}
389391

390392
item .gold img {
393+
width: 32px;
391394
height: 32px;
392395
display: inline-block;
393396
padding-right: 4px;
@@ -452,13 +455,39 @@ preview item {
452455
}
453456

454457
preview item p.gold {
455-
margin: -19px 0 0 0;
458+
margin-top: -19px;
456459
}
457460

458-
preview .item img {
459-
display: block;
461+
preview .item > item,
462+
preview .item > item > img {
463+
width: 64px;
464+
height: 64px;
460465
border-radius: 8px;
466+
}
467+
468+
preview .item > item {
461469
margin: 0 auto;
470+
display: block;
471+
}
472+
473+
preview hr {
474+
border: 1px solid;
475+
height: 0;
476+
margin: 6px 30px -18px 30px;
477+
}
478+
479+
preview hr.up {
480+
border: 1px solid;
481+
width: 0;
482+
height: 10px;
483+
margin: 2px auto 0 auto;
484+
}
485+
486+
preview hr.down {
487+
border: 1px solid;
488+
width: 0;
489+
height: 10px;
490+
margin: 0 auto -18px auto;
462491
}
463492

464493
/* items-from */
@@ -476,26 +505,50 @@ items-from item {
476505
display: block;
477506
margin: 0 auto;
478507
padding: 0 8px;
479-
background-color: cadetblue;
508+
background-color: transparent;
480509
}
481510

482511
items-from item:hover {
483-
background-color: cadetblue;
512+
background-color: transparent;
513+
}
514+
515+
items-from > div> item:before {
516+
content: '';
517+
border: 1px solid;
518+
position: absolute;
519+
width: 60px;
520+
}
521+
522+
items-from > div:first-of-type > item:before {
523+
margin: -12px 0px 6px 22px;
524+
}
525+
526+
items-from > div:last-of-type > item:before {
527+
margin: -12px 0px 6px -40px;
528+
}
529+
530+
items-from > div:not(:first-of-type):not(:last-of-type) > item:before {
531+
margin: -12px 0 0 -40px;
532+
width: 120px;
533+
}
534+
535+
items-from > div:first-of-type:last-of-type > item:before {
536+
display: none;
484537
}
485538

486539
/* media */
487540

488-
@media (max-width: 1700px) {
489-
item {
490-
width: 32%;
541+
@media (max-width: 1650px) {
542+
shop .items item {
543+
width: 48%;
491544
}
492545
}
493546

494-
@media (max-width: 1350px) {
495-
item {
547+
/*@media (max-width: 1350px) {
548+
shop .items item {
496549
width: 48%;
497550
}
498-
}
551+
}*/
499552

500553
@media (max-width: 800px) {
501554
shop .left {
@@ -504,10 +557,10 @@ items-from item:hover {
504557
}
505558

506559
@media (max-width: 600px) {
507-
item {
560+
shop .items item {
508561
width: 100%;
509562
}
510-
item .gold {
563+
shop .items item .gold {
511564
display: inline-block;
512565
text-align: right;
513566
}

0 commit comments

Comments
 (0)