{"action":"created","issue":{"url":"https://api.github.com/repos/volkanceylan/Serenity/issues/3485","repository_url":"https://api.github.com/repos/volkanceylan/Serenity","labels_url":"https://api.github.com/repos/volkanceylan/Serenity/issues/3485/labels{/name}","comments_url":"https://api.github.com/repos/volkanceylan/Serenity/issues/3485/comments","events_url":"https://api.github.com/repos/volkanceylan/Serenity/issues/3485/events","html_url":"https://github.com/volkanceylan/Serenity/issues/3485","id":314419321,"number":3485,"title":"Improved GridEditorBase (Support for TEntity) - Pull Request ?","user":{"login":"brunobola","id":10889019,"avatar_url":"https://avatars0.githubusercontent.com/u/10889019?v=4","gravatar_id":"","url":"https://api.github.com/users/brunobola","html_url":"https://github.com/brunobola","followers_url":"https://api.github.com/users/brunobola/followers","following_url":"https://api.github.com/users/brunobola/following{/other_user}","gists_url":"https://api.github.com/users/brunobola/gists{/gist_id}","starred_url":"https://api.github.com/users/brunobola/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brunobola/subscriptions","organizations_url":"https://api.github.com/users/brunobola/orgs","repos_url":"https://api.github.com/users/brunobola/repos","events_url":"https://api.github.com/users/brunobola/events{/privacy}","received_events_url":"https://api.github.com/users/brunobola/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-04-15T14:15:41Z","updated_at":"2018-04-23T12:42:41Z","closed_at":null,"author_association":"NONE","body":"I've created a improved GridEditorBase that adds the functionality that some needs in witch it stores the TEntity that owns it.\r\n\r\nThe code is this, I believe it can improve the current Editor. \r\n\r\n```\r\nnamespace FichaProjeto.Projetos {\r\n\r\n    @Serenity.Decorators.registerClass([Serenity.IGetEditValue, Serenity.ISetEditValue])\r\n    @Serenity.Decorators.editor()\r\n    @Serenity.Decorators.element(\"<div/>\")\r\n    export class GridEditorBaseAdvanced<TEntity> extends FichaProjeto.Common.GridEditorBase<TEntity>\r\n        implements Serenity.IGetEditValue, Serenity.ISetEditValue {\r\n\r\n        protected entidade: Object;\r\n        public setEntidade(entity: Object) {\r\n            this.entidade = entity;\r\n        }\r\n\r\n        public getEntidade() {\r\n            return this.entidade;\r\n        }\r\n\r\n        protected getIdProperty() { return \"__id\"; }\r\n\r\n        protected nextId = 1;\r\n\r\n        constructor(container: JQuery) {\r\n            super(container);\r\n        }\r\n\r\n        protected id(entity: TEntity) {\r\n            return (entity as any)[this.getIdProperty()];\r\n        }\r\n\r\n        protected getNextId() {\r\n            return \"`\" + this.nextId++;\r\n        }\r\n\r\n        protected setNewId(entity: TEntity) {\r\n            entity[this.getIdProperty()] = this.getNextId();\r\n        }\r\n\r\n        protected save(opt: Serenity.ServiceOptions<any>, callback: (r: Serenity.ServiceResponse) => void) {\r\n            var request = opt.request as Serenity.SaveRequest<TEntity>;\r\n            var row = Q.deepClone(request.Entity);\r\n\r\n            var id = this.id(row);\r\n            if (id == null) {\r\n                (row as any)[this.getIdProperty()] = this.getNextId();\r\n            }\r\n\r\n            if (!this.validateEntity(row, id)) {\r\n                return;\r\n            }\r\n\r\n            var items = this.view.getItems().slice();\r\n            if (id == null) {\r\n                items.push(row);\r\n            }\r\n            else {\r\n                var index = Q.indexOf(items, x => this.id(x) === id);\r\n                items[index] = Q.deepClone({} as TEntity, items[index], row);\r\n            }\r\n\r\n            this.setEntities(items);\r\n            callback({});\r\n        }\r\n\r\n        protected deleteEntity(id: number) {\r\n            this.view.deleteItem(id);\r\n            return true;\r\n        }\r\n\r\n        protected validateEntity(row: TEntity, id: number) {\r\n            return true;\r\n        }\r\n\r\n        protected setEntities(items: TEntity[]) {\r\n            this.view.setItems(items, true);\r\n        }\r\n\r\n        protected getNewEntity(): TEntity {\r\n            return {} as TEntity;\r\n        }\r\n\r\n        protected getButtons(): Serenity.ToolButton[] {\r\n            return [{\r\n                title: this.getAddButtonCaption(),\r\n                cssClass: 'add-button',\r\n                onClick: () => {\r\n                    this.createEntityDialog(this.getItemType(), dlg => {\r\n                        var dialog = dlg as FichaProjeto.Common.GridEditorDialog<TEntity>;\r\n                        dialog.onSave = (opt, callback) => this.save(opt, callback);\r\n                        dialog.loadEntityAndOpenDialog(this.getNewEntity());\r\n                    });\r\n                }\r\n            }];\r\n        }\r\n\r\n        protected editItem(entityOrId: any): void {\r\n\r\n            var id = entityOrId;\r\n            var item = this.view.getItemById(id);\r\n            this.createEntityDialog(this.getItemType(), dlg => {\r\n                var dialog = dlg as FichaProjeto.Common.GridEditorDialog<TEntity>;\r\n                dialog.onDelete = (opt, callback) => {\r\n                    if (!this.deleteEntity(id)) {\r\n                        return;\r\n                    }\r\n                    callback({});\r\n                };\r\n\r\n                dialog.onSave = (opt, callback) => this.save(opt, callback);\r\n                dialog.loadEntityAndOpenDialog(item);\r\n            });;\r\n        }\r\n\r\n        public getEditValue(property, target) {\r\n            target[property.name] = this.value;\r\n        }\r\n\r\n        public setEditValue(source, property) {\r\n            this.value = source[property.name];\r\n        }\r\n\r\n        public get value(): TEntity[] {\r\n            var p = this.getIdProperty();\r\n            return this.view.getItems().map(x => {\r\n                var y = Q.deepClone(x);\r\n                var id = y[p];\r\n                if (id && id.toString().charAt(0) == '`')\r\n                    delete y[p];\r\n                return y;\r\n            });\r\n        }\r\n\r\n        public set value(value: TEntity[]) {\r\n            var p = this.getIdProperty();\r\n            this.view.setItems((value || []).map(x => {\r\n                var y = Q.deepClone(x);\r\n                if ((y as any)[p] == null)\r\n                    (y as any)[p] = \"`\" + this.getNextId();\r\n                return y;\r\n            }), true);\r\n        }\r\n\r\n        protected getGridCanLoad() {\r\n            return false;\r\n        }\r\n\r\n        protected usePager() {\r\n            return false;\r\n        }\r\n\r\n        protected getInitialTitle() {\r\n            return null;\r\n        }\r\n\r\n        protected createQuickSearchInput() {\r\n        }\r\n    }\r\n}\r\n \r\n```\r\n\r\nIt  can be used like so:\r\nExample editor: \r\n\r\n... export class CopObraEstadosEditor extends GridEditorBaseAdvanced<CopObraEstadosRow> {...\r\n...\r\n//Puts the Entity to the variable and it won't be lost....\r\n public setEditValue(source, property) {\r\n            super.setEditValue(source, property);\r\n\r\n            //Fica com a Fase Pai\r\n            super.setEntidade(source);\r\n        }\r\n...\r\n        protected getButtons(): Serenity.ToolButton[] {\r\n            // call base method to get list of buttons\r\n            // by default, base entity grid adds a few buttons, \r\n            // add, refresh, column selection in order.\r\n            var buttons = super.getButtons();\r\n\r\n            var addButton = buttons[Q.indexOf(buttons, x => x.cssClass == \"add-button\")];\r\n            addButton.title = \"Atribuir Estado a Fase\";\r\n\r\n            buttons[0].onClick = () => {\r\n\r\n               // Retrieve owner TEntity\r\n                var entidade = super.getEntidade();\r\n\r\n                //Atualiza a fase da obra\r\n                if (entidade != null) {\r\n\r\n                    // do Some checks\r\n                }\r\n             ...\r\n            \r\n            return buttons;\r\n        }\r\n...\r\n\r\nThere are more benefits of this approach, please include in serenity.\r\n"},"comment":{"url":"https://api.github.com/repos/volkanceylan/Serenity/issues/comments/383561291","html_url":"https://github.com/volkanceylan/Serenity/issues/3485#issuecomment-383561291","issue_url":"https://api.github.com/repos/volkanceylan/Serenity/issues/3485","id":383561291,"user":{"login":"brunobola","id":10889019,"avatar_url":"https://avatars0.githubusercontent.com/u/10889019?v=4","gravatar_id":"","url":"https://api.github.com/users/brunobola","html_url":"https://github.com/brunobola","followers_url":"https://api.github.com/users/brunobola/followers","following_url":"https://api.github.com/users/brunobola/following{/other_user}","gists_url":"https://api.github.com/users/brunobola/gists{/gist_id}","starred_url":"https://api.github.com/users/brunobola/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brunobola/subscriptions","organizations_url":"https://api.github.com/users/brunobola/orgs","repos_url":"https://api.github.com/users/brunobola/repos","events_url":"https://api.github.com/users/brunobola/events{/privacy}","received_events_url":"https://api.github.com/users/brunobola/received_events","type":"User","site_admin":false},"created_at":"2018-04-23T12:42:41Z","updated_at":"2018-04-23T12:42:41Z","author_association":"NONE","body":"@dfaruque This code is to add the functionality to easy access the parent entity of the owner dialog with ease and with no lost of the current updated properties, with the standard you couldn't easily access the parent entity to do some co-related calculations and/or validations.\r\n\r\nThis way the Owner TEntity is always available and with easy access just like I point out, event in button click events or other isolated events :)"}}
{"actor":{"display_login":"brunobola"}}