Skip to content

Commit d954336

Browse files
MyesterybenceruleanluDrJKLgithub-actionschristian-byrne
authored
New Workflow Templates Modal (#5142)
This pull request refactors and simplifies the template workflow card components and related UI in the codebase. The main changes focus on removing unused or redundant components, improving visual and interaction consistency, and enhancing error handling for images. Below are the most important changes grouped by theme: **Template Workflow Card Refactor and Cleanup** * Removed the `TemplateWorkflowCard.vue` component and its associated test file `TemplateWorkflowCard.spec.ts`, as well as the `TemplateWorkflowCardSkeleton.vue` and `TemplateWorkflowList.vue` components, indicating a shift away from the previous card-based template workflow UI. [[1]](diffhunk://#diff-49569af0404058e8257f3cc0716b066517ce7397dd58744b02aa0d0c61f2a815L1-L139) [[2]](diffhunk://#diff-9fa6fc1470371f0b520d4deda4129fb313b1bea69888a376556f4bd824f9d751L1-L263) [[3]](diffhunk://#diff-bc35b6f77d1cee6e86b05d0da80b7bd40013c7a6a97a89706d3bc52573e1c574L1-L30) [[4]](diffhunk://#diff-48171f792b22022526fca411d3c3a366d48b675dab77943a20846ae079cbaf3bL1-L68) * Removed the `TemplateSearchBar.vue` component, suggesting a redesign or replacement of the search/filter UI for templates. **UI and Interaction Improvements** * Improved the `CardBottom.vue` component by making its height configurable via a `fullHeight` prop, enhancing layout flexibility. * Updated the `CardContainer.vue` component to add hover effects (background, border, shadow, and padding) and support a new `none` aspect ratio for more flexible card layouts. **Image and Input Enhancements** * Enhanced the `LazyImage.vue` component to display a default placeholder image when an image fails to load, improving error handling and user experience. * Improved the `SearchBox.vue` component by making the input focusable when clicking anywhere on the wrapper, and added a template ref for better accessibility and usability. [[1]](diffhunk://#diff-08f3b0c51fbfe63171509b9944bf7558228f6c2596a1ef5338e88ab64585791bL2-R5) [[2]](diffhunk://#diff-08f3b0c51fbfe63171509b9944bf7558228f6c2596a1ef5338e88ab64585791bL16-R17) [[3]](diffhunk://#diff-08f3b0c51fbfe63171509b9944bf7558228f6c2596a1ef5338e88ab64585791bR33-R39) **Minor UI Tweaks** * Adjusted label styling in `SingleSelect.vue` to remove unnecessary overflow handling, simplifying the visual layout. --------- Co-authored-by: Benjamin Lu <[email protected]> Co-authored-by: Alexander Brown <[email protected]> Co-authored-by: github-actions <[email protected]> Co-authored-by: Christian Byrne <[email protected]> Co-authored-by: Claude <[email protected]> Co-authored-by: snomiao <[email protected]> Co-authored-by: GitHub Action <[email protected]> Co-authored-by: filtered <[email protected]> Co-authored-by: Comfy Org PR Bot <[email protected]> Co-authored-by: Jin Yi <[email protected]>
1 parent 49f373c commit d954336

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1840
-1355
lines changed

browser_tests/tests/templates.spec.ts

Lines changed: 126 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ test.describe('Templates', () => {
8080
// Load a template
8181
await comfyPage.executeCommand('Comfy.BrowseTemplates')
8282
await expect(comfyPage.templates.content).toBeVisible()
83+
84+
await comfyPage.page
85+
.locator(
86+
'nav > div:nth-child(2) > div > span:has-text("Getting Started")'
87+
)
88+
.click()
8389
await comfyPage.templates.loadTemplate('default')
8490
await expect(comfyPage.templates.content).toBeHidden()
8591

@@ -102,48 +108,72 @@ test.describe('Templates', () => {
102108
expect(await comfyPage.templates.content.isVisible()).toBe(true)
103109
})
104110

105-
test('Uses title field as fallback when the key is not found in locales', async ({
111+
test('Uses proper locale files for templates', async ({ comfyPage }) => {
112+
// Set locale to French before opening templates
113+
await comfyPage.setSetting('Comfy.Locale', 'fr')
114+
115+
// Load the templates dialog and wait for the French index file request
116+
const requestPromise = comfyPage.page.waitForRequest(
117+
'**/templates/index.fr.json'
118+
)
119+
120+
await comfyPage.executeCommand('Comfy.BrowseTemplates')
121+
122+
const request = await requestPromise
123+
124+
// Verify French index was requested
125+
expect(request.url()).toContain('templates/index.fr.json')
126+
127+
await expect(comfyPage.templates.content).toBeVisible()
128+
})
129+
130+
test('Falls back to English templates when locale file not found', async ({
106131
comfyPage
107132
}) => {
108-
// Capture request for the index.json
109-
await comfyPage.page.route('**/templates/index.json', async (route, _) => {
110-
// Add a new template that won't have a translation pre-generated
111-
const response = [
112-
{
113-
moduleName: 'default',
114-
title: 'FALLBACK CATEGORY',
115-
type: 'image',
116-
templates: [
117-
{
118-
name: 'unknown_key_has_no_translation_available',
119-
title: 'FALLBACK TEMPLATE NAME',
120-
mediaType: 'image',
121-
mediaSubtype: 'webp',
122-
description: 'No translations found'
123-
}
124-
]
125-
}
126-
]
133+
// Set locale to a language that doesn't have a template file
134+
await comfyPage.setSetting('Comfy.Locale', 'de') // German - no index.de.json exists
135+
136+
// Wait for the German request (expected to 404)
137+
const germanRequestPromise = comfyPage.page.waitForRequest(
138+
'**/templates/index.de.json'
139+
)
140+
141+
// Wait for the fallback English request
142+
const englishRequestPromise = comfyPage.page.waitForRequest(
143+
'**/templates/index.json'
144+
)
145+
146+
// Intercept the German file to simulate a 404
147+
await comfyPage.page.route('**/templates/index.de.json', async (route) => {
127148
await route.fulfill({
128-
status: 200,
129-
body: JSON.stringify(response),
130-
headers: {
131-
'Content-Type': 'application/json',
132-
'Cache-Control': 'no-store'
133-
}
149+
status: 404,
150+
headers: { 'Content-Type': 'text/plain' },
151+
body: 'Not Found'
134152
})
135153
})
136154

155+
// Allow the English index to load normally
156+
await comfyPage.page.route('**/templates/index.json', (route) =>
157+
route.continue()
158+
)
159+
137160
// Load the templates dialog
138161
await comfyPage.executeCommand('Comfy.BrowseTemplates')
162+
await expect(comfyPage.templates.content).toBeVisible()
163+
164+
// Verify German was requested first, then English as fallback
165+
const germanRequest = await germanRequestPromise
166+
const englishRequest = await englishRequestPromise
167+
168+
expect(germanRequest.url()).toContain('templates/index.de.json')
169+
expect(englishRequest.url()).toContain('templates/index.json')
139170

140-
// Expect the title to be used as fallback for template cards
171+
// Verify English titles are shown as fallback
141172
await expect(
142-
comfyPage.templates.content.getByText('FALLBACK TEMPLATE NAME')
173+
comfyPage.templates.content.getByRole('heading', {
174+
name: 'Image Generation'
175+
})
143176
).toBeVisible()
144-
145-
// Expect the title to be used as fallback for the template categories
146-
await expect(comfyPage.page.getByLabel('FALLBACK CATEGORY')).toBeVisible()
147177
})
148178

149179
test('template cards are dynamically sized and responsive', async ({
@@ -153,36 +183,57 @@ test.describe('Templates', () => {
153183
await comfyPage.executeCommand('Comfy.BrowseTemplates')
154184
await expect(comfyPage.templates.content).toBeVisible()
155185

156-
// Wait for at least one template card to appear
157-
await expect(comfyPage.page.locator('.template-card').first()).toBeVisible({
158-
timeout: 5000
159-
})
186+
const firstCard = comfyPage.page
187+
.locator('[data-testid^="template-workflow-"]')
188+
.first()
189+
await expect(firstCard).toBeVisible({ timeout: 5000 })
160190

161-
// Take snapshot of the template grid
162-
const templateGrid = comfyPage.templates.content.locator('.grid').first()
191+
// Get the template grid
192+
const templateGrid = comfyPage.page.locator(
193+
'[data-testid="template-workflows-content"]'
194+
)
163195
await expect(templateGrid).toBeVisible()
164-
await expect(templateGrid).toHaveScreenshot('template-grid-desktop.png')
196+
197+
// Check grid layout at desktop size (default)
198+
const desktopGridClass = await templateGrid.getAttribute('class')
199+
expect(desktopGridClass).toContain('grid')
200+
expect(desktopGridClass).toContain(
201+
'grid-cols-[repeat(auto-fill,minmax(16rem,1fr))]'
202+
)
203+
204+
// Count visible cards at desktop size
205+
const desktopCardCount = await comfyPage.page
206+
.locator('[data-testid^="template-workflow-"]')
207+
.count()
208+
expect(desktopCardCount).toBeGreaterThan(0)
165209

166210
// Check cards at mobile viewport size
167211
await comfyPage.page.setViewportSize({ width: 640, height: 800 })
168212
await expect(templateGrid).toBeVisible()
169-
await expect(templateGrid).toHaveScreenshot('template-grid-mobile.png')
213+
// Grid should still be responsive at mobile size
214+
const mobileGridClass = await templateGrid.getAttribute('class')
215+
expect(mobileGridClass).toContain('grid')
170216

171217
// Check cards at tablet size
172218
await comfyPage.page.setViewportSize({ width: 1024, height: 800 })
173219
await expect(templateGrid).toBeVisible()
174-
await expect(templateGrid).toHaveScreenshot('template-grid-tablet.png')
220+
// Grid should still be responsive at tablet size
221+
const tabletGridClass = await templateGrid.getAttribute('class')
222+
expect(tabletGridClass).toContain('grid')
175223
})
176224

177225
test('hover effects work on template cards', async ({ comfyPage }) => {
178226
// Open templates dialog
179227
await comfyPage.executeCommand('Comfy.BrowseTemplates')
180228
await expect(comfyPage.templates.content).toBeVisible()
181229

182-
// Get a template card
183-
const firstCard = comfyPage.page.locator('.template-card').first()
230+
// Get a template card using data-testid
231+
const firstCard = comfyPage.page
232+
.locator('[data-testid^="template-workflow-"]')
233+
.first()
184234
await expect(firstCard).toBeVisible({ timeout: 5000 })
185235

236+
// Check initial state - card should have transition classes
186237
// Take snapshot before hover
187238
await expect(firstCard).toHaveScreenshot('template-card-before-hover.png')
188239

@@ -257,21 +308,42 @@ test.describe('Templates', () => {
257308
await comfyPage.executeCommand('Comfy.BrowseTemplates')
258309
await expect(comfyPage.templates.content).toBeVisible()
259310

260-
// Verify cards are visible with varying content lengths
261-
await expect(
262-
comfyPage.page.getByText('This is a short description.')
263-
).toBeVisible({ timeout: 5000 })
311+
// Wait for cards to load
264312
await expect(
265-
comfyPage.page.getByText('This is a medium length description')
266-
).toBeVisible({ timeout: 5000 })
267-
await expect(
268-
comfyPage.page.getByText('This is a much longer description')
313+
comfyPage.page.locator(
314+
'[data-testid="template-workflow-short-description"]'
315+
)
269316
).toBeVisible({ timeout: 5000 })
270317

271-
// Take snapshot of a grid with specific cards
272-
const templateGrid = comfyPage.templates.content
273-
.locator('.grid:has-text("Short Description")')
274-
.first()
318+
// Verify all three cards with different descriptions are visible
319+
const shortDescCard = comfyPage.page.locator(
320+
'[data-testid="template-workflow-short-description"]'
321+
)
322+
const mediumDescCard = comfyPage.page.locator(
323+
'[data-testid="template-workflow-medium-description"]'
324+
)
325+
const longDescCard = comfyPage.page.locator(
326+
'[data-testid="template-workflow-long-description"]'
327+
)
328+
329+
await expect(shortDescCard).toBeVisible()
330+
await expect(mediumDescCard).toBeVisible()
331+
await expect(longDescCard).toBeVisible()
332+
333+
// Verify descriptions are visible and have line-clamp class
334+
// The description is in a p tag with text-muted class
335+
const shortDesc = shortDescCard.locator('p.text-muted.line-clamp-2')
336+
const mediumDesc = mediumDescCard.locator('p.text-muted.line-clamp-2')
337+
const longDesc = longDescCard.locator('p.text-muted.line-clamp-2')
338+
339+
await expect(shortDesc).toContainText('short description')
340+
await expect(mediumDesc).toContainText('medium length description')
341+
await expect(longDesc).toContainText('much longer description')
342+
343+
// Verify grid layout maintains consistency
344+
const templateGrid = comfyPage.page.locator(
345+
'[data-testid="template-workflows-content"]'
346+
)
275347
await expect(templateGrid).toBeVisible()
276348
await expect(templateGrid).toHaveScreenshot(
277349
'template-grid-varying-content.png'
11.2 KB
Loading
23.4 KB
Loading
47.9 KB
Loading

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@
125125
"@tiptap/extension-table-row": "^2.10.4",
126126
"@tiptap/starter-kit": "^2.10.4",
127127
"@vueuse/core": "^11.0.0",
128+
"@vueuse/integrations": "^13.9.0",
128129
"@xterm/addon-fit": "^0.10.0",
129130
"@xterm/addon-serialize": "^0.13.0",
130131
"@xterm/xterm": "^5.5.0",

pnpm-lock.yaml

Lines changed: 80 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
54 KB
Loading
Lines changed: 10 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)