Skip to content

Commit

Permalink
Merge branch 'main' into CS-7763-create-representative-card
Browse files Browse the repository at this point in the history
  • Loading branch information
lucaslyl committed Jan 8, 2025
2 parents b023351 + f12d695 commit a4d52bb
Show file tree
Hide file tree
Showing 14 changed files with 115 additions and 18 deletions.
10 changes: 7 additions & 3 deletions packages/base/cards-grid.gts
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ class Isolated extends Component<typeof CardsGrid> {
</style>
</template>

filters: { displayName: string; icon: IconComponent; query: any }[] =
filters: { displayName: string; icon: IconComponent | string; query: any }[] =
new TrackedArray([
{
displayName: 'All Cards',
Expand Down Expand Up @@ -424,7 +424,11 @@ class Isolated extends Component<typeof CardsGrid> {
}
let cardTypeSummaries = (await response.json()).data as {
id: string;
attributes: { displayName: string; total: number };
attributes: {
displayName: string;
total: number;
iconHTML: string | null;
};
}[];
let excludedCardTypeIds = [
`${baseRealm.url}card-api/CardDef`,
Expand All @@ -441,7 +445,7 @@ class Isolated extends Component<typeof CardsGrid> {
const lastIndex = summary.id.lastIndexOf('/');
this.filters.push({
displayName: summary.attributes.displayName,
icon: Captions,
icon: summary.attributes.iconHTML ?? Captions,
query: {
filter: {
type: {
Expand Down
32 changes: 27 additions & 5 deletions packages/boxel-ui/addon/src/components/filter-list/index.gts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ export interface FilterListIconSignature {

export type FilterListIcon = ComponentLike<FilterListIconSignature>;

import { htmlSafe } from '@ember/template';

import { cn, eq } from '../../helpers.ts';

export type Filter = {
displayName: string;
icon: FilterListIcon;
icon: FilterListIcon | string;
};

interface Signature {
Expand All @@ -39,9 +41,16 @@ export default class FilterList extends Component<Signature> {
class={{cn 'filter-list__button' selected=(eq @activeFilter filter)}}
{{on 'click' (fn this.onChanged filter)}}
data-test-boxel-filter-list-button={{filter.displayName}}
><filter.icon
class='filter-list__icon'
/>{{filter.displayName}}</button>
>
{{#if (isIconString filter.icon)}}
{{htmlSafe
(addClassToSVG filter.icon 'filter-list__icon')
}}{{filter.displayName}}
{{else}}
<filter.icon
class='filter-list__icon'
/>{{filter.displayName}}{{/if}}</button>

{{/each}}
</div>
<style scoped>
Expand All @@ -58,6 +67,9 @@ export default class FilterList extends Component<Signature> {
font: 500 var(--boxel-font-sm);
padding: var(--boxel-sp-xxs);
margin-bottom: var(--boxel-sp-4xs);
display: flex;
gap: var(--boxel-sp-4xs);
}
.filter-list__button.selected {
color: var(--boxel-light);
Expand All @@ -68,11 +80,21 @@ export default class FilterList extends Component<Signature> {
background: var(--boxel-300);
border-radius: 6px;
}
.filter-list__icon {
:global(.filter-list__icon) {
width: var(--boxel-icon-xs);
height: var(--boxel-icon-xs);
vertical-align: top;
}
</style>
</template>
}

function addClassToSVG(svgString: string, className: string) {
return svgString
.replace(/<svg\b([^>]*)\sclass="([^"]*)"/, `<svg$1 class="$2 ${className}"`)
.replace(/<svg\b([^>]*)>/, `<svg$1 class="${className}">`);
}

function isIconString(icon: FilterListIcon | string): icon is string {
return typeof icon === 'string';
}
6 changes: 4 additions & 2 deletions packages/host/app/components/card-prerender.gts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ export default class CardPrerender extends Component {
realmURL,
reader,
indexWriter,
renderCard: this.renderService.renderCard.bind(this.renderService),
renderCard: this.renderService.renderCard,
render: this.renderService.render,
});
setOwner(currentRun, getOwner(this)!);

Expand All @@ -127,7 +128,8 @@ export default class CardPrerender extends Component {
reader,
indexWriter,
ignoreData: { ...ignoreData },
renderCard: this.renderService.renderCard.bind(this.renderService),
renderCard: this.renderService.renderCard,
render: this.renderService.render,
});
setOwner(currentRun, getOwner(this)!);
let current = await CurrentRun.incremental(currentRun, {
Expand Down
9 changes: 9 additions & 0 deletions packages/host/app/lib/current-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
serializableError,
type SerializedError,
} from '@cardstack/runtime-common/error';
import { cardTypeIcon } from '@cardstack/runtime-common/helpers';
import { RealmPaths, LocalPath } from '@cardstack/runtime-common/paths';
import { isIgnored } from '@cardstack/runtime-common/realm-index-updater';
import { type Reader, type Stats } from '@cardstack/runtime-common/worker';
Expand All @@ -50,6 +51,7 @@ import type * as CardAPI from 'https://cardstack.com/base/card-api';

import {
type RenderCard,
type Render,
IdentityContextWithErrors,
} from '../services/render-service';

Expand Down Expand Up @@ -82,6 +84,7 @@ export class CurrentRun {
#realmPaths: RealmPaths;
#ignoreData: Record<string, string>;
#renderCard: RenderCard;
#render: Render;
#realmURL: URL;
#realmInfo?: RealmInfo;
readonly stats: Stats = {
Expand All @@ -100,19 +103,22 @@ export class CurrentRun {
indexWriter,
ignoreData = {},
renderCard,
render,
}: {
realmURL: URL;
reader: Reader;
indexWriter: IndexWriter;
ignoreData?: Record<string, string>;
renderCard: RenderCard;
render: Render;
}) {
this.#indexWriter = indexWriter;
this.#realmPaths = new RealmPaths(realmURL);
this.#reader = reader;
this.#realmURL = realmURL;
this.#ignoreData = ignoreData;
this.#renderCard = renderCard;
this.#render = render;
}

static async fromScratch(current: CurrentRun): Promise<IndexResults> {
Expand Down Expand Up @@ -413,6 +419,7 @@ export class CurrentRun {
let cardType: typeof CardDef | undefined;
let isolatedHtml: string | undefined;
let atomHtml: string | undefined;
let iconHTML: string | undefined;
let card: CardDef | undefined;
let embeddedHtml: Record<string, string> | undefined;
let fittedHtml: Record<string, string> | undefined;
Expand Down Expand Up @@ -473,6 +480,7 @@ export class CurrentRun {
}),
),
);
iconHTML = unwrap(sanitizeHTML(this.#render(cardTypeIcon(card))));
cardType = Reflect.getPrototypeOf(card)?.constructor as typeof CardDef;
let data = api.serializeCard(card, { includeComputeds: true });
// prepare the document for index serialization
Expand Down Expand Up @@ -552,6 +560,7 @@ export class CurrentRun {
atomHtml,
embeddedHtml,
fittedHtml,
iconHTML,
lastModified,
resourceCreatedAt,
types: typesMaybeError.types.map(({ refURL }) => refURL),
Expand Down
4 changes: 2 additions & 2 deletions packages/host/app/lib/isolated-render.gts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ import type { SimpleElement } from '@simple-dom/interface';

interface Signature {
Args: {
format: Format;
format?: Format;
};
}

export function render(
C: ComponentLike<Signature>,
element: SimpleElement,
owner: Owner,
format: Format,
format?: Format,
): void {
// this needs to be a template-only component because the way we're invoking it
// just grabs the template and would drop any associated class.
Expand Down
15 changes: 13 additions & 2 deletions packages/host/app/services/render-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getOwner } from '@ember/application';
import type Owner from '@ember/owner';
import Service, { service } from '@ember/service';

import { ComponentLike } from '@glint/template';
import Serializer from '@simple-dom/serializer';

import voidMap from '@simple-dom/void-map';
Expand Down Expand Up @@ -58,6 +59,7 @@ interface RenderCardParams {
componentCodeRef?: CodeRef;
}
export type RenderCard = (params: RenderCardParams) => Promise<string>;
export type Render = (component: ComponentLike) => string;

const maxRenderThreshold = 10000;
export default class RenderService extends Service {
Expand All @@ -69,7 +71,7 @@ export default class RenderService extends Service {
renderError: Error | undefined;
owner: Owner = getOwner(this)!;

async renderCard(params: RenderCardParams): Promise<string> {
renderCard = async (params: RenderCardParams): Promise<string> => {
let {
card,
visit,
Expand Down Expand Up @@ -127,7 +129,16 @@ export default class RenderService extends Service {
let serializer = new Serializer(voidMap);
let html = serializer.serialize(element);
return parseCardHtml(html);
}
};

render = (component: ComponentLike): string => {
let element = getIsolatedRenderElement(this.document);
render(component, element, this.owner);

let serializer = new Serializer(voidMap);
let html = serializer.serialize(element);
return parseCardHtml(html);
};

// TODO delete me
private async resolveField(
Expand Down
1 change: 1 addition & 0 deletions packages/host/config/schema/1735668047598_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
fitted_html BLOB,
display_names BLOB,
resource_created_at,
icon_html TEXT,
PRIMARY KEY ( url, realm_version, realm_url )
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* eslint-disable camelcase */

exports.shorthands = undefined;

exports.up = (pgm) => {
pgm.addColumns('boxel_index', {
icon_html: 'varchar',
});
};

exports.down = (pgm) => {
pgm.dropColumns('boxel_index', ['icon_html']);
};
6 changes: 5 additions & 1 deletion packages/realm-server/tests/realm-server-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4055,7 +4055,8 @@ module('Realm Server', function (hooks) {
let response = await request
.get('/_types')
.set('Accept', 'application/json');

let iconHTML =
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="lucide lucide-captions" viewbox="0 0 24 24"><rect width="18" height="14" x="3" y="5" rx="2" ry="2"></rect><path d="M7 15h4m4 0h2M7 11h2m4 0h4"></path></svg>';
assert.strictEqual(response.status, 200, 'HTTP 200 status');
assert.deepEqual(response.body, {
data: [
Expand All @@ -4065,6 +4066,7 @@ module('Realm Server', function (hooks) {
attributes: {
displayName: 'Friend',
total: 2,
iconHTML,
},
},
{
Expand All @@ -4073,6 +4075,7 @@ module('Realm Server', function (hooks) {
attributes: {
displayName: 'Home',
total: 1,
iconHTML,
},
},
{
Expand All @@ -4081,6 +4084,7 @@ module('Realm Server', function (hooks) {
attributes: {
displayName: 'Person',
total: 3,
iconHTML,
},
},
],
Expand Down
1 change: 1 addition & 0 deletions packages/runtime-common/card-document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ export function makeCardTypeSummaryDoc(summaries: CardTypeSummary[]) {
attributes: {
displayName: summary.display_name,
total: summary.total,
iconHTML: summary.icon_html,
},
}));

Expand Down
2 changes: 2 additions & 0 deletions packages/runtime-common/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { parse } from 'date-fns';

export * from './card-type-display-name';

export interface SharedTests<T> {
[testName: string]: (assert: Assert, args: T) => Promise<void>;
}
Expand Down
2 changes: 2 additions & 0 deletions packages/runtime-common/index-structure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export interface BoxelIndexTable {
fitted_html: Record<string, string> | null;
isolated_html: string | null;
atom_html: string | null;
icon_html: string | null;
indexed_at: string | null; // pg represents big integers as strings in javascript
last_modified: string | null; // pg represents big integers as strings in javascript
resource_created_at: string | null; // pg represents big integers as strings in javascript
Expand All @@ -40,6 +41,7 @@ export interface CardTypeSummary {
code_ref: string;
display_name: string;
total: number;
icon_html: string;
}

export interface RealmMetaTable {
Expand Down
4 changes: 3 additions & 1 deletion packages/runtime-common/index-writer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export interface InstanceEntry {
embeddedHtml?: Record<string, string>;
fittedHtml?: Record<string, string>;
atomHtml?: string;
iconHTML?: string;
types: string[];
displayNames: string[];
deps: Set<string>;
Expand Down Expand Up @@ -168,6 +169,7 @@ export class Batch {
embedded_html: entry.embeddedHtml,
fitted_html: entry.fittedHtml,
atom_html: entry.atomHtml,
icon_html: entry.iconHTML,
deps: [...entry.deps],
types: entry.types,
display_names: entry.displayNames,
Expand Down Expand Up @@ -295,7 +297,7 @@ export class Batch {

private async updateRealmMeta() {
let results = await this.#query([
`SELECT CAST(count(i.url) AS INTEGER) as total, i.display_names->>0 as display_name, i.types->>0 as code_ref
`SELECT CAST(count(i.url) AS INTEGER) as total, i.display_names->>0 as display_name, i.types->>0 as code_ref, MAX(i.icon_html) as icon_html
FROM boxel_index as i
INNER JOIN realm_versions r ON i.realm_url = r.realm_url
WHERE`,
Expand Down
Loading

0 comments on commit a4d52bb

Please sign in to comment.