diff --git a/migrations/1686943144806_update-projects-with-template-fields.ts b/migrations/1686943144806_update-projects-with-template-fields.ts new file mode 100644 index 00000000..795a2565 --- /dev/null +++ b/migrations/1686943144806_update-projects-with-template-fields.ts @@ -0,0 +1,24 @@ +import { MigrationBuilder } from 'node-pg-migrate' +import { Project } from '../src/Project' + +const tableName = Project.tableName + +/** + * Migrates the DB by adding the is_template, video and template_status columns to the projects table. + * The is_template column will be false for projects created by the users. + * The video column will be null for projects created by the users or string for projects created as templates. + * The template_status column will be null for projects created by the users or string for projects created as templates. + */ +export async function up(pgm: MigrationBuilder): Promise { + pgm.addColumn(tableName, { + ['is_template']: { type: 'BOOLEAN', default: false, notNull: true }, + ['video']: { type: 'TEXT', default: null, notNull: false }, + ['template_status']: { type: 'TEXT', default: null, notNull: false }, + }) +} + +export async function down(pgm: MigrationBuilder): Promise { + pgm.dropColumn(tableName, 'is_template') + pgm.dropColumn(tableName, 'video') + pgm.dropColumn(tableName, 'template_status') +} diff --git a/src/Project/Project.router.ts b/src/Project/Project.router.ts index 07671f93..3542da67 100644 --- a/src/Project/Project.router.ts +++ b/src/Project/Project.router.ts @@ -7,7 +7,11 @@ import { Router } from '../common/Router' import { addInmutableCacheControlHeader } from '../common/headers' import { HTTPError, STATUS_CODES } from '../common/HTTPError' import { getValidator } from '../utils/validator' -import { withModelExists, withModelAuthorization } from '../middleware' +import { + withModelExists, + withModelAuthorization, + withLowercaseQueryParams, +} from '../middleware' import { S3Project, getBucketURL, getUploader } from '../S3' import { withAuthentication, AuthRequest } from '../middleware/authentication' import { Ownable } from '../Ownable' @@ -45,6 +49,7 @@ export class ProjectRouter extends Router { this.router.get( '/projects', withAuthentication, + withLowercaseQueryParams(['is_template']), server.handleRequest(this.getProjects) ) @@ -130,8 +135,15 @@ export class ProjectRouter extends Router { async getProjects(req: AuthRequest) { const eth_address = req.auth.ethAddress + const is_template = req.query.is_template + const projectSearcher = new SearchableProject(req) - return projectSearcher.searchByEthAddress(eth_address) + + if (is_template === 'true') { + return projectSearcher.searchByIsTemplate() + } else { + return projectSearcher.searchByEthAddress(eth_address) + } } async getProject(req: AuthRequest) { diff --git a/src/Project/Project.types.ts b/src/Project/Project.types.ts index 1a71bfbf..41b3e6aa 100644 --- a/src/Project/Project.types.ts +++ b/src/Project/Project.types.ts @@ -18,6 +18,9 @@ export type ProjectAttributes = { created_at: Date updated_at: Date creation_coords: string + is_template: boolean + video?: string + template_status?: TemplateStatus } export type ProjectStatisticsAttributes = Pick< @@ -32,6 +35,11 @@ export type ProjectStatisticsAttributes = Pick< | 'nft_shapes' > +export enum TemplateStatus { + PENDING = 'pending', + AVAILABLE = 'available', +} + export const projectSchema = Object.freeze({ type: 'object', properties: { @@ -47,6 +55,12 @@ export const projectSchema = Object.freeze({ created_at: { type: ['string', 'null'] }, updated_at: { type: ['string', 'null'] }, creation_coords: { type: 'string' }, + is_template: { type: ['boolean', 'null'] }, + video: { type: ['string', 'null'] }, + template_status: { + type: ['string', 'null'], + enum: [TemplateStatus.PENDING, TemplateStatus.AVAILABLE, null], + }, }, additionalProperties: false, required: ['id', 'title', 'description', 'scene_id', 'cols', 'rows'], @@ -60,4 +74,6 @@ export const searchableProjectProperties: (keyof ProjectAttributes)[] = [ 'created_at', 'updated_at', 'creation_coords', + 'is_template', + 'template_status', ] diff --git a/src/Project/SearchableProject.ts b/src/Project/SearchableProject.ts index d7e039ff..9a2828fb 100644 --- a/src/Project/SearchableProject.ts +++ b/src/Project/SearchableProject.ts @@ -28,4 +28,22 @@ export class SearchableProject { return searchableProject.search(parameters, conditions) } + + async searchByIsTemplate() { + const requestParameters = new RequestParameters(this.req) + const searchableProject = new SearchableModel( + Project.tableName + ) + const parameters = new SearchableParameters( + requestParameters + ) + const conditions = new SearchableConditions( + requestParameters, + { eq: searchableProjectProperties } + ) + conditions.addExtras('eq', { is_template: true }) + conditions.addExtras('eq', { is_deleted: false }) + + return searchableProject.search(parameters, conditions) + } }