mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
Link to edit "About Me" links directly to the field.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
The route for editing a user's "About Me" bio.
|
||||
|
||||
@class PreferencesAboutRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesAboutRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
controller.setProperties({ model: model, newBio: model.get('bio_raw') });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
exit: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
},
|
||||
|
||||
events: {
|
||||
changeAbout: function() {
|
||||
var route = this;
|
||||
var controller = route.controllerFor('preferencesAbout');
|
||||
|
||||
controller.setProperties({ saving: true });
|
||||
return controller.get('model').save().then(function() {
|
||||
controller.set('saving', false);
|
||||
route.transitionTo('user.index');
|
||||
}, function() {
|
||||
// model failed to save
|
||||
controller.set('saving', false);
|
||||
alert(I18n.t('generic_error'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
/**
|
||||
This controller supports actions related to updating your "About Me" bio
|
||||
|
||||
@class PreferencesAboutController
|
||||
@extends Discourse.ObjectController
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesAboutController = Discourse.ObjectController.extend({
|
||||
saving: false,
|
||||
|
||||
saveButtonText: function() {
|
||||
if (this.get('saving')) return I18n.t("saving");
|
||||
return I18n.t("user.change");
|
||||
}.property('saving'),
|
||||
|
||||
|
||||
});
|
||||
@@ -1,3 +1,21 @@
|
||||
/**
|
||||
The common route stuff for a user's preference
|
||||
|
||||
@class PreferencesRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
This controller supports actions related to updating one's preferences
|
||||
|
||||
@@ -10,47 +28,32 @@ Discourse.PreferencesController = Discourse.ObjectController.extend({
|
||||
// By default we haven't saved anything
|
||||
saved: false,
|
||||
|
||||
saveDisabled: (function() {
|
||||
saveDisabled: function() {
|
||||
if (this.get('saving')) return true;
|
||||
if (this.blank('content.name')) return true;
|
||||
if (this.blank('content.email')) return true;
|
||||
if (this.blank('name')) return true;
|
||||
if (this.blank('email')) return true;
|
||||
return false;
|
||||
}).property('saving', 'content.name', 'content.email'),
|
||||
}.property('saving', 'name', 'email'),
|
||||
|
||||
digestFrequencies: (function() {
|
||||
var freqs;
|
||||
freqs = Em.A();
|
||||
freqs.addObject({ name: I18n.t('user.email_digests.daily'), value: 1 });
|
||||
freqs.addObject({ name: I18n.t('user.email_digests.weekly'), value: 7 });
|
||||
freqs.addObject({ name: I18n.t('user.email_digests.bi_weekly'), value: 14 });
|
||||
return freqs;
|
||||
}).property(),
|
||||
digestFrequencies: [{ name: I18n.t('user.email_digests.daily'), value: 1 },
|
||||
{ name: I18n.t('user.email_digests.weekly'), value: 7 },
|
||||
{ name: I18n.t('user.email_digests.bi_weekly'), value: 14 }],
|
||||
|
||||
autoTrackDurations: (function() {
|
||||
var freqs;
|
||||
freqs = Em.A();
|
||||
freqs.addObject({ name: I18n.t('user.auto_track_options.never'), value: -1 });
|
||||
freqs.addObject({ name: I18n.t('user.auto_track_options.always'), value: 0 });
|
||||
freqs.addObject({ name: I18n.t('user.auto_track_options.after_n_seconds', { count: 30 }), value: 30000 });
|
||||
freqs.addObject({ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 1 }), value: 60000 });
|
||||
freqs.addObject({ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 2 }), value: 120000 });
|
||||
freqs.addObject({ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 3 }), value: 180000 });
|
||||
freqs.addObject({ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 4 }), value: 240000 });
|
||||
freqs.addObject({ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 5 }), value: 300000 });
|
||||
freqs.addObject({ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 10 }), value: 600000 });
|
||||
return freqs;
|
||||
}).property(),
|
||||
autoTrackDurations: [{ name: I18n.t('user.auto_track_options.never'), value: -1 },
|
||||
{ name: I18n.t('user.auto_track_options.always'), value: 0 },
|
||||
{ name: I18n.t('user.auto_track_options.after_n_seconds', { count: 30 }), value: 30000 },
|
||||
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 1 }), value: 60000 },
|
||||
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 2 }), value: 120000 },
|
||||
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 3 }), value: 180000 },
|
||||
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 4 }), value: 240000 },
|
||||
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 5 }), value: 300000 },
|
||||
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 10 }), value: 600000 }],
|
||||
|
||||
considerNewTopicOptions: (function() {
|
||||
var opts;
|
||||
opts = Em.A();
|
||||
opts.addObject({ name: I18n.t('user.new_topic_duration.not_viewed'), value: -1 });
|
||||
opts.addObject({ name: I18n.t('user.new_topic_duration.after_n_days', { count: 1 }), value: 60 * 24 });
|
||||
opts.addObject({ name: I18n.t('user.new_topic_duration.after_n_days', { count: 2 }), value: 60 * 48 });
|
||||
opts.addObject({ name: I18n.t('user.new_topic_duration.after_n_weeks', { count: 1 }), value: 7 * 60 * 24 });
|
||||
opts.addObject({ name: I18n.t('user.new_topic_duration.last_here'), value: -2 });
|
||||
return opts;
|
||||
}).property(),
|
||||
considerNewTopicOptions: [{ name: I18n.t('user.new_topic_duration.not_viewed'), value: -1 },
|
||||
{ name: I18n.t('user.new_topic_duration.after_n_days', { count: 1 }), value: 60 * 24 },
|
||||
{ name: I18n.t('user.new_topic_duration.after_n_days', { count: 2 }), value: 60 * 48 },
|
||||
{ name: I18n.t('user.new_topic_duration.after_n_weeks', { count: 1 }), value: 7 * 60 * 24 },
|
||||
{ name: I18n.t('user.new_topic_duration.last_here'), value: -2 }],
|
||||
|
||||
save: function() {
|
||||
var preferencesController = this;
|
||||
@@ -58,7 +61,7 @@ Discourse.PreferencesController = Discourse.ObjectController.extend({
|
||||
this.set('saved', false);
|
||||
|
||||
// Cook the bio for preview
|
||||
var model = this.get('content');
|
||||
var model = this.get('model');
|
||||
return model.save().then(function() {
|
||||
// model was saved
|
||||
preferencesController.set('saving', false);
|
||||
@@ -66,8 +69,8 @@ Discourse.PreferencesController = Discourse.ObjectController.extend({
|
||||
Discourse.User.current().set('name', model.get('name'));
|
||||
}
|
||||
|
||||
preferencesController.set('content.bio_cooked',
|
||||
Discourse.Markdown.cook(preferencesController.get('content.bio_raw')));
|
||||
preferencesController.set('bio_cooked',
|
||||
Discourse.Markdown.cook(preferencesController.get('bio_raw')));
|
||||
preferencesController.set('saved', true);
|
||||
}, function() {
|
||||
// model failed to save
|
||||
@@ -76,16 +79,15 @@ Discourse.PreferencesController = Discourse.ObjectController.extend({
|
||||
});
|
||||
},
|
||||
|
||||
saveButtonText: (function() {
|
||||
if (this.get('saving')) return I18n.t('saving');
|
||||
return I18n.t('save');
|
||||
}).property('saving'),
|
||||
saveButtonText: function() {
|
||||
return this.get('saving') ? I18n.t('saving') : I18n.t('save');
|
||||
}.property('saving'),
|
||||
|
||||
changePassword: function() {
|
||||
var preferencesController = this;
|
||||
if (!this.get('passwordProgress')) {
|
||||
this.set('passwordProgress', I18n.t("user.change_password.in_progress"));
|
||||
return this.get('content').changePassword().then(function() {
|
||||
return this.get('model').changePassword().then(function() {
|
||||
// password changed
|
||||
preferencesController.setProperties({
|
||||
changePasswordProgress: false,
|
||||
|
||||
@@ -1,3 +1,32 @@
|
||||
/**
|
||||
The route for editing a user's email
|
||||
|
||||
@class PreferencesEmailRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesEmailRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
setupController: function(controller, model) {
|
||||
controller.setProperties({ model: model, newEmail: model.get('email') });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
exit: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
This controller supports actions related to updating one's email address
|
||||
|
||||
@@ -13,25 +42,14 @@ Discourse.PreferencesEmailController = Discourse.ObjectController.extend({
|
||||
success: false,
|
||||
newEmail: null,
|
||||
|
||||
saveDisabled: (function() {
|
||||
if (this.get('saving')) return true;
|
||||
if (this.blank('newEmail')) return true;
|
||||
if (this.get('taken')) return true;
|
||||
if (this.get('unchanged')) return true;
|
||||
}).property('newEmail', 'taken', 'unchanged', 'saving'),
|
||||
newEmailEmpty: Em.computed.empty('newEmail'),
|
||||
saveDisabled: Em.computed.or('saving', 'newEmailEmpty', 'taken', 'unchanged'),
|
||||
unchanged: Discourse.computed.propertyEqual('newEmail', 'email'),
|
||||
|
||||
unchanged: (function() {
|
||||
return this.get('newEmail') === this.get('content.email');
|
||||
}).property('newEmail', 'content.email'),
|
||||
|
||||
initializeEmail: (function() {
|
||||
this.set('newEmail', this.get('content.email'));
|
||||
}).observes('content.email'),
|
||||
|
||||
saveButtonText: (function() {
|
||||
saveButtonText: function() {
|
||||
if (this.get('saving')) return I18n.t("saving");
|
||||
return I18n.t("user.change_email.action");
|
||||
}).property('saving'),
|
||||
return I18n.t("user.change");
|
||||
}.property('saving'),
|
||||
|
||||
changeEmail: function() {
|
||||
var preferencesEmailController = this;
|
||||
@@ -39,9 +57,10 @@ Discourse.PreferencesEmailController = Discourse.ObjectController.extend({
|
||||
return this.get('content').changeEmail(this.get('newEmail')).then(function() {
|
||||
preferencesEmailController.set('success', true);
|
||||
}, function() {
|
||||
// Error
|
||||
preferencesEmailController.set('error', true);
|
||||
preferencesEmailController.set('saving', false);
|
||||
preferencesEmailController.setProperties({
|
||||
error: true,
|
||||
saving: false
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,32 @@
|
||||
/**
|
||||
The route for updating a user's username
|
||||
|
||||
@class PreferencesUsernameRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesUsernameRoute = Discourse.RestrictedUserRoute.extend({
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
return this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
exit: function() {
|
||||
this._super();
|
||||
this.render('preferences', { into: 'user', outlet: 'userOutlet', controller: 'preferences' });
|
||||
},
|
||||
|
||||
setupController: function(controller, user) {
|
||||
controller.setProperties({ model: user, newUsername: user.get('username') });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
This controller supports actions related to updating one's username
|
||||
|
||||
@@ -13,18 +42,9 @@ Discourse.PreferencesUsernameController = Discourse.ObjectController.extend({
|
||||
errorMessage: null,
|
||||
newUsername: null,
|
||||
|
||||
saveDisabled: function() {
|
||||
if (this.get('saving')) return true;
|
||||
if (this.blank('newUsername')) return true;
|
||||
if (this.get('taken')) return true;
|
||||
if (this.get('unchanged')) return true;
|
||||
if (this.get('errorMessage')) return true;
|
||||
return false;
|
||||
}.property('newUsername', 'taken', 'errorMessage', 'unchanged', 'saving'),
|
||||
|
||||
unchanged: function() {
|
||||
return this.get('newUsername') === this.get('content.username');
|
||||
}.property('newUsername', 'content.username'),
|
||||
newUsernameEmpty: Em.computed.empty('newUsername'),
|
||||
saveDisabled: Em.computed.or('saving', 'newUsernameEmpty', 'taken', 'unchanged', 'errorMessage'),
|
||||
unchanged: Discourse.computed.propertyEqual('newUsername', 'username'),
|
||||
|
||||
checkTaken: function() {
|
||||
if( this.get('newUsername') && this.get('newUsername').length < 3 ) {
|
||||
@@ -47,7 +67,7 @@ Discourse.PreferencesUsernameController = Discourse.ObjectController.extend({
|
||||
|
||||
saveButtonText: function() {
|
||||
if (this.get('saving')) return I18n.t("saving");
|
||||
return I18n.t("user.change_username.action");
|
||||
return I18n.t("user.change");
|
||||
}.property('saving'),
|
||||
|
||||
changeUsername: function() {
|
||||
|
||||
@@ -56,6 +56,7 @@ Discourse.Route.buildRoutes(function() {
|
||||
this.resource('preferences', { path: '/preferences' }, function() {
|
||||
this.route('username', { path: '/username' });
|
||||
this.route('email', { path: '/email' });
|
||||
this.route('about', { path: '/about-me' });
|
||||
});
|
||||
|
||||
this.route('invited', { path: 'invited' });
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/**
|
||||
The route for editing a user's email
|
||||
|
||||
@class PreferencesEmailRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesEmailRoute = Discourse.RestrictedUserRoute.extend({
|
||||
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
exit: function() {
|
||||
this._super();
|
||||
this.render('preferences', {
|
||||
into: 'user',
|
||||
outlet: 'userOutlet',
|
||||
controller: 'preferences'
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
The common route stuff for a user's preference
|
||||
|
||||
@class PreferencesRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesRoute = Discourse.RestrictedUserRoute.extend({
|
||||
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('preferences', {
|
||||
into: 'user',
|
||||
outlet: 'userOutlet',
|
||||
controller: 'preferences'
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
The route for updating a user's username
|
||||
|
||||
@class PreferencesUsernameRoute
|
||||
@extends Discourse.RestrictedUserRoute
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesUsernameRoute = Discourse.RestrictedUserRoute.extend({
|
||||
|
||||
model: function() {
|
||||
return this.modelFor('user');
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
return this.render({ into: 'user', outlet: 'userOutlet' });
|
||||
},
|
||||
|
||||
// A bit odd, but if we leave to /preferences we need to re-render that outlet
|
||||
exit: function() {
|
||||
this._super();
|
||||
this.render('preferences', {
|
||||
into: 'user',
|
||||
outlet: 'userOutlet',
|
||||
controller: 'preferences'
|
||||
});
|
||||
},
|
||||
|
||||
setupController: function(controller, user) {
|
||||
controller.set('model', user);
|
||||
controller.set('newUsername', user.get('username'));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -20,13 +20,16 @@ Discourse.UserRoute = Discourse.Route.extend({
|
||||
return Discourse.User.create({username: params.username});
|
||||
},
|
||||
|
||||
afterModel: function() {
|
||||
return this.modelFor('user').findDetails();
|
||||
},
|
||||
|
||||
serialize: function(params) {
|
||||
if (!params) return {};
|
||||
return { username: Em.get(params, 'username').toLowerCase() };
|
||||
},
|
||||
|
||||
setupController: function(controller, user) {
|
||||
user.findDetails();
|
||||
controller.set('model', user);
|
||||
|
||||
// Add a search context
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<form class="form-horizontal">
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<h3>{{i18n user.change_about.title}}</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if error}}
|
||||
<div class="control-group">
|
||||
<div class="instructions">
|
||||
<div class='alert error'>{{i18n user.change_about.error}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{i18n user.bio}}</label>
|
||||
<div class="controls">
|
||||
{{pagedown value=bio_raw}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<button {{action changeAbout}} {{bindAttr disabled="saveDisabled"}} class="btn btn-primary">{{saveButtonText}}</button>
|
||||
{{#if saved}}{{i18n saved}}{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
@@ -4,7 +4,7 @@
|
||||
<label class="control-label">{{i18n user.username.title}}</label>
|
||||
<div class="controls">
|
||||
<span class='static'>{{username}}</span>
|
||||
{{#linkTo "preferences.username" class="btn pad-left"}}{{i18n user.change_username.action}}{{/linkTo}}
|
||||
{{#linkTo "preferences.username" class="btn pad-left"}}{{i18n user.change}}{{/linkTo}}
|
||||
</div>
|
||||
<div class='instructions'>
|
||||
{{{i18n user.username.short_instructions username="username"}}}
|
||||
@@ -25,7 +25,7 @@
|
||||
<label class="control-label">{{i18n user.email.title}}</label>
|
||||
<div class="controls">
|
||||
<span class='static'>{{email}}</span>
|
||||
{{#linkTo "preferences.email" class="btn pad-left"}}{{i18n user.change_email.action}}{{/linkTo}}
|
||||
{{#linkTo "preferences.email" class="btn pad-left"}}{{i18n user.change}}{{/linkTo}}
|
||||
</div>
|
||||
<div class='instructions'>
|
||||
{{i18n user.email.instructions}}
|
||||
@@ -35,7 +35,7 @@
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{i18n user.password.title}}</label>
|
||||
<div class="controls">
|
||||
<a href="#" {{action changePassword}} class='btn'>{{i18n user.change_password.action}}</a> {{passwordProgress}}
|
||||
<a href="#" {{action changePassword}} class='btn'>{{i18n user.change}}</a> {{passwordProgress}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
This view handles rendering of a user's bio editor
|
||||
|
||||
@class PreferencesAboutView
|
||||
@extends Discourse.View
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.PreferencesAboutView = Discourse.View.extend({
|
||||
templateName: 'user/about',
|
||||
classNames: ['user-preferences'],
|
||||
|
||||
didInsertElement: function() {
|
||||
this.$('textarea').focus();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user