Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1d3f8f4
Add HTML prerendering for FileDef entries during indexing
lukemelia Jan 28, 2026
c1737ca
Fix lint errors, prettier formatting, and type issues
lukemelia Jan 29, 2026
c83b0d6
Remove redundant consumeClearCacheForRender call in file render phase
lukemelia Jan 29, 2026
b435211
Skip file HTML render for modules and card instances during indexing
lukemelia Jan 29, 2026
e950d9c
Revert "Skip file HTML render for modules and card instances during i…
lukemelia Jan 29, 2026
221a30e
Increase realm-server test timeout to 180s for file render overhead
lukemelia Jan 29, 2026
ff19e3d
Render only isolated HTML for file entries to fix CI timeouts
lukemelia Jan 29, 2026
c76a69a
Fix CI timeouts: add manager proxy route, fix expectedId, skip module…
lukemelia Jan 29, 2026
1c6ddf5
Restore realm-server test timeout to 60s
lukemelia Jan 29, 2026
3212cab
capitalize action item labels via css (#3920)
lucaslyl Jan 29, 2026
6ab155f
Fix: Pass createCard and saveCard to CRMTaskPlanner (#3914)
lucaslyl Jan 29, 2026
a3fc1d8
server: Fix determination of injected scoped CSS (#3919)
backspace Jan 29, 2026
6a8eed9
server: Remove SSR for `is_deleted IS TRUE` (#3924)
backspace Jan 29, 2026
4b02930
server: Fix SSR HTML injection corruption from dollar signs in card c…
lukemelia Jan 29, 2026
18055da
Lint fix
lukemelia Jan 29, 2026
9478c3a
Update custom domain publishing approach (#3917)
backspace Jan 29, 2026
51324bc
server: Remove `boxel_index_working` from SSR (#3925)
backspace Jan 29, 2026
17f76ec
Adjust auto-attachment logic to include .gts file of card instance (#…
FadhlanR Jan 30, 2026
b5b776e
host mode stack layering and scroll update (#3934)
burieberry Jan 31, 2026
4333dfe
lint: Add warning for `position: fixed` in card CSS
lukemelia Jan 29, 2026
fddc8ba
Fix ESLint rule visitor name and add unit tests
lukemelia Jan 29, 2026
42ebbfb
ci: Add unit test job for eslint-plugin-boxel
lukemelia Jan 29, 2026
cc70d6d
Calculate plan allowance availability per current subscription cycle …
jurgenwerk Jan 29, 2026
46555b4
Use authenticated store for FileDef instances in fileRender path
lukemelia Feb 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
boxel: ${{ steps.filter.outputs.boxel }}
ai-bot: ${{ steps.filter.outputs.ai-bot }}
bot-runner: ${{ steps.filter.outputs.bot-runner }}
eslint-plugin-boxel: ${{ steps.filter.outputs.eslint-plugin-boxel }}
postgres-migrations: ${{ steps.filter.outputs.postgres-migrations }}
boxel-icons: ${{ steps.filter.outputs.boxel-icons }}
boxel-motion: ${{ steps.filter.outputs.boxel-motion }}
Expand Down Expand Up @@ -67,6 +68,9 @@ jobs:
- *shared
- 'packages/bot-runner/**'
- 'packages/postgres/**'
eslint-plugin-boxel:
- *shared
- 'packages/eslint-plugin-boxel/**'
postgres-migrations:
- 'packages/postgres/migrations/**'
boxel-icons:
Expand Down Expand Up @@ -162,6 +166,21 @@ jobs:
run: pnpm test
working-directory: packages/bot-runner

eslint-plugin-boxel-test:
name: ESLint Plugin Boxel Tests
needs: change-check
if: needs.change-check.outputs.eslint-plugin-boxel == 'true' || github.ref == 'refs/heads/main' || needs.change-check.outputs.run_all == 'true'
runs-on: ubuntu-latest
concurrency:
group: eslint-plugin-boxel-test-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2
- uses: ./.github/actions/init
- name: ESLint Plugin Boxel test suite
run: pnpm test
working-directory: packages/eslint-plugin-boxel

postgres-migration-test:
name: Postgres Migration Test
needs: change-check
Expand Down
19 changes: 11 additions & 8 deletions packages/billing/billing-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -562,14 +562,17 @@ export async function spendCredits(
if (!subscriptionCycle) {
throw new Error('subscription cycle not found');
}
let availablePlanAllowanceCredits = await sumUpCreditsLedger(dbAdapter, {
creditType: [
'plan_allowance',
'plan_allowance_used',
'plan_allowance_expired',
],
userId,
});
let availablePlanAllowanceCredits = Math.max(
0,
await sumUpCreditsLedger(dbAdapter, {
creditType: [
'plan_allowance',
'plan_allowance_used',
'plan_allowance_expired',
],
subscriptionCycleId: subscriptionCycle.id,
}),
);

if (availablePlanAllowanceCredits >= creditsToSpend) {
await addToCreditsLedger(dbAdapter, {
Expand Down
1 change: 1 addition & 0 deletions packages/boxel-ui/addon/src/components/menu/index.gts
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ export default class Menu extends Component<Signature> {
display: flex;
align-items: center;
gap: var(--boxel-menu-item-gap);
text-transform: capitalize;
}
.menu-item__icon-url {
flex-shrink: 0;
Expand Down
2 changes: 2 additions & 0 deletions packages/catalog-realm/crm-app/crm-app.gts
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,8 @@ class CrmAppTemplate extends Component<typeof CrmApp> {
@searchFilter={{this.searchFilter}}
@taskFilter={{this.taskFilter}}
@sort={{this.taskSort}}
@createCard={{@createCard}}
@saveCard={{@saveCard}}
/>
{{else if this.query}}
{{#if (eq this.selectedView 'card')}}
Expand Down
40 changes: 40 additions & 0 deletions packages/eslint-plugin-boxel/lib/rules/no-css-position-fixed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
type: 'problem',
docs: {
description:
'disallow `position: fixed` in card CSS because cards should not break out of their bounding box',
category: 'Ember Octane',
recommended: true,
},
schema: [],
messages: {
'no-css-position-fixed':
'Do not use `position: fixed` in card CSS. Cards should not break out of their bounding box. Consider using `position: absolute` or `position: sticky` instead.',
},
},

create: (context) => {
return {
GlimmerElementNode(node) {
if (node.tag !== 'style') {
return;
}
for (const child of node.children) {
if (child.type === 'GlimmerTextNode') {
const text = child.value;
const regex = /position\s*:\s*fixed/gi;
let match;
while ((match = regex.exec(text)) !== null) {
context.report({
node: child,
messageId: 'no-css-position-fixed',
});
}
}
}
},
};
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
const rule = require('../../../lib/rules/no-css-position-fixed');
const RuleTester = require('eslint').RuleTester;

const ruleTester = new RuleTester({
parser: require.resolve('ember-eslint-parser'),
parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
});
ruleTester.run('no-css-position-fixed', rule, {
valid: [
`
<template>
<div class="my-card">Hello</div>
<style scoped>
.my-card {
position: relative;
top: 0;
}
</style>
</template>
`,
`
<template>
<div class="my-card">Hello</div>
<style scoped>
.my-card {
position: absolute;
top: 0;
}
</style>
</template>
`,
`
<template>
<div class="my-card">Hello</div>
<style scoped>
.my-card {
position: sticky;
top: 0;
}
</style>
</template>
`,
// No style tag at all
`
<template>
<div class="my-card">Hello</div>
</template>
`,
],

invalid: [
{
code: `
<template>
<div class="my-card">Hello</div>
<style scoped>
.my-card {
position: fixed;
top: 0;
}
</style>
</template>
`,
errors: [
{
type: 'GlimmerTextNode',
message: rule.meta.messages['no-css-position-fixed'],
},
],
},
// Without space after colon
{
code: `
<template>
<style scoped>
.my-card {
position:fixed;
}
</style>
</template>
`,
errors: [
{
type: 'GlimmerTextNode',
message: rule.meta.messages['no-css-position-fixed'],
},
],
},
// With extra whitespace
{
code: `
<template>
<style scoped>
.my-card {
position: fixed;
}
</style>
</template>
`,
errors: [
{
type: 'GlimmerTextNode',
message: rule.meta.messages['no-css-position-fixed'],
},
],
},
// Multiple occurrences
{
code: `
<template>
<style scoped>
.my-card {
position: fixed;
}
.another {
position: fixed;
}
</style>
</template>
`,
errors: [
{
type: 'GlimmerTextNode',
message: rule.meta.messages['no-css-position-fixed'],
},
{
type: 'GlimmerTextNode',
message: rule.meta.messages['no-css-position-fixed'],
},
],
},
],
});
2 changes: 2 additions & 0 deletions packages/experiments-realm/crm-app.gts
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,8 @@ class CrmAppTemplate extends Component<typeof CrmApp> {
@searchFilter={{this.searchFilter}}
@taskFilter={{this.taskFilter}}
@sort={{this.taskSort}}
@createCard={{@createCard}}
@saveCard={{@saveCard}}
/>
{{else if this.query}}
{{#if (eq this.selectedView 'card')}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ interface Signature {
Args: {
items: (CardDef | FileDef | CardErrorJSONAPI)[];
autoAttachedCardIds?: TrackedSet<string>;
autoAttachedFile?: FileDef;
autoAttachedFiles?: FileDef[];
removeCard: (cardId: string) => void;
removeFile: (file: FileDef) => void;
chooseCard?: (cardId: string) => void;
Expand Down Expand Up @@ -63,7 +63,11 @@ export default class AttachedItems extends Component<Signature> {
};

private isAutoAttachedFile = (file: FileDef): boolean => {
return this.args.autoAttachedFile?.sourceUrl === file.sourceUrl;
return (
this.args.autoAttachedFiles?.some(
(autoFile) => autoFile.sourceUrl === file.sourceUrl,
) ?? false
);
};

@action
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface Signature {
Args: {
autoAttachedCardIds?: TrackedSet<string>;
cardIdsToAttach: string[] | undefined;
autoAttachedFile?: FileDef;
autoAttachedFiles?: FileDef[];
filesToAttach: FileDef[] | undefined;
chooseCard: (cardId: string) => void;
removeCard: (cardId: string) => void;
Expand All @@ -37,7 +37,7 @@ interface Signature {
typeof AttachedItems,
| 'items'
| 'autoAttachedCardIds'
| 'autoAttachedFile'
| 'autoAttachedFiles'
| 'removeCard'
| 'removeFile'
| 'chooseCard'
Expand All @@ -59,7 +59,7 @@ export default class AiAssistantAttachmentPicker extends Component<Signature> {
isLoaded=this.isLoaded
items=this.items
autoAttachedCardIds=@autoAttachedCardIds
autoAttachedFile=@autoAttachedFile
autoAttachedFiles=@autoAttachedFiles
removeCard=@removeCard
removeFile=@removeFile
chooseCard=@chooseCard
Expand Down Expand Up @@ -109,18 +109,20 @@ export default class AiAssistantAttachmentPicker extends Component<Signature> {
private get files() {
let files = this.args.filesToAttach ?? [];

if (!this.args.autoAttachedFile) {
let autoAttachedFiles = this.args.autoAttachedFiles ?? [];

if (autoAttachedFiles.length === 0) {
return files;
}

if (
files.some(
(file) => file.sourceUrl === this.args.autoAttachedFile?.sourceUrl,
)
) {
let autoFilesToPrepend = autoAttachedFiles.filter(
(file) => !files.some((item) => item.sourceUrl === file.sourceUrl),
);

if (autoFilesToPrepend.length === 0) {
return files;
}

return [this.args.autoAttachedFile, ...files];
return [...autoFilesToPrepend, ...files];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default class AiAssistantCardPickerUsage extends Component {
cardIds: TrackedArray<string> = new TrackedArray([]);
@tracked maxNumberOfCards: number | undefined = undefined;
@tracked autoAttachedCardIds?: TrackedSet<string> = new TrackedSet();
@tracked autoAttachedFile?: FileDef | undefined;
@tracked autoAttachedFiles?: FileDef[];
@tracked filesToAttach: TrackedArray<FileDef> = new TrackedArray([]);

@action chooseCard(cardId: string) {
Expand Down Expand Up @@ -60,7 +60,7 @@ export default class AiAssistantCardPickerUsage extends Component {
@removeCard={{this.removeCard}}
@chooseFile={{this.chooseFile}}
@removeFile={{this.removeFile}}
@autoAttachedFile={{this.autoAttachedFile}}
@autoAttachedFiles={{this.autoAttachedFiles}}
@filesToAttach={{this.filesToAttach}}
as |AttachedItems AttachButton|
>
Expand All @@ -81,9 +81,9 @@ export default class AiAssistantCardPickerUsage extends Component {
@value={{this.autoAttachedCardIds}}
/>
<Args.Object
@name='autoAttachedFile'
@description='A file automatically attached to the message.'
@value={{this.autoAttachedFile}}
@name='autoAttachedFiles'
@description='Files automatically attached to the message.'
@value={{this.autoAttachedFiles}}
/>
<Args.Object
@name='filesToAttach'
Expand Down
Loading
Loading