mirror of
https://github.com/superdesigndev/treg.git
synced 2026-10-02 03:24:35 +08:00
fix(dashboard): a find result opens its job, and Back returns to the Catalog page
- Back into the first entry of a page opened at /catalog (or /catalog/<slug>) showed "Your own tools": that entry has no history state and no hash, and popstate fell back to the tools view. It now resolves the view from the path, as the first load does. A bug on main that the find flow walks into. - A result opened from the Catalog page landed on its platform's shelf with the shelf's box filled with the row's name, which the always-ask box then filtered and searched by. It now opens the job: its comparison once the shelf has loaded (replacing the shelf's history entry, so Back returns to the answer), else the tool in the drawer; the shelf's box is never prefilled. openPlatform returns its load.
This commit is contained in:
@@ -102,6 +102,11 @@ this page keeps what no single file shows. The look follows the root `design.md`
|
||||
name keeps filtering and gets its answer too), and while it reads, or when it is `none` or empty,
|
||||
it is one line. Enter (or the suggestion row) asks for the full answer (`findFull`): shelves
|
||||
unfiltered and lit where it landed.
|
||||
- A find result opens its job (`findOpen`): the job's comparison on its platform when that shelf
|
||||
compares it, else the tool in the drawer; from the Catalog page the shelf loads first and the
|
||||
comparison replaces its history entry. Back returns to the Catalog page with the box, the answer
|
||||
and the filtered shelves as they were: the first entry of a page opened at `/catalog` (or
|
||||
`/catalog/<slug>`) has no history state, so popstate resolves it from the path.
|
||||
- A shelf's own box answers from that shelf only. An empty answer there is one line, "Nothing in
|
||||
<platform> for …", and "Search all tools" (`findEverywhere`) moves to the Catalog page with the box
|
||||
prefilled and the same words asked unscoped. "Request it" appears only on an unscoped gap (and on
|
||||
|
||||
@@ -99,3 +99,18 @@ test('an empty answer on a shelf offers the whole catalog, and asks it with the
|
||||
await expect(page.locator('.fa .ui-tbody .ui-tr')).toHaveCount(1)
|
||||
expect(asked.at(-1)).toEqual({ q: 'verify an email before sending', platform: null })
|
||||
})
|
||||
|
||||
test('a result opened from the Catalog page leads to its job, and Back returns to the Catalog page', async ({ page }) => {
|
||||
const asked = await answer(page, { verdict: 'strong', rows: [row('hunter.people.email.find', 0.9)] })
|
||||
await box(page).fill('find a work email')
|
||||
await expect.poll(() => asked).toEqual(['find a work email'])
|
||||
await page.locator('.fa .ui-tbody .ui-tr').first().click()
|
||||
// the job's own comparison on its platform, every provider of it
|
||||
await expect(page).toHaveURL(/\/catalog\/people\/[^/]+$/)
|
||||
await expect(page.locator('h1')).toContainText('work email')
|
||||
await page.goBack()
|
||||
await expect(page).toHaveURL(/\/catalog$/)
|
||||
await expect(page.locator('.pl.cat h1')).toContainText('tools for agents') // the Catalog page, not "Your own tools"
|
||||
await expect(box(page)).toHaveValue('find a work email')
|
||||
await expect(page.locator('.fa .ui-tbody .ui-tr')).toHaveCount(1) // the answer is still there
|
||||
})
|
||||
|
||||
@@ -30,6 +30,10 @@ export default async function boot(){
|
||||
if(d){ this.openDetail(d.kind, d.name, true); return; }
|
||||
const rid=(e.state&&e.state.run)||this.runFromPath(location.pathname);
|
||||
if(rid){ this.openRun(rid, true); return; }
|
||||
// The first entry of a page opened at a public catalog URL (/catalog, /catalog/<slug>) carries no
|
||||
// state and no hash: resolve it from the path, as the first load did, not as the tools view.
|
||||
const cr=!(e.state&&e.state.view) && !location.hash && this.catalogFromPath(location.pathname);
|
||||
if(cr){ this.openCatalogRoute(cr); return; }
|
||||
let v=(e.state&&e.state.view)||(location.hash||'').replace('#','')||'tools';
|
||||
if(v==='billing'){ this.orgTab='billing'; v='orgs'; }
|
||||
if(['tools','orgs','activity','usage','admin','help','secrets','start','resources','catalog','connections','referrals','hub'].includes(v)) this.go(v, true);
|
||||
|
||||
@@ -86,7 +86,7 @@ openPlatform(slug, fromPop, cap){ this.resetConfirms();
|
||||
// Connected/not-connected is a member fact and the endpoint needs a session; a public
|
||||
// visitor has none, so skip it rather than fire a guaranteed 401 on every shelf view.
|
||||
if(!this.publicCatalog && !this.providers.length) this.loadConnections();
|
||||
this.loadPlatform(); },
|
||||
return this.loadPlatform(); }, // the shelf's data, for a caller that acts on it once loaded
|
||||
// Where a provider name leads: the public provider page signed out, the provider's page in the app
|
||||
// signed in. Both list every tool the provider serves.
|
||||
provUrl(service){ return this.publicCatalog ? '/tools/'+encodeURIComponent(service) : '/app/marketplace/'+encodeURIComponent(service); },
|
||||
|
||||
+15
-12
@@ -214,20 +214,23 @@ export default {
|
||||
signed_in:!!this.authed, ...extra});
|
||||
},
|
||||
|
||||
// Open the platform shelf the row lives on, its search box filtered to this job.
|
||||
// On a shelf's own search the answer is already on that shelf: a job several providers do opens its
|
||||
// comparison, anything else opens in the tool drawer.
|
||||
findOpen(group, rank){
|
||||
// Open the job a row is: its comparison on its platform when that shelf compares it (several
|
||||
// providers), else the tool itself in the drawer. From another page the shelf is opened first and
|
||||
// the job chosen once its data is in, the comparison replacing the shelf's history entry so Back
|
||||
// returns to where the answer was. The shelf's own box is never filled with the row's name.
|
||||
async findOpen(group, rank){
|
||||
this.findTrackClick('job', group.platform, {provider:group.rows[0]?.provider, rank});
|
||||
if(this.view==='platform' && group.platform===this.platSlug){
|
||||
const cap=group.rows[0]?.capability;
|
||||
const job=cap && this.platComparisons.find(j=>j.key===cap);
|
||||
if(job) this.openComparison(job.slug);
|
||||
else this.openTool(group.rows[0].id);
|
||||
return;
|
||||
const slug=group.platform, cap=group.rows[0]?.capability, id=group.rows[0]?.id;
|
||||
const here=this.view==='platform' && slug===this.platSlug;
|
||||
if(!here){
|
||||
await this.openPlatform(slug);
|
||||
if(this.view!=='platform' || this.platSlug!==slug) return; // the person moved on meanwhile
|
||||
}
|
||||
this.openPlatform(group.platform);
|
||||
this.platQ=group.rows[0]?.name || group.label;
|
||||
const job=cap && this.platComparisons.find(j=>j.key===cap);
|
||||
if(!job){ this.openTool(id); return; }
|
||||
if(here){ this.openComparison(job.slug); return; }
|
||||
this.openPlatform(slug, true, job.slug);
|
||||
history.replaceState({platform:slug}, '', this.platUrl(slug, job.slug));
|
||||
},
|
||||
|
||||
// From /search into the dashboard: the platform's page. Signed
|
||||
|
||||
@@ -74,3 +74,30 @@ test('a shelf\'s answer asks the whole catalog with the same words', () => {
|
||||
find.findEverywhere.call(vm)
|
||||
expect(calls).toEqual([['exit'], ['go', 'catalog', 'verify emails'], ['run', 'verify emails', { scope: '' }]])
|
||||
})
|
||||
|
||||
test('a result opens its job: the comparison when its shelf has one, else the tool; never the shelf\'s box', async () => {
|
||||
const group = { platform: 'people', rows: [{ id: 'hunter.people.email.find', capability: 'people.email.find', provider: 'hunter' }] }
|
||||
const calls: any[] = []
|
||||
const replaced: any[] = []
|
||||
const history0 = globalThis.history
|
||||
;(globalThis as any).history = { replaceState: (...a: any[]) => replaced.push(a) }
|
||||
const vm: any = { view: 'catalog', platSlug: '', platQ: '', platComparisons: [] as any[],
|
||||
findTrackClick() {}, platUrl: (slug: string, key: string) => '/catalog/' + slug + '/' + key,
|
||||
async openPlatform(slug: string, fromPop?: boolean, key?: string) {
|
||||
calls.push(['platform', slug, fromPop ?? false, key ?? null]); this.view = 'platform'; this.platSlug = slug },
|
||||
openComparison(key: string) { calls.push(['comparison', key]) }, openTool(id: string) { calls.push(['tool', id]) } }
|
||||
try {
|
||||
vm.platComparisons = [{ key: 'people.email.find', slug: 'email.find' }]
|
||||
await find.findOpen.call(vm, group, 1) // from the Catalog page: shelf, then its job
|
||||
expect(calls).toEqual([['platform', 'people', false, null], ['platform', 'people', true, 'email.find']])
|
||||
expect(replaced).toEqual([[{ platform: 'people' }, '', '/catalog/people/email.find']])
|
||||
calls.length = 0
|
||||
await find.findOpen.call(vm, group, 1) // already on that shelf: the comparison directly
|
||||
expect(calls).toEqual([['comparison', 'email.find']])
|
||||
calls.length = 0
|
||||
vm.platComparisons = []
|
||||
await find.findOpen.call(vm, group, 1) // a job with no comparison: the tool
|
||||
expect(calls).toEqual([['tool', 'hunter.people.email.find']])
|
||||
expect(vm.platQ).toBe('')
|
||||
} finally { (globalThis as any).history = history0 }
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user