Commit d14121298f31300970fed97c1216414bbcdb5037
Exists in
master
and in
1 other branch
Merge branch 'ngforward' of softwarepublico.gov.br:noosfero-themes/angular-theme into ngforward
Showing
261 changed files
with
3984 additions
and
3345 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 261 files displayed.
.vscode/settings.json
... | ... | @@ -0,0 +1,13 @@ |
1 | +let replace = require("replace"); | |
2 | + | |
3 | +import * as path from "path"; | |
4 | + | |
5 | +let wrong_jqlite_d_ts_file = path.join(__dirname, "../node_modules/ng-forward/cjs/util/jqlite-extensions.d.ts"); | |
6 | + | |
7 | +replace({ | |
8 | + regex: /import JQuery from \".\/\";/, | |
9 | + replacement: "", | |
10 | + paths: [wrong_jqlite_d_ts_file], | |
11 | + sillent: false | |
12 | +}); | |
13 | + | ... | ... |
package.json
... | ... | @@ -4,21 +4,23 @@ |
4 | 4 | "dependencies": { |
5 | 5 | "angular": "^1.5.0", |
6 | 6 | "angular-mock": "^1.0.0", |
7 | - "moment": "^2.11.2" | |
7 | + "moment": "^2.11.2", | |
8 | + "ng-forward": "0.0.1-alpha.12" | |
8 | 9 | }, |
9 | 10 | "scripts": { |
10 | 11 | "build": "webpack; gulp build", |
11 | 12 | "webpack": "webpack", |
13 | + "karma": "concurrently \"webpack -w\" \"karma start\"", | |
12 | 14 | "docs": "gulp ngdocs; static-server docs", |
13 | - "karma": "karma", | |
14 | 15 | "coverage": "karma start --single-run; npm run remap-coverage", |
15 | 16 | "remap-coverage": "ts-node --project ./dev-scripts ./dev-scripts/remapCoverage.ts", |
16 | 17 | "test-single": "karma start --single-run", |
17 | 18 | "test-and-coverage": "karma start & npm run remap-coverage", |
18 | 19 | "test": "webpack -w --test", |
19 | - "postinstall": "npm install -g bower && bower install && typings install && cd dev-scripts && typings install", | |
20 | + "postinstall": "npm install -g bower; bower install; typings install; npm run fix-jqlite; cd dev-scripts; typings install", | |
20 | 21 | "start": "concurrently \"webpack -w\" \"gulp serve\"", |
21 | - "generate-indexes": "ts-node --project ./dev-scripts ./dev-scripts/generate-index-modules.ts" | |
22 | + "generate-indexes": "ts-node --project ./dev-scripts ./dev-scripts/generate-index-modules.ts", | |
23 | + "fix-jqlite": "ts-node --project ./dev-scripts dev-scripts/fix-jqlite.ts" | |
22 | 24 | }, |
23 | 25 | "devDependencies": { |
24 | 26 | "browser-sync": "~2.9.11", |
... | ... | @@ -71,7 +73,6 @@ |
71 | 73 | "karma-webpack": "^1.7.0", |
72 | 74 | "lodash": "~3.10.1", |
73 | 75 | "main-bower-files": "~2.9.0", |
74 | - "ng-forward": "0.0.1-alpha.12", | |
75 | 76 | "on-build-webpack": "^0.1.0", |
76 | 77 | "phantomjs": "~1.9.18", |
77 | 78 | "phantomjs-polyfill": "0.0.2", | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +/* Module Index Entry - generated using the script npm run generate-index */ | ... | ... |
... | ... | @@ -0,0 +1,108 @@ |
1 | + | |
2 | +import {Input, provide, Component} from 'ng-forward'; | |
3 | +import {ArticleViewComponent, ArticleDefaultViewComponent} from './article-default-view.component'; | |
4 | + | |
5 | +import {createComponentFromClass, quickCreateComponent} from "../../spec/helpers"; | |
6 | + | |
7 | +// this htmlTemplate will be re-used between the container components in this spec file | |
8 | +const htmlTemplate: string = '<noosfero-article [article]="ctrl.article" [profile]="ctrl.profile"></noosfero-article>'; | |
9 | + | |
10 | + | |
11 | +describe("Components", () => { | |
12 | + | |
13 | + describe("ArticleView Component", () => { | |
14 | + | |
15 | + // the karma preprocessor html2js transform the templates html into js files which put | |
16 | + // the templates to the templateCache into the module templates | |
17 | + // we need to load the module templates here as the template for the | |
18 | + // component Noosfero ArtileView will be load on our tests | |
19 | + beforeEach(angular.mock.module("templates")); | |
20 | + | |
21 | + it("renders the default component when no specific component is found", (done: Function) => { | |
22 | + // Creating a container component (ArticleContainerComponent) to include | |
23 | + // the component under test (ArticleView) | |
24 | + @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleViewComponent] }) | |
25 | + class ArticleContainerComponent { | |
26 | + article = { type: 'anyArticleType' }; | |
27 | + profile = { name: 'profile-name' }; | |
28 | + constructor() { | |
29 | + } | |
30 | + } | |
31 | + | |
32 | + createComponentFromClass(ArticleContainerComponent).then((fixture) => { | |
33 | + // and here we can inspect and run the test assertions | |
34 | + | |
35 | + // gets the children component of ArticleContainerComponent | |
36 | + let articleView: ArticleViewComponent = fixture.debugElement.componentViewChildren[0].componentInstance; | |
37 | + | |
38 | + // and checks if the article View rendered was the Default Article View | |
39 | + expect(articleView.constructor.prototype).toEqual(ArticleDefaultViewComponent.prototype); | |
40 | + | |
41 | + // done needs to be called (it isn't really needed, as we can read in | |
42 | + // here (https://github.com/ngUpgraders/ng-forward/blob/master/API.md#createasync) | |
43 | + // because createAsync in ng-forward is not really async, but as the intention | |
44 | + // here is write tests in angular 2 ways, this is recommended | |
45 | + done(); | |
46 | + }); | |
47 | + | |
48 | + }); | |
49 | + | |
50 | + it("receives the article and profile as inputs", (done: Function) => { | |
51 | + | |
52 | + // Creating a container component (ArticleContainerComponent) to include | |
53 | + // the component under test (ArticleView) | |
54 | + @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleViewComponent] }) | |
55 | + class ArticleContainerComponent { | |
56 | + article = { type: 'anyArticleType' }; | |
57 | + profile = { name: 'profile-name' }; | |
58 | + constructor() { | |
59 | + } | |
60 | + } | |
61 | + | |
62 | + // uses the TestComponentBuilder instance to initialize the component | |
63 | + createComponentFromClass(ArticleContainerComponent).then((fixture) => { | |
64 | + // and here we can inspect and run the test assertions | |
65 | + let articleView: ArticleViewComponent = fixture.debugElement.componentViewChildren[0].componentInstance; | |
66 | + | |
67 | + // assure the article object inside the ArticleView matches | |
68 | + // the provided through the parent component | |
69 | + expect(articleView.article.type).toEqual("anyArticleType"); | |
70 | + expect(articleView.profile.name).toEqual("profile-name"); | |
71 | + | |
72 | + // done needs to be called (it isn't really needed, as we can read in | |
73 | + // here (https://github.com/ngUpgraders/ng-forward/blob/master/API.md#createasync) | |
74 | + // because createAsync in ng-forward is not really async, but as the intention | |
75 | + // here is write tests in angular 2 ways, this is recommended | |
76 | + done(); | |
77 | + }); | |
78 | + }); | |
79 | + | |
80 | + | |
81 | + it("renders a article view which matches to the article type", done => { | |
82 | + // NoosferoTinyMceArticle component created to check if it will be used | |
83 | + // when a article with type 'TinyMceArticle' is provided to the noosfero-article (ArticleView) | |
84 | + // *** Important *** - the selector is what ng-forward uses to define the name of the directive provider | |
85 | + @Component({ selector: 'noosfero-tiny-mce-article', template: "<h1>TinyMceArticle</h1>" }) | |
86 | + class TinyMceArticleView { | |
87 | + @Input() article: any; | |
88 | + @Input() profile: any; | |
89 | + } | |
90 | + | |
91 | + // Creating a container component (ArticleContainerComponent) to include our NoosferoTinyMceArticle | |
92 | + @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleViewComponent, TinyMceArticleView] }) | |
93 | + class CustomArticleType { | |
94 | + article = { type: 'TinyMceArticle' }; | |
95 | + profile = { name: 'profile-name' }; | |
96 | + constructor() { | |
97 | + } | |
98 | + } | |
99 | + createComponentFromClass(CustomArticleType).then(fixture => { | |
100 | + let myComponent: CustomArticleType = fixture.componentInstance; | |
101 | + expect(myComponent.article.type).toEqual("TinyMceArticle"); | |
102 | + expect(fixture.debugElement.componentViewChildren[0].text()).toEqual("TinyMceArticle"); | |
103 | + done(); | |
104 | + }); | |
105 | + }); | |
106 | + | |
107 | + }); | |
108 | +}); | |
0 | 109 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,57 @@ |
1 | +import { bundle, Input, Inject, Component, Directive } from 'ng-forward'; | |
2 | +import {ArticleBlogComponent} from "./types/blog/blog.component"; | |
3 | + | |
4 | +/** | |
5 | + * @ngdoc controller | |
6 | + * @name ArticleDefaultView | |
7 | + * @description | |
8 | + * A default view for Noosfero Articles. If the specific article view is | |
9 | + * not implemented, then this view is used. | |
10 | + */ | |
11 | +@Component({ | |
12 | + selector: 'noosfero-default-article', | |
13 | + templateUrl: 'app/article/article.html' | |
14 | +}) | |
15 | +export class ArticleDefaultViewComponent { | |
16 | + | |
17 | + @Input() article: noosfero.Article; | |
18 | + @Input() profile: noosfero.Profile; | |
19 | + | |
20 | +} | |
21 | + | |
22 | +/** | |
23 | + * @ngdoc controller | |
24 | + * @name ArticleView | |
25 | + * @description | |
26 | + * A dynamic view for articles. It uses the article type to replace | |
27 | + * the default template with the custom article directive. | |
28 | + */ | |
29 | +@Component({ | |
30 | + selector: 'noosfero-article', | |
31 | + template: 'not-used', | |
32 | + directives: [ArticleDefaultViewComponent, ArticleBlogComponent] | |
33 | +}) | |
34 | +@Inject("$element", "$scope", "$injector", "$compile") | |
35 | +export class ArticleViewComponent { | |
36 | + | |
37 | + @Input() article: noosfero.Article; | |
38 | + @Input() profile: noosfero.Profile; | |
39 | + directiveName: string; | |
40 | + | |
41 | + ngOnInit() { | |
42 | + let specificDirective = 'noosfero' + this.article.type; | |
43 | + this.directiveName = "noosfero-default-article"; | |
44 | + if (this.$injector.has(specificDirective + 'Directive')) { | |
45 | + this.directiveName = specificDirective.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); | |
46 | + } | |
47 | + this.$element.replaceWith(this.$compile('<' + this.directiveName + ' [article]="ctrl.article" [profile]="ctrl.profile"></' + this.directiveName + '>')(this.$scope)); | |
48 | + } | |
49 | + | |
50 | + constructor( | |
51 | + private $element: any, | |
52 | + private $scope: ng.IScope, | |
53 | + private $injector: ng.auto.IInjectorService, | |
54 | + private $compile: ng.ICompileService) { | |
55 | + | |
56 | + } | |
57 | +} | ... | ... |
... | ... | @@ -0,0 +1,23 @@ |
1 | +<div class="article"> | |
2 | + <div class="page-header"> | |
3 | + <h3 ng-bind="ctrl.article.title"></h3> | |
4 | + </div> | |
5 | + | |
6 | + <div class="sub-header clearfix"> | |
7 | + <div class="page-info pull-right small text-muted"> | |
8 | + <span class="time"> | |
9 | + <i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.article.created_at | dateFormat"></span> | |
10 | + </span> | |
11 | + <span class="author" ng-if="ctrl.article.author"> | |
12 | + <i class="fa fa-user"></i> | |
13 | + <a ui-sref="main.profile.home({profile: ctrl.article.author.identifier})"> | |
14 | + <span class="author-name" ng-bind="ctrl.article.author.name"></span> | |
15 | + </a> | |
16 | + </span> | |
17 | + </div> | |
18 | + </div> | |
19 | + | |
20 | + <div class="page-body"> | |
21 | + <div ng-bind-html="ctrl.article.body"></div> | |
22 | + </div> | |
23 | +</div> | ... | ... |
... | ... | @@ -0,0 +1,55 @@ |
1 | +import {quickCreateComponent} from "../../spec/helpers"; | |
2 | +import {BasicEditorComponent} from "./basic-editor.component"; | |
3 | + | |
4 | + | |
5 | +describe("Article BasicEditor", () => { | |
6 | + | |
7 | + let $rootScope: ng.IRootScopeService; | |
8 | + let $q: ng.IQService; | |
9 | + let articleServiceMock: any; | |
10 | + let profileServiceMock: any; | |
11 | + let $state: any; | |
12 | + let profile = { id: 1 }; | |
13 | + let notification: any; | |
14 | + | |
15 | + | |
16 | + beforeEach(inject((_$rootScope_: ng.IRootScopeService, _$q_: ng.IQService) => { | |
17 | + $rootScope = _$rootScope_; | |
18 | + $q = _$q_; | |
19 | + })); | |
20 | + | |
21 | + beforeEach(() => { | |
22 | + $state = jasmine.createSpyObj("$state", ["transitionTo"]); | |
23 | + notification = jasmine.createSpyObj("notification", ["success"]); | |
24 | + profileServiceMock = jasmine.createSpyObj("profileServiceMock", ["getCurrentProfile"]); | |
25 | + articleServiceMock = jasmine.createSpyObj("articleServiceMock", ["createInProfile"]); | |
26 | + | |
27 | + let getCurrentProfileResponse = $q.defer(); | |
28 | + getCurrentProfileResponse.resolve(profile); | |
29 | + | |
30 | + let articleCreate = $q.defer(); | |
31 | + articleCreate.resolve({ data: { path: "path", profile: { identifier: "profile" } } }); | |
32 | + | |
33 | + profileServiceMock.getCurrentProfile = jasmine.createSpy("getCurrentProfile").and.returnValue(getCurrentProfileResponse.promise); | |
34 | + articleServiceMock.createInProfile = jasmine.createSpy("createInProfile").and.returnValue(articleCreate.promise); | |
35 | + }); | |
36 | + | |
37 | + it("create an article in the current profile when save", done => { | |
38 | + let component: BasicEditorComponent = new BasicEditorComponent(articleServiceMock, profileServiceMock, $state, notification); | |
39 | + component.save(); | |
40 | + $rootScope.$apply(); | |
41 | + expect(profileServiceMock.getCurrentProfile).toHaveBeenCalled(); | |
42 | + expect(articleServiceMock.createInProfile).toHaveBeenCalledWith(profile, component.article); | |
43 | + done(); | |
44 | + }); | |
45 | + | |
46 | + 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); | |
48 | + component.save(); | |
49 | + $rootScope.$apply(); | |
50 | + expect($state.transitionTo).toHaveBeenCalledWith("main.profile.page", { page: "path", profile: "profile" }); | |
51 | + expect(notification.success).toHaveBeenCalled(); | |
52 | + done(); | |
53 | + }); | |
54 | + | |
55 | +}); | ... | ... |
... | ... | @@ -0,0 +1,35 @@ |
1 | +import {StateConfig, Component, Inject, provide} from 'ng-forward'; | |
2 | +import {ArticleService} from "../../lib/ng-noosfero-api/http/article.service"; | |
3 | +import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service"; | |
4 | +import {NotificationService} from "../shared/services/notification.service.ts"; | |
5 | + | |
6 | +@Component({ | |
7 | + selector: 'article-basic-editor', | |
8 | + templateUrl: "app/article/basic-editor.html", | |
9 | + providers: [ | |
10 | + provide('articleService', { useClass: ArticleService }), | |
11 | + provide('profileService', { useClass: ProfileService }), | |
12 | + provide('notification', { useClass: NotificationService }) | |
13 | + ] | |
14 | +}) | |
15 | +@Inject(ArticleService, ProfileService, "$state", NotificationService) | |
16 | +export class BasicEditorComponent { | |
17 | + | |
18 | + article: noosfero.Article = <noosfero.Article>{}; | |
19 | + | |
20 | + constructor(private articleService: ArticleService, | |
21 | + private profileService: ProfileService, | |
22 | + private $state: ng.ui.IStateService, | |
23 | + private notification: NotificationService) { } | |
24 | + | |
25 | + save() { | |
26 | + this.profileService.getCurrentProfile().then((profile: noosfero.Profile) => { | |
27 | + return this.articleService.createInProfile(profile, this.article); | |
28 | + }).then((response: noosfero.RestResult<noosfero.Article>) => { | |
29 | + let article = (<noosfero.Article>response.data); | |
30 | + this.$state.transitionTo('main.profile.page', { page: article.path, profile: article.profile.identifier }); | |
31 | + this.notification.success("Good job!", "Article saved!"); | |
32 | + }); | |
33 | + } | |
34 | + | |
35 | +} | ... | ... |
... | ... | @@ -0,0 +1,11 @@ |
1 | +<form> | |
2 | + <div class="form-group"> | |
3 | + <label for="titleInput">Title</label> | |
4 | + <input type="text" class="form-control" id="titleInput" placeholder="title" ng-model="vm.article.name"> | |
5 | + </div> | |
6 | + <div class="form-group"> | |
7 | + <label for="bodyInput">Text</label> | |
8 | + <textarea class="form-control" id="bodyInput" rows="10" ng-model="vm.article.body"></textarea> | |
9 | + </div> | |
10 | + <button type="submit" class="btn btn-default" ng-click="vm.save()">Save</button> | |
11 | +</form> | ... | ... |
src/app/article/content-viewer/content-viewer-actions.component.spec.ts
0 → 100644
... | ... | @@ -0,0 +1,67 @@ |
1 | +import {providers} from 'ng-forward/cjs/testing/providers'; | |
2 | + | |
3 | +import {Input, Component, provide} from 'ng-forward'; | |
4 | + | |
5 | +import * as helpers from "../../../spec/helpers"; | |
6 | + | |
7 | +import {ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder'; | |
8 | +import {ContentViewerActions} from './content-viewer-actions.component'; | |
9 | + | |
10 | +// this htmlTemplate will be re-used between the container components in this spec file | |
11 | +const htmlTemplate: string = '<content-viewer-actions [article]="ctrl.article" [profile]="ctrl.profile"></content-viewer-actions>'; | |
12 | + | |
13 | +describe('Content Viewer Actions Component', () => { | |
14 | + | |
15 | + beforeEach(() => { | |
16 | + | |
17 | + angular.mock.module("templates"); | |
18 | + | |
19 | + providers((provide: any) => { | |
20 | + return <any>[ | |
21 | + provide('ProfileService', { | |
22 | + useValue: helpers.mocks.profileService | |
23 | + }) | |
24 | + ]; | |
25 | + }); | |
26 | + }); | |
27 | + | |
28 | + let buildComponent = (): Promise<ComponentFixture> => { | |
29 | + return helpers.quickCreateComponent({ | |
30 | + providers: [ | |
31 | + helpers.provideEmptyObjects('Restangular'), | |
32 | + helpers.provideFilters('translateFilter') | |
33 | + ], | |
34 | + directives: [ContentViewerActions], | |
35 | + template: htmlTemplate | |
36 | + }); | |
37 | + }; | |
38 | + | |
39 | + it('renders content viewer actions directive', (done: Function) => { | |
40 | + buildComponent().then((fixture: ComponentFixture) => { | |
41 | + expect(fixture.debugElement.query('content-viewer-actions').length).toEqual(1); | |
42 | + | |
43 | + done(); | |
44 | + }); | |
45 | + }); | |
46 | + | |
47 | + it('check if profile was loaded', (done: Function) => { | |
48 | + let profile: any = { | |
49 | + id: 1, | |
50 | + identifier: 'the-profile-test', | |
51 | + type: 'Person' | |
52 | + }; | |
53 | + | |
54 | + helpers.mocks.profileService.getCurrentProfile = () => { | |
55 | + return helpers.mocks.promiseResultTemplate(profile); | |
56 | + }; | |
57 | + | |
58 | + buildComponent().then((fixture: ComponentFixture) => { | |
59 | + let contentViewerComp: ContentViewerActions = fixture.debugElement.componentViewChildren[0].componentInstance; | |
60 | + | |
61 | + expect(contentViewerComp.profile).toEqual(jasmine.objectContaining(profile)); | |
62 | + | |
63 | + done(); | |
64 | + }); | |
65 | + }); | |
66 | + | |
67 | +}); | ... | ... |
src/app/article/content-viewer/content-viewer-actions.component.ts
0 → 100644
... | ... | @@ -0,0 +1,20 @@ |
1 | +import {Component, Inject, provide} from "ng-forward"; | |
2 | +import {ProfileService} from "../../../lib/ng-noosfero-api/http/profile.service"; | |
3 | + | |
4 | +@Component({ | |
5 | + selector: "content-viewer-actions", | |
6 | + templateUrl: "app/article/content-viewer/navbar-actions.html", | |
7 | + providers: [provide('profileService', { useClass: ProfileService })] | |
8 | +}) | |
9 | +@Inject(ProfileService) | |
10 | +export class ContentViewerActions { | |
11 | + | |
12 | + article: noosfero.Article; | |
13 | + profile: noosfero.Profile; | |
14 | + | |
15 | + constructor(profileService: ProfileService) { | |
16 | + profileService.getCurrentProfile().then((profile: noosfero.Profile) => { | |
17 | + this.profile = profile; | |
18 | + }); | |
19 | + } | |
20 | +} | ... | ... |
src/app/article/content-viewer/content-viewer.component.spec.ts
0 → 100644
... | ... | @@ -0,0 +1,88 @@ |
1 | +import {providers} from 'ng-forward/cjs/testing/providers'; | |
2 | + | |
3 | +import {Input, Component, provide} from 'ng-forward'; | |
4 | + | |
5 | +import * as helpers from "../../../spec/helpers"; | |
6 | + | |
7 | +import {ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder'; | |
8 | +import {ContentViewerComponent} from './content-viewer.component'; | |
9 | + | |
10 | +// this htmlTemplate will be re-used between the container components in this spec file | |
11 | +const htmlTemplate: string = '<content-viewer [article]="ctrl.article" [profile]="ctrl.profile"></content-viewer>'; | |
12 | + | |
13 | +describe('Content Viewer Component', () => { | |
14 | + | |
15 | + let stateParamsService: any; | |
16 | + | |
17 | + // loading the templates | |
18 | + beforeEach(() => { | |
19 | + angular.mock.module("templates"); | |
20 | + | |
21 | + stateParamsService = { page: 1 }; | |
22 | + | |
23 | + providers((provide: any) => { | |
24 | + return <any>[ | |
25 | + provide('ArticleService', { | |
26 | + useValue: helpers.mocks.articleService | |
27 | + }), | |
28 | + provide('ProfileService', { | |
29 | + useValue: helpers.mocks.profileService | |
30 | + }), | |
31 | + // TODO: Como criar um mock do atributo "page" de stateParams | |
32 | + provide('$stateParams', { | |
33 | + useValue: stateParamsService | |
34 | + }) | |
35 | + ]; | |
36 | + }); | |
37 | + }); | |
38 | + | |
39 | + let buildComponent = (): Promise<ComponentFixture> => { | |
40 | + return helpers.quickCreateComponent({ | |
41 | + providers: [ | |
42 | + helpers.provideEmptyObjects('Restangular') | |
43 | + ], | |
44 | + directives: [ContentViewerComponent], | |
45 | + template: htmlTemplate | |
46 | + }); | |
47 | + }; | |
48 | + | |
49 | + it('renders content viewer directive', (done: Function) => { | |
50 | + buildComponent().then((fixture: ComponentFixture) => { | |
51 | + expect(fixture.debugElement.query('content-viewer').length).toEqual(1); | |
52 | + | |
53 | + done(); | |
54 | + }); | |
55 | + }); | |
56 | + | |
57 | + it('check if article was loaded', (done: Function) => { | |
58 | + let article: any = { | |
59 | + id: 1, | |
60 | + title: 'The article test' | |
61 | + }; | |
62 | + let profile: any = { | |
63 | + id: 1, | |
64 | + identifier: 'the-profile-test', | |
65 | + type: 'Person' | |
66 | + }; | |
67 | + | |
68 | + helpers.mocks.profileService.getCurrentProfile = () => { | |
69 | + return helpers.mocks.promiseResultTemplate(profile); | |
70 | + }; | |
71 | + | |
72 | + helpers.mocks.articleService.getArticleByProfileAndPath = (profile: noosfero.Profile, path: string) => { | |
73 | + return helpers.mocks.promiseResultTemplate({ | |
74 | + data: article | |
75 | + }); | |
76 | + }; | |
77 | + | |
78 | + | |
79 | + buildComponent().then((fixture: ComponentFixture) => { | |
80 | + let contentViewerComp: ContentViewerComponent = fixture.debugElement.componentViewChildren[0].componentInstance; | |
81 | + | |
82 | + expect(contentViewerComp.profile).toEqual(profile); | |
83 | + expect(contentViewerComp.article).toEqual(article); | |
84 | + | |
85 | + done(); | |
86 | + }); | |
87 | + }); | |
88 | +}); | ... | ... |
src/app/article/content-viewer/content-viewer.component.ts
0 → 100644
... | ... | @@ -0,0 +1,38 @@ |
1 | +import {ArticleViewComponent} from "./../article-default-view.component"; | |
2 | +import {Input, Component, StateConfig, Inject, provide} from "ng-forward"; | |
3 | + | |
4 | +import {ArticleBlogComponent} from "./../types/blog/blog.component"; | |
5 | +import {ArticleService} from "../../../lib/ng-noosfero-api/http/article.service"; | |
6 | +import {ProfileService} from "../../../lib/ng-noosfero-api/http/profile.service"; | |
7 | + | |
8 | +@Component({ | |
9 | + selector: "content-viewer", | |
10 | + templateUrl: "app/article/content-viewer/page.html", | |
11 | + directives: [ArticleBlogComponent, ArticleViewComponent], | |
12 | + providers: [ | |
13 | + provide('articleService', { useClass: ArticleService }), | |
14 | + provide('profileService', { useClass: ProfileService }) | |
15 | + ] | |
16 | +}) | |
17 | +@Inject(ArticleService, ProfileService, "$log", "$stateParams") | |
18 | +export class ContentViewerComponent { | |
19 | + | |
20 | + @Input() | |
21 | + article: noosfero.Article = null; | |
22 | + | |
23 | + @Input() | |
24 | + profile: noosfero.Profile = null; | |
25 | + | |
26 | + constructor(private articleService: ArticleService, private profileService: ProfileService, private $log: ng.ILogService, private $stateParams: angular.ui.IStateParamsService) { | |
27 | + this.activate(); | |
28 | + } | |
29 | + | |
30 | + activate() { | |
31 | + this.profileService.getCurrentProfile().then((profile: noosfero.Profile) => { | |
32 | + this.profile = profile; | |
33 | + return this.articleService.getArticleByProfileAndPath(this.profile, this.$stateParams["page"]); | |
34 | + }).then((result: noosfero.RestResult<any>) => { | |
35 | + this.article = <noosfero.Article>result.data; | |
36 | + }); | |
37 | + } | |
38 | +} | ... | ... |
... | ... | @@ -0,0 +1,7 @@ |
1 | +<ul class="nav navbar-nav"> | |
2 | + <li ng-show="vm.profile"> | |
3 | + <a href="#" role="button" ui-sref="main.profile.cms({profile: vm.profile.identifier})"> | |
4 | + <i class="fa fa-file fa-fw fa-lg"></i> {{"navbar.content_viewer_actions.new_post" | translate}} | |
5 | + </a> | |
6 | + </li> | |
7 | +</ul> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +<noosfero-article ng-if="vm.article" [article]="vm.article" [profile]="vm.profile"></noosfero-article> | ... | ... |
... | ... | @@ -0,0 +1,129 @@ |
1 | +import { | |
2 | +providers | |
3 | +} from 'ng-forward/cjs/testing/providers'; | |
4 | + | |
5 | +import { | |
6 | +Input, | |
7 | +Component | |
8 | +} from 'ng-forward'; | |
9 | +import { | |
10 | +ArticleBlogComponent | |
11 | +} from './blog.component'; | |
12 | + | |
13 | +import { | |
14 | +createComponentFromClass, | |
15 | +quickCreateComponent, | |
16 | +provideEmptyObjects, | |
17 | +createProviderToValue, | |
18 | +provideFilters | |
19 | +} from "../../../../spec/helpers.ts"; | |
20 | + | |
21 | +// this htmlTemplate will be re-used between the container components in this spec file | |
22 | +const htmlTemplate: string = '<noosfero-blog [article]="ctrl.article" [profile]="ctrl.profile"></noosfero-blog>'; | |
23 | + | |
24 | +describe("Blog Component", () => { | |
25 | + | |
26 | + function promiseResultTemplate(response?: {}) { | |
27 | + let thenFuncEmpty = (func: Function) => { | |
28 | + // does nothing | |
29 | + }; | |
30 | + if (response) { | |
31 | + return { | |
32 | + then: (func: (response: any) => void) => { | |
33 | + func(response); | |
34 | + } | |
35 | + }; | |
36 | + } else { | |
37 | + return { | |
38 | + then: (func: (response: any) => void) => { | |
39 | + // does nothing | |
40 | + } | |
41 | + }; | |
42 | + } | |
43 | + } | |
44 | + | |
45 | + let articleService = { | |
46 | + getChildren: (article_id: number, filters: {}) => { | |
47 | + return promiseResultTemplate(null); | |
48 | + } | |
49 | + }; | |
50 | + | |
51 | + @Component({ | |
52 | + selector: 'test-container-component', | |
53 | + template: htmlTemplate, | |
54 | + directives: [ArticleBlogComponent], | |
55 | + providers: [ | |
56 | + provideEmptyObjects('Restangular'), | |
57 | + createProviderToValue('ArticleService', articleService), | |
58 | + provideFilters('truncateFilter') | |
59 | + ] | |
60 | + }) | |
61 | + class BlogContainerComponent { | |
62 | + article = { | |
63 | + type: 'anyArticleType' | |
64 | + }; | |
65 | + profile = { | |
66 | + name: 'profile-name' | |
67 | + }; | |
68 | + } | |
69 | + | |
70 | + beforeEach(() => { | |
71 | + | |
72 | + // the karma preprocessor html2js transform the templates html into js files which put | |
73 | + // the templates to the templateCache into the module templates | |
74 | + // we need to load the module templates here as the template for the | |
75 | + // component Noosfero ArtileView will be load on our tests | |
76 | + angular.mock.module("templates"); | |
77 | + | |
78 | + providers((provide: any) => { | |
79 | + return <any>[ | |
80 | + provide('ArticleService', { | |
81 | + useValue: articleService | |
82 | + }) | |
83 | + ]; | |
84 | + }); | |
85 | + }); | |
86 | + | |
87 | + it("renders the blog content", (done: Function) => { | |
88 | + | |
89 | + createComponentFromClass(BlogContainerComponent).then((fixture) => { | |
90 | + | |
91 | + expect(fixture.debugElement.query('div.blog').length).toEqual(1); | |
92 | + | |
93 | + done(); | |
94 | + }); | |
95 | + }); | |
96 | + | |
97 | + it("verify the blog data", (done: Function) => { | |
98 | + | |
99 | + let articles = [{ | |
100 | + id: 1, | |
101 | + title: 'The article test' | |
102 | + }]; | |
103 | + | |
104 | + let result = { data: articles, headers: (name: string) => { return 1; } }; | |
105 | + | |
106 | + // defining a mock result to articleService.getChildren method | |
107 | + articleService.getChildren = (article_id: number, filters: {}) => { | |
108 | + return promiseResultTemplate(result); | |
109 | + }; | |
110 | + | |
111 | + createComponentFromClass(BlogContainerComponent).then((fixture) => { | |
112 | + | |
113 | + // gets the children component of BlogContainerComponent | |
114 | + let articleBlog: BlogContainerComponent = fixture.debugElement.componentViewChildren[0].componentInstance; | |
115 | + | |
116 | + // check if the component property are the provided by the mocked articleService | |
117 | + let post = { | |
118 | + id: 1, | |
119 | + title: 'The article test' | |
120 | + }; | |
121 | + expect((<any>articleBlog)["posts"][0]).toEqual(jasmine.objectContaining(post)); | |
122 | + expect((<any>articleBlog)["totalPosts"]).toEqual(1); | |
123 | + | |
124 | + done(); | |
125 | + }); | |
126 | + | |
127 | + }); | |
128 | + | |
129 | +}); | |
0 | 130 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,47 @@ |
1 | +import {Component, Input, Inject} from "ng-forward"; | |
2 | + | |
3 | +import {ArticleService} from "../../../../lib/ng-noosfero-api/http/article.service"; | |
4 | + | |
5 | +/** | |
6 | + * @ngdoc controller | |
7 | + * @name ArticleBlog | |
8 | + * @description | |
9 | + * An specific {@link ArticleView} for Blog articles. | |
10 | + */ | |
11 | +@Component({ | |
12 | + selector: "noosfero-blog", | |
13 | + templateUrl: "app/article/types/blog/blog.html" | |
14 | +}) | |
15 | +@Inject(ArticleService) | |
16 | +export class ArticleBlogComponent { | |
17 | + | |
18 | + @Input() article: noosfero.Article; | |
19 | + @Input() profile: noosfero.Profile; | |
20 | + | |
21 | + private posts: noosfero.Article[]; | |
22 | + private perPage: number = 3; | |
23 | + private currentPage: number; | |
24 | + private totalPosts: number = 0; | |
25 | + | |
26 | + constructor(private articleService: ArticleService) { } | |
27 | + | |
28 | + ngOnInit() { | |
29 | + this.loadPage(); | |
30 | + } | |
31 | + | |
32 | + loadPage() { | |
33 | + let filters = { | |
34 | + content_type: "TinyMceArticle", | |
35 | + per_page: this.perPage, | |
36 | + page: this.currentPage | |
37 | + }; | |
38 | + | |
39 | + this.articleService | |
40 | + .getChildren(this.article, filters) | |
41 | + .then((result: noosfero.RestResult<noosfero.Article[]>) => { | |
42 | + this.totalPosts = <number>result.headers("total"); | |
43 | + this.posts = result.data; | |
44 | + }); | |
45 | + } | |
46 | + | |
47 | +} | ... | ... |
... | ... | @@ -0,0 +1,24 @@ |
1 | +<div class="blog"> | |
2 | + <div class="blog-cover" ng-show="ctrl.article.image"> | |
3 | + <img ng-src="{{ctrl.article.image.url}}" class="img-responsive"> | |
4 | + <h3 ng-bind="ctrl.article.title"></h3> | |
5 | + </div> | |
6 | + | |
7 | + <div class="page-header" ng-show="!ctrl.article.image"> | |
8 | + <h3 ng-bind="ctrl.article.title"></h3> | |
9 | + </div> | |
10 | + | |
11 | + <div> | |
12 | + <div ng-repeat="child in ctrl.posts | orderBy: 'created_at':true"> | |
13 | + <div class="page-header"> | |
14 | + <a class="title" ui-sref="main.profile.page({profile: ctrl.profile.identifier, page: child.path})"><h4 ng-bind="child.title"></h4></a> | |
15 | + <div class="post-lead" ng-bind-html="child.body | truncate: 500: '...': true"></div> | |
16 | + </div> | |
17 | + </div> | |
18 | + </div> | |
19 | + | |
20 | + <pagination ng-model="ctrl.currentPage" total-items="ctrl.totalPosts" class="pagination-sm center-block" | |
21 | + boundary-links="true" items-per-page="ctrl.perPage" ng-change="ctrl.loadPage()" | |
22 | + first-text="«" last-text="»" previous-text="‹" next-text="›"> | |
23 | + </pagination> | |
24 | +</div> | ... | ... |
... | ... | @@ -0,0 +1 @@ |
1 | +/* Module Index Entry - generated using the script npm run generate-index */ | ... | ... |
src/app/cms/cms.component.spec.ts
... | ... | @@ -1,54 +0,0 @@ |
1 | -import {quickCreateComponent} from "../../spec/helpers"; | |
2 | -import {Cms} from "./cms.component"; | |
3 | - | |
4 | -describe("Components", () => { | |
5 | - describe("Cms Component", () => { | |
6 | - | |
7 | - let $rootScope: ng.IRootScopeService; | |
8 | - let $q: ng.IQService; | |
9 | - let articleServiceMock: any; | |
10 | - let profileServiceMock: any; | |
11 | - let $state: any; | |
12 | - let notification: any; | |
13 | - | |
14 | - beforeEach(inject((_$rootScope_: ng.IRootScopeService, _$q_: ng.IQService) => { | |
15 | - $rootScope = _$rootScope_; | |
16 | - $q = _$q_; | |
17 | - })); | |
18 | - | |
19 | - beforeEach(() => { | |
20 | - $state = jasmine.createSpyObj("$state", ["transitionTo"]); | |
21 | - notification = jasmine.createSpyObj("notification", ["success"]); | |
22 | - profileServiceMock = jasmine.createSpyObj("profileServiceMock", ["getCurrentProfile"]); | |
23 | - articleServiceMock = jasmine.createSpyObj("articleServiceMock", ["create"]); | |
24 | - | |
25 | - let getCurrentProfileResponse = $q.defer(); | |
26 | - getCurrentProfileResponse.resolve({ id: 1 }); | |
27 | - | |
28 | - let articleCreate = $q.defer(); | |
29 | - articleCreate.resolve({ data: { article: { path: "path", profile: { identifier: "profile" } } } }); | |
30 | - | |
31 | - profileServiceMock.getCurrentProfile = jasmine.createSpy("getCurrentProfile").and.returnValue(getCurrentProfileResponse.promise); | |
32 | - articleServiceMock.create = jasmine.createSpy("create").and.returnValue(articleCreate.promise); | |
33 | - }); | |
34 | - | |
35 | - it("create an article in the current profile when save", done => { | |
36 | - let component: Cms = new Cms(articleServiceMock, profileServiceMock, $state, notification); | |
37 | - component.save(); | |
38 | - $rootScope.$apply(); | |
39 | - expect(profileServiceMock.getCurrentProfile).toHaveBeenCalled(); | |
40 | - expect(articleServiceMock.create).toHaveBeenCalledWith(1, component.article); | |
41 | - done(); | |
42 | - }); | |
43 | - | |
44 | - it("got to the new article page and display an alert when saving sucessfully", done => { | |
45 | - let component: Cms = new Cms(articleServiceMock, profileServiceMock, $state, notification); | |
46 | - component.save(); | |
47 | - $rootScope.$apply(); | |
48 | - expect($state.transitionTo).toHaveBeenCalledWith("main.profile.page", { page: "path", profile: "profile" }); | |
49 | - expect(notification.success).toHaveBeenCalled(); | |
50 | - done(); | |
51 | - }); | |
52 | - | |
53 | - }); | |
54 | -}); |
src/app/cms/cms.component.ts
... | ... | @@ -1,35 +0,0 @@ |
1 | -import {StateConfig, Component, Inject, provide} from 'ng-forward'; | |
2 | -import {Profile} from "./../models/interfaces"; | |
3 | -import {ArticleService} from "../../lib/ng-noosfero-api/http/article.service"; | |
4 | -import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service"; | |
5 | -import {Notification} from "../components/notification/notification.component"; | |
6 | - | |
7 | -@Component({ | |
8 | - selector: 'cms', | |
9 | - templateUrl: "app/cms/cms.html", | |
10 | - providers: [ | |
11 | - provide('articleService', { useClass: ArticleService }), | |
12 | - provide('profileService', { useClass: ProfileService }), | |
13 | - provide('notification', { useClass: Notification }) | |
14 | - ] | |
15 | -}) | |
16 | -@Inject(ArticleService, ProfileService, "$state", Notification) | |
17 | -export class Cms { | |
18 | - | |
19 | - article: any = {}; | |
20 | - | |
21 | - constructor(private articleService: ArticleService, | |
22 | - private profileService: ProfileService, | |
23 | - private $state: ng.ui.IStateService, | |
24 | - private notification: Notification) { } | |
25 | - | |
26 | - save() { | |
27 | - this.profileService.getCurrentProfile().then((profile: Profile) => { | |
28 | - return this.articleService.create(profile.id, this.article); | |
29 | - }).then((response: restangular.IResponse) => { | |
30 | - this.$state.transitionTo('main.profile.page', { page: response.data.article.path, profile: response.data.article.profile.identifier }); | |
31 | - this.notification.success("Good job!", "Article saved!"); | |
32 | - }); | |
33 | - } | |
34 | - | |
35 | -} |
src/app/cms/cms.html
... | ... | @@ -1,11 +0,0 @@ |
1 | -<form> | |
2 | - <div class="form-group"> | |
3 | - <label for="titleInput">Title</label> | |
4 | - <input type="text" class="form-control" id="titleInput" placeholder="title" ng-model="vm.article.name"> | |
5 | - </div> | |
6 | - <div class="form-group"> | |
7 | - <label for="bodyInput">Text</label> | |
8 | - <textarea class="form-control" id="bodyInput" rows="10" ng-model="vm.article.body"></textarea> | |
9 | - </div> | |
10 | - <button type="submit" class="btn btn-default" ng-click="vm.save()">Save</button> | |
11 | -</form> |
src/app/cms/index.ts
src/app/components/auth/auth_controller.spec.ts
... | ... | @@ -1,33 +0,0 @@ |
1 | -import {AuthController} from "./auth_controller"; | |
2 | -import {AuthService} from "./auth_service"; | |
3 | - | |
4 | -describe("Controllers", () => { | |
5 | - | |
6 | - | |
7 | - describe("AuthController", () => { | |
8 | - | |
9 | - it("calls authenticate on AuthService when login called", () => { | |
10 | - | |
11 | - // creating a Mock AuthService | |
12 | - let AuthServiceMock: AuthService = jasmine.createSpyObj("AuthService", ["login"]); | |
13 | - | |
14 | - // pass AuthServiceMock into the constructor | |
15 | - let authController = new AuthController(null, null, AuthServiceMock); | |
16 | - | |
17 | - // setup of authController -> set the credentials instance property | |
18 | - let credentials = { username: "username", password: "password" }; | |
19 | - | |
20 | - authController.credentials = credentials; | |
21 | - | |
22 | - // calls the authController login method | |
23 | - authController.login(); | |
24 | - | |
25 | - // checks if the method login of the injected AuthService has been called | |
26 | - expect(AuthServiceMock.login).toHaveBeenCalledWith(credentials); | |
27 | - | |
28 | - }); | |
29 | - | |
30 | - | |
31 | - | |
32 | - }); | |
33 | -}); |
src/app/components/auth/auth_controller.ts
... | ... | @@ -1,21 +0,0 @@ |
1 | -import {Credentials} from "./../../models/interfaces"; | |
2 | -import {AuthService} from "./auth_service"; | |
3 | - | |
4 | -export class AuthController { | |
5 | - | |
6 | - static $inject = ["$log", "$stateParams", "AuthService"]; | |
7 | - | |
8 | - constructor( | |
9 | - private $log: ng.ILogService, | |
10 | - private $stateParams: any, | |
11 | - private AuthService: AuthService | |
12 | - ) { | |
13 | - | |
14 | - } | |
15 | - | |
16 | - credentials: Credentials; | |
17 | - | |
18 | - login() { | |
19 | - this.AuthService.login(this.credentials); | |
20 | - } | |
21 | -} |
src/app/components/auth/auth_events.ts
... | ... | @@ -1,11 +0,0 @@ |
1 | -export interface IAuthEvents { | |
2 | - loginSuccess: string; | |
3 | - loginFailed: string; | |
4 | - logoutSuccess: string; | |
5 | -} | |
6 | - | |
7 | -export const AUTH_EVENTS: IAuthEvents = { | |
8 | - loginSuccess: "auth-login-success", | |
9 | - loginFailed: "auth-login-failed", | |
10 | - logoutSuccess: "auth-logout-success" | |
11 | -}; | |
12 | 0 | \ No newline at end of file |
src/app/components/auth/auth_service.spec.ts
... | ... | @@ -1,82 +0,0 @@ |
1 | - | |
2 | - | |
3 | -import {AuthService, AUTH_EVENTS} from "./"; | |
4 | -import {User, Credentials} from "./../../models/interfaces"; | |
5 | - | |
6 | -describe("Services", () => { | |
7 | - | |
8 | - | |
9 | - describe("Auth Service", () => { | |
10 | - | |
11 | - let $httpBackend: ng.IHttpBackendService; | |
12 | - let authService: AuthService; | |
13 | - let credentials: Credentials; | |
14 | - let $rootScope: ng.IRootScopeService; | |
15 | - let user: User; | |
16 | - | |
17 | - beforeEach(angular.mock.module("noosferoApp", ($translateProvider: angular.translate.ITranslateProvider) => { | |
18 | - $translateProvider.translations('en', {}); | |
19 | - })); | |
20 | - | |
21 | - beforeEach(inject((_$httpBackend_: ng.IHttpBackendService, _$rootScope_: ng.IRootScopeService, _AuthService_: AuthService) => { | |
22 | - $httpBackend = _$httpBackend_; | |
23 | - authService = _AuthService_; | |
24 | - $rootScope = _$rootScope_; | |
25 | - | |
26 | - user = <User>{ | |
27 | - id: 1, | |
28 | - login: "user" | |
29 | - }; | |
30 | - })); | |
31 | - | |
32 | - | |
33 | - describe("Succesffull login", () => { | |
34 | - | |
35 | - beforeEach(() => { | |
36 | - credentials = { username: "user", password: "password" }; | |
37 | - | |
38 | - $httpBackend.expectPOST("/api/v1/login", "login=user&password=password").respond(200, { user: user }); | |
39 | - }); | |
40 | - | |
41 | - it("should return loggedUser", (done) => { | |
42 | - authService.login(credentials).then((loggedUser) => { | |
43 | - expect(loggedUser).toBeDefined(); | |
44 | - done(); | |
45 | - }); | |
46 | - $httpBackend.flush(); | |
47 | - expect($httpBackend.verifyNoOutstandingRequest()); | |
48 | - }); | |
49 | - | |
50 | - | |
51 | - it("should emit event loggin successful with user logged data", () => { | |
52 | - | |
53 | - authService.login(credentials); | |
54 | - | |
55 | - let eventEmmited: boolean = false; | |
56 | - $rootScope.$on(AUTH_EVENTS.loginSuccess, (event: ng.IAngularEvent, userThroughEvent: User) => { | |
57 | - eventEmmited = true; | |
58 | - expect(userThroughEvent).toEqual(user) | |
59 | - }); | |
60 | - | |
61 | - $httpBackend.flush(); | |
62 | - | |
63 | - expect(eventEmmited).toBeTruthy(AUTH_EVENTS.loginSuccess + " was not emmited!"); | |
64 | - }); | |
65 | - | |
66 | - it("should return the current logged in user", () => { | |
67 | - authService.login(credentials); | |
68 | - $httpBackend.flush(); | |
69 | - let actual: User = authService.currentUser(); | |
70 | - expect(actual).toEqual(user, "The returned user must be present"); | |
71 | - }); | |
72 | - | |
73 | - it("should not return the current user after logout", () => { | |
74 | - authService.logout(); | |
75 | - let actual: any = authService.currentUser(); | |
76 | - expect(actual).toEqual(undefined, "The returned user must not be defined"); | |
77 | - }); | |
78 | - }); | |
79 | - | |
80 | - | |
81 | - }); | |
82 | -}); |
src/app/components/auth/auth_service.ts
... | ... | @@ -1,69 +0,0 @@ |
1 | -import {Injectable, Inject} from "ng-forward"; | |
2 | - | |
3 | -import {Credentials, NoosferoRootScope, User, UserResponse} from "./../../models/interfaces"; | |
4 | -import {Session} from "./session"; | |
5 | - | |
6 | -import {AUTH_EVENTS, IAuthEvents} from "./auth_events"; | |
7 | - | |
8 | -@Injectable() | |
9 | -@Inject("$q", "$http", "$rootScope", "Session", "$log", "AUTH_EVENTS") | |
10 | -export class AuthService { | |
11 | - | |
12 | - constructor(private $q: ng.IQService, | |
13 | - private $http: ng.IHttpService, | |
14 | - private $rootScope: NoosferoRootScope, | |
15 | - private session: Session, | |
16 | - private $log: ng.ILogService, | |
17 | - private auth_events: IAuthEvents) { | |
18 | - | |
19 | - } | |
20 | - | |
21 | - loginFromCookie() { | |
22 | - let url: string = '/api/v1/login_from_cookie'; | |
23 | - return this.$http.post(url, null).then(this.loginSuccessCallback.bind(this), this.loginFailedCallback.bind(this)); | |
24 | - } | |
25 | - | |
26 | - | |
27 | - private loginSuccessCallback(response: ng.IHttpPromiseCallbackArg<UserResponse>) { | |
28 | - this.$log.debug('AuthService.login [SUCCESS] response', response); | |
29 | - let currentUser: User = this.session.create(response.data); | |
30 | - this.$rootScope.currentUser = currentUser; | |
31 | - this.$rootScope.$broadcast(this.auth_events.loginSuccess, currentUser); | |
32 | - return currentUser; | |
33 | - } | |
34 | - | |
35 | - login(credentials: Credentials): ng.IPromise<User> { | |
36 | - let url = '/api/v1/login'; | |
37 | - let encodedData = 'login=' + credentials.username + '&password=' + credentials.password; | |
38 | - return this.$http.post(url, encodedData).then(this.loginSuccessCallback.bind(this), this.loginFailedCallback.bind(this)); | |
39 | - } | |
40 | - | |
41 | - private loginFailedCallback(response: ng.IHttpPromiseCallbackArg<any>): any { | |
42 | - this.$log.debug('AuthService.login [FAIL] response', response); | |
43 | - this.$rootScope.$broadcast(this.auth_events.loginFailed); | |
44 | - // return $q.reject(response); | |
45 | - return null; | |
46 | - } | |
47 | - | |
48 | - public logout() { | |
49 | - this.session.destroy(); | |
50 | - this.$rootScope.currentUser = undefined; | |
51 | - this.$rootScope.$broadcast(this.auth_events.logoutSuccess); | |
52 | - this.$http.jsonp('/account/logout'); // FIXME logout from noosfero to sync login state | |
53 | - } | |
54 | - | |
55 | - public isAuthenticated() { | |
56 | - return !!this.session.currentUser(); | |
57 | - } | |
58 | - | |
59 | - public currentUser(): User { | |
60 | - return this.session.currentUser(); | |
61 | - } | |
62 | - | |
63 | - public isAuthorized(authorizedRoles: string | string[]) { | |
64 | - if (!angular.isArray(authorizedRoles)) { | |
65 | - authorizedRoles = [<string>authorizedRoles]; | |
66 | - } | |
67 | - return (this.isAuthenticated() && authorizedRoles.indexOf(this.session.currentUser().userRole) !== -1); | |
68 | - } | |
69 | -} | |
70 | 0 | \ No newline at end of file |
src/app/components/auth/index.ts
src/app/components/auth/login.html
... | ... | @@ -1,16 +0,0 @@ |
1 | -<div class="modal-header"> | |
2 | - <h3 class="modal-title">{{"auth.title" | translate}}</h3> | |
3 | -</div> | |
4 | -<div class="modal-body"> | |
5 | - <form> | |
6 | - <div class="form-group"> | |
7 | - <label for="exampleInputEmail1">{{"auth.form.login" | translate}}</label> | |
8 | - <input type="text" class="form-control" id="exampleInputEmail1" placeholder="Login / Email" ng-model="vm.credentials.username"> | |
9 | - </div> | |
10 | - <div class="form-group"> | |
11 | - <label for="exampleInputPassword1">{{"auth.form.password" | translate}}</label> | |
12 | - <input type="password" class="form-control" id="exampleInputPassword1" placeholder="Password" ng-model="vm.credentials.password"> | |
13 | - </div> | |
14 | - <button type="submit" class="btn btn-default" ng-click="vm.login()">{{"auth.form.login_button" | translate}}</button> | |
15 | - </form> | |
16 | -</div> |
src/app/components/auth/session.ts
... | ... | @@ -1,27 +0,0 @@ |
1 | -import {Injectable, Inject} from "ng-forward"; | |
2 | -import {UserResponse, User, INoosferoLocalStorage} from "./../../models/interfaces"; | |
3 | - | |
4 | -@Injectable() | |
5 | -@Inject("$localStorage", "$log") | |
6 | -export class Session { | |
7 | - | |
8 | - constructor(private $localStorage: INoosferoLocalStorage, private $log: ng.ILogService) { | |
9 | - | |
10 | - } | |
11 | - | |
12 | - create(data: UserResponse): User { | |
13 | - this.$localStorage.currentUser = data.user; | |
14 | - this.$log.debug('User session created.', this.$localStorage.currentUser); | |
15 | - return this.$localStorage.currentUser; | |
16 | - }; | |
17 | - | |
18 | - destroy() { | |
19 | - delete this.$localStorage.currentUser; | |
20 | - this.$log.debug('User session destroyed.'); | |
21 | - }; | |
22 | - | |
23 | - currentUser(): User { | |
24 | - return this.$localStorage.currentUser; | |
25 | - }; | |
26 | - | |
27 | -} | |
28 | 0 | \ No newline at end of file |
src/app/components/auth/session_spec.ts
... | ... | @@ -1,49 +0,0 @@ |
1 | -import {Component} from "ng-forward"; | |
2 | -import {Session} from "./"; | |
3 | -import {fixtures, createComponentFromClass, createProviderToValue} from "./../../../spec/helpers"; | |
4 | -import {UserResponse, User, INoosferoLocalStorage} from "./../../models/interfaces"; | |
5 | - | |
6 | - | |
7 | -describe("Services", () => { | |
8 | - | |
9 | - | |
10 | - describe("Session Service", () => { | |
11 | - | |
12 | - let $localStorage: INoosferoLocalStorage = null; | |
13 | - let $log: any; | |
14 | - | |
15 | - beforeEach(() => { | |
16 | - $localStorage = <INoosferoLocalStorage>{ currentUser: null }; | |
17 | - $log = jasmine.createSpyObj('$log', ['debug']); | |
18 | - }); | |
19 | - | |
20 | - it("method 'create()' saves the current user on $localstorage service", () => { | |
21 | - let session = new Session($localStorage, $log); | |
22 | - let userResponse = <UserResponse>{ | |
23 | - user: fixtures.user | |
24 | - }; | |
25 | - session.create(userResponse); | |
26 | - expect($localStorage.currentUser).toEqual(userResponse.user); | |
27 | - }); | |
28 | - | |
29 | - it("method 'destroy()' clean the currentUser on $localstorage", () => { | |
30 | - let session = new Session($localStorage, $log); | |
31 | - let userResponse = <UserResponse>{ | |
32 | - user: fixtures.user | |
33 | - }; | |
34 | - $localStorage.currentUser = fixtures.user; | |
35 | - session.destroy(); | |
36 | - expect($localStorage.currentUser).toBeUndefined(); | |
37 | - }); | |
38 | - | |
39 | - it("method 'currentUser()' returns the user recorded on $localstorage service", () => { | |
40 | - let session = new Session($localStorage, $log); | |
41 | - let userResponse = <UserResponse>{ | |
42 | - user: fixtures.user | |
43 | - }; | |
44 | - $localStorage.currentUser = fixtures.user; | |
45 | - expect(session.currentUser()).toEqual($localStorage.currentUser); | |
46 | - }); | |
47 | - }); | |
48 | - | |
49 | -}); | |
50 | 0 | \ No newline at end of file |
src/app/components/index.ts
... | ... | @@ -1 +0,0 @@ |
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/language-selector/language-selector.component.spec.ts
... | ... | @@ -1,46 +0,0 @@ |
1 | -import {ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder'; | |
2 | -import {provide} from 'ng-forward'; | |
3 | - | |
4 | -import {LanguageSelector} from './language-selector.component'; | |
5 | - | |
6 | -import * as helpers from "../../../spec/helpers"; | |
7 | - | |
8 | -describe("Components", () => { | |
9 | - | |
10 | - describe("Language Selector Component", () => { | |
11 | - | |
12 | - beforeEach(angular.mock.module("templates")); | |
13 | - | |
14 | - let translatorService: any; | |
15 | - | |
16 | - let buildComponent = (): Promise<ComponentFixture> => { | |
17 | - translatorService = jasmine.createSpyObj("translatorService", ["availableLanguages", "currentLanguage"]) | |
18 | - return helpers.quickCreateComponent({ | |
19 | - template: "<language-selector></language-selector>", | |
20 | - directives: [LanguageSelector], | |
21 | - providers: [ | |
22 | - provide('TranslatorService', { | |
23 | - useValue: translatorService | |
24 | - }) | |
25 | - ].concat(helpers.provideFilters("translateFilter")) | |
26 | - }); | |
27 | - } | |
28 | - | |
29 | - it("display language options", (done) => { | |
30 | - buildComponent().then(fixture => { | |
31 | - fixture.debugElement.getLocal("$rootScope").$apply(); | |
32 | - expect(fixture.debugElement.queryAll('li.language').length).toEqual(2); | |
33 | - done(); | |
34 | - }); | |
35 | - }); | |
36 | - | |
37 | - it("call the translator service when change the language", (done) => { | |
38 | - let translatorService = jasmine.createSpyObj("translatorService", ["changeLanguage"]); | |
39 | - let languageSelector = new LanguageSelector(<any>translatorService); | |
40 | - languageSelector.changeLanguage("en"); | |
41 | - expect(translatorService.changeLanguage).toHaveBeenCalledWith("en"); | |
42 | - done(); | |
43 | - }); | |
44 | - | |
45 | - }); | |
46 | -}); |
src/app/components/language-selector/language-selector.component.ts
... | ... | @@ -1,24 +0,0 @@ |
1 | -import {Component, Inject} from "ng-forward"; | |
2 | -import {TranslatorService} from "../translator/translator.service"; | |
3 | - | |
4 | -@Component({ | |
5 | - selector: "language-selector", | |
6 | - templateUrl: "app/components/language-selector/language-selector.html" | |
7 | -}) | |
8 | -@Inject(TranslatorService) | |
9 | -export class LanguageSelector { | |
10 | - | |
11 | - constructor(private translatorService: TranslatorService) { } | |
12 | - | |
13 | - currentLanguage() { | |
14 | - return this.translatorService.currentLanguage(); | |
15 | - } | |
16 | - | |
17 | - changeLanguage(language: string) { | |
18 | - this.translatorService.changeLanguage(language); | |
19 | - } | |
20 | - | |
21 | - availableLanguages() { | |
22 | - return this.translatorService.availableLanguages; | |
23 | - } | |
24 | -} |
src/app/components/language-selector/language-selector.html
... | ... | @@ -1,13 +0,0 @@ |
1 | -<li class="dropdown profile-menu" dropdown> | |
2 | - <a href="#" class="dropdown-toggle" aria-expanded="false" dropdown-toggle> | |
3 | - <span>{{"language.selector" | translate}}</span> <b class="caret"></b> | |
4 | - </a> | |
5 | - <ul class="dropdown-menu" dropdown-menu> | |
6 | - <li ng-repeat="(language, description) in ctrl.availableLanguages()" | |
7 | - class="language language-{{language}}" ng-class="{'active': language==ctrl.currentLanguage()}"> | |
8 | - <a href="#" ng-click="ctrl.changeLanguage(language)"> | |
9 | - {{description}} | |
10 | - </a> | |
11 | - </li> | |
12 | - </ul> | |
13 | -</li> |
src/app/components/navbar/index.ts
src/app/components/navbar/navbar.directive.spec.js
... | ... | @@ -1,45 +0,0 @@ |
1 | -(function() { | |
2 | - 'use strict'; | |
3 | - | |
4 | - describe('directive navbar', function() { | |
5 | - var vm; | |
6 | - var el; | |
7 | - var AUTH_EVENTS; | |
8 | - var $state; | |
9 | - | |
10 | - beforeEach(module('angular')); | |
11 | - beforeEach(inject(function($compile, $rootScope, $httpBackend, _AUTH_EVENTS_, _$state_) { | |
12 | - $state = _$state_; | |
13 | - AUTH_EVENTS = _AUTH_EVENTS_; | |
14 | - $httpBackend.when('POST','/api/v1/login_from_cookie').respond({}); | |
15 | - | |
16 | - el = angular.element('<acme-navbar></acme-navbar>'); | |
17 | - | |
18 | - $compile(el)($rootScope.$new()); | |
19 | - $rootScope.$digest(); | |
20 | - vm = el.isolateScope().vm; | |
21 | - })); | |
22 | - | |
23 | - it('should be compiled', function() { | |
24 | - expect(el.html()).not.toEqual(null); | |
25 | - }); | |
26 | - | |
27 | - it('should have isolate scope object with instanciate members', function() { | |
28 | - expect(vm).toEqual(jasmine.any(Object)); | |
29 | - expect(vm.currentUser).toEqual(undefined); | |
30 | - }); | |
31 | - | |
32 | - it('should reload current state after login', function() { | |
33 | - spyOn($state, 'go'); | |
34 | - el.isolateScope().$broadcast(AUTH_EVENTS.loginSuccess, {}); | |
35 | - expect($state.go).toHaveBeenCalled(); | |
36 | - }); | |
37 | - | |
38 | - it('should open login when not logged in', function() { | |
39 | - spyOn(vm, 'openLogin'); | |
40 | - vm.activate(); | |
41 | - expect(vm.openLogin).toHaveBeenCalled(); | |
42 | - }); | |
43 | - | |
44 | - }); | |
45 | -})(); |
src/app/components/navbar/navbar.html
... | ... | @@ -1,49 +0,0 @@ |
1 | -<nav class="navbar navbar-static-top navbar-inverse"> | |
2 | - <div class="container-fluid"> | |
3 | - <div class="navbar-header"> | |
4 | - <button type="button" class="navbar-toggle collapsed" ng-click="isCollapsed = !isCollapsed"> | |
5 | - <span class="sr-only">{{"navbar.toggle_menu" | translate}}</span> | |
6 | - <span class="icon-bar"></span> | |
7 | - <span class="icon-bar"></span> | |
8 | - <span class="icon-bar"></span> | |
9 | - </button> | |
10 | - <a class="navbar-brand" ui-sref="main"> | |
11 | - <span class="noosfero-logo"><img src="assets/images/logo-noosfero.png"></span> {{"noosfero.name" | translate}} | |
12 | - </a> | |
13 | - </div> | |
14 | - | |
15 | - <div class="collapse navbar-collapse" id="navbar-collapse" collapse="isCollapsed"> | |
16 | - <ul class="nav navbar-nav"> | |
17 | - </ul> | |
18 | - | |
19 | - <ul class="nav navbar-nav navbar-right"> | |
20 | - <li ng-show="!ctrl.currentUser"> | |
21 | - <a ng-href="#" ng-click="ctrl.openLogin()">{{"navbar.login" | translate}}</a> | |
22 | - </li> | |
23 | - | |
24 | - <li class="dropdown profile-menu" ng-show="ctrl.currentUser" dropdown> | |
25 | - <a href="#" class="dropdown-toggle" aria-expanded="false" dropdown-toggle> | |
26 | - <noosfero-profile-image [profile]="ctrl.currentUser.person" class="profile-image"></noosfero-profile-image> | |
27 | - <span ng-bind="ctrl.currentUser.person.name"></span> <b class="caret"></b> | |
28 | - </a> | |
29 | - <ul class="dropdown-menu" dropdown-menu> | |
30 | - <li> | |
31 | - <a ui-sref="main.profile.info({profile: ctrl.currentUser.person.identifier})"><i class="fa fa-fw fa-user"></i> {{"navbar.profile" | translate}}</a> | |
32 | - </li> | |
33 | - <li> | |
34 | - <a target="_self" ui-sref="main.profile.settings({profile: ctrl.currentUser.person.identifier})"><i class="fa fa-fw fa-gear"></i> {{"navbar.settings" | translate}}</a> | |
35 | - </li> | |
36 | - <li class="divider"></li> | |
37 | - <li> | |
38 | - <a href="#" ng-click="ctrl.logout()"><i class="fa fa-fw fa-power-off"></i> {{"navbar.logout" | translate}}</a> | |
39 | - </li> | |
40 | - </ul> | |
41 | - </li> | |
42 | - </ul> | |
43 | - <ul class="nav navbar-nav navbar-right"> | |
44 | - <language-selector class="nav navbar-nav navbar-right"></language-selector> | |
45 | - </ul> | |
46 | - <div ui-view="actions"></div> | |
47 | - </div> | |
48 | - </div> | |
49 | -</nav> |
src/app/components/navbar/navbar.scss
... | ... | @@ -1,31 +0,0 @@ |
1 | -.navbar { | |
2 | - | |
3 | - .container-fluid { | |
4 | - padding-right: 12%; | |
5 | - padding-left: 12%; | |
6 | - @media (max-width: 978px) { | |
7 | - padding-right: 2%; | |
8 | - padding-left: 2%; | |
9 | - } | |
10 | - | |
11 | - .navbar-brand { | |
12 | - .noosfero-logo img { | |
13 | - height: 35px; | |
14 | - } | |
15 | - } | |
16 | - | |
17 | - .navbar-nav { | |
18 | - .profile-menu .profile-image { | |
19 | - img { | |
20 | - height: 30px; | |
21 | - width: 30px; | |
22 | - display: inline-block; | |
23 | - @extend .img-circle; | |
24 | - } | |
25 | - i { | |
26 | - font-size: 1.7em; | |
27 | - } | |
28 | - } | |
29 | - } | |
30 | - } | |
31 | -} |
src/app/components/navbar/navbar.spec.ts
... | ... | @@ -1,188 +0,0 @@ |
1 | -import * as helpers from "./../../../spec/helpers"; | |
2 | -import {Navbar} from "./navbar"; | |
3 | -import {AUTH_EVENTS} from "./../auth"; | |
4 | -import {User} from "./../../models/interfaces"; | |
5 | -import {Injectable, Provider, provide} from "ng-forward"; | |
6 | - | |
7 | -import {ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder'; | |
8 | - | |
9 | -import {Session, AuthService, AuthController, IAuthEvents} from "./../auth"; | |
10 | - | |
11 | - | |
12 | -describe("Components", () => { | |
13 | - | |
14 | - describe("Navbar Component", () => { | |
15 | - | |
16 | - let user: User = null; | |
17 | - let scope: any; | |
18 | - let $rootScope: ng.IRootScopeService; | |
19 | - | |
20 | - let modalInstance: any; | |
21 | - let $modal: any; | |
22 | - let authService: any; | |
23 | - let stateService: any; | |
24 | - let sessionService: Session; | |
25 | - | |
26 | - let provideFunc = provide; | |
27 | - | |
28 | - // before Each -> loading mocks on locals variables | |
29 | - beforeEach(() => { | |
30 | - user = <User>{ | |
31 | - id: 1, | |
32 | - login: "user" | |
33 | - }; | |
34 | - scope = helpers.mocks.scopeWithEvents; | |
35 | - modalInstance = helpers.mocks.modalInstance; | |
36 | - $modal = helpers.mocks.$modal; | |
37 | - authService = helpers.mocks.authService; | |
38 | - stateService = jasmine.createSpyObj("$state", ["go"]); | |
39 | - sessionService = <any>helpers.mocks.sessionWithCurrentUser(user); | |
40 | - }); | |
41 | - | |
42 | - | |
43 | - // loading the templates | |
44 | - beforeEach(angular.mock.module("templates")); | |
45 | - | |
46 | - | |
47 | - // this function allow build the fixture of the container component | |
48 | - // and is reused in each test | |
49 | - // The main idea behing not prebuild it on a general beforeEach block is | |
50 | - // to allow tests configure the mock services accordilly their own needs | |
51 | - let buildComponent = (): Promise<ComponentFixture> => { | |
52 | - return helpers.quickCreateComponent({ | |
53 | - providers: [ | |
54 | - provide('$modal', { | |
55 | - useValue: $modal | |
56 | - }), | |
57 | - provide('AuthService', { | |
58 | - useValue: authService | |
59 | - }), | |
60 | - helpers.provideEmptyObjects('moment'), | |
61 | - provide('$state', { | |
62 | - useValue: stateService | |
63 | - }), | |
64 | - provide("$scope", { | |
65 | - useValue: scope | |
66 | - }), | |
67 | - provide('Session', { | |
68 | - useValue: sessionService | |
69 | - }), | |
70 | - provide('AUTH_EVENTS', { | |
71 | - useValue: { | |
72 | - AUTH_EVENTS | |
73 | - } | |
74 | - }), | |
75 | - provide('TranslatorService', { | |
76 | - useValue: helpers.mocks.translatorService | |
77 | - }) | |
78 | - ].concat(helpers.provideFilters("translateFilter")), | |
79 | - directives: [Navbar], | |
80 | - template: '<acme-navbar></acme-navbar>' | |
81 | - }); | |
82 | - } | |
83 | - | |
84 | - | |
85 | - it('should get the loggedIn user', (done: Function) => { | |
86 | - buildComponent().then((fixture: ComponentFixture) => { | |
87 | - let navbarInstance: Navbar = fixture.debugElement.componentViewChildren[0].componentInstance; | |
88 | - expect(navbarInstance).toBeDefined(); | |
89 | - expect(navbarInstance["currentUser"]).toEqual(user); | |
90 | - done(); | |
91 | - }); | |
92 | - }); | |
93 | - | |
94 | - it('should open on click', (done: Function) => { | |
95 | - spyOn($modal, "open"); | |
96 | - buildComponent().then((fixture: ComponentFixture) => { | |
97 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | |
98 | - navbarComp.openLogin(); | |
99 | - expect($modal.open).toHaveBeenCalled(); | |
100 | - expect($modal.open).toHaveBeenCalledWith({ | |
101 | - templateUrl: 'app/components/auth/login.html', | |
102 | - controller: AuthController, | |
103 | - controllerAs: 'vm', | |
104 | - bindToController: true | |
105 | - }); | |
106 | - done(); | |
107 | - }); | |
108 | - }); | |
109 | - | |
110 | - it('should logout', (done: Function) => { | |
111 | - buildComponent().then((fixture: ComponentFixture) => { | |
112 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | |
113 | - spyOn(authService, "logout"); | |
114 | - try { | |
115 | - navbarComp.logout(); | |
116 | - expect(authService.logout).toHaveBeenCalled(); | |
117 | - done(); | |
118 | - } catch (e) { | |
119 | - console.error(e); | |
120 | - fail(e.message); | |
121 | - done(); | |
122 | - } | |
123 | - }); | |
124 | - }); | |
125 | - | |
126 | - | |
127 | - it('should not activate user when logged in', (done: Function) => { | |
128 | - buildComponent().then((fixture: ComponentFixture) => { | |
129 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | |
130 | - spyOn(navbarComp, "openLogin"); | |
131 | - navbarComp.activate(); | |
132 | - expect((<any>navbarComp.openLogin).calls.count()).toBe(0); | |
133 | - done(); | |
134 | - }); | |
135 | - }); | |
136 | - | |
137 | - it('should activate when user not logged in', (done: Function) => { | |
138 | - spyOn(sessionService, 'currentUser').and.returnValue(null); | |
139 | - buildComponent().then((fixture: ComponentFixture) => { | |
140 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | |
141 | - spyOn(navbarComp, "openLogin"); | |
142 | - navbarComp.activate(); | |
143 | - expect(navbarComp.openLogin).toHaveBeenCalled(); | |
144 | - done(); | |
145 | - }); | |
146 | - }); | |
147 | - | |
148 | - | |
149 | - it('closes the modal after login', (done: Function) => { | |
150 | - modalInstance = jasmine.createSpyObj("modalInstance", ["close"]); | |
151 | - modalInstance.close = jasmine.createSpy("close"); | |
152 | - | |
153 | - $modal.open = () => { | |
154 | - return modalInstance; | |
155 | - }; | |
156 | - | |
157 | - buildComponent().then((fixture: ComponentFixture) => { | |
158 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | |
159 | - let localScope: ng.IScope = navbarComp["$scope"]; | |
160 | - | |
161 | - navbarComp.openLogin(); | |
162 | - localScope.$emit(AUTH_EVENTS.loginSuccess); | |
163 | - expect(modalInstance.close).toHaveBeenCalled(); | |
164 | - done(); | |
165 | - }); | |
166 | - }); | |
167 | - | |
168 | - it('updates current user on logout', (done: Function) => { | |
169 | - buildComponent().then((fixture: ComponentFixture) => { | |
170 | - let navbarComp: Navbar = <Navbar>fixture.debugElement.componentViewChildren[0].componentInstance; | |
171 | - let localScope: ng.IScope = navbarComp["$scope"]; | |
172 | - | |
173 | - // init navbar currentUser with some user | |
174 | - navbarComp["currentUser"] = user; | |
175 | - | |
176 | - // changes the current User to return null, | |
177 | - // and emmit the 'logoutSuccess' event | |
178 | - // just what happens when user logsout | |
179 | - sessionService.currentUser = () => { return null; }; | |
180 | - localScope.$emit(AUTH_EVENTS.logoutSuccess); | |
181 | - expect(navbarComp["currentUser"]).toBeNull(); | |
182 | - done(); | |
183 | - }); | |
184 | - }); | |
185 | - | |
186 | - | |
187 | - }); | |
188 | -}); |
src/app/components/navbar/navbar.ts
... | ... | @@ -1,67 +0,0 @@ |
1 | -import {Component, Inject} from "ng-forward"; | |
2 | -import {LanguageSelector} from "../language-selector/language-selector.component"; | |
3 | - | |
4 | - | |
5 | -import {Session, AuthService, AuthController, IAuthEvents, AUTH_EVENTS} from "./../auth"; | |
6 | -import {User} from "./../../models/interfaces"; | |
7 | - | |
8 | -@Component({ | |
9 | - selector: "acme-navbar", | |
10 | - templateUrl: "app/components/navbar/navbar.html", | |
11 | - directives: [LanguageSelector], | |
12 | - providers: [AuthService, Session] | |
13 | -}) | |
14 | -@Inject("$modal", AuthService, "Session", "$scope", "$state") | |
15 | -export class Navbar { | |
16 | - | |
17 | - private currentUser: User; | |
18 | - private modalInstance: any = null; | |
19 | - /** | |
20 | - * | |
21 | - */ | |
22 | - constructor( | |
23 | - private $modal: any, | |
24 | - private authService: AuthService, | |
25 | - private session: Session, | |
26 | - private $scope: ng.IScope, | |
27 | - private $state: ng.ui.IStateService | |
28 | - ) { | |
29 | - this.currentUser = this.session.currentUser(); | |
30 | - | |
31 | - this.$scope.$on(AUTH_EVENTS.loginSuccess, () => { | |
32 | - if (this.modalInstance) { | |
33 | - this.modalInstance.close(); | |
34 | - this.modalInstance = null; | |
35 | - } | |
36 | - | |
37 | - this.$state.go(this.$state.current, {}, { reload: true }); // TODO move to auth | |
38 | - }); | |
39 | - | |
40 | - this.$scope.$on(AUTH_EVENTS.logoutSuccess, () => { | |
41 | - this.currentUser = this.session.currentUser(); | |
42 | - }); | |
43 | - } | |
44 | - | |
45 | - openLogin() { | |
46 | - this.modalInstance = this.$modal.open({ | |
47 | - templateUrl: 'app/components/auth/login.html', | |
48 | - controller: AuthController, | |
49 | - controllerAs: 'vm', | |
50 | - bindToController: true | |
51 | - }); | |
52 | - }; | |
53 | - | |
54 | - logout() { | |
55 | - this.authService.logout(); | |
56 | - this.$state.go(this.$state.current, {}, { reload: true }); // TODO move to auth | |
57 | - }; | |
58 | - | |
59 | - | |
60 | - | |
61 | - activate() { | |
62 | - if (!this.currentUser) { | |
63 | - this.openLogin(); | |
64 | - } | |
65 | - } | |
66 | - | |
67 | -} |
src/app/components/noosfero-activities/activities.component.spec.ts
... | ... | @@ -1,36 +0,0 @@ |
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | |
2 | -import {Pipe, Input, provide, Component} from 'ng-forward'; | |
3 | -import {provideFilters} from '../../../spec/helpers'; | |
4 | - | |
5 | -import {NoosferoActivities} from './activities.component'; | |
6 | - | |
7 | -const tcb = new TestComponentBuilder(); | |
8 | - | |
9 | -const htmlTemplate: string = '<noosfero-activities [activities]="ctrl.activities"></noosfero-activities>'; | |
10 | - | |
11 | - | |
12 | -describe("Components", () => { | |
13 | - | |
14 | - describe("Noosfero Activities", () => { | |
15 | - | |
16 | - beforeEach(angular.mock.module("templates")); | |
17 | - | |
18 | - @Component({ | |
19 | - selector: 'test-container-component', | |
20 | - template: htmlTemplate, | |
21 | - directives: [NoosferoActivities], | |
22 | - providers: provideFilters("truncateFilter", "stripTagsFilter", "translateFilter") | |
23 | - }) | |
24 | - class BlockContainerComponent { | |
25 | - activities = [{ name: "activity1", verb: "create_article" }, { name: "activity2", verb: "create_article" }]; | |
26 | - } | |
27 | - | |
28 | - it("render a noosfero activity tag for each activity", done => { | |
29 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | |
30 | - expect(fixture.debugElement.queryAll("noosfero-activity").length).toEqual(2); | |
31 | - done(); | |
32 | - }); | |
33 | - }); | |
34 | - }); | |
35 | - | |
36 | -}); |
src/app/components/noosfero-activities/activities.component.ts
... | ... | @@ -1,27 +0,0 @@ |
1 | -import {Component, Input} from "ng-forward"; | |
2 | -import {NoosferoActivity} from "./activity/activity.component"; | |
3 | -import {Activity} from "../../models/interfaces"; | |
4 | - | |
5 | -/** | |
6 | - * @ngdoc controller | |
7 | - * @name NoosferoActivities | |
8 | - * @description | |
9 | - * The controller responsible to retreive profile activities. | |
10 | - */ | |
11 | - | |
12 | -@Component({ | |
13 | - selector: "noosfero-activities", | |
14 | - templateUrl: 'app/components/noosfero-activities/activities.html', | |
15 | - directives: [NoosferoActivity] | |
16 | -}) | |
17 | -export class NoosferoActivities { | |
18 | - | |
19 | - /** | |
20 | - * @ngdoc property | |
21 | - * @propertyOf NoosferoActivities | |
22 | - * @name activities | |
23 | - * @returns {Activity[]} An array of {@link Activity}. | |
24 | - */ | |
25 | - @Input() activities: Activity[]; | |
26 | - | |
27 | -} |
src/app/components/noosfero-activities/activities.html
src/app/components/noosfero-activities/activities.scss
src/app/components/noosfero-activities/activity/activity.component.spec.ts
... | ... | @@ -1,38 +0,0 @@ |
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | |
2 | -import {Pipe, Input, provide, Component} from 'ng-forward'; | |
3 | -import {provideFilters} from '../../../../spec/helpers'; | |
4 | - | |
5 | -import {NoosferoActivity} from './activity.component'; | |
6 | - | |
7 | -const tcb = new TestComponentBuilder(); | |
8 | - | |
9 | -const htmlTemplate: string = '<noosfero-activity [activity]="ctrl.activity"></noosfero-activity>'; | |
10 | - | |
11 | - | |
12 | -describe("Components", () => { | |
13 | - | |
14 | - describe("Noosfero Activity", () => { | |
15 | - | |
16 | - beforeEach(angular.mock.module("templates")); | |
17 | - | |
18 | - @Component({ | |
19 | - selector: 'test-container-component', | |
20 | - template: htmlTemplate, | |
21 | - directives: [NoosferoActivity], | |
22 | - providers: provideFilters("truncateFilter", "stripTagsFilter", "translateFilter") | |
23 | - }) | |
24 | - class BlockContainerComponent { | |
25 | - activity = { name: "activity1", verb: "create_article" }; | |
26 | - } | |
27 | - | |
28 | - it("render the specific template for an activity verb", done => { | |
29 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | |
30 | - let component: NoosferoActivity = fixture.debugElement.componentViewChildren[0].componentInstance; | |
31 | - expect(component.getActivityTemplate()).toEqual('app/components/noosfero-activities/activity/create_article.html'); | |
32 | - expect(fixture.debugElement.queryAll(".activity.create_article").length).toEqual(1); | |
33 | - done(); | |
34 | - }); | |
35 | - }); | |
36 | - }); | |
37 | - | |
38 | -}); |
src/app/components/noosfero-activities/activity/activity.component.ts
... | ... | @@ -1,16 +0,0 @@ |
1 | -import {Component, Input} from "ng-forward"; | |
2 | -import {Activity} from "../../../models/interfaces"; | |
3 | - | |
4 | -@Component({ | |
5 | - selector: "noosfero-activity", | |
6 | - templateUrl: 'app/components/noosfero-activities/activity/activity.html' | |
7 | -}) | |
8 | -export class NoosferoActivity { | |
9 | - | |
10 | - @Input() activity: Activity; | |
11 | - | |
12 | - getActivityTemplate() { | |
13 | - return 'app/components/noosfero-activities/activity/' + this.activity.verb + '.html'; | |
14 | - } | |
15 | - | |
16 | -} |
src/app/components/noosfero-activities/activity/activity.html
src/app/components/noosfero-activities/activity/add_member_in_community.html
... | ... | @@ -1,13 +0,0 @@ |
1 | -<timeline-badge class="info"> | |
2 | - <i class="fa fa-user-plus"></i> | |
3 | -</timeline-badge> | |
4 | -<timeline-panel> | |
5 | - <timeline-heading> | |
6 | - <h4 class="timeline-title"> | |
7 | - <a ui-sref="main.profile.info({profile: ctrl.activity.user.identifier})"><strong ng-bind="ctrl.activity.user.name"></strong></a> | |
8 | - <span> {{"activities.add_member_in_community.description" | translate}}</span> | |
9 | - </h4> | |
10 | - <p><small class="text-muted"><i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.activity.created_at | dateFormat"></span></small></p> | |
11 | - </timeline-heading> | |
12 | - <div class="timeline-body"></div> | |
13 | -</timeline-panel> |
src/app/components/noosfero-activities/activity/create_article.html
... | ... | @@ -1,26 +0,0 @@ |
1 | -<timeline-badge class="success"> | |
2 | - <i class="fa fa-file-text"></i> | |
3 | -</timeline-badge> | |
4 | -<timeline-panel> | |
5 | - <timeline-heading> | |
6 | - <h4 class="timeline-title"> | |
7 | - <a ui-sref="main.profile.info({profile: ctrl.activity.user.identifier})"><strong ng-bind="ctrl.activity.user.name"></strong></a> | |
8 | - <span> {{"activities.create_article.description" | translate}} </span> | |
9 | - <a ui-sref="main.profile.info({profile: ctrl.activity.target.article.profile.identifier})"> | |
10 | - <strong ng-bind="ctrl.activity.target.article.profile.name"></strong></span> | |
11 | - </a> | |
12 | - </h4> | |
13 | - <p><small class="text-muted"><i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.activity.created_at | dateFormat"></span></small></p> | |
14 | - </timeline-heading> | |
15 | - <div class="timeline-body"> | |
16 | - <div class="article"> | |
17 | - <div class="title"> | |
18 | - <a ui-sref="main.profile.page({profile: ctrl.activity.target.article.profile.identifier, page: ctrl.activity.target.article.path})" | |
19 | - ng-bind="ctrl.activity.target.article.title"></a> | |
20 | - </div> | |
21 | - <div class="lead small"> | |
22 | - <div ng-bind-html="ctrl.activity.target.article.body | stripTags | truncate: 100 : '...': true"></div> | |
23 | - </div> | |
24 | - </div> | |
25 | - </div> | |
26 | -</timeline-panel> |
src/app/components/noosfero-activities/activity/index.ts
... | ... | @@ -1 +0,0 @@ |
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-activities/activity/new_friendship.html
... | ... | @@ -1,18 +0,0 @@ |
1 | -<timeline-badge class="info"> | |
2 | - <i class="fa fa-user-plus"></i> | |
3 | -</timeline-badge> | |
4 | -<timeline-panel> | |
5 | - <timeline-heading> | |
6 | - <h4 class="timeline-title"> | |
7 | - <a ui-sref="main.profile.info({profile: ctrl.activity.user.identifier})"><strong ng-bind="ctrl.activity.user.name"></strong></a> | |
8 | - <span> {{"activities.new_friendship.description" | translate:{friends: ctrl.activity.params.friend_name.length}:"messageformat" }} </span> | |
9 | - <span class="comma-separated"> | |
10 | - <a class="separated-item" ui-sref="main.profile.info({profile: ctrl.activity.params.friend_url[$index].profile})" ng-repeat="friend in ctrl.activity.params.friend_name"> | |
11 | - <strong ng-bind="friend"></strong> | |
12 | - </a> | |
13 | - </span> | |
14 | - </h4> | |
15 | - <p><small class="text-muted"><i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.activity.created_at | dateFormat"></span></small></p> | |
16 | - </timeline-heading> | |
17 | - <div class="timeline-body"></div> | |
18 | -</timeline-panel> |
src/app/components/noosfero-activities/index.ts
... | ... | @@ -1 +0,0 @@ |
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-articles/article/article.html
... | ... | @@ -1,23 +0,0 @@ |
1 | -<div class="article"> | |
2 | - <div class="page-header"> | |
3 | - <h3 ng-bind="ctrl.article.title"></h3> | |
4 | - </div> | |
5 | - | |
6 | - <div class="sub-header clearfix"> | |
7 | - <div class="page-info pull-right small text-muted"> | |
8 | - <span class="time"> | |
9 | - <i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.article.created_at | dateFormat"></span> | |
10 | - </span> | |
11 | - <span class="author" ng-if="ctrl.article.author"> | |
12 | - <i class="fa fa-user"></i> | |
13 | - <a ui-sref="main.profile.home({profile: ctrl.article.author.identifier})"> | |
14 | - <span class="author-name" ng-bind="ctrl.article.author.name"></span> | |
15 | - </a> | |
16 | - </span> | |
17 | - </div> | |
18 | - </div> | |
19 | - | |
20 | - <div class="page-body"> | |
21 | - <div ng-bind-html="ctrl.article.body"></div> | |
22 | - </div> | |
23 | -</div> |
src/app/components/noosfero-articles/article/article.scss
src/app/components/noosfero-articles/article/article_view.spec.ts
... | ... | @@ -1,108 +0,0 @@ |
1 | - | |
2 | -import {Input, provide, Component} from 'ng-forward'; | |
3 | -import {ArticleView, ArticleDefaultView} from './article_view'; | |
4 | - | |
5 | -import {createComponentFromClass, quickCreateComponent} from "../../../../spec/helpers"; | |
6 | - | |
7 | -// this htmlTemplate will be re-used between the container components in this spec file | |
8 | -const htmlTemplate: string = '<noosfero-article [article]="ctrl.article" [profile]="ctrl.profile"></noosfero-article>'; | |
9 | - | |
10 | - | |
11 | -describe("Components", () => { | |
12 | - | |
13 | - describe("ArticleView Component", () => { | |
14 | - | |
15 | - // the karma preprocessor html2js transform the templates html into js files which put | |
16 | - // the templates to the templateCache into the module templates | |
17 | - // we need to load the module templates here as the template for the | |
18 | - // component Noosfero ArtileView will be load on our tests | |
19 | - beforeEach(angular.mock.module("templates")); | |
20 | - | |
21 | - it("renders the default component when no specific component is found", (done: Function) => { | |
22 | - // Creating a container component (ArticleContainerComponent) to include | |
23 | - // the component under test (ArticleView) | |
24 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleView] }) | |
25 | - class ArticleContainerComponent { | |
26 | - article = { type: 'anyArticleType' }; | |
27 | - profile = { name: 'profile-name' }; | |
28 | - constructor() { | |
29 | - } | |
30 | - } | |
31 | - | |
32 | - createComponentFromClass(ArticleContainerComponent).then((fixture) => { | |
33 | - // and here we can inspect and run the test assertions | |
34 | - | |
35 | - // gets the children component of ArticleContainerComponent | |
36 | - let articleView: ArticleView = fixture.debugElement.componentViewChildren[0].componentInstance; | |
37 | - | |
38 | - // and checks if the article View rendered was the Default Article View | |
39 | - expect(articleView.constructor.prototype).toEqual(ArticleDefaultView.prototype); | |
40 | - | |
41 | - // done needs to be called (it isn't really needed, as we can read in | |
42 | - // here (https://github.com/ngUpgraders/ng-forward/blob/master/API.md#createasync) | |
43 | - // because createAsync in ng-forward is not really async, but as the intention | |
44 | - // here is write tests in angular 2 ways, this is recommended | |
45 | - done(); | |
46 | - }); | |
47 | - | |
48 | - }); | |
49 | - | |
50 | - it("receives the article and profile as inputs", (done: Function) => { | |
51 | - | |
52 | - // Creating a container component (ArticleContainerComponent) to include | |
53 | - // the component under test (ArticleView) | |
54 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleView] }) | |
55 | - class ArticleContainerComponent { | |
56 | - article = { type: 'anyArticleType' }; | |
57 | - profile = { name: 'profile-name' }; | |
58 | - constructor() { | |
59 | - } | |
60 | - } | |
61 | - | |
62 | - // uses the TestComponentBuilder instance to initialize the component | |
63 | - createComponentFromClass(ArticleContainerComponent).then((fixture) => { | |
64 | - // and here we can inspect and run the test assertions | |
65 | - let articleView: ArticleView = fixture.debugElement.componentViewChildren[0].componentInstance; | |
66 | - | |
67 | - // assure the article object inside the ArticleView matches | |
68 | - // the provided through the parent component | |
69 | - expect(articleView.article.type).toEqual("anyArticleType"); | |
70 | - expect(articleView.profile.name).toEqual("profile-name"); | |
71 | - | |
72 | - // done needs to be called (it isn't really needed, as we can read in | |
73 | - // here (https://github.com/ngUpgraders/ng-forward/blob/master/API.md#createasync) | |
74 | - // because createAsync in ng-forward is not really async, but as the intention | |
75 | - // here is write tests in angular 2 ways, this is recommended | |
76 | - done(); | |
77 | - }); | |
78 | - }); | |
79 | - | |
80 | - | |
81 | - it("renders a article view which matches to the article type", done => { | |
82 | - // NoosferoTinyMceArticle component created to check if it will be used | |
83 | - // when a article with type 'TinyMceArticle' is provided to the noosfero-article (ArticleView) | |
84 | - // *** Important *** - the selector is what ng-forward uses to define the name of the directive provider | |
85 | - @Component({ selector: 'noosfero-tiny-mce-article', template: "<h1>TinyMceArticle</h1>" }) | |
86 | - class TinyMceArticleView { | |
87 | - @Input() article: any; | |
88 | - @Input() profile: any; | |
89 | - } | |
90 | - | |
91 | - // Creating a container component (ArticleContainerComponent) to include our NoosferoTinyMceArticle | |
92 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [ArticleView, TinyMceArticleView] }) | |
93 | - class CustomArticleType { | |
94 | - article = { type: 'TinyMceArticle' }; | |
95 | - profile = { name: 'profile-name' }; | |
96 | - constructor() { | |
97 | - } | |
98 | - } | |
99 | - createComponentFromClass(CustomArticleType).then(fixture => { | |
100 | - let myComponent: CustomArticleType = fixture.componentInstance; | |
101 | - expect(myComponent.article.type).toEqual("TinyMceArticle"); | |
102 | - expect(fixture.debugElement.componentViewChildren[0].text()).toEqual("TinyMceArticle"); | |
103 | - done(); | |
104 | - }); | |
105 | - }); | |
106 | - | |
107 | - }); | |
108 | -}); | |
109 | 0 | \ No newline at end of file |
src/app/components/noosfero-articles/article/article_view.ts
... | ... | @@ -1,57 +0,0 @@ |
1 | -import { bundle, Input, Inject, Component, Directive } from 'ng-forward'; | |
2 | -import {ArticleBlog} from "../blog/blog.component"; | |
3 | - | |
4 | -/** | |
5 | - * @ngdoc controller | |
6 | - * @name ArticleDefaultView | |
7 | - * @description | |
8 | - * A default view for Noosfero Articles. If the specific article view is | |
9 | - * not implemented, then this view is used. | |
10 | - */ | |
11 | -@Component({ | |
12 | - selector: 'noosfero-default-article', | |
13 | - templateUrl: 'app/components/noosfero-articles/article/article.html' | |
14 | -}) | |
15 | -export class ArticleDefaultView { | |
16 | - | |
17 | - @Input() article: any; | |
18 | - @Input() profile: any; | |
19 | - | |
20 | -} | |
21 | - | |
22 | -/** | |
23 | - * @ngdoc controller | |
24 | - * @name ArticleView | |
25 | - * @description | |
26 | - * A dynamic view for articles. It uses the article type to replace | |
27 | - * the default template with the custom article directive. | |
28 | - */ | |
29 | -@Component({ | |
30 | - selector: 'noosfero-article', | |
31 | - template: 'not-used', | |
32 | - directives: [ArticleDefaultView, ArticleBlog] | |
33 | -}) | |
34 | -@Inject("$element", "$scope", "$injector", "$compile") | |
35 | -export class ArticleView { | |
36 | - | |
37 | - @Input() article: any; | |
38 | - @Input() profile: any; | |
39 | - directiveName: string; | |
40 | - | |
41 | - ngOnInit() { | |
42 | - let specificDirective = 'noosfero' + this.article.type; | |
43 | - this.directiveName = "noosfero-default-article"; | |
44 | - if (this.$injector.has(specificDirective + 'Directive')) { | |
45 | - this.directiveName = specificDirective.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); | |
46 | - } | |
47 | - this.$element.replaceWith(this.$compile('<' + this.directiveName + ' [article]="ctrl.article" [profile]="ctrl.profile"></' + this.directiveName + '>')(this.$scope)); | |
48 | - } | |
49 | - | |
50 | - constructor( | |
51 | - private $element: any, | |
52 | - private $scope: ng.IScope, | |
53 | - private $injector: ng.auto.IInjectorService, | |
54 | - private $compile: ng.ICompileService) { | |
55 | - | |
56 | - } | |
57 | -} |
src/app/components/noosfero-articles/article/index.ts
src/app/components/noosfero-articles/blog/blog.component.spec.ts
... | ... | @@ -1,132 +0,0 @@ |
1 | -import { | |
2 | - providers | |
3 | -} from 'ng-forward/cjs/testing/providers'; | |
4 | - | |
5 | -import { | |
6 | - Input, | |
7 | - Component | |
8 | -} from 'ng-forward'; | |
9 | -import { | |
10 | - ArticleBlog | |
11 | -} from './blog.component'; | |
12 | - | |
13 | -import { | |
14 | - createComponentFromClass, | |
15 | - quickCreateComponent, | |
16 | - provideEmptyObjects, | |
17 | - createProviderToValue, | |
18 | - provideFilters | |
19 | -} from "../../../../spec/helpers.ts"; | |
20 | - | |
21 | -// this htmlTemplate will be re-used between the container components in this spec file | |
22 | -const htmlTemplate: string = '<noosfero-blog [article]="ctrl.article" [profile]="ctrl.profile"></noosfero-blog>'; | |
23 | - | |
24 | -describe("Blog Component", () => { | |
25 | - | |
26 | - function promiseResultTemplate(response ? : {}) { | |
27 | - let thenFuncEmpty = (func: Function) => { | |
28 | - // does nothing | |
29 | - }; | |
30 | - if (response) { | |
31 | - return { | |
32 | - then: (func: (response: any) => void) => { | |
33 | - func(response); | |
34 | - } | |
35 | - }; | |
36 | - } else { | |
37 | - return { | |
38 | - then: (func: (response: any) => void) => { | |
39 | - // does nothing | |
40 | - } | |
41 | - }; | |
42 | - } | |
43 | - } | |
44 | - | |
45 | - let articleService = { | |
46 | - getChildren: (article_id: number, filters: {}) => { | |
47 | - return promiseResultTemplate(null); | |
48 | - } | |
49 | - }; | |
50 | - | |
51 | - @Component({ | |
52 | - selector: 'test-container-component', | |
53 | - template: htmlTemplate, | |
54 | - directives: [ArticleBlog], | |
55 | - providers: [ | |
56 | - provideEmptyObjects('Restangular'), | |
57 | - createProviderToValue('ArticleService', articleService), | |
58 | - provideFilters('truncateFilter') | |
59 | - ] | |
60 | - }) | |
61 | - class BlogContainerComponent { | |
62 | - article = { | |
63 | - type: 'anyArticleType' | |
64 | - }; | |
65 | - profile = { | |
66 | - name: 'profile-name' | |
67 | - }; | |
68 | - } | |
69 | - | |
70 | - beforeEach(() => { | |
71 | - | |
72 | - // the karma preprocessor html2js transform the templates html into js files which put | |
73 | - // the templates to the templateCache into the module templates | |
74 | - // we need to load the module templates here as the template for the | |
75 | - // component Noosfero ArtileView will be load on our tests | |
76 | - angular.mock.module("templates") | |
77 | - | |
78 | - providers((provide: any) => { | |
79 | - return <any > [ | |
80 | - provide('ArticleService', { | |
81 | - useValue: articleService | |
82 | - }) | |
83 | - ] | |
84 | - }); | |
85 | - }); | |
86 | - | |
87 | - it("renders the blog content", (done: Function) => { | |
88 | - | |
89 | - createComponentFromClass(BlogContainerComponent).then((fixture) => { | |
90 | - | |
91 | - expect(fixture.debugElement.query('div.blog').length).toEqual(1); | |
92 | - | |
93 | - done(); | |
94 | - }); | |
95 | - }); | |
96 | - | |
97 | - it("verify the blog data", (done: Function) => { | |
98 | - | |
99 | - // defining a mock result to articleService.getChildren method | |
100 | - 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 | - }); | |
112 | - }; | |
113 | - | |
114 | - createComponentFromClass(BlogContainerComponent).then((fixture) => { | |
115 | - | |
116 | - // gets the children component of BlogContainerComponent | |
117 | - let articleBlog: BlogContainerComponent = fixture.debugElement.componentViewChildren[0].componentInstance; | |
118 | - | |
119 | - // check if the component property are the provided by the mocked articleService | |
120 | - let post = { | |
121 | - id: 1, | |
122 | - title: 'The article test' | |
123 | - }; | |
124 | - expect(( < any > articleBlog)["posts"][0]).toEqual(jasmine.objectContaining(post)); | |
125 | - expect(( < any > articleBlog)["totalPosts"]).toEqual(1); | |
126 | - | |
127 | - done(); | |
128 | - }); | |
129 | - | |
130 | - }); | |
131 | - | |
132 | -}); | |
133 | 0 | \ No newline at end of file |
src/app/components/noosfero-articles/blog/blog.component.ts
... | ... | @@ -1,48 +0,0 @@ |
1 | -import {Component, Input, Inject} from "ng-forward"; | |
2 | - | |
3 | -import {Article, Profile} from "./../../../models/interfaces"; | |
4 | -import {ArticleService} from "../../../../lib/ng-noosfero-api/http/article.service"; | |
5 | - | |
6 | -/** | |
7 | - * @ngdoc controller | |
8 | - * @name ArticleBlog | |
9 | - * @description | |
10 | - * An specific {@link ArticleView} for Blog articles. | |
11 | - */ | |
12 | -@Component({ | |
13 | - selector: "noosfero-blog", | |
14 | - templateUrl: "app/components/noosfero-articles/blog/blog.html" | |
15 | -}) | |
16 | -@Inject(ArticleService) | |
17 | -export class ArticleBlog { | |
18 | - | |
19 | - @Input() article: Article; | |
20 | - @Input() profile: Profile; | |
21 | - | |
22 | - private posts: any[]; | |
23 | - private perPage: number = 3; | |
24 | - private currentPage: number; | |
25 | - private totalPosts: number = 0; | |
26 | - | |
27 | - constructor(private articleService: ArticleService) { } | |
28 | - | |
29 | - ngOnInit() { | |
30 | - this.loadPage(); | |
31 | - } | |
32 | - | |
33 | - loadPage() { | |
34 | - let filters = { | |
35 | - content_type: "TinyMceArticle", | |
36 | - per_page: this.perPage, | |
37 | - page: this.currentPage | |
38 | - }; | |
39 | - | |
40 | - this.articleService | |
41 | - .getChildren(this.article.id, filters) | |
42 | - .then((response: restangular.IResponse) => { | |
43 | - this.totalPosts = <number>(<any>response.headers("total")); | |
44 | - this.posts = response.data.articles; | |
45 | - }); | |
46 | - } | |
47 | - | |
48 | -} |
src/app/components/noosfero-articles/blog/blog.html
... | ... | @@ -1,24 +0,0 @@ |
1 | -<div class="blog"> | |
2 | - <div class="blog-cover" ng-show="ctrl.article.image"> | |
3 | - <img ng-src="{{ctrl.article.image.url}}" class="img-responsive"> | |
4 | - <h3 ng-bind="ctrl.article.title"></h3> | |
5 | - </div> | |
6 | - | |
7 | - <div class="page-header" ng-show="!ctrl.article.image"> | |
8 | - <h3 ng-bind="ctrl.article.title"></h3> | |
9 | - </div> | |
10 | - | |
11 | - <div> | |
12 | - <div ng-repeat="child in ctrl.posts | orderBy: 'created_at':true"> | |
13 | - <div class="page-header"> | |
14 | - <a class="title" ui-sref="main.profile.page({profile: ctrl.profile.identifier, page: child.path})"><h4 ng-bind="child.title"></h4></a> | |
15 | - <div class="post-lead" ng-bind-html="child.body | truncate: 500: '...': true"></div> | |
16 | - </div> | |
17 | - </div> | |
18 | - </div> | |
19 | - | |
20 | - <pagination ng-model="ctrl.currentPage" total-items="ctrl.totalPosts" class="pagination-sm center-block" | |
21 | - boundary-links="true" items-per-page="ctrl.perPage" ng-change="ctrl.loadPage()" | |
22 | - first-text="«" last-text="»" previous-text="‹" next-text="›"> | |
23 | - </pagination> | |
24 | -</div> |
src/app/components/noosfero-articles/blog/blog.scss
src/app/components/noosfero-articles/blog/index.ts
src/app/components/noosfero-articles/index.ts
... | ... | @@ -1 +0,0 @@ |
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-blocks/block.component.spec.ts
... | ... | @@ -1,91 +0,0 @@ |
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | |
2 | -import {Input, provide, Component} from 'ng-forward'; | |
3 | - | |
4 | -import {Block} from './block.component'; | |
5 | - | |
6 | -const tcb = new TestComponentBuilder(); | |
7 | - | |
8 | -const htmlTemplate: string = '<noosfero-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-block>'; | |
9 | - | |
10 | -describe("Components", () => { | |
11 | - describe("Block Component", () => { | |
12 | - | |
13 | - // the karma preprocessor html2js transform the templates html into js files which put | |
14 | - // the templates to the templateCache into the module templates | |
15 | - // we need to load the module templates here as the template for the | |
16 | - // component Block will be load on our tests | |
17 | - beforeEach(angular.mock.module("templates")); | |
18 | - | |
19 | - it("receives the block and the owner as inputs", done => { | |
20 | - | |
21 | - // Creating a container component (BlockContainerComponent) to include | |
22 | - // the component under test (Block) | |
23 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [Block] }) | |
24 | - class BlockContainerComponent { | |
25 | - block = { type: 'Block' }; | |
26 | - owner = { name: 'profile-name' }; | |
27 | - constructor() { | |
28 | - } | |
29 | - } | |
30 | - | |
31 | - // uses the TestComponentBuilder instance to initialize the component | |
32 | - tcb | |
33 | - .createAsync(BlockContainerComponent).then(fixture => { | |
34 | - // and here we can inspect and run the test assertions | |
35 | - let myComponent: Block = fixture.componentInstance; | |
36 | - | |
37 | - // assure the block object inside the Block matches | |
38 | - // the provided through the parent component | |
39 | - expect(myComponent.block.type).toEqual("Block"); | |
40 | - expect(myComponent.owner.name).toEqual("profile-name"); | |
41 | - done(); | |
42 | - }); | |
43 | - }); | |
44 | - | |
45 | - | |
46 | - it("renders a component which matches to the block type", done => { | |
47 | - // CustomBlock component created to check if it will be used | |
48 | - // when a block with type 'CustomBlock' is provided to the noosfero-block (Block) | |
49 | - // *** Important *** - the selector is what ng-forward uses to define the name of the directive provider | |
50 | - @Component({ selector: 'noosfero-custom-block', template: "<h1>My Custom Block</h1>" }) | |
51 | - class CustomBlock { | |
52 | - @Input() block: any; | |
53 | - @Input() owner: any; | |
54 | - } | |
55 | - | |
56 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [Block, CustomBlock] }) | |
57 | - class CustomBlockType { | |
58 | - block = { type: 'CustomBlock' }; | |
59 | - owner = { name: 'profile-name' }; | |
60 | - constructor() { | |
61 | - } | |
62 | - } | |
63 | - tcb | |
64 | - .createAsync(CustomBlockType).then(fixture => { | |
65 | - let myComponent: CustomBlockType = fixture.componentInstance; | |
66 | - expect(myComponent.block.type).toEqual("CustomBlock"); | |
67 | - expect(fixture.debugElement.componentViewChildren[0].text()).toEqual("My Custom Block"); | |
68 | - done(); | |
69 | - }); | |
70 | - }); | |
71 | - | |
72 | - | |
73 | - it("renders the default block when hasn't defined a block type", done => { | |
74 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [Block] }) | |
75 | - class CustomBlockType { | |
76 | - block: any = { type: null }; | |
77 | - owner: any = { name: 'profile-name' }; | |
78 | - constructor() { | |
79 | - } | |
80 | - } | |
81 | - tcb | |
82 | - .createAsync(CustomBlockType).then(fixture => { | |
83 | - let myComponent: CustomBlockType = fixture.componentInstance; | |
84 | - expect(myComponent.block.type).toBeNull(); | |
85 | - expect(!!fixture.debugElement.nativeElement.querySelector("noosfero-default-block")).toBeTruthy(); | |
86 | - done(); | |
87 | - }); | |
88 | - }); | |
89 | - | |
90 | - }); | |
91 | -}); | |
92 | 0 | \ No newline at end of file |
src/app/components/noosfero-blocks/block.component.ts
... | ... | @@ -1,20 +0,0 @@ |
1 | -import { Input, Inject, Component } from 'ng-forward'; | |
2 | - | |
3 | -@Component({ | |
4 | - selector: 'noosfero-block', | |
5 | - template: '<div></div>' | |
6 | -}) | |
7 | -@Inject("$element", "$scope", "$injector", "$compile") | |
8 | -export class Block { | |
9 | - | |
10 | - @Input() block: any; | |
11 | - @Input() owner: any; | |
12 | - | |
13 | - ngOnInit() { | |
14 | - let blockName = (this.block && this.block.type) ? this.block.type.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() : "default-block"; | |
15 | - this.$element.replaceWith(this.$compile('<noosfero-' + blockName + ' [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-' + blockName + '>')(this.$scope)); | |
16 | - } | |
17 | - | |
18 | - constructor(private $element: any, private $scope: ng.IScope, private $injector: ng.auto.IInjectorService, private $compile: ng.ICompileService) { | |
19 | - } | |
20 | -} |
src/app/components/noosfero-blocks/block.scss
src/app/components/noosfero-blocks/index.ts
src/app/components/noosfero-blocks/link-list/index.ts
src/app/components/noosfero-blocks/link-list/link-list.component.spec.ts
... | ... | @@ -1,65 +0,0 @@ |
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | |
2 | -import {Pipe, Input, provide, Component} from 'ng-forward'; | |
3 | -import {provideFilters} from '../../../../spec/helpers'; | |
4 | - | |
5 | -import {LinkListBlock} from './link-list.component'; | |
6 | - | |
7 | -const tcb = new TestComponentBuilder(); | |
8 | - | |
9 | -const htmlTemplate: string = '<noosfero-link-list-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-link-list-block>'; | |
10 | - | |
11 | - | |
12 | -describe("Components", () => { | |
13 | - | |
14 | - describe("Link List Block Component", () => { | |
15 | - | |
16 | - beforeEach(angular.mock.module("templates")); | |
17 | - | |
18 | - it("receives the block and the owner as inputs", done => { | |
19 | - | |
20 | - // Creating a container component (BlockContainerComponent) to include | |
21 | - // the component under test (Block) | |
22 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [LinkListBlock] }) | |
23 | - class BlockContainerComponent { | |
24 | - block = { type: 'Block' }; | |
25 | - owner = { name: 'profile-name' }; | |
26 | - constructor() { | |
27 | - } | |
28 | - } | |
29 | - | |
30 | - // uses the TestComponentBuilder instance to initialize the component | |
31 | - //.overrideView(LinkListBlock, { template: 'asdasdasd', pipes: [NoosferoTemplate] }) | |
32 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | |
33 | - // and here we can inspect and run the test assertions | |
34 | - let myComponent: LinkListBlock = fixture.componentInstance; | |
35 | - | |
36 | - // assure the block object inside the Block matches | |
37 | - // the provided through the parent component | |
38 | - expect(myComponent.block.type).toEqual("Block"); | |
39 | - expect(myComponent.owner.name).toEqual("profile-name"); | |
40 | - done(); | |
41 | - }); | |
42 | - }); | |
43 | - | |
44 | - | |
45 | - it("display links stored in block settings", done => { | |
46 | - | |
47 | - @Component({ | |
48 | - selector: 'test-container-component', | |
49 | - template: htmlTemplate, | |
50 | - directives: [LinkListBlock], | |
51 | - providers: provideFilters("noosferoTemplateFilter") | |
52 | - }) | |
53 | - class CustomBlockType { | |
54 | - block: any = { settings: { links: [{ name: 'link1', address: 'address1' }, { name: 'link2', address: 'address2' }] } }; | |
55 | - owner: any = { name: 'profile-name' }; | |
56 | - } | |
57 | - tcb.createAsync(CustomBlockType).then(fixture => { | |
58 | - expect(fixture.debugElement.queryAll(".link-list-block a").length).toEqual(2); | |
59 | - done(); | |
60 | - }); | |
61 | - }); | |
62 | - | |
63 | - }); | |
64 | - | |
65 | -}); | |
66 | 0 | \ No newline at end of file |
src/app/components/noosfero-blocks/link-list/link-list.component.ts
... | ... | @@ -1,20 +0,0 @@ |
1 | -import {Component, Input} from "ng-forward"; | |
2 | - | |
3 | -@Component({ | |
4 | - selector: "noosfero-link-list-block", | |
5 | - templateUrl: "app/components/noosfero-blocks/link-list/link-list.html" | |
6 | -}) | |
7 | -export class LinkListBlock { | |
8 | - | |
9 | - @Input() block: any; | |
10 | - @Input() owner: any; | |
11 | - | |
12 | - links: any; | |
13 | - | |
14 | - ngOnInit() { | |
15 | - if (this.block && this.block.settings) { | |
16 | - this.links = this.block.settings.links; | |
17 | - } | |
18 | - } | |
19 | - | |
20 | -} |
src/app/components/noosfero-blocks/link-list/link-list.html
src/app/components/noosfero-blocks/link-list/link-list.scss
... | ... | @@ -1,34 +0,0 @@ |
1 | -.icon-event { | |
2 | - @extend .fa-calendar; | |
3 | -} | |
4 | -.icon-photos { | |
5 | - @extend .fa-photo; | |
6 | -} | |
7 | -.icon-edit { | |
8 | - @extend .fa-edit; | |
9 | -} | |
10 | -.icon-ok { | |
11 | - @extend .fa-check; | |
12 | -} | |
13 | -.icon-send { | |
14 | - @extend .fa-send-o; | |
15 | -} | |
16 | -.icon-menu-people { | |
17 | - @extend .fa-user; | |
18 | -} | |
19 | -.icon-forum { | |
20 | - @extend .fa-users; | |
21 | -} | |
22 | -.icon-new { | |
23 | - @extend .fa-file-o; | |
24 | -} | |
25 | -.icon-save { | |
26 | - @extend .fa-save; | |
27 | -} | |
28 | - | |
29 | -.link-list-block { | |
30 | - a i { | |
31 | - line-height: 25px; | |
32 | - color: #949494; | |
33 | - } | |
34 | -} |
src/app/components/noosfero-blocks/main-block/index.ts
... | ... | @@ -1 +0,0 @@ |
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-blocks/main-block/main-block.component.spec.ts
... | ... | @@ -1,41 +0,0 @@ |
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | |
2 | -import {Input, provide, Component, StateConfig} from 'ng-forward'; | |
3 | - | |
4 | -import {MainBlock} from './main-block.component'; | |
5 | -import {NoosferoApp} from '../../../index.module'; | |
6 | - | |
7 | -const tcb = new TestComponentBuilder(); | |
8 | - | |
9 | -const htmlTemplate: string = '<noosfero-main-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-main-block>'; | |
10 | - | |
11 | -describe("Components", () => { | |
12 | - describe("Main Block Component", () => { | |
13 | - | |
14 | - // the karma preprocessor html2js transform the templates html into js files which put | |
15 | - // the templates to the templateCache into the module templates | |
16 | - // we need to load the module templates here as the template for the | |
17 | - // component Block will be load on our tests | |
18 | - beforeEach(angular.mock.module("templates")); | |
19 | - | |
20 | - it("check if the main block has a tag with ui-view attribute", done => { | |
21 | - | |
22 | - // Creating a container component (BlockContainerComponent) to include | |
23 | - // the component under test (Block) | |
24 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [MainBlock] }) | |
25 | - class BlockContainerComponent { | |
26 | - } | |
27 | - | |
28 | - // uses the TestComponentBuilder instance to initialize the component | |
29 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | |
30 | - // and here we can inspect and run the test assertions | |
31 | - //let myComponent: MainBlock = fixture.componentInstance; | |
32 | - | |
33 | - // assure the block object inside the Block matches | |
34 | - // the provided through the parent component | |
35 | - expect(fixture.debugElement.queryAll('[ui-view="mainBlockContent"]').length).toEqual(1) | |
36 | - done(); | |
37 | - }); | |
38 | - }); | |
39 | - | |
40 | - }); | |
41 | -}); | |
42 | 0 | \ No newline at end of file |
src/app/components/noosfero-blocks/main-block/main-block.component.ts
src/app/components/noosfero-blocks/main-block/main-block.html
... | ... | @@ -1 +0,0 @@ |
1 | -<div ui-view="mainBlockContent" autoscroll></div> |
src/app/components/noosfero-blocks/members-block/index.ts
... | ... | @@ -1 +0,0 @@ |
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-blocks/members-block/members-block.component.spec.ts
... | ... | @@ -1,53 +0,0 @@ |
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | |
2 | -import {Provider, Input, provide, Component} from 'ng-forward'; | |
3 | - | |
4 | -import {MembersBlock} from './members-block.component'; | |
5 | - | |
6 | -const htmlTemplate: string = '<noosfero-members-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-members-block>'; | |
7 | - | |
8 | -const tcb = new TestComponentBuilder(); | |
9 | - | |
10 | -describe("Components", () => { | |
11 | - describe("Members Block Component", () => { | |
12 | - | |
13 | - beforeEach(angular.mock.module("templates")); | |
14 | - | |
15 | - let state = jasmine.createSpyObj("state", ["go"]); | |
16 | - let providers = [ | |
17 | - new Provider('truncateFilter', { useValue: () => { } }), | |
18 | - new Provider('stripTagsFilter', { useValue: () => { } }), | |
19 | - new Provider('$state', { useValue: state }), | |
20 | - new Provider('ProfileService', { | |
21 | - useValue: { | |
22 | - getProfileMembers: (profileId: number, filters: any): any => { | |
23 | - return Promise.resolve({ data: { people: [{ identifier: "person1" }] } }); | |
24 | - } | |
25 | - } | |
26 | - }), | |
27 | - ]; | |
28 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [MembersBlock], providers: providers }) | |
29 | - class BlockContainerComponent { | |
30 | - block = { type: 'Block', settings: {} }; | |
31 | - owner = { name: 'profile-name' }; | |
32 | - constructor() { | |
33 | - } | |
34 | - } | |
35 | - | |
36 | - it("get members of the block owner", done => { | |
37 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | |
38 | - let block: MembersBlock = fixture.debugElement.componentViewChildren[0].componentInstance; | |
39 | - expect(block.members).toEqual([{ identifier: "person1" }]); | |
40 | - done(); | |
41 | - }); | |
42 | - }); | |
43 | - | |
44 | - it("render the profile image for each member", done => { | |
45 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | |
46 | - fixture.debugElement.getLocal("$rootScope").$apply(); | |
47 | - expect(fixture.debugElement.queryAll("noosfero-profile-image").length).toEqual(1); | |
48 | - done(); | |
49 | - }); | |
50 | - }); | |
51 | - | |
52 | - }); | |
53 | -}); | |
54 | 0 | \ No newline at end of file |
src/app/components/noosfero-blocks/members-block/members-block.component.ts
... | ... | @@ -1,25 +0,0 @@ |
1 | -import {Input, Inject, Component} from "ng-forward"; | |
2 | -import {ProfileService} from "../../../../lib/ng-noosfero-api/http/profile.service"; | |
3 | - | |
4 | -@Component({ | |
5 | - selector: "noosfero-members-block", | |
6 | - templateUrl: 'app/components/noosfero-blocks/members-block/members-block.html', | |
7 | -}) | |
8 | -@Inject(ProfileService) | |
9 | -export class MembersBlock { | |
10 | - | |
11 | - @Input() block: any; | |
12 | - @Input() owner: any; | |
13 | - | |
14 | - members: any = []; | |
15 | - | |
16 | - constructor(private profileService: ProfileService) { | |
17 | - | |
18 | - } | |
19 | - | |
20 | - ngOnInit() { | |
21 | - this.profileService.getProfileMembers(this.owner.id, { per_page: 6 }).then((response: any) => { | |
22 | - this.members = response.data.people; | |
23 | - }); | |
24 | - } | |
25 | -} |
src/app/components/noosfero-blocks/members-block/members-block.html
src/app/components/noosfero-blocks/members-block/members-block.scss
... | ... | @@ -1,17 +0,0 @@ |
1 | -.members-block { | |
2 | - .member { | |
3 | - img, i.profile-image { | |
4 | - width: 60px; | |
5 | - } | |
6 | - img { | |
7 | - display: inline-block; | |
8 | - vertical-align: top; | |
9 | - } | |
10 | - i.profile-image { | |
11 | - text-align: center; | |
12 | - background-color: #889DB1; | |
13 | - color: #F1F1F1; | |
14 | - font-size: 4.5em; | |
15 | - } | |
16 | - } | |
17 | -} |
src/app/components/noosfero-blocks/profile-image-block/profile-image-block.component.spec.ts
... | ... | @@ -1,46 +0,0 @@ |
1 | -import {TestComponentBuilder, ComponentFixture} from 'ng-forward/cjs/testing/test-component-builder'; | |
2 | -import {Pipe, Input, provide, Component} from 'ng-forward'; | |
3 | - | |
4 | -import {ProfileImageBlock} from './profile-image-block.component'; | |
5 | - | |
6 | -import * as helpers from "./../../../../spec/helpers"; | |
7 | - | |
8 | -const tcb = new TestComponentBuilder(); | |
9 | - | |
10 | -const htmlTemplate: string = '<noosfero-profile-image-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-profile-image-block>'; | |
11 | - | |
12 | -describe("Components", () => { | |
13 | - | |
14 | - describe("Profile Image Block Component", () => { | |
15 | - | |
16 | - beforeEach(angular.mock.module("templates")); | |
17 | - | |
18 | - @Component({ | |
19 | - selector: 'test-container-component', | |
20 | - template: htmlTemplate, | |
21 | - directives: [ProfileImageBlock], | |
22 | - providers: helpers.provideFilters("translateFilter") | |
23 | - }) | |
24 | - class BlockContainerComponent { | |
25 | - block = { type: 'Block' }; | |
26 | - owner = { name: 'profile-name' }; | |
27 | - constructor() { | |
28 | - } | |
29 | - } | |
30 | - | |
31 | - it("show image if present", () => { | |
32 | - helpers.tcb.createAsync(BlockContainerComponent).then(fixture => { | |
33 | - var elProfile = fixture.debugElement.componentViewChildren[0]; | |
34 | - expect(elProfile.query('div.profile-image-block').length).toEqual(1); | |
35 | - }); | |
36 | - }); | |
37 | - | |
38 | - it("has link to the profile", () => { | |
39 | - helpers.tcb.createAsync(BlockContainerComponent).then(fixture => { | |
40 | - var elProfile = fixture.debugElement.componentViewChildren[0]; | |
41 | - expect(elProfile.query('a.settings-link').length).toEqual(1); | |
42 | - }); | |
43 | - }); | |
44 | - | |
45 | - }); | |
46 | -}); |
src/app/components/noosfero-blocks/profile-image-block/profile-image-block.component.ts
... | ... | @@ -1,14 +0,0 @@ |
1 | -import {Inject, Input, Component} from "ng-forward"; | |
2 | -import {ProfileImage} from "./../../../components/noosfero/profile-image/profile-image.component"; | |
3 | - | |
4 | -@Component({ | |
5 | - selector: "noosfero-profile-image-block", | |
6 | - templateUrl: 'app/components/noosfero-blocks/profile-image-block/profile-image-block.html', | |
7 | - directives: [ProfileImage] | |
8 | -}) | |
9 | -export class ProfileImageBlock { | |
10 | - | |
11 | - @Input() block: any; | |
12 | - @Input() owner: any; | |
13 | - | |
14 | -} |
src/app/components/noosfero-blocks/profile-image-block/profile-image-block.html
... | ... | @@ -1,6 +0,0 @@ |
1 | -<div class="center-block text-center profile-image-block"> | |
2 | - <a ui-sref="main.profile.info({profile: ctrl.owner.identifier})"> | |
3 | - <noosfero-profile-image [profile]="ctrl.owner"></noosfero-profile-image> | |
4 | - </a> | |
5 | - <a class="settings-link" target="_self" ui-sref="main.profile.settings({profile: ctrl.owner.identifier})">{{"blocks.profile_image.control_panel" | translate}}</a> | |
6 | -</div> |
src/app/components/noosfero-blocks/profile-image-block/profile-image-block.scss
src/app/components/noosfero-blocks/raw-html/raw-html.component.spec.ts
... | ... | @@ -1,36 +0,0 @@ |
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | |
2 | -import {Component} from 'ng-forward'; | |
3 | - | |
4 | -import {RawHTMLBlock} from './raw-html.component'; | |
5 | - | |
6 | -const tcb = new TestComponentBuilder(); | |
7 | - | |
8 | -const htmlTemplate: string = '<noosfero-raw-htmlblock [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-raw-htmlblock>'; | |
9 | - | |
10 | -describe("Components", () => { | |
11 | - | |
12 | - describe("Raw Html Block Component", () => { | |
13 | - | |
14 | - beforeEach(angular.mock.module("templates")); | |
15 | - beforeEach(angular.mock.module("ngSanitize")); | |
16 | - | |
17 | - it("display html stored in block settings", done => { | |
18 | - | |
19 | - @Component({ | |
20 | - selector: 'test-container-component', | |
21 | - template: htmlTemplate, | |
22 | - directives: [RawHTMLBlock], | |
23 | - }) | |
24 | - class CustomBlockType { | |
25 | - block: any = { settings: { html: '<em>block content</em>' } }; | |
26 | - owner: any = { name: 'profile-name' }; | |
27 | - } | |
28 | - tcb.createAsync(CustomBlockType).then(fixture => { | |
29 | - expect(fixture.debugElement.query(".raw-html-block em").text().trim()).toEqual('block content'); | |
30 | - done(); | |
31 | - }); | |
32 | - }); | |
33 | - | |
34 | - }); | |
35 | - | |
36 | -}); |
src/app/components/noosfero-blocks/raw-html/raw-html.component.ts
... | ... | @@ -1,18 +0,0 @@ |
1 | -import {Component, Input} from "ng-forward"; | |
2 | - | |
3 | -@Component({ | |
4 | - selector: "noosfero-raw-htmlblock", | |
5 | - templateUrl: 'app/components/noosfero-blocks/raw-html/raw-html.html' | |
6 | -}) | |
7 | - | |
8 | -export class RawHTMLBlock { | |
9 | - | |
10 | - @Input() block: any; | |
11 | - @Input() owner: any; | |
12 | - | |
13 | - html: string; | |
14 | - | |
15 | - ngOnInit() { | |
16 | - this.html = this.block.settings.html; | |
17 | - } | |
18 | -} |
src/app/components/noosfero-blocks/raw-html/raw-html.html
src/app/components/noosfero-blocks/recent-documents/index.ts
... | ... | @@ -1 +0,0 @@ |
1 | -/* Module Index Entry - generated using the script npm run generate-index */ |
src/app/components/noosfero-blocks/recent-documents/recent-documents.component.spec.ts
... | ... | @@ -1,53 +0,0 @@ |
1 | -import {TestComponentBuilder} from 'ng-forward/cjs/testing/test-component-builder'; | |
2 | -import {Provider, Input, provide, Component} from 'ng-forward'; | |
3 | -import {provideFilters} from '../../../../spec/helpers'; | |
4 | -import {RecentDocumentsBlock} from './recent-documents.component'; | |
5 | - | |
6 | -const htmlTemplate: string = '<noosfero-recent-documents-block [block]="ctrl.block" [owner]="ctrl.owner"></noosfero-recent-documents-block>'; | |
7 | - | |
8 | -const tcb = new TestComponentBuilder(); | |
9 | - | |
10 | -describe("Components", () => { | |
11 | - describe("Recent Documents Block Component", () => { | |
12 | - | |
13 | - beforeEach(angular.mock.module("templates")); | |
14 | - | |
15 | - let state = jasmine.createSpyObj("state", ["go"]); | |
16 | - let providers = [ | |
17 | - new Provider('$state', { useValue: state }), | |
18 | - new Provider('ArticleService', { | |
19 | - useValue: { | |
20 | - getByProfile: (profileId: number, filters: any): any => { | |
21 | - return Promise.resolve({ data: { articles: [{ name: "article1" }] } }); | |
22 | - } | |
23 | - } | |
24 | - }), | |
25 | - ].concat(provideFilters("truncateFilter", "stripTagsFilter")); | |
26 | - | |
27 | - @Component({ selector: 'test-container-component', template: htmlTemplate, directives: [RecentDocumentsBlock], providers: providers }) | |
28 | - class BlockContainerComponent { | |
29 | - block = { type: 'Block', settings: {} }; | |
30 | - owner = { name: 'profile-name' }; | |
31 | - constructor() { | |
32 | - } | |
33 | - } | |
34 | - | |
35 | - it("get recent documents from the article service", done => { | |
36 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | |
37 | - let recentDocumentsBlock: RecentDocumentsBlock = fixture.debugElement.componentViewChildren[0].componentInstance; | |
38 | - expect(recentDocumentsBlock.documents).toEqual([{ name: "article1" }]); | |
39 | - done(); | |
40 | - }); | |
41 | - }); | |
42 | - | |
43 | - it("go to article page when open a document", done => { | |
44 | - tcb.createAsync(BlockContainerComponent).then(fixture => { | |
45 | - let recentDocumentsBlock: RecentDocumentsBlock = fixture.debugElement.componentViewChildren[0].componentInstance; | |
46 | - recentDocumentsBlock.openDocument({ path: "path", profile: { identifier: "identifier" } }); | |
47 | - expect(state.go).toHaveBeenCalledWith("main.profile.page", { page: "path", profile: "identifier" }); | |
48 | - done(); | |
49 | - }); | |
50 | - }); | |
51 | - | |
52 | - }); | |
53 | -}); | |
54 | 0 | \ No newline at end of file |
src/app/components/noosfero-blocks/recent-documents/recent-documents.component.ts
... | ... | @@ -1,38 +0,0 @@ |
1 | -import {Component, Inject, Input} from "ng-forward"; | |
2 | -import {ArticleService} from "../../../../lib/ng-noosfero-api/http/article.service"; | |
3 | - | |
4 | -@Component({ | |
5 | - selector: "noosfero-recent-documents-block", | |
6 | - templateUrl: 'app/components/noosfero-blocks/recent-documents/recent-documents.html' | |
7 | -}) | |
8 | -@Inject(ArticleService, "$state") | |
9 | -export class RecentDocumentsBlock { | |
10 | - | |
11 | - @Input() block: any; | |
12 | - @Input() owner: any; | |
13 | - | |
14 | - profile: any; | |
15 | - documents: any; | |
16 | - | |
17 | - documentsLoaded: boolean = false; | |
18 | - | |
19 | - constructor(private articleService: ArticleService, private $state: any) { | |
20 | - } | |
21 | - | |
22 | - ngOnInit() { | |
23 | - this.profile = this.owner; | |
24 | - this.documents = []; | |
25 | - | |
26 | - var limit = (this.block && this.block.settings) ? this.block.settings.limit : null || 5; | |
27 | - //FIXME get all text articles | |
28 | - this.articleService.getByProfile(this.profile.id, { content_type: 'TinyMceArticle', per_page: limit }).then((response: any) => { | |
29 | - this.documents = response.data.articles; | |
30 | - this.documentsLoaded = true; | |
31 | - }); | |
32 | - } | |
33 | - | |
34 | - openDocument(article: any) { | |
35 | - this.$state.go("main.profile.page", { page: article.path, profile: article.profile.identifier }); | |
36 | - } | |
37 | - | |
38 | -} |
src/app/components/noosfero-blocks/recent-documents/recent-documents.html
... | ... | @@ -1,18 +0,0 @@ |
1 | -<div deckgrid source="ctrl.documents" class="deckgrid"> | |
2 | - <div class="a-card panel media" ng-click="mother.ctrl.openDocument(card);"> | |
3 | - <div class="author media-left" ng-show="card.author.image"> | |
4 | - <img ng-src="{{card.author.image.url}}" class="img-circle"> | |
5 | - </div> | |
6 | - <div class="header media-body"> | |
7 | - <h5 class="title media-heading" ng-bind="card.title"></h5> | |
8 | - | |
9 | - <div class="subheader"> | |
10 | - <span class="time"> | |
11 | - <i class="fa fa-clock-o"></i> <span am-time-ago="card.created_at | dateFormat"></span> | |
12 | - </span> | |
13 | - </div> | |
14 | - </div> | |
15 | - <img ng-show="card.image" ng-src="{{card.image.url}}" class="img-responsive article-image"> | |
16 | - <div class="post-lead" ng-bind-html="card.body | stripTags | truncate: 100: '...': true"></div> | |
17 | - </div> | |
18 | -</div> |