Commit 2259690d92c4ced0e7a5a8a08be67b27d8112932
1 parent
28d86107
Exists in
master
and in
27 other branches
Create article and associate it to parent
Showing
11 changed files
with
89 additions
and
20 deletions
Show diff stats
src/app/article/basic-editor.component.spec.ts
... | ... | @@ -9,6 +9,7 @@ describe("Article BasicEditor", () => { |
9 | 9 | let articleServiceMock: any; |
10 | 10 | let profileServiceMock: any; |
11 | 11 | let $state: any; |
12 | + let $stateParams: any; | |
12 | 13 | let profile = { id: 1 }; |
13 | 14 | let notification: any; |
14 | 15 | |
... | ... | @@ -20,9 +21,10 @@ describe("Article BasicEditor", () => { |
20 | 21 | |
21 | 22 | beforeEach(() => { |
22 | 23 | $state = jasmine.createSpyObj("$state", ["transitionTo"]); |
24 | + $stateParams = jasmine.createSpyObj("$stateParams", ["parent_id"]); | |
23 | 25 | notification = jasmine.createSpyObj("notification", ["success"]); |
24 | 26 | profileServiceMock = jasmine.createSpyObj("profileServiceMock", ["getCurrentProfile"]); |
25 | - articleServiceMock = jasmine.createSpyObj("articleServiceMock", ["createInProfile"]); | |
27 | + articleServiceMock = jasmine.createSpyObj("articleServiceMock", ["createInParent"]); | |
26 | 28 | |
27 | 29 | let getCurrentProfileResponse = $q.defer(); |
28 | 30 | getCurrentProfileResponse.resolve(profile); |
... | ... | @@ -31,20 +33,20 @@ describe("Article BasicEditor", () => { |
31 | 33 | articleCreate.resolve({ data: { path: "path", profile: { identifier: "profile" } } }); |
32 | 34 | |
33 | 35 | profileServiceMock.getCurrentProfile = jasmine.createSpy("getCurrentProfile").and.returnValue(getCurrentProfileResponse.promise); |
34 | - articleServiceMock.createInProfile = jasmine.createSpy("createInProfile").and.returnValue(articleCreate.promise); | |
36 | + articleServiceMock.createInParent = jasmine.createSpy("createInParent").and.returnValue(articleCreate.promise); | |
35 | 37 | }); |
36 | 38 | |
37 | 39 | it("create an article in the current profile when save", done => { |
38 | - let component: BasicEditorComponent = new BasicEditorComponent(articleServiceMock, profileServiceMock, $state, notification); | |
3 |
|
|
40 | + let component: BasicEditorComponent = new BasicEditorComponent(articleServiceMock, profileServiceMock, $state, notification, $stateParams); | |
39 | 41 | component.save(); |
40 | 42 | $rootScope.$apply(); |
41 | 43 | expect(profileServiceMock.getCurrentProfile).toHaveBeenCalled(); |
42 | - expect(articleServiceMock.createInProfile).toHaveBeenCalledWith(profile, component.article); | |
44 | + expect(articleServiceMock.createInParent).toHaveBeenCalledWith($stateParams.parent_id, component.article); | |
43 | 45 | done(); |
44 | 46 | }); |
45 | 47 | |
46 | 48 | it("got to the new article page and display an alert when saving sucessfully", done => { |
47 | - let component: BasicEditorComponent = new BasicEditorComponent(articleServiceMock, profileServiceMock, $state, notification); | |
49 | + let component: BasicEditorComponent = new BasicEditorComponent(articleServiceMock, profileServiceMock, $state, notification, $stateParams); | |
48 | 50 | component.save(); |
49 | 51 | $rootScope.$apply(); |
50 | 52 | expect($state.transitionTo).toHaveBeenCalledWith("main.profile.page", { page: "path", profile: "profile" }); | ... | ... |
src/app/article/basic-editor.component.ts
... | ... | @@ -12,19 +12,25 @@ import {NotificationService} from "../shared/services/notification.service.ts"; |
12 | 12 | provide('notification', { useClass: NotificationService }) |
13 | 13 | ] |
14 | 14 | }) |
15 | -@Inject(ArticleService, ProfileService, "$state", NotificationService) | |
15 | +@Inject(ArticleService, ProfileService, "$state", NotificationService, "$stateParams") | |
16 | 16 | export class BasicEditorComponent { |
17 | 17 | |
18 | 18 | article: noosfero.Article = <noosfero.Article>{}; |
19 | + parentId: number; | |
20 | + | |
21 | + editorOptions = {}; | |
19 | 22 | |
20 | 23 | constructor(private articleService: ArticleService, |
21 | 24 | private profileService: ProfileService, |
22 | 25 | private $state: ng.ui.IStateService, |
23 | - private notification: NotificationService) { } | |
26 | + private notification: NotificationService, | |
27 | + private $stateParams: ng.ui.IStateParamsService) { | |
28 | + this.parentId = this.$stateParams['parent_id']; | |
29 | + } | |
24 | 30 | |
25 | 31 | save() { |
26 | 32 | this.profileService.getCurrentProfile().then((profile: noosfero.Profile) => { |
27 | - return this.articleService.createInProfile(profile, this.article); | |
33 | + return this.articleService.createInParent(this.parentId, this.article); | |
28 | 34 | }).then((response: noosfero.RestResult<noosfero.Article>) => { |
29 | 35 | let article = (<noosfero.Article>response.data); |
30 | 36 | this.$state.transitionTo('main.profile.page', { page: article.path, profile: article.profile.identifier }); | ... | ... |
src/app/article/content-viewer/content-viewer-actions.component.spec.ts
... | ... | @@ -20,6 +20,9 @@ describe('Content Viewer Actions Component', () => { |
20 | 20 | return <any>[ |
21 | 21 | provide('ProfileService', { |
22 | 22 | useValue: helpers.mocks.profileService |
23 | + }), | |
24 | + provide('ArticleService', { | |
25 | + useValue: helpers.mocks.articleService | |
23 | 26 | }) |
24 | 27 | ]; |
25 | 28 | }); |
... | ... | @@ -44,6 +47,33 @@ describe('Content Viewer Actions Component', () => { |
44 | 47 | }); |
45 | 48 | }); |
46 | 49 | |
50 | + it('return article parent as container when it is not a folder', (done: Function) => { | |
51 | + buildComponent().then((fixture: ComponentFixture) => { | |
52 | + let component = fixture.debugElement.componentViewChildren[0].componentInstance; | |
2 |
|
|
53 | + let article = <noosfero.Article>({ id: 1, type: 'TextArticle', parent: { id: 2 } }); | |
54 | + expect(component.getArticleContainer(article)).toEqual(2); | |
55 | + done(); | |
56 | + }); | |
57 | + }); | |
58 | + | |
59 | + it('return article as container when it is a folder', (done: Function) => { | |
60 | + buildComponent().then((fixture: ComponentFixture) => { | |
61 | + let component = fixture.debugElement.componentViewChildren[0].componentInstance; | |
62 | + let article = <noosfero.Article>({ id: 1, type: 'Folder' }); | |
63 | + expect(component.getArticleContainer(article)).toEqual(1); | |
64 | + done(); | |
65 | + }); | |
66 | + }); | |
67 | + | |
68 | + it('return article as container when it is a blog', (done: Function) => { | |
69 | + buildComponent().then((fixture: ComponentFixture) => { | |
70 | + let component = fixture.debugElement.componentViewChildren[0].componentInstance; | |
71 | + let article = <noosfero.Article>({ id: 1, type: 'Blog' }); | |
72 | + expect(component.getArticleContainer(article)).toEqual(1); | |
73 | + done(); | |
74 | + }); | |
75 | + }); | |
76 | + | |
47 | 77 | it('check if profile was loaded', (done: Function) => { |
48 | 78 | let profile: any = { |
49 | 79 | id: 1, | ... | ... |
src/app/article/content-viewer/content-viewer-actions.component.ts
1 | 1 | import {Component, Inject, provide} from "ng-forward"; |
2 | 2 | import {ProfileService} from "../../../lib/ng-noosfero-api/http/profile.service"; |
3 | +import {ArticleService} from "../../../lib/ng-noosfero-api/http/article.service"; | |
3 | 4 | |
4 | 5 | @Component({ |
5 | 6 | selector: "content-viewer-actions", |
6 | 7 | templateUrl: "app/article/content-viewer/navbar-actions.html", |
7 | - providers: [provide('profileService', { useClass: ProfileService })] | |
8 | + providers: [ | |
9 | + provide('profileService', { useClass: ProfileService }), | |
3 |
|
|
10 | + provide('articleService', { useClass: ArticleService }) | |
11 | + ] | |
8 | 12 | }) |
9 | -@Inject(ProfileService) | |
13 | +@Inject(ProfileService, ArticleService) | |
10 | 14 | export class ContentViewerActionsComponent { |
11 | 15 | |
12 | 16 | article: noosfero.Article; |
13 | 17 | profile: noosfero.Profile; |
18 | + parentId: number; | |
14 | 19 | |
15 | - constructor(profileService: ProfileService) { | |
20 | + constructor(profileService: ProfileService, articleService: ArticleService) { | |
16 | 21 | profileService.getCurrentProfile().then((profile: noosfero.Profile) => { |
17 | 22 | this.profile = profile; |
23 | + return articleService.getCurrent(); | |
24 | + }).then((article: noosfero.Article) => { | |
25 | + this.article = article; | |
26 | + this.parentId = this.getArticleContainer(article); | |
18 | 27 | }); |
19 | 28 | } |
29 | + | |
30 | + getArticleContainer(article: noosfero.Article) { | |
31 | + // FIXME get folder types from api | |
32 | + if (article.type === "Blog" || article.type === "Folder") { | |
33 | + return article.id; | |
34 | + } else if (article.parent) { | |
35 | + return article.parent.id; | |
36 | + } | |
37 | + } | |
20 | 38 | } | ... | ... |
src/app/article/content-viewer/content-viewer.component.ts
... | ... | @@ -28,11 +28,12 @@ export class ContentViewerComponent { |
28 | 28 | } |
29 | 29 | |
30 | 30 | activate() { |
31 | - this.profileService.getCurrentProfile().then((profile: noosfero.Profile) => { | |
31 | + this.profileService.getCurrentProfile().then((profile: noosfero.Profile) => { | |
32 | 32 | this.profile = profile; |
33 | 33 | return this.articleService.getArticleByProfileAndPath(this.profile, this.$stateParams["page"]); |
34 | 34 | }).then((result: noosfero.RestResult<any>) => { |
35 | 35 | this.article = <noosfero.Article>result.data; |
36 | + this.articleService.setCurrent(this.article); | |
36 | 37 | }); |
37 | 38 | } |
38 | 39 | } | ... | ... |
src/app/article/content-viewer/navbar-actions.html
1 | 1 | <ul class="nav navbar-nav"> |
2 | 2 | <li ng-show="vm.profile"> |
3 | - <a href="#" role="button" ui-sref="main.profile.cms({profile: vm.profile.identifier})"> | |
3 | + <a ng-show="vm.parentId" href="#" role="button" ui-sref="main.profile.cms({profile: vm.profile.identifier, parent_id: vm.parentId})"> | |
4 | 4 | <i class="fa fa-file fa-fw fa-lg"></i> {{"navbar.content_viewer_actions.new_post" | translate}} |
5 | 5 | </a> |
6 | 6 | </li> | ... | ... |
src/app/profile/profile.component.ts
... | ... | @@ -46,7 +46,7 @@ import {MyProfileComponent} from "./myprofile.component"; |
46 | 46 | }, |
47 | 47 | { |
48 | 48 | name: 'main.profile.cms', |
49 | - url: "^/myprofile/:profile/cms", | |
49 | + url: "^/myprofile/:profile/cms?parent_id", | |
50 | 50 | component: BasicEditorComponent, |
51 | 51 | views: { |
52 | 52 | "mainBlockContent": { | ... | ... |
src/lib/ng-noosfero-api/http/article.service.ts
... | ... | @@ -32,6 +32,14 @@ export class ArticleService extends RestangularService<noosfero.Article> { |
32 | 32 | return this.create(article, <noosfero.RestModel>profileElement, null, headers); |
33 | 33 | } |
34 | 34 | |
35 | + createInParent(parentId: number, article: noosfero.Article): ng.IPromise<noosfero.RestResult<noosfero.Article>> { | |
36 | + let headers = { | |
37 | + 'Content-Type': 'application/json' | |
38 | + }; | |
39 | + | |
40 | + let parent = this.getElement(parentId); | |
41 | + return this.create(article, parent, null, headers, true, "children"); | |
42 | + } | |
35 | 43 | |
36 | 44 | getAsCollectionChildrenOf<C>(rootElement: noosfero.Environment | noosfero.Article | noosfero.Profile, path: string, queryParams?: any, headers?: any): restangular.ICollectionPromise<C> { |
37 | 45 | return rootElement.getList<C>(path, queryParams, headers); | ... | ... |
src/lib/ng-noosfero-api/http/restangular_service.ts
... | ... | @@ -236,7 +236,7 @@ export abstract class RestangularService<T extends noosfero.RestModel> { |
236 | 236 | * Creates a new Resource into the resource collection |
237 | 237 | * calls POST /resourcePath |
238 | 238 | */ |
239 | - public create(obj: T, rootElement?: noosfero.RestModel, queryParams?: any, headers?: any, isSub: boolean = true): ng.IPromise<noosfero.RestResult<T>> { | |
239 | + public create(obj: T, rootElement?: noosfero.RestModel, queryParams?: any, headers?: any, isSub: boolean = true, path?: string): ng.IPromise<noosfero.RestResult<T>> { | |
240 | 240 | let deferred = this.$q.defer<noosfero.RestResult<T>>(); |
241 | 241 | |
242 | 242 | let restRequest: ng.IPromise<noosfero.RestResult<T>>; |
... | ... | @@ -248,8 +248,9 @@ export abstract class RestangularService<T extends noosfero.RestModel> { |
248 | 248 | data = obj; |
249 | 249 | } |
250 | 250 | |
251 | + let subpath = path || this.getResourcePath(); | |
251 | 252 | if (rootElement) { |
252 | - restRequest = rootElement.all(this.getResourcePath()).post(data, queryParams, headers); | |
253 | + restRequest = rootElement.all(subpath).post(data, queryParams, headers); | |
253 | 254 | } else { |
254 | 255 | restRequest = this.baseResource.post(data, queryParams, headers); |
255 | 256 | } | ... | ... |
src/lib/ng-noosfero-api/interfaces/article.ts
src/spec/mocks.ts
1 | 1 | const DEBUG = false; |
2 | 2 | |
3 | -let log = (message: string, ...args: any[]) => { | |
3 | +let log = (message: string, ...args: any[]) => { | |
4 | 4 | if (DEBUG) { |
5 | 5 | console.log(message); |
6 | 6 | } |
... | ... | @@ -70,7 +70,9 @@ export var mocks = { |
70 | 70 | return { |
71 | 71 | then: (func?: Function) => { if (func) func(); } |
72 | 72 | }; |
73 | - } | |
73 | + }, | |
74 | + setCurrent: (article: noosfero.Article) => { }, | |
75 | + getCurrent: () => { return Promise.resolve({}); } | |
74 | 76 | }, |
75 | 77 | environmentService: { |
76 | 78 | getEnvironmentPeople: (params: any) => { | ... | ... |