From fa8275bae120881a8afb680b8f03e42e6b4470a3 Mon Sep 17 00:00:00 2001 From: Burcu Noyan Date: Mon, 29 Jun 2026 12:36:46 -0400 Subject: [PATCH 01/24] improved result card fitted template --- .../software-factory/realm/eval-result.gts | 133 ++++------- .../realm/instantiate-result.gts | 133 ++++------- .../software-factory/realm/lint-result.gts | 141 +++++------- .../software-factory/realm/parse-result.gts | 133 ++++------- .../realm/result-fitted-card.gts | 217 ++++++++++++++++++ .../software-factory/realm/test-results.gts | 142 +++++------- 6 files changed, 463 insertions(+), 436 deletions(-) create mode 100644 packages/software-factory/realm/result-fitted-card.gts diff --git a/packages/software-factory/realm/eval-result.gts b/packages/software-factory/realm/eval-result.gts index 61285135fd..2c66b1f39d 100644 --- a/packages/software-factory/realm/eval-result.gts +++ b/packages/software-factory/realm/eval-result.gts @@ -12,6 +12,14 @@ import NumberField from 'https://cardstack.com/base/number'; import DateTimeField from 'https://cardstack.com/base/datetime'; import enumField from 'https://cardstack.com/base/enum'; import { Project, Issue } from './darkfactory.gts'; +import { + ResultFittedCard, + type ResultMetaItem, +} from './result-fitted-card.gts'; + +import Code from '@cardstack/boxel-icons/code'; +import CircleCheck from '@cardstack/boxel-icons/circle-check'; +import CircleX from '@cardstack/boxel-icons/circle-x'; export const EvalResultStatusField = enumField(StringField, { options: [ @@ -106,7 +114,7 @@ export class EvalResult extends CardDef { }, }); - @field title = contains(StringField, { + @field cardTitle = contains(StringField, { computeVia: function (this: EvalResult) { let seq = this.sequenceNumber ?? '?'; let status = this.status ?? 'unknown'; @@ -129,93 +137,44 @@ export class EvalResult extends CardDef { return this.args.model.status; } + get titleText() { + return this.args.model.issue?.summary ?? 'Eval Run'; + } + + get metaItems(): ResultMetaItem[] { + let m = this.args.model; + let items: ResultMetaItem[] = [ + { + icon: CircleCheck, + text: `${m.modulesPassed}/${m.modulesChecked} passed`, + tone: 'clean', + }, + ]; + if (m.modulesWithErrors) { + items.push({ + icon: CircleX, + text: `${m.modulesWithErrors} error(s)`, + tone: 'error', + }); + } + return items; + } + }; diff --git a/packages/software-factory/realm/instantiate-result.gts b/packages/software-factory/realm/instantiate-result.gts index ac128f8677..04dd818d55 100644 --- a/packages/software-factory/realm/instantiate-result.gts +++ b/packages/software-factory/realm/instantiate-result.gts @@ -15,6 +15,14 @@ import CodeRefField from 'https://cardstack.com/base/code-ref'; import enumField from 'https://cardstack.com/base/enum'; import { RealmPaths } from '@cardstack/runtime-common'; import { Project, Issue } from './darkfactory.gts'; +import { + ResultFittedCard, + type ResultMetaItem, +} from './result-fitted-card.gts'; + +import Box from '@cardstack/boxel-icons/box'; +import CircleCheck from '@cardstack/boxel-icons/circle-check'; +import CircleX from '@cardstack/boxel-icons/circle-x'; export const InstantiateResultStatusField = enumField(StringField, { options: [ @@ -129,7 +137,7 @@ export class InstantiateResult extends CardDef { }, }); - @field title = contains(StringField, { + @field cardTitle = contains(StringField, { computeVia: function (this: InstantiateResult) { let seq = this.sequenceNumber ?? '?'; let status = this.status ?? 'unknown'; @@ -152,93 +160,44 @@ export class InstantiateResult extends CardDef { return this.args.model.status; } + get titleText() { + return this.args.model.issue?.summary ?? 'Instantiate Run'; + } + + get metaItems(): ResultMetaItem[] { + let m = this.args.model; + let items: ResultMetaItem[] = [ + { + icon: CircleCheck, + text: `${m.cardsPassed}/${m.cardsChecked} passed`, + tone: 'clean', + }, + ]; + if (m.cardsWithErrors) { + items.push({ + icon: CircleX, + text: `${m.cardsWithErrors} error(s)`, + tone: 'error', + }); + } + return items; + } + }; diff --git a/packages/software-factory/realm/lint-result.gts b/packages/software-factory/realm/lint-result.gts index ac8903ead4..5f950b7204 100644 --- a/packages/software-factory/realm/lint-result.gts +++ b/packages/software-factory/realm/lint-result.gts @@ -12,6 +12,15 @@ import NumberField from 'https://cardstack.com/base/number'; import DateTimeField from 'https://cardstack.com/base/datetime'; import enumField from 'https://cardstack.com/base/enum'; import { Project, Issue } from './darkfactory.gts'; +import { + ResultFittedCard, + type ResultMetaItem, +} from './result-fitted-card.gts'; + +import ListChecks from '@cardstack/boxel-icons/list-checks'; +import CircleCheck from '@cardstack/boxel-icons/circle-check'; +import CircleX from '@cardstack/boxel-icons/circle-x'; +import CircleAlert from '@cardstack/boxel-icons/circle-alert'; export const LintResultStatusField = enumField(StringField, { options: [ @@ -225,7 +234,7 @@ export class LintResult extends CardDef { }, }); - @field title = contains(StringField, { + @field cardTitle = contains(StringField, { computeVia: function (this: LintResult) { let seq = this.sequenceNumber ?? '?'; let status = this.status ?? 'unknown'; @@ -252,93 +261,51 @@ export class LintResult extends CardDef { return this.args.model.status; } + get titleText() { + return this.args.model.issue?.summary ?? 'Lint Run'; + } + + get metaItems(): ResultMetaItem[] { + let m = this.args.model; + let items: ResultMetaItem[] = [ + { + icon: CircleCheck, + text: `${m.filesClean}/${m.filesChecked} clean`, + tone: 'clean', + }, + ]; + if (m.totalErrors) { + items.push({ + icon: CircleX, + text: `${m.totalErrors} error(s)`, + tone: 'error', + }); + } + if (m.totalWarnings) { + items.push({ + icon: CircleAlert, + text: `${m.totalWarnings} warning(s)`, + tone: 'warning', + }); + } + return items; + } + }; diff --git a/packages/software-factory/realm/parse-result.gts b/packages/software-factory/realm/parse-result.gts index abbc5c07cb..24fd00d099 100644 --- a/packages/software-factory/realm/parse-result.gts +++ b/packages/software-factory/realm/parse-result.gts @@ -12,6 +12,14 @@ import NumberField from 'https://cardstack.com/base/number'; import DateTimeField from 'https://cardstack.com/base/datetime'; import enumField from 'https://cardstack.com/base/enum'; import { Project, Issue } from './darkfactory.gts'; +import { + ResultFittedCard, + type ResultMetaItem, +} from './result-fitted-card.gts'; + +import FileCode from '@cardstack/boxel-icons/file-code'; +import CircleCheck from '@cardstack/boxel-icons/circle-check'; +import CircleX from '@cardstack/boxel-icons/circle-x'; export const ParseResultStatusField = enumField(StringField, { options: [ @@ -174,7 +182,7 @@ export class ParseResult extends CardDef { }, }); - @field title = contains(StringField, { + @field cardTitle = contains(StringField, { computeVia: function (this: ParseResult) { let seq = this.sequenceNumber ?? '?'; let status = this.status ?? 'unknown'; @@ -201,93 +209,44 @@ export class ParseResult extends CardDef { return this.args.model.status; } + get titleText() { + return this.args.model.issue?.summary ?? 'Parse Run'; + } + + get metaItems(): ResultMetaItem[] { + let m = this.args.model; + let items: ResultMetaItem[] = [ + { + icon: CircleCheck, + text: `${m.filesClean}/${m.filesChecked} valid`, + tone: 'clean', + }, + ]; + if (m.totalErrors) { + items.push({ + icon: CircleX, + text: `${m.totalErrors} error(s)`, + tone: 'error', + }); + } + return items; + } + }; diff --git a/packages/software-factory/realm/result-fitted-card.gts b/packages/software-factory/realm/result-fitted-card.gts new file mode 100644 index 0000000000..84a633e498 --- /dev/null +++ b/packages/software-factory/realm/result-fitted-card.gts @@ -0,0 +1,217 @@ +import GlimmerComponent from '@glimmer/component'; +import type { ComponentLike } from '@glint/template'; +import { FittedCard } from '@cardstack/boxel-ui/components'; +import { StatusPill } from './status-pill.gts'; +import Clock from '@cardstack/boxel-icons/clock'; + +type IconComponent = ComponentLike<{ Element: SVGSVGElement }>; + +export type ResultMetaTone = 'clean' | 'error' | 'warning' | 'muted'; + +export interface ResultMetaItem { + icon: IconComponent; + text: string; + tone?: ResultMetaTone; +} + +interface Signature { + Args: { + // Eyebrow icon and label, rendered as "