- /**
- This module has two mixins: godForm and formComponent, they are used to manage form handler
- @module mixins
- @submodule form
- */
- import { action, get, setProperties } from '@ember/object';
- import { inject, inject as service } from '@ember/service';
- import { isNone } from '@ember/utils';
- import Component from '@glimmer/component';
- import { tracked } from '@glimmer/tracking';
- import { A } from '@ember/array';
-
- /**
- delete object from backend server
- @event deleteObject
- @param {Object} selectedItem The current selected item
- */
- let deleteObject = function (selectedItem) {
- if (!this.modelName) {
- throw new Error(`mixin component modelName is invalid: ${this.modelName}`);
- }
- this.loading = true;
- this.store
- .deleteRecord(this.modelName, selectedItem)
- .then((data) => {
- this.loading = false;
- this.success('delete', data, selectedItem);
- })
- .catch((reason) => {
- this.loading = false;
- this.fail('delete', reason, selectedItem);
- });
- };
-
- /**
- GodForm is used for data list to create, update and delete children object
- only support native style class component
- @public
- @class godForm
- **/
- class GodForm extends Component {
- constructor() {
- super(...arguments);
- this.model = this.args.model ? this.args.model : A();
- }
-
- @service store;
-
- /**
- @property modelName
- @type String
- */
- modelName = '';
-
- /**
- for loading
- @property loading
- @type boolean
- */
- @tracked loading = false;
-
- /**
- data set, normally array
- @property model
- @type Object
- */
- @tracked model = null;
- /**
- current selected item
- @property selectedItem
- @type Object
- */
- @tracked selectedItem = null;
- /**
- for modal dialog
- @property modalShow
- @type boolean
- */
- @tracked modalShow = false;
- /**
- ajax fail reason
- @property reason
- @type String
- */
- @tracked reason = null;
- /**
- orm store service
- @property store
- @type Object
- */
- @inject store;
-
- /**
- create new record according to modelName
- @event add
- */
- @action
- add() {
- this.modalShow = true;
- this.selectedItem = this.store.createRecord(this.modelName);
- }
-
- /**
- edit current selected item
- @event edit
- @param {Object} selectedItem
- */
- @action
- edit(selectedItem) {
- this.modalShow = true;
- if (!isNone(selectedItem)) {
- this.selectedItem = selectedItem;
- }
- }
-
- /**
- cancel current operation
- @event cancel
- */
- @action
- cancel() {
- this.modalShow = false;
- }
-
- /**
- remove current selected item
- @event remove
- @param {Object} selectedItem
- */
- @action
- remove(selectedItem) {
- if (!this.modelName) {
- throw new Error(
- `mixin component modelName is invalid: ${this.modelName}`
- );
- }
- this.loading = true;
- this.store
- .deleteRecord(this.modelName, selectedItem)
- .then((data) => {
- console.log(data, selectedItem);
- this.loading = false;
- this.success('delete', data, selectedItem);
- })
- .catch((reason) => {
- this.loading = false;
- this.fail('delete', reason, selectedItem);
- });
- }
-
- /**
- success ajax request success callback
- @event success
- @params {String} action The current operation: create, update, delete
- @params {Object} data The response data from backend server
- @params {Object} selectedItem Thc current selected item
- */
- @action
- success(action, data, selectedItem) {
- this.modalShow = false;
- if (this.args?.success) {
- this.args.success(action, data, selectedItem);
- }
-
- // child component send action to parent
- if (action === 'delete') {
- this.model.removeObject(selectedItem);
- return;
- }
-
- if (!this.model.includes(selectedItem)) {
- this.model.insertAt(0, selectedItem);
- }
- }
-
- /**
- fail ajax request success callback
- @event fail
- @params {string} action The current operation: create, update, delete
- @params {Object} reason The ajax request response
- @params {Object} selectedItem Thc current selected item
- */
- @action
- fail(action, reason, selectedItem) {
- this.reason = reason;
- // check parent callback
- if (this.args?.fail) {
- this.args.fail(action, reason, selectedItem);
- }
- }
- }
-
- /**
- Form is used for one record to create, update and delete
- only support native style class component
- @public
- @class Form
- **/
- class Form extends Component {
- constructor() {
- super(...arguments);
- this.model = this.args.model ? this.args.model : null;
- }
-
- /**
- @property modelName
- @type String
- */
- modelName = '';
- /**
- single object, normally for form
- @property model
- @type Object
- */
- @tracked model = null;
- /**
- orm store service
- @property store
- @type Object
- */
- @inject store;
- /**
- ajax fail reason
- @property reason
- @type String
- */
- @tracked reason = null;
- @tracked loading = false;
-
- /**
- save triggle when user click save action
- @event save
- */
- @action
- save() {
- if (!this.modelName) {
- throw new Error(`FormComponent modelName is invalid: ${this.modelName}`);
- }
- this.loading = true;
- if (!this.validate()) {
- return;
- }
- let primaryKey = this.store.modelFor(this.modelName).primaryKey;
- let actionName = get(this.model, primaryKey) ? 'update' : 'create';
- this.store
- .save(this.modelName, this.model)
- .then((data) => {
- this.loading = false;
- this.success(actionName, data);
- })
- .catch((reason) => {
- this.loading = false;
- this.fail(actionName, reason);
- });
- }
-
- /**
- delete triggle when user click save action
- @event remove
- */
- @action
- remove() {
- deleteObject.call(this, this.model);
- }
-
- /**
- success ajax request success callback
- @event succuess
- @params {String} action The current operation: create, update, delete
- @params {Object} data The response data from backend server
- */
- @action
- success(action, data) {
- if ((action === 'create' || action === 'update') && data) {
- setProperties(this.model, data);
- }
- if (this.args.success) {
- this.args.success(action, data, this.model);
- }
- }
-
- /**
- fail ajax request success callback
- @event fail
- @params {string} action The current operation: create, update, delete
- @params {Object} reason The ajax request response
- */
- @action
- fail(action, reason) {
- this.reason = reason;
- // call object fail function from action
- if (this.args.fail) {
- this.args.fail(action, reason, this.model);
- }
- }
-
- /**
- cancel current operation
- @event cancel
- */
- @action
- cancel() {
- if (this.args.cancel) {
- this.args.cancel(this.model);
- }
- }
- /**
- validate current model
- @method validate
- @return {Boolean} Returns true when success, false when fails
- */
- validate() {
- console.log('subclass override this function for model validate');
- return true;
- }
- }
-
- export { GodForm, Form };
-
-