diff --git a/src/app/main/main.component.ts b/src/app/main/main.component.ts index 9519618..2162c96 100644 --- a/src/app/main/main.component.ts +++ b/src/app/main/main.component.ts @@ -16,6 +16,7 @@ import {RecentDocumentsBlockComponent} from "../layout/blocks/recent-documents/r import {ProfileImageBlockComponent} from "../layout/blocks/profile-image/profile-image-block.component"; import {RawHTMLBlockComponent} from "../layout/blocks/raw-html/raw-html-block.component"; import {StatisticsBlockComponent} from "../layout/blocks/statistics/statistics-block.component"; +import {CustomContentComponent} from "../profile/custom-content/custom-content.component"; import {MembersBlockComponent} from "../layout/blocks/members/members-block.component"; import {CommunitiesBlockComponent} from "../layout/blocks/communities/communities-block.component"; @@ -99,7 +100,7 @@ export class EnvironmentContent { LinkListBlockComponent, CommunitiesBlockComponent, HtmlEditorComponent, MainBlockComponent, RecentDocumentsBlockComponent, Navbar, SidebarComponent, ProfileImageBlockComponent, MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent, StatisticsBlockComponent, - LoginBlockComponent + LoginBlockComponent, CustomContentComponent ].concat(plugins.mainComponents).concat(plugins.hotspots), providers: [AuthService, SessionService, NotificationService, BodyStateClassesService] diff --git a/src/app/profile/custom-content/custom-content.component.spec.ts b/src/app/profile/custom-content/custom-content.component.spec.ts new file mode 100644 index 0000000..6f88606 --- /dev/null +++ b/src/app/profile/custom-content/custom-content.component.spec.ts @@ -0,0 +1,77 @@ +import {CustomContentComponent} from './custom-content.component'; +import {ComponentTestHelper, createClass} from '../../../spec/component-test-helper'; +import * as helpers from "../../../spec/helpers"; + +const htmlTemplate: string = ''; + +describe("Components", () => { + describe("Custom Content Component", () => { + + let helper: ComponentTestHelper; + beforeEach(angular.mock.module("templates")); + beforeEach(angular.mock.module("ngSanitize")); + + beforeEach((done) => { + let profileService = jasmine.createSpyObj("profileService", ["update"]); + let notificationService = jasmine.createSpyObj("notificationService", ["success"]); + let properties = { profile: { custom_footer: "footer" } }; + let cls = createClass({ + template: htmlTemplate, + directives: [CustomContentComponent], + properties: properties, + providers: [ + helpers.createProviderToValue("$uibModal", helpers.mocks.$modal), + helpers.createProviderToValue("ProfileService", profileService), + helpers.createProviderToValue("NotificationService", notificationService) + ] + }); + helper = new ComponentTestHelper(cls, done); + }); + + it("set modal instance when open edit modal", () => { + helper.component['$uibModal'].open = jasmine.createSpy("open"); + helper.component.openEdit(); + expect(helper.component['$uibModal'].open).toHaveBeenCalled(); + expect(helper.component.originalContent).toEqual(helper.component.content); + }); + + it("restore original content when cancelled", () => { + helper.component.openEdit(); + helper.component.content = "modified"; + helper.component.cancel(); + expect(helper.component.content).toEqual(helper.component.originalContent); + }); + + it("keep modified content when click on preview", () => { + helper.component.openEdit(); + helper.component.content = "modified"; + helper.component.preview(); + expect(helper.component.content).toEqual("modified"); + }); + + it("not override original content when cancelled openEdit again", () => { + helper.component.openEdit(); + helper.component.content = "modified"; + helper.component.openEdit(); + expect(helper.component.originalContent).toEqual("footer"); + }); + + it("reset modal instance when close edit modal", () => { + let modalInstance = jasmine.createSpyObj("modalInstance", ["close"]); + helper.component['$uibModal'].open = jasmine.createSpy("open").and.returnValue(modalInstance); + helper.component.openEdit(); + expect(helper.component['$uibModal'].open).toHaveBeenCalled(); + helper.component.cancel(); + expect(modalInstance.close).toHaveBeenCalled(); + expect(helper.component['modalInstance']).toBeNull(); + }); + + it("call profile service to update profile when save", () => { + helper.component['profileService'].update = jasmine.createSpy("update").and.returnValue({ + then: (func: Function) => { func(); } + }); + helper.component.save(); + expect(helper.component['notificationService'].success).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/app/profile/custom-content/custom-content.component.ts b/src/app/profile/custom-content/custom-content.component.ts new file mode 100644 index 0000000..0d8cf89 --- /dev/null +++ b/src/app/profile/custom-content/custom-content.component.ts @@ -0,0 +1,70 @@ +import {Component, Input, Inject} from 'ng-forward'; +import {ProfileService} from '../../../lib/ng-noosfero-api/http/profile.service'; +import {NotificationService} from '../../shared/services/notification.service'; + +@Component({ + selector: 'custom-content', + templateUrl: "app/profile/custom-content/custom-content.html", +}) +@Inject("$uibModal", "$scope", ProfileService, NotificationService) +export class CustomContentComponent { + + @Input() attribute: string; + @Input() profile: noosfero.Profile; + @Input() label: string; + + content: string; + originalContent: string; + private modalInstance: any = null; + + constructor(private $uibModal: any, + private $scope: ng.IScope, + private profileService: ProfileService, + private notificationService: NotificationService) { } + + ngOnInit() { + this.$scope.$watch(() => { + return this.profile ? (this.profile)[this.attribute] : null; + }, () => { + if (this.profile) this.content = (this.profile)[this.attribute]; + }); + } + + openEdit() { + if (!this.originalContent) this.originalContent = this.content; + this.modalInstance = this.$uibModal.open({ + templateUrl: 'app/profile/custom-content/edit-content.html', + size: 'lg', + controller: CustomContentComponent, + controllerAs: 'modal', + bindToController: true, + scope: this.$scope, + backdrop: 'static' + }); + } + + save() { + let profile: any = { id: this.profile.id }; + profile[this.attribute] = this.content; + this.profileService.update(profile).then(() => { + this.closeEdit(); + this.notificationService.success({ title: "profile.content.success.title", message: "profile.content.success.message" }); + }); + } + + preview() { + this.closeEdit(); + } + + cancel() { + this.content = this.originalContent; + this.closeEdit(); + } + + private closeEdit() { + if (this.modalInstance) { + this.modalInstance.close(); + this.modalInstance = null; + } + } +} diff --git a/src/app/profile/custom-content/custom-content.html b/src/app/profile/custom-content/custom-content.html new file mode 100644 index 0000000..50d046e --- /dev/null +++ b/src/app/profile/custom-content/custom-content.html @@ -0,0 +1,6 @@ +
+
+ +
+
+
diff --git a/src/app/profile/custom-content/edit-content.html b/src/app/profile/custom-content/edit-content.html new file mode 100644 index 0000000..bd5d1d8 --- /dev/null +++ b/src/app/profile/custom-content/edit-content.html @@ -0,0 +1,7 @@ +
+

{{"custom_content.title" | translate}}

+ + + + +
diff --git a/src/app/profile/custom-content/edit-content.scss b/src/app/profile/custom-content/edit-content.scss new file mode 100644 index 0000000..ff66987 --- /dev/null +++ b/src/app/profile/custom-content/edit-content.scss @@ -0,0 +1,3 @@ +.edit-content { + margin: 20px; +} diff --git a/src/app/profile/profile.html b/src/app/profile/profile.html index 5a205ca..160f623 100644 --- a/src/app/profile/profile.html +++ b/src/app/profile/profile.html @@ -1,7 +1,7 @@
-
+
- +
diff --git a/src/languages/en.json b/src/languages/en.json index 1d22f1f..05d1ee4 100644 --- a/src/languages/en.json +++ b/src/languages/en.json @@ -66,5 +66,10 @@ "statistics.categories": "Categories", "statistics.tags": "Tags", "statistics.comments": "Comments", - "statistics.hits": "Hits" + "statistics.hits": "Hits", + "profile.content.success.title": "Good job!", + "profile.content.success.message": "Profile saved!", + "custom_content.title": "Edit content", + "profile.custom_header.label": "Header", + "profile.custom_footer.label": "Footer" } diff --git a/src/languages/pt.json b/src/languages/pt.json index e101d49..17d3694 100644 --- a/src/languages/pt.json +++ b/src/languages/pt.json @@ -63,5 +63,10 @@ "statistics.categories": "Categorias", "statistics.tags": "Tags", "statistics.comments": "Comentários", - "statistics.hits": "Acessos" + "statistics.hits": "Acessos", + "profile.content.success.title": "Bom trabalho!", + "profile.content.success.message": "Perfil salvo!", + "custom_content.title": "Editar conteúdo", + "profile.custom_header.label": "Cabeçalho", + "profile.custom_footer.label": "Rodapé" } diff --git a/src/lib/ng-noosfero-api/http/profile.service.spec.ts b/src/lib/ng-noosfero-api/http/profile.service.spec.ts index 05a8e8c..d27d65c 100644 --- a/src/lib/ng-noosfero-api/http/profile.service.spec.ts +++ b/src/lib/ng-noosfero-api/http/profile.service.spec.ts @@ -101,6 +101,16 @@ describe("Services", () => { }); $httpBackend.flush(); }); + + it("should update the profile attributes", (done) => { + let profileId = 1; + $httpBackend.expectPOST(`/api/v1/profiles/${profileId}`).respond(200, { profile: { custom_header: "something" } }); + profileService.update({ id: profileId, custom_header: "something" }).then((response: restangular.IResponse) => { + expect(response.data.profile.custom_header).toEqual("something"); + done(); + }); + $httpBackend.flush(); + }); }); diff --git a/src/lib/ng-noosfero-api/http/profile.service.ts b/src/lib/ng-noosfero-api/http/profile.service.ts index a84540e..4e9bd64 100644 --- a/src/lib/ng-noosfero-api/http/profile.service.ts +++ b/src/lib/ng-noosfero-api/http/profile.service.ts @@ -60,4 +60,8 @@ export class ProfileService { return this.restangular.one('profiles', profileId); } + update(profile: noosfero.Profile) { + let headers = { 'Content-Type': 'application/json' }; + return this.get(profile.id).customPOST({ profile: profile }, null, null, headers); + } } diff --git a/src/lib/ng-noosfero-api/interfaces/profile.ts b/src/lib/ng-noosfero-api/interfaces/profile.ts index 646db7f..84a4649 100644 --- a/src/lib/ng-noosfero-api/interfaces/profile.ts +++ b/src/lib/ng-noosfero-api/interfaces/profile.ts @@ -62,5 +62,21 @@ namespace noosfero { * @returns {string} The Profile homepage */ homepage: string; + + /** + * @ngdoc property + * @name custom_header + * @propertyOf noofero.Profile + * @returns {string} The Profile header + */ + custom_header: string; + + /** + * @ngdoc property + * @name custom_footer + * @propertyOf noofero.Profile + * @returns {string} The Profile footer + */ + custom_footer: string; } } -- libgit2 0.21.2