Compare View
Commits (8)
-
…designModeToggler Component
-
The use of bootstrap to start the application broke the startup process.
Showing
27 changed files
Show diff stats
bower.json
... | ... | @@ -35,9 +35,10 @@ |
35 | 35 | "angular-i18n": "^1.5.0", |
36 | 36 | "angular-load": "^0.4.1", |
37 | 37 | "angular-translate-interpolation-messageformat": "^2.10.0", |
38 | - "angular-bind-html-compile": "^1.2.1", | |
39 | - "angular-click-outside": "^2.7.1", | |
40 | - "ng-ckeditor": "^0.2.1" | |
38 | + "angular-bind-html-compile": "^1.2.1", | |
39 | + "angular-click-outside": "^2.7.1", | |
40 | + "ng-ckeditor": "^0.2.1", | |
41 | + "angular-bootstrap-toggle-switch": "^0.5.6" | |
41 | 42 | }, |
42 | 43 | "devDependencies": { |
43 | 44 | "angular-mocks": "~1.5.0" | ... | ... |
... | ... | @@ -0,0 +1,31 @@ |
1 | +import {DesignModeService} from './designMode.service'; | |
2 | + | |
3 | +describe('DesignMode Service', () => { | |
4 | + let service: DesignModeService; | |
5 | + | |
6 | + beforeEach(() => { | |
7 | + service = new DesignModeService(); | |
8 | + }); | |
9 | + | |
10 | + it('has the designModeOn equals false as default', () => { | |
11 | + expect(service.isInDesignMode()).toBeFalsy(); | |
12 | + }); | |
13 | + | |
14 | + it('allows set the designMode value', () => { | |
15 | + spyOn(service.onToggle, 'next').and.stub(); | |
16 | + service.setInDesignMode(true); | |
17 | + expect(service.isInDesignMode).toBeTruthy(); | |
18 | + }); | |
19 | + | |
20 | + it('emits the onToggle event when changing the designModeOn property', () => { | |
21 | + spyOn(service.onToggle, 'next').and.stub(); | |
22 | + service.setInDesignMode(true); | |
23 | + expect(service.onToggle.next).toHaveBeenCalled(); | |
24 | + }); | |
25 | + | |
26 | + it('does not emit onToggle event when there is no change on designModeOn property', () => { | |
27 | + spyOn(service.onToggle, 'next').and.stub(); | |
28 | + service.setInDesignMode(false); | |
29 | + expect(service.onToggle.next).not.toHaveBeenCalled(); | |
30 | + }); | |
31 | +}); | |
0 | 32 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,23 @@ |
1 | +import {Component, Injectable, Output, EventEmitter} from 'ng-forward'; | |
2 | +import {BodyStateClassesService} from '../../layout/services/body-state-classes.service'; | |
3 | + | |
4 | +@Injectable() | |
5 | +export class DesignModeService { | |
6 | + @Output() onToggle: EventEmitter<boolean> = new EventEmitter<boolean>(); | |
7 | + | |
8 | + private designModeOn: boolean = false; | |
9 | + | |
10 | + isInDesignMode(): boolean { | |
11 | + return this.designModeOn; | |
12 | + } | |
13 | + | |
14 | + setInDesignMode(value: boolean) { | |
15 | + if (this.designModeOn !== value) { | |
16 | + this.designModeOn = value; | |
17 | + this.onToggle.next(this.designModeOn); | |
18 | + } | |
19 | + } | |
20 | + | |
21 | + constructor() { | |
22 | + } | |
23 | +} | |
0 | 24 | \ No newline at end of file | ... | ... |
src/app/admin/layout-edit/designModeToggler.component.spec.ts
0 → 100644
... | ... | @@ -0,0 +1,59 @@ |
1 | +import {ComponentTestHelper, createClass} from '../../../spec/component-test-helper'; | |
2 | +import * as helpers from '../../../spec/helpers'; | |
3 | +import {DesignModeTogglerComponent} from './designModeToggler.component'; | |
4 | +import {DesignModeService} from './designMode.service'; | |
5 | + | |
6 | +describe('DesignModeToggler Component', () => { | |
7 | + const htmlTemplate: string = '<noosfero-design-toggler></noosfero-design-toggler>'; | |
8 | + | |
9 | + let helper: ComponentTestHelper<DesignModeTogglerComponent>; | |
10 | + beforeEach(() => { | |
11 | + angular.mock.module('templates'); | |
12 | + angular.mock.module('ngSanitize'); | |
13 | + angular.mock.module('toggle-switch'); | |
14 | + }); | |
15 | + | |
16 | + let designModeService: DesignModeService; | |
17 | + beforeEach((done) => { | |
18 | + designModeService = new DesignModeService(); | |
19 | + let cls = createClass({ | |
20 | + template: htmlTemplate, | |
21 | + directives: [DesignModeTogglerComponent], | |
22 | + providers: [ | |
23 | + helpers.createProviderToValue('DesignModeService', designModeService) | |
24 | + ] | |
25 | + }); | |
26 | + helper = new ComponentTestHelper<DesignModeTogglerComponent>(cls, done); | |
27 | + }); | |
28 | + | |
29 | + it('changes css classes representing the switch is on or off', () => { | |
30 | + expect(helper.debugElement.query('div.switch-animate').hasClass('switch-off')).toBeTruthy(); | |
31 | + expect(helper.debugElement.query('div.switch-animate').hasClass('switch-on')).toBeFalsy(); | |
32 | + helper.component.inDesignMode = true; | |
33 | + helper.detectChanges(); | |
34 | + expect(helper.debugElement.query('div.switch-animate').hasClass('switch-on')).toBeTruthy(); | |
35 | + expect(helper.debugElement.query('div.switch-animate').hasClass('switch-off')).toBeFalsy(); | |
36 | + }); | |
37 | + | |
38 | + it('emits event with value "true" when changing inDesignMode to On', (done) => { | |
39 | + designModeService.onToggle.subscribe((designModeOn: boolean) => { | |
40 | + expect(designModeOn).toBeTruthy(); | |
41 | + done(); | |
42 | + }); | |
43 | + helper.component.inDesignMode = true; | |
44 | + helper.detectChanges(); | |
45 | + }); | |
46 | + | |
47 | + it('emits events with value "false" when changing inDesignMode to Off', (done) => { | |
48 | + helper.component.inDesignMode = true; | |
49 | + helper.detectChanges(); | |
50 | + | |
51 | + designModeService.onToggle.subscribe((designModeOn: boolean) => { | |
52 | + expect(designModeOn).toBeFalsy(); | |
53 | + done(); | |
54 | + }); | |
55 | + | |
56 | + helper.component.inDesignMode = false; | |
57 | + helper.detectChanges(); | |
58 | + }); | |
59 | +}); | |
0 | 60 | \ No newline at end of file | ... | ... |
src/app/admin/layout-edit/designModeToggler.component.ts
0 → 100644
... | ... | @@ -0,0 +1,24 @@ |
1 | +import {Component, Inject} from 'ng-forward'; | |
2 | +import {DesignModeService} from './designMode.service'; | |
3 | +@Component({ | |
4 | + selector: 'noosfero-design-toggler', | |
5 | + templateUrl: 'app/admin/layout-edit/designModeToggler.html' | |
6 | +}) | |
7 | +@Inject(DesignModeService) | |
8 | +export class DesignModeTogglerComponent { | |
9 | + | |
10 | + icon: string = " <i class='glyphicon glyphicon-wrench'></i> "; | |
11 | + | |
12 | + constructor(private designModeService: DesignModeService) { | |
13 | + } | |
14 | + | |
15 | + private _inDesignMode: boolean = false; | |
16 | + | |
17 | + get inDesignMode(): boolean { | |
18 | + return this.designModeService.isInDesignMode(); | |
19 | + }; | |
20 | + | |
21 | + set inDesignMode(value: boolean) { | |
22 | + this.designModeService.setInDesignMode(value); | |
23 | + }; | |
24 | +} | |
0 | 25 | \ No newline at end of file | ... | ... |
... | ... | @@ -0,0 +1,8 @@ |
1 | +<toggle-switch | |
2 | + html="true" | |
3 | + ng-model="ctrl.inDesignMode" | |
4 | + on-label="{{'designMode.toggle.ON' | translate}}" | |
5 | + off-label="{{'designMode.toggle.OFF' | translate}}" | |
6 | + class="switch-small" | |
7 | + knob-label="{{ ctrl.icon + ('designMode.label' | translate) }}"> | |
8 | +</toggle-switch> | |
0 | 9 | \ No newline at end of file | ... | ... |
src/app/article/content-viewer/content-viewer.component.ts
... | ... | @@ -14,7 +14,7 @@ import {ProfileService} from "../../../lib/ng-noosfero-api/http/profile.service" |
14 | 14 | provide('profileService', { useClass: ProfileService }) |
15 | 15 | ] |
16 | 16 | }) |
17 | -@Inject(ArticleService, ProfileService, "$log", "$stateParams") | |
17 | +@Inject(ArticleService, ProfileService, "$stateParams") | |
18 | 18 | export class ContentViewerComponent { |
19 | 19 | |
20 | 20 | @Input() |
... | ... | @@ -23,7 +23,10 @@ export class ContentViewerComponent { |
23 | 23 | @Input() |
24 | 24 | profile: noosfero.Profile = null; |
25 | 25 | |
26 | - constructor(private articleService: ArticleService, private profileService: ProfileService, private $log: ng.ILogService, private $stateParams: angular.ui.IStateParamsService) { | |
26 | + constructor( | |
27 | + private articleService: ArticleService, | |
28 | + private profileService: ProfileService, | |
29 | + private $stateParams: angular.ui.IStateParamsService) { | |
27 | 30 | this.activate(); |
28 | 31 | } |
29 | 32 | ... | ... |
src/app/layout/navbar/navbar.html
... | ... | @@ -26,19 +26,20 @@ |
26 | 26 | <span ng-bind="ctrl.currentUser.person.name"></span> <b class="caret"></b> |
27 | 27 | </a> |
28 | 28 | <ul class="dropdown-menu" uib-dropdown-menu> |
29 | - <li> | |
30 | - <a ui-sref="main.profile.info({profile: ctrl.currentUser.person.identifier})"><i class="fa fa-fw fa-user"></i> {{"navbar.profile" | translate}}</a> | |
31 | - </li> | |
32 | - <li> | |
33 | - <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> | |
34 | - </li> | |
35 | - <li class="divider"></li> | |
36 | - <li> | |
37 | - <a href="#" ng-click="ctrl.logout()"><i class="fa fa-fw fa-power-off"></i> {{"navbar.logout" | translate}}</a> | |
38 | - </li> | |
29 | + <li> | |
30 | + <a ui-sref="main.profile.info({profile: ctrl.currentUser.person.identifier})"><i class="fa fa-fw fa-user"></i> {{"navbar.profile" | translate}}</a> | |
31 | + </li> | |
32 | + <li> | |
33 | + <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> | |
34 | + </li> | |
35 | + <li class="divider"></li> | |
36 | + <li> | |
37 | + <a href="#" ng-click="ctrl.logout()"><i class="fa fa-fw fa-power-off"></i> {{"navbar.logout" | translate}}</a> | |
38 | + </li> | |
39 | 39 | </ul> |
40 | 40 | </li> |
41 | 41 | </ul> |
42 | + | |
42 | 43 | <ul class="nav navbar-nav navbar-right"> |
43 | 44 | <language-selector class="nav navbar-nav navbar-right"></language-selector> |
44 | 45 | </ul> |
... | ... | @@ -49,3 +50,5 @@ |
49 | 50 | </div> |
50 | 51 | </div> |
51 | 52 | </nav> |
53 | +<div ui-view="toolbar"> | |
54 | +</div> | |
52 | 55 | \ No newline at end of file | ... | ... |
src/app/layout/navbar/navbar.ts
... | ... | @@ -4,11 +4,13 @@ import {SessionService, AuthService, AuthController, AuthEvents} from "./../../l |
4 | 4 | import {EnvironmentService} from "./../../../lib/ng-noosfero-api/http/environment.service"; |
5 | 5 | import {SidebarNotificationService} from "../sidebar/sidebar.notification.service"; |
6 | 6 | import {BodyStateClassesService} from '../services/body-state-classes.service'; |
7 | +import {DesignModeTogglerComponent} from './../../admin/layout-edit/designModeToggler.component'; | |
8 | +import {BootstrapSwitcherComponent, BootstrapSwitcherItem} from './../../shared/components/bootstrap-switcher/bootstrap-switcher.component'; | |
7 | 9 | |
8 | 10 | @Component({ |
9 | 11 | selector: "acme-navbar", |
10 | 12 | templateUrl: "app/layout/navbar/navbar.html", |
11 | - directives: [LanguageSelectorComponent], | |
13 | + directives: [LanguageSelectorComponent, DesignModeTogglerComponent, BootstrapSwitcherComponent], | |
12 | 14 | providers: [AuthService, SessionService, SidebarNotificationService, EnvironmentService] |
13 | 15 | }) |
14 | 16 | @Inject("$uibModal", AuthService, "SessionService", "$state", SidebarNotificationService, BodyStateClassesService, EnvironmentService) |
... | ... | @@ -18,7 +20,6 @@ export class Navbar { |
18 | 20 | private modalInstance: any = null; |
19 | 21 | public showHamburger: boolean = false; |
20 | 22 | public currentEnvironment: noosfero.Environment = <any>{ name: '' }; |
21 | - | |
22 | 23 | /** |
23 | 24 | * |
24 | 25 | */ | ... | ... |
src/app/layout/scss/_layout.scss
... | ... | @@ -35,3 +35,24 @@ |
35 | 35 | padding: 0 20px 20px 20px; |
36 | 36 | } |
37 | 37 | } |
38 | + | |
39 | + | |
40 | +body.noosfero-design-on { | |
41 | + | |
42 | + div.content-wrapper { | |
43 | + opacity: 0.5; | |
44 | + } | |
45 | +} | |
46 | + | |
47 | +ul.nav > li.toggler-container { | |
48 | + position: relative; | |
49 | + padding-top: 12px; | |
50 | +} | |
51 | + | |
52 | +.noosfero-main-toolbar { | |
53 | + padding: 5px; | |
54 | + @include make-row(); | |
55 | + margin-left: 0px; | |
56 | + margin-right: 0px; | |
57 | + background-color: #edecec; | |
58 | +} | |
38 | 59 | \ No newline at end of file | ... | ... |
src/app/layout/scss/skins/_whbl.scss
... | ... | @@ -281,6 +281,31 @@ $whbl-font-color: #16191c; |
281 | 281 | .pace .pace-progress { |
282 | 282 | background-color: #fff; |
283 | 283 | } |
284 | + | |
285 | + noosfero-design-toggler .ats-switch .knob i { | |
286 | + color: #999999; | |
287 | + } | |
288 | + | |
289 | + .ats-switch .knob { | |
290 | + padding-right: 15px; | |
291 | + } | |
292 | + | |
293 | + .ats-switch .glyphicon { | |
294 | + top: 2px; | |
295 | + } | |
296 | + | |
297 | + .ats-switch .switch-left { | |
298 | + background-color: #41b941; | |
299 | + font-weight: bold; | |
300 | + color: white; | |
301 | + } | |
302 | + | |
303 | + .ats-switch .switch-right { | |
304 | + background-color: #ce3b3b; | |
305 | + font-weight: bold; | |
306 | + color: white; | |
307 | + } | |
308 | + | |
284 | 309 | } |
285 | 310 | .rtl.skin-whbl #content-wrapper { |
286 | 311 | border-left: 0; | ... | ... |
src/app/layout/services/body-state-classes.service.spec.ts
... | ... | @@ -4,7 +4,7 @@ import {AuthService} from "./../../login/auth.service"; |
4 | 4 | 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 | 8 | |
9 | 9 | describe("BodyStateClasses Service", () => { |
10 | 10 | |
... | ... | @@ -19,10 +19,13 @@ describe("BodyStateClasses Service", () => { |
19 | 19 | }, |
20 | 20 | authService: any = helpers.mocks.authService, |
21 | 21 | bodyEl: { className: string }, |
22 | - bodyElJq: any; | |
22 | + bodyElJq: any, | |
23 | + designModeService = new DesignModeService(); | |
24 | + | |
25 | + | |
23 | 26 | |
24 | 27 | let getService = (): BodyStateClassesService => { |
25 | - return new BodyStateClassesService($rootScope, $document, $state, authService); | |
28 | + return new BodyStateClassesService($rootScope, $document, $state, authService, designModeService); | |
26 | 29 | }; |
27 | 30 | |
28 | 31 | beforeEach(() => { |
... | ... | @@ -168,4 +171,30 @@ describe("BodyStateClasses Service", () => { |
168 | 171 | |
169 | 172 | expect(contentWrapperMock.removeClass).toHaveBeenCalledWith(BodyStateClassesService.CONTENT_WRAPPER_FULL); |
170 | 173 | }); |
174 | + | |
175 | + it("should add the class noosfero-design-on when designMode is changed to true", () => { | |
176 | + let fnOnToggle: Function = null; | |
177 | + designModeService.onToggle = <any> { | |
178 | + subscribe: (fn: Function) => { | |
179 | + fnOnToggle = fn; | |
180 | + }, | |
181 | + next: (value: boolean) => { | |
182 | + fnOnToggle.apply(designModeService, [value]); | |
183 | + } | |
184 | + }; | |
185 | + | |
186 | + let service = getService(); | |
187 | + | |
188 | + bodyElJq.addClass = jasmine.createSpy("addClass"); | |
189 | + bodyElJq.removeClass = jasmine.createSpy("removeClass"); | |
190 | + service["bodyElement"] = bodyElJq; | |
191 | + | |
192 | + service.start(); | |
193 | + | |
194 | + debugger; | |
195 | + designModeService.setInDesignMode(true); | |
196 | + | |
197 | + | |
198 | + expect(bodyElJq.addClass).toHaveBeenCalledWith(BodyStateClassesService.DESIGN_MODE_ON_CLASSNAME); | |
199 | + }); | |
171 | 200 | }); | ... | ... |
src/app/layout/services/body-state-classes.service.ts
... | ... | @@ -3,6 +3,7 @@ import {AuthEvents} from "../../login/auth-events"; |
3 | 3 | import {AuthService} from "./../../login/auth.service"; |
4 | 4 | import {HtmlUtils} from "../html-utils"; |
5 | 5 | import {INgForwardJQuery} from 'ng-forward/cjs/util/jqlite-extensions'; |
6 | +import {DesignModeService} from './../../admin/layout-edit/designMode.service'; | |
6 | 7 | |
7 | 8 | export interface StartParams { |
8 | 9 | skin?: string; |
... | ... | @@ -22,12 +23,13 @@ export interface StartParams { |
22 | 23 | * - full-content |
23 | 24 | */ |
24 | 25 | @Injectable() |
25 | -@Inject("$rootScope", "$document", "$state", AuthService) | |
26 | +@Inject("$rootScope", "$document", "$state", AuthService, DesignModeService) | |
26 | 27 | export class BodyStateClassesService { |
27 | 28 | |
28 | 29 | private started: boolean = false; |
29 | 30 | private skin: string; |
30 | 31 | |
32 | + public static get DESIGN_MODE_ON_CLASSNAME(): string { return "noosfero-design-on"; } | |
31 | 33 | public static get USER_LOGGED_CLASSNAME(): string { return "noosfero-user-logged"; } |
32 | 34 | public static get ROUTE_STATE_CLASSNAME_PREFIX(): string { return "noosfero-route-"; } |
33 | 35 | public static get CONTENT_WRAPPER_FULL(): string { return "full-content"; } |
... | ... | @@ -38,16 +40,16 @@ export class BodyStateClassesService { |
38 | 40 | private $rootScope: ng.IRootScopeService, |
39 | 41 | private $document: ng.IDocumentService, |
40 | 42 | private $state: ng.ui.IStateService, |
41 | - private authService: AuthService | |
43 | + private authService: AuthService, | |
44 | + private designModeService: DesignModeService | |
42 | 45 | ) { |
43 | - | |
44 | 46 | } |
45 | 47 | |
46 | 48 | start(config?: StartParams) { |
47 | 49 | if (!this.started) { |
48 | 50 | this.setupUserLoggedClassToggle(); |
49 | 51 | this.setupStateClassToggle(); |
50 | - | |
52 | + this.setupDesignModeClassToggle(); | |
51 | 53 | if (config) { |
52 | 54 | this.setThemeSkin(config.skin); |
53 | 55 | } |
... | ... | @@ -87,9 +89,19 @@ export class BodyStateClassesService { |
87 | 89 | } |
88 | 90 | |
89 | 91 | /** |
90 | - * Setup the initial class name on body element indicating the current route | |
91 | - * and adds event handler to swith this class when the current page/state changes | |
92 | + * setup the listeners to the desigModeService to add class on the Body Element | |
93 | + * indicating the user activated the designMode | |
92 | 94 | */ |
95 | + private setupDesignModeClassToggle() { | |
96 | + this.designModeService.onToggle.subscribe((designOn: boolean) => { | |
97 | + if (designOn) { | |
98 | + this.getBodyElement().addClass(BodyStateClassesService.DESIGN_MODE_ON_CLASSNAME); | |
99 | + } else { | |
100 | + this.getBodyElement().removeClass(BodyStateClassesService.DESIGN_MODE_ON_CLASSNAME); | |
101 | + } | |
102 | + }); | |
103 | + } | |
104 | + | |
93 | 105 | private setupStateClassToggle() { |
94 | 106 | let bodyElement = this.getBodyElement(); |
95 | 107 | bodyElement.addClass(BodyStateClassesService.ROUTE_STATE_CLASSNAME_PREFIX + this.$state.current.name); | ... | ... |
src/app/main/main.component.ts
... | ... | @@ -111,7 +111,7 @@ export class EnvironmentContent { |
111 | 111 | "angular-bind-html-compile", "angularMoment", "angular.filter", "akoenig.deckgrid", |
112 | 112 | "angular-timeline", "duScroll", "oitozero.ngSweetAlert", |
113 | 113 | "pascalprecht.translate", "tmh.dynamicLocale", "angularLoad", |
114 | - "angular-click-outside", "noosfero.init"] | |
114 | + "angular-click-outside", "toggle-switch", "noosfero.init"] | |
115 | 115 | }) |
116 | 116 | @StateConfig([ |
117 | 117 | { | ... | ... |
... | ... | @@ -0,0 +1,21 @@ |
1 | +import {Component, Inject, provide} from "ng-forward"; | |
2 | +import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service"; | |
3 | + | |
4 | +@Component({ | |
5 | + selector: "profile-toolbar", | |
6 | + templateUrl: "app/profile/toolbar.html", | |
7 | + providers: [ | |
8 | + provide('profileService', { useClass: ProfileService }) | |
9 | + ] | |
10 | +}) | |
11 | +@Inject(ProfileService) | |
12 | +export class ProfileToolbarComponent { | |
13 | + profile: noosfero.Profile; | |
14 | + parentId: number; | |
15 | + | |
16 | + constructor(profileService: ProfileService) { | |
17 | + profileService.getCurrentProfile().then((profile: noosfero.Profile) => { | |
18 | + this.profile = profile; | |
19 | + }); | |
20 | + } | |
21 | +} | ... | ... |
src/app/profile/profile.component.ts
... | ... | @@ -10,7 +10,7 @@ import {ProfileService} from "../../lib/ng-noosfero-api/http/profile.service"; |
10 | 10 | import {NotificationService} from "../shared/services/notification.service"; |
11 | 11 | import {MyProfileComponent} from "./myprofile.component"; |
12 | 12 | import {ProfileActionsComponent} from "./profile-actions.component"; |
13 | - | |
13 | +import {ProfileToolbarComponent} from "./profile-toolbar.component"; | |
14 | 14 | /** |
15 | 15 | * @ngdoc controller |
16 | 16 | * @name profile.Profile |
... | ... | @@ -42,6 +42,11 @@ import {ProfileActionsComponent} from "./profile-actions.component"; |
42 | 42 | templateUrl: "app/profile/navbar-actions.html", |
43 | 43 | controller: ProfileActionsComponent, |
44 | 44 | controllerAs: "vm" |
45 | + }, | |
46 | + "toolbar@main": { | |
47 | + templateUrl: "app/profile/toolbar.html", | |
48 | + controller: ProfileToolbarComponent, | |
49 | + controllerAs: "vm" | |
45 | 50 | } |
46 | 51 | } |
47 | 52 | }, |
... | ... | @@ -54,6 +59,11 @@ import {ProfileActionsComponent} from "./profile-actions.component"; |
54 | 59 | templateUrl: "app/profile/navbar-actions.html", |
55 | 60 | controller: ProfileActionsComponent, |
56 | 61 | controllerAs: "vm" |
62 | + }, | |
63 | + "toolbar@main": { | |
64 | + templateUrl: "app/profile/toolbar.html", | |
65 | + controller: ProfileToolbarComponent, | |
66 | + controllerAs: "vm" | |
57 | 67 | } |
58 | 68 | } |
59 | 69 | }, |
... | ... | @@ -106,6 +116,11 @@ import {ProfileActionsComponent} from "./profile-actions.component"; |
106 | 116 | templateUrl: "app/article/content-viewer/navbar-actions.html", |
107 | 117 | controller: ContentViewerActionsComponent, |
108 | 118 | controllerAs: "vm" |
119 | + }, | |
120 | + "toolbar@main": { | |
121 | + templateUrl: "app/profile/toolbar.html", | |
122 | + controller: ProfileToolbarComponent, | |
123 | + controllerAs: "vm" | |
109 | 124 | } |
110 | 125 | } |
111 | 126 | } | ... | ... |
src/app/shared/components/bootstrap-switcher/bootstrap-switcher.component.ts
0 → 100644
... | ... | @@ -0,0 +1,51 @@ |
1 | +import {Component, Input, Output, EventEmitter} from 'ng-forward'; | |
2 | + | |
3 | + | |
4 | +export interface BootstrapSwitcherItem { | |
5 | + value: any; | |
6 | + label: string; | |
7 | +} | |
8 | +@Component({ | |
9 | + selector: 'noosfero-bootstrap-switcher', | |
10 | + template: ` | |
11 | + <span class="switcher-label" ng-bind="ctrl.label | translate"></span> | |
12 | + <div class="btn-group switcher"> | |
13 | + <button ng-repeat="option in ctrl.options track by $index" | |
14 | + (click)="ctrl.switcherClick(option)" | |
15 | + ng-class="ctrl.getCssClassForItem(option)" | |
16 | + class="btn btn-xs" ng-bind="option.label | translate"> | |
17 | + </button> | |
18 | + </div> | |
19 | + `, | |
20 | + inputs: ['activeClass', 'defaultClass', 'label', 'options', 'defaultOption'], | |
21 | + outputs: ['onSwitch'] | |
22 | +}) | |
23 | +export class BootstrapSwitcherComponent { | |
24 | + @Input() activeClass: string = 'active btn-danger'; | |
25 | + @Input() defaultClass: string = 'btn-default'; | |
26 | + @Input() label: string; | |
27 | + @Input() options: BootstrapSwitcherItem[]; | |
28 | + @Input() defaultOption: BootstrapSwitcherItem; | |
29 | + @Output() onSwitch: EventEmitter<BootstrapSwitcherItem> = new EventEmitter<BootstrapSwitcherItem>(); | |
30 | + | |
31 | + selectedOption: BootstrapSwitcherItem = null; | |
32 | + | |
33 | + constructor() { } | |
34 | + | |
35 | + ngOnInit() { | |
36 | + this.selectedOption = this.defaultOption; | |
37 | + } | |
38 | + | |
39 | + isSelectedOption(value: BootstrapSwitcherItem): boolean { | |
40 | + return this.selectedOption === value; | |
41 | + } | |
42 | + | |
43 | + getCssClassForItem(value: BootstrapSwitcherItem): string { | |
44 | + return this.isSelectedOption(value) ? this.activeClass : this.defaultClass; | |
45 | + } | |
46 | + | |
47 | + switcherClick(value: BootstrapSwitcherItem) { | |
48 | + this.selectedOption = value; | |
49 | + this.onSwitch.next(value); | |
50 | + } | |
51 | +} | |
0 | 52 | \ No newline at end of file | ... | ... |
src/app/shared/components/permission/permission.directive.ts
... | ... | @@ -6,7 +6,7 @@ import {Directive, Inject, Input} from "ng-forward"; |
6 | 6 | @Inject('$attrs', '$scope', '$element') |
7 | 7 | export class PermissionDirective { |
8 | 8 | |
9 | - constructor($attrs: ng.IAttributes, $scope: ng.IScope, $element: any) { | |
9 | + constructor($attrs: ng.IAttributes, $scope: ng.IScope, $element: ng.IAugmentedJQuery) { | |
10 | 10 | $scope.$watch($attrs['permission'], () => { |
11 | 11 | let permissions = $scope.$eval($attrs['permission']); |
12 | 12 | let permissionAction = $attrs['permissionAction']; | ... | ... |
src/languages/en.json
... | ... | @@ -75,6 +75,9 @@ |
75 | 75 | "custom_content.title": "Edit content", |
76 | 76 | "profile.custom_header.label": "Header", |
77 | 77 | "profile.custom_footer.label": "Footer", |
78 | + "designMode.label": "In Design", | |
79 | + "designMode.toggle.ON": "ON", | |
80 | + "designMode.toggle.OFF": "OFF", | |
78 | 81 | "search.results.summary": "{results, plural, one{result} other{# results}}", |
79 | 82 | "search.results.query.label": "Search for:", |
80 | 83 | "search.results.query.placeholder": "Search" | ... | ... |
src/languages/pt.json
... | ... | @@ -75,6 +75,9 @@ |
75 | 75 | "custom_content.title": "Editar conteúdo", |
76 | 76 | "profile.custom_header.label": "Cabeçalho", |
77 | 77 | "profile.custom_footer.label": "Rodapé", |
78 | + "designMode.label": "Modo de Edição", | |
79 | + "designMode.toggle.ON": "Ligado", | |
80 | + "designMode.toggle.OFF": "Desligado", | |
78 | 81 | "search.results.summary": "{results, plural, one{# resultado} other{# resultados}}", |
79 | 82 | "search.results.query.label": "Buscar:", |
80 | 83 | "search.results.query.placeholder": "Informe aqui sua busca" | ... | ... |
src/lib/ng-noosfero-api/http/profile.service.ts
... | ... | @@ -22,7 +22,7 @@ export class ProfileService { |
22 | 22 | this._currentProfilePromise.resolve(profile); |
23 | 23 | } |
24 | 24 | |
25 | - setCurrentProfileByIdentifier(identifier: string) { | |
25 | + setCurrentProfileByIdentifier(identifier: string): ng.IPromise<noosfero.Profile> { | |
26 | 26 | this.resetCurrentProfile(); |
27 | 27 | return this.getByIdentifier(identifier).then((profile: noosfero.Profile) => { |
28 | 28 | this.setCurrentProfile(profile); | ... | ... |
src/lib/ng-noosfero-api/interfaces/article.ts
src/lib/ng-noosfero-api/interfaces/modelWithPermissions.ts
0 → 100644
src/lib/ng-noosfero-api/interfaces/profile.ts