Skip to content

Commit 73b2b62

Browse files
committed
feat: PictureCrop via gRPC
1 parent 38a9b2e commit 73b2b62

File tree

4 files changed

+287
-22
lines changed

4 files changed

+287
-22
lines changed

src/app/moder/pictures/item/crop/crop.component.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import {Component, OnDestroy, OnInit} from '@angular/core';
22
import {ActivatedRoute, Router} from '@angular/router';
3-
import {APIService} from '@services/api.service';
3+
import {SetPictureCropRequest} from '@grpc/spec.pb';
4+
import {PicturesClient} from '@grpc/spec.pbsc';
45
import {PageEnvService} from '@services/page-env.service';
56
import {APIPicture, PictureService} from '@services/picture';
67
import * as $ from 'jquery';
7-
import {BehaviorSubject, Subscription} from 'rxjs';
8-
import {debounceTime, distinctUntilChanged, map, switchMap} from 'rxjs/operators';
8+
import {BehaviorSubject, EMPTY, Subscription} from 'rxjs';
9+
import {catchError, debounceTime, distinctUntilChanged, map, switchMap} from 'rxjs/operators';
910

1011
// @ts-expect-error Legacy
1112
import Jcrop from '../../../../jcrop/jquery.Jcrop.js';
13+
import {ToastsService} from '../../../../toasts/toasts.service';
1214

1315
interface Crop {
1416
h: number;
@@ -37,11 +39,12 @@ export class ModerPicturesItemCropComponent implements OnInit, OnDestroy {
3739
protected readonly img$ = new BehaviorSubject<HTMLElement | null>(null);
3840

3941
constructor(
40-
private readonly api: APIService,
4142
private readonly router: Router,
4243
private readonly route: ActivatedRoute,
4344
private readonly pictureService: PictureService,
4445
private readonly pageEnv: PageEnvService,
46+
private readonly picturesClient: PicturesClient,
47+
private readonly toastService: ToastsService,
4548
) {}
4649

4750
ngOnInit(): void {
@@ -126,17 +129,22 @@ export class ModerPicturesItemCropComponent implements OnInit, OnDestroy {
126129

127130
protected saveCrop() {
128131
this.picture &&
129-
this.api
130-
.request<void>('PUT', 'picture/' + this.picture.id, {
131-
body: {
132-
crop: {
133-
height: Math.round(this.currentCrop.h),
134-
left: Math.round(this.currentCrop.x),
135-
top: Math.round(this.currentCrop.y),
136-
width: Math.round(this.currentCrop.w),
137-
},
138-
},
139-
})
132+
this.picturesClient
133+
.setPictureCrop(
134+
new SetPictureCropRequest({
135+
cropHeight: Math.round(this.currentCrop.h),
136+
cropLeft: Math.round(this.currentCrop.x),
137+
cropTop: Math.round(this.currentCrop.y),
138+
cropWidth: Math.round(this.currentCrop.w),
139+
pictureId: '' + this.picture.id,
140+
}),
141+
)
142+
.pipe(
143+
catchError((error: unknown) => {
144+
this.toastService.handleError(error);
145+
return EMPTY;
146+
}),
147+
)
140148
.subscribe(() => {
141149
this.picture && this.router.navigate(['/moder/pictures', this.picture.id]);
142150
});

src/app/upload/index/index.component.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import {HttpErrorResponse, HttpEventType} from '@angular/common/http';
22
import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
33
import {ActivatedRoute} from '@angular/router';
4-
import {APIItem, ItemFields, ItemRequest} from '@grpc/spec.pb';
5-
import {ItemsClient} from '@grpc/spec.pbsc';
4+
import {APIItem, ItemFields, ItemRequest, SetPictureCropRequest} from '@grpc/spec.pb';
5+
import {ItemsClient, PicturesClient} from '@grpc/spec.pbsc';
66
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
77
import {APIService} from '@services/api.service';
88
import {AuthService} from '@services/auth.service';
@@ -105,6 +105,7 @@ export class UploadIndexComponent implements OnInit {
105105
private readonly keycloak: KeycloakService,
106106
private readonly languageService: LanguageService,
107107
private readonly itemsClient: ItemsClient,
108+
private readonly picturesClient: PicturesClient,
108109
) {}
109110

110111
ngOnInit(): void {
@@ -256,11 +257,15 @@ export class UploadIndexComponent implements OnInit {
256257
modalRef.componentInstance.changed
257258
.pipe(
258259
switchMap(() =>
259-
this.api.request<void>('PUT', 'picture/' + picture.id, {
260-
body: {
261-
crop: picture.crop,
262-
},
263-
}),
260+
this.picturesClient.setPictureCrop(
261+
new SetPictureCropRequest({
262+
cropHeight: picture.crop.height || undefined,
263+
cropLeft: picture.crop.left || undefined,
264+
cropTop: picture.crop.top || undefined,
265+
cropWidth: picture.crop.width || undefined,
266+
pictureId: '' + picture.id,
267+
}),
268+
),
264269
),
265270
catchError((response: unknown) => {
266271
if (response instanceof HttpErrorResponse) {

src/grpc/spec.pb.ts

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24900,6 +24900,221 @@ export module CreatePictureItemRequest {
2490024900
}
2490124901
}
2490224902

24903+
/**
24904+
* Message implementation for goautowp.SetPictureCropRequest
24905+
*/
24906+
export class SetPictureCropRequest implements GrpcMessage {
24907+
static id = 'goautowp.SetPictureCropRequest';
24908+
24909+
/**
24910+
* Deserialize binary data to message
24911+
* @param instance message instance
24912+
*/
24913+
static deserializeBinary(bytes: ByteSource) {
24914+
const instance = new SetPictureCropRequest();
24915+
SetPictureCropRequest.deserializeBinaryFromReader(
24916+
instance,
24917+
new BinaryReader(bytes)
24918+
);
24919+
return instance;
24920+
}
24921+
24922+
/**
24923+
* Check all the properties and set default protobuf values if necessary
24924+
* @param _instance message instance
24925+
*/
24926+
static refineValues(_instance: SetPictureCropRequest) {
24927+
_instance.pictureId = _instance.pictureId || '0';
24928+
_instance.cropLeft = _instance.cropLeft || 0;
24929+
_instance.cropTop = _instance.cropTop || 0;
24930+
_instance.cropWidth = _instance.cropWidth || 0;
24931+
_instance.cropHeight = _instance.cropHeight || 0;
24932+
}
24933+
24934+
/**
24935+
* Deserializes / reads binary message into message instance using provided binary reader
24936+
* @param _instance message instance
24937+
* @param _reader binary reader instance
24938+
*/
24939+
static deserializeBinaryFromReader(
24940+
_instance: SetPictureCropRequest,
24941+
_reader: BinaryReader
24942+
) {
24943+
while (_reader.nextField()) {
24944+
if (_reader.isEndGroup()) break;
24945+
24946+
switch (_reader.getFieldNumber()) {
24947+
case 1:
24948+
_instance.pictureId = _reader.readInt64String();
24949+
break;
24950+
case 4:
24951+
_instance.cropLeft = _reader.readUint32();
24952+
break;
24953+
case 5:
24954+
_instance.cropTop = _reader.readUint32();
24955+
break;
24956+
case 6:
24957+
_instance.cropWidth = _reader.readUint32();
24958+
break;
24959+
case 7:
24960+
_instance.cropHeight = _reader.readUint32();
24961+
break;
24962+
default:
24963+
_reader.skipField();
24964+
}
24965+
}
24966+
24967+
SetPictureCropRequest.refineValues(_instance);
24968+
}
24969+
24970+
/**
24971+
* Serializes a message to binary format using provided binary reader
24972+
* @param _instance message instance
24973+
* @param _writer binary writer instance
24974+
*/
24975+
static serializeBinaryToWriter(
24976+
_instance: SetPictureCropRequest,
24977+
_writer: BinaryWriter
24978+
) {
24979+
if (_instance.pictureId) {
24980+
_writer.writeInt64String(1, _instance.pictureId);
24981+
}
24982+
if (_instance.cropLeft) {
24983+
_writer.writeUint32(4, _instance.cropLeft);
24984+
}
24985+
if (_instance.cropTop) {
24986+
_writer.writeUint32(5, _instance.cropTop);
24987+
}
24988+
if (_instance.cropWidth) {
24989+
_writer.writeUint32(6, _instance.cropWidth);
24990+
}
24991+
if (_instance.cropHeight) {
24992+
_writer.writeUint32(7, _instance.cropHeight);
24993+
}
24994+
}
24995+
24996+
private _pictureId: string;
24997+
private _cropLeft: number;
24998+
private _cropTop: number;
24999+
private _cropWidth: number;
25000+
private _cropHeight: number;
25001+
25002+
/**
25003+
* Message constructor. Initializes the properties and applies default Protobuf values if necessary
25004+
* @param _value initial values object or instance of SetPictureCropRequest to deeply clone from
25005+
*/
25006+
constructor(_value?: RecursivePartial<SetPictureCropRequest.AsObject>) {
25007+
_value = _value || {};
25008+
this.pictureId = _value.pictureId;
25009+
this.cropLeft = _value.cropLeft;
25010+
this.cropTop = _value.cropTop;
25011+
this.cropWidth = _value.cropWidth;
25012+
this.cropHeight = _value.cropHeight;
25013+
SetPictureCropRequest.refineValues(this);
25014+
}
25015+
get pictureId(): string {
25016+
return this._pictureId;
25017+
}
25018+
set pictureId(value: string) {
25019+
this._pictureId = value;
25020+
}
25021+
get cropLeft(): number {
25022+
return this._cropLeft;
25023+
}
25024+
set cropLeft(value: number) {
25025+
this._cropLeft = value;
25026+
}
25027+
get cropTop(): number {
25028+
return this._cropTop;
25029+
}
25030+
set cropTop(value: number) {
25031+
this._cropTop = value;
25032+
}
25033+
get cropWidth(): number {
25034+
return this._cropWidth;
25035+
}
25036+
set cropWidth(value: number) {
25037+
this._cropWidth = value;
25038+
}
25039+
get cropHeight(): number {
25040+
return this._cropHeight;
25041+
}
25042+
set cropHeight(value: number) {
25043+
this._cropHeight = value;
25044+
}
25045+
25046+
/**
25047+
* Serialize message to binary data
25048+
* @param instance message instance
25049+
*/
25050+
serializeBinary() {
25051+
const writer = new BinaryWriter();
25052+
SetPictureCropRequest.serializeBinaryToWriter(this, writer);
25053+
return writer.getResultBuffer();
25054+
}
25055+
25056+
/**
25057+
* Cast message to standard JavaScript object (all non-primitive values are deeply cloned)
25058+
*/
25059+
toObject(): SetPictureCropRequest.AsObject {
25060+
return {
25061+
pictureId: this.pictureId,
25062+
cropLeft: this.cropLeft,
25063+
cropTop: this.cropTop,
25064+
cropWidth: this.cropWidth,
25065+
cropHeight: this.cropHeight
25066+
};
25067+
}
25068+
25069+
/**
25070+
* Convenience method to support JSON.stringify(message), replicates the structure of toObject()
25071+
*/
25072+
toJSON() {
25073+
return this.toObject();
25074+
}
25075+
25076+
/**
25077+
* Cast message to JSON using protobuf JSON notation: https://developers.google.com/protocol-buffers/docs/proto3#json
25078+
* Attention: output differs from toObject() e.g. enums are represented as names and not as numbers, Timestamp is an ISO Date string format etc.
25079+
* If the message itself or some of descendant messages is google.protobuf.Any, you MUST provide a message pool as options. If not, the messagePool is not required
25080+
*/
25081+
toProtobufJSON(
25082+
// @ts-ignore
25083+
options?: ToProtobufJSONOptions
25084+
): SetPictureCropRequest.AsProtobufJSON {
25085+
return {
25086+
pictureId: this.pictureId,
25087+
cropLeft: this.cropLeft,
25088+
cropTop: this.cropTop,
25089+
cropWidth: this.cropWidth,
25090+
cropHeight: this.cropHeight
25091+
};
25092+
}
25093+
}
25094+
export module SetPictureCropRequest {
25095+
/**
25096+
* Standard JavaScript object representation for SetPictureCropRequest
25097+
*/
25098+
export interface AsObject {
25099+
pictureId: string;
25100+
cropLeft: number;
25101+
cropTop: number;
25102+
cropWidth: number;
25103+
cropHeight: number;
25104+
}
25105+
25106+
/**
25107+
* Protobuf JSON representation for SetPictureCropRequest
25108+
*/
25109+
export interface AsProtobufJSON {
25110+
pictureId: string;
25111+
cropLeft: number;
25112+
cropTop: number;
25113+
cropWidth: number;
25114+
cropHeight: number;
25115+
}
25116+
}
25117+
2490325118
/**
2490425119
* Message implementation for goautowp.DeleteSimilarRequest
2490525120
*/

src/grpc/spec.pbsc.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3884,6 +3884,27 @@ export class PicturesClient {
38843884
requestClass: thisProto.CreatePictureItemRequest,
38853885
responseClass: googleProtobuf001.Empty
38863886
});
3887+
},
3888+
/**
3889+
* Unary call: /goautowp.Pictures/SetPictureCrop
3890+
*
3891+
* @param requestMessage Request message
3892+
* @param requestMetadata Request metadata
3893+
* @returns Observable<GrpcEvent<googleProtobuf001.Empty>>
3894+
*/
3895+
setPictureCrop: (
3896+
requestData: thisProto.SetPictureCropRequest,
3897+
requestMetadata = new GrpcMetadata()
3898+
): Observable<GrpcEvent<googleProtobuf001.Empty>> => {
3899+
return this.handler.handle({
3900+
type: GrpcCallType.unary,
3901+
client: this.client,
3902+
path: '/goautowp.Pictures/SetPictureCrop',
3903+
requestData,
3904+
requestMetadata,
3905+
requestClass: thisProto.SetPictureCropRequest,
3906+
responseClass: googleProtobuf001.Empty
3907+
});
38873908
}
38883909
};
38893910

@@ -4166,6 +4187,22 @@ export class PicturesClient {
41664187
.createPictureItem(requestData, requestMetadata)
41674188
.pipe(throwStatusErrors(), takeMessages());
41684189
}
4190+
4191+
/**
4192+
* Unary call @/goautowp.Pictures/SetPictureCrop
4193+
*
4194+
* @param requestMessage Request message
4195+
* @param requestMetadata Request metadata
4196+
* @returns Observable<googleProtobuf001.Empty>
4197+
*/
4198+
setPictureCrop(
4199+
requestData: thisProto.SetPictureCropRequest,
4200+
requestMetadata = new GrpcMetadata()
4201+
): Observable<googleProtobuf001.Empty> {
4202+
return this.$raw
4203+
.setPictureCrop(requestData, requestMetadata)
4204+
.pipe(throwStatusErrors(), takeMessages());
4205+
}
41694206
}
41704207
/**
41714208
* Service client implementation for goautowp.Messaging

0 commit comments

Comments
 (0)