custom.js.es6 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. export default {
  2. name: 'custom-routes',
  3. initialize() {
  4. if (window.location.pathname.indexOf('/w/') < 0) return;
  5. const Router = requirejs('wizard/router').default;
  6. const ApplicationRoute = requirejs('wizard/routes/application').default;
  7. const ajax = requirejs('wizard/lib/ajax').ajax;
  8. const StepModel = requirejs('wizard/models/step').default;
  9. const CustomWizard = requirejs('discourse/plugins/discourse-custom-wizard/wizard/models/custom').default;
  10. const WizardStep = requirejs('wizard/components/wizard-step').default;
  11. const WizardField = requirejs('wizard/components/wizard-field').default;
  12. const getUrl = requirejs('discourse-common/lib/get-url').default;
  13. const FieldModel = requirejs('wizard/models/wizard-field').default;
  14. const autocomplete = requirejs('discourse/lib/autocomplete').default;
  15. const cook = requirejs('discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite').cook;
  16. $.fn.autocomplete = autocomplete;
  17. // this is for discourse/lib/utilities.avatarImg;
  18. Discourse.getURLWithCDN = getUrl;
  19. Router.reopen({
  20. rootURL: getUrl('/w/')
  21. });
  22. Router.map(function() {
  23. this.route('custom', { path: '/:wizard_id' }, function() {
  24. this.route('steps');
  25. this.route('step', { path: '/steps/:step_id' });
  26. });
  27. });
  28. ApplicationRoute.reopen({
  29. redirect() {
  30. this.transitionTo('custom');
  31. },
  32. model() {}
  33. });
  34. WizardStep.reopen({
  35. classNameBindings: ['step.id'],
  36. animateInvalidFields() {
  37. Ember.run.scheduleOnce('afterRender', () => {
  38. $('.invalid input[type=text], .invalid textarea, .invalid input[type=checkbox]').wiggle(2, 100);
  39. });
  40. },
  41. ensureStartsAtTop: function() {
  42. window.scrollTo(0,0);
  43. }.observes('step.id'),
  44. showQuitButton: function() {
  45. const index = this.get('step.index');
  46. const required = this.get('wizard.required');
  47. return index === 0 && !required;
  48. }.property('step.index', 'wizard.required'),
  49. cookedDescription: function() {
  50. return cook(this.get('step.description'));
  51. }.property('step.description'),
  52. bannerImage: function() {
  53. const src = this.get('step.banner');
  54. if (!src) return;
  55. const localPaths = ['uploads', 'plugins', 'images'];
  56. if (localPaths.indexOf(src.split('/')[1]) > -1) {
  57. return getUrl(src);
  58. } else {
  59. return getUrl(`/images/wizard/${src}`);
  60. };
  61. }.property('step.banner'),
  62. handleMessage: function() {
  63. const message = this.get('step.message');
  64. this.sendAction('showMessage', message);
  65. }.observes('step.message'),
  66. advance() {
  67. this.set('saving', true);
  68. this.get('step').save()
  69. .then(response => {
  70. if (this.get('finalStep')) {
  71. CustomWizard.finished(response);
  72. } else {
  73. this.sendAction('goNext', response);
  74. }
  75. })
  76. .catch(() => this.animateInvalidFields())
  77. .finally(() => this.set('saving', false));
  78. },
  79. actions: {
  80. quit() {
  81. this.get('wizard').skip();
  82. },
  83. done() {
  84. this.set('finalStep', true);
  85. this.send('nextStep');
  86. },
  87. showMessage(message) {
  88. this.sendAction('showMessage', message);
  89. }
  90. }
  91. });
  92. StepModel.reopen({
  93. save() {
  94. const wizardId = this.get('wizardId');
  95. const fields = {};
  96. this.get('fields').forEach(f => fields[f.id] = f.value);
  97. return ajax({
  98. url: `/w/${wizardId}/steps/${this.get('id')}`,
  99. type: 'PUT',
  100. data: { fields }
  101. }).catch(response => {
  102. if (response && response.responseJSON && response.responseJSON.errors) {
  103. let wizardErrors = [];
  104. response.responseJSON.errors.forEach(err => {
  105. if (err.field === wizardId) {
  106. wizardErrors.push(err.description);
  107. } else if (err.field) {
  108. this.fieldError(err.field, err.description);
  109. } else if (err) {
  110. wizardErrors.push(err);
  111. }
  112. });
  113. if (wizardErrors.length) {
  114. this.handleWizardError(wizardErrors.join('\n'));
  115. }
  116. throw response;
  117. }
  118. if (response && response.responseText) {
  119. const responseText = response.responseText;
  120. const start = responseText.indexOf('>') + 1;
  121. const end = responseText.indexOf('plugins');
  122. const message = responseText.substring(start, end);
  123. this.handleWizardError(message);
  124. throw message;
  125. }
  126. });
  127. },
  128. handleWizardError(message) {
  129. this.set('message', {
  130. state: 'error',
  131. text: message
  132. });
  133. Ember.run.later(() => this.set('message', null), 6000);
  134. }
  135. });
  136. WizardField.reopen({
  137. classNameBindings: ['field.id'],
  138. cookedDescription: function() {
  139. return cook(this.get('field.description'));
  140. }.property('field.description'),
  141. inputComponentName: function() {
  142. const type = this.get('field.type');
  143. const id = this.get('field.id');
  144. if (type === 'text-only') return false;
  145. return (type === 'component') ? Ember.String.dasherize(id) : `wizard-field-${type}`;
  146. }.property('field.type', 'field.id')
  147. });
  148. const StandardFields = ['text', 'textarea', 'dropdown', 'image', 'checkbox', 'user-selector', 'text-only', 'composer'];
  149. FieldModel.reopen({
  150. hasCustomCheck: false,
  151. customCheck() {
  152. return true;
  153. },
  154. check() {
  155. let valid = this.get('valid');
  156. if (!this.get('required')) {
  157. this.setValid(true);
  158. return true;
  159. }
  160. const hasCustomCheck = this.get('hasCustomCheck');
  161. if (hasCustomCheck) {
  162. valid = this.customCheck();
  163. } else {
  164. const val = this.get('value');
  165. const type = this.get('type');
  166. if (type === 'checkbox') {
  167. valid = val;
  168. } else if (StandardFields.indexOf(type) > -1) {
  169. valid = val && val.length > 0;
  170. }
  171. }
  172. this.setValid(valid);
  173. return valid;
  174. }
  175. });
  176. }
  177. };