Commit ade7c078b4032f09e1e33e6c2e4c00906939724c
Exists in
master
and in
9 other branches
Merge branch 'fix-edit-mode-state' into 'master'
Fix edit mode state See merge request !46
Showing
16 changed files
with
75 additions
and
25 deletions
Show diff stats
src/app/admin/layout-edit/designMode.service.spec.ts
1 | 1 | import {DesignModeService} from './designMode.service'; |
2 | +import {INoosferoLocalStorage} from "./../../shared/models/interfaces"; | |
2 | 3 | |
3 | 4 | describe('DesignMode Service', () => { |
4 | 5 | let service: DesignModeService; |
5 | 6 | |
7 | + let $localStorage = <INoosferoLocalStorage>{ currentUser: null, settings: { designMode: false } }; | |
6 | 8 | beforeEach(() => { |
7 | - service = new DesignModeService(); | |
9 | + service = new DesignModeService($localStorage); | |
8 | 10 | }); |
9 | 11 | |
10 | 12 | it('has the designModeOn equals false as default', () => { |
... | ... | @@ -18,12 +20,14 @@ describe('DesignMode Service', () => { |
18 | 20 | }); |
19 | 21 | |
20 | 22 | it('emits the onToggle event when changing the designModeOn property', () => { |
23 | + service.setInDesignMode(false); | |
21 | 24 | spyOn(service.onToggle, 'next').and.stub(); |
22 | 25 | service.setInDesignMode(true); |
23 | 26 | expect(service.onToggle.next).toHaveBeenCalled(); |
24 | 27 | }); |
25 | 28 | |
26 | 29 | it('does not emit onToggle event when there is no change on designModeOn property', () => { |
30 | + service.setInDesignMode(false); | |
27 | 31 | spyOn(service.onToggle, 'next').and.stub(); |
28 | 32 | service.setInDesignMode(false); |
29 | 33 | expect(service.onToggle.next).not.toHaveBeenCalled(); | ... | ... |
src/app/admin/layout-edit/designMode.service.ts
1 | -import {Injectable, Output, EventEmitter} from 'ng-forward'; | |
1 | +import {Injectable, Output, EventEmitter, Inject} from 'ng-forward'; | |
2 | +import {INoosferoLocalStorage} from "./../../shared/models/interfaces"; | |
2 | 3 | |
3 | 4 | @Injectable() |
5 | +@Inject("$localStorage") | |
4 | 6 | export class DesignModeService { |
5 | 7 | @Output() onToggle: EventEmitter<boolean> = new EventEmitter<boolean>(); |
6 | 8 | |
7 | - private designModeOn: boolean = false; | |
8 | - | |
9 | 9 | isInDesignMode(): boolean { |
10 | - return this.designModeOn; | |
10 | + return this.$localStorage.settings.designModeOn; | |
11 | + } | |
12 | + | |
13 | + destroy() { | |
14 | + delete this.$localStorage.settings; | |
15 | + this.$localStorage.settings = {}; | |
11 | 16 | } |
12 | 17 | |
13 | 18 | setInDesignMode(value: boolean) { |
14 | - if (this.designModeOn !== value) { | |
15 | - this.designModeOn = value; | |
16 | - this.onToggle.next(this.designModeOn); | |
19 | + if (this.$localStorage.settings.designModeOn !== value) { | |
20 | + this.$localStorage.settings.designModeOn = value; | |
21 | + this.onToggle.next(value); | |
17 | 22 | } |
18 | 23 | } |
19 | 24 | |
20 | - constructor() { | |
25 | + constructor(private $localStorage: INoosferoLocalStorage) { | |
26 | + if (!this.$localStorage.settings) { | |
27 | + this.$localStorage.settings = {}; | |
28 | + } | |
21 | 29 | } |
22 | 30 | } | ... | ... |
src/app/admin/layout-edit/designModeToggler.component.spec.ts
... | ... | @@ -2,6 +2,7 @@ import {ComponentTestHelper, createClass} from '../../../spec/component-test-hel |
2 | 2 | import * as helpers from '../../../spec/helpers'; |
3 | 3 | import {DesignModeTogglerComponent} from './designModeToggler.component'; |
4 | 4 | import {DesignModeService} from './designMode.service'; |
5 | +import {INoosferoLocalStorage} from "./../../shared/models/interfaces"; | |
5 | 6 | |
6 | 7 | describe('DesignModeToggler Component', () => { |
7 | 8 | const htmlTemplate: string = '<noosfero-design-toggler></noosfero-design-toggler>'; |
... | ... | @@ -14,13 +15,15 @@ describe('DesignModeToggler Component', () => { |
14 | 15 | }); |
15 | 16 | |
16 | 17 | let designModeService: DesignModeService; |
18 | + let $localStorage = <INoosferoLocalStorage>{ currentUser: null, settings: { designMode: false } }; | |
17 | 19 | beforeEach((done) => { |
18 | - designModeService = new DesignModeService(); | |
20 | + designModeService = new DesignModeService($localStorage); | |
19 | 21 | let cls = createClass({ |
20 | 22 | template: htmlTemplate, |
21 | 23 | directives: [DesignModeTogglerComponent], |
22 | 24 | providers: [ |
23 | - helpers.createProviderToValue('DesignModeService', designModeService) | |
25 | + helpers.createProviderToValue('DesignModeService', designModeService), | |
26 | + helpers.createProviderToValue('AuthService', helpers.mocks.authService), | |
24 | 27 | ] |
25 | 28 | }); |
26 | 29 | helper = new ComponentTestHelper<DesignModeTogglerComponent>(cls, done); |
... | ... | @@ -36,6 +39,7 @@ describe('DesignModeToggler Component', () => { |
36 | 39 | }); |
37 | 40 | |
38 | 41 | it('emits event with value "true" when changing inDesignMode to On', (done) => { |
42 | + designModeService.setInDesignMode(false); | |
39 | 43 | designModeService.onToggle.subscribe((designModeOn: boolean) => { |
40 | 44 | expect(designModeOn).toBeTruthy(); |
41 | 45 | done(); | ... | ... |
src/app/admin/layout-edit/designModeToggler.component.ts
1 | 1 | import {Component, Inject} from 'ng-forward'; |
2 | 2 | import {DesignModeService} from './designMode.service'; |
3 | +import {AuthService, AuthEvents} from '../../login' | |
4 | + | |
3 | 5 | @Component({ |
4 | 6 | selector: 'noosfero-design-toggler', |
5 | 7 | templateUrl: 'app/admin/layout-edit/designModeToggler.html' |
6 | 8 | }) |
7 | -@Inject(DesignModeService) | |
9 | +@Inject(DesignModeService, AuthService) | |
8 | 10 | export class DesignModeTogglerComponent { |
9 | 11 | |
10 | 12 | icon: string = " <i class='glyphicon glyphicon-wrench'></i> "; |
11 | 13 | |
12 | - constructor(private designModeService: DesignModeService) { | |
14 | + constructor(private designModeService: DesignModeService, private authService: AuthService) { | |
15 | + this.authService.subscribe(AuthEvents[AuthEvents.logoutSuccess], () => { | |
16 | + this.designModeService.destroy(); | |
17 | + }); | |
13 | 18 | } |
14 | 19 | |
15 | 20 | private _inDesignMode: boolean = false; | ... | ... |
src/app/layout/blocks/block.component.spec.ts
... | ... | @@ -2,6 +2,7 @@ import {Component} from 'ng-forward'; |
2 | 2 | import {BlockComponent} from './block.component'; |
3 | 3 | import * as helpers from "../../../spec/helpers"; |
4 | 4 | import {ComponentTestHelper, createClass} from '../../../spec/component-test-helper'; |
5 | +import {DesignModeService} from '../../admin/layout-edit/designMode.service'; | |
5 | 6 | |
6 | 7 | const htmlTemplate: string = '<noosfero-block [block]="ctrl.block" [owner]="ctrl.profile"></noosfero-block>'; |
7 | 8 | |
... | ... | @@ -32,16 +33,17 @@ describe("Boxes Component", () => { |
32 | 33 | helpers.createProviderToValue('TranslatorService', translatorService), |
33 | 34 | helpers.createProviderToValue('$uibModal', helpers.mocks.$modal), |
34 | 35 | helpers.createProviderToValue('BlockService', blockService), |
35 | - helpers.createProviderToValue('NotificationService', helpers.mocks.notificationService) | |
36 | + helpers.createProviderToValue('NotificationService', helpers.mocks.notificationService), | |
37 | + helpers.createProviderToValue('DesignModeService', helpers.mocks.designModeService) | |
36 | 38 | ] |
37 | 39 | }); |
38 | 40 | helper = new ComponentTestHelper<BlockComponent>(cls, done); |
39 | 41 | }); |
40 | - | |
41 | 42 | let translatorService = jasmine.createSpyObj("translatorService", ["currentLanguage"]); |
42 | 43 | let blockService = jasmine.createSpyObj("blockService", ["update"]); |
43 | 44 | let state = jasmine.createSpyObj("state", ["current"]); |
44 | 45 | state.current = { name: "" }; |
46 | + | |
45 | 47 | |
46 | 48 | it("set isHomepage as false by default", () => { |
47 | 49 | expect(helper.component.isHomepage).toBeFalsy(); | ... | ... |
src/app/layout/blocks/block.component.ts
... | ... | @@ -11,7 +11,8 @@ import { DesignModeService } from "../../admin/layout-edit/designMode.service"; |
11 | 11 | templateUrl: 'app/layout/blocks/block.html', |
12 | 12 | directives: [BlockEditionComponent] |
13 | 13 | }) |
14 | -@Inject("$uibModal", "$scope", "$state", "$rootScope", BlockService, NotificationService, AuthService, SessionService, TranslatorService, DesignModeService) | |
14 | +@Inject("$uibModal", "$scope", "$state", "$rootScope", BlockService, NotificationService, | |
15 | +AuthService, SessionService, TranslatorService, DesignModeService) | |
15 | 16 | export class BlockComponent { |
16 | 17 | |
17 | 18 | @Input() block: noosfero.Block; | ... | ... |
src/app/layout/blocks/block.html
1 | -<div ng-show="ctrl.canDisplay() || ctrl.editionMode || ctrl.designMode" ng-class="{'invisible-block': !ctrl.canDisplay()}" class="noosfero-block" ng-mouseover="displayActions = true" ng-mouseleave="displayActions = false"> | |
1 | +<div ng-show="ctrl.canDisplay() || ctrl.inEditMode() || ctrl.designMode" ng-class="{'invisible-block': !ctrl.canDisplay()}" class="noosfero-block" ng-mouseover="displayActions = true" ng-mouseleave="displayActions = false"> | |
2 | 2 | <div ng-show="displayActions" class="actions block-actions" permission="ctrl.block.permissions" permission-action="allow_edit"> |
3 | 3 | <button type="submit" class="btn btn-xs btn-default" ng-click="ctrl.openEdit()"><i class="fa fa-edit fa-fw"></i></button> |
4 | 4 | </div> | ... | ... |
src/app/layout/navbar/navbar.spec.ts
... | ... | @@ -9,6 +9,8 @@ import {SessionService, AuthService, AuthController, AuthEvents} from "./../../l |
9 | 9 | |
10 | 10 | import events from 'ng-forward/cjs/events/events'; |
11 | 11 | |
12 | +import {DesignModeService} from '../../admin/layout-edit/designMode.service'; | |
13 | + | |
12 | 14 | describe("Components", () => { |
13 | 15 | |
14 | 16 | describe("Navbar Component", () => { |
... | ... | @@ -22,6 +24,7 @@ describe("Components", () => { |
22 | 24 | let authService: any; |
23 | 25 | let stateService: any; |
24 | 26 | let sessionService: SessionService; |
27 | + let designModeService: DesignModeService; | |
25 | 28 | |
26 | 29 | let provideFunc = provide; |
27 | 30 | |
... | ... | @@ -37,6 +40,7 @@ describe("Components", () => { |
37 | 40 | authService = helpers.mocks.authService; |
38 | 41 | stateService = jasmine.createSpyObj("$state", ["go"]); |
39 | 42 | sessionService = <any>helpers.mocks.sessionWithCurrentUser(user); |
43 | + designModeService = helpers.mocks.designModeService; | |
40 | 44 | }); |
41 | 45 | |
42 | 46 | |
... | ... | @@ -76,6 +80,9 @@ describe("Components", () => { |
76 | 80 | }), |
77 | 81 | provide('TranslatorService', { |
78 | 82 | useValue: helpers.mocks.translatorService |
83 | + }), | |
84 | + provide('DesignModeService', { | |
85 | + useValue: helpers.mocks.designModeService | |
79 | 86 | }) |
80 | 87 | ].concat(helpers.provideFilters("translateFilter")), |
81 | 88 | directives: [Navbar], | ... | ... |
src/app/layout/services/body-state-classes.service.spec.ts
... | ... | @@ -5,11 +5,13 @@ import {AuthEvents} from "./../../login/auth-events"; |
5 | 5 | |
6 | 6 | import {EventEmitter} from 'ng-forward'; |
7 | 7 | import {DesignModeService} from './../../admin/layout-edit/designMode.service'; |
8 | +import {INoosferoLocalStorage} from "./../../shared/models/interfaces"; | |
8 | 9 | |
9 | 10 | describe("BodyStateClasses Service", () => { |
10 | 11 | |
11 | 12 | let currentStateName = "main"; |
12 | 13 | let bodyStateClasseService: BodyStateClassesService; |
14 | + let $localStorage = <INoosferoLocalStorage>{ currentUser: null, settings: { designMode: false } }; | |
13 | 15 | let $rootScope: ng.IRootScopeService = <any>{}, |
14 | 16 | $document: ng.IDocumentService = <any>{}, |
15 | 17 | $state: ng.ui.IStateService = <any>{ |
... | ... | @@ -20,7 +22,8 @@ describe("BodyStateClasses Service", () => { |
20 | 22 | authService: any = helpers.mocks.authService, |
21 | 23 | bodyEl: { className: string }, |
22 | 24 | bodyElJq: any, |
23 | - designModeService = new DesignModeService(); | |
25 | + | |
26 | + designModeService = new DesignModeService($localStorage); | |
24 | 27 | |
25 | 28 | |
26 | 29 | ... | ... |
src/app/login/session.service.spec.ts
... | ... | @@ -13,7 +13,7 @@ describe("Services", () => { |
13 | 13 | let $log: any; |
14 | 14 | |
15 | 15 | beforeEach(() => { |
16 | - $localStorage = <INoosferoLocalStorage>{ currentUser: null }; | |
16 | + $localStorage = <INoosferoLocalStorage>{ currentUser: null, settings: null }; | |
17 | 17 | $log = jasmine.createSpyObj('$log', ['debug']); |
18 | 18 | }); |
19 | 19 | ... | ... |
src/app/login/session.service.ts
src/app/profile/custom-content/custom-content.component.spec.ts
1 | 1 | import {CustomContentComponent} from './custom-content.component'; |
2 | 2 | import {ComponentTestHelper, createClass} from '../../../spec/component-test-helper'; |
3 | 3 | import * as helpers from "../../../spec/helpers"; |
4 | +import {DesignModeService} from '../../admin/layout-edit/designMode.service'; | |
4 | 5 | |
5 | 6 | const htmlTemplate: string = '<custom-content [attribute]="\'custom_footer\'" [profile]="ctrl.profile"></custom-content>'; |
6 | 7 | |
... | ... | @@ -14,6 +15,7 @@ describe("Components", () => { |
14 | 15 | beforeEach((done) => { |
15 | 16 | let profileService = jasmine.createSpyObj("profileService", ["update"]); |
16 | 17 | let notificationService = jasmine.createSpyObj("notificationService", ["success"]); |
18 | + let designModeService = { isInDesignMode: () => { return true; }}; | |
17 | 19 | let properties = { profile: { custom_footer: "footer" } }; |
18 | 20 | let cls = createClass({ |
19 | 21 | template: htmlTemplate, |
... | ... | @@ -22,7 +24,8 @@ describe("Components", () => { |
22 | 24 | providers: [ |
23 | 25 | helpers.createProviderToValue("$uibModal", helpers.mocks.$modal), |
24 | 26 | helpers.createProviderToValue("ProfileService", profileService), |
25 | - helpers.createProviderToValue("NotificationService", notificationService) | |
27 | + helpers.createProviderToValue("NotificationService", notificationService), | |
28 | + helpers.createProviderToValue("DesignModeService", designModeService) | |
26 | 29 | ] |
27 | 30 | }); |
28 | 31 | helper = new ComponentTestHelper<CustomContentComponent>(cls, done); | ... | ... |
src/app/profile/custom-content/custom-content.component.ts
... | ... | @@ -20,7 +20,6 @@ export class CustomContentComponent { |
20 | 20 | |
21 | 21 | content: string; |
22 | 22 | originalContent: string; |
23 | - editionMode = false; | |
24 | 23 | private modalInstance: any = null; |
25 | 24 | |
26 | 25 | constructor(private $uibModal: any, |
... | ... | @@ -35,9 +34,10 @@ export class CustomContentComponent { |
35 | 34 | }, () => { |
36 | 35 | if (this.profile) this.content = (<any>this.profile)[this.attribute]; |
37 | 36 | }); |
38 | - this.designModeService.onToggle.subscribe((designModeOn: boolean) => { | |
39 | - this.editionMode = designModeOn; | |
40 | - }); | |
37 | + } | |
38 | + | |
39 | + inEditMode() { | |
40 | + return this.designModeService.isInDesignMode(); | |
41 | 41 | } |
42 | 42 | |
43 | 43 | openEdit() { | ... | ... |
src/app/profile/custom-content/custom-content.html
1 | 1 | <div class="custom-content"> |
2 | - <div class="actions" permission="ctrl.profile.permissions" permission-action="allow_edit" ng-show="ctrl.editionMode"> | |
2 | + <div class="actions" permission="ctrl.profile.permissions" permission-action="allow_edit" ng-show="ctrl.inEditMode()"> | |
3 | 3 | <button type="submit" class="btn btn-xs btn-default" ng-click="ctrl.openEdit()"><i class="fa fa-edit fa-fw"></i> {{ctrl.label | translate}}</button> |
4 | 4 | </div> |
5 | 5 | <div class="content" ng-bind-html="ctrl.content"></div> | ... | ... |
src/app/shared/models/interfaces.ts
src/spec/mocks.ts
... | ... | @@ -193,6 +193,17 @@ export var mocks: any = { |
193 | 193 | currentUser: () => { return user; } |
194 | 194 | }; |
195 | 195 | }, |
196 | + designModeService: { | |
197 | + modeFn: null, | |
198 | + onToggle: { | |
199 | + subscribe: (fn: Function) => { | |
200 | + mocks.designModeService.modeFn = fn; | |
201 | + }, | |
202 | + next: (param: any) => { | |
203 | + mocks.designModeService.modeFn(param); | |
204 | + } | |
205 | + } | |
206 | + }, | |
196 | 207 | $translate: { |
197 | 208 | use: (lang?: string) => { |
198 | 209 | return lang ? Promise.resolve(lang) : "en"; | ... | ... |