From 9b90e1033eacca6eab2a11a1b29ade23e39455db Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Fri, 6 Feb 2026 13:17:22 -0600 Subject: [PATCH] MME-8 Main image selected and passed to backend. --- .../EnterRecipeDataSubmitEvent.ts | 3 ++ .../enter-recipe-data/enter-recipe-data.html | 5 ++- .../enter-recipe-data/enter-recipe-data.ts | 1 + .../image-select/image-select.css | 8 ++--- .../image-select/image-select.html | 31 ++++++++++++++----- .../image-select/image-select.spec.ts | 27 ++++++++-------- .../image-select/image-select.ts | 7 +++-- src/app/shared/models/SetImageBody.ts | 4 +++ src/app/shared/services/EndpointService.ts | 6 +++- src/app/shared/services/ImageService.ts | 6 ++-- src/app/shared/services/RecipeDraftService.ts | 13 +++++++- 11 files changed, 76 insertions(+), 35 deletions(-) create mode 100644 src/app/shared/models/SetImageBody.ts diff --git a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/EnterRecipeDataSubmitEvent.ts b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/EnterRecipeDataSubmitEvent.ts index bbe05fd..c8ee008 100644 --- a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/EnterRecipeDataSubmitEvent.ts +++ b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/EnterRecipeDataSubmitEvent.ts @@ -1,3 +1,5 @@ +import { ImageView } from '../../../../shared/models/ImageView.model'; + export interface EnterRecipeDataSubmitEvent { title: string; slug: string; @@ -6,5 +8,6 @@ export interface EnterRecipeDataSubmitEvent { name: string; notes?: string | null; }>; + mainImage: ImageView | null; rawText: string; } diff --git a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/enter-recipe-data.html b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/enter-recipe-data.html index 6618532..75bbe1d 100644 --- a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/enter-recipe-data.html +++ b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/enter-recipe-data.html @@ -88,7 +88,10 @@

Select Main Image

- +

Recipe Text

diff --git a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/enter-recipe-data.ts b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/enter-recipe-data.ts index 87082e4..af810dc 100644 --- a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/enter-recipe-data.ts +++ b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/enter-recipe-data.ts @@ -211,6 +211,7 @@ export class EnterRecipeData implements OnInit { title: value.title!, slug: value.slug!, ingredients: this.ingredientModels().map((ingredientModel) => ingredientModel.draft), + mainImage: this.mainImage(), rawText: value.text!, }); } diff --git a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.css b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.css index bde5764..4a9b765 100644 --- a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.css +++ b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.css @@ -4,14 +4,12 @@ gap: 5px; } -.image-grid > img { +.image-grid-image { width: 100%; height: 100%; object-fit: cover; } -.selected-image { - border: 5px solid var(--primary-black); - border-radius: 10px; - box-sizing: border-box; +mat-card-content p { + overflow-wrap: anywhere; } diff --git a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.html b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.html index c653765..5625fd0 100644 --- a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.html +++ b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.html @@ -11,14 +11,31 @@

There was an error loading this image.

} @else { @let imageData = imageQuery.data(); - imageData!.imageView.alt + + imageData!.imageView.alt + +

{{ imageData!.imageView.filename }}

+
+ + Main image + +
} } - + } diff --git a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.spec.ts b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.spec.ts index 41a18e3..acb818f 100644 --- a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.spec.ts +++ b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.spec.ts @@ -3,21 +3,20 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ImageSelect } from './image-select'; describe('ImageSelect', () => { - let component: ImageSelect; - let fixture: ComponentFixture; + let component: ImageSelect; + let fixture: ComponentFixture; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ImageSelect] - }) - .compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ImageSelect], + }).compileComponents(); - fixture = TestBed.createComponent(ImageSelect); - component = fixture.componentInstance; - await fixture.whenStable(); - }); + fixture = TestBed.createComponent(ImageSelect); + component = fixture.componentInstance; + await fixture.whenStable(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.ts b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.ts index 3ed45f3..77f43c0 100644 --- a/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.ts +++ b/src/app/pages/recipe-upload-page/steps/enter-recipe-data/image-select/image-select.ts @@ -4,12 +4,13 @@ import { ImageService } from '../../../../../shared/services/ImageService'; import { injectQuery, keepPreviousData } from '@tanstack/angular-query-experimental'; import { Spinner } from '../../../../../shared/components/spinner/spinner'; import { ImageView } from '../../../../../shared/models/ImageView.model'; -import { injectQueries } from '@tanstack/angular-query-experimental/inject-queries-experimental' -import { NgClass } from '@angular/common'; +import { injectQueries } from '@tanstack/angular-query-experimental/inject-queries-experimental'; +import { MatCard, MatCardActions, MatCardContent, MatCardImage } from '@angular/material/card'; +import { MatCheckbox } from '@angular/material/checkbox'; @Component({ selector: 'app-image-select', - imports: [MatPaginator, Spinner, NgClass], + imports: [MatPaginator, Spinner, MatCard, MatCardImage, MatCardContent, MatCardActions, MatCheckbox], templateUrl: './image-select.html', styleUrl: './image-select.css', }) diff --git a/src/app/shared/models/SetImageBody.ts b/src/app/shared/models/SetImageBody.ts new file mode 100644 index 0000000..a20d6fa --- /dev/null +++ b/src/app/shared/models/SetImageBody.ts @@ -0,0 +1,4 @@ +export interface SetImageBody { + username: string; + userFilename: string; +} diff --git a/src/app/shared/services/EndpointService.ts b/src/app/shared/services/EndpointService.ts index 6e82292..3d1d1fe 100644 --- a/src/app/shared/services/EndpointService.ts +++ b/src/app/shared/services/EndpointService.ts @@ -7,7 +7,11 @@ import { environment } from '../../../environments/environment'; providedIn: 'root', }) export class EndpointService { - public getUrl

(endpoint: keyof typeof Endpoints, pathParts?: string[], queryParams?: QueryParams

): string { + public getUrl

( + endpoint: keyof typeof Endpoints, + pathParts?: string[], + queryParams?: QueryParams

, + ): string { const urlSearchParams = new URLSearchParams(); if (queryParams?.page !== undefined) { urlSearchParams.set('page', queryParams.page.toString()); diff --git a/src/app/shared/services/ImageService.ts b/src/app/shared/services/ImageService.ts index f7bab37..81f8a5a 100644 --- a/src/app/shared/services/ImageService.ts +++ b/src/app/shared/services/ImageService.ts @@ -4,7 +4,7 @@ import { firstValueFrom, map } from 'rxjs'; import { EndpointService } from './EndpointService'; import { ImageView } from '../models/ImageView.model'; import { SliceView } from '../models/SliceView.model'; -import { QueryParams } from '../models/Query.model';; +import { QueryParams } from '../models/Query.model'; @Injectable({ providedIn: 'root', @@ -22,7 +22,7 @@ export class ImageService { 'height', 'width', 'owner', - 'viewers' + 'viewers', ] as const; private readonly httpClient = inject(HttpClient); @@ -30,7 +30,7 @@ export class ImageService { public getOwnedImages(queryParams?: QueryParams): Promise> { return firstValueFrom( - this.httpClient.get>(this.endpointService.getUrl('images', [], queryParams)) + this.httpClient.get>(this.endpointService.getUrl('images', [], queryParams)), ); } diff --git a/src/app/shared/services/RecipeDraftService.ts b/src/app/shared/services/RecipeDraftService.ts index 1437566..f0a1ef2 100644 --- a/src/app/shared/services/RecipeDraftService.ts +++ b/src/app/shared/services/RecipeDraftService.ts @@ -7,6 +7,8 @@ import { RecipeDraftViewModel } from '../models/RecipeDraftView.model'; import { EndpointService } from './EndpointService'; import { WithStringDates } from '../util'; import { Recipe } from '../models/Recipe.model'; +import { ImageView } from '../models/ImageView.model'; +import { SetImageBody } from '../models/SetImageBody'; @Injectable({ providedIn: 'root', @@ -82,12 +84,21 @@ export class RecipeDraftService { name: string; notes?: string | null; }>; + mainImage?: ImageView | null; rawText?: string | null; }, ): Promise { return firstValueFrom( this.http - .put>(this.endpointService.getUrl('recipeDrafts', [id]), data) + .put>(this.endpointService.getUrl('recipeDrafts', [id]), { + ...data, + mainImage: data.mainImage + ? ({ + username: data.mainImage.owner.username, + userFilename: data.mainImage.filename, + } satisfies SetImageBody) + : undefined, + }) .pipe( map((rawView) => this.hydrateView(rawView)), map((draft) => ({