Commit c2abd5b3c556a651216f070ba6696c23f33d383c
1 parent
c1e0c406
Exists in
master
and in
30 other branches
Completed initial two columns profile-info. Needs create a unit test for new profile-data component
Showing
13 changed files
with
216 additions
and
49 deletions
Show diff stats
src/app/index.scss
| ... | ... | @@ -24,12 +24,19 @@ $main-bg-color: #e7ebee; |
| 24 | 24 | $primary-color: #03a9f4; |
| 25 | 25 | $primary-color-dark: #0288d1; |
| 26 | 26 | |
| 27 | +//OTHER COLORS | |
| 28 | +$default-bg-hover-color: #f8f8f8; | |
| 29 | +$red-color: #e84e40; | |
| 30 | +$red-color-dark: #dd191d; | |
| 31 | + | |
| 27 | 32 | //GRID - media queries breakpoints |
| 28 | 33 | $break-xxs-min: 420px; |
| 29 | 34 | $break-xs-min: 768px; |
| 30 | 35 | |
| 31 | 36 | $break-xxs-max: ($break-xxs-min - 1); |
| 32 | 37 | $break-xs-max: ($break-xs-min - 1); |
| 38 | + | |
| 39 | + | |
| 33 | 40 | @import "../../bower_components/bootswatch/flatly/_variables.scss"; |
| 34 | 41 | |
| 35 | 42 | /** |
| ... | ... | @@ -68,4 +75,5 @@ h1, h2, h3, h4, h5 { |
| 68 | 75 | @import "../../bower_components/bootswatch/flatly/_bootswatch.scss"; |
| 69 | 76 | @import "layout/scss/mixins"; |
| 70 | 77 | @import "layout/scss/bootstrap-overrides"; |
| 71 | -@import "layout/scss/layout" | |
| 78 | +@import "layout/scss/layout"; | |
| 79 | +@import "layout/scss/tables"; | ... | ... |
src/app/layout/scss/_bootstrap-overrides.scss
| 1 | -/* MAINBOX */ | |
| 2 | -.main-box { | |
| 3 | - border: 1px solid #e7ebee; | |
| 4 | - box-shadow: 0px 1px 1px rgba(0,0,0,0.1); | |
| 5 | - margin-bottom: 16px; | |
| 6 | - /* overflow: hidden; */ | |
| 7 | - @include border-radius($border-radius-base); | |
| 8 | - | |
| 9 | - @media (max-width: $break-xs-max) { | |
| 10 | - margin-bottom: 10px; | |
| 11 | - } | |
| 12 | - | |
| 13 | - h2 { | |
| 14 | - font-size: 1.3em; | |
| 15 | - line-height: 29px; | |
| 16 | - margin: 0; | |
| 17 | - padding: 0; | |
| 18 | - | |
| 19 | - @media (max-width: $break-xxs-max) { | |
| 20 | - margin-bottom: 5px; | |
| 21 | - } | |
| 22 | - } | |
| 23 | - &.no-header { | |
| 24 | - padding-top: 20px; | |
| 25 | - } | |
| 26 | - .main-box-header { | |
| 27 | - min-height: 50px; | |
| 28 | - padding: 10px 20px; | |
| 29 | - | |
| 30 | - &.with-border { | |
| 31 | - border-bottom: 1px solid #ecf0f1; | |
| 32 | - } | |
| 33 | - } | |
| 34 | - .main-box-body { | |
| 35 | - padding: 0 20px 20px 20px; | |
| 36 | - } | |
| 37 | -} | |
| 38 | - | |
| 39 | 1 | /* TABS */ |
| 40 | 2 | .nav-tabs { |
| 41 | 3 | background: #f9f9f9; | ... | ... |
src/app/layout/scss/_layout.scss
| ... | ... | @@ -0,0 +1,103 @@ |
| 1 | +/* TABLES */ | |
| 2 | +.table-hover > tbody > tr:hover > td, | |
| 3 | +.table-hover > tbody > tr:hover > th { | |
| 4 | + background-color: $default-bg-hover-color; | |
| 5 | +} | |
| 6 | +.table { | |
| 7 | + thead > tr { | |
| 8 | + > th { | |
| 9 | + border-bottom: 2px solid $main-bg-color; | |
| 10 | + text-transform: uppercase; | |
| 11 | + font-size: 0.875em; | |
| 12 | + | |
| 13 | + > a span { | |
| 14 | + color: $text-color; | |
| 15 | + } | |
| 16 | + } | |
| 17 | + } | |
| 18 | + tbody > tr { | |
| 19 | + > td { | |
| 20 | + font-size: 0.875em; | |
| 21 | + vertical-align: middle; | |
| 22 | + border-top: 1px solid $main-bg-color; | |
| 23 | + padding: 12px 8px; | |
| 24 | + | |
| 25 | + &:first-child { | |
| 26 | + font-size: 1.125em; | |
| 27 | + font-weight: bold; | |
| 28 | + } | |
| 29 | + } | |
| 30 | + td { | |
| 31 | + .call-type { | |
| 32 | + display: block; | |
| 33 | + font-size: 0.75em; | |
| 34 | + text-align: center; | |
| 35 | + } | |
| 36 | + .first-line { | |
| 37 | + line-height: 1.5; | |
| 38 | + font-weight: 400; | |
| 39 | + font-size: 1.125em; | |
| 40 | + | |
| 41 | + span { | |
| 42 | + font-size: 0.875em; | |
| 43 | + color: #969696; | |
| 44 | + font-weight: 300; | |
| 45 | + } | |
| 46 | + } | |
| 47 | + .second-line { | |
| 48 | + font-size: 0.875em; | |
| 49 | + line-height: 1.2; | |
| 50 | + } | |
| 51 | + } | |
| 52 | + &.table-line-fb > td { | |
| 53 | + background-color: #9daccb; | |
| 54 | + color: #262525; | |
| 55 | + } | |
| 56 | + &.table-line-twitter > td { | |
| 57 | + background-color: #9fccff; | |
| 58 | + color: #262525; | |
| 59 | + } | |
| 60 | + &.table-line-plus > td { | |
| 61 | + background-color: #eea59c; | |
| 62 | + color: #262525; | |
| 63 | + } | |
| 64 | + } | |
| 65 | + | |
| 66 | + a { | |
| 67 | + &.table-link { | |
| 68 | + margin: 0 5px; | |
| 69 | + font-size: 1.125em; | |
| 70 | + | |
| 71 | + &:hover { | |
| 72 | + text-decoration: none; | |
| 73 | + color: #2980b9; | |
| 74 | + } | |
| 75 | + &.danger { | |
| 76 | + color: $red-color; | |
| 77 | + | |
| 78 | + &:hover { | |
| 79 | + color: $red-color-dark; | |
| 80 | + } | |
| 81 | + } | |
| 82 | + } | |
| 83 | + } | |
| 84 | + | |
| 85 | + &.table-condensed { | |
| 86 | + tbody > tr { | |
| 87 | + > td { | |
| 88 | + padding: 8px 5px; | |
| 89 | + } | |
| 90 | + } | |
| 91 | + } | |
| 92 | +} | |
| 93 | + | |
| 94 | +.table-striped { | |
| 95 | + tbody > tr { | |
| 96 | + > td { | |
| 97 | + width: 50%; | |
| 98 | + background: none; | |
| 99 | + border: none; | |
| 100 | + border-bottom: 1px solid #ebebeb; | |
| 101 | + } | |
| 102 | + } | |
| 103 | +} | ... | ... |
| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | +import {StateConfig, Component, Inject, Input, provide} from 'ng-forward'; | |
| 2 | +import {ProfileService} from "../../../lib/ng-noosfero-api/http/profile.service"; | |
| 3 | +import {TranslateProfile} from "../../shared/pipes/translate-profile.filter"; | |
| 4 | + | |
| 5 | +@Component({ | |
| 6 | + selector: 'profile-data', | |
| 7 | + templateUrl: "app/profile/data/profile-data.html", | |
| 8 | + pipes: [TranslateProfile] | |
| 9 | +}) | |
| 10 | +export class ProfileDataComponent { | |
| 11 | + | |
| 12 | + @Input() | |
| 13 | + profile: noosfero.Profile; | |
| 14 | + | |
| 15 | +} | ... | ... |
| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | +<!-- Basic data --> | |
| 2 | +<div class="main-box clearfix"> | |
| 3 | + <header class="main-box-header clearfix"> | |
| 4 | + <h2>{{"profile.basic_info" | translate}}</h2> | |
| 5 | + </header> | |
| 6 | + <div class="main-box-body clearfix"> | |
| 7 | + <div class="table-responsive"> | |
| 8 | + <table class="table table-striped table-hover"> | |
| 9 | + <tbody> | |
| 10 | + <tr> | |
| 11 | + <td> | |
| 12 | + {{"profile.type" | translate}} | |
| 13 | + </td> | |
| 14 | + <td> | |
| 15 | + <span class="label" ng-class="{'label-danger': ctrl.profile.type == 'Community', 'label-info': ctrl.profile.type == 'Person'}">{{ctrl.profile | translateProfile}}</span> | |
| 16 | + </td> | |
| 17 | + </tr> | |
| 18 | + </tbody> | |
| 19 | + </table> | |
| 20 | + </div> | |
| 21 | + </div> | |
| 22 | +</div> | |
| 23 | + | |
| 24 | +<!-- Custom Fields --> | |
| 25 | +<div class="main-box clearfix"> | |
| 26 | + <header class="main-box-header clearfix"> | |
| 27 | + <h2>{{"profile.others_info" | translate}}</h2> | |
| 28 | + </header> | |
| 29 | + <div class="main-box-body clearfix"> | |
| 30 | + <div class="table-responsive"> | |
| 31 | + <table class="table table-striped table-hover"> | |
| 32 | + <tbody> | |
| 33 | + <tr ng-repeat="(field, value) in ctrl.profile.additional_data"> | |
| 34 | + <td> | |
| 35 | + {{ field }} | |
| 36 | + </td> | |
| 37 | + <td> | |
| 38 | + {{ value }} | |
| 39 | + </td> | |
| 40 | + </tr> | |
| 41 | + </tbody> | |
| 42 | + </table> | |
| 43 | + </div> | |
| 44 | + </div> | |
| 45 | +</div> | ... | ... |
src/app/profile/info/profile-info.component.spec.ts
| ... | ... | @@ -8,6 +8,7 @@ describe("Components", () => { |
| 8 | 8 | let $q: ng.IQService; |
| 9 | 9 | let profileServiceMock: any; |
| 10 | 10 | let $stateParams: any; |
| 11 | + let amDateFormatMock: any; | |
| 11 | 12 | |
| 12 | 13 | beforeEach(inject((_$rootScope_: ng.IRootScopeService, _$q_: ng.IQService) => { |
| 13 | 14 | $rootScope = _$rootScope_; |
| ... | ... | @@ -17,6 +18,7 @@ describe("Components", () => { |
| 17 | 18 | beforeEach(() => { |
| 18 | 19 | $stateParams = jasmine.createSpyObj("$stateParams", ["profile"]); |
| 19 | 20 | profileServiceMock = jasmine.createSpyObj("profileServiceMock", ["getCurrentProfile", "getActivities"]); |
| 21 | + amDateFormatMock = jasmine.createSpyObj("amDateFormatMock", ["transform"]); | |
| 20 | 22 | |
| 21 | 23 | let getCurrentProfileResponse = $q.defer(); |
| 22 | 24 | getCurrentProfileResponse.resolve({ id: 1 }); |
| ... | ... | @@ -29,7 +31,7 @@ describe("Components", () => { |
| 29 | 31 | }); |
| 30 | 32 | |
| 31 | 33 | it("get the profile activities", done => { |
| 32 | - let component: ProfileInfoComponent = new ProfileInfoComponent(profileServiceMock); | |
| 34 | + let component: ProfileInfoComponent = new ProfileInfoComponent(profileServiceMock, amDateFormatMock); | |
| 33 | 35 | $rootScope.$apply(); |
| 34 | 36 | expect(profileServiceMock.getCurrentProfile).toHaveBeenCalled(); |
| 35 | 37 | expect(profileServiceMock.getActivities).toHaveBeenCalled(); | ... | ... |
src/app/profile/info/profile-info.component.ts
| 1 | 1 | import {StateConfig, Component, Inject, provide} from 'ng-forward'; |
| 2 | 2 | import {ProfileService} from "../../../lib/ng-noosfero-api/http/profile.service"; |
| 3 | +import {ProfileDataComponent} from "../data/profile-data.component"; | |
| 4 | +import {TranslateProfile} from "../../shared/pipes/translate-profile.filter"; | |
| 3 | 5 | |
| 4 | 6 | @Component({ |
| 5 | 7 | selector: 'profile', |
| 6 | 8 | templateUrl: "app/profile/info/profile-info.html", |
| 7 | - providers: [provide('profileService', { useClass: ProfileService })] | |
| 9 | + providers: [provide('profileService', { useClass: ProfileService })], | |
| 10 | + directives: [ProfileDataComponent], | |
| 11 | + pipes: [TranslateProfile] | |
| 8 | 12 | }) |
| 9 | 13 | @Inject(ProfileService) |
| 10 | 14 | @Inject("amDateFormatFilter") |
| ... | ... | @@ -14,10 +18,10 @@ export class ProfileInfoComponent { |
| 14 | 18 | profile: noosfero.Profile; |
| 15 | 19 | |
| 16 | 20 | constructor(private profileService: ProfileService, private amDateFormatFilter: any) { |
| 17 | - this.activate(); | |
| 21 | + this.init(); | |
| 18 | 22 | } |
| 19 | 23 | |
| 20 | - activate() { | |
| 24 | + init() { | |
| 21 | 25 | this.profileService.getCurrentProfile().then((profile: noosfero.Profile) => { |
| 22 | 26 | this.profile = profile; |
| 23 | 27 | return this.profileService.getActivities(<number>this.profile.id); | ... | ... |
src/app/profile/info/profile-info.html
| ... | ... | @@ -5,8 +5,9 @@ |
| 5 | 5 | <header class="main-box-header clearfix"> |
| 6 | 6 | <h2>{{vm.profile.name}}</h2> |
| 7 | 7 | </header> |
| 8 | - <div class="main-box-body clearfix"> | |
| 8 | + <div id="profile-left" class="main-box-body clearfix"> | |
| 9 | 9 | <noosfero-profile-image [profile]="vm.profile" class="img-responsive center-block"></noosfero-profile-image> |
| 10 | + <span class="label" ng-class="{'label-danger': vm.profile.type == 'Community', 'label-info': vm.profile.type == 'Person'}">{{vm.profile | translateProfile}}</span> | |
| 10 | 11 | <div class="profile-since"> |
| 11 | 12 | {{"profile.member_since" | translate}}: {{vm.profile.created_at | amDateFormat:'MMMM YYYY'}} |
| 12 | 13 | </div> |
| ... | ... | @@ -21,7 +22,7 @@ |
| 21 | 22 | <noosfero-activities [activities]="vm.activities"></noosfero-activities> |
| 22 | 23 | </uib-tab> |
| 23 | 24 | <uib-tab index="0" heading="{{ 'profile.about' | translate }}"> |
| 24 | - <!-- Profile data here --> | |
| 25 | + <profile-data [profile]="vm.profile"></profile-data> | |
| 25 | 26 | </uib-tab> |
| 26 | 27 | </uib-tabset> |
| 27 | 28 | </div> | ... | ... |
src/app/profile/profile.scss
| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | +import {Pipe, Inject} from "ng-forward"; | |
| 2 | + | |
| 3 | +@Pipe("translateProfile") | |
| 4 | +@Inject("translateFilter") | |
| 5 | +export class TranslateProfile { | |
| 6 | + | |
| 7 | + constructor(private translateFilter: any) { } | |
| 8 | + | |
| 9 | + transform(profile: noosfero.Profile, options: any) { | |
| 10 | + | |
| 11 | + return this.translateFilter("profile." + profile.type.toLowerCase() + ".title"); | |
| 12 | + } | |
| 13 | + | |
| 14 | +} | ... | ... |
src/languages/en.json
| ... | ... | @@ -10,7 +10,12 @@ |
| 10 | 10 | "language.pt": "Portuguese", |
| 11 | 11 | "language.selector": "Language", |
| 12 | 12 | "profile.member_since": "Member since", |
| 13 | - "profile.about": "About me", | |
| 13 | + "profile.type": "Tipo", | |
| 14 | + "profile.about": "About", | |
| 15 | + "profile.basic_info": "Basic Information", | |
| 16 | + "profile.others_info": "Others", | |
| 17 | + "profile.community.title": "Community", | |
| 18 | + "profile.person.title": "Person", | |
| 14 | 19 | "activities.title": "Activities", |
| 15 | 20 | "activities.create_article.description": "has published on", |
| 16 | 21 | "activities.add_member_in_community.description": "has joined the community", | ... | ... |
src/languages/pt.json
| ... | ... | @@ -9,9 +9,13 @@ |
| 9 | 9 | "language.en": "Inglês", |
| 10 | 10 | "language.pt": "Português", |
| 11 | 11 | "language.selector": "Idioma", |
| 12 | - "profile.wall": "Mural do Perfil", | |
| 13 | 12 | "profile.member_since": "Membro desde", |
| 14 | - "profile.about": "Meus dados", | |
| 13 | + "profile.type": "Tipo", | |
| 14 | + "profile.about": "Sobre", | |
| 15 | + "profile.basic_info": "Dados básicos", | |
| 16 | + "profile.others_info": "Outras informações", | |
| 17 | + "profile.community.title": "Comunidade", | |
| 18 | + "profile.person.title": "Pessoa", | |
| 15 | 19 | "activities.title": "Atividades", |
| 16 | 20 | "activities.create_article.description": "publicou em", |
| 17 | 21 | "activities.add_member_in_community.description": "entrou na comunidade", | ... | ... |