Commit bc42797ed1b1ba23f8b0e5723c7474e5d6396b4c
1 parent
68deaf35
Exists in
master
and in
26 other branches
refactory on article.service articleRemoved event to make it simpler
Showing
8 changed files
with
22 additions
and
167 deletions
Show diff stats
src/app/article/article-default-view-component.spec.ts
1 | import {Input, provide, Component} from 'ng-forward'; | 1 | import {Input, provide, Component} from 'ng-forward'; |
2 | import {ArticleViewComponent, ArticleDefaultViewComponent} from './article-default-view.component'; | 2 | import {ArticleViewComponent, ArticleDefaultViewComponent} from './article-default-view.component'; |
3 | import {ComponentTestHelper, createClass} from './../../spec/component-test-helper'; | 3 | import {ComponentTestHelper, createClass} from './../../spec/component-test-helper'; |
4 | -import {ModelEvent, ArticleEventType} from "./../shared/models/events"; | ||
5 | 4 | ||
6 | import * as helpers from "../../spec/helpers"; | 5 | import * as helpers from "../../spec/helpers"; |
7 | 6 | ||
@@ -85,8 +84,7 @@ describe("Components", () => { | @@ -85,8 +84,7 @@ describe("Components", () => { | ||
85 | * Simulate the ArticleService ArticleEvent.removed event | 84 | * Simulate the ArticleService ArticleEvent.removed event |
86 | */ | 85 | */ |
87 | function simulateRemovedEvent() { | 86 | function simulateRemovedEvent() { |
88 | - let event: ModelEvent = ModelEvent.event(ArticleEventType.removed); | ||
89 | - helper.component.articleService.notifyArticleRemovedListeners(article); | 87 | + helper.component.articleService["notifyArticleRemovedListeners"](article); |
90 | } | 88 | } |
91 | }); | 89 | }); |
92 | 90 |
src/app/article/article-default-view.component.ts
@@ -5,7 +5,6 @@ import {MacroDirective} from "./macro/macro.directive"; | @@ -5,7 +5,6 @@ import {MacroDirective} from "./macro/macro.directive"; | ||
5 | import {ArticleToolbarHotspotComponent} from "../hotspot/article-toolbar-hotspot.component"; | 5 | import {ArticleToolbarHotspotComponent} from "../hotspot/article-toolbar-hotspot.component"; |
6 | import {ArticleContentHotspotComponent} from "../hotspot/article-content-hotspot.component"; | 6 | import {ArticleContentHotspotComponent} from "../hotspot/article-content-hotspot.component"; |
7 | import {ArticleService} from "./../../lib/ng-noosfero-api/http/article.service"; | 7 | import {ArticleService} from "./../../lib/ng-noosfero-api/http/article.service"; |
8 | -import {ModelEvent, ArticleEventType} from "./../shared/models/events"; | ||
9 | 8 | ||
10 | /** | 9 | /** |
11 | * @ngdoc controller | 10 | * @ngdoc controller |
@@ -26,8 +25,7 @@ export class ArticleDefaultViewComponent { | @@ -26,8 +25,7 @@ export class ArticleDefaultViewComponent { | ||
26 | 25 | ||
27 | constructor(private $state: ng.ui.IStateService, public articleService: ArticleService) { | 26 | constructor(private $state: ng.ui.IStateService, public articleService: ArticleService) { |
28 | // Subscribe to the Article Removed Event | 27 | // Subscribe to the Article Removed Event |
29 | - let event = ModelEvent.event(ArticleEventType.removed); | ||
30 | - this.articleService.subscribe(event, (article: noosfero.Article) => { | 28 | + this.articleService.subscribeToArticleRemoved((article: noosfero.Article) => { |
31 | if (this.article.parent) { | 29 | if (this.article.parent) { |
32 | this.$state.transitionTo('main.profile.page', { page: this.article.parent.path, profile: this.article.profile.identifier }); | 30 | this.$state.transitionTo('main.profile.page', { page: this.article.parent.path, profile: this.article.profile.identifier }); |
33 | } else { | 31 | } else { |
src/app/shared/models/events.spec.ts
@@ -1,71 +0,0 @@ | @@ -1,71 +0,0 @@ | ||
1 | -import { EventEmitter } from "ng-forward"; | ||
2 | -import {ModelEvent, ArticleEventType} from "./events"; | ||
3 | -import {HashMap} from "./../utils/hashmap"; | ||
4 | -import {ArrayUtils} from "./../utils/arrays"; | ||
5 | - | ||
6 | -describe("Events", () => { | ||
7 | - | ||
8 | - describe("Event Type Tests", () => { | ||
9 | - | ||
10 | - it("verify event type is correctly created", (done) => { | ||
11 | - let eventType1 = ArticleEventType.removed; | ||
12 | - expect(eventType1.type).toBe("removed"); | ||
13 | - expect(ArrayUtils.arraysEqual(eventType1.types, ["added", "removed"])).toBeTruthy(); | ||
14 | - done(); | ||
15 | - }); | ||
16 | - | ||
17 | - it("different event types of same type should be equal", (done) => { | ||
18 | - let eventType1 = ArticleEventType.removed; | ||
19 | - let eventType2 = ArticleEventType.removed; | ||
20 | - expect(eventType1).toBe(eventType2); | ||
21 | - expect(eventType1 === eventType2).toBeTruthy(); | ||
22 | - done(); | ||
23 | - }); | ||
24 | - | ||
25 | - it("different events types of different types should not be equal", (done) => { | ||
26 | - let eventType1 = ArticleEventType.removed; | ||
27 | - let eventType2 = ArticleEventType.added; | ||
28 | - expect(eventType1).not.toBe(eventType2); | ||
29 | - expect(eventType1 === eventType2).not.toBeTruthy(); | ||
30 | - done(); | ||
31 | - }); | ||
32 | - | ||
33 | - it("different events of same type should be equal", (done) => { | ||
34 | - let event1 = ModelEvent.event(ArticleEventType.added); | ||
35 | - let event2 = ModelEvent.event(ArticleEventType.added); | ||
36 | - expect(event1.equals(event2)).toBeTruthy(); | ||
37 | - done(); | ||
38 | - }); | ||
39 | - | ||
40 | - }); | ||
41 | - | ||
42 | - describe("Event HashMap Tests", () => { | ||
43 | - let events: HashMap<ModelEvent, EventEmitter<noosfero.Article>>; | ||
44 | - beforeEach((done) => { | ||
45 | - events = new HashMap<ModelEvent, EventEmitter<noosfero.Article>>(); | ||
46 | - done(); | ||
47 | - }); | ||
48 | - | ||
49 | - it("verify event HashMap contains the correct event", () => { | ||
50 | - let expected = new EventEmitter<noosfero.Article>(); | ||
51 | - events.put(ModelEvent.event(ArticleEventType.added), expected); | ||
52 | - let actual = events.get(ModelEvent.event(ArticleEventType.added)); | ||
53 | - expect(expected === actual).toBeTruthy(); | ||
54 | - }); | ||
55 | - | ||
56 | - it("verify event HashMap does not contain the wrong event", () => { | ||
57 | - events.put(ModelEvent.event(ArticleEventType.added), new EventEmitter<noosfero.Article>()); | ||
58 | - let actual = events.get(ModelEvent.event(ArticleEventType.removed)); | ||
59 | - expect(actual).not.toBeTruthy(); | ||
60 | - }); | ||
61 | - | ||
62 | - it("verify HashMap has been cleared", () => { | ||
63 | - events.put(ModelEvent.event(ArticleEventType.added), new EventEmitter<noosfero.Article>()); | ||
64 | - events.clear(); | ||
65 | - let actual = events.get(ModelEvent.event(ArticleEventType.added)); | ||
66 | - expect(actual).not.toBeTruthy(); | ||
67 | - }); | ||
68 | - | ||
69 | - }); | ||
70 | - | ||
71 | -}); |
src/app/shared/models/events.ts
@@ -1,62 +0,0 @@ | @@ -1,62 +0,0 @@ | ||
1 | -import {ArrayUtils} from "./../utils/arrays"; | ||
2 | - | ||
3 | -export abstract class EventType { | ||
4 | - /** | ||
5 | - * All possible types for the event | ||
6 | - */ | ||
7 | - types = new Array<string>(); | ||
8 | - | ||
9 | - /** | ||
10 | - * The event type | ||
11 | - */ | ||
12 | - type: string; | ||
13 | - | ||
14 | - constructor(types: Array<string>, type: string) { | ||
15 | - this.types = types; | ||
16 | - this.type = type; | ||
17 | - } | ||
18 | - | ||
19 | - equals(other: EventType) { | ||
20 | - return ArrayUtils.arraysEqual(this.types, other.types) && this.type === other.type; | ||
21 | - } | ||
22 | - | ||
23 | -} | ||
24 | - | ||
25 | -export class ArticleEventType extends EventType { | ||
26 | - static types = ["added", "removed"]; | ||
27 | - static removed: ArticleEventType = new ArticleEventType("removed"); | ||
28 | - static added: ArticleEventType = new ArticleEventType("added"); | ||
29 | - | ||
30 | - constructor(type: string) { | ||
31 | - super(ArticleEventType.types, type); | ||
32 | - } | ||
33 | -} | ||
34 | - | ||
35 | -/** | ||
36 | - * A model event have a type (ModelEventType), and optionally with a model element. | ||
37 | - * Therefore, it is possible to have events related to specific model elements. | ||
38 | - * If the model element element is not provided, then the event is a generic event | ||
39 | - * of the given type. | ||
40 | - */ | ||
41 | -export class ModelEvent { | ||
42 | - private type: EventType; | ||
43 | - private id: number; | ||
44 | - | ||
45 | - static event(type: EventType, model?: noosfero.RestModel): ModelEvent { | ||
46 | - if (model) { | ||
47 | - return new ModelEvent(type, model.id); | ||
48 | - } else { | ||
49 | - return new ModelEvent(type); | ||
50 | - } | ||
51 | - } | ||
52 | - | ||
53 | - constructor(type: EventType, id?: number) { | ||
54 | - this.type = type; | ||
55 | - this.id = id; | ||
56 | - } | ||
57 | - | ||
58 | - equals(other: ModelEvent) { | ||
59 | - return other.type.equals(this.type) && other.id === this.id; | ||
60 | - } | ||
61 | - | ||
62 | -} |
src/app/shared/models/index.ts
src/lib/ng-noosfero-api/http/article.service.spec.ts
@@ -25,6 +25,7 @@ describe("Services", () => { | @@ -25,6 +25,7 @@ describe("Services", () => { | ||
25 | $httpBackend.expectDELETE(`/api/v1/articles/${articleId}`).respond(200, { success: "true" }); | 25 | $httpBackend.expectDELETE(`/api/v1/articles/${articleId}`).respond(200, { success: "true" }); |
26 | articleService.removeArticle(<noosfero.Article>{id: articleId}); | 26 | articleService.removeArticle(<noosfero.Article>{id: articleId}); |
27 | $httpBackend.flush(); | 27 | $httpBackend.flush(); |
28 | + $httpBackend.verifyNoOutstandingExpectation(); | ||
28 | done(); | 29 | done(); |
29 | }); | 30 | }); |
30 | 31 |
src/lib/ng-noosfero-api/http/article.service.ts
@@ -2,21 +2,15 @@ import { Injectable, Inject, EventEmitter } from "ng-forward"; | @@ -2,21 +2,15 @@ import { Injectable, Inject, EventEmitter } from "ng-forward"; | ||
2 | import {RestangularService} from "./restangular_service"; | 2 | import {RestangularService} from "./restangular_service"; |
3 | import {ProfileService} from "./profile.service"; | 3 | import {ProfileService} from "./profile.service"; |
4 | import {NoosferoRootScope} from "./../../../app/shared/models/interfaces"; | 4 | import {NoosferoRootScope} from "./../../../app/shared/models/interfaces"; |
5 | -import {ModelEvent, ArticleEventType} from "./../../../app/shared/models/events"; | ||
6 | -import {HashMap} from "./../../../app/shared/utils/hashmap"; | ||
7 | 5 | ||
8 | @Injectable() | 6 | @Injectable() |
9 | @Inject("Restangular", "$q", "$log", ProfileService) | 7 | @Inject("Restangular", "$q", "$log", ProfileService) |
10 | export class ArticleService extends RestangularService<noosfero.Article> { | 8 | export class ArticleService extends RestangularService<noosfero.Article> { |
11 | 9 | ||
12 | - private events: HashMap<ModelEvent, EventEmitter<noosfero.Article>> = new HashMap<ModelEvent, EventEmitter<noosfero.Article>>(); | ||
13 | - | ||
14 | - // This event is not tyed to any specific model element. | ||
15 | - private removed: ModelEvent = ModelEvent.event(ArticleEventType.removed); | 10 | + private articleRemoved: EventEmitter<noosfero.Article> = new EventEmitter<noosfero.Article>(); |
16 | 11 | ||
17 | constructor(Restangular: restangular.IService, $q: ng.IQService, $log: ng.ILogService, protected profileService: ProfileService) { | 12 | constructor(Restangular: restangular.IService, $q: ng.IQService, $log: ng.ILogService, protected profileService: ProfileService) { |
18 | super(Restangular, $q, $log); | 13 | super(Restangular, $q, $log); |
19 | - this.events.put(this.removed, new EventEmitter<noosfero.Article>()); | ||
20 | } | 14 | } |
21 | 15 | ||
22 | getResourcePath() { | 16 | getResourcePath() { |
@@ -42,22 +36,17 @@ export class ArticleService extends RestangularService<noosfero.Article> { | @@ -42,22 +36,17 @@ export class ArticleService extends RestangularService<noosfero.Article> { | ||
42 | /** | 36 | /** |
43 | * Notify listeners that this article has been removed | 37 | * Notify listeners that this article has been removed |
44 | */ | 38 | */ |
45 | - notifyArticleRemovedListeners(article: noosfero.Article) { | ||
46 | - let listener = this.events.get(this.removed); | ||
47 | - listener.next(article); | 39 | + private notifyArticleRemovedListeners(article: noosfero.Article) { |
40 | + // let listener = this.events.get(this.removed); | ||
41 | + // listener.next(article); | ||
42 | + this.articleRemoved.next(article); | ||
48 | } | 43 | } |
49 | 44 | ||
50 | /** | 45 | /** |
51 | - * Subscribe a listener a given article event | ||
52 | - */ | ||
53 | - subscribe(eventToSubscribe: ModelEvent, fn: Function) { | ||
54 | - // Find the requested event in map | ||
55 | - let event: EventEmitter<noosfero.Article> = this.events.get(eventToSubscribe); | ||
56 | - if (event) { | ||
57 | - event.subscribe(fn); | ||
58 | - } else { | ||
59 | - throw new Error(`The event: ${eventToSubscribe} not exists`); | ||
60 | - } | 46 | + * subscribes to the ArticleRemoved event emitter |
47 | + */ | ||
48 | + subscribeToArticleRemoved(fn: Function) { | ||
49 | + this.articleRemoved.subscribe(fn); | ||
61 | } | 50 | } |
62 | 51 | ||
63 | updateArticle(article: noosfero.Article) { | 52 | updateArticle(article: noosfero.Article) { |
src/spec/mocks.ts
@@ -76,17 +76,20 @@ export var mocks: any = { | @@ -76,17 +76,20 @@ export var mocks: any = { | ||
76 | isAuthenticated: () => { } | 76 | isAuthenticated: () => { } |
77 | }, | 77 | }, |
78 | articleService: { | 78 | articleService: { |
79 | - events: [ | 79 | + articleRemovedFn: null, |
80 | + subscribeToArticleRemoved: (fn: Function) => { | ||
81 | + mocks.articleService.articleRemovedFn = fn; | ||
82 | + }, | ||
83 | + articleRemoved: | ||
80 | { | 84 | { |
81 | - event: Function, | ||
82 | subscribe: (fn: Function) => { | 85 | subscribe: (fn: Function) => { |
83 | - mocks.articleService.events[0].event = fn; | 86 | + mocks.articleService.articleRemovedFn = fn; |
84 | }, | 87 | }, |
85 | next: (param: any) => { | 88 | next: (param: any) => { |
86 | - mocks.articleService.events[0].event(param); | 89 | + mocks.articleService.articleRemovedFn(param); |
87 | } | 90 | } |
88 | } | 91 | } |
89 | - ], | 92 | + , |
90 | removeArticle: (article: noosfero.Article) => { | 93 | removeArticle: (article: noosfero.Article) => { |
91 | return { | 94 | return { |
92 | catch: (func?: Function) => { | 95 | catch: (func?: Function) => { |
@@ -94,10 +97,10 @@ export var mocks: any = { | @@ -94,10 +97,10 @@ export var mocks: any = { | ||
94 | }; | 97 | }; |
95 | }, | 98 | }, |
96 | notifyArticleRemovedListeners: (article: noosfero.Article) => { | 99 | notifyArticleRemovedListeners: (article: noosfero.Article) => { |
97 | - mocks.articleService.events[0].next(article); | 100 | + mocks.articleService.articleRemoved.next(article); |
98 | }, | 101 | }, |
99 | subscribe: (eventType: any, fn: Function) => { | 102 | subscribe: (eventType: any, fn: Function) => { |
100 | - mocks.articleService.events[0].subscribe(fn); | 103 | + mocks.articleService.articleRemoved.subscribe(fn); |
101 | }, | 104 | }, |
102 | getByProfile: (profileId: number, params?: any) => { | 105 | getByProfile: (profileId: number, params?: any) => { |
103 | return { | 106 | return { |