Show:
  1. /**
  2. This module has two mixins: godForm and formComponent, they are used to manage form handler
  3. @module mixins
  4. @submodule form
  5. */
  6. import { action, get, setProperties } from '@ember/object';
  7. import { inject, inject as service } from '@ember/service';
  8. import { isNone } from '@ember/utils';
  9. import Component from '@glimmer/component';
  10. import { tracked } from '@glimmer/tracking';
  11. import { A } from '@ember/array';
  12.  
  13. /**
  14. delete object from backend server
  15. @event deleteObject
  16. @param {Object} selectedItem The current selected item
  17. */
  18. let deleteObject = function (selectedItem) {
  19. if (!this.modelName) {
  20. throw new Error(`mixin component modelName is invalid: ${this.modelName}`);
  21. }
  22. this.loading = true;
  23. this.store
  24. .deleteRecord(this.modelName, selectedItem)
  25. .then((data) => {
  26. this.loading = false;
  27. this.success('delete', data, selectedItem);
  28. })
  29. .catch((reason) => {
  30. this.loading = false;
  31. this.fail('delete', reason, selectedItem);
  32. });
  33. };
  34.  
  35. /**
  36. GodForm is used for data list to create, update and delete children object
  37. only support native style class component
  38. @public
  39. @class godForm
  40. **/
  41. class GodForm extends Component {
  42. constructor() {
  43. super(...arguments);
  44. this.model = this.args.model ? this.args.model : A();
  45. }
  46.  
  47. @service store;
  48.  
  49. /**
  50. @property modelName
  51. @type String
  52. */
  53. modelName = '';
  54.  
  55. /**
  56. for loading
  57. @property loading
  58. @type boolean
  59. */
  60. @tracked loading = false;
  61.  
  62. /**
  63. data set, normally array
  64. @property model
  65. @type Object
  66. */
  67. @tracked model = null;
  68. /**
  69. current selected item
  70. @property selectedItem
  71. @type Object
  72. */
  73. @tracked selectedItem = null;
  74. /**
  75. for modal dialog
  76. @property modalShow
  77. @type boolean
  78. */
  79. @tracked modalShow = false;
  80. /**
  81. ajax fail reason
  82. @property reason
  83. @type String
  84. */
  85. @tracked reason = null;
  86. /**
  87. orm store service
  88. @property store
  89. @type Object
  90. */
  91. @inject store;
  92.  
  93. /**
  94. create new record according to modelName
  95. @event add
  96. */
  97. @action
  98. add() {
  99. this.modalShow = true;
  100. this.selectedItem = this.store.createRecord(this.modelName);
  101. }
  102.  
  103. /**
  104. edit current selected item
  105. @event edit
  106. @param {Object} selectedItem
  107. */
  108. @action
  109. edit(selectedItem) {
  110. this.modalShow = true;
  111. if (!isNone(selectedItem)) {
  112. this.selectedItem = selectedItem;
  113. }
  114. }
  115.  
  116. /**
  117. cancel current operation
  118. @event cancel
  119. */
  120. @action
  121. cancel() {
  122. this.modalShow = false;
  123. }
  124.  
  125. /**
  126. remove current selected item
  127. @event remove
  128. @param {Object} selectedItem
  129. */
  130. @action
  131. remove(selectedItem) {
  132. if (!this.modelName) {
  133. throw new Error(
  134. `mixin component modelName is invalid: ${this.modelName}`
  135. );
  136. }
  137. this.loading = true;
  138. this.store
  139. .deleteRecord(this.modelName, selectedItem)
  140. .then((data) => {
  141. console.log(data, selectedItem);
  142. this.loading = false;
  143. this.success('delete', data, selectedItem);
  144. })
  145. .catch((reason) => {
  146. this.loading = false;
  147. this.fail('delete', reason, selectedItem);
  148. });
  149. }
  150.  
  151. /**
  152. success ajax request success callback
  153. @event success
  154. @params {String} action The current operation: create, update, delete
  155. @params {Object} data The response data from backend server
  156. @params {Object} selectedItem Thc current selected item
  157. */
  158. @action
  159. success(action, data, selectedItem) {
  160. this.modalShow = false;
  161. if (this.args?.success) {
  162. this.args.success(action, data, selectedItem);
  163. }
  164.  
  165. // child component send action to parent
  166. if (action === 'delete') {
  167. this.model.removeObject(selectedItem);
  168. return;
  169. }
  170.  
  171. if (!this.model.includes(selectedItem)) {
  172. this.model.insertAt(0, selectedItem);
  173. }
  174. }
  175.  
  176. /**
  177. fail ajax request success callback
  178. @event fail
  179. @params {string} action The current operation: create, update, delete
  180. @params {Object} reason The ajax request response
  181. @params {Object} selectedItem Thc current selected item
  182. */
  183. @action
  184. fail(action, reason, selectedItem) {
  185. this.reason = reason;
  186. // check parent callback
  187. if (this.args?.fail) {
  188. this.args.fail(action, reason, selectedItem);
  189. }
  190. }
  191. }
  192.  
  193. /**
  194. Form is used for one record to create, update and delete
  195. only support native style class component
  196. @public
  197. @class Form
  198. **/
  199. class Form extends Component {
  200. constructor() {
  201. super(...arguments);
  202. this.model = this.args.model ? this.args.model : null;
  203. }
  204.  
  205. /**
  206. @property modelName
  207. @type String
  208. */
  209. modelName = '';
  210. /**
  211. single object, normally for form
  212. @property model
  213. @type Object
  214. */
  215. @tracked model = null;
  216. /**
  217. orm store service
  218. @property store
  219. @type Object
  220. */
  221. @inject store;
  222. /**
  223. ajax fail reason
  224. @property reason
  225. @type String
  226. */
  227. @tracked reason = null;
  228. @tracked loading = false;
  229.  
  230. /**
  231. save triggle when user click save action
  232. @event save
  233. */
  234. @action
  235. save() {
  236. if (!this.modelName) {
  237. throw new Error(`FormComponent modelName is invalid: ${this.modelName}`);
  238. }
  239. this.loading = true;
  240. if (!this.validate()) {
  241. return;
  242. }
  243. let primaryKey = this.store.modelFor(this.modelName).primaryKey;
  244. let actionName = get(this.model, primaryKey) ? 'update' : 'create';
  245. this.store
  246. .save(this.modelName, this.model)
  247. .then((data) => {
  248. this.loading = false;
  249. this.success(actionName, data);
  250. })
  251. .catch((reason) => {
  252. this.loading = false;
  253. this.fail(actionName, reason);
  254. });
  255. }
  256.  
  257. /**
  258. delete triggle when user click save action
  259. @event remove
  260. */
  261. @action
  262. remove() {
  263. deleteObject.call(this, this.model);
  264. }
  265.  
  266. /**
  267. success ajax request success callback
  268. @event succuess
  269. @params {String} action The current operation: create, update, delete
  270. @params {Object} data The response data from backend server
  271. */
  272. @action
  273. success(action, data) {
  274. if ((action === 'create' || action === 'update') && data) {
  275. setProperties(this.model, data);
  276. }
  277. if (this.args.success) {
  278. this.args.success(action, data, this.model);
  279. }
  280. }
  281.  
  282. /**
  283. fail ajax request success callback
  284. @event fail
  285. @params {string} action The current operation: create, update, delete
  286. @params {Object} reason The ajax request response
  287. */
  288. @action
  289. fail(action, reason) {
  290. this.reason = reason;
  291. // call object fail function from action
  292. if (this.args.fail) {
  293. this.args.fail(action, reason, this.model);
  294. }
  295. }
  296.  
  297. /**
  298. cancel current operation
  299. @event cancel
  300. */
  301. @action
  302. cancel() {
  303. if (this.args.cancel) {
  304. this.args.cancel(this.model);
  305. }
  306. }
  307. /**
  308. validate current model
  309. @method validate
  310. @return {Boolean} Returns true when success, false when fails
  311. */
  312. validate() {
  313. console.log('subclass override this function for model validate');
  314. return true;
  315. }
  316. }
  317.  
  318. export { GodForm, Form };
  319.