From 3d1ee732b4e2301a3f4280a9c292fb787abcee2a Mon Sep 17 00:00:00 2001 From: Cameron Perera Date: Thu, 12 Jun 2025 17:19:56 -0500 Subject: [PATCH] Icu 17232 improve host source resource fetching (#2877) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: 💡 add fallback value for address column ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-17232 * fix: 🐛 make host address optional in search for plugin hosts ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-17232 * feat: 🎸 remove pageSize reset for user preference ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-17232 * test: 💍 update e2e tests for host sources ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-17232 * feat: 🎸 improve host source resource fetching ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-17232 * refactor: 💡 remove em dash translation ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-17232 * refactor: 💡 add comment to target route for duplicate hosts ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-17232 * refactor: 💡 add filter to query for hosts ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-17232 * refactor: 💡 use Promise.all() when fetching hosts ✅ Closes: https://hashicorp.atlassian.net/browse/ICU-17232 --- addons/api/mirage/factories/target.js | 12 ++++++++ e2e-tests/desktop/tests/pagination.spec.js | 28 ++++++++++++----- .../scope/projects/targets/target/index.js | 2 +- .../scopes/scope/projects/targets/target.js | 30 ++++++++++--------- .../scope/projects/targets/target/index.js | 1 - .../scope/projects/targets/target/index.hbs | 8 +++-- 6 files changed, 54 insertions(+), 27 deletions(-) diff --git a/addons/api/mirage/factories/target.js b/addons/api/mirage/factories/target.js index 99ffb2bfa..c677e139f 100644 --- a/addons/api/mirage/factories/target.js +++ b/addons/api/mirage/factories/target.js @@ -120,6 +120,10 @@ export default factory.extend({ type: hostCatalog.type, }), ]; + const hostSetIds = hostSets.map((hostSet) => hostSet.id); + hosts.forEach((host) => { + host.update({ hostSetIds }); + }); target.update({ hostSets }); }, }), @@ -141,6 +145,10 @@ export default factory.extend({ type: hostCatalog.type, }), ]; + const hostSetIds = hostSets.map((hostSet) => hostSet.id); + hosts.forEach((host) => { + host.update({ hostSetIds }); + }); target.update({ hostSets }); }, }), @@ -160,6 +168,10 @@ export default factory.extend({ type: hostCatalog.type, }), ]; + const hostSetIds = hostSets.map((hostSet) => hostSet.id); + hosts.forEach((host) => { + host.update({ hostSetIds }); + }); target.update({ hostSets }); }, }), diff --git a/e2e-tests/desktop/tests/pagination.spec.js b/e2e-tests/desktop/tests/pagination.spec.js index 3c82ba5ab..3b2ac885a 100644 --- a/e2e-tests/desktop/tests/pagination.spec.js +++ b/e2e-tests/desktop/tests/pagination.spec.js @@ -63,11 +63,14 @@ test.describe('Search and Pagination', () => { // Check pagination await expect( - authedPage.getByRole('cell', { name: hosts[0].name, exact: true }), + authedPage.getByRole('cell', { + name: hosts[hosts.length - 1].name, + exact: true, + }), ).toBeVisible(); await expect( authedPage.getByRole('cell', { - name: hosts[hosts.length - 1].name, + name: hosts[0].name, exact: true, }), ).toBeHidden(); @@ -78,11 +81,14 @@ test.describe('Search and Pagination', () => { .getByRole('link', { name: 'page 2' }) .click(); await expect( - authedPage.getByRole('cell', { name: hosts[0].name, exact: true }), + authedPage.getByRole('cell', { + name: hosts[hosts.length - 1].name, + exact: true, + }), ).toBeHidden(); await expect( authedPage.getByRole('cell', { - name: hosts[hosts.length - 1].name, + name: hosts[0].name, exact: true, }), ).toBeVisible(); @@ -93,11 +99,14 @@ test.describe('Search and Pagination', () => { .getByRole('link', { name: 'Previous page' }) .click(); await expect( - authedPage.getByRole('cell', { name: hosts[0].name, exact: true }), + authedPage.getByRole('cell', { + name: hosts[hosts.length - 1].name, + exact: true, + }), ).toBeVisible(); await expect( authedPage.getByRole('cell', { - name: hosts[hosts.length - 1].name, + name: hosts[0].name, exact: true, }), ).toBeHidden(); @@ -108,11 +117,14 @@ test.describe('Search and Pagination', () => { .getByRole('link', { name: 'Next page' }) .click(); await expect( - authedPage.getByRole('cell', { name: hosts[0].name, exact: true }), + authedPage.getByRole('cell', { + name: hosts[hosts.length - 1].name, + exact: true, + }), ).toBeHidden(); await expect( authedPage.getByRole('cell', { - name: hosts[hosts.length - 1].name, + name: hosts[0].name, exact: true, }), ).toBeVisible(); diff --git a/ui/desktop/app/controllers/scopes/scope/projects/targets/target/index.js b/ui/desktop/app/controllers/scopes/scope/projects/targets/target/index.js index c8d31c49f..1e0aace03 100644 --- a/ui/desktop/app/controllers/scopes/scope/projects/targets/target/index.js +++ b/ui/desktop/app/controllers/scopes/scope/projects/targets/target/index.js @@ -39,7 +39,7 @@ export default class ScopesScopeProjectsTargetsTargetIndexController extends Con return ( host.displayName.toLowerCase().includes(searchTerm) || host.description?.toLowerCase().includes(searchTerm) || - host.address.toLowerCase().includes(searchTerm) + host.address?.toLowerCase().includes(searchTerm) ); }); } diff --git a/ui/desktop/app/routes/scopes/scope/projects/targets/target.js b/ui/desktop/app/routes/scopes/scope/projects/targets/target.js index 95577ac51..da30e8433 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/targets/target.js +++ b/ui/desktop/app/routes/scopes/scope/projects/targets/target.js @@ -42,22 +42,24 @@ export default class ScopesScopeProjectsTargetsTargetRoute extends Route { * from the model hook for hosts */ try { - const hostSets = await Promise.all( - target.host_sources.map(({ host_source_id }) => - this.store.findRecord('host-set', host_source_id), - ), - ); + const { host_sources } = target; - // Extract host ids from all host sets - const hostIds = hostSets.flatMap(({ host_ids }) => host_ids); + const allFilteredHosts = ( + await Promise.all( + host_sources.map((hostSource) => { + const query = { + host_catalog_id: hostSource.host_catalog_id, + filter: `("${hostSource.host_source_id}" in "/item/host_set_ids")`, + }; + return this.store.query('host', query); + }), + ) + ).flat(); - // Load unique hosts - const uniqueHostIds = new Set(hostIds); - - hosts = await Promise.all( - [...uniqueHostIds].map((hostId) => - this.store.findRecord('host', hostId), - ), + // Remove duplicate hosts based on their IDs + // This is necessary because a host can be part of multiple host sets + hosts = Array.from( + new Map(allFilteredHosts.map((host) => [host.id, host])).values(), ); } catch (error) { // no operation diff --git a/ui/desktop/app/routes/scopes/scope/projects/targets/target/index.js b/ui/desktop/app/routes/scopes/scope/projects/targets/target/index.js index 190af08ed..c1294517a 100644 --- a/ui/desktop/app/routes/scopes/scope/projects/targets/target/index.js +++ b/ui/desktop/app/routes/scopes/scope/projects/targets/target/index.js @@ -25,7 +25,6 @@ export default class ScopesScopeProjectsTargetsTargetIndexRoute extends Route { if (isExiting) { controller.set('search', ''); controller.set('page', 1); - controller.set('pageSize', 10); } } } diff --git a/ui/desktop/app/templates/scopes/scope/projects/targets/target/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/targets/target/index.hbs index 1d6394a00..b16433293 100644 --- a/ui/desktop/app/templates/scopes/scope/projects/targets/target/index.hbs +++ b/ui/desktop/app/templates/scopes/scope/projects/targets/target/index.hbs @@ -39,10 +39,13 @@ - {{B.data.address}} + {{#if B.data.address}} + {{B.data.address}} + {{else}} + — + {{/if}} - -