Skip to content
Snippets Groups Projects
Commit fc6f114e authored by Richard Fernando Heise Ferreira's avatar Richard Fernando Heise Ferreira
Browse files

Merge branch 'Issue/Connections-new-backend' into 'develop'

Conection resource

See merge request !62
parents be96cf6c 49c83f22
No related branches found
No related tags found
1 merge request!62Conection resource
ALTER TYPE "resource_state" ADD VALUE 'deleted';--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "item_achievements" (
"item_id" integer NOT NULL,
"achievement_id" integer NOT NULL,
CONSTRAINT "item_achievements_item_id_achievement_id_pk" PRIMARY KEY("item_id","achievement_id")
);
--> statement-breakpoint
ALTER TABLE "achievements" RENAME COLUMN "state" TO "review_state";--> statement-breakpoint
ALTER TABLE "collection_likes" RENAME COLUMN "collection" TO "collection_id";--> statement-breakpoint
ALTER TABLE "users" RENAME COLUMN "active" TO "is_active";--> statement-breakpoint
ALTER TABLE "collection_likes" DROP CONSTRAINT "collection_likes_collection_collections_id_fk";
--> statement-breakpoint
ALTER TABLE "items" DROP CONSTRAINT "items_achievement_id_achievements_id_fk";
--> statement-breakpoint
ALTER TABLE "achievements" ALTER COLUMN "review_state" SET DEFAULT 'under_review';--> statement-breakpoint
ALTER TABLE "collections" ALTER COLUMN "name" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "resources" ALTER COLUMN "thumbnail" DROP NOT NULL;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "item_achievements" ADD CONSTRAINT "item_achievements_item_id_items_id_fk" FOREIGN KEY ("item_id") REFERENCES "public"."items"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "item_achievements" ADD CONSTRAINT "item_achievements_achievement_id_achievements_id_fk" FOREIGN KEY ("achievement_id") REFERENCES "public"."achievements"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "collection_likes" ADD CONSTRAINT "collection_likes_collection_id_collections_id_fk" FOREIGN KEY ("collection_id") REFERENCES "public"."collections"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
ALTER TABLE "items" DROP COLUMN IF EXISTS "achievement_id";--> statement-breakpoint
ALTER TABLE "resources" DROP COLUMN IF EXISTS "active";--> statement-breakpoint
ALTER TABLE "users" DROP COLUMN IF EXISTS "institution";
\ No newline at end of file
This diff is collapsed.
......@@ -8,6 +8,13 @@
"when": 1744041940840,
"tag": "0000_volatile_whirlwind",
"breakpoints": true
},
{
"idx": 1,
"version": "7",
"when": 1743689366285,
"tag": "0001_milky_annihilus",
"breakpoints": true
}
]
}
\ No newline at end of file
......@@ -6,12 +6,8 @@ import type {
} from '../schema/collections.schema'
import db from "..";
import collectionTable, { collectionSchemas } from "../schema/collections.schema";
import { and, eq, isNull } from 'drizzle-orm'
import resourceTable, { resourceSchema, type ResourceModel } from "../schema/resource.schema";
import fs from 'fs';
import path from 'path';
import archiver from 'archiver';
import { PassThrough } from "stream";
import { and, eq } from 'drizzle-orm'
import resourceTable, { type ResourceModel } from "../schema/resource.schema";
import { collectionResourcesTable } from "../schema";
......
......@@ -61,7 +61,6 @@ export class commentsRepo {
.select()
.from(commentsTable)
.where(isNull(commentsTable.deleted_at))
return commentsSchema.model.array().parse(comments)
}
......@@ -72,7 +71,7 @@ export class commentsRepo {
.from(commentsTable)
.where(and(eq(commentsTable.resource_id, id_resource), isNull(commentsTable.deleted_at)))
return commentsSchema.model.array().parse(comments)
return comments ? commentsSchema.model.array().parse(comments) : []
}
//retorna todos(ativos e inativos) os comentarios de um recurso
......@@ -80,9 +79,9 @@ export class commentsRepo {
const comments = await db
.select()
.from(commentsTable)
.where(and(eq(commentsTable.resource_id, id_resource)))
.where((eq(commentsTable.resource_id, id_resource)))
return commentsSchema.model.array().parse(comments)
return comments ? commentsSchema.model.array().parse(comments) : []
}
......
......@@ -31,5 +31,4 @@ export class HomologationRepo {
return resourceSchema.model.array().parse(resources)
}
}
......@@ -7,6 +7,7 @@ import { createApexError, HttpStatus } from "@/services/error.service";
import { Hono } from "hono";
import { UserStatsService } from "@/services/user-stats.service";
import { ResourceStatsService } from "@/services/resource-stats.service";
import { UserService } from "@/services/user.service";
import {
createCommentRoute,
......@@ -24,6 +25,7 @@ import {
const service = Container.get(CommentsService);
const serviceUserStats = Container.get(UserStatsService)
const serviceStatsResource = Container.get(ResourceStatsService)
const serviceUser = Container.get(UserService)
export const commentsRouter = honoWithJwt()
......@@ -35,6 +37,7 @@ export const commentsRouter = honoWithJwt()
try {
const input = await c.req.valid('json')
const comment = commentsSchema.dto.parse(await service.create(input))
console.log("nao funcioina")
await serviceUserStats.updateComments(input.user_id)
await serviceStatsResource.updateComments(input.resource_id)
......@@ -172,13 +175,26 @@ export const publicCommentsRoute = new Hono()
}
)
// get all resource by resource
.get('/findCommentsByResource/:resource_id', findCommentsByResourceRoute, async (c) => {
try {
const id_resource = +c.req.param('resource_id')
const comments =commentsSchema.dto.array().parse( await service.findCommentsByResource(id_resource));
return c.json(comments);
const comments = await service.findCommentsByResource(id_resource);
const commentsWithUser = await Promise.all(
comments.map(async(comment) =>{
const user = await serviceUser.findById(comment.user_id)
return{
...comment,
author_name: user?.name || 'unknown'
};
})
);
//retornar nome do usuario que comentou
return c.json(commentsWithUser);
} catch (e) {
return c.json(
createApexError({
......@@ -193,7 +209,7 @@ export const publicCommentsRoute = new Hono()
}
})
// get active resource by resource
.get('/findAllCommentsByResource/:resource_id', findAllCommentsByResourceRoute, async (c) => {
try {
const id_resource = +c.req.param('resource_id')
......
......@@ -12,6 +12,7 @@ import { resourceLanguagesRepo } from "@/db/repo/resource-language.repo";
import { ObjectTypeService } from "@/services/object-type.service";
import { ResourceEducationalStagesService } from "@/services/resource-educational-stages.service";
import { ResourceSubjectsService } from "@/services/resource-subjects.service";
import { UserService } from "@/services/user.service";
import {
createResourceRoute,
......@@ -33,6 +34,7 @@ const objectTypeService = Container.get(ObjectTypeService);
const resourceLanguagesService = Container.get(resourceLanguagesRepo);
const resourceEducationalStagesService = Container.get(ResourceEducationalStagesService);
const resourceSubjectsService = Container.get(ResourceSubjectsService);
const userService = Container.get(UserService);
//define um novo Model
type ResourceWithObjectTypeName = ResourceModel & {
......@@ -319,18 +321,21 @@ export const publicResourceRouter = new Hono()
return c.json({ message: "Arquivo não encontrado" }, 404);
}
// Buscar todas as linguagens do recurso
const languages = await resourceLanguagesService.getLanguagesByResource(id);
const educationalStage = await resourceEducationalStagesService.getEducationalStagesByResource(id);
const educational_stages = await resourceEducationalStagesService.getEducationalStagesByResource(id);
const subjects = await resourceSubjectsService.getSubjectsByResource(id);
const stats = await serviceStats.findById(id);
const publisher = await userService.findById(resource.user_id)
return c.json({
...resourceWithObjectTypeName,
contentType: response.ContentType || "application/octet-stream", // Adicionando contentType ao JSON
languages,
educationalStage,
educational_stages,
subjects,
stats,
publisher,
});
} catch (e) {
......
import { deleteObject, getFile, putFile } from "@/services/s3.service";
import { zValidator } from "@hono/zod-validator";
import { Hono } from "hono";
import { z } from "zod";
import {
uploadResourceRoute,
......@@ -17,6 +15,8 @@ import {
getThumbnailCollectionRoute,
getAvatarRoute
} from "../documentation/s3Describers"
import { z } from "zod";
import { zValidator } from "@hono/zod-validator";
const resourceUploadSchema = z.object({
id_resource: z.string().min(1, 'id_resource é obrigatório'),
......@@ -41,9 +41,9 @@ export const s3Routes = new Hono()
.post('/upload/resource', uploadResourceRoute,
async (ctx) => {
const formData = await ctx.req.formData();
const fileBlob = formData.get('file');
const id_resource = formData.get('id_resource');
const content_type = formData.get('content_type');
const fileBlob = formData.get('file');
......@@ -63,7 +63,7 @@ export const s3Routes = new Hono()
}
try {
const result = await putFile(fileBlob, id_resource, content_type, "resource")
const result = await putFile(fileBlob, String(id_resource), String(content_type), "resource")
return ctx.json({
message: 'Arquivo enviado com sucesso!',
fileId:id_resource,
......@@ -83,11 +83,10 @@ export const s3Routes = new Hono()
// envio de fotos de thumbnail do recurso
.post('/upload/thumbnail/resource', uploadThumbnailResourceRoute, zValidator('json',resourceUploadSchema ),
async (ctx) => {
const { id_resource, content_type } = ctx.req.valid('json');
const formData = await ctx.req.formData();
const fileBlob = formData.get('file');
const id_resource = formData.get('id_resource');
const content_type = formData.get('content_type');
if (!fileBlob || !(fileBlob instanceof Blob)) {
......@@ -107,7 +106,7 @@ export const s3Routes = new Hono()
try {
const result = await putFile(fileBlob, id_resource, content_type, "thumbnail/resource")
const result = await putFile(fileBlob, String(id_resource), String(content_type), "thumbnail/resource")
return ctx.json({
message: 'Arquivo enviado com sucesso!',
fileId: id_resource, content_type,
......@@ -128,10 +127,12 @@ export const s3Routes = new Hono()
// envio de fotos de thumbnail da coleção
.post('/upload/thumbnail/collection', uploadThumbnailCollectionRoute, zValidator('json',collectionUploadSchema ),
async (ctx) => {
const { id_collection, content_type } = ctx.req.valid('json');
const formData = await ctx.req.formData();
const fileBlob = formData.get('file');
const id_collection = formData.get('id_collection');
const content_type = formData.get('content_type');
if (!fileBlob || !(fileBlob instanceof Blob)) {
......@@ -151,7 +152,7 @@ export const s3Routes = new Hono()
try {
const result = await putFile(fileBlob, id_collection, content_type, "thumbnail/collection")
const result = await putFile(fileBlob, String(id_collection), String(content_type), "thumbnail/collection")
return ctx.json({
message: 'Arquivo enviado com sucesso!',
fileId: id_collection,
......@@ -172,11 +173,10 @@ export const s3Routes = new Hono()
// envio de fotos de thumbnail da coleção
.post('/upload/avatar', uploadAvatarRoute, zValidator('json', userUploadSchema ),
async (ctx) => {
const { id_user, content_type } = ctx.req.valid('json');
const formData = await ctx.req.formData();
const fileBlob = formData.get('file');
const id_user = formData.get('id_user');
const content_type = formData.get('content_type');
if (!fileBlob || !(fileBlob instanceof Blob)) {
......@@ -194,9 +194,8 @@ export const s3Routes = new Hono()
}, 400);
}
try {
const result = await putFile(fileBlob, id_user, content_type, "avatar")
const result = await putFile(fileBlob, String(id_user), String(content_type), "avatar")
return ctx.json({
message: 'Arquivo enviado com sucesso!',
fileId: id_user,
......
......@@ -39,7 +39,6 @@ export class CommentsService {
//retorna os comentarios ativos de um recurso
async findCommentsByResource(id_resource: CommentsModel['resource_id']): Promise<CommentsModel[]> {
return this.repo.findCommentsByResource(id_resource)
}
......
......@@ -11,15 +11,15 @@ import { Inject, Service } from 'typedi'
import { z } from 'zod'
@Service()
export class UserService {
export class UserService {
@Inject()
private readonly repo: UserRepo
getUpdateTime(): string {
const deactivated_at = new Date()
deactivated_at.setHours(deactivated_at.getHours() + 1)
deactivated_at.setHours(deactivated_at.getHours() + 1)
return deactivated_at.toLocaleString('pt-br', {timeZone: 'America/Sao_Paulo'})
return deactivated_at.toLocaleString('pt-br', { timeZone: 'America/Sao_Paulo' })
}
async findMany(): Promise<UserModel[]> {
......@@ -33,14 +33,12 @@ export class UserService {
}
async findByEmail(
userEmail: UserModel['email']
): Promise<UserModel | null>{
userEmail: UserModel['email']
): Promise<UserModel | null> {
return await this.repo.findByEmail(userEmail)
}
async findById(
userId: UserModel['id']
): Promise<UserModel | null>{
async findById(userId: UserModel['id']): Promise<UserModel | null> {
return await this.repo.findById(userId)
}
......@@ -73,18 +71,18 @@ export class UserService {
}
async update(user: UserUpdate): Promise<UserModel> {
if(user.password)
if (user.password)
user.password = hashPassword(user.password)
return this.repo.update(user)
}
async delete(user: UserModel): Promise<UserModel> {
return this.repo.update(user)
}
async systemDelete(user: UserModel['id']): Promise<UserModel> {
return this.repo.delete(user)
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment