Files
graphql-api-js/src/datasources/interior-api.ts
T

156 lines
4.5 KiB
TypeScript

import {
Interior,
InteriorsFilter,
InteriorType,
} from '../types/interior-types';
import { Orientation } from '../types/product-types';
import { IdNumberResult, Maybe } from '../types/types';
import { BaseSQLDataSource } from './BaseSQLDataSource';
import { ImageServerApi } from './imageserver-api';
import * as CONFIG from '../config';
import { moveS3File } from '../s3';
const MINUTE = 60;
export class InteriorAPI extends BaseSQLDataSource {
imageServerApi: ImageServerApi;
constructor(config, imageServerApi: ImageServerApi) {
super(config);
this.imageServerApi = imageServerApi;
}
getInteriorType(roomTypePart: string): string {
switch (roomTypePart) {
case 'wallpaper':
return InteriorType[InteriorType.WALLPAPER];
case 'painting':
return InteriorType[InteriorType.PAINTING];
case 'poster':
return InteriorType[InteriorType.POSTER];
case 'framed-print':
return InteriorType[InteriorType.FRAMED_PRINT];
default:
throw new Error(`Unknown room type: ${roomTypePart}`);
}
}
getInteriorOrientation(roomOrientationPart: string): string {
switch (roomOrientationPart) {
case 'landscape':
return Orientation[Orientation.LANDSCAPE];
case 'standing':
return Orientation[Orientation.STANDING];
case 'square':
return Orientation[Orientation.SQUARE];
default:
throw new Error(`Unknown room orientation: ${roomOrientationPart}`);
}
}
getInteriorRoomNumber(roomNumberPart: string): number {
return parseInt(roomNumberPart.slice(4), 10);
}
decorateRow(row: any): Interior {
if (row.roomName) {
const parts = row.roomName.split('_');
row.roomNumber = this.getInteriorRoomNumber(parts[0]);
row.type = this.getInteriorType(parts[1]);
row.orientation = this.getInteriorOrientation(parts[2]);
}
return row;
}
async getInteriors(filter: Maybe<InteriorsFilter>): Promise<Array<Interior>> {
const sql = /* sql */ `
SELECT rooms.*, room_types.name roomType FROM rooms
LEFT JOIN room_types ON rooms.room_type_id = room_types.id
`;
const allInteriors = await this.cachedRaw(sql)
.cache(MINUTE * 60)
.then((data) =>
data.rows.map((row) => {
const res = {
...row,
roomName: row.name,
roomType: row.roomtype,
id: row.s3_suffix,
};
this.decorateRow(res);
return res;
}),
);
// Based on filter get valid interiors and filter out any else from all interiors
if (filter) {
const validUris = await this.imageServerApi.getInteriorsForProduct(
filter.productId,
);
return allInteriors.filter((i: Interior) => {
const it = i.type.toString().replace('_', '-').toLowerCase();
const or = i.orientation.toString().toLocaleLowerCase();
const uriMatch = `${or}/${it}/room${i.roomNumber}.`;
const foundUri = validUris.find(({ uri }) => uri.includes(uriMatch));
if (foundUri) {
i.uri = foundUri.uri;
return true;
}
return false;
});
}
// No filter so return all
return allInteriors;
}
async getPrintProductInteriors(printId: number): Promise<Array<Interior>> {
return this.knex
.select('*')
.from('v_interior_image_urls')
.orderBy('position')
.where('print_id', printId)
.cache(MINUTE)
.then((rows) => {
return rows.map((row) => {
const res = {
...row,
id: row.uri,
};
this.decorateRow(res);
return res;
});
});
}
// Mutations
async addOwnUploadToPrintId(
printId: number,
uploadedS3Key: string,
): Promise<IdNumberResult> {
// Get the last position entered in interiors for this printId
const positionRes: any = await this.knex
.queryBuilder()
.from('interiors')
.where({ print_id: printId })
.max('position')
.first();
const position = positionRes.max === null ? 0 : positionRes.max + 1;
// Insert the printId in interiors returning the id (important as it is used as image key name)
const res = await this.knex('interiors')
.insert({ print_id: printId, position: position })
.returning('id');
const interiorId = res[0];
// Move file
moveS3File(
CONFIG.uploadBucket,
uploadedS3Key,
CONFIG.imageBucket,
`interior-images/${interiorId}.jpg`,
);
return {
id: interiorId,
};
}
}