Commit c9e0fbd34222397332aa83d66ed06550e7b27731

Authored by Michel Felipe
1 parent 8f52051e

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

…t' aligned to right of screen
bower.json
... ... @@ -39,7 +39,8 @@
39 39 "angular-click-outside": "^2.7.1",
40 40 "ng-ckeditor": "^0.2.1",
41 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 45 "devDependencies": {
45 46 "angular-mocks": "~1.5.0"
... ...
src/app/admin/layout-edit/designModeToggler.component.spec.ts
1 1 import {ComponentTestHelper, createClass} from '../../../spec/component-test-helper';
  2 +import {INgForwardJQuery} from 'ng-forward/cjs/util/jqlite-extensions';
2 3 import * as helpers from '../../../spec/helpers';
3 4 import {DesignModeTogglerComponent} from './designModeToggler.component';
4 5 import {DesignModeService} from './designMode.service';
5 6 import {INoosferoLocalStorage} from "./../../shared/models/interfaces";
6 7  
7 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 11 let helper: ComponentTestHelper<DesignModeTogglerComponent>;
11 12 beforeEach(() => {
12 13 angular.mock.module('templates');
13 14 angular.mock.module('ngSanitize');
14   - angular.mock.module('toggle-switch');
  15 + angular.mock.module('uiSwitch');
15 16 });
16 17  
17 18 let designModeService: DesignModeService;
... ... @@ -30,12 +31,12 @@ describe(&#39;DesignModeToggler Component&#39;, () =&gt; {
30 31 });
31 32  
32 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 37 helper.component.inDesignMode = true;
36 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 42 it('emits event with value "true" when changing inDesignMode to On', (done) => {
... ... @@ -60,4 +61,4 @@ describe(&#39;DesignModeToggler Component&#39;, () =&gt; {
60 61 helper.component.inDesignMode = false;
61 62 helper.detectChanges();
62 63 });
63   -});
64 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 3 import {AuthService, AuthEvents} from '../../login';
4 4  
5 5 @Component({
6   - selector: 'noosfero-design-toggler',
  6 + selector: 'design-toggler',
7 7 templateUrl: 'app/admin/layout-edit/designModeToggler.html'
8 8 })
9 9 @Inject(DesignModeService, AuthService, '$sce')
10 10 export class DesignModeTogglerComponent {
11 11  
12   - @Input() iconClass: string = '';
13   - @Input() knobLabel: string = '';
14   - @Input() offLabel: string = '';
15   - @Input() onLabel: string = '';
16   -
17 12 private _inDesignMode: boolean = false;
18 13  
19 14 constructor(private designModeService: DesignModeService, private authService: AuthService, private $sce: ng.ISCEService) {
... ... @@ -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 20 get inDesignMode(): boolean {
39 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 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 6 body.noosfero-design-on {
7 7  
... ... @@ -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 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 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 13 @mixin checkbox-mark($width, $height, $top, $left, $bg, $border, $content: "", $cursor: pointer, $position: absolute) {
8 14 width: $width;
9 15 height: $height;
... ... @@ -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 68 @mixin keyframes($animation-name) {
53 69 @-webkit-keyframes #{$animation-name} {
54 70 @content;
... ...
src/app/main/main.component.ts
... ... @@ -115,7 +115,7 @@ export class EnvironmentContent {
115 115 "angular-bind-html-compile", "angularMoment", "angular.filter", "akoenig.deckgrid",
116 116 "angular-timeline", "duScroll", "oitozero.ngSweetAlert",
117 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 120 @StateConfig([
121 121 {
... ...
src/app/profile/config-bar.component.ts 0 → 100644
... ... @@ -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 @@
  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 @@
  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 10 import {NotificationService} from "../shared/services/notification.service";
11 11 import {MyProfileComponent} from "./myprofile.component";
12 12 import {ProfileActionsComponent} from "./profile-actions.component";
13   -import {ProfileToolbarComponent} from "./profile-toolbar.component";
  13 +import {ConfigBarComponent} from "./config-bar.component";
14 14 /**
15 15 * @ngdoc controller
16 16 * @name profile.Profile
... ... @@ -44,8 +44,8 @@ import {ProfileToolbarComponent} from &quot;./profile-toolbar.component&quot;;
44 44 controllerAs: "vm"
45 45 },
46 46 "toolbar@main": {
47   - templateUrl: "app/profile/toolbar.html",
48   - controller: ProfileToolbarComponent,
  47 + templateUrl: "app/profile/configbar.html",
  48 + controller: ConfigBarComponent,
49 49 controllerAs: "vm"
50 50 }
51 51 }
... ... @@ -61,8 +61,8 @@ import {ProfileToolbarComponent} from &quot;./profile-toolbar.component&quot;;
61 61 controllerAs: "vm"
62 62 },
63 63 "toolbar@main": {
64   - templateUrl: "app/profile/toolbar.html",
65   - controller: ProfileToolbarComponent,
  64 + templateUrl: "app/profile/configbar.html",
  65 + controller: ConfigBarComponent,
66 66 controllerAs: "vm"
67 67 }
68 68 }
... ... @@ -118,8 +118,8 @@ import {ProfileToolbarComponent} from &quot;./profile-toolbar.component&quot;;
118 118 controllerAs: "vm"
119 119 },
120 120 "toolbar@main": {
121   - templateUrl: "app/profile/toolbar.html",
122   - controller: ProfileToolbarComponent,
  121 + templateUrl: "app/profile/configbar.html",
  122 + controller: ConfigBarComponent,
123 123 controllerAs: "vm"
124 124 }
125 125 }
... ...
src/languages/en.json
... ... @@ -6,6 +6,8 @@
6 6 "navbar.logout": "Log Out",
7 7 "navbar.login": "Login",
8 8 "navbar.toggle_menu": "Toggle navigation",
  9 + "configbar.label": "Configuration",
  10 + "configbar.section.layout": "Layout",
9 11 "language.all": "All languages",
10 12 "language.en": "English",
11 13 "language.pt": "Portuguese",
... ... @@ -77,9 +79,7 @@
77 79 "custom_content.title": "Edit content",
78 80 "profile.custom_header.label": "Header",
79 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 83 "search.results.summary": "{results, plural, one{result} other{# results}}",
84 84 "search.results.query.label": "Search therm:",
85 85 "search.label": "Search",
... ...
src/languages/pt.json
... ... @@ -6,6 +6,8 @@
6 6 "navbar.logout": "Sair",
7 7 "navbar.login": "Login",
8 8 "navbar.toggle_menu": "Abrir Menu",
  9 + "configbar.label": "Configurações",
  10 + "configbar.section.layout": "Visual",
9 11 "language.all": "Todos os idiomas",
10 12 "language.en": "Inglês",
11 13 "language.pt": "Português",
... ... @@ -77,9 +79,7 @@
77 79 "custom_content.title": "Editar conteúdo",
78 80 "profile.custom_header.label": "Cabeçalho",
79 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 83 "search.results.summary": "{results, plural, one{# resultado} other{# resultados}}",
84 84 "search.results.query.label": "Termo da busca:",
85 85 "search.label": "Pesquisar",
... ...