Merge branch 'dev' into UH-registroGuardaSeguridad
This commit is contained in:
commit
01c1512bf7
|
@ -100,16 +100,15 @@ export class AppController {
|
||||||
@Body('canton') canton: string,
|
@Body('canton') canton: string,
|
||||||
@Body('district') district: string,
|
@Body('district') district: string,
|
||||||
@Body('num_houses') num_houses: number,
|
@Body('num_houses') num_houses: number,
|
||||||
@Body('phone') phone: number,
|
@Body('phone') phone: string,
|
||||||
@Body('quote') quote: number,
|
|
||||||
@Body('status') status: string,
|
@Body('status') status: string,
|
||||||
@Body('date_entry') date_entry: Date,
|
@Body('date_entry') date_entry: Date,
|
||||||
@Body('houses') houses: [{}],
|
@Body('houses') houses: [],
|
||||||
|
|
||||||
) {
|
) {
|
||||||
return this.appService.createCommunity(name, province, canton,
|
return this.appService.createCommunity(name, province, canton,
|
||||||
district, num_houses, phone,
|
district, num_houses, phone,
|
||||||
quote, status, date_entry, houses);
|
status, date_entry, houses);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('community/allCommunities')
|
@Get('community/allCommunities')
|
||||||
|
@ -132,6 +131,14 @@ export class AppController {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Post('community/findCommunityAdmin')
|
||||||
|
findCommunityAdmin(
|
||||||
|
@Body('community_id') community_id: string,
|
||||||
|
) {
|
||||||
|
return this.appService.findCommunityAdmin(community_id);
|
||||||
|
}
|
||||||
|
|
||||||
// #==== API Common Areas
|
// #==== API Common Areas
|
||||||
@Post('commonArea/createCommonArea')
|
@Post('commonArea/createCommonArea')
|
||||||
createCommonArea(
|
createCommonArea(
|
||||||
|
@ -318,4 +325,38 @@ export class AppController {
|
||||||
) {
|
) {
|
||||||
return this.appService.findReport(paramReport);
|
return this.appService.findReport(paramReport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Post('email/sendMail')
|
||||||
|
senMail(
|
||||||
|
@Body('email') email: string,
|
||||||
|
) {
|
||||||
|
|
||||||
|
return this.appService.sendMail(email);
|
||||||
|
}
|
||||||
|
@Post('email/html')
|
||||||
|
html(
|
||||||
|
@Body('email') email: string,
|
||||||
|
@Body('name') name: string,
|
||||||
|
) {
|
||||||
|
|
||||||
|
return this.appService.html(email, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// #==== API Users
|
||||||
|
@Post('user/testSendMail')
|
||||||
|
testSendMail(
|
||||||
|
@Body('dni') dni: string,
|
||||||
|
@Body('name') name: string,
|
||||||
|
@Body('last_name') last_name: string,
|
||||||
|
@Body('email') email: string,
|
||||||
|
@Body('phone') phone: number,
|
||||||
|
@Body('password') password: string,
|
||||||
|
@Body('user_type') user_type: string,
|
||||||
|
@Body('status') status: string,
|
||||||
|
@Body('date_entry') date_entry: Date,
|
||||||
|
) {
|
||||||
|
return this.appService.testSendMail(dni, name, last_name, email, phone, password,
|
||||||
|
user_type, status, date_entry);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -56,6 +56,7 @@ export class AppService {
|
||||||
const payload = {
|
const payload = {
|
||||||
dni: dni, name: name, last_name: last_name, email: email, phone: phone,
|
dni: dni, name: name, last_name: last_name, email: email, phone: phone,
|
||||||
password: password, user_type: user_type, status: status, date_entry: date_entry, community_id
|
password: password, user_type: user_type, status: status, date_entry: date_entry, community_id
|
||||||
|
|
||||||
};
|
};
|
||||||
return this.clientUserApp
|
return this.clientUserApp
|
||||||
.send<string>(pattern, payload)
|
.send<string>(pattern, payload)
|
||||||
|
@ -125,15 +126,27 @@ export class AppService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//GET parameter from API
|
||||||
|
findCommunityAdmin(community_id: string) {
|
||||||
|
const pattern = { cmd: 'findCommunityAdmin' };
|
||||||
|
const payload = { community_id: community_id };
|
||||||
|
return this.clientCommunityApp
|
||||||
|
.send<string>(pattern, payload)
|
||||||
|
.pipe(
|
||||||
|
map((message: string) => ({ message })),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// ====================== COMMUNITIES ===============================
|
// ====================== COMMUNITIES ===============================
|
||||||
|
|
||||||
//POST parameter from API
|
//POST parameter from API
|
||||||
createCommunity(name: string, province: string, canton: string, district: string
|
createCommunity(name: string, province: string, canton: string, district: string
|
||||||
, num_houses: number, phone: number, quote: number, status: string, date_entry: Date, houses: [{}]) {
|
, num_houses: number, phone: string, status: string, date_entry: Date, houses: []) {
|
||||||
const pattern = { cmd: 'createCommunity' };
|
const pattern = { cmd: 'createCommunity' };
|
||||||
const payload = {
|
const payload = {
|
||||||
name: name, province: province, canton: canton, district: district, num_houses: num_houses,
|
name: name, province: province, canton: canton, district: district, num_houses: num_houses,
|
||||||
phone: phone, quote: quote, status: status, date_entry: date_entry, houses
|
phone: phone, status: status, date_entry: date_entry, houses: houses
|
||||||
};
|
};
|
||||||
return this.clientCommunityApp
|
return this.clientCommunityApp
|
||||||
.send<string>(pattern, payload)
|
.send<string>(pattern, payload)
|
||||||
|
@ -443,4 +456,25 @@ export class AppService {
|
||||||
map((message: string) => ({ message })),
|
map((message: string) => ({ message })),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sendMail(email: string) {
|
||||||
|
const pattern = { cmd: 'sendMail' };
|
||||||
|
const payload = { email: email};
|
||||||
|
return this.clientNotificationtApp
|
||||||
|
.send<string>(pattern, payload)
|
||||||
|
.pipe(
|
||||||
|
map((message: string) => ({ message })),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
html(email: string, name: string) {
|
||||||
|
const pattern = { cmd: 'html' };
|
||||||
|
const payload = { email: email, name: name};
|
||||||
|
return this.clientNotificationtApp
|
||||||
|
.send<string>(pattern, payload)
|
||||||
|
.pipe(
|
||||||
|
map((message: string) => ({ message })),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -3,13 +3,11 @@ import { AppModule } from './app.module';
|
||||||
const cors = require('cors');
|
const cors = require('cors');
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create(AppModule);
|
const app = await NestFactory.create(AppModule);
|
||||||
|
|
||||||
app.enableCors({
|
app.enableCors({
|
||||||
origin: 'http://localhost:3000',
|
origin: 'http://localhost:3000',
|
||||||
methods: 'GET, PUT, POST, DELETE',
|
methods: 'GET, PUT, POST, DELETE',
|
||||||
allowedHeaders: 'Content-Type, Authorization',
|
allowedHeaders: 'Content-Type, Authorization',
|
||||||
});
|
});
|
||||||
await app.listen(4000);
|
await app.listen(4000);
|
||||||
//app.use(cors(enableCors))
|
|
||||||
}
|
}
|
||||||
bootstrap();
|
bootstrap();
|
||||||
|
|
|
@ -29,6 +29,12 @@ export class CommunitiesController {
|
||||||
return this.communitiesService.findOneName(_id);
|
return this.communitiesService.findOneName(_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* @MessagePattern({cmd: 'findCommunityAdmin'})
|
||||||
|
findCommunityAdmin(@Payload() community: any) {
|
||||||
|
let _community = community['community_id'];
|
||||||
|
return this.communitiesService.findCommunityAdmin(_community, "2");
|
||||||
|
}*/
|
||||||
|
|
||||||
@MessagePattern({cmd: 'updateCommunity'})
|
@MessagePattern({cmd: 'updateCommunity'})
|
||||||
update(@Payload() community: CommunityDocument) {
|
update(@Payload() community: CommunityDocument) {
|
||||||
return this.communitiesService.update(community.id, community);
|
return this.communitiesService.update(community.id, community);
|
||||||
|
|
|
@ -2,12 +2,23 @@ import { Module } from '@nestjs/common';
|
||||||
import { CommunitiesService } from './communities.service';
|
import { CommunitiesService } from './communities.service';
|
||||||
import { CommunitiesController } from './communities.controller';
|
import { CommunitiesController } from './communities.controller';
|
||||||
import { MongooseModule } from '@nestjs/mongoose';
|
import { MongooseModule } from '@nestjs/mongoose';
|
||||||
|
import { ClientsModule, Transport } from "@nestjs/microservices";
|
||||||
|
|
||||||
import { Community, CommunitySchema } from '../schemas/community.schema';
|
import { Community, CommunitySchema } from '../schemas/community.schema';
|
||||||
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
ClientsModule.register([
|
||||||
|
{
|
||||||
|
name: "SERVICIO_USUARIOS",
|
||||||
|
transport: Transport.TCP,
|
||||||
|
options: {
|
||||||
|
host: "127.0.0.1",
|
||||||
|
port: 3001
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]),
|
||||||
MongooseModule.forFeature([{ name: Community.name, schema: CommunitySchema }]),
|
MongooseModule.forFeature([{ name: Community.name, schema: CommunitySchema }]),
|
||||||
],
|
],
|
||||||
controllers: [CommunitiesController],
|
controllers: [CommunitiesController],
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { Model } from 'mongoose';
|
import { Model } from 'mongoose';
|
||||||
import { Community, CommunityDocument } from 'src/schemas/community.schema';
|
import { Community, CommunityDocument } from 'src/schemas/community.schema';
|
||||||
import { InjectModel } from '@nestjs/mongoose';
|
import { InjectModel } from '@nestjs/mongoose';
|
||||||
|
import { RpcException, ClientProxy } from '@nestjs/microservices';
|
||||||
|
import { from, lastValueFrom, map, scan, mergeMap } from 'rxjs';
|
||||||
|
import { Admin } from 'src/schemas/admin.entity';
|
||||||
|
import { appendFileSync } from 'fs';
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CommunitiesService {
|
export class CommunitiesService {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@InjectModel(Community.name) private readonly communityModel: Model<CommunityDocument>,
|
@InjectModel(Community.name) private readonly communityModel: Model<CommunityDocument>,
|
||||||
|
@Inject('SERVICIO_USUARIOS') private readonly clientUserApp: ClientProxy,
|
||||||
|
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async create(community: CommunityDocument): Promise<Community> {
|
async create(community: CommunityDocument): Promise<Community> {
|
||||||
|
@ -15,10 +22,25 @@ export class CommunitiesService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(): Promise<Community[]> {
|
async findAll(): Promise<Community[]> {
|
||||||
return this.communityModel
|
|
||||||
|
return await this.communityModel
|
||||||
.find()
|
.find()
|
||||||
.setOptions({ sanitizeFilter: true })
|
.setOptions({ sanitizeFilter: true })
|
||||||
.exec();
|
.exec()
|
||||||
|
.then(async community => {
|
||||||
|
if (community) {
|
||||||
|
await Promise.all(community.map(async c => {
|
||||||
|
//buscar al usuario con el id de la comunidad anexado
|
||||||
|
let admin = await this.findCommunityAdmin(c["_id"], "2")
|
||||||
|
if (admin) {
|
||||||
|
c["id_admin"] = admin["_id"]
|
||||||
|
c["name_admin"] = admin["name"]
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
return community;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
findOne(id: string): Promise<Community> {
|
findOne(id: string): Promise<Community> {
|
||||||
|
@ -37,4 +59,19 @@ export class CommunitiesService {
|
||||||
async remove(id: string) {
|
async remove(id: string) {
|
||||||
return this.communityModel.findByIdAndRemove({ _id: id }).exec();
|
return this.communityModel.findByIdAndRemove({ _id: id }).exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findCommunityAdmin(community: string, user_type: string) {
|
||||||
|
const pattern = { cmd: 'findOneCommunityUser' }
|
||||||
|
const payload = { community_id: community, user_type: user_type }
|
||||||
|
|
||||||
|
let callback = await this.clientUserApp
|
||||||
|
.send<string>(pattern, payload)
|
||||||
|
.pipe(
|
||||||
|
map((response: string) => ({ response }))
|
||||||
|
)
|
||||||
|
|
||||||
|
const finalValue = await lastValueFrom(callback);
|
||||||
|
return finalValue['response'];
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
export interface Admin {
|
||||||
|
id_community: string;
|
||||||
|
user_type: string;
|
||||||
|
}
|
|
@ -7,6 +7,11 @@ export type CommunityDocument = Community & Document;
|
||||||
|
|
||||||
@Schema({ collection: 'communities' })
|
@Schema({ collection: 'communities' })
|
||||||
export class Community {
|
export class Community {
|
||||||
|
@Prop()
|
||||||
|
id_admin: string;
|
||||||
|
|
||||||
|
@Prop()
|
||||||
|
name_admin: string ;
|
||||||
|
|
||||||
@Prop()
|
@Prop()
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -24,10 +29,7 @@ export class Community {
|
||||||
num_houses: number;
|
num_houses: number;
|
||||||
|
|
||||||
@Prop()
|
@Prop()
|
||||||
phone: number;
|
phone: string;
|
||||||
|
|
||||||
@Prop()
|
|
||||||
quote: number;
|
|
||||||
|
|
||||||
@Prop()
|
@Prop()
|
||||||
status: string;
|
status: string;
|
||||||
|
@ -37,6 +39,7 @@ export class Community {
|
||||||
|
|
||||||
@Prop({ type: [HouseSchema] })
|
@Prop({ type: [HouseSchema] })
|
||||||
houses: Array<House>;
|
houses: Array<House>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose';
|
import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose';
|
||||||
|
import e from 'express';
|
||||||
import { Document } from 'mongoose';
|
import { Document } from 'mongoose';
|
||||||
|
import { empty } from 'rxjs';
|
||||||
import { Tenant, TenantSchema } from './tenant.schema';
|
import { Tenant, TenantSchema } from './tenant.schema';
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,12 +9,12 @@ import { Tenant, TenantSchema } from './tenant.schema';
|
||||||
@Schema()
|
@Schema()
|
||||||
export class House extends Document {
|
export class House extends Document {
|
||||||
@Prop({ default: " " })
|
@Prop({ default: " " })
|
||||||
number: string;
|
number_house: string;
|
||||||
|
|
||||||
@Prop({ default: " " })
|
@Prop({ default: "desocupada" })
|
||||||
description: string;
|
state: string;
|
||||||
|
|
||||||
@Prop({ type: TenantSchema, default: " " })
|
@Prop({ type: TenantSchema })
|
||||||
tenants: Tenant;
|
tenants: Tenant;
|
||||||
}
|
}
|
||||||
export const HouseSchema = SchemaFactory.createForClass(House);
|
export const HouseSchema = SchemaFactory.createForClass(House);
|
|
@ -4,7 +4,7 @@ import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose';
|
||||||
|
|
||||||
@Schema()
|
@Schema()
|
||||||
export class Tenant {
|
export class Tenant {
|
||||||
@Prop()
|
@Prop( {default: ''})
|
||||||
tenant_id: string;
|
tenant_id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
# mail
|
||||||
|
MAIL_HOST=smtp.gmail.com
|
||||||
|
MAIL_USER=mbonilla.guti@gmail.com
|
||||||
|
MAIL_PASSWORD=laofghlofgffmyry
|
||||||
|
MAIL_FROM=noreply@example.com
|
||||||
|
|
||||||
|
# optional
|
||||||
|
MAIL_TRANSPORT=smtp://${MAIL_USER}:${MAIL_PASSWORD}@${MAIL_HOST}
|
|
@ -1,5 +1,9 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/nest-cli",
|
"$schema": "https://json.schemastore.org/nest-cli",
|
||||||
"collection": "@nestjs/schematics",
|
"collection": "@nestjs/schematics",
|
||||||
"sourceRoot": "src"
|
"sourceRoot": "src",
|
||||||
|
"compilerOptions": {
|
||||||
|
"assets": ["mails/**/*"],
|
||||||
|
"watchAssets": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,12 +21,16 @@
|
||||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@nestjs-modules/mailer": "^1.7.1",
|
||||||
"@nestjs/common": "^8.0.0",
|
"@nestjs/common": "^8.0.0",
|
||||||
|
"@nestjs/config": "^2.2.0",
|
||||||
"@nestjs/core": "^8.0.0",
|
"@nestjs/core": "^8.0.0",
|
||||||
"@nestjs/mapped-types": "*",
|
"@nestjs/mapped-types": "*",
|
||||||
"@nestjs/microservices": "^8.4.7",
|
"@nestjs/microservices": "^8.4.7",
|
||||||
"@nestjs/platform-express": "^8.0.0",
|
"@nestjs/platform-express": "^8.0.0",
|
||||||
"@nestjs/swagger": "^5.2.1",
|
"@nestjs/swagger": "^5.2.1",
|
||||||
|
"handlebars": "^4.7.7",
|
||||||
|
"nodemailer": "^6.7.7",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rxjs": "^7.2.0",
|
"rxjs": "^7.2.0",
|
||||||
|
|
|
@ -1,11 +1,45 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { AppController } from './app.controller';
|
import { AppController } from './app.controller';
|
||||||
import { NotificationsModule } from './notifications/notifications.module';
|
import { MailerModule } from '@nestjs-modules/mailer';
|
||||||
import { ClientsModule, Transport } from "@nestjs/microservices";
|
import { ClientsModule, Transport } from "@nestjs/microservices";
|
||||||
|
import { AuthModule } from './auth/auth.module';
|
||||||
|
import { EmailController } from './email.controller';
|
||||||
|
import { join } from 'path';
|
||||||
|
import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter';
|
||||||
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
MailerModule.forRootAsync({
|
||||||
|
// imports: [ConfigModule], // import module if not enabled globally
|
||||||
|
useFactory: async (config: ConfigService) => ({
|
||||||
|
// transport: config.get("MAIL_TRANSPORT"),
|
||||||
|
// or
|
||||||
|
transport: {
|
||||||
|
host: config.get('MAIL_HOST'),
|
||||||
|
secure: false,
|
||||||
|
auth: {
|
||||||
|
user: config.get('MAIL_USER'),
|
||||||
|
pass: config.get('MAIL_PASSWORD'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaults: {
|
||||||
|
from: `"No Reply" <${config.get('MAIL_USER')}>`,
|
||||||
|
},
|
||||||
|
template: {
|
||||||
|
dir: join(__dirname, 'mails'),
|
||||||
|
adapter: new HandlebarsAdapter(),
|
||||||
|
options: {
|
||||||
|
strict: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
inject: [ConfigService],
|
||||||
|
}),
|
||||||
|
ConfigModule.forRoot({
|
||||||
|
isGlobal: true, // no need to import into other modules
|
||||||
|
}),
|
||||||
ClientsModule.register([
|
ClientsModule.register([
|
||||||
{
|
{
|
||||||
name: "SERVICIO_NOTIFICACIONES",
|
name: "SERVICIO_NOTIFICACIONES",
|
||||||
|
@ -16,8 +50,8 @@ import { ClientsModule, Transport } from "@nestjs/microservices";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]),
|
]),
|
||||||
NotificationsModule],
|
AuthModule],
|
||||||
controllers: [AppController],
|
controllers: [AppController, EmailController],
|
||||||
providers: [],
|
providers: [],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
//import { AuthController } from './auth.controller';
|
||||||
|
import { AuthService } from './auth.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
//controllers: [AuthController],
|
||||||
|
providers: [AuthService],
|
||||||
|
})
|
||||||
|
export class AuthModule {}
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { AuthService } from './auth.service';
|
||||||
|
|
||||||
|
describe('AuthService', () => {
|
||||||
|
let service: AuthService;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [AuthService],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<AuthService>(AuthService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(service).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { User } from './../user/user.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthService {
|
||||||
|
|
||||||
|
async signUp(user: User) {
|
||||||
|
const token = Math.floor(1000 + Math.random() * 9000).toString();
|
||||||
|
// create user in db
|
||||||
|
// ...
|
||||||
|
// send confirmation mail
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { Controller, Get, Query } from '@nestjs/common';
|
||||||
|
import { MessagePattern, Payload } from '@nestjs/microservices';
|
||||||
|
|
||||||
|
import { MailerService } from '@nestjs-modules/mailer';
|
||||||
|
import { User } from './user/user.entity';
|
||||||
|
|
||||||
|
@Controller()
|
||||||
|
export class EmailController {
|
||||||
|
constructor(private mailService: MailerService) { }
|
||||||
|
|
||||||
|
@MessagePattern({ cmd: 'sendMail' })
|
||||||
|
sendMail(@Payload() toEmail: string) {
|
||||||
|
|
||||||
|
var response = this.mailService.sendMail({
|
||||||
|
to: toEmail["email"],
|
||||||
|
from: "mbonilla.guti@gmail.com",
|
||||||
|
subject: 'Plain Text Email ✔',
|
||||||
|
text: 'Welcome NestJS Email Sending Tutorial',
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
@MessagePattern({ cmd: 'html' })
|
||||||
|
async postHTMLEmail(@Payload() user: any) {
|
||||||
|
const url = "http://localhost:3000/";
|
||||||
|
const image = "images/email.ong";
|
||||||
|
var response = await this.mailService.sendMail({
|
||||||
|
to: user["email"],
|
||||||
|
from: "mbonilla.guti@gmail.com",
|
||||||
|
subject: 'HTML Dynamic Template',
|
||||||
|
template: 'templateEmail',
|
||||||
|
context: {
|
||||||
|
name: user["name"],
|
||||||
|
url
|
||||||
|
},
|
||||||
|
attachments: [
|
||||||
|
{
|
||||||
|
filename: 'email.png',
|
||||||
|
path: __dirname +'/mails/images/email.png',
|
||||||
|
cid: 'logo' //my mistake was putting "cid:logo@cid" here!
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<p>Hey {{ name }},</p>
|
||||||
|
<p>Please click below to confirm your email</p>
|
||||||
|
<p>
|
||||||
|
<a href="{{ url }}">Confirm</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>If you did not request this email you can safely ignore it.</p>
|
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
|
@ -0,0 +1,452 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"
|
||||||
|
xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"> <!-- utf-8 works for most cases -->
|
||||||
|
<meta name="viewport" content="width=device-width"> <!-- Forcing initial-scale shouldn't be necessary -->
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- Use the latest (edge) version of IE rendering engine -->
|
||||||
|
<meta name="x-apple-disable-message-reformatting"> <!-- Disable auto-scale in iOS 10 Mail entirely -->
|
||||||
|
<title></title> <!-- The title tag shows in email notifications, like Android 4.4. -->
|
||||||
|
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- CSS Reset : BEGIN -->
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
margin: 0 auto !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
height: 100% !important;
|
||||||
|
width: 100% !important;
|
||||||
|
background: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What it does: Stops email clients resizing small text. */
|
||||||
|
* {
|
||||||
|
-ms-text-size-adjust: 100%;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What it does: Centers email on Android 4.4 */
|
||||||
|
div[style*="margin: 16px 0"] {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What it does: Stops Outlook from adding extra spacing to tables. */
|
||||||
|
table,
|
||||||
|
td {
|
||||||
|
mso-table-lspace: 0pt !important;
|
||||||
|
mso-table-rspace: 0pt !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What it does: Fixes webkit padding issue. */
|
||||||
|
table {
|
||||||
|
border-spacing: 0 !important;
|
||||||
|
border-collapse: collapse !important;
|
||||||
|
table-layout: fixed !important;
|
||||||
|
margin: 0 auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What it does: Uses a better rendering method when resizing images in IE. */
|
||||||
|
img {
|
||||||
|
-ms-interpolation-mode: bicubic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What it does: Prevents Windows 10 Mail from underlining links despite inline CSS. Styles for underlined links should be inline. */
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What it does: A work-around for email clients meddling in triggered links. */
|
||||||
|
*[x-apple-data-detectors],
|
||||||
|
/* iOS */
|
||||||
|
.unstyle-auto-detected-links *,
|
||||||
|
.aBn {
|
||||||
|
border-bottom: 0 !important;
|
||||||
|
cursor: default !important;
|
||||||
|
color: inherit !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
font-size: inherit !important;
|
||||||
|
font-family: inherit !important;
|
||||||
|
font-weight: inherit !important;
|
||||||
|
line-height: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What it does: Prevents Gmail from displaying a download button on large, non-linked images. */
|
||||||
|
.a6S {
|
||||||
|
display: none !important;
|
||||||
|
opacity: 0.01 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What it does: Prevents Gmail from changing the text color in conversation threads. */
|
||||||
|
.im {
|
||||||
|
color: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the above doesn't work, add a .g-img class to any image in question. */
|
||||||
|
img.g-img+div {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* What it does: Removes right gutter in Gmail iOS app: https://github.com/TedGoas/Cerberus/issues/89 */
|
||||||
|
/* Create one of these media queries for each additional viewport size you'd like to fix */
|
||||||
|
|
||||||
|
/* iPhone 4, 4S, 5, 5S, 5C, and 5SE */
|
||||||
|
@media only screen and (min-device-width: 320px) and (max-device-width: 374px) {
|
||||||
|
u~div .email-container {
|
||||||
|
min-width: 320px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* iPhone 6, 6S, 7, 8, and X */
|
||||||
|
@media only screen and (min-device-width: 375px) and (max-device-width: 413px) {
|
||||||
|
u~div .email-container {
|
||||||
|
min-width: 375px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* iPhone 6+, 7+, and 8+ */
|
||||||
|
@media only screen and (min-device-width: 414px) {
|
||||||
|
u~div .email-container {
|
||||||
|
min-width: 414px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- CSS Reset : END -->
|
||||||
|
|
||||||
|
<!-- Progressive Enhancements : BEGIN -->
|
||||||
|
<style>
|
||||||
|
.primary {
|
||||||
|
background: #30e3ca;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg_white {
|
||||||
|
background: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg_light {
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg_black {
|
||||||
|
background: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg_dark {
|
||||||
|
background: rgba(0, 0, 0, .8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-section {
|
||||||
|
padding: 2.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*BUTTON*/
|
||||||
|
.btn {
|
||||||
|
padding: 10px 15px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.btn-primary {
|
||||||
|
border-radius: 5px;
|
||||||
|
background: #30e3ca;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.btn-white {
|
||||||
|
border-radius: 5px;
|
||||||
|
background: #ffffff;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.btn-white-outline {
|
||||||
|
border-radius: 5px;
|
||||||
|
background: transparent;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.btn-black-outline {
|
||||||
|
border-radius: 0px;
|
||||||
|
background: transparent;
|
||||||
|
border: 2px solid #000;
|
||||||
|
color: #000;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
font-family: 'Lato', sans-serif;
|
||||||
|
color: #000000;
|
||||||
|
margin-top: 0;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Lato', sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.8;
|
||||||
|
color: rgba(0, 0, 0, .4);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #30e3ca;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {}
|
||||||
|
|
||||||
|
/*LOGO*/
|
||||||
|
|
||||||
|
.logo h1 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo h1 a {
|
||||||
|
color: #30e3ca;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 700;
|
||||||
|
font-family: 'Lato', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*HERO*/
|
||||||
|
.hero {
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero .text {
|
||||||
|
color: rgba(0, 0, 0, .3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero .text h2 {
|
||||||
|
color: #000;
|
||||||
|
font-size: 40px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero .text h3 {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero .text h2 span {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #30e3ca;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*HEADING SECTION*/
|
||||||
|
.heading-section {}
|
||||||
|
|
||||||
|
.heading-section h2 {
|
||||||
|
color: #000000;
|
||||||
|
font-size: 28px;
|
||||||
|
margin-top: 0;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-section .subheading {
|
||||||
|
margin-bottom: 20px !important;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 13px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
color: rgba(0, 0, 0, .4);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-section .subheading::after {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: -10px;
|
||||||
|
content: '';
|
||||||
|
width: 100%;
|
||||||
|
height: 2px;
|
||||||
|
background: #30e3ca;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-section-white {
|
||||||
|
color: rgba(255, 255, 255, .8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-section-white h2 {
|
||||||
|
font-family:
|
||||||
|
line-height: 1;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-section-white h2 {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heading-section-white .subheading {
|
||||||
|
margin-bottom: 0;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 13px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
color: rgba(255, 255, 255, .4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ul.social {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.social li {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*FOOTER*/
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
border-top: 1px solid rgba(0, 0, 0, .05);
|
||||||
|
color: rgba(0, 0, 0, .5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .heading {
|
||||||
|
color: #000;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer ul li {
|
||||||
|
list-style: none;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer ul li a {
|
||||||
|
color: rgba(0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (max-width: 500px) {}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body width="100%" style="margin: 0; padding: 0 !important; mso-line-height-rule: exactly; background-color: #f1f1f1;">
|
||||||
|
<center style="width: 100%; background-color: #f1f1f1;">
|
||||||
|
<div
|
||||||
|
style="display: none; font-size: 1px;max-height: 0px; max-width: 0px; opacity: 0; overflow: hidden; mso-hide: all; font-family: sans-serif;">
|
||||||
|
‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌
|
||||||
|
</div>
|
||||||
|
<div style="max-width: 600px; margin: 0 auto;" class="email-container">
|
||||||
|
<!-- BEGIN BODY -->
|
||||||
|
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
|
||||||
|
style="margin: auto;">
|
||||||
|
<tr>
|
||||||
|
<td valign="top" class="bg_white" style="padding: 1em 2.5em 0 2.5em;">
|
||||||
|
<table role="presentation" border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td class="logo" style="text-align: center;">
|
||||||
|
<h1><a href="#">e-Verify</a></h1>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr><!-- end tr -->
|
||||||
|
<tr>
|
||||||
|
<td valign="middle" class="hero bg_white" style="padding: 3em 0 2em 0;">
|
||||||
|
<img src="cid:logo" alt=""
|
||||||
|
style="width: 300px; max-width: 600px; height: auto; margin: auto; display: block;">
|
||||||
|
</td>
|
||||||
|
</tr><!-- end tr -->
|
||||||
|
<tr>
|
||||||
|
<td valign="middle" class="hero bg_white" style="padding: 2em 0 4em 0;">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="text" style="padding: 0 2.5em; text-align: center;">
|
||||||
|
<h2>Hi, {{ name }}</h2>
|
||||||
|
<h2>Please verify your email</h2>
|
||||||
|
<h3>Amazing deals, updates, interesting news right in your inbox</h3>
|
||||||
|
<p><a href="{{ url }}" class="btn btn-primary">Yes! Subscribe Me</a></p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr><!-- end tr -->
|
||||||
|
<!-- 1 Column Text + Button : END -->
|
||||||
|
</table>
|
||||||
|
<table align="center" role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%"
|
||||||
|
style="margin: auto;">
|
||||||
|
<tr>
|
||||||
|
<td valign="middle" class="bg_light footer email-section">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="33.333%" style="padding-top: 20px;">
|
||||||
|
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: left; padding-right: 10px;">
|
||||||
|
<h3 class="heading">About</h3>
|
||||||
|
<p>A small river named Duden flows by their place and supplies it with
|
||||||
|
the necessary regelialia.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="33.333%" style="padding-top: 20px;">
|
||||||
|
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: left; padding-left: 5px; padding-right: 5px;">
|
||||||
|
<h3 class="heading">Contact Info</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="text">203 Fake St. Mountain View, San Francisco,
|
||||||
|
California, USA</span></li>
|
||||||
|
<li><span class="text">+2 392 3929 210</span></a></li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="33.333%" style="padding-top: 20px;">
|
||||||
|
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: left; padding-left: 10px;">
|
||||||
|
<h3 class="heading">Useful Links</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#">Home</a></li>
|
||||||
|
<li><a href="#">About</a></li>
|
||||||
|
<li><a href="#">Services</a></li>
|
||||||
|
<li><a href="#">Work</a></li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr><!-- end: tr -->
|
||||||
|
<tr>
|
||||||
|
<td class="bg_light" style="text-align: center;">
|
||||||
|
<p>No longer want to receive these email? You can <a href="#"
|
||||||
|
style="color: rgba(0,0,0,.8);">Unsubscribe here</a></p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</center>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,4 @@
|
||||||
|
export interface User {
|
||||||
|
email: string;
|
||||||
|
name: string;
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
|
"name": "servicio-usuarios",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -22,6 +22,7 @@ export class UsersController {
|
||||||
return this.userService.create(user);
|
return this.userService.create(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@MessagePattern({ cmd: 'findAllUsers' })
|
@MessagePattern({ cmd: 'findAllUsers' })
|
||||||
findAll() {
|
findAll() {
|
||||||
return this.userService.findAll();
|
return this.userService.findAll();
|
||||||
|
@ -39,6 +40,7 @@ export class UsersController {
|
||||||
return this.userService.findGuardsCommunity(pcommunity_id);
|
return this.userService.findGuardsCommunity(pcommunity_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@MessagePattern({ cmd: 'updateUser' })
|
@MessagePattern({ cmd: 'updateUser' })
|
||||||
update(@Payload() user: UserDocument) {
|
update(@Payload() user: UserDocument) {
|
||||||
return this.userService.update(user.id, user);
|
return this.userService.update(user.id, user);
|
||||||
|
@ -69,4 +71,19 @@ export class UsersController {
|
||||||
allUsersAdminComunidad() {
|
allUsersAdminComunidad() {
|
||||||
return this.userService.allUsersAdminComunidad();
|
return this.userService.allUsersAdminComunidad();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Prueba de envio de correo despues de registro, llamando a microservicio notificaciones
|
||||||
|
@MessagePattern({ cmd: 'testSendMail' })
|
||||||
|
testSendMail(@Payload() user: UserDocument) {
|
||||||
|
return this.userService.testSendMail(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//buscar usuario de una comunidad
|
||||||
|
@MessagePattern({ cmd: 'findOneCommunityUser' })
|
||||||
|
findCommunityUser(@Payload() user: any) {
|
||||||
|
return this.userService.findCommunityUser(user["community_id"], user["user_type"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,20 @@ import { MongooseModule } from '@nestjs/mongoose';
|
||||||
|
|
||||||
import { UsersController } from './users.controller';
|
import { UsersController } from './users.controller';
|
||||||
import { User, UserSchema } from '../schemas/user.schema';
|
import { User, UserSchema } from '../schemas/user.schema';
|
||||||
|
import { ClientsModule, Transport } from "@nestjs/microservices";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
|
ClientsModule.register([
|
||||||
|
{
|
||||||
|
name: "SERVICIO_NOTIFICACIONES",
|
||||||
|
transport: Transport.TCP,
|
||||||
|
options: {
|
||||||
|
host: "127.0.0.1",
|
||||||
|
port: 3009
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]),
|
||||||
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
|
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
|
||||||
],
|
],
|
||||||
controllers: [UsersController],
|
controllers: [UsersController],
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable, Inject } from '@nestjs/common';
|
||||||
import { Model } from 'mongoose';
|
import { Model } from 'mongoose';
|
||||||
import { User, UserDocument } from '../schemas/user.schema';
|
import { User, UserDocument } from '../schemas/user.schema';
|
||||||
import { InjectModel } from '@nestjs/mongoose';
|
import { InjectModel } from '@nestjs/mongoose';
|
||||||
import { Md5 } from "md5-typescript";
|
import { Md5 } from "md5-typescript";
|
||||||
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { RpcException, ClientProxy } from '@nestjs/microservices';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UsersService {
|
export class UsersService {
|
||||||
constructor(
|
constructor(
|
||||||
@InjectModel(User.name) private readonly userModel: Model<UserDocument>,
|
@InjectModel(User.name) private readonly userModel: Model<UserDocument>,
|
||||||
|
@Inject('SERVICIO_NOTIFICACIONES') private readonly clientNotificationtApp: ClientProxy,
|
||||||
|
|
||||||
) { }
|
) { }
|
||||||
private publicKey: string;
|
private publicKey: string;
|
||||||
async create(user: UserDocument): Promise<User> {
|
async create(user: UserDocument): Promise<User> {
|
||||||
|
@ -70,6 +77,7 @@ export class UsersService {
|
||||||
return this.userModel.find({ user_type: 1 }).exec();
|
return this.userModel.find({ user_type: 1 }).exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//find admin del sistema
|
//find admin del sistema
|
||||||
async findGuardsCommunity(pcommunity_id: string): Promise<User[]> {
|
async findGuardsCommunity(pcommunity_id: string): Promise<User[]> {
|
||||||
return this.userModel.find({ user_type: 4 }).exec();
|
return this.userModel.find({ user_type: 4 }).exec();
|
||||||
|
@ -79,5 +87,33 @@ export class UsersService {
|
||||||
return this.userModel.find({ user_type: 2 }).exec();
|
return this.userModel.find({ user_type: 2 }).exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//find admin de comunidad
|
||||||
|
async allUsersAdminComunidad(): Promise<User[]> {
|
||||||
|
return this.userModel.find({ user_type: 2 }).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
async testSendMail(user: UserDocument) {
|
||||||
|
let passwordEncriptada = Md5.init(user.password);
|
||||||
|
user.password = passwordEncriptada;
|
||||||
|
this.userModel.create(user)
|
||||||
|
/*.then(() => {
|
||||||
|
|
||||||
|
} );*/
|
||||||
|
|
||||||
|
const pattern = { cmd: 'html' };
|
||||||
|
const payload = { email: user['email'], name: user['name'] };
|
||||||
|
return this.clientNotificationtApp
|
||||||
|
.send<string>(pattern, payload)
|
||||||
|
.pipe(
|
||||||
|
map((message: string) => ({ message })),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async findCommunityUser(community_id: string, user_type: number): Promise<User> {
|
||||||
|
return this.userModel.findOne({ community_id: community_id, user_type: user_type }).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,489 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "San José",
|
||||||
|
"code": "101",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Escazú",
|
||||||
|
"code": "102",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Desamparados",
|
||||||
|
"code": "103",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Puriscal",
|
||||||
|
"code": "104",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tarrazú",
|
||||||
|
"code": "105",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Aserrí",
|
||||||
|
"code": "106",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mora",
|
||||||
|
"code": "107",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Goicoechea",
|
||||||
|
"code": "108",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Santa Ana",
|
||||||
|
"code": "109",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Alajuelita",
|
||||||
|
"code": "110",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Vasquez de Coronado",
|
||||||
|
"code": "111",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Acosta",
|
||||||
|
"code": "112",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tibás",
|
||||||
|
"code": "113",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Moravia",
|
||||||
|
"code": "114",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Montes de Oca",
|
||||||
|
"code": "115",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Turrubares",
|
||||||
|
"code": "116",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dota",
|
||||||
|
"code": "117",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Curridabat",
|
||||||
|
"code": "118",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pérez Zeledón",
|
||||||
|
"code": "119",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "León Cortés",
|
||||||
|
"code": "120",
|
||||||
|
"parentCode": "1",
|
||||||
|
"isoParent": "SJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Alajuela",
|
||||||
|
"code": "201",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "San Ramón",
|
||||||
|
"code": "202",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Grecia",
|
||||||
|
"code": "203",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "San Mateo",
|
||||||
|
"code": "204",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Atenas",
|
||||||
|
"code": "205",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Naranjo",
|
||||||
|
"code": "206",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Palmares",
|
||||||
|
"code": "207",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Poás",
|
||||||
|
"code": "208",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Orotina",
|
||||||
|
"code": "209",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "San Carlos",
|
||||||
|
"code": "210",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Alfaro Ruiz",
|
||||||
|
"code": "211",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Valverde Vega",
|
||||||
|
"code": "212",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Upala",
|
||||||
|
"code": "213",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Los Chiles",
|
||||||
|
"code": "214",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Guatuso",
|
||||||
|
"code": "215",
|
||||||
|
"parentCode": "2",
|
||||||
|
"isoParent": "ALAJ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cartago",
|
||||||
|
"code": "301",
|
||||||
|
"parentCode": "3",
|
||||||
|
"isoParent": "CAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Paraíso",
|
||||||
|
"code": "302",
|
||||||
|
"parentCode": "3",
|
||||||
|
"isoParent": "CAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "La Unión",
|
||||||
|
"code": "303",
|
||||||
|
"parentCode": "3",
|
||||||
|
"isoParent": "CAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jiménez",
|
||||||
|
"code": "304",
|
||||||
|
"parentCode": "3",
|
||||||
|
"isoParent": "CAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Turrialba",
|
||||||
|
"code": "305",
|
||||||
|
"parentCode": "3",
|
||||||
|
"isoParent": "CAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Alvarado",
|
||||||
|
"code": "306",
|
||||||
|
"parentCode": "3",
|
||||||
|
"isoParent": "CAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Oreamuno",
|
||||||
|
"code": "307",
|
||||||
|
"parentCode": "3",
|
||||||
|
"isoParent": "CAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "El Guarco",
|
||||||
|
"code": "308",
|
||||||
|
"parentCode": "3",
|
||||||
|
"isoParent": "CAR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Heredia",
|
||||||
|
"code": "401",
|
||||||
|
"parentCode": "4",
|
||||||
|
"isoParent": "HER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Barva",
|
||||||
|
"code": "402",
|
||||||
|
"parentCode": "4",
|
||||||
|
"isoParent": "HER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Santo Domingo",
|
||||||
|
"code": "403",
|
||||||
|
"parentCode": "4",
|
||||||
|
"isoParent": "HER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Santa Bárbara",
|
||||||
|
"code": "404",
|
||||||
|
"parentCode": "4",
|
||||||
|
"isoParent": "HER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "San Rafael",
|
||||||
|
"code": "405",
|
||||||
|
"parentCode": "4",
|
||||||
|
"isoParent": "HER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "San Isidro",
|
||||||
|
"code": "406",
|
||||||
|
"parentCode": "4",
|
||||||
|
"isoParent": "HER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Belén",
|
||||||
|
"code": "407",
|
||||||
|
"parentCode": "4",
|
||||||
|
"isoParent": "HER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Flores",
|
||||||
|
"code": "408",
|
||||||
|
"parentCode": "4",
|
||||||
|
"isoParent": "HER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "San Pablo",
|
||||||
|
"code": "409",
|
||||||
|
"parentCode": "4",
|
||||||
|
"isoParent": "HER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sarapiquí ",
|
||||||
|
"code": "410",
|
||||||
|
"parentCode": "4",
|
||||||
|
"isoParent": "HER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Liberia",
|
||||||
|
"code": "501",
|
||||||
|
"parentCode": "5",
|
||||||
|
"isoParent": "GUANA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nicoya",
|
||||||
|
"code": "502",
|
||||||
|
"parentCode": "5",
|
||||||
|
"isoParent": "GUANA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Santa Cruz",
|
||||||
|
"code": "503",
|
||||||
|
"parentCode": "5",
|
||||||
|
"isoParent": "GUANA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bagaces",
|
||||||
|
"code": "504",
|
||||||
|
"parentCode": "5",
|
||||||
|
"isoParent": "GUANA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Carrillo",
|
||||||
|
"code": "505",
|
||||||
|
"parentCode": "5",
|
||||||
|
"isoParent": "GUANA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cañas",
|
||||||
|
"code": "506",
|
||||||
|
"parentCode": "5",
|
||||||
|
"isoParent": "GUANA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Abangares",
|
||||||
|
"code": "507",
|
||||||
|
"parentCode": "5",
|
||||||
|
"isoParent": "GUANA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tilarán",
|
||||||
|
"code": "508",
|
||||||
|
"parentCode": "5",
|
||||||
|
"isoParent": "GUANA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nandayure",
|
||||||
|
"code": "509",
|
||||||
|
"parentCode": "5",
|
||||||
|
"isoParent": "GUANA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "La Cruz",
|
||||||
|
"code": "510",
|
||||||
|
"parentCode": "5",
|
||||||
|
"isoParent": "GUANA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hojancha",
|
||||||
|
"code": "511",
|
||||||
|
"parentCode": "5",
|
||||||
|
"isoParent": "GUANA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Puntarenas",
|
||||||
|
"code": "601",
|
||||||
|
"parentCode": "6",
|
||||||
|
"isoParent": "PUNT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Esparza",
|
||||||
|
"code": "602",
|
||||||
|
"parentCode": "6",
|
||||||
|
"isoParent": "PUNT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Buenos Aires",
|
||||||
|
"code": "603",
|
||||||
|
"parentCode": "6",
|
||||||
|
"isoParent": "PUNT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Montes de Oro",
|
||||||
|
"code": "604",
|
||||||
|
"parentCode": "6",
|
||||||
|
"isoParent": "PUNT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Osa",
|
||||||
|
"code": "605",
|
||||||
|
"parentCode": "6",
|
||||||
|
"isoParent": "PUNT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Aguirre",
|
||||||
|
"code": "606",
|
||||||
|
"parentCode": "6",
|
||||||
|
"isoParent": "PUNT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Golfito",
|
||||||
|
"code": "607",
|
||||||
|
"parentCode": "6",
|
||||||
|
"isoParent": "PUNT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Coto Brus",
|
||||||
|
"code": "608",
|
||||||
|
"parentCode": "6",
|
||||||
|
"isoParent": "PUNT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Parrita",
|
||||||
|
"code": "609",
|
||||||
|
"parentCode": "6",
|
||||||
|
"isoParent": "PUNT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Corredores",
|
||||||
|
"code": "610",
|
||||||
|
"parentCode": "6",
|
||||||
|
"isoParent": "PUNT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Garabito",
|
||||||
|
"code": "611",
|
||||||
|
"parentCode": "6",
|
||||||
|
"isoParent": "PUNT"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Limón",
|
||||||
|
"code": "701",
|
||||||
|
"parentCode": "7",
|
||||||
|
"isoParent": "LIM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pococí",
|
||||||
|
"code": "702",
|
||||||
|
"parentCode": "7",
|
||||||
|
"isoParent": "LIM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Siquirres ",
|
||||||
|
"code": "703",
|
||||||
|
"parentCode": "7",
|
||||||
|
"isoParent": "LIM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Talamanca",
|
||||||
|
"code": "704",
|
||||||
|
"parentCode": "7",
|
||||||
|
"isoParent": "LIM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Matina",
|
||||||
|
"code": "705",
|
||||||
|
"parentCode": "7",
|
||||||
|
"isoParent": "LIM"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Guácimo",
|
||||||
|
"code": "706",
|
||||||
|
"parentCode": "7",
|
||||||
|
"isoParent": "LIM"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,30 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name":"San José",
|
||||||
|
"code":"1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Alajuela",
|
||||||
|
"code":"2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Cartago",
|
||||||
|
"code":"3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Heredia",
|
||||||
|
"code":"4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Guanacaste",
|
||||||
|
"code":"5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Puntarenas",
|
||||||
|
"code":"6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Limón",
|
||||||
|
"code":"7"
|
||||||
|
}
|
||||||
|
]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -2,14 +2,14 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<title>PrimeReact - Sakai</title>
|
<title>Katoikia</title>
|
||||||
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<link rel="icon" type="image/x-icon" href="%PUBLIC_URL%/favicon.ico" />
|
<link rel="icon" type="image/x-icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
<link id="theme-link" rel="stylesheet" href="%PUBLIC_URL%/assets/themes/lara-light-indigo/theme.css">
|
<link id="theme-link" rel="stylesheet" href="%PUBLIC_URL%/assets/themes/khaki/theme.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -31,6 +31,7 @@ import IconsDemo from './templates/IconsDemo';
|
||||||
import AdministradoresSistema from './components/AdministradoresSistema';
|
import AdministradoresSistema from './components/AdministradoresSistema';
|
||||||
import AdministradoresComunidad from './components/AdministradoresComunidad';
|
import AdministradoresComunidad from './components/AdministradoresComunidad';
|
||||||
import GuardasSeguridad from './components/GuardasSeguridad';
|
import GuardasSeguridad from './components/GuardasSeguridad';
|
||||||
|
import Communities from './components/ComunidadViviendas';
|
||||||
|
|
||||||
import Crud from './pages/Crud';
|
import Crud from './pages/Crud';
|
||||||
import EmptyPage from './pages/EmptyPage';
|
import EmptyPage from './pages/EmptyPage';
|
||||||
|
@ -167,6 +168,7 @@ const App = () => {
|
||||||
{label: 'Administradores del sistema', icon: 'pi pi-fw pi-id-card', to: '/administradoresSistema'},
|
{label: 'Administradores del sistema', icon: 'pi pi-fw pi-id-card', to: '/administradoresSistema'},
|
||||||
{label: 'Administradores de comunidad', icon: 'pi pi-fw pi-id-card', to: '/administradoresComunidad'},
|
{label: 'Administradores de comunidad', icon: 'pi pi-fw pi-id-card', to: '/administradoresComunidad'},
|
||||||
{label: 'Guardas de seguridad', icon: 'pi pi-fw pi-id-card', to: '/guardasSeguridad'},
|
{label: 'Guardas de seguridad', icon: 'pi pi-fw pi-id-card', to: '/guardasSeguridad'},
|
||||||
|
{label: 'Comunidadades', icon: 'pi pi-fw pi-id-card', to: '/comunidadesViviendas'},
|
||||||
{label: 'Log in', icon: 'pi pi-fw pi-id-card', to: '/logIn'}
|
{label: 'Log in', icon: 'pi pi-fw pi-id-card', to: '/logIn'}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -323,6 +325,7 @@ const App = () => {
|
||||||
<Route path="/administradoresSistema" component={AdministradoresSistema} />
|
<Route path="/administradoresSistema" component={AdministradoresSistema} />
|
||||||
<Route path="/administradoresComunidad" component={AdministradoresComunidad} />
|
<Route path="/administradoresComunidad" component={AdministradoresComunidad} />
|
||||||
<Route path="/guardasSeguridad" component={GuardasSeguridad} />
|
<Route path="/guardasSeguridad" component={GuardasSeguridad} />
|
||||||
|
<Route path="/comunidadesViviendas" component={Communities} />
|
||||||
<Route path="/logIn" component={LogIn} />
|
<Route path="/logIn" component={LogIn} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ export const AppConfig = (props) => {
|
||||||
const [active, setActive] = useState(false);
|
const [active, setActive] = useState(false);
|
||||||
const [scale, setScale] = useState(14);
|
const [scale, setScale] = useState(14);
|
||||||
const [scales] = useState([12, 13, 14, 15, 16]);
|
const [scales] = useState([12, 13, 14, 15, 16]);
|
||||||
const [theme, setTheme] = useState('lara-light-indigo');
|
const [theme, setTheme] = useState('khaki');
|
||||||
const config = useRef(null);
|
const config = useRef(null);
|
||||||
let outsideClickListener = useRef(null);
|
let outsideClickListener = useRef(null);
|
||||||
|
|
||||||
|
@ -187,6 +187,11 @@ export const AppConfig = (props) => {
|
||||||
|
|
||||||
<h6>Material Design</h6>
|
<h6>Material Design</h6>
|
||||||
<div className="grid free-themes">
|
<div className="grid free-themes">
|
||||||
|
<div className="col-3 text-center">
|
||||||
|
<button className="p-link" onClick={e => changeTheme(e, 'md-light-indigo', 'light')}>
|
||||||
|
<img src="assets/layout/images/themes/md-light-indigo.svg" alt="Material Light Indigo" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div className="col-3 text-center">
|
<div className="col-3 text-center">
|
||||||
<button className="p-link" onClick={e => changeTheme(e, 'md-light-indigo', 'light')}>
|
<button className="p-link" onClick={e => changeTheme(e, 'md-light-indigo', 'light')}>
|
||||||
<img src="assets/layout/images/themes/md-light-indigo.svg" alt="Material Light Indigo" />
|
<img src="assets/layout/images/themes/md-light-indigo.svg" alt="Material Light Indigo" />
|
||||||
|
@ -253,6 +258,11 @@ export const AppConfig = (props) => {
|
||||||
|
|
||||||
<h6>PrimeOne Design - 2022</h6>
|
<h6>PrimeOne Design - 2022</h6>
|
||||||
<div className="grid free-themes">
|
<div className="grid free-themes">
|
||||||
|
<div className="col-3 text-center">
|
||||||
|
<button className="p-link" onClick={(e) => changeTheme(e, 'khaki', 'light')}>
|
||||||
|
<img src="assets/layout/images/themes/lara-light-indigo.png" alt="Khaki" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div className="col-3 text-center">
|
<div className="col-3 text-center">
|
||||||
<button className="p-link" onClick={(e) => changeTheme(e, 'lara-light-indigo', 'light')}>
|
<button className="p-link" onClick={(e) => changeTheme(e, 'lara-light-indigo', 'light')}>
|
||||||
<img src="assets/layout/images/themes/lara-light-indigo.png" alt="Lara Light Indigo" />
|
<img src="assets/layout/images/themes/lara-light-indigo.png" alt="Lara Light Indigo" />
|
||||||
|
|
|
@ -0,0 +1,346 @@
|
||||||
|
import React, { useEffect, useState, useRef } from 'react';
|
||||||
|
import { InputText } from 'primereact/inputtext';
|
||||||
|
import { Button } from 'primereact/button';
|
||||||
|
import { DataTable } from 'primereact/datatable';
|
||||||
|
import { Column } from 'primereact/column';
|
||||||
|
import { Dropdown } from 'primereact/dropdown';
|
||||||
|
import { Toast } from 'primereact/toast';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
|
||||||
|
const Communities = () => {
|
||||||
|
|
||||||
|
let emptyCommunity = {
|
||||||
|
name: '',
|
||||||
|
province: provinciaId,
|
||||||
|
canton: cantonId,
|
||||||
|
district: districtId,
|
||||||
|
phone: '',
|
||||||
|
num_houses: 0,
|
||||||
|
status: 'activo',
|
||||||
|
date_entry: new Date(),
|
||||||
|
houses: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const [communitiesList, setCommunitiesList] = useState([]);
|
||||||
|
const [community, setCommunity] = useState(emptyCommunity);
|
||||||
|
|
||||||
|
const [housesList, setHousesList] = useState([]);
|
||||||
|
const [provincesList, setProvincesList] = useState([]);
|
||||||
|
const [provinciaId, setProvinciaId] = useState(null);
|
||||||
|
const [cantonsList, setCantonsList] = useState([]);
|
||||||
|
const [cantonId, setCantonId] = useState(null);
|
||||||
|
const [districtsList, setDistrictsList] = useState([]);
|
||||||
|
const [districtId, setDistrictId] = useState(null);
|
||||||
|
const [codeHouses, setCodeHouses] = useState(null);
|
||||||
|
const [submitted, setSubmitted] = useState(false);
|
||||||
|
const toast = useRef(null);
|
||||||
|
const dt = useRef(null);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const p = provincesList.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.code
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
const c = cantonsList.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.code,
|
||||||
|
parent: item.parentCode
|
||||||
|
}))
|
||||||
|
|
||||||
|
const d = districtsList.map((item) => ({
|
||||||
|
label: item.name,
|
||||||
|
value: item.code,
|
||||||
|
parent: item.parentCode
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fillProvinces();
|
||||||
|
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fillCantons();
|
||||||
|
}, [provinciaId])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fillDistricts();
|
||||||
|
}, [cantonId])
|
||||||
|
|
||||||
|
async function getProvinces() {
|
||||||
|
const response = await fetch('assets/demo/data/provincias.json', { method: 'GET' });
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fillProvinces() {
|
||||||
|
const getP = await getProvinces();
|
||||||
|
setProvincesList(await getP);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCantons() {
|
||||||
|
const response = await fetch('assets/demo/data/cantones.json', { method: 'GET' });
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fillCantons() {
|
||||||
|
const resJson = await getCantons();
|
||||||
|
const cantones = await resJson.filter(function (i, n) {
|
||||||
|
return i.parentCode === provinciaId;
|
||||||
|
});
|
||||||
|
setCantonsList(await cantones);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDistricts() {
|
||||||
|
const response = await fetch('assets/demo/data/distritos.json', { method: 'GET' });
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fillDistricts() {
|
||||||
|
const resJson = await getDistricts();
|
||||||
|
const districts = await resJson.filter(function (i, n) {
|
||||||
|
return i.parentCode === cantonId;
|
||||||
|
});
|
||||||
|
setDistrictsList(await districts);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleProvinces = (event) => {
|
||||||
|
const getprovinciaId = event.target.value;
|
||||||
|
setProvinciaId(getprovinciaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCanton = (event) => {
|
||||||
|
const getCantonId = event.target.value;
|
||||||
|
setCantonId(getCantonId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDistrict = (event) => {
|
||||||
|
const getDistrictId = event.target.value;
|
||||||
|
setDistrictId(getDistrictId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handleCodeHouses = (event) => {
|
||||||
|
const getcodehouse = event.target.value;
|
||||||
|
setCodeHouses(getcodehouse);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCommunites() {
|
||||||
|
let response = await fetch('http://localhost:4000/community/allCommunities', { method: 'GET' });
|
||||||
|
let resJson = await response.json();
|
||||||
|
let pList = await getProvinces();
|
||||||
|
let cList = await getCantons();
|
||||||
|
let dList = await getDistricts();
|
||||||
|
await resJson.message.map((item) => {
|
||||||
|
item.province = pList.find(p => p.code === item.province).name
|
||||||
|
item.canton = cList.find(p => p.code === item.canton).name
|
||||||
|
item.district = dList.find(p => p.code === item.district).name
|
||||||
|
})
|
||||||
|
setCommunitiesList(await resJson.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getCommunites();
|
||||||
|
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
const saveCommunity = () => {
|
||||||
|
setSubmitted(true);
|
||||||
|
|
||||||
|
|
||||||
|
if (community.name.trim()) {
|
||||||
|
let _communities = [...communitiesList];
|
||||||
|
let _community = { ...community };
|
||||||
|
_community.province = provinciaId;
|
||||||
|
_community.canton = cantonId;
|
||||||
|
_community.district = districtId;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (let i = 0; i < _community.num_houses; i++){
|
||||||
|
_community.houses.push({
|
||||||
|
number_house: codeHouses + (i+1),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// console.log(houses)
|
||||||
|
fetch('http://localhost:4000/community/createCommunity', {
|
||||||
|
cache: 'no-cache',
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(_community),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(
|
||||||
|
function (response) {
|
||||||
|
if (response.status != 201)
|
||||||
|
console.log('Ocurrió un error con el servicio: ' + response.status);
|
||||||
|
else
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
|
||||||
|
_community.province = provincesList.find(p => p.code === _community.province).name
|
||||||
|
_community.canton = cantonsList.find(p => p.code === _community.canton).name
|
||||||
|
_community.district = districtsList.find(p => p.code === _community.district).name
|
||||||
|
|
||||||
|
_communities.push(_community);
|
||||||
|
toast.current.show({ severity: 'success', summary: 'Registro exitoso', detail: 'Comunidad de vivienda Creada', life: 3000 });
|
||||||
|
|
||||||
|
setCommunitiesList(_communities);
|
||||||
|
|
||||||
|
|
||||||
|
setProvinciaId('');
|
||||||
|
setCantonId('');
|
||||||
|
setDistrictId('');
|
||||||
|
setCodeHouses('');
|
||||||
|
|
||||||
|
setCommunity(emptyCommunity);
|
||||||
|
})
|
||||||
|
.catch(
|
||||||
|
err => console.log('Ocurrió un error con el fetch', err)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const onInputChange = (e, name) => {
|
||||||
|
const val = (e.target && e.target.value) || '';
|
||||||
|
let _community = { ...community };
|
||||||
|
_community[`${name}`] = val;
|
||||||
|
|
||||||
|
setCommunity(_community);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="grid">
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="card">
|
||||||
|
<h5>Comunidades de Viviendas</h5>
|
||||||
|
|
||||||
|
<DataTable value={communitiesList} scrollable scrollHeight="400px" scrollDirection="both" className="mt-3">
|
||||||
|
<Column field="name" header="Nombre" style={{ flexGrow: 1, flexBasis: '160px' }}></Column>
|
||||||
|
<Column field="province" header="Provincia" style={{ flexGrow: 1, flexBasis: '160px' }}></Column>
|
||||||
|
<Column field="canton" header="Cantón" style={{ flexGrow: 1, flexBasis: '160px' }}></Column>
|
||||||
|
<Column field="district" header="Distrito" style={{ flexGrow: 1, flexBasis: '160px' }}></Column>
|
||||||
|
<Column field="phone" header="Telefóno" style={{ flexGrow: 1, flexBasis: '180px' }}></Column>
|
||||||
|
<Column field="num_houses" header="Número de viviendas" style={{ flexGrow: 1, flexBasis: '180px' }}></Column>
|
||||||
|
<Column field="name_admin" header="Administrador" style={{ flexGrow: 1, flexBasis: '180px' }}></Column>
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="card">
|
||||||
|
<Toast ref={toast} />
|
||||||
|
|
||||||
|
<h5>Registro de comunidad de viviendas</h5>
|
||||||
|
<div className="p-fluid formgrid grid">
|
||||||
|
<div className="field col-12 md:col-12">
|
||||||
|
<label htmlFor="name">Nombre</label>
|
||||||
|
<div className="p-0 col-12 md:col-12">
|
||||||
|
<div className="p-inputgroup">
|
||||||
|
<span className="p-inputgroup-addon p-button p-icon-input-khaki">
|
||||||
|
<i className="pi pi-home"></i>
|
||||||
|
</span>
|
||||||
|
<InputText id="name" value={community.name} onChange={(e) => onInputChange(e, 'name')} required autoFocus className={classNames( submitted && community.name==='' ? 'p-invalid' : '' )} />
|
||||||
|
</div>
|
||||||
|
{submitted && community.name==='' && <small className="p-invalid">Nombre es requirido.</small>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="field col-12 md:col-6">
|
||||||
|
<label htmlFor="provinces">Provincia</label>
|
||||||
|
<div className="p-0 col-12 md:col-12">
|
||||||
|
<div className="p-inputgroup">
|
||||||
|
<span className="p-inputgroup-addon p-button p-icon-input-khaki">
|
||||||
|
<i className="pi pi-map-marker"></i>
|
||||||
|
</span>
|
||||||
|
<Dropdown placeholder="--Seleccione Provincia--" value={provinciaId} options={p} onChange={handleProvinces} required autoFocus className={classNames({ 'p-invalid': submitted && !provinciaId } )} />
|
||||||
|
</div>
|
||||||
|
{submitted && !provinciaId && <small className="p-invalid">Provincia es requirido.</small>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="field col-12 md:col-6">
|
||||||
|
<label htmlFor="cantons">Cantón</label>
|
||||||
|
<div className="p-0 col-12 md:col-12">
|
||||||
|
<div className="p-inputgroup">
|
||||||
|
<span className="p-inputgroup-addon p-button p-icon-input-khaki">
|
||||||
|
<i className="pi pi-map-marker"></i>
|
||||||
|
</span>
|
||||||
|
<Dropdown placeholder="--Seleccione Cantón--" value={cantonId} options={c} onChange={handleCanton} required autoFocus className={classNames({ 'p-invalid': submitted && !cantonId } )}/>
|
||||||
|
</div>
|
||||||
|
{submitted && !cantonId && <small className="p-invalid">Cantón es requirido.</small>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="field col-12 md:col-6">
|
||||||
|
<label htmlFor="districts">Distrito</label>
|
||||||
|
<div className="p-0 col-12 md:col-12">
|
||||||
|
<div className="p-inputgroup">
|
||||||
|
<span className="p-inputgroup-addon p-button p-icon-input-khaki">
|
||||||
|
<i className="pi pi-map-marker"></i>
|
||||||
|
</span>
|
||||||
|
<Dropdown placeholder="--Seleccione Distrito--" value={districtId} options={d} onChange={handleDistrict} required autoFocus className={classNames({ 'p-invalid': submitted && !districtId } )}/>
|
||||||
|
</div>
|
||||||
|
{submitted && !districtId && <small className="p-invalid">Distrito es requirido.</small>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="field col-12 md:col-6">
|
||||||
|
<label htmlFor="telefono">Número de Teléfono</label>
|
||||||
|
<div className="p-0 col-12 md:col-12">
|
||||||
|
<div className="p-inputgroup">
|
||||||
|
<span className="p-inputgroup-addon p-button p-icon-input-khaki">
|
||||||
|
<i className="pi pi-phone"></i>
|
||||||
|
</span>
|
||||||
|
<InputText id="phone" value={community.phone} onChange={(e) => onInputChange(e, 'phone')} required autoFocus className={classNames({ 'p-invalid': submitted && community.phone==='' } )} />
|
||||||
|
</div>
|
||||||
|
{submitted && community.phone==='' && <small className="p-invalid">Número de teléfono es requirido.</small>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="field col-12 md:col-6">
|
||||||
|
<label htmlFor="numHouse">Numero de Viviendas</label>
|
||||||
|
<div className="p-0 col-12 md:col-12">
|
||||||
|
<div className="p-inputgroup">
|
||||||
|
<span className="p-inputgroup-addon p-button p-icon-input-khaki">
|
||||||
|
<i className="pi pi-hashtag"></i>
|
||||||
|
</span>
|
||||||
|
<InputText id="num_houses" value={community.num_houses} onChange={(e) => onInputChange(e, 'num_houses')} required autoFocus className={classNames({ 'p-invalid': submitted && community.num_houses < 1 } )} />
|
||||||
|
</div>
|
||||||
|
{submitted && community.num_houses < 1 && <small className="p-invalid">Número de viviendas es requirido y debe ser mayor que 0.</small>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="field col-12 md:col-6">
|
||||||
|
<label htmlFor="numHouse">Ingrese el prefijo para el código de las viviendas</label>
|
||||||
|
<div className="p-0 col-12 md:col-12">
|
||||||
|
<div className="p-inputgroup">
|
||||||
|
<span className="p-inputgroup-addon p-button p-icon-input-khaki">
|
||||||
|
<i className="pi pi-hashtag"></i>
|
||||||
|
</span>
|
||||||
|
<InputText id="code_houses" value={codeHouses} onChange={handleCodeHouses} required autoFocus className={classNames({ 'p-invalid': submitted && !codeHouses } )} />
|
||||||
|
</div>
|
||||||
|
{submitted && !codeHouses && <small className="p-invalid">El código para las viviendas es requirido.</small>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-12 md:col-12 py-2">
|
||||||
|
<Button label="Registrar" icon="pi pi-check" onClick={saveCommunity}></Button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div >
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(Communities);
|
Loading…
Reference in New Issue