Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…7-12-t-node-react into perfilUser
  • Loading branch information
jwilliam96 committed Sep 14, 2024
2 parents 2e40f63 + 82e54c4 commit 5408307
Show file tree
Hide file tree
Showing 158 changed files with 7,003 additions and 2,852 deletions.
17 changes: 17 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## TICKET

- [INSERTAR NOMBRE LA ISSUE AQUI](INSERTAR DEL LINK TICKET AQUI)

## Descripción

Describe brevemente el cambio que has hecho.

## Evidencia:

### Happy Path

(Poner screenshots/video/gifs aquí)

### Unhappy Path

(Poner screenshots/video/gifs aquí)
32 changes: 32 additions & 0 deletions .github/workflows/deploy_backtend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Deploy Backend
on:
pull_request:
types: [closed]
paths:
- "backend/**"
- ".github/workflows/deploy-backend.yml"

jobs:
deploy-backend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: "20"

- name: Install Dependencies
run: |
rm package-lock.json
npm install
# Pasos para el deploy en Railway
- name: Install Railway
run: npm i -g @railway/cli

- name: Deploy
run: npm run deploy -w backend
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
30 changes: 30 additions & 0 deletions .github/workflows/deploy_frontend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Vercel Production Deployment
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
on:
push:
paths:
- "frontend/**"
jobs:
Deploy-Production:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: "18"

- name: Install Vercel CLI
run: npm install --global vercel@latest

- name: Install dependencies
run: npm install

- name: Deploy to Vercel
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} # Configura la variable de entorno
run: npm run deploy -w frontend
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
node_modules
mongoDataBase
mongo
mongoDataBase
.env
6 changes: 6 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
NODE_ENV=development
PORT=3000

DB_URI=mongodb://user:admin1@localhost:27018/

JWT_SECRET_KEY=a_secret_key_3434
6 changes: 6 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
/dist
/node_modules
/build
/mongo-data

# Customs
.http
compose.yml
pnpm-lock.yaml

# Logs
logs
Expand Down
13 changes: 11 additions & 2 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,38 @@
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
"test:e2e": "jest --config ./test/jest-e2e.json",
"deploy": "railway up --service ohmytrip-backend"
},
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.2.3",
"@nestjs/core": "^10.0.0",
"@nestjs/jwt": "^10.2.0",
"@nestjs/mapped-types": "*",
"@nestjs/mongoose": "^10.0.10",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/swagger": "^7.4.0",
"bcrypt": "^5.1.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"mongoose": "^8.5.4",
"passport-jwt": "^4.0.1",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1"
"rxjs": "^7.8.1",
"stopword": "^3.1.1"
},
"devDependencies": {
"@faker-js/faker": "^8.4.1",
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/bcrypt": "^5.0.2",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/passport-jwt": "^4.0.1",
"@types/supertest": "^6.0.0",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
Expand Down
12 changes: 12 additions & 0 deletions backend/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Oh My Trip</title>
</head>
<body>
<h2>Welcome to the OhMyTrip API!</h2>
<p>Here you will see the documentation soon.</p>
</body>
</html>
76 changes: 76 additions & 0 deletions backend/src/album/album.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {
Body,
Controller,
Delete,
Get,
Param,
Patch,
Post,
Query,
} from '@nestjs/common';

import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { Types } from 'mongoose';

import { GetUser } from '../auth/decorators';
import { type User } from '../user/entities/user.entity';
import { Auth } from '../auth/decorators/auth.decorator';
import { ObjectIdValidationPipe } from '../common/pipes/object-id-validation.pipe';
import { AlbumService } from './album.service';
import { CreateAlbumDto, UpdateAlbumDto } from './dto';

//! refactor in the future
type UserTemporalType = User & { _id: Types.ObjectId };

@ApiTags('Album')
@Controller('album')
export class AlbumController {
constructor(private readonly albumService: AlbumService) {}

@Get('search')
async searchAlbums(@Query('q') query: string) {
return await this.albumService.searchAlbums(query);
}

@Get('all')
async allAlbums() {
return await this.albumService.findAllAlbums();
}

@Get(':id')
async findOne(@Param('id', ObjectIdValidationPipe) id: string) {
return await this.albumService.findOneById(id);
}

@Get('user/:userId')
async findAll(@Param('userId', ObjectIdValidationPipe) userId: string) {
return await this.albumService.findAllByUserId(userId);
}

@ApiBearerAuth()
@Post()
@Auth()
async create(
@GetUser() user: UserTemporalType,
@Body() createAlbumDto: CreateAlbumDto,
) {
return await this.albumService.create(user._id, createAlbumDto);
}

@ApiBearerAuth()
@Patch(':id')
@Auth()
async update(
@Param('id', ObjectIdValidationPipe) id: string,
@Body() updateAlbumDto: UpdateAlbumDto,
) {
return await this.albumService.update(id, updateAlbumDto);
}

@ApiBearerAuth()
@Delete(':id')
@Auth()
async delete(@Param('id', ObjectIdValidationPipe) id: string) {
return await this.albumService.delete(id);
}
}
17 changes: 17 additions & 0 deletions backend/src/album/album.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Module } from '@nestjs/common';
import { AlbumService } from './album.service';
import { AlbumController } from './album.controller';
import { MongooseModule } from '@nestjs/mongoose';
import { Album, AlbumSchema } from './schemas/album.schema';
import { UserModule } from 'src/user/user.module';

@Module({
imports: [
MongooseModule.forFeature([{ name: Album.name, schema: AlbumSchema }]),
UserModule,
],
controllers: [AlbumController],
providers: [AlbumService],
exports: [AlbumService, MongooseModule],
})
export class AlbumModule { }
101 changes: 101 additions & 0 deletions backend/src/album/album.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';

import { Model, Types } from 'mongoose';
import * as sw from 'stopword';
import { CreateAlbumDto, UpdateAlbumDto } from './dto';
import { Album } from './schemas';
import { UserService } from '../user/user.service';

@Injectable()
export class AlbumService {
constructor(
@InjectModel(Album.name)
private readonly albumModel: Model<Album>,
private readonly userService: UserService,
) {}

async create(userId: Types.ObjectId, createAlbumDto: CreateAlbumDto) {
const createdAlbum = await this.albumModel.create({
...createAlbumDto,
userId: userId,
});

return createdAlbum;
}

async update(id: string, updateAlbumDto: UpdateAlbumDto) {
await this.findOneById(id);

const updatedAlbum = await this.albumModel.findByIdAndUpdate(
id,
updateAlbumDto,
{ new: true },
);

return updatedAlbum;
}

async delete(id: string) {
await this.findOneById(id);
await this.albumModel.findByIdAndDelete(id);
}

async findOneById(id: string) {
const foundAlbum = await this.albumModel.findById(id);

if (!foundAlbum) throw new NotFoundException(`Album with ${id} not found`);

return foundAlbum;
}

async findAllByUserId(userId: string) {
await this.userService.findOne(userId);

const userIdToObjectId = new Types.ObjectId(userId);

const foundAlbums = await this.albumModel
.find({ userId: userIdToObjectId })
.exec();

return foundAlbums;
}

async searchAlbums(query: string) {
const words = query.split(' ');
const significantWords = sw.removeStopwords(words, sw.es); // 'sw.es' is the Spanish stopword list
if (significantWords.length === 0) {
return []; // Return an empty array if no significant words are left
}
const regexes = significantWords.map((word) => new RegExp(word, 'i'));

const foundAlbums = await this.albumModel.find({
$or: [
{ title: { $in: regexes } },
{ description: { $in: regexes } },
{ tags: { $in: regexes } },
],
});
return foundAlbums;
}

async findOneByCommentId(commentId: Types.ObjectId) {
const albumFound = await this.albumModel.findOne({
comments: {
$elemMatch: { _id: commentId },
},
});

if (!albumFound)
throw new NotFoundException(
`Album with comment id ${commentId} not found`,
);

return albumFound;
}

async findAllAlbums() {
const foundAllAlbums = await this.albumModel.find();
return foundAllAlbums;
}
}
Loading

0 comments on commit 5408307

Please sign in to comment.