FIX: profile picture wasn't properly updating
This commit is contained in:
parent
5084e2bdf1
commit
11bf7da63c
|
@ -455,7 +455,7 @@
|
|||
{{#unless anonymizeForbidden}}
|
||||
{{d-button label="admin.user.anonymize"
|
||||
icon="exclamation-triangle"
|
||||
class="btn btn-danger"
|
||||
class="btn-danger"
|
||||
disabled=anonymizeForbidden
|
||||
action="anonymize"}}
|
||||
{{/unless}}
|
||||
|
@ -463,7 +463,7 @@
|
|||
{{#unless deleteForbidden}}
|
||||
{{d-button label="admin.user.delete"
|
||||
icon="exclamation-triangle"
|
||||
class="btn btn-danger"
|
||||
class="btn-danger"
|
||||
disabled=deleteForbidden
|
||||
action="destroy"}}
|
||||
{{/unless}}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import UploadMixin from 'discourse/mixins/upload';
|
||||
|
||||
export default Em.Component.extend(UploadMixin, {
|
||||
type: 'avatar',
|
||||
tagName: 'span',
|
||||
imageIsNotASquare: false,
|
||||
type: 'avatar',
|
||||
|
||||
uploadUrl: Discourse.computed.url('username', '/users/%@/preferences/user_image'),
|
||||
|
||||
uploadButtonText: function() {
|
||||
return this.get("uploading") ? I18n.t("uploading") : I18n.t("user.change_avatar.upload_picture");
|
||||
return this.get("uploading") ?
|
||||
I18n.t("uploading") :
|
||||
I18n.t("user.change_avatar.upload_picture");
|
||||
}.property("uploading"),
|
||||
|
||||
uploadDone: function(data) {
|
||||
var self = this;
|
||||
|
||||
uploadDone(data) {
|
||||
// display a warning whenever the image is not a square
|
||||
this.set("imageIsNotASquare", data.result.width !== data.result.height);
|
||||
|
||||
|
@ -21,13 +21,13 @@ export default Em.Component.extend(UploadMixin, {
|
|||
// indeed, the server gives us back the url to the file we've just uploaded
|
||||
// often, this file is not a square, so we need to crop it properly
|
||||
// this will also capture the first frame of animated avatars when they're not allowed
|
||||
Discourse.Utilities.cropAvatar(data.result.url, data.files[0].type).then(function(avatarTemplate) {
|
||||
self.set("uploadedAvatarTemplate", avatarTemplate);
|
||||
Discourse.Utilities.cropAvatar(data.result.url, data.files[0].type).then(avatarTemplate => {
|
||||
this.set("uploadedAvatarTemplate", avatarTemplate);
|
||||
|
||||
// indicates the users is using an uploaded avatar (must happen after cropping, otherwise
|
||||
// we will attempt to load an invalid avatar and cache a redirect to old one, uploadedAvatarTemplate
|
||||
// trumps over custom avatar upload id)
|
||||
self.set("custom_avatar_upload_id", data.result.upload_id);
|
||||
this.set("custom_avatar_upload_id", data.result.upload_id);
|
||||
});
|
||||
|
||||
// the upload is now done
|
||||
|
|
|
@ -32,5 +32,6 @@ export default Ember.Component.extend({
|
|||
|
||||
click() {
|
||||
this.sendAction("action", this.get("actionParam"));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2,8 +2,10 @@ import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
|||
import DiscourseController from 'discourse/controllers/controller';
|
||||
|
||||
export default DiscourseController.extend(ModalFunctionality, {
|
||||
uploadedAvatarTemplate: null,
|
||||
hasUploadedAvatar: Em.computed.or('uploadedAvatarTemplate', 'custom_avatar_upload_id'),
|
||||
|
||||
selectedUploadId: function(){
|
||||
selectedUploadId: function() {
|
||||
switch (this.get("selected")) {
|
||||
case "system": return this.get("system_avatar_upload_id");
|
||||
case "gravatar": return this.get("gravatar_avatar_upload_id");
|
||||
|
@ -12,18 +14,16 @@ export default DiscourseController.extend(ModalFunctionality, {
|
|||
}.property('selected', 'system_avatar_upload_id', 'gravatar_avatar_upload_id', 'custom_avatar_upload_id'),
|
||||
|
||||
actions: {
|
||||
useUploadedAvatar: function() { this.set("selected", "uploaded"); },
|
||||
useGravatar: function() { this.set("selected", "gravatar"); },
|
||||
useSystem: function() { this.set("selected", "system"); },
|
||||
refreshGravatar: function() {
|
||||
var self = this;
|
||||
self.set("gravatarRefreshDisabled", true);
|
||||
Discourse
|
||||
.ajax("/user_avatar/" + this.get("username") + "/refresh_gravatar", {method: 'POST'})
|
||||
.then(function(result){
|
||||
self.set("gravatarRefreshDisabled", false);
|
||||
self.set("gravatar_avatar_upload_id", result.upload_id);
|
||||
});
|
||||
useUploadedAvatar() { this.set("selected", "uploaded"); },
|
||||
useGravatar() { this.set("selected", "gravatar"); },
|
||||
useSystem() { this.set("selected", "system"); },
|
||||
|
||||
refreshGravatar() {
|
||||
this.set("gravatarRefreshDisabled", true);
|
||||
return Discourse
|
||||
.ajax("/user_avatar/" + this.get("username") + "/refresh_gravatar.json", { method: 'POST' })
|
||||
.then(result => this.set("gravatar_avatar_upload_id", result.upload_id))
|
||||
.finally(() => this.set("gravatarRefreshDisabled", false));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export default function showModal(name, model) {
|
||||
export default (name, model) => {
|
||||
// We use the container here because modals are like singletons
|
||||
// in Discourse. Only one can be shown with a particular state.
|
||||
const route = Discourse.__container__.lookup('route:application');
|
||||
|
@ -12,5 +12,4 @@ export default function showModal(name, model) {
|
|||
if (controller.onShow) { controller.onShow(); }
|
||||
controller.set('flashMessage', null);
|
||||
}
|
||||
return controller;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
export default Em.Mixin.create({
|
||||
actions: {
|
||||
didTransition: function() {
|
||||
var self = this;
|
||||
Em.run.schedule("afterRender", function() {
|
||||
self.controllerFor("application").set("showFooter", true);
|
||||
didTransition() {
|
||||
Em.run.schedule("afterRender", () => {
|
||||
this.controllerFor("application").set("showFooter", true);
|
||||
});
|
||||
return true;
|
||||
},
|
||||
|
||||
willTransition: function() {
|
||||
willTransition() {
|
||||
this.controllerFor("application").set("showFooter", false);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,10 @@ export default RestrictedUserRoute.extend(ShowFooter, {
|
|||
},
|
||||
|
||||
setupController(controller, user) {
|
||||
controller.setProperties({ model: user, newNameInput: user.get('name') });
|
||||
controller.setProperties({
|
||||
model: user,
|
||||
newNameInput: user.get('name')
|
||||
});
|
||||
},
|
||||
|
||||
actions: {
|
||||
|
@ -16,15 +19,15 @@ export default RestrictedUserRoute.extend(ShowFooter, {
|
|||
showModal('avatar-selector');
|
||||
|
||||
// all the properties needed for displaying the avatar selector modal
|
||||
const controller = this.controllerFor('avatar-selector');
|
||||
const user = this.modelFor('user');
|
||||
const props = user.getProperties(
|
||||
'username', 'email',
|
||||
'uploaded_avatar_id',
|
||||
'system_avatar_upload_id',
|
||||
'gravatar_avatar_upload_id',
|
||||
'custom_avatar_upload_id'
|
||||
);
|
||||
const controller = this.controllerFor('avatar-selector'),
|
||||
props = this.modelFor('user').getProperties(
|
||||
'email',
|
||||
'username',
|
||||
'uploaded_avatar_id',
|
||||
'system_avatar_upload_id',
|
||||
'gravatar_avatar_upload_id',
|
||||
'custom_avatar_upload_id'
|
||||
);
|
||||
|
||||
switch (props.uploaded_avatar_id) {
|
||||
case props.system_avatar_upload_id:
|
||||
|
@ -40,20 +43,20 @@ export default RestrictedUserRoute.extend(ShowFooter, {
|
|||
controller.setProperties(props);
|
||||
},
|
||||
|
||||
saveAvatarSelection: function() {
|
||||
const user = this.modelFor('user');
|
||||
const avatarSelector = this.controllerFor('avatar-selector');
|
||||
saveAvatarSelection() {
|
||||
const user = this.modelFor('user'),
|
||||
avatarSelector = this.controllerFor('avatar-selector');
|
||||
|
||||
// sends the information to the server if it has changed
|
||||
if (avatarSelector.get('selectedUploadId') !== user.get('uploaded_avatar_id')) {
|
||||
user.pickAvatar(avatarSelector.get('selectedUploadId'))
|
||||
.then(function(){
|
||||
user.setProperties(avatarSelector.getProperties(
|
||||
'system_avatar_upload_id',
|
||||
'gravatar_avatar_upload_id',
|
||||
'custom_avatar_upload_id'
|
||||
));
|
||||
});
|
||||
.then(() => {
|
||||
user.setProperties(avatarSelector.getProperties(
|
||||
'system_avatar_upload_id',
|
||||
'gravatar_avatar_upload_id',
|
||||
'custom_avatar_upload_id'
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
// saves the data back
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
|
||||
export default Discourse.Route.extend({
|
||||
|
||||
afterModel: function() {
|
||||
var user = this.modelFor('user');
|
||||
if (!user.get('can_edit')) {
|
||||
afterModel() {
|
||||
if (!this.modelFor('user').get('can_edit')) {
|
||||
this.replaceWith('userActivity');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
<div>
|
||||
<input type="radio" id="gravatar" name="avatar" value="gravatar" {{action "useGravatar"}}>
|
||||
<label class="radio" for="gravatar">{{bound-avatar controller "large" gravatar_avatar_upload_id}} {{{i18n 'user.change_avatar.gravatar'}}} {{email}}</label>
|
||||
<button href {{action "refreshGravatar"}} title="{{i18n 'user.change_avatar.refresh_gravatar_title'}}" {{bind-attr enabled="view.gravatarRefreshEnabled"}} class="btn no-text"><i class="fa fa-refresh"></i></button>
|
||||
{{d-button action="refreshGravatar" title="user.change_avatar.refresh_gravatar_title" disabled=gravatarRefreshDisabled class="no-text" icon="refresh"}}
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="uploaded_avatar" name="avatar" value="uploaded" {{action "useUploadedAvatar"}}>
|
||||
<label class="radio" for="uploaded_avatar">
|
||||
{{#if view.hasUploadedAvatar}}
|
||||
{{#if view.uploadedAvatarTemplate}}
|
||||
{{bound-avatar-template view.uploadedAvatarTemplate "large"}}
|
||||
{{#if hasUploadedAvatar}}
|
||||
{{#if uploadedAvatarTemplate}}
|
||||
{{bound-avatar-template uploadedAvatarTemplate "large"}}
|
||||
{{else}}
|
||||
{{bound-avatar controller "large" custom_avatar_upload_id}} {{i18n 'user.change_avatar.uploaded_avatar'}}
|
||||
{{/if}}
|
||||
|
@ -23,14 +23,14 @@
|
|||
{{/if}}
|
||||
</label>
|
||||
{{avatar-uploader username=username
|
||||
uploadedAvatarTemplate=view.uploadedAvatarTemplate
|
||||
custom_avatar_upload_id=controller.custom_avatar_upload_id
|
||||
uploadedAvatarTemplate=uploadedAvatarTemplate
|
||||
custom_avatar_upload_id=custom_avatar_upload_id
|
||||
done="useUploadedAvatar"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary" {{action "saveAvatarSelection"}} {{bind-attr disabled="view.saveDisabled"}}>{{i18n 'save'}}</button>
|
||||
{{d-button action="saveAvatarSelection" class="btn-primary" disabled=saveDisabled label="save"}}
|
||||
<a {{action "closeModal"}}>{{i18n 'cancel'}}</a>
|
||||
</div>
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
<div class="controls">
|
||||
<span class='static'>{{email}}</span>
|
||||
{{#if can_edit_email}}
|
||||
{{#link-to "preferences.email" class="btn btn-small pad-left no-text"}}<i class="fa fa-pencil"></i>{{/link-to}}
|
||||
{{#link-to "preferences.email" class="btn btn-small pad-left no-text"}}{{fa-icon "pencil"}}{{/link-to}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class='instructions'>
|
||||
|
@ -62,7 +62,7 @@
|
|||
</div>
|
||||
{{else}}
|
||||
<div class="controls">
|
||||
<button class="btn" title="{{i18n 'admin.users.check_email.title'}}" {{action "checkEmail" this}}>{{fa-icon "envelope-o"}} {{i18n 'admin.users.check_email.text'}}</button>
|
||||
{{d-button action="checkEmail" actionParam=this title="admin.users.check_email.title" icon="envelope-o" label="admin.users.check_email.text"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
@ -72,7 +72,8 @@
|
|||
<div class="control-group pref-password">
|
||||
<label class="control-label">{{i18n 'user.password.title'}}</label>
|
||||
<div class="controls">
|
||||
<a href="#" {{action "changePassword"}} class='btn'><i class="fa fa-envelope"></i>
|
||||
<a href="#" {{action "changePassword"}} class='btn'>
|
||||
{{fa-icon "envelope"}}
|
||||
{{#if no_password}}
|
||||
{{i18n 'user.change_password.set_password'}}
|
||||
{{else}}
|
||||
|
@ -87,9 +88,10 @@
|
|||
<div class="control-group pref-avatar">
|
||||
<label class="control-label">{{i18n 'user.avatar.title'}}</label>
|
||||
<div class="controls">
|
||||
{{bound-avatar model "large"}}
|
||||
{{! we want the "huge" version even though we're downsizing it to "large" in CSS }}
|
||||
{{bound-avatar model "huge"}}
|
||||
{{#if allowAvatarUpload}}
|
||||
<button {{action "showAvatarSelector"}} class="btn pad-left no-text">{{fa-icon "pencil"}}</button>
|
||||
{{d-button action="showAvatarSelector" class="pad-left no-text" icon="pencil"}}
|
||||
{{else}}
|
||||
{{#unless ssoOverridesAvatar}}
|
||||
<a href="//gravatar.com/emails" target="_blank" title="{{i18n 'user.change_avatar.gravatar_title'}}" class="btn no-text">{{fa-icon "pencil"}}</a>
|
||||
|
@ -245,7 +247,7 @@
|
|||
<div class="control-group delete-account">
|
||||
<hr/>
|
||||
<div class="controls">
|
||||
<button {{action "delete"}} {{bind-attr disabled="deleteDisabled"}} class="btn btn-danger"><i class="fa fa-trash-o"></i> {{i18n 'user.delete_account'}}</button>
|
||||
{{d-button action="delete" disabled="deleteDisabled" class="btn-danger" icon="trash-o" label="user.delete_account"}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
@ -4,9 +4,6 @@ export default ModalBodyView.extend({
|
|||
templateName: 'modal/avatar_selector',
|
||||
classNames: ['avatar-selector'],
|
||||
title: I18n.t('user.change_avatar.title'),
|
||||
saveDisabled: false,
|
||||
gravatarRefreshEnabled: Em.computed.not('controller.gravatarRefreshDisabled'),
|
||||
hasUploadedAvatar: Em.computed.or('uploadedAvatarTemplate', 'controller.custom_avatar_upload_id'),
|
||||
|
||||
// *HACK* used to select the proper radio button, cause {{action}}
|
||||
// stops the default behavior
|
||||
|
|
|
@ -170,6 +170,13 @@
|
|||
border-bottom: 1px solid scale-color-diff();
|
||||
}
|
||||
}
|
||||
|
||||
.pref-avatar {
|
||||
.avatar {
|
||||
max-width: 45px;
|
||||
max-height: 45px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.about {
|
||||
|
|
|
@ -3,7 +3,8 @@ moduleFor("controller:avatar-selector", "controller:avatar-selector", {
|
|||
});
|
||||
|
||||
test("avatarTemplate", function() {
|
||||
var avatarSelectorController = this.subject();
|
||||
const avatarSelectorController = this.subject();
|
||||
|
||||
avatarSelectorController.setProperties({
|
||||
selected: "system",
|
||||
system_avatar_upload_id:1,
|
||||
|
@ -11,17 +12,11 @@ test("avatarTemplate", function() {
|
|||
custom_avatar_upload_id: 3
|
||||
});
|
||||
|
||||
equal(avatarSelectorController.get("selectedUploadId"), 1,
|
||||
"we are using system by default");
|
||||
equal(avatarSelectorController.get("selectedUploadId"), 1, "we are using system by default");
|
||||
|
||||
avatarSelectorController.set('selected', 'gravatar');
|
||||
|
||||
equal(avatarSelectorController.get("selectedUploadId"), 2,
|
||||
"we are using gravatar when set");
|
||||
equal(avatarSelectorController.get("selectedUploadId"), 2, "we are using gravatar when set");
|
||||
|
||||
avatarSelectorController.set("selected", "custom");
|
||||
|
||||
equal(avatarSelectorController.get("selectedUploadId"), 3,
|
||||
"we are using custom when set");
|
||||
|
||||
equal(avatarSelectorController.get("selectedUploadId"), 3, "we are using custom when set");
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue