Skip to content

Commit 293328d

Browse files
authored
Support preselected examples in create listing modal (#4283)
* Support preselected examples in create listing modal * Fix removeSelectedExample to normalize URLs before filtering * fix lint * Replace test-only selector in runtime CSS * fix test * fix codex feedback & fix lint * update example field ui * fix host test
1 parent 109dc7a commit 293328d

11 files changed

Lines changed: 421 additions & 101 deletions

File tree

packages/host/app/commands/open-create-listing-modal.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { service } from '@ember/service';
22

3+
import { isFieldDef } from '@cardstack/runtime-common';
4+
import { loadCardDef } from '@cardstack/runtime-common/code-ref';
5+
36
import type * as BaseCommandModule from 'https://cardstack.com/base/command';
47

58
import HostBaseCommand from '../lib/host-base-command';
@@ -24,10 +27,23 @@ export default class OpenCreateListingModalCommand extends HostBaseCommand<
2427
protected async run(
2528
input: BaseCommandModule.ListingCreateInput,
2629
): Promise<undefined> {
30+
let declarationKind: 'card' | 'field' = 'card';
31+
if (input.codeRef) {
32+
try {
33+
let cardOrField = await loadCardDef(input.codeRef, {
34+
loader: this.loaderService.loader,
35+
});
36+
declarationKind = isFieldDef(cardOrField) ? 'field' : 'card';
37+
} catch {
38+
declarationKind = 'card';
39+
}
40+
}
41+
2742
this.operatorModeStateService.showCreateListingModal({
2843
codeRef: input.codeRef,
2944
targetRealm: input.targetRealm,
3045
openCardIds: input.openCardIds,
46+
declarationKind,
3147
});
3248
}
3349
}

packages/host/app/components/card-catalog/modal.gts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ type State = {
7676
availableRealmUrls: string[];
7777
hasPreselectedCard?: boolean;
7878
consumingRealm?: URL;
79+
preselectConsumingRealm?: boolean;
7980
};
8081

8182
function isNewCardArgs(item: string | NewCardArgs): item is NewCardArgs {
@@ -111,6 +112,8 @@ export default class CardCatalogModal extends Component<Signature> {
111112
@searchKey={{state.searchKey}}
112113
@baseFilter={{state.baseFilter}}
113114
@availableRealmUrls={{state.availableRealmUrls}}
115+
@consumingRealm={{state.consumingRealm}}
116+
@preselectConsumingRealm={{state.preselectConsumingRealm}}
114117
as |Bar Content|
115118
>
116119
<ModalContainer
@@ -259,6 +262,8 @@ export default class CardCatalogModal extends Component<Signature> {
259262
createNewCard?: CreateNewCard;
260263
preselectedCardTypeQuery?: Query;
261264
consumingRealm?: URL;
265+
preselectConsumingRealm?: boolean;
266+
preselectedCardUrls?: string[];
262267
},
263268
): Promise<undefined | string | string[]> {
264269
let result = await this._chooseCard.perform(
@@ -297,6 +302,8 @@ export default class CardCatalogModal extends Component<Signature> {
297302
multiSelect?: boolean;
298303
preselectedCardTypeQuery?: Query;
299304
consumingRealm?: URL;
305+
preselectConsumingRealm?: boolean;
306+
preselectedCardUrls?: string[];
300307
} = {},
301308
) => {
302309
await this.realmServer.ready;
@@ -342,6 +349,14 @@ export default class CardCatalogModal extends Component<Signature> {
342349
preselectedCardUrl = `${instances[0].id}.json`;
343350
}
344351
}
352+
let preselectedCardUrls = (
353+
opts?.preselectedCardUrls?.length
354+
? opts.preselectedCardUrls
355+
: preselectedCardUrl
356+
? [preselectedCardUrl]
357+
: []
358+
).map((url) => (url.endsWith('.json') ? url : `${url}.json`));
359+
345360
let cardCatalogState = new TrackedObject<State>({
346361
id: this.stateId,
347362
request,
@@ -350,10 +365,11 @@ export default class CardCatalogModal extends Component<Signature> {
350365
dismissModal: false,
351366
baseFilter: query.filter,
352367
availableRealmUrls: this.realmServer.availableRealmURLs,
353-
selectedCards: preselectedCardUrl ? [preselectedCardUrl] : [],
368+
selectedCards: preselectedCardUrls,
354369
multiSelect: opts?.multiSelect ?? false,
355-
hasPreselectedCard: Boolean(preselectedCardUrl),
370+
hasPreselectedCard: preselectedCardUrls.length > 0,
356371
consumingRealm: opts.consumingRealm,
372+
preselectConsumingRealm: opts.preselectConsumingRealm,
357373
});
358374
this.stateStack.push(cardCatalogState);
359375
return await request.deferred.promise;

packages/host/app/components/card-search/panel.gts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
} from '@cardstack/runtime-common/helpers/card-type-display-name';
2727

2828
import { getPrerenderedSearch } from '@cardstack/host/resources/prerendered-search';
29+
import type RealmService from '@cardstack/host/services/realm';
2930
import type RealmServerService from '@cardstack/host/services/realm-server';
3031
import type RecentCards from '@cardstack/host/services/recent-cards-service';
3132

@@ -51,6 +52,8 @@ interface Signature {
5152
searchKey: string;
5253
baseFilter?: Filter;
5354
availableRealmUrls?: string[];
55+
consumingRealm?: URL;
56+
preselectConsumingRealm?: boolean;
5457
};
5558
Blocks: {
5659
default: [
@@ -72,13 +75,15 @@ interface Signature {
7275
| 'activeSort'
7376
| 'onSortChange'
7477
| 'filteredRecentCards'
78+
| 'initialFocusedSection'
7579
>,
7680
string,
7781
];
7882
};
7983
}
8084

8185
export default class SearchPanel extends Component<Signature> {
86+
@service declare private realm: RealmService;
8287
@service declare private realmServer: RealmServerService;
8388
@service declare private recentCardsService: RecentCards;
8489
@consume(CardContextName) declare private cardContext:
@@ -87,7 +92,32 @@ export default class SearchPanel extends Component<Signature> {
8792
@consume(GetCardCollectionContextName)
8893
declare private getCardCollection: getCardCollection;
8994

90-
@tracked private selectedRealms: PickerOption[] = [];
95+
@tracked private selectedRealms: PickerOption[] = this.initialSelectedRealms;
96+
97+
private get shouldPreselectConsumingRealm(): boolean {
98+
return Boolean(this.args.preselectConsumingRealm);
99+
}
100+
101+
private get initialSelectedRealms(): PickerOption[] {
102+
let consumingRealm = this.args.consumingRealm;
103+
if (!this.shouldPreselectConsumingRealm || !consumingRealm) {
104+
return [];
105+
}
106+
let realmURL = consumingRealm.href;
107+
let info = this.realm.info(realmURL);
108+
let label = info?.name ?? realmURL;
109+
let icon = info?.iconURL ?? undefined;
110+
return [{ id: realmURL, icon, label, type: 'option' }];
111+
}
112+
113+
private get initialFocusedSectionId(): string | null {
114+
let consumingRealm = this.args.consumingRealm;
115+
if (!this.shouldPreselectConsumingRealm || !consumingRealm) {
116+
return null;
117+
}
118+
return `realm:${consumingRealm.href}`;
119+
}
120+
91121
@tracked private activeSort: SortOption = SORT_OPTIONS[0];
92122

93123
@cached
@@ -293,6 +323,7 @@ export default class SearchPanel extends Component<Signature> {
293323
activeSort=this.activeSort
294324
onSortChange=this.onSortChange
295325
filteredRecentCards=this.baseFilteredRecentCards
326+
initialFocusedSection=this.initialFocusedSectionId
296327
)
297328
this.joinedSelectedRealmURLs
298329
}}

packages/host/app/components/card-search/search-content.gts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ interface Signature {
156156
searchResource: PrerenderedSearchResource;
157157
activeSort: SortOption;
158158
onSortChange: (sort: SortOption) => void;
159+
initialFocusedSection?: string | null;
159160
};
160161
Blocks: {};
161162
}
@@ -168,7 +169,8 @@ export default class SearchContent extends Component<Signature> {
168169

169170
@tracked activeViewId = 'grid';
170171
/** Section id when focused: 'realm:<url>' or 'recents'. Null = no focus */
171-
@tracked focusedSection: string | null = null;
172+
@tracked focusedSection: string | null =
173+
this.args.initialFocusedSection ?? null;
172174
@tracked displayedCountBySection: Record<string, number> = {};
173175

174176
@consume(GetCardContextName) declare private getCard: getCard;

0 commit comments

Comments
 (0)