Skip to content

Commit

Permalink
Expose visuals constraints through the API (with args) (#4743)
Browse files Browse the repository at this point in the history
* Expose visuals constraints through the API

* address coderabbit comments

* added args input

* Address CR comments, cleaned up and renamed to defaultVisualConstraints

---------

Co-authored-by: Carlos Cano <[email protected]>
Co-authored-by: Bobby Kolev <[email protected]>
  • Loading branch information
3 people authored Dec 2, 2024
1 parent 99e1ec5 commit 7340096
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 39 deletions.
2 changes: 0 additions & 2 deletions src/domain/common/visual/avatar.constants.ts

This file was deleted.

78 changes: 78 additions & 0 deletions src/domain/common/visual/visual.constraints.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { VisualType } from '@common/enums/visual.type';
import { Field, ObjectType } from '@nestjs/graphql';

export const VISUAL_ALLOWED_TYPES = [
'image/png',
'image/jpeg',
'image/jpg',
'image/svg+xml',
'image/webp',
] as const;

export const DEFAULT_VISUAL_CONSTRAINTS = {
[VisualType.AVATAR]: {
minWidth: 190,
maxWidth: 410,
minHeight: 190,
maxHeight: 410,
aspectRatio: 1,
allowedTypes: VISUAL_ALLOWED_TYPES,
},
[VisualType.BANNER]: {
minWidth: 384,
maxWidth: 1536,
minHeight: 64,
maxHeight: 256,
aspectRatio: 6,
allowedTypes: VISUAL_ALLOWED_TYPES,
},
[VisualType.CARD]: {
minWidth: 307,
maxWidth: 410,
minHeight: 192,
maxHeight: 256,
aspectRatio: 1.6,
allowedTypes: VISUAL_ALLOWED_TYPES,
},
[VisualType.BANNER_WIDE]: {
minWidth: 640,
maxWidth: 2560,
minHeight: 64,
maxHeight: 256,
aspectRatio: 10,
allowedTypes: VISUAL_ALLOWED_TYPES,
},
} as const;

@ObjectType('VisualConstraints')
export class VisualConstraints {
@Field(() => Number, {
description: 'Minimum width resolution.',
})
minWidth!: number;

@Field(() => Number, {
description: 'Maximum width resolution.',
})
maxWidth!: number;

@Field(() => Number, {
description: 'Minimum height resolution.',
})
minHeight!: number;

@Field(() => Number, {
description: 'Maximum height resolution.',
})
maxHeight!: number;

@Field(() => Number, {
description: 'Dimensions ratio width / height.',
})
aspectRatio!: number;

@Field(() => [String], {
description: 'Allowed file types.',
})
allowedTypes!: typeof VISUAL_ALLOWED_TYPES;
}
13 changes: 2 additions & 11 deletions src/domain/common/visual/visual.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AuthorizableEntity } from '@domain/common/entity/authorizable-entity';
import { IVisual } from './visual.interface';
import { Profile } from '@domain/common/profile/profile.entity';
import { ALT_TEXT_LENGTH, URI_LENGTH } from '@common/constants';
import { VISUAL_ALLOWED_TYPES } from './visual.constraints';

@Entity()
export class Visual extends AuthorizableEntity implements IVisual {
Expand Down Expand Up @@ -42,21 +43,11 @@ export class Visual extends AuthorizableEntity implements IVisual {

constructor() {
super();
this.allowedTypes = this.createDefaultAllowedTypes();
this.allowedTypes = [...VISUAL_ALLOWED_TYPES];
this.minHeight = 0;
this.maxHeight = 0;
this.minWidth = 0;
this.maxWidth = 0;
this.aspectRatio = 1;
}

private createDefaultAllowedTypes(): string[] {
return [
'image/png',
'image/jpeg',
'image/jpg',
'image/svg+xml',
'image/webp',
];
}
}
35 changes: 10 additions & 25 deletions src/domain/common/visual/visual.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import { getImageDimensions, streamToBuffer } from '@common/utils';
import { Visual } from './visual.entity';
import { IVisual } from './visual.interface';
import { DeleteVisualInput } from './dto/visual.dto.delete';
import { avatarMinImageSize, avatarMaxImageSize } from './avatar.constants';
import { IStorageBucket } from '@domain/storage/storage-bucket/storage.bucket.interface';
import { ReadStream } from 'fs';
import { IDocument } from '@domain/storage/document/document.interface';
import { DocumentService } from '@domain/storage/document/document.service';
import { StorageBucketService } from '@domain/storage/storage-bucket/storage.bucket.service';
import { StorageUploadFailedException } from '@common/exceptions/storage/storage.upload.failed.exception';
import { AuthorizationPolicyType } from '@common/enums/authorization.policy.type';
import { VisualType } from '@common/enums/visual.type';
import { DEFAULT_VISUAL_CONSTRAINTS } from './visual.constraints';

@Injectable()
export class VisualService {
Expand Down Expand Up @@ -188,12 +189,8 @@ export class VisualService {
public createVisualBanner(uri?: string): IVisual {
return this.createVisual(
{
name: 'banner',
minWidth: 384,
maxWidth: 1536,
minHeight: 64,
maxHeight: 256,
aspectRatio: 6,
name: VisualType.BANNER,
...DEFAULT_VISUAL_CONSTRAINTS[VisualType.BANNER],
},
uri
);
Expand All @@ -202,12 +199,8 @@ export class VisualService {
public createVisualCard(uri?: string): IVisual {
return this.createVisual(
{
name: 'card',
minWidth: 307,
maxWidth: 410,
minHeight: 192,
maxHeight: 256,
aspectRatio: 1.6,
name: VisualType.CARD,
...DEFAULT_VISUAL_CONSTRAINTS[VisualType.CARD],
},
uri
);
Expand All @@ -216,25 +209,17 @@ export class VisualService {
public createVisualBannerWide(uri?: string): IVisual {
return this.createVisual(
{
name: 'bannerWide',
minWidth: 640,
maxWidth: 2560,
minHeight: 64,
maxHeight: 256,
aspectRatio: 10,
name: VisualType.BANNER_WIDE,
...DEFAULT_VISUAL_CONSTRAINTS[VisualType.BANNER_WIDE],
},
uri
);
}

public createVisualAvatar(): IVisual {
return this.createVisual({
name: 'avatar',
minWidth: avatarMinImageSize,
maxWidth: avatarMaxImageSize,
minHeight: avatarMinImageSize,
maxHeight: avatarMaxImageSize,
aspectRatio: 1,
name: VisualType.AVATAR,
...DEFAULT_VISUAL_CONSTRAINTS[VisualType.AVATAR],
});
}
}
3 changes: 2 additions & 1 deletion src/platform/configuration/config/config.module.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Module } from '@nestjs/common';
import { KonfigService } from './config.service';
import { ConfigurationResolverFields } from './config.resolver.fields';

@Module({
providers: [KonfigService],
providers: [KonfigService, ConfigurationResolverFields],
exports: [KonfigService],
})
export class KonfigModule {}
21 changes: 21 additions & 0 deletions src/platform/configuration/config/config.resolver.fields.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {
VisualConstraints,
DEFAULT_VISUAL_CONSTRAINTS,
} from '@domain/common/visual/visual.constraints';
import { Args, ResolveField } from '@nestjs/graphql';
import { Resolver } from '@nestjs/graphql';
import { IConfig } from './config.interface';
import { VisualType } from '@common/enums/visual.type';

@Resolver(() => IConfig)
export class ConfigurationResolverFields {
@ResolveField(() => VisualConstraints, {
nullable: false,
description: 'Visual constraints for the given type',
})
defaultVisualTypeConstraints(
@Args('type', { type: () => VisualType }) visualTypeInput: VisualType
): VisualConstraints {
return DEFAULT_VISUAL_CONSTRAINTS[visualTypeInput];
}
}

0 comments on commit 7340096

Please sign in to comment.