MME-8 Main image selected and passed to backend.
This commit is contained in:
parent
b07a8fd90b
commit
9b90e1033e
@ -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;
|
||||
}
|
||||
|
||||
@ -88,7 +88,10 @@
|
||||
<button matButton="outlined" (click)="openImageUploadDialog()" type="button">Upload Image</button>
|
||||
|
||||
<h4>Select Main Image</h4>
|
||||
<app-image-select (select)="onMainImageSelect($event)" [selectedUsernameFilename]="mainImageUsernameFilename()"></app-image-select>
|
||||
<app-image-select
|
||||
(select)="onMainImageSelect($event)"
|
||||
[selectedUsernameFilename]="mainImageUsernameFilename()"
|
||||
></app-image-select>
|
||||
|
||||
<h3>Recipe Text</h3>
|
||||
<mat-form-field>
|
||||
|
||||
@ -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!,
|
||||
});
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -11,14 +11,31 @@
|
||||
<p>There was an error loading this image.</p>
|
||||
} @else {
|
||||
@let imageData = imageQuery.data();
|
||||
<img
|
||||
[src]="imageData!.blobUrl"
|
||||
alt="imageData!.imageView.alt"
|
||||
(click)="onImageClick(imageData!.imageView)"
|
||||
[ngClass]="{ 'selected-image': isSelected(imageData!.imageView) }"
|
||||
>
|
||||
<mat-card>
|
||||
<img
|
||||
mat-card-image
|
||||
[src]="imageData!.blobUrl"
|
||||
alt="imageData!.imageView.alt"
|
||||
(click)="onImageClick(imageData!.imageView)"
|
||||
class="image-grid-image"
|
||||
/>
|
||||
<mat-card-content>
|
||||
<p>{{ imageData!.imageView.filename }}</p>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<mat-checkbox
|
||||
[checked]="isSelected(imageData!.imageView)"
|
||||
(click)="onImageClick(imageData!.imageView)"
|
||||
>Main image</mat-checkbox>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<mat-paginator [length]="imageCount()" [pageSize]="pageSize()" [pageSizeOptions]="[3, 6, 9, 12]" (page)="onPage($event)"></mat-paginator>
|
||||
<mat-paginator
|
||||
[length]="imageCount()"
|
||||
[pageSize]="pageSize()"
|
||||
[pageSizeOptions]="[3, 6, 9, 12]"
|
||||
(page)="onPage($event)"
|
||||
></mat-paginator>
|
||||
}
|
||||
|
||||
@ -3,21 +3,20 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ImageSelect } from './image-select';
|
||||
|
||||
describe('ImageSelect', () => {
|
||||
let component: ImageSelect;
|
||||
let fixture: ComponentFixture<ImageSelect>;
|
||||
let component: ImageSelect;
|
||||
let fixture: ComponentFixture<ImageSelect>;
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
@ -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',
|
||||
})
|
||||
|
||||
4
src/app/shared/models/SetImageBody.ts
Normal file
4
src/app/shared/models/SetImageBody.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface SetImageBody {
|
||||
username: string;
|
||||
userFilename: string;
|
||||
}
|
||||
@ -7,7 +7,11 @@ import { environment } from '../../../environments/environment';
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class EndpointService {
|
||||
public getUrl<P extends readonly string[] = []>(endpoint: keyof typeof Endpoints, pathParts?: string[], queryParams?: QueryParams<P>): string {
|
||||
public getUrl<P extends readonly string[] = []>(
|
||||
endpoint: keyof typeof Endpoints,
|
||||
pathParts?: string[],
|
||||
queryParams?: QueryParams<P>,
|
||||
): string {
|
||||
const urlSearchParams = new URLSearchParams();
|
||||
if (queryParams?.page !== undefined) {
|
||||
urlSearchParams.set('page', queryParams.page.toString());
|
||||
|
||||
@ -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<typeof ImageService.ImageProps>): Promise<SliceView<ImageView>> {
|
||||
return firstValueFrom(
|
||||
this.httpClient.get<SliceView<ImageView>>(this.endpointService.getUrl('images', [], queryParams))
|
||||
this.httpClient.get<SliceView<ImageView>>(this.endpointService.getUrl('images', [], queryParams)),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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<RecipeUploadClientModel> {
|
||||
return firstValueFrom(
|
||||
this.http
|
||||
.put<WithStringDates<RecipeDraftViewModel>>(this.endpointService.getUrl('recipeDrafts', [id]), data)
|
||||
.put<WithStringDates<RecipeDraftViewModel>>(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) => ({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user