diff --git a/.github/workflows/autolabel.yaml b/.github/workflows/autolabel.yaml index eabe804..42bfd9d 100644 --- a/.github/workflows/autolabel.yaml +++ b/.github/workflows/autolabel.yaml @@ -4,12 +4,16 @@ on: pull_request: types: [opened, reopened, synchronize] +permissions: + contents: write + pull-requests: write + jobs: autolabel: name: Autolabel PR runs-on: ubuntu-latest steps: - - name: Draft release + - name: Label PR id: drafter uses: release-drafter/release-drafter@v6 with: diff --git a/src/components/FileUpload.tsx b/src/components/FileUpload.tsx index 3ed4a91..201166a 100644 --- a/src/components/FileUpload.tsx +++ b/src/components/FileUpload.tsx @@ -6,6 +6,7 @@ import { useUIStore } from '../stores/useUIStore'; import { convertPesToPen, type PesPatternData } from '../formats/import/pesImporter'; import { canUploadPattern, getMachineStateCategory } from '../utils/machineStateHelpers'; import { PatternInfoSkeleton } from './SkeletonLoader'; +import { PatternInfo } from './PatternInfo'; import { ArrowUpTrayIcon, CheckCircleIcon, DocumentTextIcon, FolderOpenIcon } from '@heroicons/react/24/solid'; import { createFileService } from '../platform'; import type { IFileService } from '../platform/interfaces/IFileService'; @@ -200,66 +201,7 @@ export function FileUpload() { {!isLoading && pesData && (
-
-
- Size - - {((pesData.bounds.maxX - pesData.bounds.minX) / 10).toFixed(1)} x{' '} - {((pesData.bounds.maxY - pesData.bounds.minY) / 10).toFixed(1)} mm - -
-
- Stitches - - {pesData.stitchCount.toLocaleString()} - -
-
- Colors / Blocks - - {pesData.uniqueColors.length} / {pesData.threads.length} - -
-
- -
- Colors: -
- {pesData.uniqueColors.slice(0, 8).map((color, idx) => { - // Primary metadata: brand and catalog number - const primaryMetadata = [ - color.brand, - color.catalogNumber ? `#${color.catalogNumber}` : null - ].filter(Boolean).join(" "); - - // Secondary metadata: chart and description - const secondaryMetadata = [ - color.chart, - color.description - ].filter(Boolean).join(" "); - - const metadata = [primaryMetadata, secondaryMetadata].filter(Boolean).join(" • "); - - const tooltipText = metadata - ? `Color ${idx + 1}: ${color.hex} - ${metadata}` - : `Color ${idx + 1}: ${color.hex}`; - - return ( -
- ); - })} - {pesData.uniqueColors.length > 8 && ( -
- +{pesData.uniqueColors.length - 8} -
- )} -
-
+
)} diff --git a/src/components/PatternInfo.tsx b/src/components/PatternInfo.tsx new file mode 100644 index 0000000..efff798 --- /dev/null +++ b/src/components/PatternInfo.tsx @@ -0,0 +1,92 @@ +import type { PesPatternData } from '../formats/import/pesImporter'; + +interface PatternInfoProps { + pesData: PesPatternData; + showThreadBlocks?: boolean; +} + +export function PatternInfo({ pesData, showThreadBlocks = false }: PatternInfoProps) { + return ( + <> +
+
+ Size + + {((pesData.bounds.maxX - pesData.bounds.minX) / 10).toFixed(1)} x{' '} + {((pesData.bounds.maxY - pesData.bounds.minY) / 10).toFixed(1)} mm + +
+
+ Stitches + + {pesData.penStitches?.stitches.length.toLocaleString() || pesData.stitchCount.toLocaleString()} + {pesData.penStitches && pesData.penStitches.stitches.length !== pesData.stitchCount && ( + + ({pesData.stitchCount.toLocaleString()}) + + )} + +
+
+ + {showThreadBlocks ? 'Colors / Blocks' : 'Colors'} + + + {showThreadBlocks + ? `${pesData.uniqueColors.length} / ${pesData.threads.length}` + : pesData.uniqueColors.length + } + +
+
+ +
+ Colors: +
+ {pesData.uniqueColors.slice(0, 8).map((color, idx) => { + // Primary metadata: brand and catalog number + const primaryMetadata = [ + color.brand, + color.catalogNumber ? `#${color.catalogNumber}` : null + ].filter(Boolean).join(" "); + + // Secondary metadata: chart and description + const secondaryMetadata = [ + color.chart, + color.description + ].filter(Boolean).join(" "); + + const metadata = [primaryMetadata, secondaryMetadata].filter(Boolean).join(" • "); + + // Show which thread blocks use this color in PatternSummaryCard + const threadNumbers = color.threadIndices.map(i => i + 1).join(", "); + const tooltipText = showThreadBlocks + ? (metadata + ? `Color ${idx + 1}: ${color.hex} - ${metadata}` + : `Color ${idx + 1}: ${color.hex}`) + : (metadata + ? `Color ${idx + 1}: ${color.hex}\n${metadata}\nUsed in thread blocks: ${threadNumbers}` + : `Color ${idx + 1}: ${color.hex}\nUsed in thread blocks: ${threadNumbers}`); + + return ( +
+ ); + })} + {pesData.uniqueColors.length > 8 && ( +
+ +{pesData.uniqueColors.length - 8} +
+ )} +
+
+ + ); +} diff --git a/src/components/PatternSummaryCard.tsx b/src/components/PatternSummaryCard.tsx index 9abc0ca..a094f35 100644 --- a/src/components/PatternSummaryCard.tsx +++ b/src/components/PatternSummaryCard.tsx @@ -2,6 +2,7 @@ import { useShallow } from 'zustand/react/shallow'; import { useMachineStore } from '../stores/useMachineStore'; import { usePatternStore } from '../stores/usePatternStore'; import { canDeletePattern } from '../utils/machineStateHelpers'; +import { PatternInfo } from './PatternInfo'; import { DocumentTextIcon, TrashIcon } from '@heroicons/react/24/solid'; export function PatternSummaryCard() { @@ -44,68 +45,7 @@ export function PatternSummaryCard() {
-
-
- Size - - {((pesData.bounds.maxX - pesData.bounds.minX) / 10).toFixed(1)} x{' '} - {((pesData.bounds.maxY - pesData.bounds.minY) / 10).toFixed(1)} mm - -
-
- Stitches - - {pesData.stitchCount.toLocaleString()} - -
-
- Colors - - {pesData.uniqueColors.length} - -
-
- -
- Colors: -
- {pesData.uniqueColors.slice(0, 8).map((color, idx) => { - // Primary metadata: brand and catalog number - const primaryMetadata = [ - color.brand, - color.catalogNumber ? `#${color.catalogNumber}` : null - ].filter(Boolean).join(" "); - - // Secondary metadata: chart and description - const secondaryMetadata = [ - color.chart, - color.description - ].filter(Boolean).join(" "); - - const metadata = [primaryMetadata, secondaryMetadata].filter(Boolean).join(" • "); - - // Show which thread blocks use this color - const threadNumbers = color.threadIndices.map(i => i + 1).join(", "); - const tooltipText = metadata - ? `Color ${idx + 1}: ${color.hex}\n${metadata}\nUsed in thread blocks: ${threadNumbers}` - : `Color ${idx + 1}: ${color.hex}\nUsed in thread blocks: ${threadNumbers}`; - - return ( -
- ); - })} - {pesData.uniqueColors.length > 8 && ( -
- +{pesData.uniqueColors.length - 8} -
- )} -
-
+ {canDelete && (