Commit b471f0f7838ae7feecfb5326e18e1173fa051921
1 parent
52d4df8e
Exists in
master
and in
4 other branches
put the image upload works minimally propely
Showing
11 changed files
with
115 additions
and
143 deletions
Show diff stats
src/app/layout/blocks/profile-image/profile-image-block.html
| 1 | <div class="center-block text-center profile-image-block"> | 1 | <div class="center-block text-center profile-image-block"> |
| 2 | <a ui-sref="main.profile.info({profile: ctrl.owner.identifier})"> | 2 | <a ui-sref="main.profile.info({profile: ctrl.owner.identifier})"> |
| 3 | <noosfero-profile-image [profile]="ctrl.owner" [editable]="true" [edit-class]="'profile-image-block-editable'"></noosfero-profile-image> | 3 | <noosfero-profile-image [profile]="ctrl.owner" [editable]="true" [edit-class]="'profile-image-block-editable'"></noosfero-profile-image> |
| 4 | - </a> | ||
| 5 | - <a class="settings-link" target="_self" ui-sref="main.profile.settings({profile: ctrl.owner.identifier})">{{"blocks.profile_image.control_panel" | translate}}</a> | 4 | + </a> |
| 6 | <div class="actions" ng-show="ctrl.isMember!=null"> | 5 | <div class="actions" ng-show="ctrl.isMember!=null"> |
| 7 | <div class="organization-actions" ng-if="ctrl.displayOrganizationActions()"> | 6 | <div class="organization-actions" ng-if="ctrl.displayOrganizationActions()"> |
| 8 | <a ng-if="!ctrl.isMember" ng-click="ctrl.join()" class="btn btn-primary btn-sm join" href="#">{{"blocks.profile_image.join" | translate}}</a> | 7 | <a ng-if="!ctrl.isMember" ng-click="ctrl.join()" class="btn btn-primary btn-sm join" href="#">{{"blocks.profile_image.join" | translate}}</a> |
src/app/layout/blocks/profile-image/profile-image-block.scss
| 1 | .profile-image-block { | 1 | .profile-image-block { |
| 2 | - .settings-link { | ||
| 3 | - display: block; | 2 | + .img-responsive { |
| 3 | + display: initial; | ||
| 4 | } | 4 | } |
| 5 | - .upload-camera-container { | ||
| 6 | - top: 77%; | ||
| 7 | - left: 6%; | ||
| 8 | - } | ||
| 9 | -} | ||
| 10 | - | ||
| 11 | -.profile-image-block-editable { | ||
| 12 | - top: 68%; | ||
| 13 | - width: 284px; | ||
| 14 | - font-weight: 700; | ||
| 15 | - height: 43px; | ||
| 16 | - padding-left: 30px; | ||
| 17 | - padding-top: 13px; | ||
| 18 | } | 5 | } |
| 19 | - | ||
| 20 | - | ||
| 21 | - | ||
| 22 | - | ||
| 23 | - |
src/app/profile/image/image.component.ts
| 1 | import { Inject, Input, Component, provide } from "ng-forward"; | 1 | import { Inject, Input, Component, provide } from "ng-forward"; |
| 2 | import { PersonService } from "../../../lib/ng-noosfero-api/http/person.service"; | 2 | import { PersonService } from "../../../lib/ng-noosfero-api/http/person.service"; |
| 3 | +import { PermissionService } from "../../shared/services/permission.service"; | ||
| 3 | import { ProfileImageEditorComponent } from "./profile-image-editor.component"; | 4 | import { ProfileImageEditorComponent } from "./profile-image-editor.component"; |
| 4 | 5 | ||
| 5 | /** | 6 | /** |
| @@ -13,7 +14,7 @@ import { ProfileImageEditorComponent } from "./profile-image-editor.component"; | @@ -13,7 +14,7 @@ import { ProfileImageEditorComponent } from "./profile-image-editor.component"; | ||
| 13 | templateUrl: 'app/profile/image/image.html', | 14 | templateUrl: 'app/profile/image/image.html', |
| 14 | providers: [provide('personService', { useClass: PersonService })] | 15 | providers: [provide('personService', { useClass: PersonService })] |
| 15 | }) | 16 | }) |
| 16 | -@Inject(PersonService, "$uibModal", "$scope") | 17 | +@Inject(PersonService, PermissionService, "$uibModal", "$scope") |
| 17 | export class ProfileImageComponent { | 18 | export class ProfileImageComponent { |
| 18 | 19 | ||
| 19 | /** | 20 | /** |
| @@ -41,7 +42,8 @@ export class ProfileImageComponent { | @@ -41,7 +42,8 @@ export class ProfileImageComponent { | ||
| 41 | croppedDataUrl: any; | 42 | croppedDataUrl: any; |
| 42 | modalInstance: any; | 43 | modalInstance: any; |
| 43 | 44 | ||
| 44 | - constructor(private personService: PersonService, private $uibModal: ng.ui.bootstrap.IModalService, private $scope: ng.IScope) { | 45 | + constructor(private personService: PersonService, private permissionService: PermissionService, private $uibModal: ng.ui.bootstrap.IModalService, private $scope: ng.IScope) { |
| 46 | + console.log('wwwwwwwwwwwwwwwwwwwwwwww', this.editable); | ||
| 45 | } | 47 | } |
| 46 | 48 | ||
| 47 | fileSelected(file: any, errFiles: any) { | 49 | fileSelected(file: any, errFiles: any) { |
| @@ -73,6 +75,10 @@ export class ProfileImageComponent { | @@ -73,6 +75,10 @@ export class ProfileImageComponent { | ||
| 73 | return this._showCamera; | 75 | return this._showCamera; |
| 74 | } | 76 | } |
| 75 | 77 | ||
| 78 | + isEditable() { | ||
| 79 | + return this.editable && this.permissionService.isAllowed(this.profile, 'allow_edit'); | ||
| 80 | + } | ||
| 81 | + | ||
| 76 | 82 | ||
| 77 | /** | 83 | /** |
| 78 | * @ngdoc method | 84 | * @ngdoc method |
src/app/profile/image/image.html
| 1 | -<div id="profile-image-container" style=""> | ||
| 2 | - <div class="profile-image-wrap" title="{{ctrl.profile.name}}" ng-mouseenter="ctrl.showChange(true)" ng-mouseleave="ctrl.showChange(false)"> | ||
| 3 | - <img ng-if="ctrl.profile.image" ng-src="{{ctrl.profile.image.url}}" class="img-responsive profile-image"> | ||
| 4 | - <i ng-if="!ctrl.profile.image" class="fa {{ctrl.defaultIcon}} fa-5x profile-image"></i> | ||
| 5 | - <div ng-if="ctrl.editable" class="upload-camera-container"> | ||
| 6 | - <i id="camera" class="fa fa-camera upload-camera" aria-hidden="true"></i> | ||
| 7 | - </div> | ||
| 8 | - <div ng-if="ctrl.editable" id="select-photo-container" name="select-photo-container" class="select-photo-container container" ng-class="ctrl.editClass"> | ||
| 9 | - <a id="upload-container" class="upload-container" href="#" rel="dialog" role="button"> | ||
| 10 | - <!-- The upload button hidden behind the camera --> | ||
| 11 | - <div class="upload-button" ngf-select="ctrl.fileSelected($file)" | ||
| 12 | - ngf-pattern="'image/*'" ngf-accept="'image/*'" | ||
| 13 | - ngf-max-size="20MB" ngf-resize="{width: 100, height: 100}" | ||
| 14 | - data-toggle="modal" data-target=".crop-dialog"> | ||
| 15 | - {{"profile.image.upload" | translate}} | ||
| 16 | - </div> | ||
| 17 | - </a> | ||
| 18 | - </div> | ||
| 19 | - | 1 | +<div ng-if="ctrl.isEditable()" id="profile-image-container"> |
| 2 | + <div class="profile-image-wrap" title="{{ctrl.profile.name}}" ng-mouseenter="ctrl.showChange(true)" ng-mouseleave="ctrl.showChange(false)"> | ||
| 3 | + <div class="hovereffect "> | ||
| 4 | + <i ng-if="!ctrl.profile.image" class="fa {{ctrl.defaultIcon}} fa-5x profile-image"></i> | ||
| 5 | + <img ng-if="ctrl.profile.image" ng-src="{{ctrl.profile.image.url}}" class="img-responsive profile-image"> | ||
| 6 | + <div class='container-camera'> | ||
| 7 | + <a ngf-select="ctrl.fileSelected($file)" | ||
| 8 | + ngf-pattern="'image/*'" ngf-accept="'image/*'" | ||
| 9 | + ngf-max-size="20MB" | ||
| 10 | + data-toggle="modal" data-target=".crop-dialog" href="#"><i class="fa fa-camera upload-camera" ></i> | ||
| 11 | + </a> | ||
| 12 | + </div> | ||
| 13 | + <div class="overlay"></div> | ||
| 20 | </div> | 14 | </div> |
| 15 | + </div> | ||
| 21 | </div> | 16 | </div> |
| 17 | +<span ng-if="!ctrl.isEditable()" class="profile-image-wrap" title="{{ctrl.profile.name}}"> | ||
| 18 | + <img ng-if="ctrl.profile.image" ng-src="{{ctrl.profile.image.url}}" class="img-responsive profile-image"> | ||
| 19 | + <i ng-if="!ctrl.profile.image" class="fa {{ctrl.defaultIcon}} fa-5x profile-image"></i> | ||
| 20 | +</span> |
src/app/profile/image/image.scss
| 1 | -i.profile-image { | ||
| 2 | - color: rgb(44, 62, 80); | ||
| 3 | - | ||
| 4 | - border-radius: 50%; | ||
| 5 | - background-clip: padding-box; | ||
| 6 | - margin-bottom: 15px; | ||
| 7 | -} | ||
| 8 | - | ||
| 9 | -.profile-image-wrap { | ||
| 10 | - display: inline; | ||
| 11 | -} | ||
| 12 | - | ||
| 13 | -#profile-image-container { | ||
| 14 | - display: inline; | ||
| 15 | -} | ||
| 16 | - | ||
| 17 | -#profile-image-container:hover { | ||
| 18 | - .select-photo-container { | ||
| 19 | - z-index: 1; | 1 | +.hovereffect { |
| 2 | + width:100%; | ||
| 3 | + height:100%; | ||
| 4 | + float:left; | ||
| 5 | + overflow:hidden; | ||
| 6 | + position:relative; | ||
| 7 | + text-align:center; | ||
| 8 | + cursor:default; | ||
| 9 | + .container-camera { | ||
| 10 | + position: relative; | ||
| 11 | + z-index: 2; | ||
| 12 | + .upload-camera{ | ||
| 13 | + right: 0px; | ||
| 14 | + left: 0px; | ||
| 15 | + position: absolute; | ||
| 16 | + font-size: 1.5em; | ||
| 17 | + bottom: 2px; | ||
| 18 | + text-shadow: 0px 0px 3px black; | ||
| 19 | + color: white; | ||
| 20 | + padding-top: 5px; | ||
| 21 | + &:hover{ | ||
| 22 | + font-size: 1.5em; | ||
| 23 | + background-color: rgba(0, 0, 0, 0.50); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + } | ||
| 27 | + } | ||
| 28 | + .overlay { | ||
| 29 | + width:100%; | ||
| 30 | + height:100%; | ||
| 31 | + position:absolute; | ||
| 32 | + overflow:hidden; | ||
| 33 | + top:0; | ||
| 34 | + left:0; | ||
| 35 | + opacity:0; | ||
| 36 | + background-color:rgba(0,0,0,0.5); | ||
| 37 | + -webkit-transition:all .4s ease-in-out; | ||
| 38 | + transition:all .4s ease-in-out; | ||
| 39 | + z-index: 1; | ||
| 40 | + } | ||
| 41 | + img { | ||
| 42 | + display:block; | ||
| 43 | + position:relative; | ||
| 44 | + -webkit-transition:all .4s linear; | ||
| 45 | + transition:all .4s linear; | ||
| 46 | + width: 100%; | ||
| 47 | + } | ||
| 48 | + &:hover { | ||
| 49 | + img { | ||
| 50 | + -ms-transform:scale(1.2); | ||
| 51 | + -webkit-transform:scale(1.2); | ||
| 52 | + transform:scale(1.2); | ||
| 20 | } | 53 | } |
| 21 | - .upload-camera-container { | ||
| 22 | - transform: scale(.75); | 54 | + .overlay { |
| 55 | + opacity:1; | ||
| 56 | + filter:alpha(opacity=100); | ||
| 23 | } | 57 | } |
| 24 | -} | ||
| 25 | - | ||
| 26 | -.upload-camera-container { | ||
| 27 | - text-align: left; | ||
| 28 | - position: absolute; | ||
| 29 | - z-index: 5; | ||
| 30 | -} | ||
| 31 | - | ||
| 32 | -.upload-camera { | ||
| 33 | - color: white; | ||
| 34 | - position: absolute; | ||
| 35 | - transition: all .3s cubic-bezier(.175, .885, .32, 1.275); | ||
| 36 | - opacity: 1; | ||
| 37 | -} | ||
| 38 | - | ||
| 39 | -.select-photo-container { | ||
| 40 | - position: absolute; | ||
| 41 | - z-index: -1; | ||
| 42 | - background: #000; | ||
| 43 | - background: rgba(0, 0, 0, .6); | ||
| 44 | - background: linear-gradient(transparent, rgba(0, 0, 0, .6) 70%, rgba(0, 0, 0, .6) 100%); | ||
| 45 | - transition: top .13s ease-out; | ||
| 46 | -} | ||
| 47 | - | ||
| 48 | -#upload-container { | ||
| 49 | - position: relative; | ||
| 50 | - text-decoration: none; | ||
| 51 | -} | ||
| 52 | - | ||
| 53 | -.upload-container a:hover { | ||
| 54 | - text-decoration: none; | ||
| 55 | -} | ||
| 56 | - | ||
| 57 | -.upload-button { | ||
| 58 | - -webkit-font-smoothing: antialiased; | ||
| 59 | - color: #fff; | ||
| 60 | -} | ||
| 61 | - | ||
| 62 | -.upload-container { | ||
| 63 | - color:#fff; | ||
| 64 | - display: block; | ||
| 65 | - overflow: hidden; | ||
| 66 | - position: relative; | ||
| 67 | - text-align: left; | ||
| 68 | - min-width: 89px; | ||
| 69 | -} | ||
| 70 | - | ||
| 71 | -.cropArea { | ||
| 72 | - background: #E4E4E4; | ||
| 73 | - overflow: hidden; | ||
| 74 | - width:300px; | ||
| 75 | - height:150px; | ||
| 76 | -} | ||
| 77 | - | ||
| 78 | -.crop-area { | ||
| 79 | - display: none; | ||
| 80 | -} | ||
| 81 | - | ||
| 82 | -form .progress { | ||
| 83 | - line-height: 15px; | ||
| 84 | -} | ||
| 85 | - | ||
| 86 | -.progress { | ||
| 87 | - display: inline-block; | ||
| 88 | - width: 100px; | ||
| 89 | - border: 3px groove #CCC; | ||
| 90 | -} | ||
| 91 | -.progress div { | ||
| 92 | - font-size: smaller; | ||
| 93 | - background: orange; | ||
| 94 | - width: 0; | 58 | + } |
| 95 | } | 59 | } |
src/app/profile/image/profile-image-editor.component.ts
| @@ -4,7 +4,6 @@ import { PersonService } from "../../../lib/ng-noosfero-api/http/person.service" | @@ -4,7 +4,6 @@ import { PersonService } from "../../../lib/ng-noosfero-api/http/person.service" | ||
| 4 | 4 | ||
| 5 | export class ProfileImageEditorComponent { | 5 | export class ProfileImageEditorComponent { |
| 6 | 6 | ||
| 7 | - activities: any; | ||
| 8 | croppedDataUrl: string; | 7 | croppedDataUrl: string; |
| 9 | static $inject = ["picFile", "profile", "personService", "$uibModalInstance"]; | 8 | static $inject = ["picFile", "profile", "personService", "$uibModalInstance"]; |
| 10 | 9 |
src/app/profile/image/profile-image-editor.html
| @@ -3,18 +3,14 @@ | @@ -3,18 +3,14 @@ | ||
| 3 | </div> | 3 | </div> |
| 4 | <div class="modal-body"> | 4 | <div class="modal-body"> |
| 5 | <form class=""> | 5 | <form class=""> |
| 6 | - <div ngf-drop ng-model="ctrl.picFile" ngf-pattern="image/*" class="cropArea"> | 6 | + <div ngf-drop ng-model="ctrl.picFile" ngf-pattern="image/*" class="crop-area"> |
| 7 | <img-crop image="ctrl.picFile | ngfDataUrl" area-type="square" | 7 | <img-crop image="ctrl.picFile | ngfDataUrl" area-type="square" |
| 8 | result-image="ctrl.croppedDataUrl" ng-init="ctrl.croppedDataUrl=''"> | 8 | result-image="ctrl.croppedDataUrl" ng-init="ctrl.croppedDataUrl=''"> |
| 9 | </img-crop> | 9 | </img-crop> |
| 10 | </div> | 10 | </div> |
| 11 | - <div> | 11 | + <div class='cropped-image'> |
| 12 | <img ng-src="{{ctrl.croppedDataUrl}}" /> | 12 | <img ng-src="{{ctrl.croppedDataUrl}}" /> |
| 13 | - </div> | ||
| 14 | - <span class="progress" ng-show="progress >= 0"> | ||
| 15 | - <div style="width: {{progress" ng-bind="progress + '%'"></div> | ||
| 16 | - </span> <span ng-show="ctrl.result">Upload Successful</span> <span class="err" | ||
| 17 | - ng-show="ctrl.errorMsg">{{errorMsg}}</span> | 13 | + </div> |
| 18 | </form> | 14 | </form> |
| 19 | 15 | ||
| 20 | <div class="actions"> | 16 | <div class="actions"> |
| @@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
| 1 | +import {Injectable, Inject} from "ng-forward"; | ||
| 2 | + | ||
| 3 | +type WithPermissions = noosfero.Profile | noosfero.Comment | noosfero.Article; | ||
| 4 | + | ||
| 5 | +@Injectable() | ||
| 6 | +export class PermissionService { | ||
| 7 | + isAllowed(target: WithPermissions, permission: string) { | ||
| 8 | + return target.permissions.indexOf(permission) >= 0; | ||
| 9 | + } | ||
| 10 | + | ||
| 11 | +} |
src/lib/ng-noosfero-api/interfaces/article.ts
| @@ -8,6 +8,8 @@ namespace noosfero { | @@ -8,6 +8,8 @@ namespace noosfero { | ||
| 8 | parent: Article; | 8 | parent: Article; |
| 9 | body: string; | 9 | body: string; |
| 10 | title: string; | 10 | title: string; |
| 11 | + | ||
| 12 | + | ||
| 11 | name: string; | 13 | name: string; |
| 12 | published: boolean; | 14 | published: boolean; |
| 13 | setting: any; | 15 | setting: any; |
src/lib/ng-noosfero-api/interfaces/comment.ts
| @@ -5,6 +5,7 @@ namespace noosfero { | @@ -5,6 +5,7 @@ namespace noosfero { | ||
| 5 | reply_of: Comment; | 5 | reply_of: Comment; |
| 6 | replies: Comment[]; | 6 | replies: Comment[]; |
| 7 | body: string; | 7 | body: string; |
| 8 | + permissions: string[]; | ||
| 8 | } | 9 | } |
| 9 | 10 | ||
| 10 | export interface CommentViewModel extends Comment { | 11 | export interface CommentViewModel extends Comment { |