)]}'
{"horizon/static/framework/util/tech-debt/helper-functions.service.js":[{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"351fa34e1b236360acf36abe7f255385972633c0","unresolved":false,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":"  angular"},{"line_number":19,"context_line":"    .module(\u0027horizon.framework.util.tech-debt\u0027)"},{"line_number":20,"context_line":"    .factory(\u0027horizon.framework.util.tech-debt.helper-functions\u0027, helperFunctionsService);"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"  helperFunctionsService.$inject \u003d [\u0027$rootScope\u0027, \u0027$compile\u0027];"},{"line_number":23,"context_line":""}],"source_content_type":"text/javascript","patch_set":7,"id":"da20952f_eb74f068","line":20,"updated":"2015-08-28 21:26:49.000000000","message":"Oooh,,, i don\u0027t think we want to add anything into tech-debt without much debate.  better to keep local and extract later.  We also could do some actual perf tests on different methodologies later.","commit_id":"385d641c273e722e82297f736b4f81acfd0d68da"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"4d7bc2aad825940159a633fe86cd65d7f88214d4","unresolved":false,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":"  angular"},{"line_number":19,"context_line":"    .module(\u0027horizon.framework.util.tech-debt\u0027)"},{"line_number":20,"context_line":"    .factory(\u0027horizon.framework.util.tech-debt.helper-functions\u0027, helperFunctionsService);"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"  helperFunctionsService.$inject \u003d [\u0027$rootScope\u0027, \u0027$compile\u0027];"},{"line_number":23,"context_line":""}],"source_content_type":"text/javascript","patch_set":7,"id":"da20952f_2620df47","line":20,"in_reply_to":"da20952f_eb74f068","updated":"2015-08-28 23:24:04.000000000","message":"I\u0027ve moved it from to the controller. Keeping the signature as suggested in the next comment","commit_id":"385d641c273e722e82297f736b4f81acfd0d68da"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"351fa34e1b236360acf36abe7f255385972633c0","unresolved":false,"context_lines":[{"line_number":79,"context_line":"     *  [{id: 2, name: \u0027B\u0027}]"},{"line_number":80,"context_line":"     *"},{"line_number":81,"context_line":"     */"},{"line_number":82,"context_line":"    function filterByIds(list, removeIdsList) {"},{"line_number":83,"context_line":"      return list.filter(filterDeletedIds);"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"      function filterDeletedIds(elem) {"}],"source_content_type":"text/javascript","patch_set":7,"id":"da20952f_889c5a10","line":82,"updated":"2015-08-28 21:26:49.000000000","message":"could be more general if\n\nfilterByKey(list, key, removeKeyList).","commit_id":"385d641c273e722e82297f736b4f81acfd0d68da"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"b93f07de79e7acd7cce6434f8b75e505eb027606","unresolved":false,"context_lines":[{"line_number":79,"context_line":"     *  [{id: 2, name: \u0027B\u0027}]"},{"line_number":80,"context_line":"     *"},{"line_number":81,"context_line":"     */"},{"line_number":82,"context_line":"    function filterByIds(list, removeIdsList) {"},{"line_number":83,"context_line":"      return list.filter(filterDeletedIds);"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"      function filterDeletedIds(elem) {"}],"source_content_type":"text/javascript","patch_set":7,"id":"da20952f_9719d7d9","line":82,"in_reply_to":"da20952f_868a0b1a","updated":"2015-08-28 23:28:23.000000000","message":"should be in here I think but we\u0027d need a few test for it as well.","commit_id":"385d641c273e722e82297f736b4f81acfd0d68da"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"4d7bc2aad825940159a633fe86cd65d7f88214d4","unresolved":false,"context_lines":[{"line_number":79,"context_line":"     *  [{id: 2, name: \u0027B\u0027}]"},{"line_number":80,"context_line":"     *"},{"line_number":81,"context_line":"     */"},{"line_number":82,"context_line":"    function filterByIds(list, removeIdsList) {"},{"line_number":83,"context_line":"      return list.filter(filterDeletedIds);"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"      function filterDeletedIds(elem) {"}],"source_content_type":"text/javascript","patch_set":7,"id":"da20952f_868a0b1a","line":82,"in_reply_to":"da20952f_889c5a10","updated":"2015-08-28 23:24:04.000000000","message":"I can try and add this bit in the next patch on this or should it be a new patch?","commit_id":"385d641c273e722e82297f736b4f81acfd0d68da"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"4172cd85dc06d9a31d9854274d352d8faa5fba15","unresolved":false,"context_lines":[{"line_number":79,"context_line":"     *  [{id: 2, name: \u0027B\u0027}]"},{"line_number":80,"context_line":"     *"},{"line_number":81,"context_line":"     */"},{"line_number":82,"context_line":"    function filterByIds(list, removeIdsList) {"},{"line_number":83,"context_line":"      return list.filter(filterDeletedIds);"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"      function filterDeletedIds(elem) {"}],"source_content_type":"text/javascript","patch_set":7,"id":"da20952f_17ddc76e","line":82,"in_reply_to":"da20952f_889c5a10","updated":"2015-08-28 23:14:14.000000000","message":"I think this would be better as an Array.prototype function. Maybe we can create a horizon/static/horizon/js/horizon.utils.js file and put it in there. So to use, it would just be myList.intersect(otherList, key) where the intersection is the list of items that appear in both lists, aka matching items.","commit_id":"385d641c273e722e82297f736b4f81acfd0d68da"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"32770374b92cd65ca14e9697a865770d5b788afe","unresolved":false,"context_lines":[{"line_number":79,"context_line":"     *  [{id: 2, name: \u0027B\u0027}]"},{"line_number":80,"context_line":"     *"},{"line_number":81,"context_line":"     */"},{"line_number":82,"context_line":"    function filterByIds(list, removeIdsList) {"},{"line_number":83,"context_line":"      return list.filter(filterDeletedIds);"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"      function filterDeletedIds(elem) {"}],"source_content_type":"text/javascript","patch_set":7,"id":"da20952f_373faa25","line":82,"in_reply_to":"da20952f_9719d7d9","updated":"2015-08-29 00:04:40.000000000","message":"Done","commit_id":"385d641c273e722e82297f736b4f81acfd0d68da"}],"horizon/static/horizon/js/horizon.util.js":[{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"ce7ead61f6a6f11eb4d3cd15e53e1cd1c044a859","unresolved":false,"context_lines":[{"line_number":18,"context_line":"  \u0027use strict\u0027;"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"  /*eslint-disable no-extend-native */"},{"line_number":21,"context_line":"  Array.prototype.complement \u003d function(otherList, key) {"},{"line_number":22,"context_line":"    var currentList \u003d this;"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    return currentList.filter(filter);"}],"source_content_type":"text/javascript","patch_set":11,"id":"da20952f_9a149ba0","line":21,"updated":"2015-08-29 00:57:17.000000000","message":"I think this was Thai\u0027s idea. I\u0027m quite hesitant on breaking eslint rules for this.... \n\nThat said,  I think the name was Thai\u0027s idea in IRC, but this name doesn\u0027t seem right to me. This is removing elements from an array.   Google def (verb) add to (something) in a way that enhances or improves it; make perfect.  That doesn\u0027t explain to me what this does. This is removing elements.","commit_id":"dc573db85c4f97796e2afc25747e98c5be8fcaa9"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"6eb13ab859af50dc30ccf190733742c86d5f0f26","unresolved":false,"context_lines":[{"line_number":18,"context_line":"  \u0027use strict\u0027;"},{"line_number":19,"context_line":""},{"line_number":20,"context_line":"  /*eslint-disable no-extend-native */"},{"line_number":21,"context_line":"  Array.prototype.complement \u003d function(otherList, key) {"},{"line_number":22,"context_line":"    var currentList \u003d this;"},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"    return currentList.filter(filter);"}],"source_content_type":"text/javascript","patch_set":11,"id":"da20952f_ba1f1f6b","line":21,"in_reply_to":"da20952f_9a149ba0","updated":"2015-08-29 01:18:48.000000000","message":"There\u0027s the Set definition of complement which defines it as this set minus the set given. \n\nI\u0027ve renamed it to difference to avoid confusion. This is also in sync with what Underscore.js defines.\n\nAbout the ESLint violation, this can be a Angular Service in horizon/static/framework/util if that\u0027s preferred.","commit_id":"dc573db85c4f97796e2afc25747e98c5be8fcaa9"}],"openstack_dashboard/api/rest/glance.py":[{"author":{"_account_id":5623,"name":"David Lyle","email":"dklyle0@gmail.com","username":"david-lyle"},"change_message_id":"02445e416b695737dbeb1bd404c19d5c3f54f583","unresolved":false,"context_lines":[{"line_number":130,"context_line":"        This method returns HTTP 204 (no content) on success."},{"line_number":131,"context_line":"        \"\"\""},{"line_number":132,"context_line":"        for image_id in request.DATA:"},{"line_number":133,"context_line":"            api.glance.image_delete(request, image_id)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"@urls.register"}],"source_content_type":"text/x-python","patch_set":18,"id":"da20952f_0a99626e","line":133,"updated":"2015-09-02 18:04:49.000000000","message":"so for batch action we puke on the first error? That\u0027s not right. We should proceed to try the action for all in the list and collect the errors to report.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"cf1094771a6ef3436750d76b488d0b81fc0284ca","unresolved":false,"context_lines":[{"line_number":130,"context_line":"        This method returns HTTP 204 (no content) on success."},{"line_number":131,"context_line":"        \"\"\""},{"line_number":132,"context_line":"        for image_id in request.DATA:"},{"line_number":133,"context_line":"            api.glance.image_delete(request, image_id)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"@urls.register"}],"source_content_type":"text/x-python","patch_set":18,"id":"da20952f_e0aa0fd2","line":133,"in_reply_to":"da20952f_0a99626e","updated":"2015-09-02 18:32:18.000000000","message":"Basically, to keep it simple, all you need to do here is enclose the api call in a try catch block and instantiate an array to keep track of ids that failed.\n\nFor more information, here is the trace of current delete workflow.\n\nhttps://github.com/openstack/horizon/blob/master/openstack_dashboard/dashboards/project/images/images/tables.py#L115\nDeleteImage inherits from DeleteAction and overrides the delete method.\n\nhttps://github.com/openstack/horizon/blob/master/horizon/tables/actions.py#L935\nDeleteAction inherits from BatchAction and overrides the action method with the delete method.\n\nhttps://github.com/openstack/horizon/blob/master/horizon/tables/actions.py#L820\nThis is where BatchAction loops through the object _ids and invoke the delete action on each id.\n\nhttps://github.com/openstack/horizon/blob/master/horizon/tables/actions.py#L831\nThis is where they keep an array of failures to send back or log.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"408a8b97f9a577f8835b7398d6094a588ec64f4d","unresolved":false,"context_lines":[{"line_number":130,"context_line":"        This method returns HTTP 204 (no content) on success."},{"line_number":131,"context_line":"        \"\"\""},{"line_number":132,"context_line":"        for image_id in request.DATA:"},{"line_number":133,"context_line":"            api.glance.image_delete(request, image_id)"},{"line_number":134,"context_line":""},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"@urls.register"}],"source_content_type":"text/x-python","patch_set":18,"id":"da20952f_b2b6713c","line":133,"in_reply_to":"da20952f_e0aa0fd2","updated":"2015-09-03 21:45:50.000000000","message":"I\u0027ve taken this API out in favor only having a DELETE on a single image","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"}],"openstack_dashboard/static/app/core/images/actions/batch-delete.action.service.js":[{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"292625c1352823e8feb4d223c22283f18bbb61bd","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        submit(getSelectedIds(), names);"},{"line_number":75,"context_line":"      });"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"      function getSelectedNames() {"},{"line_number":78,"context_line":"        return Object.keys(selected)"},{"line_number":79,"context_line":"          .filter(function (value) {"},{"line_number":80,"context_line":"            return selected[value].checked;"}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_8f4c69c9","line":77,"updated":"2015-08-28 18:15:13.000000000","message":"nice utility functions, can probably move it outside of the open function though since you are can just pass in selected as an argument.","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"a7511580eb4022bfb08c538f7627cfb919c10e2a","unresolved":false,"context_lines":[{"line_number":74,"context_line":"        submit(getSelectedIds(), names);"},{"line_number":75,"context_line":"      });"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"      function getSelectedNames() {"},{"line_number":78,"context_line":"        return Object.keys(selected)"},{"line_number":79,"context_line":"          .filter(function (value) {"},{"line_number":80,"context_line":"            return selected[value].checked;"}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_1272bd7b","line":77,"in_reply_to":"da20952f_8f4c69c9","updated":"2015-08-28 20:30:07.000000000","message":"Done","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"a27133878da578be52ed102df376e8a4908053d6","unresolved":false,"context_lines":[{"line_number":106,"context_line":"        var message \u003d interpolate(context.success, [names]);"},{"line_number":107,"context_line":"        toast.add(\u0027success\u0027, message);"},{"line_number":108,"context_line":"        scope.$emit(events.deleteSuccess, ids);"},{"line_number":109,"context_line":"      }"},{"line_number":110,"context_line":"      function error() {"},{"line_number":111,"context_line":"        var message \u003d interpolate(context.error, [names]);"},{"line_number":112,"context_line":"        toast.add(\u0027error\u0027, message);"}],"source_content_type":"text/javascript","patch_set":14,"id":"da20952f_b257fb24","line":109,"updated":"2015-08-31 23:17:42.000000000","message":"Add whitespace here.","commit_id":"2a24dc8df1746a7987a0e9daa19116cf00e21dac"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"4d0566b46360a0b5d1788248a6c3829e1f3f1f1f","unresolved":false,"context_lines":[{"line_number":106,"context_line":"        var message \u003d interpolate(context.success, [names]);"},{"line_number":107,"context_line":"        toast.add(\u0027success\u0027, message);"},{"line_number":108,"context_line":"        scope.$emit(events.deleteSuccess, ids);"},{"line_number":109,"context_line":"      }"},{"line_number":110,"context_line":"      function error() {"},{"line_number":111,"context_line":"        var message \u003d interpolate(context.error, [names]);"},{"line_number":112,"context_line":"        toast.add(\u0027error\u0027, message);"}],"source_content_type":"text/javascript","patch_set":14,"id":"da20952f_2c8e222e","line":109,"in_reply_to":"da20952f_b257fb24","updated":"2015-09-01 06:13:06.000000000","message":"Done","commit_id":"2a24dc8df1746a7987a0e9daa19116cf00e21dac"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"a27133878da578be52ed102df376e8a4908053d6","unresolved":false,"context_lines":[{"line_number":107,"context_line":"        toast.add(\u0027success\u0027, message);"},{"line_number":108,"context_line":"        scope.$emit(events.deleteSuccess, ids);"},{"line_number":109,"context_line":"      }"},{"line_number":110,"context_line":"      function error() {"},{"line_number":111,"context_line":"        var message \u003d interpolate(context.error, [names]);"},{"line_number":112,"context_line":"        toast.add(\u0027error\u0027, message);"},{"line_number":113,"context_line":"      }"}],"source_content_type":"text/javascript","patch_set":14,"id":"da20952f_723403fb","line":110,"updated":"2015-08-31 23:17:42.000000000","message":"Missing code coverage here.","commit_id":"2a24dc8df1746a7987a0e9daa19116cf00e21dac"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"4d0566b46360a0b5d1788248a6c3829e1f3f1f1f","unresolved":false,"context_lines":[{"line_number":107,"context_line":"        toast.add(\u0027success\u0027, message);"},{"line_number":108,"context_line":"        scope.$emit(events.deleteSuccess, ids);"},{"line_number":109,"context_line":"      }"},{"line_number":110,"context_line":"      function error() {"},{"line_number":111,"context_line":"        var message \u003d interpolate(context.error, [names]);"},{"line_number":112,"context_line":"        toast.add(\u0027error\u0027, message);"},{"line_number":113,"context_line":"      }"}],"source_content_type":"text/javascript","patch_set":14,"id":"da20952f_8c7f2e14","line":110,"in_reply_to":"da20952f_723403fb","updated":"2015-09-01 06:13:06.000000000","message":"Done","commit_id":"2a24dc8df1746a7987a0e9daa19116cf00e21dac"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"96dd8f0220e6acc4b737dfed5992d9e485964d40","unresolved":false,"context_lines":[{"line_number":71,"context_line":"      var names \u003d getSelectedAttr(selected, \u0027name\u0027).join(\"\\\", \\\"\");"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"      confirmDelete(names, function() {"},{"line_number":74,"context_line":"        submit(getSelectedAttr(selected, \u0027id\u0027), getSelectedAttr(selected, \u0027name\u0027).join(\", \"));"},{"line_number":75,"context_line":"      });"},{"line_number":76,"context_line":"    }"},{"line_number":77,"context_line":""}],"source_content_type":"text/javascript","patch_set":17,"id":"da20952f_ffc89caa","line":74,"updated":"2015-09-01 23:33:29.000000000","message":"We are you running the same function twice?","commit_id":"73b15b28139acbcba050961d61c223aa6268fc05"},{"author":{"_account_id":17004,"name":"KBrown","email":"kbrown@thoughtworks.com","username":"kbrown"},"change_message_id":"d2d6736b23aebd5ef263d78e34742cfb2725a465","unresolved":false,"context_lines":[{"line_number":71,"context_line":"      var names \u003d getSelectedAttr(selected, \u0027name\u0027).join(\"\\\", \\\"\");"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"      confirmDelete(names, function() {"},{"line_number":74,"context_line":"        submit(getSelectedAttr(selected, \u0027id\u0027), getSelectedAttr(selected, \u0027name\u0027).join(\", \"));"},{"line_number":75,"context_line":"      });"},{"line_number":76,"context_line":"    }"},{"line_number":77,"context_line":""}],"source_content_type":"text/javascript","patch_set":17,"id":"da20952f_da78462e","line":74,"in_reply_to":"da20952f_ffc89caa","updated":"2015-09-02 00:07:21.000000000","message":"Done","commit_id":"73b15b28139acbcba050961d61c223aa6268fc05"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"210345ac584d72bf4ac0363642f9625d742243cf","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"    // delete selected image objects"},{"line_number":70,"context_line":"    function open(selected) {"},{"line_number":71,"context_line":"      var names \u003d getSelectedAttr(selected, \u0027name\u0027);"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"      confirmDelete(names.join(\"\\\", \\\"\"), function() {"},{"line_number":74,"context_line":"        submit(getSelectedAttr(selected, \u0027id\u0027), names.join(\", \"));"}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_f50bb87b","line":71,"updated":"2015-09-02 17:59:33.000000000","message":"I think it might be clearer to combine open and simpleModal.modal together because that is where the \"open\" logic happens. This way, you don\u0027t have to pass in a callback function that makes it look complicated.\n\nI believe confirmDelete was needed in my deleteService because it handles both batch and single deletes. I\u0027m not entirely convinced we need 2 different services for deletes either since they are very similar. At the minimum, one can DI inherit from another to reduce the code duplication.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"408a8b97f9a577f8835b7398d6094a588ec64f4d","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"    // delete selected image objects"},{"line_number":70,"context_line":"    function open(selected) {"},{"line_number":71,"context_line":"      var names \u003d getSelectedAttr(selected, \u0027name\u0027);"},{"line_number":72,"context_line":""},{"line_number":73,"context_line":"      confirmDelete(names.join(\"\\\", \\\"\"), function() {"},{"line_number":74,"context_line":"        submit(getSelectedAttr(selected, \u0027id\u0027), names.join(\", \"));"}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_b2e4313c","line":71,"in_reply_to":"da20952f_f50bb87b","updated":"2015-09-03 21:45:50.000000000","message":"This code has now moved closer to what a Single delete image does. I\u0027ll reuse this service or repurpose this handle both cases. Would that be ok?\n\nAlternately, I could add the single image delete to this patch and abandon the subsequent one.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"ce9f74681d7ac30faa2cebb89618872bbef3bd02","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        .map(function (value) {"},{"line_number":81,"context_line":"          return {id: selected[value].item.id, name: selected[value].item.name};"},{"line_number":82,"context_line":"        });"},{"line_number":83,"context_line":"    }"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    function confirmDelete(images) {"},{"line_number":86,"context_line":"      var options \u003d {"}],"source_content_type":"text/javascript","patch_set":20,"id":"da20952f_5a710d0b","line":83,"updated":"2015-09-04 18:32:24.000000000","message":"nit: add an inline name to the above, for debugging and to meet the style guide.","commit_id":"ba722dd0581fd46c032d8c744126d6b880d97954"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"2b12268c202658470a7287afc05f54bc8d2e9d4d","unresolved":false,"context_lines":[{"line_number":80,"context_line":"        .map(function (value) {"},{"line_number":81,"context_line":"          return {id: selected[value].item.id, name: selected[value].item.name};"},{"line_number":82,"context_line":"        });"},{"line_number":83,"context_line":"    }"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    function confirmDelete(images) {"},{"line_number":86,"context_line":"      var options \u003d {"}],"source_content_type":"text/javascript","patch_set":20,"id":"da20952f_6bdf4ed6","line":83,"in_reply_to":"da20952f_5a710d0b","updated":"2015-09-05 05:50:18.000000000","message":"Done","commit_id":"ba722dd0581fd46c032d8c744126d6b880d97954"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"ce9f74681d7ac30faa2cebb89618872bbef3bd02","unresolved":false,"context_lines":[{"line_number":115,"context_line":"          return deferred.promise;"},{"line_number":116,"context_line":"        }"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"        function notify() {"},{"line_number":119,"context_line":"          notifySuccess(imagesDeletedSuccess, deletedImageIds);"},{"line_number":120,"context_line":"          notifyError(imagesDeletedFailed);"},{"line_number":121,"context_line":"        }"}],"source_content_type":"text/javascript","patch_set":20,"id":"da20952f_93ec6abc","line":118,"updated":"2015-09-04 18:32:24.000000000","message":"Question, just to confirm your intent.  You created two separate messages because this effects the styling (red vs green) for the pop up message right?  I think that makes sense.","commit_id":"ba722dd0581fd46c032d8c744126d6b880d97954"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"2b12268c202658470a7287afc05f54bc8d2e9d4d","unresolved":false,"context_lines":[{"line_number":115,"context_line":"          return deferred.promise;"},{"line_number":116,"context_line":"        }"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":"        function notify() {"},{"line_number":119,"context_line":"          notifySuccess(imagesDeletedSuccess, deletedImageIds);"},{"line_number":120,"context_line":"          notifyError(imagesDeletedFailed);"},{"line_number":121,"context_line":"        }"}],"source_content_type":"text/javascript","patch_set":20,"id":"da20952f_cbe45aa9","line":118,"in_reply_to":"da20952f_93ec6abc","updated":"2015-09-05 05:50:18.000000000","message":"Yes. If there\u0027s nothing to show then that message won\u0027t show. That logic is in the method.","commit_id":"ba722dd0581fd46c032d8c744126d6b880d97954"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"219c1698c54ba473ddcb7841fed4e1d4c2621254","unresolved":false,"context_lines":[{"line_number":89,"context_line":"        submit: context.submit"},{"line_number":90,"context_line":"      };"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"      simpleModal.modal(options).result.then(function() {"},{"line_number":93,"context_line":"        var deletedImageIds \u003d [];"},{"line_number":94,"context_line":"        var imagesDeletedSuccess \u003d [];"},{"line_number":95,"context_line":"        var imagesDeletedFailed \u003d [];"}],"source_content_type":"text/javascript","patch_set":28,"id":"9a1a9d01_c8c2f284","line":92,"updated":"2015-09-30 22:30:36.000000000","message":"move big anonymous functions out and name it.","commit_id":"8248308e50ca2b75364247c73dc1aa6adb4983ee"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"743c2aaec63c2b71359a092f2a28b9d2a13010f3","unresolved":false,"context_lines":[{"line_number":89,"context_line":"        submit: context.submit"},{"line_number":90,"context_line":"      };"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"      simpleModal.modal(options).result.then(function() {"},{"line_number":93,"context_line":"        var deletedImageIds \u003d [];"},{"line_number":94,"context_line":"        var imagesDeletedSuccess \u003d [];"},{"line_number":95,"context_line":"        var imagesDeletedFailed \u003d [];"}],"source_content_type":"text/javascript","patch_set":28,"id":"9a1a9d01_be11f453","line":92,"in_reply_to":"9a1a9d01_c8c2f284","updated":"2015-09-30 23:49:33.000000000","message":"Done","commit_id":"8248308e50ca2b75364247c73dc1aa6adb4983ee"},{"author":{"_account_id":11778,"name":"Diana Whitten","email":"hurgleburgler@gmail.com","username":"hurgleburgler"},"change_message_id":"b4beba94f2123e808d02e40723e2dfa6640e5b7a","unresolved":false,"context_lines":[{"line_number":57,"context_line":"      open: open"},{"line_number":58,"context_line":"    };"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"    return service;"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    //////////////"},{"line_number":63,"context_line":""}],"source_content_type":"text/javascript","patch_set":39,"id":"5a2ca52d_cfa1bcf9","line":60,"updated":"2015-10-16 23:08:53.000000000","message":"why is this return floating in the middle of the function?","commit_id":"c46a1667273299b70e143d19299ddc938035e895"},{"author":{"_account_id":15742,"name":"Paulo Ewerton Gomes Fragoso","email":"pauloewerton@lsd.ufcg.edu.br","username":"pauloewerton"},"change_message_id":"8d91d1de4991395f39c23517a5f1626284e20502","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"    function getSelectedImages(selected) {"},{"line_number":70,"context_line":"      return Object.keys(selected)"},{"line_number":71,"context_line":"        .filter(function (value) {"},{"line_number":72,"context_line":"          return selected[value].checked;"},{"line_number":73,"context_line":"        })"},{"line_number":74,"context_line":"        .map(function (value) {"}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_e72674cd","line":71,"updated":"2015-11-10 15:14:33.000000000","message":"nit: anonymous function","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":18508,"name":"Errol Pais","email":"errol.pais@protonmail.com","username":"errol"},"change_message_id":"3a61d335e90e14bae1148c1c09385b10a3625b5f","unresolved":false,"context_lines":[{"line_number":68,"context_line":""},{"line_number":69,"context_line":"    function getSelectedImages(selected) {"},{"line_number":70,"context_line":"      return Object.keys(selected)"},{"line_number":71,"context_line":"        .filter(function (value) {"},{"line_number":72,"context_line":"          return selected[value].checked;"},{"line_number":73,"context_line":"        })"},{"line_number":74,"context_line":"        .map(function (value) {"}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_f29138f2","line":71,"in_reply_to":"da85f559_e72674cd","updated":"2015-11-11 21:51:19.000000000","message":"Done","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":10442,"name":"Masco Kaliyamoorthy","email":"mkaliyam@redhat.com","username":"masco"},"change_message_id":"5c29a5e35c9597b4bfb7de223dc70445059203f6","unresolved":false,"context_lines":[{"line_number":34,"context_line":"   * On cancel, do nothing."},{"line_number":35,"context_line":"   */"},{"line_number":36,"context_line":"  function batchDeleteService(deleteImageService, gettext) {"},{"line_number":37,"context_line":"    var scope;"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    var context \u003d {"},{"line_number":40,"context_line":"      title: gettext(\u0027Confirm Delete Images\u0027),"}],"source_content_type":"text/javascript","patch_set":63,"id":"9a8ffd7b_6eb8a111","line":37,"updated":"2015-11-30 09:22:09.000000000","message":"scope is unused.","commit_id":"e4eee680df70ab9470cdf1fced94296a08e0f1dc"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"31900e94e0e83a21b1bf2285b7452ac4ee1599d3","unresolved":false,"context_lines":[{"line_number":34,"context_line":"   * On cancel, do nothing."},{"line_number":35,"context_line":"   */"},{"line_number":36,"context_line":"  function batchDeleteService(deleteImageService, gettext) {"},{"line_number":37,"context_line":"    var scope;"},{"line_number":38,"context_line":""},{"line_number":39,"context_line":"    var context \u003d {"},{"line_number":40,"context_line":"      title: gettext(\u0027Confirm Delete Images\u0027),"}],"source_content_type":"text/javascript","patch_set":63,"id":"9a8ffd7b_f408ad2f","line":37,"in_reply_to":"9a8ffd7b_6eb8a111","updated":"2015-12-01 05:02:49.000000000","message":"Done","commit_id":"e4eee680df70ab9470cdf1fced94296a08e0f1dc"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":41,"context_line":"      /* eslint-enable max-len */"},{"line_number":42,"context_line":"      submit: gettext(\u0027Delete Images\u0027),"},{"line_number":43,"context_line":"      success: gettext(\u0027Deleted Images: %s.\u0027),"},{"line_number":44,"context_line":"      error: gettext(\u0027Unable to delete Images: %s.\u0027)"},{"line_number":45,"context_line":"    };"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    var service \u003d {"}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_c63f1124","line":44,"updated":"2015-12-03 23:57:44.000000000","message":"For multiselect, the error text is different from django horizon when the user has selected an image they aren\u0027t actually allowed to delete. It is slightly more descriptive.\n This form: \"Unable to delete Images\" regardless of reason.\n Django form: \"You are not allowed to delete image: test-v2-api-image-protected.\"\n\nBoth the django table and the angular table allow the user to select the row and press delete even if some of the images can\u0027t be deleted.  I assume this is due to there being the possibiliy of multiple multi-select actions, so you can\u0027t remove the checkbox.\n\nThe django one hits this code after the user clicks submit on the confirmation dialog, but before calling delete on the Glance API.\n\nhttps://github.com/openstack/horizon/blob/d38bb868da15acde3ce50dfc9aeb3cacc0c697c5/openstack_dashboard/dashboards/project/images/images/tables.py#L106-L113\n\nAdded notes to https://review.openstack.org/#/c/217422/72/openstack_dashboard/static/app/core/images/actions/delete-image.service.js","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"e575c6cb485a7c846751087265c2ef073b78d898","unresolved":false,"context_lines":[{"line_number":41,"context_line":"      /* eslint-enable max-len */"},{"line_number":42,"context_line":"      submit: gettext(\u0027Delete Images\u0027),"},{"line_number":43,"context_line":"      success: gettext(\u0027Deleted Images: %s.\u0027),"},{"line_number":44,"context_line":"      error: gettext(\u0027Unable to delete Images: %s.\u0027)"},{"line_number":45,"context_line":"    };"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    var service \u003d {"}],"source_content_type":"text/javascript","patch_set":84,"id":"5a710552_826588e2","line":44,"updated":"2015-12-14 19:31:16.000000000","message":"What are your plans to address my comments from patchset 72? Copied below.\n\nFor multiselect, the error text is different from django horizon when the user has selected an image they aren\u0027t actually allowed to delete. It is slightly more descriptive. In addition, it reduces API calls to glance.\n\n This form: \"Unable to delete Images\" regardless of reason.\n Django form: \"You are not allowed to delete image: test-v2-api-image-protected.\"\n\nBoth the django table and the angular table allow the user to select the row and press delete even if some of the images can\u0027t be deleted. I assume this is due to there being the possibiliy of multiple multi-select actions, so you can\u0027t remove the checkbox.\n\nThe django one hits this code after the user clicks submit on the confirmation dialog, but before calling delete on the Glance API.\n\nhttps://github.com/openstack/horizon/blob/d38bb868da15acde3ce50dfc9aeb3cacc0c697c5/openstack_dashboard/dashboards/project/images/images/tables.py#L106-L113\n\nAdded notes to https://review.openstack.org/#/c/217422/72/openstack_dashboard/static/app/core/images/actions/delete-image.service.js","commit_id":"cff1f7c89a22092bc0dee2be800e71797a018759"},{"author":{"_account_id":15424,"name":"javeme","email":"javaloveme@gmail.com","username":"javeme"},"change_message_id":"cd4a51592ff6f5242a2c6ef63772a23ebd96ee66","unresolved":false,"context_lines":[{"line_number":74,"context_line":"      return policy.ifAllowed({ rules: [[\u0027image\u0027, \u0027delete_image\u0027]] });"},{"line_number":75,"context_line":"    }"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    function getSelectedImages(selected) {"},{"line_number":78,"context_line":"      return Object.keys(selected)"},{"line_number":79,"context_line":"        .filter(function isChecked(value) {"},{"line_number":80,"context_line":"          return selected[value].checked;"}],"source_content_type":"text/javascript","patch_set":97,"id":"1a7b0d38_77b00944","line":77,"range":{"start_line":77,"start_character":13,"end_line":77,"end_character":30},"updated":"2015-12-24 16:32:35.000000000","message":"this may be as a public common method that can be used by instances/volumes...","commit_id":"747faa769da99e96450aee8345f0f7d71756d624"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"c6ef3b3d6627c745b4750597421d7e3e7ec7d780","unresolved":false,"context_lines":[{"line_number":74,"context_line":"      return policy.ifAllowed({ rules: [[\u0027image\u0027, \u0027delete_image\u0027]] });"},{"line_number":75,"context_line":"    }"},{"line_number":76,"context_line":""},{"line_number":77,"context_line":"    function getSelectedImages(selected) {"},{"line_number":78,"context_line":"      return Object.keys(selected)"},{"line_number":79,"context_line":"        .filter(function isChecked(value) {"},{"line_number":80,"context_line":"          return selected[value].checked;"}],"source_content_type":"text/javascript","patch_set":97,"id":"1a7b0d38_dbf23f6f","line":77,"range":{"start_line":77,"start_character":13,"end_line":77,"end_character":30},"in_reply_to":"1a7b0d38_77b00944","updated":"2015-12-25 07:44:48.000000000","message":"I tried making it a common public method - via the directive and then a service but the resultant complexity isn\u0027t worth the cost.\n\nIf you\u0027ve something in mind, do let me know.","commit_id":"747faa769da99e96450aee8345f0f7d71756d624"},{"author":{"_account_id":12071,"name":"Richard Jones","email":"r1chardj0n3s@gmail.com","username":"richard"},"change_message_id":"6aebb379adff7fdf092d0ad8a96535c34eee1fdc","unresolved":false,"context_lines":[{"line_number":42,"context_line":"    var context \u003d {"},{"line_number":43,"context_line":"      title: gettext(\u0027Confirm Delete Images\u0027),"},{"line_number":44,"context_line":"      /* eslint-disable max-len */"},{"line_number":45,"context_line":"      message: gettext(\u0027You have selected \"%s\". Please confirm your selection. Deleted images are not recoverable.\u0027),"},{"line_number":46,"context_line":"      /* eslint-enable max-len */"},{"line_number":47,"context_line":"      submit: gettext(\u0027Delete Images\u0027),"},{"line_number":48,"context_line":"      success: gettext(\u0027Deleted Images: %s.\u0027),"}],"source_content_type":"text/javascript","patch_set":102,"id":"fa69d971_6652fc36","line":45,"updated":"2016-01-07 06:24:49.000000000","message":"I have a concern that these places with the items substitutions (it took me a while to figure out how the substitution was actually being done, which I think is a problem with the increasing complexity of this code) could run into serious trouble with a tens of images being deleted at once.","commit_id":"5f134d3281235d4d93b20d926e3daf9f8b964d02"}],"openstack_dashboard/static/app/core/images/actions/batch-delete.action.service.spec.js":[{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"210345ac584d72bf4ac0363642f9625d742243cf","unresolved":false,"context_lines":[{"line_number":170,"context_line":"      };"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"      service.initScope($scope);"},{"line_number":173,"context_line":""},{"line_number":174,"context_line":"      service.open(selected);"},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"      $scope.$apply();"}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_76c48e3f","line":173,"updated":"2015-09-02 17:59:33.000000000","message":"I\u0027m generally not a big fan of empty lines, but i also don\u0027t want to dictate it. I normally use them to separate logical parts or for emphasis, but here, the emphasis is lost when every other line is spaced out. I won\u0027t dictate this since we don\u0027t have a code format or styles guide for it, so its an optional thing.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"408a8b97f9a577f8835b7398d6094a588ec64f4d","unresolved":false,"context_lines":[{"line_number":170,"context_line":"      };"},{"line_number":171,"context_line":""},{"line_number":172,"context_line":"      service.initScope($scope);"},{"line_number":173,"context_line":""},{"line_number":174,"context_line":"      service.open(selected);"},{"line_number":175,"context_line":""},{"line_number":176,"context_line":"      $scope.$apply();"}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_92d6cd4d","line":173,"in_reply_to":"da20952f_76c48e3f","updated":"2015-09-03 21:45:50.000000000","message":"Done","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":5623,"name":"David Lyle","email":"dklyle0@gmail.com","username":"david-lyle"},"change_message_id":"02445e416b695737dbeb1bd404c19d5c3f54f583","unresolved":false,"context_lines":[{"line_number":179,"context_line":"      expect($scope.$emit).not.toHaveBeenCalled();"},{"line_number":180,"context_line":"    });"},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"  });"},{"line_number":183,"context_line":""},{"line_number":184,"context_line":"})();"}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_4a043a7d","line":182,"updated":"2015-09-02 18:04:49.000000000","message":"a test case to handle 1 in many failing would be beneficial.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"408a8b97f9a577f8835b7398d6094a588ec64f4d","unresolved":false,"context_lines":[{"line_number":179,"context_line":"      expect($scope.$emit).not.toHaveBeenCalled();"},{"line_number":180,"context_line":"    });"},{"line_number":181,"context_line":""},{"line_number":182,"context_line":"  });"},{"line_number":183,"context_line":""},{"line_number":184,"context_line":"})();"}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_f2c5c98d","line":182,"in_reply_to":"da20952f_4a043a7d","updated":"2015-09-03 21:45:50.000000000","message":"Done","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"}],"openstack_dashboard/static/app/core/images/actions/delete-image.service.js":[{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":57,"context_line":""},{"line_number":58,"context_line":"    function open(images) {"},{"line_number":59,"context_line":""},{"line_number":60,"context_line":"      context.deleteEntity \u003d function deleteEntity(image) {"},{"line_number":61,"context_line":"        return glance.deleteImage(image, true);"},{"line_number":62,"context_line":"      };"},{"line_number":63,"context_line":""}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_e6d80df2","line":60,"updated":"2015-12-03 23:57:44.000000000","message":"Because of multi-select it would be ideal if this checked whether or not the selected images could be deleted.  The workflow could even check it first before putting up the confirmation dialog and instead put up a message of the images images in the selection that can\u0027t be deleted.\n\nSee my note here: https://review.openstack.org/#/c/217422/72/openstack_dashboard/static/app/core/images/actions/batch-delete.action.service.js","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"}],"openstack_dashboard/static/app/core/images/images.module.js":[{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"76ea9067d6cc22b35c9e1f8ffa4454d2c0ecbb6c","unresolved":false,"context_lines":[{"line_number":42,"context_line":"   */"},{"line_number":43,"context_line":"  function events() {"},{"line_number":44,"context_line":"    return {"},{"line_number":45,"context_line":"      deleteSuccess: \u0027images.deleteSuccess\u0027"},{"line_number":46,"context_line":"    };"},{"line_number":47,"context_line":"  }"},{"line_number":48,"context_line":""}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_1d4bd7b1","line":45,"updated":"2015-08-28 06:30:28.000000000","message":"I\u0027d just go ahead and fully qualify this as horizon.app.core.images.events.","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"292625c1352823e8feb4d223c22283f18bbb61bd","unresolved":false,"context_lines":[{"line_number":42,"context_line":"   */"},{"line_number":43,"context_line":"  function events() {"},{"line_number":44,"context_line":"    return {"},{"line_number":45,"context_line":"      deleteSuccess: \u0027images.deleteSuccess\u0027"},{"line_number":46,"context_line":"    };"},{"line_number":47,"context_line":"  }"},{"line_number":48,"context_line":""}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_4f2df1fc","line":45,"in_reply_to":"da20952f_1d4bd7b1","updated":"2015-08-28 18:15:13.000000000","message":"Right, you can name it whatever you like, the more details the better. That was the primary reason I switched to it be a map. I should update my own event list as well :P","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"a7511580eb4022bfb08c538f7627cfb919c10e2a","unresolved":false,"context_lines":[{"line_number":42,"context_line":"   */"},{"line_number":43,"context_line":"  function events() {"},{"line_number":44,"context_line":"    return {"},{"line_number":45,"context_line":"      deleteSuccess: \u0027images.deleteSuccess\u0027"},{"line_number":46,"context_line":"    };"},{"line_number":47,"context_line":"  }"},{"line_number":48,"context_line":""}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_b20191b1","line":45,"in_reply_to":"da20952f_4f2df1fc","updated":"2015-08-28 20:30:07.000000000","message":"Done","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":27,"context_line":"   */"},{"line_number":28,"context_line":"  angular"},{"line_number":29,"context_line":"    .module(\u0027horizon.app.core.images\u0027, [])"},{"line_number":30,"context_line":"    .value(\u0027horizon.app.core.images.events\u0027, events())"},{"line_number":31,"context_line":"    .config(config);"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"  config.$inject \u003d ["}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_19b9fee9","line":30,"updated":"2015-12-03 23:57:44.000000000","message":"See Sean\u0027s comments here.  We should go for consistency with Thai\u0027s patch. So need to ensure both are doing similar.\n\nhttps://review.openstack.org/#/c/222297/22/openstack_dashboard/dashboards/identity/static/dashboard/identity/users/users.module.js\n\nI think it is good advice. This is a constant, so .constant would seem to make sense here instead of .value.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":42,"context_line":"   */"},{"line_number":43,"context_line":"  function events() {"},{"line_number":44,"context_line":"    return {"},{"line_number":45,"context_line":"      deleteSuccess: \u0027horizon.app.core.images.deleteSuccess\u0027"},{"line_number":46,"context_line":"    };"},{"line_number":47,"context_line":"  }"},{"line_number":48,"context_line":""}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_99c16e31","line":45,"updated":"2015-12-03 23:57:44.000000000","message":"Also see notes on all caps in review linked above.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"}],"openstack_dashboard/static/app/core/images/table/batch-actions.service.js":[{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"292625c1352823e8feb4d223c22283f18bbb61bd","unresolved":false,"context_lines":[{"line_number":28,"context_line":"  /**"},{"line_number":29,"context_line":"   * @ngdoc factory"},{"line_number":30,"context_line":"   * @name horizon.app.core.images.table.batch-actions.service"},{"line_number":31,"context_line":"   * @description A list of table batch actions."},{"line_number":32,"context_line":"   */"},{"line_number":33,"context_line":"  function tableBatchActions(deleteService) {"},{"line_number":34,"context_line":""}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_4ff09167","line":31,"updated":"2015-08-28 18:15:13.000000000","message":"A list of table batch actions for the images table? Not so sure this belongs in core. I can see that we plan on re-using actions like delete, create, etc..., but not so sure if the batch actions are re-usable enough to put into core.","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"a7511580eb4022bfb08c538f7627cfb919c10e2a","unresolved":false,"context_lines":[{"line_number":28,"context_line":"  /**"},{"line_number":29,"context_line":"   * @ngdoc factory"},{"line_number":30,"context_line":"   * @name horizon.app.core.images.table.batch-actions.service"},{"line_number":31,"context_line":"   * @description A list of table batch actions."},{"line_number":32,"context_line":"   */"},{"line_number":33,"context_line":"  function tableBatchActions(deleteService) {"},{"line_number":34,"context_line":""}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_525a752b","line":31,"in_reply_to":"da20952f_1e0de9e7","updated":"2015-08-28 20:30:07.000000000","message":"Would it help if we started on a patch for an images table on the Admin dashboard which could help crystalize what belongs where?","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"eb541b5591e7caeddfeb00014f6cecf9ef6a7882","unresolved":false,"context_lines":[{"line_number":28,"context_line":"  /**"},{"line_number":29,"context_line":"   * @ngdoc factory"},{"line_number":30,"context_line":"   * @name horizon.app.core.images.table.batch-actions.service"},{"line_number":31,"context_line":"   * @description A list of table batch actions."},{"line_number":32,"context_line":"   */"},{"line_number":33,"context_line":"  function tableBatchActions(deleteService) {"},{"line_number":34,"context_line":""}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_1e0de9e7","line":31,"in_reply_to":"da20952f_4ff09167","updated":"2015-08-28 19:44:12.000000000","message":"Thai, the images table is in core, so not sure why this wouldn\u0027t be here.\n\nWe discussed at the meetup and debated on this.  Since images are a core service of the dashboard and will be shared between project and admin dashboard, we didn\u0027t want to put it in the project only dashboard. Not seeing how it would make sense to have images table in core, but not the actions?","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"219c1698c54ba473ddcb7841fed4e1d4c2621254","unresolved":false,"context_lines":[{"line_number":37,"context_line":"      deleted: deleteService"},{"line_number":38,"context_line":"    };"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    return service;"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    ///////////////"},{"line_number":43,"context_line":""}],"source_content_type":"text/javascript","patch_set":28,"id":"9a1a9d01_e87a5676","line":40,"updated":"2015-09-30 22:30:36.000000000","message":"strangely, npm threshold says i was below the threshold for this. https://review.openstack.org/#/c/222297/8/openstack_dashboard/dashboards/identity/static/dashboard/identity/users/table/table.batch-actions.service.spec.js\n\nIf we abstract out the initScope logic into a parent service, then writing test for it only need to happen once.","commit_id":"8248308e50ca2b75364247c73dc1aa6adb4983ee"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"743c2aaec63c2b71359a092f2a28b9d2a13010f3","unresolved":false,"context_lines":[{"line_number":37,"context_line":"      deleted: deleteService"},{"line_number":38,"context_line":"    };"},{"line_number":39,"context_line":""},{"line_number":40,"context_line":"    return service;"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"    ///////////////"},{"line_number":43,"context_line":""}],"source_content_type":"text/javascript","patch_set":28,"id":"9a1a9d01_fe6f6cc1","line":40,"in_reply_to":"9a1a9d01_e87a5676","updated":"2015-09-30 23:49:33.000000000","message":"I see it covered.","commit_id":"8248308e50ca2b75364247c73dc1aa6adb4983ee"},{"author":{"_account_id":15742,"name":"Paulo Ewerton Gomes Fragoso","email":"pauloewerton@lsd.ufcg.edu.br","username":"pauloewerton"},"change_message_id":"8d91d1de4991395f39c23517a5f1626284e20502","unresolved":false,"context_lines":[{"line_number":58,"context_line":"    function initScope(scope) {"},{"line_number":59,"context_line":"      // pass child scope onto actions"},{"line_number":60,"context_line":"      // so that actions can emit events"},{"line_number":61,"context_line":"      angular.forEach(service, function(action) {"},{"line_number":62,"context_line":"        if (action.initScope) {"},{"line_number":63,"context_line":"          action.initScope(scope.$new());"},{"line_number":64,"context_line":"        }"}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_623832a1","line":61,"updated":"2015-11-10 15:14:33.000000000","message":"nit: anonymous function","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":18508,"name":"Errol Pais","email":"errol.pais@protonmail.com","username":"errol"},"change_message_id":"3a61d335e90e14bae1148c1c09385b10a3625b5f","unresolved":false,"context_lines":[{"line_number":58,"context_line":"    function initScope(scope) {"},{"line_number":59,"context_line":"      // pass child scope onto actions"},{"line_number":60,"context_line":"      // so that actions can emit events"},{"line_number":61,"context_line":"      angular.forEach(service, function(action) {"},{"line_number":62,"context_line":"        if (action.initScope) {"},{"line_number":63,"context_line":"          action.initScope(scope.$new());"},{"line_number":64,"context_line":"        }"}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_f2a85822","line":61,"in_reply_to":"da85f559_623832a1","updated":"2015-11-11 21:51:19.000000000","message":"Done","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":1,"context_line":"/**"},{"line_number":2,"context_line":" * Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":3,"context_line":" * not use this file except in compliance with the License. You may obtain"},{"line_number":4,"context_line":" * a copy of the License at"}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_3912bab5","line":1,"updated":"2015-12-03 23:57:44.000000000","message":"Copyright should be here and the other files.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":37,"context_line":"    policy"},{"line_number":38,"context_line":"  ) {"},{"line_number":39,"context_line":"    var actions \u003d [{"},{"line_number":40,"context_line":"      callback: \u0027table.batchActions.delete.open\u0027,"},{"line_number":41,"context_line":"      template: {"},{"line_number":42,"context_line":"        type: \u0027delete-selected\u0027,"},{"line_number":43,"context_line":"        text: gettext(\u0027Delete Images\u0027)"}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_d7749dd0","line":40,"updated":"2015-12-03 23:57:44.000000000","message":"Please see my comments on the rowActions service and apply here respectively.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":15424,"name":"javeme","email":"javaloveme@gmail.com","username":"javeme"},"change_message_id":"cd4a51592ff6f5242a2c6ef63772a23ebd96ee66","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    ///////////////"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    function initScope(scope) {"},{"line_number":46,"context_line":"      angular.forEach([deleteService], setActionScope);"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"      function setActionScope(action) {"},{"line_number":49,"context_line":"        action.initScope(scope.$new());"}],"source_content_type":"text/javascript","patch_set":97,"id":"1a7b0d38_e1cd1bb8","line":46,"range":{"start_line":46,"start_character":23,"end_line":46,"end_character":36},"updated":"2015-12-24 16:32:35.000000000","message":"better to automatically collect this actions like this: [action.service for action in actions()], or add a function like initActions(scope):\n\nangular.forEach(actions(), function(action){\n  action.service.initScope(...));\n});","commit_id":"747faa769da99e96450aee8345f0f7d71756d624"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"c6ef3b3d6627c745b4750597421d7e3e7ec7d780","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    ///////////////"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    function initScope(scope) {"},{"line_number":46,"context_line":"      angular.forEach([deleteService], setActionScope);"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"      function setActionScope(action) {"},{"line_number":49,"context_line":"        action.initScope(scope.$new());"}],"source_content_type":"text/javascript","patch_set":97,"id":"1a7b0d38_fbfdbb3a","line":46,"range":{"start_line":46,"start_character":23,"end_line":46,"end_character":36},"in_reply_to":"1a7b0d38_e1cd1bb8","updated":"2015-12-25 07:44:48.000000000","message":"Not all Services need to called initScope on. There\u0027s a couple of patches that depend on this that add more actions where it\u0027s not needed.","commit_id":"747faa769da99e96450aee8345f0f7d71756d624"}],"openstack_dashboard/static/app/core/images/table/batch-actions.service.spec.js":[{"author":{"_account_id":15742,"name":"Paulo Ewerton Gomes Fragoso","email":"pauloewerton@lsd.ufcg.edu.br","username":"pauloewerton"},"change_message_id":"8d91d1de4991395f39c23517a5f1626284e20502","unresolved":false,"context_lines":[{"line_number":31,"context_line":"    ///////////////////////"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    beforeEach(module(\u0027ui.bootstrap\u0027));"},{"line_number":34,"context_line":"    beforeEach(module(\u0027horizon.framework\u0027));"},{"line_number":35,"context_line":"    beforeEach(module(\u0027horizon.app.core\u0027));"},{"line_number":36,"context_line":"    beforeEach(module(\u0027horizon.app.core.images\u0027));"},{"line_number":37,"context_line":""}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_e24c2244","line":34,"updated":"2015-11-10 15:14:33.000000000","message":"can you use only horizon.framework","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":18508,"name":"Errol Pais","email":"errol.pais@protonmail.com","username":"errol"},"change_message_id":"3a61d335e90e14bae1148c1c09385b10a3625b5f","unresolved":false,"context_lines":[{"line_number":31,"context_line":"    ///////////////////////"},{"line_number":32,"context_line":""},{"line_number":33,"context_line":"    beforeEach(module(\u0027ui.bootstrap\u0027));"},{"line_number":34,"context_line":"    beforeEach(module(\u0027horizon.framework\u0027));"},{"line_number":35,"context_line":"    beforeEach(module(\u0027horizon.app.core\u0027));"},{"line_number":36,"context_line":"    beforeEach(module(\u0027horizon.app.core.images\u0027));"},{"line_number":37,"context_line":""}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_55e7ce10","line":34,"in_reply_to":"da85f559_e24c2244","updated":"2015-11-11 21:51:19.000000000","message":"Done","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":10442,"name":"Masco Kaliyamoorthy","email":"mkaliyam@redhat.com","username":"masco"},"change_message_id":"5c29a5e35c9597b4bfb7de223dc70445059203f6","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    var service;"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    var policyAPI \u003d {"},{"line_number":22,"context_line":"      ifAllowed: function(rules) {"},{"line_number":23,"context_line":"        return {"},{"line_number":24,"context_line":"          success: function(callback) {"},{"line_number":25,"context_line":"            callback({allowed: true});"}],"source_content_type":"text/javascript","patch_set":63,"id":"9a8ffd7b_8efce5b8","line":22,"updated":"2015-11-30 09:22:09.000000000","message":"rules is unused.","commit_id":"e4eee680df70ab9470cdf1fced94296a08e0f1dc"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"31900e94e0e83a21b1bf2285b7452ac4ee1599d3","unresolved":false,"context_lines":[{"line_number":19,"context_line":"    var service;"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"    var policyAPI \u003d {"},{"line_number":22,"context_line":"      ifAllowed: function(rules) {"},{"line_number":23,"context_line":"        return {"},{"line_number":24,"context_line":"          success: function(callback) {"},{"line_number":25,"context_line":"            callback({allowed: true});"}],"source_content_type":"text/javascript","patch_set":63,"id":"9a8ffd7b_9405a115","line":22,"in_reply_to":"9a8ffd7b_8efce5b8","updated":"2015-12-01 05:02:49.000000000","message":"Done","commit_id":"e4eee680df70ab9470cdf1fced94296a08e0f1dc"}],"openstack_dashboard/static/app/core/images/table/images-table.controller.js":[{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"292625c1352823e8feb4d223c22283f18bbb61bd","unresolved":false,"context_lines":[{"line_number":33,"context_line":"    \u0027$scope\u0027,"},{"line_number":34,"context_line":"    \u0027horizon.app.core.images.basePath\u0027,"},{"line_number":35,"context_line":"    \u0027horizon.app.core.images.events\u0027,"},{"line_number":36,"context_line":"    \u0027horizon.app.core.images.batch-actions.service\u0027,"},{"line_number":37,"context_line":"    \u0027horizon.app.core.openstack-service-api.glance\u0027"},{"line_number":38,"context_line":"  ];"},{"line_number":39,"context_line":""}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_ef7645d6","line":36,"updated":"2015-08-28 18:15:13.000000000","message":"should alphabetize","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"a7511580eb4022bfb08c538f7627cfb919c10e2a","unresolved":false,"context_lines":[{"line_number":33,"context_line":"    \u0027$scope\u0027,"},{"line_number":34,"context_line":"    \u0027horizon.app.core.images.basePath\u0027,"},{"line_number":35,"context_line":"    \u0027horizon.app.core.images.events\u0027,"},{"line_number":36,"context_line":"    \u0027horizon.app.core.images.batch-actions.service\u0027,"},{"line_number":37,"context_line":"    \u0027horizon.app.core.openstack-service-api.glance\u0027"},{"line_number":38,"context_line":"  ];"},{"line_number":39,"context_line":""}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_7e38a5ef","line":36,"in_reply_to":"da20952f_ef7645d6","updated":"2015-08-28 20:30:07.000000000","message":"Done","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"76ea9067d6cc22b35c9e1f8ffa4454d2c0ecbb6c","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        return imageIds.filter(function(deletedImageId) {"},{"line_number":77,"context_line":"            return deletedImageId \u003d\u003d image.id;"},{"line_number":78,"context_line":"          }).length \u003d\u003d 0;"},{"line_number":79,"context_line":"      }"},{"line_number":80,"context_line":"    }"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    function destroy() {"}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_609348a4","line":79,"updated":"2015-08-28 06:30:28.000000000","message":"There is an anonymous functions embedded in the above.  Could probably be more generic and called idFilter.  In fact a whole lot of the onDeleteSuccess could be broken out into a common idFilter service so that every table doesn\u0027t have to copy this code and retest it.","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"a7511580eb4022bfb08c538f7627cfb919c10e2a","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        return imageIds.filter(function(deletedImageId) {"},{"line_number":77,"context_line":"            return deletedImageId \u003d\u003d image.id;"},{"line_number":78,"context_line":"          }).length \u003d\u003d 0;"},{"line_number":79,"context_line":"      }"},{"line_number":80,"context_line":"    }"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    function destroy() {"}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_b5189b1f","line":79,"in_reply_to":"da20952f_154b872b","updated":"2015-08-28 20:30:07.000000000","message":"I\u0027ve attempted to extract it helper-functions.","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"eb541b5591e7caeddfeb00014f6cecf9ef6a7882","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        return imageIds.filter(function(deletedImageId) {"},{"line_number":77,"context_line":"            return deletedImageId \u003d\u003d image.id;"},{"line_number":78,"context_line":"          }).length \u003d\u003d 0;"},{"line_number":79,"context_line":"      }"},{"line_number":80,"context_line":"    }"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    function destroy() {"}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_5e2e0144","line":79,"in_reply_to":"da20952f_2f151d48","updated":"2015-08-28 19:44:12.000000000","message":"Yes, basically.","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"b6f82afd5668e5d188e20684ac78611d610fa2f2","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        return imageIds.filter(function(deletedImageId) {"},{"line_number":77,"context_line":"            return deletedImageId \u003d\u003d image.id;"},{"line_number":78,"context_line":"          }).length \u003d\u003d 0;"},{"line_number":79,"context_line":"      }"},{"line_number":80,"context_line":"    }"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    function destroy() {"}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_154b872b","line":79,"in_reply_to":"da20952f_5e2e0144","updated":"2015-08-28 20:17:10.000000000","message":"I think it is easier to extract out a common function after a couple concrete examples are done. So, I\u0027m okay with doing this in a follow on patch with the user\u0027s delete action, but before we build more tables.  In general, I\u0027m hoping to see a couple concrete sets of code built (users and images) and to use those to simplify and remove boilerplate.","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"292625c1352823e8feb4d223c22283f18bbb61bd","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        return imageIds.filter(function(deletedImageId) {"},{"line_number":77,"context_line":"            return deletedImageId \u003d\u003d image.id;"},{"line_number":78,"context_line":"          }).length \u003d\u003d 0;"},{"line_number":79,"context_line":"      }"},{"line_number":80,"context_line":"    }"},{"line_number":81,"context_line":""},{"line_number":82,"context_line":"    function destroy() {"}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_2f151d48","line":79,"in_reply_to":"da20952f_609348a4","updated":"2015-08-28 18:15:13.000000000","message":"Are you talking about a filter for finding the ids of an item?","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"9e362ea6c20afffaeaa091354d83b23a8f691988","unresolved":false,"context_lines":[{"line_number":80,"context_line":"    function onGetImages(response) {"},{"line_number":81,"context_line":"      ctrl.imagesSrc \u003d response.items;"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"      checkPolicy();"},{"line_number":84,"context_line":"    }"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    function checkPolicy() {"}],"source_content_type":"text/javascript","patch_set":10,"id":"da20952f_17286699","line":83,"updated":"2015-08-29 00:20:03.000000000","message":"This should be in init.  Both of these can happen asynchronously.  We don\u0027t want checkPolicy to wait until images are retrieved to check the policy.","commit_id":"5128865030e0d40651ba528ff5f2e8fd78c03861"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"0c33016e980edf817029f56bd14114497bb28137","unresolved":false,"context_lines":[{"line_number":80,"context_line":"    function onGetImages(response) {"},{"line_number":81,"context_line":"      ctrl.imagesSrc \u003d response.items;"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":"      checkPolicy();"},{"line_number":84,"context_line":"    }"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    function checkPolicy() {"}],"source_content_type":"text/javascript","patch_set":10,"id":"da20952f_5a1e0360","line":83,"in_reply_to":"da20952f_17286699","updated":"2015-08-29 00:25:06.000000000","message":"I was a little conflicted about it. If there are no images listed if the fetch failed, then not much point in having a button to delete them. Though from a UI consistency perspective, it makes sense to apply it regardless of that.\n\nDone.","commit_id":"5128865030e0d40651ba528ff5f2e8fd78c03861"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"ce7ead61f6a6f11eb4d3cd15e53e1cd1c044a859","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    \u0027horizon.app.core.images.events\u0027,"},{"line_number":37,"context_line":"    \u0027horizon.app.core.openstack-service-api.glance\u0027,"},{"line_number":38,"context_line":"    \u0027horizon.app.core.openstack-service-api.policy\u0027,"},{"line_number":39,"context_line":"    \u0027horizon.framework.util.tech-debt.helper-functions\u0027"},{"line_number":40,"context_line":"  ];"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"  function ImagesTableController("}],"source_content_type":"text/javascript","patch_set":11,"id":"da20952f_da18d320","line":39,"updated":"2015-08-29 00:57:17.000000000","message":"No longer needed.","commit_id":"dc573db85c4f97796e2afc25747e98c5be8fcaa9"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"6eb13ab859af50dc30ccf190733742c86d5f0f26","unresolved":false,"context_lines":[{"line_number":36,"context_line":"    \u0027horizon.app.core.images.events\u0027,"},{"line_number":37,"context_line":"    \u0027horizon.app.core.openstack-service-api.glance\u0027,"},{"line_number":38,"context_line":"    \u0027horizon.app.core.openstack-service-api.policy\u0027,"},{"line_number":39,"context_line":"    \u0027horizon.framework.util.tech-debt.helper-functions\u0027"},{"line_number":40,"context_line":"  ];"},{"line_number":41,"context_line":""},{"line_number":42,"context_line":"  function ImagesTableController("}],"source_content_type":"text/javascript","patch_set":11,"id":"da20952f_1d16454c","line":39,"in_reply_to":"da20952f_da18d320","updated":"2015-08-29 01:18:48.000000000","message":"Done","commit_id":"dc573db85c4f97796e2afc25747e98c5be8fcaa9"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"ce7ead61f6a6f11eb4d3cd15e53e1cd1c044a859","unresolved":false,"context_lines":[{"line_number":46,"context_line":"    events,"},{"line_number":47,"context_line":"    glance,"},{"line_number":48,"context_line":"    policy,"},{"line_number":49,"context_line":"    helperFunctions"},{"line_number":50,"context_line":"  ) {"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"    var ctrl \u003d this;"}],"source_content_type":"text/javascript","patch_set":11,"id":"da20952f_9ad57b1d","line":49,"updated":"2015-08-29 00:57:17.000000000","message":"No longer needed.","commit_id":"dc573db85c4f97796e2afc25747e98c5be8fcaa9"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"6eb13ab859af50dc30ccf190733742c86d5f0f26","unresolved":false,"context_lines":[{"line_number":46,"context_line":"    events,"},{"line_number":47,"context_line":"    glance,"},{"line_number":48,"context_line":"    policy,"},{"line_number":49,"context_line":"    helperFunctions"},{"line_number":50,"context_line":"  ) {"},{"line_number":51,"context_line":""},{"line_number":52,"context_line":"    var ctrl \u003d this;"}],"source_content_type":"text/javascript","patch_set":11,"id":"da20952f_3d13095d","line":49,"in_reply_to":"da20952f_9ad57b1d","updated":"2015-08-29 01:18:48.000000000","message":"Done","commit_id":"dc573db85c4f97796e2afc25747e98c5be8fcaa9"},{"author":{"_account_id":11778,"name":"Diana Whitten","email":"hurgleburgler@gmail.com","username":"hurgleburgler"},"change_message_id":"1e311354a7c2b3e0cac3247e14e142ac249a6255","unresolved":false,"context_lines":[{"line_number":104,"context_line":"      function filter(elem) {"},{"line_number":105,"context_line":"        return otherList.filter(function(deletedItem) {"},{"line_number":106,"context_line":"          return deletedItem \u003d\u003d elem[key];"},{"line_number":107,"context_line":"        }).length \u003d\u003d 0;"},{"line_number":108,"context_line":"      }"},{"line_number":109,"context_line":"    }"},{"line_number":110,"context_line":""}],"source_content_type":"text/javascript","patch_set":12,"id":"da20952f_f47fe3a8","line":107,"updated":"2015-08-29 18:01:39.000000000","message":"\u003d\u003d\u003d ?","commit_id":"87e5f080525c92a3cf87f29984573387b4f98346"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"b2e2ed184edf0f10dfa6910676adca3b66a713a8","unresolved":false,"context_lines":[{"line_number":104,"context_line":"      function filter(elem) {"},{"line_number":105,"context_line":"        return otherList.filter(function(deletedItem) {"},{"line_number":106,"context_line":"          return deletedItem \u003d\u003d elem[key];"},{"line_number":107,"context_line":"        }).length \u003d\u003d 0;"},{"line_number":108,"context_line":"      }"},{"line_number":109,"context_line":"    }"},{"line_number":110,"context_line":""}],"source_content_type":"text/javascript","patch_set":12,"id":"da20952f_132fdf88","line":107,"in_reply_to":"da20952f_f47fe3a8","updated":"2015-08-31 15:30:22.000000000","message":"Done","commit_id":"87e5f080525c92a3cf87f29984573387b4f98346"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"a27133878da578be52ed102df376e8a4908053d6","unresolved":false,"context_lines":[{"line_number":95,"context_line":"    }"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"    function destroy() {"},{"line_number":98,"context_line":"      deleteWatcher();"},{"line_number":99,"context_line":"    }"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    function difference(currentList, otherList, key) {"}],"source_content_type":"text/javascript","patch_set":14,"id":"da20952f_3243eb6d","line":98,"updated":"2015-08-31 23:17:42.000000000","message":"Missing code coverage here.","commit_id":"2a24dc8df1746a7987a0e9daa19116cf00e21dac"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"4d0566b46360a0b5d1788248a6c3829e1f3f1f1f","unresolved":false,"context_lines":[{"line_number":95,"context_line":"    }"},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"    function destroy() {"},{"line_number":98,"context_line":"      deleteWatcher();"},{"line_number":99,"context_line":"    }"},{"line_number":100,"context_line":""},{"line_number":101,"context_line":"    function difference(currentList, otherList, key) {"}],"source_content_type":"text/javascript","patch_set":14,"id":"da20952f_ac7a3222","line":98,"in_reply_to":"da20952f_3243eb6d","updated":"2015-09-01 06:13:06.000000000","message":"Done","commit_id":"2a24dc8df1746a7987a0e9daa19116cf00e21dac"},{"author":{"_account_id":11778,"name":"Diana Whitten","email":"hurgleburgler@gmail.com","username":"hurgleburgler"},"change_message_id":"43c226a42c399215e4d2ca024440b2980c8e53ba","unresolved":false,"context_lines":[{"line_number":103,"context_line":""},{"line_number":104,"context_line":"      function filter(elem) {"},{"line_number":105,"context_line":"        return otherList.filter(function(deletedItem) {"},{"line_number":106,"context_line":"          return deletedItem \u003d\u003d elem[key];"},{"line_number":107,"context_line":"        }).length \u003d\u003d\u003d 0;"},{"line_number":108,"context_line":"      }"},{"line_number":109,"context_line":"    }"}],"source_content_type":"text/javascript","patch_set":14,"id":"da20952f_be4d8ac5","line":106,"updated":"2015-08-31 21:07:24.000000000","message":"Does the one above also need to be a \u0027\u003d\u003d\u003d\u0027 ?\n\nIf it doesn\u0027t and is relying on just checking equality and not type, then that\u0027s ok. If so, can we add a comment?\n\nJust want to make sure...","commit_id":"2a24dc8df1746a7987a0e9daa19116cf00e21dac"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"4d0566b46360a0b5d1788248a6c3829e1f3f1f1f","unresolved":false,"context_lines":[{"line_number":103,"context_line":""},{"line_number":104,"context_line":"      function filter(elem) {"},{"line_number":105,"context_line":"        return otherList.filter(function(deletedItem) {"},{"line_number":106,"context_line":"          return deletedItem \u003d\u003d elem[key];"},{"line_number":107,"context_line":"        }).length \u003d\u003d\u003d 0;"},{"line_number":108,"context_line":"      }"},{"line_number":109,"context_line":"    }"}],"source_content_type":"text/javascript","patch_set":14,"id":"da20952f_0c923e4c","line":106,"in_reply_to":"da20952f_be4d8ac5","updated":"2015-09-01 06:13:06.000000000","message":"Done","commit_id":"2a24dc8df1746a7987a0e9daa19116cf00e21dac"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"37f39ad85d02b212bbf224f1e6e729b743f5ddd9","unresolved":false,"context_lines":[{"line_number":54,"context_line":""},{"line_number":55,"context_line":"    ctrl.deletePermitted \u003d false;"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    ctrl.checked \u003d {};"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"    ctrl.batchActions \u003d batchActions;"},{"line_number":60,"context_line":"    ctrl.batchActions.initScope($scope);"}],"source_content_type":"text/javascript","patch_set":16,"id":"da20952f_f6b3f0e7","line":57,"updated":"2015-09-01 20:23:23.000000000","message":"Is this really needed?  I think it can be deleted.","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"1a0d426a69bcd7dc6e13ec306ce09954a92b89c4","unresolved":false,"context_lines":[{"line_number":54,"context_line":""},{"line_number":55,"context_line":"    ctrl.deletePermitted \u003d false;"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    ctrl.checked \u003d {};"},{"line_number":58,"context_line":""},{"line_number":59,"context_line":"    ctrl.batchActions \u003d batchActions;"},{"line_number":60,"context_line":"    ctrl.batchActions.initScope($scope);"}],"source_content_type":"text/javascript","patch_set":16,"id":"da20952f_e63b3937","line":57,"in_reply_to":"da20952f_f6b3f0e7","updated":"2015-09-01 22:31:31.000000000","message":"This is needed by hz-table. It is use for selecting rows via checkboxes.","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"1a0d426a69bcd7dc6e13ec306ce09954a92b89c4","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    ctrl.batchActions \u003d batchActions;"},{"line_number":60,"context_line":"    ctrl.batchActions.initScope($scope);"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    ctrl.path \u003d basePath + \u0027table/\u0027;"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    var deleteWatcher \u003d $scope.$on(events.deleteSuccess, onDeleteSuccess);"},{"line_number":65,"context_line":""}],"source_content_type":"text/javascript","patch_set":16,"id":"da20952f_c653956b","line":62,"updated":"2015-09-01 22:31:31.000000000","message":"no longer needed. original intent was for templating via ng-include, but since we merged table.html, no longer needed. don\u0027t forget to remove the DI as well.","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":17004,"name":"KBrown","email":"kbrown@thoughtworks.com","username":"kbrown"},"change_message_id":"760121c24bb5098263e4ca4a9eb20bc40e0da42a","unresolved":false,"context_lines":[{"line_number":59,"context_line":"    ctrl.batchActions \u003d batchActions;"},{"line_number":60,"context_line":"    ctrl.batchActions.initScope($scope);"},{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    ctrl.path \u003d basePath + \u0027table/\u0027;"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    var deleteWatcher \u003d $scope.$on(events.deleteSuccess, onDeleteSuccess);"},{"line_number":65,"context_line":""}],"source_content_type":"text/javascript","patch_set":16,"id":"da20952f_e99f8a4e","line":62,"in_reply_to":"da20952f_c653956b","updated":"2015-09-01 23:01:57.000000000","message":"Done","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"37f39ad85d02b212bbf224f1e6e729b743f5ddd9","unresolved":false,"context_lines":[{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    ctrl.path \u003d basePath + \u0027table/\u0027;"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    var deleteWatcher \u003d $scope.$on(events.deleteSuccess, onDeleteSuccess);"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    $scope.$on(\u0027$destroy\u0027, destroy);"},{"line_number":67,"context_line":""}],"source_content_type":"text/javascript","patch_set":16,"id":"da20952f_16b544cf","line":64,"updated":"2015-09-01 20:23:23.000000000","message":"nit: won\u0027t block on this. The above could have the whitespace removed.  I\u0027m not sure it adds value.  Also, possibly alphabetized.","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":17004,"name":"KBrown","email":"kbrown@thoughtworks.com","username":"kbrown"},"change_message_id":"760121c24bb5098263e4ca4a9eb20bc40e0da42a","unresolved":false,"context_lines":[{"line_number":61,"context_line":""},{"line_number":62,"context_line":"    ctrl.path \u003d basePath + \u0027table/\u0027;"},{"line_number":63,"context_line":""},{"line_number":64,"context_line":"    var deleteWatcher \u003d $scope.$on(events.deleteSuccess, onDeleteSuccess);"},{"line_number":65,"context_line":""},{"line_number":66,"context_line":"    $scope.$on(\u0027$destroy\u0027, destroy);"},{"line_number":67,"context_line":""}],"source_content_type":"text/javascript","patch_set":16,"id":"da20952f_290d8237","line":64,"in_reply_to":"da20952f_16b544cf","updated":"2015-09-01 23:01:57.000000000","message":"Done","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"37f39ad85d02b212bbf224f1e6e729b743f5ddd9","unresolved":false,"context_lines":[{"line_number":90,"context_line":"    }"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    function onDeleteSuccess(e, removedImageIds) {"},{"line_number":93,"context_line":"      ctrl.imagesSrc \u003d difference(ctrl.imagesSrc, removedImageIds, \u0027id\u0027);"},{"line_number":94,"context_line":"      e.stopPropagation();"},{"line_number":95,"context_line":"    }"},{"line_number":96,"context_line":""}],"source_content_type":"text/javascript","patch_set":16,"id":"da20952f_504e6497","line":93,"updated":"2015-09-01 20:23:23.000000000","message":"So I created 3 demo images (use location and don\u0027t copy data).  I then tested delete.  I deleted the first one \"demo1\" and everything was fine. It was removed from the table.  I then selected the other two (\"demo2\", \"demo3\") and clicked delete.  The message showed all three (\"demo1\" should not be in the list):\n\nYou have selected \"demo1\", \"demo2\", \"demo3\". Please confirm your selection. Deleted images are not recoverable.\n\nAt first I thought it was due to you re-assigning imagesSrc to a new reference here rather than modifying the in place array. I traced through the code a bit, but didn\u0027t chase it all the way down. The ng-model of selected provided by hz-table directives is not clearing out the elements from the selected array when they are deleted. The selected array could be passed all the way through to here where it is removed from that array, but that doesn\u0027t seem right.\n\nAt any rate, can you investigate further?  If this is a bug in hz-table, we\u0027ll probably need to fix that independently of this patch.","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":17004,"name":"KBrown","email":"kbrown@thoughtworks.com","username":"kbrown"},"change_message_id":"760121c24bb5098263e4ca4a9eb20bc40e0da42a","unresolved":false,"context_lines":[{"line_number":90,"context_line":"    }"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"    function onDeleteSuccess(e, removedImageIds) {"},{"line_number":93,"context_line":"      ctrl.imagesSrc \u003d difference(ctrl.imagesSrc, removedImageIds, \u0027id\u0027);"},{"line_number":94,"context_line":"      e.stopPropagation();"},{"line_number":95,"context_line":"    }"},{"line_number":96,"context_line":""}],"source_content_type":"text/javascript","patch_set":16,"id":"da20952f_86059d15","line":93,"in_reply_to":"da20952f_504e6497","updated":"2015-09-01 23:01:57.000000000","message":"you\u0027re right the deleted image was still \"checked:true\" in the selected array.  Now, when the delete is successful the selected array is cleared on the image table controller.","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"210345ac584d72bf4ac0363642f9625d742243cf","unresolved":false,"context_lines":[{"line_number":65,"context_line":"    function init() {"},{"line_number":66,"context_line":"      // if user has permission"},{"line_number":67,"context_line":"      // fetch table data and populate it"},{"line_number":68,"context_line":"      glance.getImages().success(onGetImages);"},{"line_number":69,"context_line":"      checkPolicy();"},{"line_number":70,"context_line":"    }"},{"line_number":71,"context_line":""}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_d64f9abc","line":68,"updated":"2015-09-02 17:59:33.000000000","message":"might need to check policy for glance get images too, not just delete.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"694c0f6644147e91f6087d485f18682446738b96","unresolved":false,"context_lines":[{"line_number":65,"context_line":"    function init() {"},{"line_number":66,"context_line":"      // if user has permission"},{"line_number":67,"context_line":"      // fetch table data and populate it"},{"line_number":68,"context_line":"      glance.getImages().success(onGetImages);"},{"line_number":69,"context_line":"      checkPolicy();"},{"line_number":70,"context_line":"    }"},{"line_number":71,"context_line":""}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_adb97017","line":68,"in_reply_to":"da20952f_d64f9abc","updated":"2015-09-02 18:19:12.000000000","message":"Could be done, but shouldn\u0027t that be on the panel as a whole?  Current table doesn\u0027t do policy check.  The API itself will just reject the request.\n\nhttps://github.com/openstack/horizon/blob/master/openstack_dashboard/dashboards/project/images/views.py#L35","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"210345ac584d72bf4ac0363642f9625d742243cf","unresolved":false,"context_lines":[{"line_number":75,"context_line":""},{"line_number":76,"context_line":"    function checkPolicy() {"},{"line_number":77,"context_line":"      var rules \u003d [[\u0027image\u0027, \u0027delete_image\u0027]];"},{"line_number":78,"context_line":"      policy.check({ rules: rules }).success(policySuccess);"},{"line_number":79,"context_line":"    }"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    function policySuccess(response) {"}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_aab4f634","line":78,"updated":"2015-09-02 17:59:33.000000000","message":"I think the delete policy check should happen in the delete service. and then to reference it in the html, it\u0027ll just be ctrl.batchActions.deleteService.allowed or something.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"f90f6623880f27263159b69b5d0b99dda89ff2b1","unresolved":false,"context_lines":[{"line_number":83,"context_line":"    }"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    function onDeleteSuccess(e, removedImageIds) {"},{"line_number":86,"context_line":"      ctrl.imagesSrc \u003d difference(ctrl.imagesSrc, removedImageIds, \u0027id\u0027);"},{"line_number":87,"context_line":""},{"line_number":88,"context_line":"      /* eslint-disable angular/ng_controller_as */"},{"line_number":89,"context_line":"      $scope.selected \u003d [];"}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_ca728a7c","line":86,"updated":"2015-09-02 17:51:19.000000000","message":"Should this be modifying imagesSrc rather than resetting the reference?","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"f90f6623880f27263159b69b5d0b99dda89ff2b1","unresolved":false,"context_lines":[{"line_number":85,"context_line":"    function onDeleteSuccess(e, removedImageIds) {"},{"line_number":86,"context_line":"      ctrl.imagesSrc \u003d difference(ctrl.imagesSrc, removedImageIds, \u0027id\u0027);"},{"line_number":87,"context_line":""},{"line_number":88,"context_line":"      /* eslint-disable angular/ng_controller_as */"},{"line_number":89,"context_line":"      $scope.selected \u003d [];"},{"line_number":90,"context_line":"      $scope.numSelected \u003d 0;"},{"line_number":91,"context_line":"      /* eslint-enable angular/ng_controller_as */"}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_4a5e7aea","line":88,"updated":"2015-09-02 17:51:19.000000000","message":"I do think we could check with Kelly to see if there is a better way to do this.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"210345ac584d72bf4ac0363642f9625d742243cf","unresolved":false,"context_lines":[{"line_number":85,"context_line":"    function onDeleteSuccess(e, removedImageIds) {"},{"line_number":86,"context_line":"      ctrl.imagesSrc \u003d difference(ctrl.imagesSrc, removedImageIds, \u0027id\u0027);"},{"line_number":87,"context_line":""},{"line_number":88,"context_line":"      /* eslint-disable angular/ng_controller_as */"},{"line_number":89,"context_line":"      $scope.selected \u003d [];"},{"line_number":90,"context_line":"      $scope.numSelected \u003d 0;"},{"line_number":91,"context_line":"      /* eslint-enable angular/ng_controller_as */"}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_8af25299","line":88,"updated":"2015-09-02 17:59:33.000000000","message":"we should create a clear method in hz table.controller.js and invoke that method here instead. also, $scope.select should be reset to an object - not an array. https://github.com/openstack/horizon/blob/master/horizon/static/framework/widgets/table/table.controller.js#L34","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":17327,"name":"Kyle Olivo","email":"keolivo@thoughtworks.com","username":"kyleolivo"},"change_message_id":"4bc34bdb0181293a0c837c62e50f8e8716f3483e","unresolved":false,"context_lines":[{"line_number":85,"context_line":"    function onDeleteSuccess(e, removedImageIds) {"},{"line_number":86,"context_line":"      ctrl.imagesSrc \u003d difference(ctrl.imagesSrc, removedImageIds, \u0027id\u0027);"},{"line_number":87,"context_line":""},{"line_number":88,"context_line":"      /* eslint-disable angular/ng_controller_as */"},{"line_number":89,"context_line":"      $scope.selected \u003d [];"},{"line_number":90,"context_line":"      $scope.numSelected \u003d 0;"},{"line_number":91,"context_line":"      /* eslint-enable angular/ng_controller_as */"}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_a90e37e3","line":88,"in_reply_to":"da20952f_8af25299","updated":"2015-09-02 23:48:28.000000000","message":"@Thai\n\nWe\u0027ll fix it to set as an object instead of an array.\n\n@Travis + @Thai\n\nWe\u0027re looking at the code in the Table Controller. There\u0027s access to the controller from the Image Table Controller, so while we could create a method, we might not be able to invoke it.\n\nIt might be slightly better to broadcast \u0027hzTable:rowsCleared\u0027 event which the table controller could watch and accordingly clear the selected. Would that work? That would be a different patch though, not requiring this one.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"ce9f74681d7ac30faa2cebb89618872bbef3bd02","unresolved":false,"context_lines":[{"line_number":88,"context_line":"      /* eslint-disable angular/ng_controller_as */"},{"line_number":89,"context_line":"      $scope.selected \u003d {};"},{"line_number":90,"context_line":"      $scope.numSelected \u003d 0;"},{"line_number":91,"context_line":"      /* eslint-enable angular/ng_controller_as */"},{"line_number":92,"context_line":""},{"line_number":93,"context_line":"      e.stopPropagation();"},{"line_number":94,"context_line":"    }"}],"source_content_type":"text/javascript","patch_set":20,"id":"da20952f_9de31ad8","line":91,"updated":"2015-09-04 18:32:24.000000000","message":"Adding the same note here that I don\u0027t like reaching inside the internal variables of another directive. So, we need to provide a way to access it in a way that doesn\u0027t violate encapsulation principles.","commit_id":"ba722dd0581fd46c032d8c744126d6b880d97954"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"219c1698c54ba473ddcb7841fed4e1d4c2621254","unresolved":false,"context_lines":[{"line_number":78,"context_line":"      policy.check({ rules: rules }).success(policySuccess);"},{"line_number":79,"context_line":"    }"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    function policySuccess(response) {"},{"line_number":82,"context_line":"      ctrl.deletePermitted \u003d response.allowed;"},{"line_number":83,"context_line":"    }"},{"line_number":84,"context_line":""}],"source_content_type":"text/javascript","patch_set":28,"id":"9a1a9d01_2dc2a0e9","line":81,"updated":"2015-09-30 22:30:36.000000000","message":"at the risk of sounding like a hypocrite, i think the hz-if-policies directive would be a tremendous help here. then the check wouldnt need to be in the controller at all, it can be done in the html instead.","commit_id":"8248308e50ca2b75364247c73dc1aa6adb4983ee"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"743c2aaec63c2b71359a092f2a28b9d2a13010f3","unresolved":false,"context_lines":[{"line_number":78,"context_line":"      policy.check({ rules: rules }).success(policySuccess);"},{"line_number":79,"context_line":"    }"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    function policySuccess(response) {"},{"line_number":82,"context_line":"      ctrl.deletePermitted \u003d response.allowed;"},{"line_number":83,"context_line":"    }"},{"line_number":84,"context_line":""}],"source_content_type":"text/javascript","patch_set":28,"id":"9a1a9d01_7e5cbc18","line":81,"in_reply_to":"9a1a9d01_2dc2a0e9","updated":"2015-09-30 23:49:33.000000000","message":"There\u0027s more logic to when a service can be deleted. It\u0027s captured better in the subsequent patch.\n\nhttps://review.openstack.org/#/c/217949","commit_id":"8248308e50ca2b75364247c73dc1aa6adb4983ee"},{"author":{"_account_id":11778,"name":"Diana Whitten","email":"hurgleburgler@gmail.com","username":"hurgleburgler"},"change_message_id":"b4beba94f2123e808d02e40723e2dfa6640e5b7a","unresolved":false,"context_lines":[{"line_number":52,"context_line":"    ctrl.images \u003d [];"},{"line_number":53,"context_line":"    ctrl.imagesSrc \u003d [];"},{"line_number":54,"context_line":""},{"line_number":55,"context_line":"    var deleteWatcher \u003d $scope.$on(events.deleteSuccess, onDeleteSuccess);"},{"line_number":56,"context_line":""},{"line_number":57,"context_line":"    $scope.$on(\u0027$destroy\u0027, destroy);"},{"line_number":58,"context_line":""}],"source_content_type":"text/javascript","patch_set":39,"id":"5a2ca52d_8f7e6468","line":55,"updated":"2015-10-16 23:08:53.000000000","message":"ctrl is a pointer to \u0027this\u0027 at this point ... so, its no different than ctrl.deleteWatcher \u003d \n\nIs there a reason for this?  If you don\u0027t want deleteWatcher to be part of ctrl, you\u0027ll need to extend or clone this.","commit_id":"c46a1667273299b70e143d19299ddc938035e895"},{"author":{"_account_id":15742,"name":"Paulo Ewerton Gomes Fragoso","email":"pauloewerton@lsd.ufcg.edu.br","username":"pauloewerton"},"change_message_id":"8d91d1de4991395f39c23517a5f1626284e20502","unresolved":false,"context_lines":[{"line_number":90,"context_line":"      return currentList.filter(filter);"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"      function filter(elem) {"},{"line_number":93,"context_line":"        return otherList.filter(function(deletedItem) {"},{"line_number":94,"context_line":"          return deletedItem \u003d\u003d\u003d elem[key];"},{"line_number":95,"context_line":"        }).length \u003d\u003d\u003d 0;"},{"line_number":96,"context_line":"      }"}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_22278a65","line":93,"updated":"2015-11-10 15:14:33.000000000","message":"nit: anonymous function","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":18508,"name":"Errol Pais","email":"errol.pais@protonmail.com","username":"errol"},"change_message_id":"3a61d335e90e14bae1148c1c09385b10a3625b5f","unresolved":false,"context_lines":[{"line_number":90,"context_line":"      return currentList.filter(filter);"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"      function filter(elem) {"},{"line_number":93,"context_line":"        return otherList.filter(function(deletedItem) {"},{"line_number":94,"context_line":"          return deletedItem \u003d\u003d\u003d elem[key];"},{"line_number":95,"context_line":"        }).length \u003d\u003d\u003d 0;"},{"line_number":96,"context_line":"      }"}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_95b776f4","line":93,"in_reply_to":"da85f559_22278a65","updated":"2015-11-11 21:51:19.000000000","message":"Done","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":67,"context_line":""},{"line_number":68,"context_line":"    function init() {"},{"line_number":69,"context_line":"      // if user has permission"},{"line_number":70,"context_line":"      // fetch table data and populate it"},{"line_number":71,"context_line":"      glance.getImages().success(onGetImages);"},{"line_number":72,"context_line":"    }"},{"line_number":73,"context_line":""}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_fc1f4059","line":70,"updated":"2015-12-03 23:57:44.000000000","message":"the \"if user has permission\" is kind of funny. There are no permission checks that I see in the path here other than glance service side. Nothing would preclude that being added in the future, but it made me go searching for the permissions which I missed(?) or don\u0027t think are really there.\n\n controller -\u003e js service -\u003e  api\\rest\\glance.py -\u003e api\\glance.py\n\nI think this is a copy / paste from Thai\u0027s table controller, but he actually is doing a policy check. https://review.openstack.org/#/c/222297/22/openstack_dashboard/dashboards/identity/static/dashboard/identity/users/table/table.controller.js\n\nFWIW, I don\u0027t see any policy check on existing django code, so I don\u0027t think that\u0027s needed here and this comment just go away.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"}],"openstack_dashboard/static/app/core/images/table/images-table.controller.spec.js":[{"author":{"_account_id":10442,"name":"Masco Kaliyamoorthy","email":"mkaliyam@redhat.com","username":"masco"},"change_message_id":"5c29a5e35c9597b4bfb7de223dc70445059203f6","unresolved":false,"context_lines":[{"line_number":79,"context_line":"    });"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    it(\u0027should destroy the event watchers\u0027, function() {"},{"line_number":82,"context_line":"      var deleteWatcher \u003d jasmine.createSpy(\u0027deleteWatcher\u0027);"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"      var ctrl \u003d createController();"},{"line_number":85,"context_line":""}],"source_content_type":"text/javascript","patch_set":63,"id":"9a8ffd7b_eeded13c","line":82,"updated":"2015-11-30 09:22:09.000000000","message":"deleteWatcher is unused.","commit_id":"e4eee680df70ab9470cdf1fced94296a08e0f1dc"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"31900e94e0e83a21b1bf2285b7452ac4ee1599d3","unresolved":false,"context_lines":[{"line_number":79,"context_line":"    });"},{"line_number":80,"context_line":""},{"line_number":81,"context_line":"    it(\u0027should destroy the event watchers\u0027, function() {"},{"line_number":82,"context_line":"      var deleteWatcher \u003d jasmine.createSpy(\u0027deleteWatcher\u0027);"},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"      var ctrl \u003d createController();"},{"line_number":85,"context_line":""}],"source_content_type":"text/javascript","patch_set":63,"id":"9a8ffd7b_b402250a","line":82,"in_reply_to":"9a8ffd7b_eeded13c","updated":"2015-12-01 05:02:49.000000000","message":"Done","commit_id":"e4eee680df70ab9470cdf1fced94296a08e0f1dc"}],"openstack_dashboard/static/app/core/images/table/images-table.html":[{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"76ea9067d6cc22b35c9e1f8ffa4454d2c0ecbb6c","unresolved":false,"context_lines":[{"line_number":18,"context_line":"            \u003caction action-classes\u003d\"\u0027btn btn-default btn-sm btn-danger pull-right\u0027\""},{"line_number":19,"context_line":"                    disabled\u003d\"numSelected \u003d\u003d\u003d 0\""},{"line_number":20,"context_line":"                    callback\u003d\"table.batchActions.deleted.open\""},{"line_number":21,"context_line":"                    item\u003d\"selected\"\u003e"},{"line_number":22,"context_line":"              \u003ci class\u003d\"fa fa-trash-o\"\u003e\u003c/i\u003e"},{"line_number":23,"context_line":"              \u003ctranslate\u003eDelete Images\u003c/translate\u003e"},{"line_number":24,"context_line":"            \u003c/action\u003e"}],"source_content_type":"text/html","patch_set":6,"id":"da20952f_60cb4873","line":21,"updated":"2015-08-28 06:30:28.000000000","message":"I think the action directive could have some profiles built in where all of the above inputs (except callback) are set.  So instead of specifying ALL of those, you\u0027d just specify something like:\n\nprofile\u003d\"dangerous-table-action\" and it would set all of the above.  That\u0027s a lot of boilerplate.\n\nThoughts? Could be a follow on cleanup patch.\n\nSame comments here:\n\nhttps://review.openstack.org/#/c/202315/18/openstack_dashboard/dashboards/identity/static/dashboard/identity/users/table/table-batch-actions.html","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"292625c1352823e8feb4d223c22283f18bbb61bd","unresolved":false,"context_lines":[{"line_number":18,"context_line":"            \u003caction action-classes\u003d\"\u0027btn btn-default btn-sm btn-danger pull-right\u0027\""},{"line_number":19,"context_line":"                    disabled\u003d\"numSelected \u003d\u003d\u003d 0\""},{"line_number":20,"context_line":"                    callback\u003d\"table.batchActions.deleted.open\""},{"line_number":21,"context_line":"                    item\u003d\"selected\"\u003e"},{"line_number":22,"context_line":"              \u003ci class\u003d\"fa fa-trash-o\"\u003e\u003c/i\u003e"},{"line_number":23,"context_line":"              \u003ctranslate\u003eDelete Images\u003c/translate\u003e"},{"line_number":24,"context_line":"            \u003c/action\u003e"}],"source_content_type":"text/html","patch_set":6,"id":"da20952f_d2b1aa48","line":21,"in_reply_to":"da20952f_60cb4873","updated":"2015-08-28 18:15:13.000000000","message":"Yeah that would save you on the css but not much else. If you compare profile\u003d\"dangerous-table-action\" to action-classes\u003d\"btn btn-default btn-sm btn-danger pull-right\", you\u0027re not saving a whole lot.\n\nIf we do go down this path, I prefer to keep it css related. You can still have a profile but it is written in css as oppose to hardcoding it into the code as a defaults for that profile. we can use scss imports or mixins to help us here. This makes it easier for a deployer to come in a override the profile via their own css if they don\u0027t like it.","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"eb541b5591e7caeddfeb00014f6cecf9ef6a7882","unresolved":false,"context_lines":[{"line_number":18,"context_line":"            \u003caction action-classes\u003d\"\u0027btn btn-default btn-sm btn-danger pull-right\u0027\""},{"line_number":19,"context_line":"                    disabled\u003d\"numSelected \u003d\u003d\u003d 0\""},{"line_number":20,"context_line":"                    callback\u003d\"table.batchActions.deleted.open\""},{"line_number":21,"context_line":"                    item\u003d\"selected\"\u003e"},{"line_number":22,"context_line":"              \u003ci class\u003d\"fa fa-trash-o\"\u003e\u003c/i\u003e"},{"line_number":23,"context_line":"              \u003ctranslate\u003eDelete Images\u003c/translate\u003e"},{"line_number":24,"context_line":"            \u003c/action\u003e"}],"source_content_type":"text/html","patch_set":6,"id":"da20952f_7e6ae5ef","line":21,"in_reply_to":"da20952f_d2b1aa48","updated":"2015-08-28 19:44:12.000000000","message":"yeah, mainly looking for a way to make it a single thing to change.\n\naction-classes, disabled, and item all could be in this.\n\nNot a blocker here. But something to consider.","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"351fa34e1b236360acf36abe7f255385972633c0","unresolved":false,"context_lines":[{"line_number":15,"context_line":"      \u003cth colspan\u003d\"100\" class\u003d\"search-header\"\u003e"},{"line_number":16,"context_line":"        \u003chz-search-bar group-classes\u003d\"input-group-sm\" icon-classes\u003d\"fa-search\"\u003e"},{"line_number":17,"context_line":"          \u003caction-list class\u003d\"btn-addon\"\u003e"},{"line_number":18,"context_line":"            \u003caction action-classes\u003d\"\u0027btn btn-default btn-sm btn-danger pull-right\u0027\""},{"line_number":19,"context_line":"                    disabled\u003d\"numSelected \u003d\u003d\u003d 0\""},{"line_number":20,"context_line":"                    callback\u003d\"table.batchActions.deleted.open\""},{"line_number":21,"context_line":"                    item\u003d\"selected\"\u003e"}],"source_content_type":"text/html","patch_set":7,"id":"da20952f_2b58a889","line":18,"updated":"2015-08-28 21:26:49.000000000","message":"Should not appear if policy doesn\u0027t pass.\n\nhttps://github.com/openstack/horizon/blob/master/openstack_dashboard/dashboards/project/images/images/tables.py#L106\n\nProbably can be in controller, should use the policy service see if delete image is allowed and set it on scope, then check here. According to the below, we don\u0027t need to check on each image, because the current policy only checks as a whole. So, although declarative, I don\u0027t think we need the policy directive here.\n\nhttps://github.com/openstack/horizon/blob/master/openstack_dashboard/dashboards/project/images/images/tables.py#L104","commit_id":"385d641c273e722e82297f736b4f81acfd0d68da"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"4d7bc2aad825940159a633fe86cd65d7f88214d4","unresolved":false,"context_lines":[{"line_number":15,"context_line":"      \u003cth colspan\u003d\"100\" class\u003d\"search-header\"\u003e"},{"line_number":16,"context_line":"        \u003chz-search-bar group-classes\u003d\"input-group-sm\" icon-classes\u003d\"fa-search\"\u003e"},{"line_number":17,"context_line":"          \u003caction-list class\u003d\"btn-addon\"\u003e"},{"line_number":18,"context_line":"            \u003caction action-classes\u003d\"\u0027btn btn-default btn-sm btn-danger pull-right\u0027\""},{"line_number":19,"context_line":"                    disabled\u003d\"numSelected \u003d\u003d\u003d 0\""},{"line_number":20,"context_line":"                    callback\u003d\"table.batchActions.deleted.open\""},{"line_number":21,"context_line":"                    item\u003d\"selected\"\u003e"}],"source_content_type":"text/html","patch_set":7,"id":"da20952f_f7e933e7","line":18,"in_reply_to":"da20952f_2b58a889","updated":"2015-08-28 23:24:04.000000000","message":"Done","commit_id":"385d641c273e722e82297f736b4f81acfd0d68da"},{"author":{"_account_id":11778,"name":"Diana Whitten","email":"hurgleburgler@gmail.com","username":"hurgleburgler"},"change_message_id":"1e311354a7c2b3e0cac3247e14e142ac249a6255","unresolved":false,"context_lines":[{"line_number":20,"context_line":"                    disabled\u003d\"numSelected \u003d\u003d\u003d 0\""},{"line_number":21,"context_line":"                    callback\u003d\"table.batchActions.deleted.open\""},{"line_number":22,"context_line":"                    item\u003d\"selected\"\u003e"},{"line_number":23,"context_line":"              \u003ci class\u003d\"fa fa-trash-o\"\u003e\u003c/i\u003e"},{"line_number":24,"context_line":"              \u003ctranslate\u003eDelete Images\u003c/translate\u003e"},{"line_number":25,"context_line":"            \u003c/action\u003e"},{"line_number":26,"context_line":"          \u003c/action-list\u003e"}],"source_content_type":"text/html","patch_set":12,"id":"da20952f_6f077a18","line":23,"updated":"2015-08-29 18:01:39.000000000","message":"Using \u003ci\u003e as an icon is a controversial topic, with there being good things and bad things behind each side of the debate.  We should eventually have the discussion of whether we want to bypass the w3c\u0027s definition of \u003ci\u003e and use it to be more semantic, but until then, lets keep the standard usage of \u003cspan\u003e for icon fonts for now.\n\nGiven, there are usages of \u003ci\u003e sprinkled through out the codebase, but usage of \u003cspan\u003e is far more consistent.  I\u0027ll be making the global change to \u003cspan\u003e eventually, but we should start scrutinizing all new code going in for this compliance.\n\nThanks!","commit_id":"87e5f080525c92a3cf87f29984573387b4f98346"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"b2e2ed184edf0f10dfa6910676adca3b66a713a8","unresolved":false,"context_lines":[{"line_number":20,"context_line":"                    disabled\u003d\"numSelected \u003d\u003d\u003d 0\""},{"line_number":21,"context_line":"                    callback\u003d\"table.batchActions.deleted.open\""},{"line_number":22,"context_line":"                    item\u003d\"selected\"\u003e"},{"line_number":23,"context_line":"              \u003ci class\u003d\"fa fa-trash-o\"\u003e\u003c/i\u003e"},{"line_number":24,"context_line":"              \u003ctranslate\u003eDelete Images\u003c/translate\u003e"},{"line_number":25,"context_line":"            \u003c/action\u003e"},{"line_number":26,"context_line":"          \u003c/action-list\u003e"}],"source_content_type":"text/html","patch_set":12,"id":"da20952f_b329538c","line":23,"in_reply_to":"da20952f_6f077a18","updated":"2015-08-31 15:30:22.000000000","message":"Done","commit_id":"87e5f080525c92a3cf87f29984573387b4f98346"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"37f39ad85d02b212bbf224f1e6e729b743f5ddd9","unresolved":false,"context_lines":[{"line_number":62,"context_line":"      rsp-p1 rsp-p2 are responsive priority as user resizes window."},{"line_number":63,"context_line":"    --\u003e"},{"line_number":64,"context_line":"    \u003ctr ng-repeat-start\u003d\"image in table.images track by image.id\""},{"line_number":65,"context_line":"        ng-class\u003d\"{\u0027st-selected\u0027: checked[image.id]}\"\u003e"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"      \u003ctd class\u003d\"select-col\"\u003e"},{"line_number":68,"context_line":"        \u003cinput type\u003d\"checkbox\""}],"source_content_type":"text/html","patch_set":16,"id":"da20952f_5ba9a523","line":65,"updated":"2015-09-01 20:23:23.000000000","message":"What is this doing?  I think you can delete it.","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":17004,"name":"KBrown","email":"kbrown@thoughtworks.com","username":"kbrown"},"change_message_id":"760121c24bb5098263e4ca4a9eb20bc40e0da42a","unresolved":false,"context_lines":[{"line_number":62,"context_line":"      rsp-p1 rsp-p2 are responsive priority as user resizes window."},{"line_number":63,"context_line":"    --\u003e"},{"line_number":64,"context_line":"    \u003ctr ng-repeat-start\u003d\"image in table.images track by image.id\""},{"line_number":65,"context_line":"        ng-class\u003d\"{\u0027st-selected\u0027: checked[image.id]}\"\u003e"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"      \u003ctd class\u003d\"select-col\"\u003e"},{"line_number":68,"context_line":"        \u003cinput type\u003d\"checkbox\""}],"source_content_type":"text/html","patch_set":16,"id":"da20952f_297102e1","line":65,"in_reply_to":"da20952f_5ba9a523","updated":"2015-09-01 23:01:57.000000000","message":"Done: removed the ng-class","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"37f39ad85d02b212bbf224f1e6e729b743f5ddd9","unresolved":false,"context_lines":[{"line_number":66,"context_line":""},{"line_number":67,"context_line":"      \u003ctd class\u003d\"select-col\"\u003e"},{"line_number":68,"context_line":"        \u003cinput type\u003d\"checkbox\""},{"line_number":69,"context_line":"               ng-model\u003d\"selected[image.id].checked\""},{"line_number":70,"context_line":"               hz-select\u003d\"image\"\u003e"},{"line_number":71,"context_line":"      \u003c/td\u003e"},{"line_number":72,"context_line":"      \u003ctd class\u003d\"expander\"\u003e"}],"source_content_type":"text/html","patch_set":16,"id":"da20952f_96407437","line":69,"updated":"2015-09-01 20:23:23.000000000","message":"The element in the selected array is not being cleared out when deleted.","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":17004,"name":"KBrown","email":"kbrown@thoughtworks.com","username":"kbrown"},"change_message_id":"760121c24bb5098263e4ca4a9eb20bc40e0da42a","unresolved":false,"context_lines":[{"line_number":66,"context_line":""},{"line_number":67,"context_line":"      \u003ctd class\u003d\"select-col\"\u003e"},{"line_number":68,"context_line":"        \u003cinput type\u003d\"checkbox\""},{"line_number":69,"context_line":"               ng-model\u003d\"selected[image.id].checked\""},{"line_number":70,"context_line":"               hz-select\u003d\"image\"\u003e"},{"line_number":71,"context_line":"      \u003c/td\u003e"},{"line_number":72,"context_line":"      \u003ctd class\u003d\"expander\"\u003e"}],"source_content_type":"text/html","patch_set":16,"id":"da20952f_891cce6b","line":69,"in_reply_to":"da20952f_96407437","updated":"2015-09-01 23:01:57.000000000","message":"Done","commit_id":"4faba9548284188add6855877a89acac5170eae0"},{"author":{"_account_id":15742,"name":"Paulo Ewerton Gomes Fragoso","email":"pauloewerton@lsd.ufcg.edu.br","username":"pauloewerton"},"change_message_id":"8d91d1de4991395f39c23517a5f1626284e20502","unresolved":false,"context_lines":[{"line_number":41,"context_line":"      \u003cth class\u003d\"rsp-p2\" st-sort\u003d\"protected\" translate\u003eProtected\u003c/th\u003e"},{"line_number":42,"context_line":"      \u003cth class\u003d\"rsp-p2\" st-sort\u003d\"disk_format\" translate\u003eFormat\u003c/th\u003e"},{"line_number":43,"context_line":"      \u003cth class\u003d\"rsp-p2\" st-sort\u003d\"size\" translate\u003eSize\u003c/th\u003e"},{"line_number":44,"context_line":"      \u003cth\u003e\u003c/th\u003e"},{"line_number":45,"context_line":"    \u003c/tr\u003e"},{"line_number":46,"context_line":"  \u003c/thead\u003e"},{"line_number":47,"context_line":""}],"source_content_type":"text/html","patch_set":52,"id":"da85f559_c29b1e71","line":44,"updated":"2015-11-10 15:14:33.000000000","message":"what\u0027s this empty header for?","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":18508,"name":"Errol Pais","email":"errol.pais@protonmail.com","username":"errol"},"change_message_id":"3a61d335e90e14bae1148c1c09385b10a3625b5f","unresolved":false,"context_lines":[{"line_number":41,"context_line":"      \u003cth class\u003d\"rsp-p2\" st-sort\u003d\"protected\" translate\u003eProtected\u003c/th\u003e"},{"line_number":42,"context_line":"      \u003cth class\u003d\"rsp-p2\" st-sort\u003d\"disk_format\" translate\u003eFormat\u003c/th\u003e"},{"line_number":43,"context_line":"      \u003cth class\u003d\"rsp-p2\" st-sort\u003d\"size\" translate\u003eSize\u003c/th\u003e"},{"line_number":44,"context_line":"      \u003cth\u003e\u003c/th\u003e"},{"line_number":45,"context_line":"    \u003c/tr\u003e"},{"line_number":46,"context_line":"  \u003c/thead\u003e"},{"line_number":47,"context_line":""}],"source_content_type":"text/html","patch_set":52,"id":"da85f559_f59da266","line":44,"in_reply_to":"da85f559_c29b1e71","updated":"2015-11-11 21:51:19.000000000","message":"Done","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":17,"context_line":"      \u003cth colspan\u003d\"100\" class\u003d\"search-header\"\u003e"},{"line_number":18,"context_line":"        \u003chz-search-bar group-classes\u003d\"input-group-sm\" icon-classes\u003d\"fa-search\"\u003e"},{"line_number":19,"context_line":"          \u003cactions allowed-actions\u003d\"table.batchActions.actions\" action-list-type\u003d\"batch\"\u003e"},{"line_number":20,"context_line":"          \u003c/actions\u003e"},{"line_number":21,"context_line":"        \u003c/hz-search-bar\u003e"},{"line_number":22,"context_line":"      \u003c/th\u003e"},{"line_number":23,"context_line":"    \u003c/tr\u003e"}],"source_content_type":"text/html","patch_set":72,"id":"7a740942_9c5f1c0e","line":20,"updated":"2015-12-03 23:57:44.000000000","message":"I\u0027d actually like to see this as a function that takes a prefix in for the patch to callback function.  See my comments here (yes, that is row action, but similar concerns apply):\n\nhttps://review.openstack.org/#/c/217422/72/openstack_dashboard/static/app/core/images/table/row-actions.service.js","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"cb539b07d47de9fefa30933ad3949bc1f486c0c4","unresolved":false,"context_lines":[{"line_number":17,"context_line":"      \u003cth colspan\u003d\"100\" class\u003d\"search-header\"\u003e"},{"line_number":18,"context_line":"        \u003chz-search-bar group-classes\u003d\"input-group-sm\" icon-classes\u003d\"fa-search\"\u003e"},{"line_number":19,"context_line":"          \u003cactions allowed-actions\u003d\"table.batchActions.actions\" action-list-type\u003d\"batch\"\u003e"},{"line_number":20,"context_line":"          \u003c/actions\u003e"},{"line_number":21,"context_line":"        \u003c/hz-search-bar\u003e"},{"line_number":22,"context_line":"      \u003c/th\u003e"},{"line_number":23,"context_line":"    \u003c/tr\u003e"}],"source_content_type":"text/html","patch_set":72,"id":"5a710552_56d1aafa","line":20,"in_reply_to":"7a740942_9c5f1c0e","updated":"2015-12-14 18:48:20.000000000","message":"After discussion with Thai, I definitely agree it is better to not use a prefix at all and we should be taking the function directly from the service and item in as separate inputs.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":81,"context_line":"        Table-row-action-column:"},{"line_number":82,"context_line":"        Actions taken here applies to a single item/row."},{"line_number":83,"context_line":"        --\u003e"},{"line_number":84,"context_line":"        \u003cactions allowed-actions\u003d\"table.rowActions.actions(image)\" action-list-type\u003d\"row\"\u003e"},{"line_number":85,"context_line":"        \u003c/actions\u003e"},{"line_number":86,"context_line":"      \u003c/td\u003e"},{"line_number":87,"context_line":"    \u003c/tr\u003e"}],"source_content_type":"text/html","patch_set":72,"id":"7a740942_5768adf5","line":84,"updated":"2015-12-03 23:57:44.000000000","message":"This needs to take in some sort of action callback prefix along with the image.  See my comments here.\n\nhttps://review.openstack.org/#/c/217422/72/openstack_dashboard/static/app/core/images/table/row-actions.service.js\n\nBasically, here\u0027s how I see it.\n\nIt is okay for the HTML to know about the controller.\n\nIt is okay for the controller to know about the services that it injects and their exposed functions.\n\nIt is NOT okay for the services injected into the controller to have to know about the HTML they are used in (controller name) or the variable name they are assigned to within the controller.  That is an incorrect usage of dependency injection and will be problematic for the uses I mentioned with searchlight in previous general comments on this patch.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"cb539b07d47de9fefa30933ad3949bc1f486c0c4","unresolved":false,"context_lines":[{"line_number":81,"context_line":"        Table-row-action-column:"},{"line_number":82,"context_line":"        Actions taken here applies to a single item/row."},{"line_number":83,"context_line":"        --\u003e"},{"line_number":84,"context_line":"        \u003cactions allowed-actions\u003d\"table.rowActions.actions(image)\" action-list-type\u003d\"row\"\u003e"},{"line_number":85,"context_line":"        \u003c/actions\u003e"},{"line_number":86,"context_line":"      \u003c/td\u003e"},{"line_number":87,"context_line":"    \u003c/tr\u003e"}],"source_content_type":"text/html","patch_set":72,"id":"5a710552_d6035a75","line":84,"in_reply_to":"7a740942_5768adf5","updated":"2015-12-14 18:48:20.000000000","message":"After discussion with Thai, I definitely agree it is better to not use a prefix at all and we should be taking the function directly from the service and item in as separate inputs.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"}],"openstack_dashboard/static/app/core/images/table/row-actions.service.js":[{"author":{"_account_id":15742,"name":"Paulo Ewerton Gomes Fragoso","email":"pauloewerton@lsd.ufcg.edu.br","username":"pauloewerton"},"change_message_id":"8d91d1de4991395f39c23517a5f1626284e20502","unresolved":false,"context_lines":[{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    var service \u003d {"},{"line_number":48,"context_line":"      initScope: initScope,"},{"line_number":49,"context_line":"      delete: deleteService,"},{"line_number":50,"context_line":"      actions: actions"},{"line_number":51,"context_line":"    };"},{"line_number":52,"context_line":""}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_c2455eb3","line":49,"updated":"2015-11-10 15:14:33.000000000","message":"I wonder if using this \u0027delete\u0027 reserved word will have any undesired side effects","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":18508,"name":"Errol Pais","email":"errol.pais@protonmail.com","username":"errol"},"change_message_id":"3a61d335e90e14bae1148c1c09385b10a3625b5f","unresolved":false,"context_lines":[{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    var service \u003d {"},{"line_number":48,"context_line":"      initScope: initScope,"},{"line_number":49,"context_line":"      delete: deleteService,"},{"line_number":50,"context_line":"      actions: actions"},{"line_number":51,"context_line":"    };"},{"line_number":52,"context_line":""}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_5fe6dbe8","line":49,"in_reply_to":"da85f559_c2455eb3","updated":"2015-11-11 21:51:19.000000000","message":"renamed it to deleteImage","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":15742,"name":"Paulo Ewerton Gomes Fragoso","email":"pauloewerton@lsd.ufcg.edu.br","username":"pauloewerton"},"change_message_id":"8d91d1de4991395f39c23517a5f1626284e20502","unresolved":false,"context_lines":[{"line_number":57,"context_line":"    function initScope(scope) {"},{"line_number":58,"context_line":"      // pass child scope onto actions"},{"line_number":59,"context_line":"      // so that actions can emit events"},{"line_number":60,"context_line":"      angular.forEach(service, function(action) {"},{"line_number":61,"context_line":"        if (action.initScope) {"},{"line_number":62,"context_line":"          action.initScope(scope.$new());"},{"line_number":63,"context_line":"        }"}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_42108ea8","line":60,"updated":"2015-11-10 15:14:33.000000000","message":"nit: anonymous function","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":18508,"name":"Errol Pais","email":"errol.pais@protonmail.com","username":"errol"},"change_message_id":"3a61d335e90e14bae1148c1c09385b10a3625b5f","unresolved":false,"context_lines":[{"line_number":57,"context_line":"    function initScope(scope) {"},{"line_number":58,"context_line":"      // pass child scope onto actions"},{"line_number":59,"context_line":"      // so that actions can emit events"},{"line_number":60,"context_line":"      angular.forEach(service, function(action) {"},{"line_number":61,"context_line":"        if (action.initScope) {"},{"line_number":62,"context_line":"          action.initScope(scope.$new());"},{"line_number":63,"context_line":"        }"}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_b5915a49","line":60,"in_reply_to":"da85f559_42108ea8","updated":"2015-11-11 21:51:19.000000000","message":"Done","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    function actions(image) {"},{"line_number":76,"context_line":"      return [{"},{"line_number":77,"context_line":"        callback: \u0027table.rowActions.deleteImage.open\u0027,"},{"line_number":78,"context_line":"        template: {"},{"line_number":79,"context_line":"          text: gettext(\u0027Delete Image\u0027),"},{"line_number":80,"context_line":"          type: \u0027delete\u0027,"}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_b768f1bb","line":77,"updated":"2015-12-03 23:57:44.000000000","message":"Okay, this actually makes me very nervous. The service is essentially aware of the fact that the controller is \"table\" and that this service is assigned to a variable name \"rowActions\" within the controller.\n\nThis mostly makes me think this is very wrong, because this is injected as a dependency into the table controller and it knows what it will assigned to within the controller.\n\nPart of me thinks it is okay because it is a form of programming by convention.\n\nBut I\u0027m very worried about how I\u0027ll use this from the searchlight table where I will inject row actions across different types of resources.  How would I use this when each row may have different actions?  That controller can\u0027t set the top level table rowActions to this object. Rather it would be looking up all the actions.\n\nBasically, here\u0027s how I see it.\n\nIt is okay for the HTML to know about the controller.\n\nIt is okay for the controller to know about the services that it injects and their exposed functions.\n\nIt is NOT okay for the services injected into the controller to have to know about the HTML they are used in (controller name) or the variable name they are assigned to within the controller.  That is an incorrect usage of dependency injection and will be problematic for the uses I mentioned with searchlight in previous general comments on this patch.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"c563dcf1ff9f388c20635844459fdff42bf3cea5","unresolved":false,"context_lines":[{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    function actions(image) {"},{"line_number":76,"context_line":"      return [{"},{"line_number":77,"context_line":"        callback: \u0027table.rowActions.deleteImage.open\u0027,"},{"line_number":78,"context_line":"        template: {"},{"line_number":79,"context_line":"          text: gettext(\u0027Delete Image\u0027),"},{"line_number":80,"context_line":"          type: \u0027delete\u0027,"}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_5ab09f43","line":77,"in_reply_to":"7a740942_b768f1bb","updated":"2015-12-04 21:51:52.000000000","message":"\u0027table.rowActions.deleteImage.open\u0027 is deleteService.open. Just use that here instead and problem solve. Furthermore, specifying it in string notation work? https://github.com/openstack/horizon/blob/d38bb868da15acde3ce50dfc9aeb3cacc0c697c5/horizon/static/framework/widgets/action-list/actions.service.js#L131","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"12cbee2bf5678a058a0ce94e401e2fce9b5e5bc4","unresolved":false,"context_lines":[{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    function actions(image) {"},{"line_number":76,"context_line":"      return [{"},{"line_number":77,"context_line":"        callback: \u0027table.rowActions.deleteImage.open\u0027,"},{"line_number":78,"context_line":"        template: {"},{"line_number":79,"context_line":"          text: gettext(\u0027Delete Image\u0027),"},{"line_number":80,"context_line":"          type: \u0027delete\u0027,"}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_12b0f3f3","line":77,"in_reply_to":"7a740942_b768f1bb","updated":"2015-12-04 00:03:42.000000000","message":"Copying from my general comments before:\n\nThere is one thing that I spoke with Thai and other about at the summit, which we really need and I\u0027d like to ensure we can accomplish easily in a follow up patch (if not sooner). I just want to make sure that these actions are in a state that can support the following concept:\n\nThat is the ability to lookup up actions for a given resource type so that they can be added to any page easily. The idea we came up with is something like an action registry service eg (total pseudo code below.:\n\n actionRegistry \u003d {\n   getActions: function(resourceType),\n   registerAction: function(resourceType, action)\n }\n\nThis would be injected into actions and they would register themselves. For example, glance actions would be something like:\n\n   registerAction(\"OS::Glance::Image\", this);\n\nThe actions should completely be self contained in terms of policy, etc, so any page that wants to inject the actions for the type of service doesn\u0027t do anything more than:\n\n   getActions(\"OS::Glance::Image\")\n\nAnd then they render. See my searchlight panel patch. I specifically want to be able lookup the actions based on resource type and add them as row actions dynamically.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"12cbee2bf5678a058a0ce94e401e2fce9b5e5bc4","unresolved":false,"context_lines":[{"line_number":74,"context_line":""},{"line_number":75,"context_line":"    function actions(image) {"},{"line_number":76,"context_line":"      return [{"},{"line_number":77,"context_line":"        callback: \u0027table.rowActions.deleteImage.open\u0027,"},{"line_number":78,"context_line":"        template: {"},{"line_number":79,"context_line":"          text: gettext(\u0027Delete Image\u0027),"},{"line_number":80,"context_line":"          type: \u0027delete\u0027,"}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_92c5c35c","line":77,"in_reply_to":"7a740942_b768f1bb","updated":"2015-12-04 00:03:42.000000000","message":"Copying from my general comments before:\n\nThere is one thing that I spoke with Thai and other about at the summit, which we really need and I\u0027d like to ensure we can accomplish easily in a follow up patch (if not sooner). I just want to make sure that these actions are in a state that can support the following concept:\n\nThat is the ability to lookup up actions for a given resource type so that they can be added to any page easily. The idea we came up with is something like an action registry service eg (total pseudo code below.:\n\n actionRegistry \u003d {\n   getActions: function(resourceType),\n   registerAction: function(resourceType, action)\n }\n\nThis would be injected into actions and they would register themselves. For example, glance actions would be something like:\n\n   registerAction(\"OS::Glance::Image\", this);\n\nThe actions should completely be self contained in terms of policy, etc, so any page that wants to inject the actions for the type of service doesn\u0027t do anything more than:\n\n   getActions(\"OS::Glance::Image\")\n\nAnd then they render. See my searchlight panel patch. I specifically want to be able lookup the actions based on resource type and add them as row actions dynamically.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":84,"context_line":"      }];"},{"line_number":85,"context_line":"    }"},{"line_number":86,"context_line":""},{"line_number":87,"context_line":"    function imageDeletePermitted(image) {"},{"line_number":88,"context_line":"      return $q.all(["},{"line_number":89,"context_line":"        imageNotProtected(image),"},{"line_number":90,"context_line":"        deleteImagePromise,"}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_7c903096","line":87,"updated":"2015-12-03 23:57:44.000000000","message":"I think this function might need to be separated into something that can be leveraged by batch delete as I mentioned in other comments (the error messaging).","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"023f0dbfccaab2a72433822a7b7747345b14fd42","unresolved":false,"context_lines":[{"line_number":117,"context_line":"      return wrapInPromise(!image.protected);"},{"line_number":118,"context_line":"    }"},{"line_number":119,"context_line":""},{"line_number":120,"context_line":"    function wrapInPromise(check) {"},{"line_number":121,"context_line":"      var deferred \u003d $q.defer();"},{"line_number":122,"context_line":""},{"line_number":123,"context_line":"      if (check) {"}],"source_content_type":"text/javascript","patch_set":72,"id":"7a740942_5c30d456","line":120,"updated":"2015-12-03 23:57:44.000000000","message":"This is named a bit funny with no comments. Took me a second to figure out why you didn\u0027t just use $q.when.\n\nSeems like a great utility function we can extract out later.\n\n*Consider* (not required) a name like booleanPromise.\n\nCode is king, but a small comment here wouldn\u0027t hurt to prevent people like me from wondering why $q.when couldn\u0027t be used.","commit_id":"cddf589066c006949e1cea2ad0ec00fe6cbc678d"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"e575c6cb485a7c846751087265c2ef073b78d898","unresolved":false,"context_lines":[{"line_number":73,"context_line":""},{"line_number":74,"context_line":"    function actions(image) {"},{"line_number":75,"context_line":"      return [{"},{"line_number":76,"context_line":"        callback: deleteService.open,"},{"line_number":77,"context_line":"        template: {"},{"line_number":78,"context_line":"          text: gettext(\u0027Delete Image\u0027),"},{"line_number":79,"context_line":"          type: \u0027delete\u0027"}],"source_content_type":"text/javascript","patch_set":84,"id":"5a710552_0768caf4","line":76,"updated":"2015-12-14 19:31:16.000000000","message":"This is MUCH better! (vs what was in patch set 72).","commit_id":"cff1f7c89a22092bc0dee2be800e71797a018759"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"e575c6cb485a7c846751087265c2ef073b78d898","unresolved":false,"context_lines":[{"line_number":76,"context_line":"        callback: deleteService.open,"},{"line_number":77,"context_line":"        template: {"},{"line_number":78,"context_line":"          text: gettext(\u0027Delete Image\u0027),"},{"line_number":79,"context_line":"          type: \u0027delete\u0027"},{"line_number":80,"context_line":"        },"},{"line_number":81,"context_line":"        permissions: imageDeletePermitted(image)"},{"line_number":82,"context_line":"      }];"}],"source_content_type":"text/javascript","patch_set":84,"id":"5a710552_27814690","line":79,"updated":"2015-12-14 19:31:16.000000000","message":"Also great to see image string out of here and in actions so that the ng-repeat assigned name is in the html where it belongs.","commit_id":"cff1f7c89a22092bc0dee2be800e71797a018759"},{"author":{"_account_id":7665,"name":"Travis Tripp","email":"os.travis.tripp@gmail.com","username":"travis.tripp"},"change_message_id":"e575c6cb485a7c846751087265c2ef073b78d898","unresolved":false,"context_lines":[{"line_number":82,"context_line":"      }];"},{"line_number":83,"context_line":"    }"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    function imageDeletePermitted(image) {"},{"line_number":86,"context_line":"      return $q.all(["},{"line_number":87,"context_line":"        imageNotProtected(image),"},{"line_number":88,"context_line":"        deleteImagePromise,"}],"source_content_type":"text/javascript","patch_set":84,"id":"5a710552_67250ec1","line":85,"updated":"2015-12-14 19:31:16.000000000","message":"What are your plans for addressing my comments about this that I made in patch set 72?\n\n\"I think this function might need to be separated into something that can be leveraged by batch delete as I mentioned in other comments (the error messaging).\"","commit_id":"cff1f7c89a22092bc0dee2be800e71797a018759"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"58fc1b63ce74adb1d8001d87b6221b76ed03529f","unresolved":false,"context_lines":[{"line_number":82,"context_line":"      }];"},{"line_number":83,"context_line":"    }"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"    function imageDeletePermitted(image) {"},{"line_number":86,"context_line":"      return $q.all(["},{"line_number":87,"context_line":"        imageNotProtected(image),"},{"line_number":88,"context_line":"        deleteImagePromise,"}],"source_content_type":"text/javascript","patch_set":84,"id":"5a710552_19658e44","line":85,"in_reply_to":"5a710552_67250ec1","updated":"2015-12-14 20:14:31.000000000","message":"There\u0027s the option that I just thought of moving this over to the actual service which could determine viability of the action before performing it.\n\nThat\u0027ll change the way permissions are checked in this service and move that code to the actual service. Let me try it out and see how it looks and works","commit_id":"cff1f7c89a22092bc0dee2be800e71797a018759"},{"author":{"_account_id":15424,"name":"javeme","email":"javaloveme@gmail.com","username":"javeme"},"change_message_id":"cd4a51592ff6f5242a2c6ef63772a23ebd96ee66","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    ///////////////"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    function initScope(scope) {"},{"line_number":46,"context_line":"      angular.forEach([deleteService], setActionScope);"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"      function setActionScope(action) {"},{"line_number":49,"context_line":"        action.initScope(scope.$new());"}],"source_content_type":"text/javascript","patch_set":97,"id":"1a7b0d38_d4477b75","line":46,"range":{"start_line":46,"start_character":14,"end_line":46,"end_character":21},"updated":"2015-12-24 16:32:35.000000000","message":"ditto","commit_id":"747faa769da99e96450aee8345f0f7d71756d624"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"c6ef3b3d6627c745b4750597421d7e3e7ec7d780","unresolved":false,"context_lines":[{"line_number":43,"context_line":"    ///////////////"},{"line_number":44,"context_line":""},{"line_number":45,"context_line":"    function initScope(scope) {"},{"line_number":46,"context_line":"      angular.forEach([deleteService], setActionScope);"},{"line_number":47,"context_line":""},{"line_number":48,"context_line":"      function setActionScope(action) {"},{"line_number":49,"context_line":"        action.initScope(scope.$new());"}],"source_content_type":"text/javascript","patch_set":97,"id":"1a7b0d38_1bf9a74d","line":46,"range":{"start_line":46,"start_character":14,"end_line":46,"end_character":21},"in_reply_to":"1a7b0d38_d4477b75","updated":"2015-12-25 07:44:48.000000000","message":"Not all Services need to called initScope on. There\u0027s a couple of patches that depend on this that add more actions where it\u0027s not needed.\n\nIt might make more sense if \"row-actions\" service had a common implementation but it\u0027s not this patch to create that.","commit_id":"747faa769da99e96450aee8345f0f7d71756d624"},{"author":{"_account_id":12071,"name":"Richard Jones","email":"r1chardj0n3s@gmail.com","username":"richard"},"change_message_id":"6aebb379adff7fdf092d0ad8a96535c34eee1fdc","unresolved":false,"context_lines":[{"line_number":17,"context_line":""},{"line_number":18,"context_line":"  angular"},{"line_number":19,"context_line":"    .module(\u0027horizon.app.core.images\u0027)"},{"line_number":20,"context_line":"    .factory(\u0027horizon.app.core.images.row-actions.service\u0027, rowActions);"},{"line_number":21,"context_line":""},{"line_number":22,"context_line":"  rowActions.$inject \u003d ["},{"line_number":23,"context_line":"    \u0027horizon.app.core.images.actions.deleteService\u0027,"}],"source_content_type":"text/javascript","patch_set":102,"id":"fa69d971_d327e960","line":20,"updated":"2016-01-07 06:24:49.000000000","message":"Just noting that there\u0027s some inconsistency in the naming of services here. We have these two in this one file:\n\n  horizon.app.core.images.row-actions.service\n  horizon.app.core.images.actions.deleteService\n\nWe should really pick one, I think :-)\n\nI like the former because it mirrors the filename. But then again, it doesn\u0027t completely reflect the filesystem path. Ho hum.","commit_id":"5f134d3281235d4d93b20d926e3daf9f8b964d02"}],"openstack_dashboard/static/app/core/images/table/row-actions.service.spec.js":[{"author":{"_account_id":15742,"name":"Paulo Ewerton Gomes Fragoso","email":"pauloewerton@lsd.ufcg.edu.br","username":"pauloewerton"},"change_message_id":"8d91d1de4991395f39c23517a5f1626284e20502","unresolved":false,"context_lines":[{"line_number":41,"context_line":"    ///////////////////////"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    beforeEach(module(\u0027ui.bootstrap\u0027));"},{"line_number":44,"context_line":"    beforeEach(module(\u0027horizon.framework\u0027));"},{"line_number":45,"context_line":"    beforeEach(module(\u0027horizon.app.core\u0027));"},{"line_number":46,"context_line":"    beforeEach(module(\u0027horizon.app.core.images\u0027));"},{"line_number":47,"context_line":""}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_a2785af3","line":44,"updated":"2015-11-10 15:14:33.000000000","message":"can use only horizon.framework","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"},{"author":{"_account_id":18508,"name":"Errol Pais","email":"errol.pais@protonmail.com","username":"errol"},"change_message_id":"3a61d335e90e14bae1148c1c09385b10a3625b5f","unresolved":false,"context_lines":[{"line_number":41,"context_line":"    ///////////////////////"},{"line_number":42,"context_line":""},{"line_number":43,"context_line":"    beforeEach(module(\u0027ui.bootstrap\u0027));"},{"line_number":44,"context_line":"    beforeEach(module(\u0027horizon.framework\u0027));"},{"line_number":45,"context_line":"    beforeEach(module(\u0027horizon.app.core\u0027));"},{"line_number":46,"context_line":"    beforeEach(module(\u0027horizon.app.core.images\u0027));"},{"line_number":47,"context_line":""}],"source_content_type":"text/javascript","patch_set":52,"id":"da85f559_f5e362a2","line":44,"in_reply_to":"da85f559_a2785af3","updated":"2015-11-11 21:51:19.000000000","message":"Done","commit_id":"b2cd229795468f12df74d2560579a364da2507d0"}],"openstack_dashboard/static/app/core/openstack-service-api/glance.service.js":[{"author":{"_account_id":5623,"name":"David Lyle","email":"dklyle0@gmail.com","username":"david-lyle"},"change_message_id":"02445e416b695737dbeb1bd404c19d5c3f54f583","unresolved":false,"context_lines":[{"line_number":71,"context_line":"    function deleteImages(imageIds) {"},{"line_number":72,"context_line":"      return apiService.delete(\u0027/api/glance/images/\u0027, imageIds)"},{"line_number":73,"context_line":"        .error(function () {"},{"line_number":74,"context_line":"          toastService.add(\u0027error\u0027, gettext(\u0027Unable to delete the images.\u0027));"},{"line_number":75,"context_line":"        });"},{"line_number":76,"context_line":"    }"},{"line_number":77,"context_line":""}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_aa72b60f","line":74,"updated":"2015-09-02 18:04:49.000000000","message":"This is unhelpful. Should be a list of images that we failed to delete with their IDs.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"408a8b97f9a577f8835b7398d6094a588ec64f4d","unresolved":false,"context_lines":[{"line_number":71,"context_line":"    function deleteImages(imageIds) {"},{"line_number":72,"context_line":"      return apiService.delete(\u0027/api/glance/images/\u0027, imageIds)"},{"line_number":73,"context_line":"        .error(function () {"},{"line_number":74,"context_line":"          toastService.add(\u0027error\u0027, gettext(\u0027Unable to delete the images.\u0027));"},{"line_number":75,"context_line":"        });"},{"line_number":76,"context_line":"    }"},{"line_number":77,"context_line":""}],"source_content_type":"text/javascript","patch_set":18,"id":"da20952f_72ef7987","line":74,"in_reply_to":"da20952f_aa72b60f","updated":"2015-09-03 21:45:50.000000000","message":"We deleted this in favor of having a single delete API call and combining the errors later.","commit_id":"20e15820c91deea58840eae40fb55fe0a998385e"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"219c1698c54ba473ddcb7841fed4e1d4c2621254","unresolved":false,"context_lines":[{"line_number":69,"context_line":"     * The Id of the image to delete"},{"line_number":70,"context_line":"     *"},{"line_number":71,"context_line":"     * @param {boolean} suppressError"},{"line_number":72,"context_line":"     * If passed in, this will not show the default error handling"},{"line_number":73,"context_line":"     * (horizon alert). The glance API may not have metadata definitions"},{"line_number":74,"context_line":"     * enabled."},{"line_number":75,"context_line":"     */"}],"source_content_type":"text/javascript","patch_set":28,"id":"9a1a9d01_edffc863","line":72,"updated":"2015-09-30 22:30:36.000000000","message":"This comment is incorrect. We are no longer using horizon alert, it is now the toast service.","commit_id":"8248308e50ca2b75364247c73dc1aa6adb4983ee"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"743c2aaec63c2b71359a092f2a28b9d2a13010f3","unresolved":false,"context_lines":[{"line_number":69,"context_line":"     * The Id of the image to delete"},{"line_number":70,"context_line":"     *"},{"line_number":71,"context_line":"     * @param {boolean} suppressError"},{"line_number":72,"context_line":"     * If passed in, this will not show the default error handling"},{"line_number":73,"context_line":"     * (horizon alert). The glance API may not have metadata definitions"},{"line_number":74,"context_line":"     * enabled."},{"line_number":75,"context_line":"     */"}],"source_content_type":"text/javascript","patch_set":28,"id":"9a1a9d01_5eb8d829","line":72,"in_reply_to":"9a1a9d01_edffc863","updated":"2015-09-30 23:49:33.000000000","message":"Done","commit_id":"8248308e50ca2b75364247c73dc1aa6adb4983ee"}],"openstack_dashboard/static/app/core/openstack-service-api/glance.service.spec.js":[{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"292625c1352823e8feb4d223c22283f18bbb61bd","unresolved":false,"context_lines":[{"line_number":94,"context_line":"        \"func\": \"deleteImages\","},{"line_number":95,"context_line":"        \"method\": \"delete\","},{"line_number":96,"context_line":"        \"path\": \"/api/glance/images/\","},{"line_number":97,"context_line":"        \"data\": ["},{"line_number":98,"context_line":"          1,"},{"line_number":99,"context_line":"          2,"},{"line_number":100,"context_line":"          3"}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_123f2288","line":97,"updated":"2015-08-28 18:15:13.000000000","message":"why not just data: [1, 2, 3] ? that is a lot of line breaks","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"a7511580eb4022bfb08c538f7627cfb919c10e2a","unresolved":false,"context_lines":[{"line_number":94,"context_line":"        \"func\": \"deleteImages\","},{"line_number":95,"context_line":"        \"method\": \"delete\","},{"line_number":96,"context_line":"        \"path\": \"/api/glance/images/\","},{"line_number":97,"context_line":"        \"data\": ["},{"line_number":98,"context_line":"          1,"},{"line_number":99,"context_line":"          2,"},{"line_number":100,"context_line":"          3"}],"source_content_type":"text/javascript","patch_set":6,"id":"da20952f_3e70eddb","line":97,"in_reply_to":"da20952f_123f2288","updated":"2015-08-28 20:30:07.000000000","message":"Done","commit_id":"05244fff8997a30599490a921a997046be476dda"},{"author":{"_account_id":9576,"name":"Thai Tran","email":"tqtran@us.ibm.com","username":"tqtran"},"change_message_id":"219c1698c54ba473ddcb7841fed4e1d4c2621254","unresolved":false,"context_lines":[{"line_number":21,"context_line":"    var testCall, service, $q, $rootScope;"},{"line_number":22,"context_line":"    var apiService \u003d {};"},{"line_number":23,"context_line":"    var toastService \u003d {};"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"    beforeEach(function() {"},{"line_number":26,"context_line":"      module("},{"line_number":27,"context_line":"        \u0027horizon.mock.openstack-service-api\u0027,"}],"source_content_type":"text/javascript","patch_set":28,"id":"9a1a9d01_2d662051","line":24,"updated":"2015-09-30 22:30:36.000000000","message":"a bit hard to follow due to code formatting","commit_id":"8248308e50ca2b75364247c73dc1aa6adb4983ee"},{"author":{"_account_id":17013,"name":"Rajat Vig","email":"rajatv@thoughtworks.com","username":"rajatvig"},"change_message_id":"743c2aaec63c2b71359a092f2a28b9d2a13010f3","unresolved":false,"context_lines":[{"line_number":21,"context_line":"    var testCall, service, $q, $rootScope;"},{"line_number":22,"context_line":"    var apiService \u003d {};"},{"line_number":23,"context_line":"    var toastService \u003d {};"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"    beforeEach(function() {"},{"line_number":26,"context_line":"      module("},{"line_number":27,"context_line":"        \u0027horizon.mock.openstack-service-api\u0027,"}],"source_content_type":"text/javascript","patch_set":28,"id":"9a1a9d01_bec25483","line":24,"in_reply_to":"9a1a9d01_2d662051","updated":"2015-09-30 23:49:33.000000000","message":"Done. The $q remained from a previous iteration on the code. Thanks for checking it out.","commit_id":"8248308e50ca2b75364247c73dc1aa6adb4983ee"}]}
