change-username-form.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import Ember from 'ember';
  2. import ValidatedForm from 'misago/components/forms/validated-form';
  3. export default ValidatedForm.extend({
  4. tagName: 'form',
  5. classNames: 'form-horizontal',
  6. isLoaded: false,
  7. loadError: null,
  8. isBusy: false,
  9. options: null,
  10. username: '',
  11. apiUrl: function() {
  12. return 'users/' + this.auth.get('user.id') + '/username';
  13. }.property(),
  14. loadOptions: function() {
  15. var self = this;
  16. this.ajax.get(this.get('apiUrl')
  17. ).then(function(options) {
  18. if (self.isDestroyed) { return; }
  19. self.setProperties({
  20. 'options': Ember.Object.create(options),
  21. 'isLoaded': true
  22. });
  23. }, function(jqXHR) {
  24. if (self.isDestroyed) { return; }
  25. if (typeof jqXHR.responseJSON !== 'undefined') {
  26. self.set('loadError', jqXHR.responseJSON);
  27. } else if (jqXHR.status === 0) {
  28. self.set('loadError', {'detail': gettext('Lost connection with application.')});
  29. } else {
  30. self.set('loadError', {'detail': gettext('Application has errored.')});
  31. }
  32. });
  33. }.on('init'),
  34. usernameValidation: function() {
  35. var state = true;
  36. var value = Ember.$.trim(this.get('username'));
  37. var valueLength = value.length;
  38. var limit = 0;
  39. var message = null;
  40. if (valueLength < this.get('options.length_min')) {
  41. limit = this.get('options.length_min');
  42. message = ngettext('Username must be at least %(limit)s character long.',
  43. 'Username must be at least %(limit)s characters long.',
  44. limit);
  45. state = [interpolate(message, {limit: limit}, true)];
  46. } else if (valueLength > this.get('options.length_max')) {
  47. limit = this.get('options.length_max');
  48. message = ngettext('Username cannot be longer than %(limit)s characters.',
  49. 'Username cannot be longer than %(limit)s characters.',
  50. limit);
  51. state = [interpolate(message, {limit: limit}, true)];
  52. } else if (!new RegExp('^[0-9a-z]+$', 'i').test(value)) {
  53. state = [gettext('Username can only contain latin alphabet letters and digits.')];
  54. } else if (value === this.get('auth.user.username')) {
  55. state = [gettext('New username is same as current one.')];
  56. }
  57. if (state === true) {
  58. this.set('validation.username', 'ok');
  59. } else {
  60. this.set('validation.username', state);
  61. }
  62. }.observes('username'),
  63. submit: function() {
  64. if (this.get('isBusy')) {
  65. return false;
  66. }
  67. var data = {
  68. username: Ember.$.trim(this.get('username')),
  69. };
  70. this.usernameValidation();
  71. if (this.hasValidationErrors()) {
  72. this.toast.error(gettext('Form contains errors.'));
  73. return false;
  74. }
  75. this.set('isBusy', true);
  76. var self = this;
  77. this.ajax.post(this.get('apiUrl'), data
  78. ).then(function(response) {
  79. if (self.isDestroyed) { return; }
  80. self.success(response);
  81. }, function(jqXHR) {
  82. if (self.isDestroyed) { return; }
  83. self.error(jqXHR);
  84. }).finally(function() {
  85. if (self.isDestroyed) { return; }
  86. self.set('isBusy', false);
  87. });
  88. return false;
  89. },
  90. success: function(responseJSON) {
  91. this.set('username', '');
  92. this.resetValidation();
  93. this.toast.success(gettext('Your username has been changed.'));
  94. this.get('options').setProperties(responseJSON.options);
  95. var oldUsername = this.get('auth.user.username');
  96. this.get('auth.user').setProperties({
  97. 'username': responseJSON.username,
  98. 'slug': responseJSON.slug
  99. });
  100. var userPOJO = this.auth.getUserPOJO();
  101. this.store.pushPayload({
  102. 'username-changes': [
  103. {
  104. 'id': Math.floor(new Date().getTime() / 1000),
  105. 'user': userPOJO,
  106. 'changed_by': userPOJO,
  107. 'changed_by_username': this.get('auth.user.username'),
  108. 'changed_by_slug': this.get('auth.user.slug'),
  109. 'changed_on': moment(),
  110. 'new_username': this.get('auth.user.username'),
  111. 'old_username': oldUsername
  112. }
  113. ]
  114. });
  115. },
  116. error: function(jqXHR) {
  117. var rejection = jqXHR.responseJSON;
  118. if (jqXHR.status === 400) {
  119. this.toast.error(rejection.detail);
  120. this.get('options').setProperties(rejection.options);
  121. } else {
  122. this.toast.apiError(jqXHR);
  123. }
  124. },
  125. changesLeft: Ember.computed.alias('options.changes_left'),
  126. changesLeftMessage: function() {
  127. var changes = this.get('options.changes_left');
  128. var message = ngettext('You can change your username %(changes)s more time.',
  129. 'You can change your username %(changes)s more times.',
  130. changes);
  131. return interpolate(message, {changes: changes}, true);
  132. }.property('options.changes_left'),
  133. nextChange: function() {
  134. if (this.get('options.next_on')) {
  135. return moment(this.get('options.next_on'));
  136. } else {
  137. return null;
  138. }
  139. }.property('options.next_on', 'clock.tick')
  140. });