Commit 9e3a58f8acfe2bd0dee59401bf8b84e8e4ccb875

Authored by Ábner Oliveira
1 parent eef070ef
Exists in master and in 1 other branch dev-fixes

changes on article service

src/app/cms/cms.component.spec.ts
... ... @@ -26,7 +26,7 @@ describe("Components", () => {
26 26 getCurrentProfileResponse.resolve({ id: 1 });
27 27  
28 28 let articleCreate = $q.defer();
29   - articleCreate.resolve({ data: { article: { path: "path", profile: { identifier: "profile" } } } });
  29 + articleCreate.resolve({ path: "path", profile: { identifier: "profile" } });
30 30  
31 31 profileServiceMock.getCurrentProfile = jasmine.createSpy("getCurrentProfile").and.returnValue(getCurrentProfileResponse.promise);
32 32 articleServiceMock.create = jasmine.createSpy("create").and.returnValue(articleCreate.promise);
... ...
src/app/cms/cms.component.ts
... ... @@ -23,8 +23,8 @@ export class Cms {
23 23 save() {
24 24 this.profileService.getCurrentProfile().then((profile: Profile) => {
25 25 return this.articleService.create(profile.id, this.article);
26   - }).then((response: restangular.IResponse) => {
27   - this.$state.transitionTo('main.profile.page', { page: response.data.article.path, profile: response.data.article.profile.identifier });
  26 + }).then((article: noosfero.Article) => {
  27 + this.$state.transitionTo('main.profile.page', { page: article.path, profile: article.profile.identifier });
28 28 this.SweetAlert.swal({
29 29 title: "Good job!",
30 30 text: "Article saved!",
... ...
src/app/components/noosfero-articles/blog/blog.component.spec.ts
1 1 import {
2   - providers
  2 +providers
3 3 } from 'ng-forward/cjs/testing/providers';
4 4  
5 5 import {
6   - Input,
7   - Component
  6 +Input,
  7 +Component
8 8 } from 'ng-forward';
9 9 import {
10   - ArticleBlog
  10 +ArticleBlog
11 11 } from './blog.component';
12 12  
13 13 import {
14   - createComponentFromClass,
15   - quickCreateComponent,
16   - provideEmptyObjects,
17   - createProviderToValue,
18   - provideFilters
  14 +createComponentFromClass,
  15 +quickCreateComponent,
  16 +provideEmptyObjects,
  17 +createProviderToValue,
  18 +provideFilters
19 19 } from "../../../../spec/helpers.ts";
20 20  
21 21 // this htmlTemplate will be re-used between the container components in this spec file
... ... @@ -23,7 +23,7 @@ const htmlTemplate: string = '<noosfero-blog [article]="ctrl.article" [profile]=
23 23  
24 24 describe("Blog Component", () => {
25 25  
26   - function promiseResultTemplate(response ? : {}) {
  26 + function promiseResultTemplate(response?: {}) {
27 27 let thenFuncEmpty = (func: Function) => {
28 28 // does nothing
29 29 };
... ... @@ -76,7 +76,7 @@ describe("Blog Component", () => {
76 76 angular.mock.module("templates")
77 77  
78 78 providers((provide: any) => {
79   - return <any > [
  79 + return <any>[
80 80 provide('ArticleService', {
81 81 useValue: articleService
82 82 })
... ... @@ -96,19 +96,16 @@ describe(&quot;Blog Component&quot;, () =&gt; {
96 96  
97 97 it("verify the blog data", (done: Function) => {
98 98  
  99 + let articles = [{
  100 + id: 1,
  101 + title: 'The article test'
  102 + }];
  103 +
  104 + (<any>articles)['_headers'] = { total: 1 };
  105 +
99 106 // defining a mock result to articleService.getChildren method
100 107 articleService.getChildren = (article_id: number, filters: {}) => {
101   - return promiseResultTemplate({
102   - headers: (headerName: string) => {
103   - return 1;
104   - },
105   - data: < any > {
106   - articles: [{
107   - id: 1,
108   - title: 'The article test'
109   - }]
110   - }
111   - });
  108 + return promiseResultTemplate(articles);
112 109 };
113 110  
114 111 createComponentFromClass(BlogContainerComponent).then((fixture) => {
... ... @@ -121,8 +118,8 @@ describe(&quot;Blog Component&quot;, () =&gt; {
121 118 id: 1,
122 119 title: 'The article test'
123 120 };
124   - expect(( < any > articleBlog)["posts"][0]).toEqual(jasmine.objectContaining(post));
125   - expect(( < any > articleBlog)["totalPosts"]).toEqual(1);
  121 + expect((<any>articleBlog)["posts"][0]).toEqual(jasmine.objectContaining(post));
  122 + expect((<any>articleBlog)["totalPosts"]).toEqual(1);
126 123  
127 124 done();
128 125 });
... ...
src/app/components/noosfero-articles/blog/blog.component.ts
... ... @@ -33,9 +33,9 @@ export class ArticleBlog {
33 33  
34 34 this.articleService
35 35 .getChildren(this.article.id, filters)
36   - .then((response: restangular.IResponse) => {
37   - this.totalPosts = <number>(<any>response.headers("total"));
38   - this.posts = response.data.articles;
  36 + .then((articles: noosfero.Article[]) => {
  37 + this.totalPosts = <number>(<any>articles)["_headers"]["total"];
  38 + this.posts = articles;
39 39 });
40 40 }
41 41  
... ...
src/lib/ng-noosfero-api/http/article.service.spec.ts
... ... @@ -24,8 +24,8 @@ describe(&quot;Services&quot;, () =&gt; {
24 24 it("should return article children", (done) => {
25 25 let articleId = 1;
26 26 $httpBackend.expectGET(`/api/v1/articles/${articleId}/children`).respond(200, { articles: [{ name: "article1" }] });
27   - articleService.getChildren(articleId).then((response: restangular.IResponse) => {
28   - expect(response.data.articles).toEqual([{ name: "article1" }]);
  27 + articleService.getChildren<noosfero.ArticlesResult>(articleId).then((result: noosfero.ArticlesResult) => {
  28 + expect(result.articles).toEqual([{ name: "article1" }]);
29 29 done();
30 30 });
31 31 $httpBackend.flush();
... ... @@ -34,8 +34,8 @@ describe(&quot;Services&quot;, () =&gt; {
34 34 it("should get articles by profile", (done) => {
35 35 let profileId = 1;
36 36 $httpBackend.expectGET(`/api/v1/profiles/${profileId}/articles`).respond(200, { articles: [{ name: "article1" }] });
37   - articleService.getByProfile(profileId).then((response: restangular.IResponse) => {
38   - expect(response.data.articles).toEqual([{ name: "article1" }]);
  37 + articleService.getByProfile<noosfero.ArticlesResult>(profileId).then((result: noosfero.ArticlesResult) => {
  38 + expect(result.articles).toEqual([{ name: "article1" }]);
39 39 done();
40 40 });
41 41 $httpBackend.flush();
... ... @@ -44,8 +44,8 @@ describe(&quot;Services&quot;, () =&gt; {
44 44 it("should get articles by profile with additional filters", (done) => {
45 45 let profileId = 1;
46 46 $httpBackend.expectGET(`/api/v1/profiles/${profileId}/articles?path=test`).respond(200, { articles: [{ name: "article1" }] });
47   - articleService.getByProfile(profileId, { path: 'test' }).then((response: restangular.IResponse) => {
48   - expect(response.data.articles).toEqual([{ name: "article1" }]);
  47 + articleService.getByProfile<noosfero.ArticlesResult>(profileId, { path: 'test' }).then((result: noosfero.ArticlesResult) => {
  48 + expect(result.articles).toEqual([{ name: "article1" }]);
49 49 done();
50 50 });
51 51 $httpBackend.flush();
... ... @@ -54,8 +54,8 @@ describe(&quot;Services&quot;, () =&gt; {
54 54 it("should get article children with additional filters", (done) => {
55 55 let articleId = 1;
56 56 $httpBackend.expectGET(`/api/v1/articles/${articleId}/children?path=test`).respond(200, { articles: [{ name: "article1" }] });
57   - articleService.getChildren(articleId, { path: 'test' }).then((response: restangular.IResponse) => {
58   - expect(response.data.articles).toEqual([{ name: "article1" }]);
  57 + articleService.getChildren<noosfero.ArticlesResult>(articleId, { path: 'test' }).then((result: noosfero.ArticlesResult) => {
  58 + expect(result.articles).toEqual([{ name: "article1" }]);
59 59 done();
60 60 });
61 61 $httpBackend.flush();
... ... @@ -63,10 +63,10 @@ describe(&quot;Services&quot;, () =&gt; {
63 63  
64 64 it("should create an article in a profile", (done) => {
65 65 let profileId = 1;
66   - let article: Article = { id: null };
67   - $httpBackend.expectPOST(`/api/v1/profiles/${profileId}/articles`, { article: article }).respond(200, { articles: [{ id: 2 }] });
68   - articleService.create(profileId, article).then((response: restangular.IResponse) => {
69   - expect(response.data.articles).toEqual([{ id: 2 }]);
  66 + let article: noosfero.Article = <any>{ id: null};
  67 + $httpBackend.expectPOST(`/api/v1/profiles/${profileId}/articles`, { article: article }).respond(200, { id: 2 });
  68 + articleService.create(profileId, article).then((result: noosfero.Article) => {
  69 + expect(article).toEqual({ id: 2 });
70 70 done();
71 71 });
72 72 $httpBackend.flush();
... ...
src/lib/ng-noosfero-api/http/article.service.ts
1 1 import { Injectable, Inject } from "ng-forward";
2   -import {Article} from "../../../app/models/interfaces";
3   -
  2 +import {RestangularWrapperService} from "./restangular_wrapper_service";
4 3 @Injectable()
5 4 @Inject("Restangular", "$q")
6 5  
  6 +export class ArticleService extends RestangularWrapperService<noosfero.Article> {
7 7  
8   -export class ArticleService {
  8 + constructor(Restangular: restangular.IService, $q: ng.IQService, $log: ng.ILogService) {
  9 + super(Restangular, $q, $log);
  10 + }
9 11  
10   - constructor(private Restangular: restangular.IService, private $q: ng.IQService, private $log: ng.ILogService) { }
  12 + getPath() {
  13 + return "articles";
  14 + }
11 15  
12   - create(profileId: number, article: Article) {
13   - return this.Restangular.one('profiles', profileId).customPOST(
14   - { article: article },
15   - 'articles',
16   - {},
17   - { 'Content-Type': 'application/json' }
18   - );
  16 + getDataKeys() {
  17 + return {
  18 + singular: 'article',
  19 + plural: 'articles'
  20 + }
19 21 }
20 22  
21   - // TODO create a handle ErrorFactory too and move handleSuccessFactory and handleErrorFactory
22   - // to a base class (of course we will have to creates a base class too)
23   - handleSuccessFactory<T>(deferred: ng.IDeferred<T>): (response: restangular.IResponse) => void {
24   - let self = this;
25   - let successFunction = (response: restangular.IResponse): void => {
26   - this.$log.debug("Request successfull executed", this, response);
27   - deferred.resolve(response.data);
28   - };
29   - return successFunction;
  23 + create(profileId: number, article: noosfero.Article): ng.IPromise<noosfero.Article> {
  24 + return this.post(this.Restangular.one('profiles', profileId), article);
30 25 }
31 26  
  27 + // // TODO create a handle ErrorFactory too and move handleSuccessFactory and handleErrorFactory
  28 + // // to a base class (of course we will have to creates a base class too)
  29 + // handleSuccessFactory<T>(deferred: ng.IDeferred<T>): (response: restangular.IResponse) => void {
  30 + // let self = this;
  31 + // let successFunction = (response: restangular.IResponse): void => {
  32 + // this.$log.debug("Request successfull executed", self, response);
  33 + // deferred.resolve(response.data);
  34 + // };
  35 + // return successFunction;
  36 + // }
  37 + //
  38 + // handleErrorFactory<T>(deferred: ng.IDeferred<T>): (response: restangular.IResponse) => void {
  39 + // let self = this;
  40 + // let successFunction = (response: restangular.IResponse): void => {
  41 + // this.$log.error("Error executing request", self, response);
  42 + // deferred.reject(response.data);
  43 + // };
  44 + // return successFunction;
  45 + // }
  46 +
32 47 // TODO -> change all Restangular services to this approach "Return promise to a specific type"
33 48 // it makes easy consume the service
34 49 getByProfile<T>(profileId: number, params?: any): ng.IPromise<T> {
35 50 let deferred = this.$q.defer<T>();
36   - this.Restangular.one('profiles', profileId).customGET('articles', params).then(this.handleSuccessFactory(deferred));
  51 + this.Restangular.one('profiles', profileId).customGET('articles', params)
  52 + .then(this.getHandleSuccessFunction<T>(deferred, 'articles'))
  53 + .catch(this.getHandleErrorFunction(deferred));
37 54 return deferred.promise;
38 55 }
39 56  
40   - getChildren(articleId: number, params?: any) {
41   - return this.get(articleId).customGET('children', params);
42   - }
  57 + getChildren<T>(articleId: number, params?: any): ng.IPromise<T> {
  58 + let deferred = this.$q.defer<T>();
  59 +
  60 + this.get(articleId).customGET('children', params)
  61 + .then(this.getHandleSuccessFunction<T>(deferred, 'articles').bind(this))
  62 + .catch(this.getHandleErrorFunction(deferred));
43 63  
44   - private get(articleId: number) {
45   - return this.Restangular.one('articles', articleId);
  64 + return deferred.promise;
46 65 }
47 66  
  67 +
  68 +
48 69 }
... ...
src/lib/ng-noosfero-api/http/http_client.ts
... ... @@ -1,11 +0,0 @@
1   -namespace NgNoosferoAPI {
2   - export class NoosferoHttpClient {
3   - static $inject = ['$http', '$q'];
4   -
5   - constructor(private $http: ng.IHttpService, private $q: ng.IQService) {
6   -
7   - }
8   - }
9   -
10   - NgNoosferoAPI.ngModule.service(NoosferoHttpClient);
11   -}
12 0 \ No newline at end of file
src/lib/ng-noosfero-api/http/rest.decorator.ts 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +namespace noosfero.http {
  2 + export function Rest(config: {
  3 + path: string
  4 + }
  5 + ): Function {
  6 + let path = config.path;
  7 + return (t: Function) => {
  8 + if (!path) {
  9 + throw new Error(`Rest decorator error in ${(<any>t).name}. Rest path should be provided`);
  10 + }
  11 + t.prototype.getPath = function() {
  12 + return path;
  13 + };
  14 + };
  15 + }
  16 +}
0 17 \ No newline at end of file
... ...
src/lib/ng-noosfero-api/http/restangular_wrapper_service.ts 0 → 100644
... ... @@ -0,0 +1,80 @@
  1 +export abstract class RestangularWrapperService<T> {
  2 +
  3 + private lastResponse: restangular.IResponse;
  4 + constructor(protected Restangular: restangular.IService, protected $q: ng.IQService, protected $log: ng.ILogService) {
  5 +
  6 + }
  7 +
  8 + protected abstract getPath(): string;
  9 +
  10 + protected abstract getDataKeys(): { singular: string, plural: string };
  11 +
  12 + protected get(id: number): restangular.IElement {
  13 + return this.Restangular.one(this.getPath(), id);
  14 + }
  15 +
  16 + protected post(elementRoot: restangular.IElement, element?: any, path?: string, params?: any, headers?: any): ng.IPromise<T> {
  17 + let deferred = this.$q.defer<T>();
  18 +
  19 + this.customPOST(
  20 + elementRoot,
  21 + element,
  22 + this.getPath(),
  23 + {}
  24 + )
  25 + .then(this.getHandleSuccessFunction(deferred))
  26 + .catch(this.getHandleErrorFunction(deferred));
  27 +
  28 + return deferred.promise;
  29 + }
  30 +
  31 + protected customPOST(elementRoot: restangular.IElement, elem?: any, path?: string, params?: any, headers?: any) {
  32 + if (headers) {
  33 + headers['Content-Type'] = 'application/json';
  34 + } else {
  35 + headers = { 'Content-Type': 'application/json' };
  36 + }
  37 + return elementRoot.customPOST(elem, path, params, headers);
  38 + }
  39 +
  40 + // TODO create a handle ErrorFactory too and move handleSuccessFactory and handleErrorFactory
  41 + // to a base class (of course we will have to creates a base class too)
  42 + getHandleSuccessFunction<C>(deferred: ng.IDeferred<C>, responseKey?: string): (response: restangular.IResponse) => void {
  43 + let self = this;
  44 + let successFunction = (response: restangular.IResponse): void => {
  45 + if (self.$log) {
  46 + self.$log.debug("Request successfull executed", self, response);
  47 + }
  48 + let data = response.data;
  49 +
  50 + let dataKey: string;
  51 +
  52 + if (data && self.getDataKeys()) {
  53 + if ((<Object>data).hasOwnProperty(self.getDataKeys().singular)) {
  54 + data = data[self.getDataKeys().singular];
  55 + dataKey = self.getDataKeys().singular;
  56 + } else if ((<Object>data).hasOwnProperty(self.getDataKeys().plural)) {
  57 + data = data[self.getDataKeys().plural];
  58 + dataKey = self.getDataKeys().plural;
  59 + }
  60 + }
  61 +
  62 + let result: any = {};
  63 + result[dataKey] = data;
  64 + result.headers = response.headers;
  65 + deferred.resolve(result);
  66 + };
  67 + return successFunction;
  68 + }
  69 +
  70 + getHandleErrorFunction<T>(deferred: ng.IDeferred<T>): (response: restangular.IResponse) => void {
  71 + let self = this;
  72 + let successFunction = (response: restangular.IResponse): void => {
  73 + if (self.$log) {
  74 + self.$log.error("Error executing request", self, response);
  75 + }
  76 + deferred.reject(response);
  77 + };
  78 + return successFunction;
  79 + }
  80 +}
... ...
src/lib/ng-noosfero-api/interfaces/article.ts
1 1  
2 2 namespace noosfero {
3   - interface Article {
  3 + export interface Article {
4 4 id: number;
  5 + path: string;
  6 + profile: Profile;
5 7 }
6 8 }
7 9 \ No newline at end of file
... ...
src/lib/ng-noosfero-api/interfaces/articles_result.ts 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +
  2 +namespace noosfero {
  3 + export interface ArticlesResult {
  4 + articles: Article[];
  5 + headers: Function;
  6 + }
  7 +
  8 + export interface ArticleResult {
  9 + article: Article;
  10 + headers: Function;
  11 + }
  12 +}
0 13 \ No newline at end of file
... ...