)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"e3201b89ad4c7976711c805a606d5e1de12a0f4f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"cf48fdd4_b14006ee","updated":"2026-05-31 19:21:06.000000000","message":"@gthiemon@redhat.com Hello, please find time for look it, we really need update UI to more friendly ;)","commit_id":"b0b7b4f254f142437324170cc8ef9341ce873128"},{"author":{"_account_id":38562,"name":"Richard Cruise","email":"rcruise@redhat.com","username":"rcruise"},"change_message_id":"0fc6acbe2895636f6295f9c04ab30c8d316b0aa4","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":15,"id":"d0fc471d_7c404869","updated":"2026-05-26 10:03:18.000000000","message":"LGTM, reviewed with assistacne from Claude Sonnet 4.6","commit_id":"b0b7b4f254f142437324170cc8ef9341ce873128"}],"octavia_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.js":[{"author":{"_account_id":38562,"name":"Richard Cruise","email":"rcruise@redhat.com","username":"rcruise"},"tag":"autogenerated:claude-review","change_message_id":"4a64e4aeb6135b00946dc89281f2a0d82fd3726c","unresolved":false,"context_lines":[{"line_number":93,"context_line":"      l7ruleCompareTypes: [\u0027REGEX\u0027, \u0027EQUAL_TO\u0027, \u0027STARTS_WITH\u0027, \u0027ENDS_WITH\u0027, \u0027CONTAINS\u0027],"},{"line_number":94,"context_line":"      l7ruleFileTypeCompareTypes: [\u0027REGEX\u0027, \u0027EQUAL_TO\u0027],"},{"line_number":95,"context_line":"      poolProtocols: [\u0027HTTP\u0027, \u0027HTTPS\u0027, \u0027PROXY\u0027, \u0027PROXYV2\u0027, \u0027TCP\u0027, \u0027UDP\u0027, \u0027SCTP\u0027],"},{"line_number":96,"context_line":"      methods: ["},{"line_number":97,"context_line":"        {value: \u0027LEAST_CONNECTIONS\u0027, label: gettext(\u0027Least Connections\u0027)},"},{"line_number":98,"context_line":"        {value: \u0027ROUND_ROBIN\u0027, label: gettext(\u0027Round Robin\u0027)},"},{"line_number":99,"context_line":"        {value: \u0027SOURCE_IP\u0027, label: gettext(\u0027Source IP\u0027)},"},{"line_number":100,"context_line":"        {value: \u0027SOURCE_IP_PORT\u0027, label: gettext(\u0027Source IP:Port\u0027)}"},{"line_number":101,"context_line":"      ],"},{"line_number":102,"context_line":"      types: ["},{"line_number":103,"context_line":"        {value: \u0027SOURCE_IP\u0027, label: gettext(\u0027Source IP\u0027)},"},{"line_number":104,"context_line":"        {value: \u0027HTTP_COOKIE\u0027, label: gettext(\u0027HTTP Cookie\u0027)},"},{"line_number":105,"context_line":"        {value: \u0027APP_COOKIE\u0027, label: gettext(\u0027App Cookie\u0027)}"},{"line_number":106,"context_line":"      ],"},{"line_number":107,"context_line":"      monitorTypes: [\u0027HTTP\u0027, \u0027HTTPS\u0027, \u0027PING\u0027, \u0027TCP\u0027, \u0027TLS-HELLO\u0027, \u0027UDP-CONNECT\u0027, \u0027SCTP\u0027],"},{"line_number":108,"context_line":"      monitorMethods: [\u0027GET\u0027, \u0027HEAD\u0027, \u0027POST\u0027, \u0027PUT\u0027, \u0027DELETE\u0027,"},{"line_number":109,"context_line":"                       \u0027TRACE\u0027, \u0027OPTIONS\u0027, \u0027PATCH\u0027, \u0027CONNECT\u0027],"}],"source_content_type":"text/javascript","patch_set":14,"id":"d2ea08a9_f7aaaf78","line":106,"range":{"start_line":96,"start_character":0,"end_line":106,"end_character":0},"updated":"2026-05-26 09:21:53.000000000","message":"The `{value, label}` object pattern is the right approach. The `gettext()` call on the labels enables i18n extraction. This is consistent with `yesNoOptions` (lines 112–115) which already uses the same pattern.","commit_id":"b798ba4fbc439b806acda6e48c9ee7985015264d"}],"octavia_dashboard/static/dashboard/project/lbaasv2/workflow/model.service.spec.js":[{"author":{"_account_id":38562,"name":"Richard Cruise","email":"rcruise@redhat.com","username":"rcruise"},"tag":"autogenerated:claude-review","change_message_id":"4a64e4aeb6135b00946dc89281f2a0d82fd3726c","unresolved":false,"context_lines":[{"line_number":522,"context_line":"          \u0027UDP\u0027, \u0027SCTP\u0027]);"},{"line_number":523,"context_line":"      });"},{"line_number":524,"context_line":""},{"line_number":525,"context_line":"      it(\u0027has array of pool lb_algorithms\u0027, function() {"},{"line_number":526,"context_line":"        expect(model.methods).toEqual(["},{"line_number":527,"context_line":"          {value: \u0027LEAST_CONNECTIONS\u0027, label: \u0027Least Connections\u0027},"},{"line_number":528,"context_line":"          {value: \u0027ROUND_ROBIN\u0027, label: \u0027Round Robin\u0027},"},{"line_number":529,"context_line":"          {value: \u0027SOURCE_IP\u0027, label: \u0027Source IP\u0027},"},{"line_number":530,"context_line":"          {value: \u0027SOURCE_IP_PORT\u0027, label: \u0027Source IP:Port\u0027}"},{"line_number":531,"context_line":"        ]);"},{"line_number":532,"context_line":"      });"},{"line_number":533,"context_line":""},{"line_number":534,"context_line":"      it(\u0027has array of pool session persistence types\u0027, function() {"},{"line_number":535,"context_line":"        expect(model.types).toEqual(["},{"line_number":536,"context_line":"          {value: \u0027SOURCE_IP\u0027, label: \u0027Source IP\u0027},"},{"line_number":537,"context_line":"          {value: \u0027HTTP_COOKIE\u0027, label: \u0027HTTP Cookie\u0027},"},{"line_number":538,"context_line":"          {value: \u0027APP_COOKIE\u0027, label: \u0027App Cookie\u0027}"},{"line_number":539,"context_line":"        ]);"},{"line_number":540,"context_line":"      });"},{"line_number":541,"context_line":""},{"line_number":542,"context_line":"      it(\u0027has array of monitor types\u0027, function() {"},{"line_number":543,"context_line":"        expect(model.monitorTypes).toEqual([\u0027HTTP\u0027, \u0027HTTPS\u0027, \u0027PING\u0027, \u0027TCP\u0027, \u0027TLS-HELLO\u0027,"},{"line_number":544,"context_line":"          \u0027UDP-CONNECT\u0027, \u0027SCTP\u0027]);"},{"line_number":545,"context_line":"      });"},{"line_number":546,"context_line":""},{"line_number":547,"context_line":"      it(\u0027has array of monitor http_methods\u0027, function() {"},{"line_number":548,"context_line":"        expect(model.monitorMethods).toEqual([\u0027GET\u0027, \u0027HEAD\u0027, \u0027POST\u0027, \u0027PUT\u0027, \u0027DELETE\u0027,"},{"line_number":549,"context_line":"          \u0027TRACE\u0027, \u0027OPTIONS\u0027, \u0027PATCH\u0027, \u0027CONNECT\u0027]);"},{"line_number":550,"context_line":"      });"},{"line_number":551,"context_line":""},{"line_number":552,"context_line":"      it(\u0027has an \"initialize\" function\u0027, function() {"}],"source_content_type":"text/javascript","patch_set":14,"id":"86c560ed_7a1f7313","line":549,"range":{"start_line":525,"start_character":0,"end_line":549,"end_character":0},"updated":"2026-05-26 09:21:53.000000000","message":"Tests correctly updated to assert the new object structure. Tests verify both `value` and `label` for each entry, which is appropriate coverage.","commit_id":"b798ba4fbc439b806acda6e48c9ee7985015264d"}],"octavia_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.help.html":[{"author":{"_account_id":38562,"name":"Richard Cruise","email":"rcruise@redhat.com","username":"rcruise"},"tag":"autogenerated:claude-review","change_message_id":"4a64e4aeb6135b00946dc89281f2a0d82fd3726c","unresolved":false,"context_lines":[{"line_number":7,"context_line":"  The load balancer algorithm that distributes traffic to the pool members."},{"line_number":8,"context_line":"  \u003c/translate\u003e"},{"line_number":9,"context_line":"  \u003cul\u003e"},{"line_number":10,"context_line":"    \u003cli translate\u003e"},{"line_number":11,"context_line":"       \u003cstrong\u003eLeast Connections\u003c/strong\u003e: Allocates requests to the instance with the least number of active"},{"line_number":12,"context_line":"      connections."},{"line_number":13,"context_line":"    \u003c/li\u003e"},{"line_number":14,"context_line":"    \u003cli translate\u003e"},{"line_number":15,"context_line":"       \u003cstrong\u003eRound Robin\u003c/strong\u003e: Rotates requests evenly between multiple instances."},{"line_number":16,"context_line":"    \u003c/li\u003e"},{"line_number":17,"context_line":"    \u003cli translate\u003e"},{"line_number":18,"context_line":"       \u003cstrong\u003eSource IP\u003c/strong\u003e: Requests from a unique source IP address are consistently directed to the same instance."},{"line_number":19,"context_line":"    \u003c/li\u003e"},{"line_number":20,"context_line":"    \u003cli translate\u003e"},{"line_number":21,"context_line":"      \u003cstrong\u003eSource IP:Port\u003c/strong\u003e: Requests from a unique source IP address and port pair are consistently directed to the same instance."},{"line_number":22,"context_line":"    \u003c/li\u003e"},{"line_number":23,"context_line":"  \u003c/ul\u003e"},{"line_number":24,"context_line":"\u003c/p\u003e"},{"line_number":25,"context_line":"\u003cp\u003e"},{"line_number":26,"context_line":"  \u003cstrong translate\u003eProtocol:\u003c/strong\u003e"}],"source_content_type":"text/html","patch_set":14,"id":"59d90134_1755ddf5","line":23,"range":{"start_line":10,"start_character":0,"end_line":23,"end_character":0},"updated":"2026-05-26 09:21:53.000000000","message":"Inconsistent leading whitespace. Lines with `\u003cstrong\u003eLeast Connections\u003c/strong\u003e`, `\u003cstrong\u003eRound Robin\u003c/strong\u003e`, and `\u003cstrong\u003eSource IP\u003c/strong\u003e` (first occurrence) have 7 spaces of leading whitespace, while `\u003cstrong\u003eSource IP:Port\u003c/strong\u003e` has 6. All should be consistent.\n\n**Lines 10, 14, 17, 20, 37, 40, 43** (`\u003cli translate\u003e` with embedded HTML):","commit_id":"b798ba4fbc439b806acda6e48c9ee7985015264d"},{"author":{"_account_id":37632,"name":"Dmitriy Chubinidze","email":"dcu995@gmail.com","username":"chubinidzedr"},"change_message_id":"385f222ed0c6dab6a665cb900729173be964efcc","unresolved":false,"context_lines":[{"line_number":7,"context_line":"  The load balancer algorithm that distributes traffic to the pool members."},{"line_number":8,"context_line":"  \u003c/translate\u003e"},{"line_number":9,"context_line":"  \u003cul\u003e"},{"line_number":10,"context_line":"    \u003cli translate\u003e"},{"line_number":11,"context_line":"       \u003cstrong\u003eLeast Connections\u003c/strong\u003e: Allocates requests to the instance with the least number of active"},{"line_number":12,"context_line":"      connections."},{"line_number":13,"context_line":"    \u003c/li\u003e"},{"line_number":14,"context_line":"    \u003cli translate\u003e"},{"line_number":15,"context_line":"       \u003cstrong\u003eRound Robin\u003c/strong\u003e: Rotates requests evenly between multiple instances."},{"line_number":16,"context_line":"    \u003c/li\u003e"},{"line_number":17,"context_line":"    \u003cli translate\u003e"},{"line_number":18,"context_line":"       \u003cstrong\u003eSource IP\u003c/strong\u003e: Requests from a unique source IP address are consistently directed to the same instance."},{"line_number":19,"context_line":"    \u003c/li\u003e"},{"line_number":20,"context_line":"    \u003cli translate\u003e"},{"line_number":21,"context_line":"      \u003cstrong\u003eSource IP:Port\u003c/strong\u003e: Requests from a unique source IP address and port pair are consistently directed to the same instance."},{"line_number":22,"context_line":"    \u003c/li\u003e"},{"line_number":23,"context_line":"  \u003c/ul\u003e"},{"line_number":24,"context_line":"\u003c/p\u003e"},{"line_number":25,"context_line":"\u003cp\u003e"},{"line_number":26,"context_line":"  \u003cstrong translate\u003eProtocol:\u003c/strong\u003e"}],"source_content_type":"text/html","patch_set":14,"id":"bb6323ae_568bdb65","line":23,"range":{"start_line":10,"start_character":0,"end_line":23,"end_character":0},"in_reply_to":"59d90134_1755ddf5","updated":"2026-05-26 09:29:02.000000000","message":"Thanks, corrected to consistent number of whitespaces","commit_id":"b798ba4fbc439b806acda6e48c9ee7985015264d"}],"octavia_dashboard/static/dashboard/project/lbaasv2/workflow/pool/pool.html":[{"author":{"_account_id":37598,"name":"Ivan Anfimov","display_name":"Ivan Anfimov","email":"lazekteam@gmail.com","username":"anfimovir"},"change_message_id":"c69c7380c09bfbf519e7a6cf2cc3f2ddfb0a69f5","unresolved":true,"context_lines":[{"line_number":84,"context_line":"          \u003c/label\u003e"},{"line_number":85,"context_line":"          \u003cselect class\u003d\"form-control\" name\u003d\"type\" id\u003d\"type\""},{"line_number":86,"context_line":"                  ng-model\u003d\"model.spec.pool.session_persistence.type\"\u003e"},{"line_number":87,"context_line":"            \u003coption value\u003d\"\"\u003eNone\u003c/option\u003e"},{"line_number":88,"context_line":"            \u003coption ng-repeat\u003d\"type in model.types\""},{"line_number":89,"context_line":"                    ng-disabled\u003d\"model.spec.listener.protocol \u003d\u003d\u003d \u0027UDP\u0027 \u0026\u0026 type.value !\u003d\u003d \u0027SOURCE_IP\u0027\""},{"line_number":90,"context_line":"                    value\u003d\"{$ type.value $}\"\u003e"}],"source_content_type":"text/html","patch_set":3,"id":"2650d7d9_2bbf46b1","line":87,"updated":"2026-03-25 11:12:10.000000000","message":"@dcu995@gmail.com may be add in translation?","commit_id":"cfad9b9833606c926787dad4e7cea6ec060c1479"},{"author":{"_account_id":37632,"name":"Dmitriy Chubinidze","email":"dcu995@gmail.com","username":"chubinidzedr"},"change_message_id":"412439e45c77788860a899b63cbadd9bf2cdda31","unresolved":false,"context_lines":[{"line_number":84,"context_line":"          \u003c/label\u003e"},{"line_number":85,"context_line":"          \u003cselect class\u003d\"form-control\" name\u003d\"type\" id\u003d\"type\""},{"line_number":86,"context_line":"                  ng-model\u003d\"model.spec.pool.session_persistence.type\"\u003e"},{"line_number":87,"context_line":"            \u003coption value\u003d\"\"\u003eNone\u003c/option\u003e"},{"line_number":88,"context_line":"            \u003coption ng-repeat\u003d\"type in model.types\""},{"line_number":89,"context_line":"                    ng-disabled\u003d\"model.spec.listener.protocol \u003d\u003d\u003d \u0027UDP\u0027 \u0026\u0026 type.value !\u003d\u003d \u0027SOURCE_IP\u0027\""},{"line_number":90,"context_line":"                    value\u003d\"{$ type.value $}\"\u003e"}],"source_content_type":"text/html","patch_set":3,"id":"40a1bb29_e5b4aa06","line":87,"in_reply_to":"2650d7d9_2bbf46b1","updated":"2026-03-25 11:17:58.000000000","message":"Done","commit_id":"cfad9b9833606c926787dad4e7cea6ec060c1479"},{"author":{"_account_id":38562,"name":"Richard Cruise","email":"rcruise@redhat.com","username":"rcruise"},"tag":"autogenerated:claude-review","change_message_id":"4a64e4aeb6135b00946dc89281f2a0d82fd3726c","unresolved":false,"context_lines":[{"line_number":50,"context_line":"            \u003cspan class\u003d\"hz-icon-required fa fa-asterisk\"\u003e\u003c/span\u003e"},{"line_number":51,"context_line":"          \u003c/label\u003e"},{"line_number":52,"context_line":"          \u003cselect class\u003d\"form-control\" name\u003d\"method\" id\u003d\"method\""},{"line_number":53,"context_line":"                  ng-options\u003d\"method.value as method.label for method in model.methods\""},{"line_number":54,"context_line":"                  ng-model\u003d\"model.spec.pool.lb_algorithm\""},{"line_number":55,"context_line":"                  ng-required\u003d\"true\"\u003e"},{"line_number":56,"context_line":"          \u003c/select\u003e"}],"source_content_type":"text/html","patch_set":14,"id":"34c0517a_0710a708","line":53,"updated":"2026-05-26 09:21:53.000000000","message":"This is the correct Angular `ng-options` syntax for separating display from model value. The `method.value` (API enum string) is bound to `ng-model`, so `model.spec.pool.lb_algorithm` correctly receives `\u0027ROUND_ROBIN\u0027` etc. when the user makes a selection, and when editing an existing pool (where `spec.lb_algorithm \u003d pool.lb_algorithm` sets it from the API), the dropdown correctly pre-selects based on the value match.","commit_id":"b798ba4fbc439b806acda6e48c9ee7985015264d"},{"author":{"_account_id":38562,"name":"Richard Cruise","email":"rcruise@redhat.com","username":"rcruise"},"tag":"autogenerated:claude-review","change_message_id":"4a64e4aeb6135b00946dc89281f2a0d82fd3726c","unresolved":false,"context_lines":[{"line_number":84,"context_line":"          \u003c/label\u003e"},{"line_number":85,"context_line":"          \u003cselect class\u003d\"form-control\" name\u003d\"type\" id\u003d\"type\""},{"line_number":86,"context_line":"                  ng-model\u003d\"model.spec.pool.session_persistence.type\"\u003e"},{"line_number":87,"context_line":"            \u003coption value\u003d\"\" translate\u003eNone\u003c/option\u003e"},{"line_number":88,"context_line":"            \u003coption ng-repeat\u003d\"type in model.types\""},{"line_number":89,"context_line":"                    ng-disabled\u003d\"model.spec.listener.protocol \u003d\u003d\u003d \u0027UDP\u0027 \u0026\u0026 type.value !\u003d\u003d \u0027SOURCE_IP\u0027\""},{"line_number":90,"context_line":"                    value\u003d\"{$ type.value $}\"\u003e"}],"source_content_type":"text/html","patch_set":14,"id":"b347053e_ec4a5d85","line":87,"updated":"2026-05-26 09:21:53.000000000","message":"Adding `translate` to the \"None\" option is a good fix for a pre-existing i18n omission.","commit_id":"b798ba4fbc439b806acda6e48c9ee7985015264d"},{"author":{"_account_id":38562,"name":"Richard Cruise","email":"rcruise@redhat.com","username":"rcruise"},"tag":"autogenerated:claude-review","change_message_id":"4a64e4aeb6135b00946dc89281f2a0d82fd3726c","unresolved":false,"context_lines":[{"line_number":85,"context_line":"          \u003cselect class\u003d\"form-control\" name\u003d\"type\" id\u003d\"type\""},{"line_number":86,"context_line":"                  ng-model\u003d\"model.spec.pool.session_persistence.type\"\u003e"},{"line_number":87,"context_line":"            \u003coption value\u003d\"\" translate\u003eNone\u003c/option\u003e"},{"line_number":88,"context_line":"            \u003coption ng-repeat\u003d\"type in model.types\""},{"line_number":89,"context_line":"                    ng-disabled\u003d\"model.spec.listener.protocol \u003d\u003d\u003d \u0027UDP\u0027 \u0026\u0026 type.value !\u003d\u003d \u0027SOURCE_IP\u0027\""},{"line_number":90,"context_line":"                    value\u003d\"{$ type.value $}\"\u003e"},{"line_number":91,"context_line":"              {$ type.label $}"},{"line_number":92,"context_line":"            \u003c/option\u003e"},{"line_number":93,"context_line":"          \u003c/select\u003e"},{"line_number":94,"context_line":"        \u003c/div\u003e"},{"line_number":95,"context_line":"      \u003c/div\u003e"}],"source_content_type":"text/html","patch_set":14,"id":"92cd791c_cda3aadd","line":92,"range":{"start_line":88,"start_character":0,"end_line":92,"end_character":0},"updated":"2026-05-26 09:21:53.000000000","message":"Using `ng-repeat` with explicit `value\u003d\"{$ type.value $}\"` and `{$ type.label $}` display is correct for the `\u003cselect\u003e/\u003coption\u003e` pattern (as opposed to `ng-options`). The `ng-disabled` condition correctly checks `type.value !\u003d\u003d \u0027SOURCE_IP\u0027` (previously was `type !\u003d\u003d \u0027SOURCE_IP\u0027` which would have compared the whole object).","commit_id":"b798ba4fbc439b806acda6e48c9ee7985015264d"}]}
