Commit c9e0fbd34222397332aa83d66ed06550e7b27731

Authored by Michel Felipe
1 parent 8f52051e

Refactor the 'ProfileToolbarComponent' to a new concept using 'ConfigBarComponen…

…t' aligned to right of screen
@@ -39,7 +39,8 @@ @@ -39,7 +39,8 @@
39 "angular-click-outside": "^2.7.1", 39 "angular-click-outside": "^2.7.1",
40 "ng-ckeditor": "^0.2.1", 40 "ng-ckeditor": "^0.2.1",
41 "angular-bootstrap-toggle-switch": "^0.5.6", 41 "angular-bootstrap-toggle-switch": "^0.5.6",
42 - "angular-tag-cloud": "^0.3.0" 42 + "angular-tag-cloud": "^0.3.0",
  43 + "angular-ui-switch": "^0.1.1"
43 }, 44 },
44 "devDependencies": { 45 "devDependencies": {
45 "angular-mocks": "~1.5.0" 46 "angular-mocks": "~1.5.0"
src/app/admin/layout-edit/designModeToggler.component.spec.ts
1 import {ComponentTestHelper, createClass} from '../../../spec/component-test-helper'; 1 import {ComponentTestHelper, createClass} from '../../../spec/component-test-helper';
  2 +import {INgForwardJQuery} from 'ng-forward/cjs/util/jqlite-extensions';
2 import * as helpers from '../../../spec/helpers'; 3 import * as helpers from '../../../spec/helpers';
3 import {DesignModeTogglerComponent} from './designModeToggler.component'; 4 import {DesignModeTogglerComponent} from './designModeToggler.component';
4 import {DesignModeService} from './designMode.service'; 5 import {DesignModeService} from './designMode.service';
5 import {INoosferoLocalStorage} from "./../../shared/models/interfaces"; 6 import {INoosferoLocalStorage} from "./../../shared/models/interfaces";
6 7
7 describe('DesignModeToggler Component', () => { 8 describe('DesignModeToggler Component', () => {
8 - const htmlTemplate: string = '<noosfero-design-toggler></noosfero-design-toggler>'; 9 + const htmlTemplate: string = '<design-toggler></design-toggler>';
9 10
10 let helper: ComponentTestHelper<DesignModeTogglerComponent>; 11 let helper: ComponentTestHelper<DesignModeTogglerComponent>;
11 beforeEach(() => { 12 beforeEach(() => {
12 angular.mock.module('templates'); 13 angular.mock.module('templates');
13 angular.mock.module('ngSanitize'); 14 angular.mock.module('ngSanitize');
14 - angular.mock.module('toggle-switch'); 15 + angular.mock.module('uiSwitch');
15 }); 16 });
16 17
17 let designModeService: DesignModeService; 18 let designModeService: DesignModeService;
@@ -30,12 +31,12 @@ describe(&#39;DesignModeToggler Component&#39;, () =&gt; { @@ -30,12 +31,12 @@ describe(&#39;DesignModeToggler Component&#39;, () =&gt; {
30 }); 31 });
31 32
32 it('changes css classes representing the switch is on or off', () => { 33 it('changes css classes representing the switch is on or off', () => {
33 - expect(helper.debugElement.query('div.switch-animate').hasClass('switch-off')).toBeTruthy();  
34 - expect(helper.debugElement.query('div.switch-animate').hasClass('switch-on')).toBeFalsy(); 34 + let switchEl: INgForwardJQuery = helper.debugElement.query('span.switch');
  35 +
  36 + expect(switchEl.hasClass('checked')).toBeFalsy();
35 helper.component.inDesignMode = true; 37 helper.component.inDesignMode = true;
36 helper.detectChanges(); 38 helper.detectChanges();
37 - expect(helper.debugElement.query('div.switch-animate').hasClass('switch-on')).toBeTruthy();  
38 - expect(helper.debugElement.query('div.switch-animate').hasClass('switch-off')).toBeFalsy(); 39 + expect(switchEl.hasClass('checked')).toBeTruthy();
39 }); 40 });
40 41
41 it('emits event with value "true" when changing inDesignMode to On', (done) => { 42 it('emits event with value "true" when changing inDesignMode to On', (done) => {
@@ -60,4 +61,4 @@ describe(&#39;DesignModeToggler Component&#39;, () =&gt; { @@ -60,4 +61,4 @@ describe(&#39;DesignModeToggler Component&#39;, () =&gt; {
60 helper.component.inDesignMode = false; 61 helper.component.inDesignMode = false;
61 helper.detectChanges(); 62 helper.detectChanges();
62 }); 63 });
63 -});  
64 \ No newline at end of file 64 \ No newline at end of file
  65 +});
src/app/admin/layout-edit/designModeToggler.component.ts
@@ -3,17 +3,12 @@ import {DesignModeService} from &#39;./designMode.service&#39;; @@ -3,17 +3,12 @@ import {DesignModeService} from &#39;./designMode.service&#39;;
3 import {AuthService, AuthEvents} from '../../login'; 3 import {AuthService, AuthEvents} from '../../login';
4 4
5 @Component({ 5 @Component({
6 - selector: 'noosfero-design-toggler', 6 + selector: 'design-toggler',
7 templateUrl: 'app/admin/layout-edit/designModeToggler.html' 7 templateUrl: 'app/admin/layout-edit/designModeToggler.html'
8 }) 8 })
9 @Inject(DesignModeService, AuthService, '$sce') 9 @Inject(DesignModeService, AuthService, '$sce')
10 export class DesignModeTogglerComponent { 10 export class DesignModeTogglerComponent {
11 11
12 - @Input() iconClass: string = '';  
13 - @Input() knobLabel: string = '';  
14 - @Input() offLabel: string = '';  
15 - @Input() onLabel: string = '';  
16 -  
17 private _inDesignMode: boolean = false; 12 private _inDesignMode: boolean = false;
18 13
19 constructor(private designModeService: DesignModeService, private authService: AuthService, private $sce: ng.ISCEService) { 14 constructor(private designModeService: DesignModeService, private authService: AuthService, private $sce: ng.ISCEService) {
@@ -22,19 +17,6 @@ export class DesignModeTogglerComponent { @@ -22,19 +17,6 @@ export class DesignModeTogglerComponent {
22 }); 17 });
23 } 18 }
24 19
25 - get icon(): string {  
26 - if (this.iconClass && this.iconClass.trim().length > 0) {  
27 - return '<i class=\'design-toggle-icon ' + this.iconClass + '\'></i>';  
28 - }  
29 - else {  
30 - return '';  
31 - }  
32 - }  
33 -  
34 - getKnobLabel(): string {  
35 - return this.$sce.trustAsHtml(this.icon + this.knobLabel);  
36 - }  
37 -  
38 get inDesignMode(): boolean { 20 get inDesignMode(): boolean {
39 return this.designModeService.isInDesignMode(); 21 return this.designModeService.isInDesignMode();
40 }; 22 };
src/app/admin/layout-edit/designModeToggler.html
1 -<toggle-switch  
2 - html="true"  
3 - ng-model="ctrl.inDesignMode"  
4 - on-label="{{ctrl.onLabel}}"  
5 - off-label="{{ctrl.offLabel}}"  
6 - class="switch-small"  
7 - knob-label="{{ ctrl.getKnobLabel() }}">  
8 -</toggle-switch>  
9 \ No newline at end of file 1 \ No newline at end of file
  2 +<switch id="enabled" name="enabled" ng-model="ctrl.inDesignMode" on="ON" off="OFF" class="green"></switch>
src/app/admin/layout-edit/designModeToggler.scss
1 -ul.nav > li.toggler-container {  
2 - position: relative;  
3 - padding-top: 12px;  
4 -} 1 +$off-text: #949494;
  2 +$off-color: #EFEFEF;
  3 +$blue-color: #36B4F6;
  4 +$red-color: #DF3B3A;
5 5
6 body.noosfero-design-on { 6 body.noosfero-design-on {
7 7
@@ -10,14 +10,46 @@ body.noosfero-design-on { @@ -10,14 +10,46 @@ body.noosfero-design-on {
10 } 10 }
11 } 11 }
12 12
  13 +.switch {
  14 + @include not-select();
  15 + background-color: $off-color;
13 16
  17 + &[on][off] {
  18 + width: 60px;
  19 + }
14 20
15 -noosfero-design-toggler .ats-switch .knob i {  
16 - color: #999999;  
17 -} 21 + &:focus {
  22 + outline: none;
  23 + }
  24 +
  25 + &.checked small {
  26 + left: initial;
  27 + right: 0px;
  28 + }
  29 +
  30 + &.blue.checked {
  31 + background: $blue-color;
  32 + border-color: $blue-color;
  33 + }
18 34
  35 + &.red.checked {
  36 + background: $red-color;
  37 + border-color: $red-color;
  38 + }
19 39
20 -.design-toggle-icon {  
21 - margin-left: 3px;  
22 - margin-right: 3px;  
23 -}  
24 \ No newline at end of file 40 \ No newline at end of file
  41 + %switch-label {
  42 + font-weight: bold;
  43 + }
  44 +
  45 + .on {
  46 + @extend %switch-label;
  47 + }
  48 +
  49 + .off {
  50 + @extend %switch-label;
  51 + right: 2px;
  52 + top: 25%;
  53 + color: $off-text;
  54 + text-align: center;
  55 + }
  56 +}
src/app/layout/scss/_mixins.scss
@@ -4,6 +4,12 @@ @@ -4,6 +4,12 @@
4 background-clip: padding-box; /* stops bg color from leaking outside the border: */ 4 background-clip: padding-box; /* stops bg color from leaking outside the border: */
5 } 5 }
6 6
  7 +@mixin box-shadow($args...) {
  8 + -webkit-box-shadow: $args;
  9 + -moz-box-shadow: $args;
  10 + box-shadow: $args;
  11 +}
  12 +
7 @mixin checkbox-mark($width, $height, $top, $left, $bg, $border, $content: "", $cursor: pointer, $position: absolute) { 13 @mixin checkbox-mark($width, $height, $top, $left, $bg, $border, $content: "", $cursor: pointer, $position: absolute) {
8 width: $width; 14 width: $width;
9 height: $height; 15 height: $height;
@@ -49,6 +55,16 @@ @@ -49,6 +55,16 @@
49 } 55 }
50 } 56 }
51 57
  58 +@mixin not-select() {
  59 + -webkit-touch-callout: none; /* iOS Safari */
  60 + -webkit-user-select: none; /* Chrome/Safari/Opera */
  61 + -khtml-user-select: none; /* Konqueror */
  62 + -moz-user-select: none; /* Firefox */
  63 + -ms-user-select: none; /* Internet Explorer/Edge */
  64 + user-select: none; /* Non-prefixed version, currently
  65 + not supported by any browser */
  66 +}
  67 +
52 @mixin keyframes($animation-name) { 68 @mixin keyframes($animation-name) {
53 @-webkit-keyframes #{$animation-name} { 69 @-webkit-keyframes #{$animation-name} {
54 @content; 70 @content;
src/app/main/main.component.ts
@@ -115,7 +115,7 @@ export class EnvironmentContent { @@ -115,7 +115,7 @@ export class EnvironmentContent {
115 "angular-bind-html-compile", "angularMoment", "angular.filter", "akoenig.deckgrid", 115 "angular-bind-html-compile", "angularMoment", "angular.filter", "akoenig.deckgrid",
116 "angular-timeline", "duScroll", "oitozero.ngSweetAlert", 116 "angular-timeline", "duScroll", "oitozero.ngSweetAlert",
117 "pascalprecht.translate", "tmh.dynamicLocale", "angularLoad", 117 "pascalprecht.translate", "tmh.dynamicLocale", "angularLoad",
118 - "angular-click-outside", "toggle-switch", "ngTagCloud", "noosfero.init"] 118 + "angular-click-outside", "toggle-switch", "ngTagCloud", "noosfero.init", "uiSwitch"]
119 }) 119 })
120 @StateConfig([ 120 @StateConfig([
121 { 121 {
src/app/profile/config-bar.component.ts 0 → 100644
@@ -0,0 +1,21 @@ @@ -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: "configbar",
  6 + templateUrl: "app/profile/configbar.html",
  7 + providers: [
  8 + provide('profileService', { useClass: ProfileService })
  9 + ]
  10 +})
  11 +@Inject(ProfileService)
  12 +export class ConfigBarComponent {
  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/configbar.html 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +<div id="config-tool" ng-class="{'closed': !showConfig}">
  2 + <a id="config-tool-cog" ng-click="showConfig = !showConfig">
  3 + <i class="fa fa-cog" ng-class="{'anim-icon': showConfig}"></i>
  4 + </a>
  5 +
  6 + <div id="config-tool-options">
  7 + <h4>{{ 'configbar.label' | translate }}</h4>
  8 + <div class="section-title">{{ 'configbar.section.layout' | translate }}</div>
  9 + <ul>
  10 + <li>
  11 + <label class="pull-left">
  12 + <i class="fa fa-th-large"></i>
  13 + <span class="item-label">{{ 'designMode.label' | translate }}</span>
  14 + </label>
  15 + <label class="pull-right">
  16 + <design-toggler></design-toggler>
  17 + </label>
  18 + </li>
  19 + </ul>
  20 + </div>
  21 +</div>
src/app/profile/configbar.scss 0 → 100644
@@ -0,0 +1,102 @@ @@ -0,0 +1,102 @@
  1 +@import "../layout/scss/mixins";
  2 +
  3 +@include keyframes(rotating) {
  4 + from {
  5 + transform: rotate(0deg);
  6 + }
  7 + to {
  8 + transform: rotate(360deg);
  9 + }
  10 +}
  11 +
  12 +/* CONFIG TOOLS */
  13 +#config-tool {
  14 + @include transition(all 0.2s ease-in-out 0s);
  15 + @include box-shadow(0px 1px 4px rgba(0, 0, 0, 0.3));
  16 + position: fixed;
  17 + right: 0;
  18 + top: 120px;
  19 + min-width: 200px;
  20 + z-index: 1000;
  21 +
  22 + #config-tool-cog {
  23 + @include border-radius($border-radius-base 0 0 $border-radius-base);
  24 + @include transition(all 0.1s ease-in-out 0s);
  25 + @include box-shadow(-3px 3px 3px -2px rgba(0, 0, 0, 0.1));
  26 + background: #fff;
  27 + cursor: pointer;
  28 + left: -50px;
  29 + padding: 10px;
  30 + position: absolute;
  31 + text-align: center;
  32 + width: 50px;
  33 + top: 0;
  34 +
  35 + i {
  36 + font-size: 2.2em;
  37 + }
  38 +
  39 + .anim-icon {
  40 + @include animation(rotating 0.7s ease-in-out 0s);
  41 + }
  42 + }
  43 +
  44 + &.closed {
  45 + right: -280px;
  46 + box-shadow: none;
  47 +
  48 + #config-tool-cog {
  49 + &:hover {
  50 + background-color: $primary-color;
  51 + color: #fff;
  52 + }
  53 + }
  54 + }
  55 +
  56 + &.opened {
  57 + right: 0;
  58 + }
  59 +
  60 + .section-title {
  61 + font-size: 15px;
  62 + font-weight: bold;
  63 + margin: 30px 0 5px;
  64 + }
  65 +
  66 + #config-tool-options {
  67 + @include box-shadow(-3px 3px 3px -2px rgba(0, 0, 0, 0.1));
  68 + background: #fff;
  69 + padding: 15px;
  70 +
  71 + h4 {
  72 + margin: 0;
  73 + font-size: 1.3em;
  74 + }
  75 +
  76 + ul {
  77 + list-style: none;
  78 + border-radius: 2px;
  79 + background-clip: padding-box;
  80 + background-color: #f1f3f2;
  81 + padding: 0;
  82 +
  83 + li {
  84 + font-size: 13px;
  85 + font-weight: 300;
  86 + padding: 10px;
  87 + width: 250px;
  88 + min-height: 50px;
  89 +
  90 + .checkbox {
  91 + margin: 0;
  92 + }
  93 +
  94 + .pull-left {
  95 + margin-top: 8px;
  96 + font-weight: normal;
  97 + }
  98 +
  99 + }
  100 + }
  101 + }
  102 +}
src/app/profile/profile.component.ts
@@ -10,7 +10,7 @@ import {ProfileService} from &quot;../../lib/ng-noosfero-api/http/profile.service&quot;; @@ -10,7 +10,7 @@ import {ProfileService} from &quot;../../lib/ng-noosfero-api/http/profile.service&quot;;
10 import {NotificationService} from "../shared/services/notification.service"; 10 import {NotificationService} from "../shared/services/notification.service";
11 import {MyProfileComponent} from "./myprofile.component"; 11 import {MyProfileComponent} from "./myprofile.component";
12 import {ProfileActionsComponent} from "./profile-actions.component"; 12 import {ProfileActionsComponent} from "./profile-actions.component";
13 -import {ProfileToolbarComponent} from "./profile-toolbar.component"; 13 +import {ConfigBarComponent} from "./config-bar.component";
14 /** 14 /**
15 * @ngdoc controller 15 * @ngdoc controller
16 * @name profile.Profile 16 * @name profile.Profile
@@ -44,8 +44,8 @@ import {ProfileToolbarComponent} from &quot;./profile-toolbar.component&quot;; @@ -44,8 +44,8 @@ import {ProfileToolbarComponent} from &quot;./profile-toolbar.component&quot;;
44 controllerAs: "vm" 44 controllerAs: "vm"
45 }, 45 },
46 "toolbar@main": { 46 "toolbar@main": {
47 - templateUrl: "app/profile/toolbar.html",  
48 - controller: ProfileToolbarComponent, 47 + templateUrl: "app/profile/configbar.html",
  48 + controller: ConfigBarComponent,
49 controllerAs: "vm" 49 controllerAs: "vm"
50 } 50 }
51 } 51 }
@@ -61,8 +61,8 @@ import {ProfileToolbarComponent} from &quot;./profile-toolbar.component&quot;; @@ -61,8 +61,8 @@ import {ProfileToolbarComponent} from &quot;./profile-toolbar.component&quot;;
61 controllerAs: "vm" 61 controllerAs: "vm"
62 }, 62 },
63 "toolbar@main": { 63 "toolbar@main": {
64 - templateUrl: "app/profile/toolbar.html",  
65 - controller: ProfileToolbarComponent, 64 + templateUrl: "app/profile/configbar.html",
  65 + controller: ConfigBarComponent,
66 controllerAs: "vm" 66 controllerAs: "vm"
67 } 67 }
68 } 68 }
@@ -118,8 +118,8 @@ import {ProfileToolbarComponent} from &quot;./profile-toolbar.component&quot;; @@ -118,8 +118,8 @@ import {ProfileToolbarComponent} from &quot;./profile-toolbar.component&quot;;
118 controllerAs: "vm" 118 controllerAs: "vm"
119 }, 119 },
120 "toolbar@main": { 120 "toolbar@main": {
121 - templateUrl: "app/profile/toolbar.html",  
122 - controller: ProfileToolbarComponent, 121 + templateUrl: "app/profile/configbar.html",
  122 + controller: ConfigBarComponent,
123 controllerAs: "vm" 123 controllerAs: "vm"
124 } 124 }
125 } 125 }
src/languages/en.json
@@ -6,6 +6,8 @@ @@ -6,6 +6,8 @@
6 "navbar.logout": "Log Out", 6 "navbar.logout": "Log Out",
7 "navbar.login": "Login", 7 "navbar.login": "Login",
8 "navbar.toggle_menu": "Toggle navigation", 8 "navbar.toggle_menu": "Toggle navigation",
  9 + "configbar.label": "Configuration",
  10 + "configbar.section.layout": "Layout",
9 "language.all": "All languages", 11 "language.all": "All languages",
10 "language.en": "English", 12 "language.en": "English",
11 "language.pt": "Portuguese", 13 "language.pt": "Portuguese",
@@ -77,9 +79,7 @@ @@ -77,9 +79,7 @@
77 "custom_content.title": "Edit content", 79 "custom_content.title": "Edit content",
78 "profile.custom_header.label": "Header", 80 "profile.custom_header.label": "Header",
79 "profile.custom_footer.label": "Footer", 81 "profile.custom_footer.label": "Footer",
80 - "designMode.label": "In Design",  
81 - "designMode.toggle.ON": "ON",  
82 - "designMode.toggle.OFF": "OFF", 82 + "designMode.label": "Design mode",
83 "search.results.summary": "{results, plural, one{result} other{# results}}", 83 "search.results.summary": "{results, plural, one{result} other{# results}}",
84 "search.results.query.label": "Search therm:", 84 "search.results.query.label": "Search therm:",
85 "search.label": "Search", 85 "search.label": "Search",
src/languages/pt.json
@@ -6,6 +6,8 @@ @@ -6,6 +6,8 @@
6 "navbar.logout": "Sair", 6 "navbar.logout": "Sair",
7 "navbar.login": "Login", 7 "navbar.login": "Login",
8 "navbar.toggle_menu": "Abrir Menu", 8 "navbar.toggle_menu": "Abrir Menu",
  9 + "configbar.label": "Configurações",
  10 + "configbar.section.layout": "Visual",
9 "language.all": "Todos os idiomas", 11 "language.all": "Todos os idiomas",
10 "language.en": "Inglês", 12 "language.en": "Inglês",
11 "language.pt": "Português", 13 "language.pt": "Português",
@@ -77,9 +79,7 @@ @@ -77,9 +79,7 @@
77 "custom_content.title": "Editar conteúdo", 79 "custom_content.title": "Editar conteúdo",
78 "profile.custom_header.label": "Cabeçalho", 80 "profile.custom_header.label": "Cabeçalho",
79 "profile.custom_footer.label": "Rodapé", 81 "profile.custom_footer.label": "Rodapé",
80 - "designMode.label": "Modo de Edição",  
81 - "designMode.toggle.ON": "Ligado",  
82 - "designMode.toggle.OFF": "Desligado", 82 + "designMode.label": "Alterar design",
83 "search.results.summary": "{results, plural, one{# resultado} other{# resultados}}", 83 "search.results.summary": "{results, plural, one{# resultado} other{# resultados}}",
84 "search.results.query.label": "Termo da busca:", 84 "search.results.query.label": "Termo da busca:",
85 "search.label": "Pesquisar", 85 "search.label": "Pesquisar",