From eba74fcc6134b3367d470388a0eb194c37da2f3d Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Mon, 14 Sep 2020 23:55:27 +0300 Subject: [PATCH 01/42] Update rate-limiter usage --- server/.env.example | 1 + server/package-lock.json | 20 +++++++++----------- server/package.json | 2 +- server/src/app.module.ts | 3 ++- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/server/.env.example b/server/.env.example index cf863a54..7d7bd8a8 100755 --- a/server/.env.example +++ b/server/.env.example @@ -1,4 +1,5 @@ APP_DOMAIN=http://localhost +FRONTEND_IP= # ------------------------------------------------------------ # Database Configuration diff --git a/server/package-lock.json b/server/package-lock.json index 86909203..952e6f26 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -11728,18 +11728,11 @@ "integrity": "sha512-ZyRdSVs9GczI+39B7tNXsxfBXQOYnEF6l/q2aLYG8wSEvRHRDXAlzZ1SIosDibM02pLahGkDNLFC+nZ8uzJGDQ==" }, "nestjs-rate-limiter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/nestjs-rate-limiter/-/nestjs-rate-limiter-2.1.0.tgz", - "integrity": "sha512-ddW3SZqFTTwTk/V2syk7Kyqd4sMQenx1NrpavXcHb/lTDaapRTYdepKtzxx6LL/BHYnXt0/GM/TdWP5SlfMAxg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/nestjs-rate-limiter/-/nestjs-rate-limiter-2.4.0.tgz", + "integrity": "sha512-0oEhTK/QiiC/ioicYlgHzd54WAZvo8FFPmt6lxzNyelaz+yb3iOl5wPP6fG41s3aS5+CRym7LAyiVXo/e+tObQ==", "requires": { - "rate-limiter-flexible": "^2.1.10" - }, - "dependencies": { - "rate-limiter-flexible": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-2.1.10.tgz", - "integrity": "sha512-Pa+8TPD4xYaiCUB5K4a/+j2FHDUe4HP1g49JmKEmkOkhqPaeVqxJsZuuVaza/svSCOT+V73vtsyBiSFK/e1yXw==" - } + "rate-limiter-flexible": "2.1.10" } }, "next-tick": { @@ -12870,6 +12863,11 @@ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, + "rate-limiter-flexible": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/rate-limiter-flexible/-/rate-limiter-flexible-2.1.10.tgz", + "integrity": "sha512-Pa+8TPD4xYaiCUB5K4a/+j2FHDUe4HP1g49JmKEmkOkhqPaeVqxJsZuuVaza/svSCOT+V73vtsyBiSFK/e1yXw==" + }, "raw-body": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", diff --git a/server/package.json b/server/package.json index 0ec8a97a..50c6ed46 100644 --- a/server/package.json +++ b/server/package.json @@ -50,7 +50,7 @@ "nan": "^2.14.1", "nest-raven": "^5.0.0", "nest-router": "^1.0.9", - "nestjs-rate-limiter": "^2.1.0", + "nestjs-rate-limiter": "^2.4.0", "nodemailer": "^6.4.10", "passport": "^0.4.1", "passport-jwt": "^4.0.0", diff --git a/server/src/app.module.ts b/server/src/app.module.ts index 34bd5a5f..eb24a826 100755 --- a/server/src/app.module.ts +++ b/server/src/app.module.ts @@ -22,7 +22,8 @@ import { SitemapModule } from './sitemap/sitemap.module' RateLimiterModule.register({ for: 'Fastify', points: Number.MAX_SAFE_INTEGER, - duration: 1 + duration: 1, + whiteList: ['127.0.0.1', configService.getEnv('FRONTEND_IP')] }), SitemapModule, V1Module, From 2573f1c47ee704f5afd93c477e371b1fffe89ffd Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Mon, 14 Sep 2020 23:55:45 +0300 Subject: [PATCH 02/42] Get rid of Category logic --- .../src/shared/Entities/categories.entity.ts | 37 ----- server/src/shared/Entities/titles.entity.ts | 5 +- .../Repositories/categories.repository.ts | 143 ------------------ .../shared/Repositories/title.repository.ts | 32 ++-- server/src/shared/Services/config.service.ts | 3 +- .../Controller/category.controller.ts | 65 -------- .../v1/Category/Dto/create-category.dto.ts | 30 ---- .../v1/Category/Dto/update-category.dto.ts | 31 ---- .../v1/Category/Service/category.service.ts | 94 ------------ server/src/v1/Category/category.module.ts | 30 ---- .../v1/Title/Controller/title.controller.ts | 4 +- server/src/v1/Title/Dto/create-title.dto.ts | 8 +- server/src/v1/Title/Dto/update-title.dto.ts | 7 +- server/src/v1/Title/Service/title.service.ts | 36 +---- server/src/v1/Title/title.module.ts | 3 +- server/src/v1/v1.module.ts | 2 - server/src/version.routes.ts | 5 - 17 files changed, 27 insertions(+), 508 deletions(-) delete mode 100644 server/src/shared/Entities/categories.entity.ts delete mode 100644 server/src/shared/Repositories/categories.repository.ts delete mode 100644 server/src/v1/Category/Controller/category.controller.ts delete mode 100644 server/src/v1/Category/Dto/create-category.dto.ts delete mode 100644 server/src/v1/Category/Dto/update-category.dto.ts delete mode 100644 server/src/v1/Category/Service/category.service.ts delete mode 100755 server/src/v1/Category/category.module.ts diff --git a/server/src/shared/Entities/categories.entity.ts b/server/src/shared/Entities/categories.entity.ts deleted file mode 100644 index 41414215..00000000 --- a/server/src/shared/Entities/categories.entity.ts +++ /dev/null @@ -1,37 +0,0 @@ -// Other dependencies -import { - Column, - Entity, - ObjectID, - ObjectIdColumn, - CreateDateColumn, - UpdateDateColumn, -} from 'typeorm' - -@Entity('Categories') -export class CategoriesEntity { - constructor(partial: Partial) { - Object.assign(this, partial) - } - - @ObjectIdColumn() - id: ObjectID - - @Column({ type: 'string', nullable: true }) - parent_category: string - - @Column({ type: 'string', length: 50 }) - name: string - - @Column('boolean') - is_leaf: boolean - - @Column('array') - ancestors: string[] - - @CreateDateColumn('date') - created_at: Date - - @UpdateDateColumn('date') - updated_at: Date -} diff --git a/server/src/shared/Entities/titles.entity.ts b/server/src/shared/Entities/titles.entity.ts index df9da946..2465379a 100644 --- a/server/src/shared/Entities/titles.entity.ts +++ b/server/src/shared/Entities/titles.entity.ts @@ -18,11 +18,8 @@ export class TitlesEntity { @ObjectIdColumn() id: ObjectID - @Column({ type: 'string' }) - category_id: string - @Column({ type: 'array' }) - category_ancestors: string[] + tags: string[] @Column({ unique: true, diff --git a/server/src/shared/Repositories/categories.repository.ts b/server/src/shared/Repositories/categories.repository.ts deleted file mode 100644 index 29f5a76c..00000000 --- a/server/src/shared/Repositories/categories.repository.ts +++ /dev/null @@ -1,143 +0,0 @@ -// Nest dependencies -import { BadRequestException, UnprocessableEntityException, NotFoundException } from '@nestjs/common' - -// Other dependencies -import { Repository, EntityRepository } from 'typeorm' - -// Local files -import { CategoriesEntity } from '../Entities/categories.entity' -import { CreateCategoryDto } from 'src/v1/Category/Dto/create-category.dto' -import { UpdateCategoryDto } from 'src/v1/Category/Dto/update-category.dto' - -@EntityRepository(CategoriesEntity) -export class CategoriesRepository extends Repository { - async getCategory(categoryId: string): Promise { - try { - const category: CategoriesEntity = await this.findOneOrFail(categoryId) - return category - } catch (err) { - throw new NotFoundException('Category could not find by given id') - } - } - - async getMainCategories(): Promise<{categories: CategoriesEntity[], count: number}> { - const [categories, total] = await this.findAndCount({ - where: { - parent_category: null - }, - order: { - name: 'ASC' - } - }) - return { categories, count: total } - } - - async getChildCategories(categoryId: string): Promise<{categories: CategoriesEntity[], count: number}> { - const [categories, total] = await this.findAndCount({ - where: { - parent_category: categoryId, - }, - order: { - is_leaf: 'ASC', - name: 'ASC' - } - }) - return { categories, count: total } - } - - async getCategoryListByIds(idList: string[]): Promise<{categories: CategoriesEntity[], count: number}> { - const [categories, total] = await this.findAndCount({ - where: { - '_id': { - $in: idList - } - }, - skip: 0, - }) - return { categories, count: total } - } - - async createCategory(dto: CreateCategoryDto): Promise { - const categoryPayload: { - name: string, - parent_category?: string, - is_leaf: boolean, - ancestors: string[] - } = { - name: dto.categoryName, - is_leaf: dto.isLeaf, - ancestors: [] - } - - if (dto.parentCategoryId) { - try { - const parentCategory = await this.findOneOrFail(dto.parentCategoryId) - categoryPayload.parent_category = dto.parentCategoryId - categoryPayload.ancestors.push(...parentCategory.ancestors, dto.parentCategoryId) - } catch (err) { - throw new NotFoundException('Category could not find by given id') - } - } - - const newCategory: CategoriesEntity = new CategoriesEntity(categoryPayload) - - try { - return await this.save(newCategory) - } catch (err) { - throw new UnprocessableEntityException(err.errmsg) - } - } - - async updateCategory(categoryId: string, dto: UpdateCategoryDto): Promise { - let parentCategory: CategoriesEntity | null = null - if (dto.parentCategoryId) { - try { - parentCategory = await this.findOneOrFail(dto.parentCategoryId) - } catch (err) { - throw new NotFoundException('Parent category could not find by given id') - } - } - - let category: CategoriesEntity - try { - category = await this.findOneOrFail(categoryId) - } catch { - throw new NotFoundException('Category could not find by given id') - } - - try { - if (dto.categoryName) category.name = dto.categoryName - if (dto.isLeaf !== undefined) category.is_leaf = dto.isLeaf - if (parentCategory) { - category.parent_category = dto.parentCategoryId - category.ancestors = [...parentCategory.ancestors, String(parentCategory.id)] - } - - await this.save(category) - return category - } catch (err) { - throw new BadRequestException(err.errmsg) - } - } - - async deleteCategory(categoryId: string): Promise { - let category: CategoriesEntity - try { - category = await this.findOneOrFail(categoryId) - await this.delete(category) - } catch (err) { - throw new NotFoundException('Category could not find by given id') - } - - // Delete all child categories that belongs to deleted category - const childCategories: any[] = await this.find({ - where: { - ancestors: { - $in: [String(category.id)] - } - }, - }) - await this.remove(childCategories) - } - -} diff --git a/server/src/shared/Repositories/title.repository.ts b/server/src/shared/Repositories/title.repository.ts index 7ac0d613..a3734b4b 100644 --- a/server/src/shared/Repositories/title.repository.ts +++ b/server/src/shared/Repositories/title.repository.ts @@ -58,7 +58,7 @@ export class TitlesRepository extends Repository { async getTitleList( query: { author: string, - categoryIds: string[], + tags: string[], sortBy: 'hot' | 'top', skip: number, } @@ -68,19 +68,10 @@ export class TitlesRepository extends Repository { ...query.author && { opened_by: query.author }, - ...query.categoryIds && { - $or: [ - { - category_id: { - $in: query.categoryIds - } - }, - { - category_ancestors: { - $in: query.categoryIds - } - }, - ] + ...query.tags && { + tags: { + $in: query.tags + } }, ...query.sortBy === 'hot' && { created_at: { @@ -121,12 +112,11 @@ export class TitlesRepository extends Repository { return { titles, count: total } } - async createTitle(openedBy: string, dto: CreateTitleDto, categoryAncestors: string[]): Promise { + async createTitle(openedBy: string, dto: CreateTitleDto): Promise { const newTitle: TitlesEntity = new TitlesEntity({ name: dto.name, slug: slugify(dto.name, { lower: true }), - category_id: dto.categoryId, - category_ancestors: categoryAncestors, + tags: dto.tags, opened_by: openedBy, }) @@ -184,17 +174,13 @@ export class TitlesRepository extends Repository { return Math.round(averageRate) } - async updateTitle(updatedBy: string, title: TitlesEntity, dto: UpdateTitleDto, categoryAncestors: string[]): Promise { + async updateTitle(updatedBy: string, title: TitlesEntity, dto: UpdateTitleDto): Promise { try { if (dto.name) { title.name = dto.name title.slug = slugify(dto.name, { lower: true }) } - - if (dto.categoryId) { - title.category_id = dto.categoryId - title.category_ancestors = categoryAncestors - } + if (dto.tags) title.tags = dto.tags title.updated_by = updatedBy diff --git a/server/src/shared/Services/config.service.ts b/server/src/shared/Services/config.service.ts index 71313051..3c2a2ac7 100755 --- a/server/src/shared/Services/config.service.ts +++ b/server/src/shared/Services/config.service.ts @@ -6,7 +6,6 @@ import * as env from 'dotenv' // Local files import { UsersEntity } from '../Entities/users.entity' -import { CategoriesEntity } from '../Entities/categories.entity' import { EntriesEntity } from '../Entities/entries.entity' import { TitlesEntity } from '../Entities/titles.entity' import { ConversationsEntity } from '../Entities/conversations.entity' @@ -33,7 +32,7 @@ export class ConfigService { synchronize: true, useUnifiedTopology: true, entities: [ - UsersEntity, CategoriesEntity, EntriesEntity, TitlesEntity, ConversationsEntity, MessagesEntity + UsersEntity, EntriesEntity, TitlesEntity, ConversationsEntity, MessagesEntity ], ssl: false, } diff --git a/server/src/v1/Category/Controller/category.controller.ts b/server/src/v1/Category/Controller/category.controller.ts deleted file mode 100644 index 0f170c5d..00000000 --- a/server/src/v1/Category/Controller/category.controller.ts +++ /dev/null @@ -1,65 +0,0 @@ -// Nest dependencies -import { Controller, Post, Body, UseGuards, Param, Get, Delete, Patch } from '@nestjs/common' -import { AuthGuard } from '@nestjs/passport' -import { ApiTags, ApiBearerAuth } from '@nestjs/swagger' - -// Local files -import { Roles } from 'src/shared/Decorators/roles.decorator' -import { CreateCategoryDto } from '../Dto/create-category.dto' -import { CategoryService } from '../Service/category.service' -import { UpdateCategoryDto } from '../Dto/update-category.dto' -import { ISerializeResponse } from 'src/shared/Services/serializer.service' -import { Role } from 'src/shared/Enums/Roles' -import { StatusOk } from 'src/shared/Types' - -@ApiTags('v1/category') -@Controller() -export class CategoryController { - constructor( - private readonly categoryService: CategoryService, - ) {} - - @Get(':categoryId') - getCategory(@Param('categoryId') categoryId: string): Promise { - return this.categoryService.getCategory(categoryId) - } - - @Get('main-categories') - getMainCategories(): Promise { - return this.categoryService.getMainCategories() - } - - @Get(':categoryId/child-categories') - getChildCategories(@Param('categoryId') categoryId: string): Promise { - return this.categoryService.getChildCategories(categoryId) - } - - @Get('trending-categories') - getTrendingCategories(): Promise { - return this.categoryService.getTrendingCategories() - } - - @ApiBearerAuth() - @UseGuards(AuthGuard('jwt')) - @Post() - @Roles(Role.SuperAdmin) - createCategory(@Body() dto: CreateCategoryDto): Promise { - return this.categoryService.createCategory(dto) - } - - @ApiBearerAuth() - @UseGuards(AuthGuard('jwt')) - @Patch(':categoryId') - @Roles(Role.SuperAdmin) - updateCategory(@Param('categoryId') categoryId: string, @Body() dto: UpdateCategoryDto): Promise { - return this.categoryService.updateCategory(categoryId, dto) - } - - @ApiBearerAuth() - @UseGuards(AuthGuard('jwt')) - @Delete(':categoryId') - @Roles(Role.SuperAdmin) - deleteCategory(@Param('categoryId') categoryId: string): Promise { - return this.categoryService.deleteCategory(categoryId) - } -} diff --git a/server/src/v1/Category/Dto/create-category.dto.ts b/server/src/v1/Category/Dto/create-category.dto.ts deleted file mode 100644 index 95343e27..00000000 --- a/server/src/v1/Category/Dto/create-category.dto.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Nest dependencies -import { ApiProperty } from '@nestjs/swagger' - -// Other dependencies -import { IsNotEmpty, MaxLength, IsOptional, IsMongoId, IsBoolean } from 'class-validator' - -export class CreateCategoryDto { - @ApiProperty({ - required: true, - example: 'Electronic', - }) - @IsNotEmpty() - @MaxLength(50) - categoryName: string - - @ApiProperty({ - required: true, - example: false - }) - @IsBoolean() - isLeaf: boolean - - @ApiProperty({ - required: false, - example: '507f1f77bcf86cd799439011', - }) - @IsMongoId() - @IsOptional() - parentCategoryId: string -} diff --git a/server/src/v1/Category/Dto/update-category.dto.ts b/server/src/v1/Category/Dto/update-category.dto.ts deleted file mode 100644 index 051c8039..00000000 --- a/server/src/v1/Category/Dto/update-category.dto.ts +++ /dev/null @@ -1,31 +0,0 @@ -// Nest dependencies -import { ApiProperty } from '@nestjs/swagger' - -// Other dependencies -import { MaxLength, IsOptional, IsMongoId, IsBoolean } from 'class-validator' - -export class UpdateCategoryDto { - @ApiProperty({ - required: false, - example: 'Example Name', - }) - @IsOptional() - @MaxLength(50) - categoryName: string - - @ApiProperty({ - required: true, - example: false - }) - @IsOptional() - @IsBoolean() - isLeaf: boolean - - @ApiProperty({ - required: false, - example: '507f1f77bcf86cd799439011', - }) - @IsOptional() - @IsMongoId() - parentCategoryId: string -} diff --git a/server/src/v1/Category/Service/category.service.ts b/server/src/v1/Category/Service/category.service.ts deleted file mode 100644 index 8704bad7..00000000 --- a/server/src/v1/Category/Service/category.service.ts +++ /dev/null @@ -1,94 +0,0 @@ -// Nest dependencies -import { Injectable, BadRequestException } from '@nestjs/common' -import { InjectRepository } from '@nestjs/typeorm' - -// Other dependencies -import { ObjectId } from 'mongodb' -import { Validator } from 'class-validator' - -// Local files -import { CategoriesRepository } from 'src/shared/Repositories/categories.repository' -import { CategoriesEntity } from 'src/shared/Entities/categories.entity' -import { serializerService, ISerializeResponse } from 'src/shared/Services/serializer.service' -import { CreateCategoryDto } from '../Dto/create-category.dto' -import { UpdateCategoryDto } from '../Dto/update-category.dto' -import { EntriesRepository } from 'src/shared/Repositories/entries.repository' -import { TitlesRepository } from 'src/shared/Repositories/title.repository' -import { StatusOk } from 'src/shared/Types' - -@Injectable() -export class CategoryService { - private validator: Validator - - constructor( - @InjectRepository(CategoriesRepository) - private readonly categoriesRepository: CategoriesRepository, - @InjectRepository(EntriesRepository) - private readonly entriesRepository: EntriesRepository, - @InjectRepository(TitlesRepository) - private readonly titlesRepository: TitlesRepository, - ) { - this.validator = new Validator() - } - - async getCategory(categoryId: string): Promise { - if (!this.validator.isMongoId(categoryId)) throw new BadRequestException('Id must be a type of MongoId') - - const category: CategoriesEntity = await this.categoriesRepository.getCategory(categoryId) - return serializerService.serializeResponse('category_detail', category) - } - - async getMainCategories(): Promise { - const result: {categories: CategoriesEntity[], count: number} = await this.categoriesRepository.getMainCategories() - return serializerService.serializeResponse('category_list', result) - } - - async getChildCategories(categoryId: string): Promise { - const result: {categories: CategoriesEntity[], count: number} = await this.categoriesRepository.getChildCategories(categoryId) - return serializerService.serializeResponse('category_list', result) - } - - async getTrendingCategories(): Promise { - const latestEntries = await this.entriesRepository.getLatestEntries() - - // Parse most belonged titles - const topTitlesOfLatestEntries = [...latestEntries.entries.reduce((previous, current) => { - if(!previous.has(current.title_id)) previous.set(current.title_id, {id: current.title_id, entryCount: 1}) - else previous.get(current.title_id).entryCount++ - return previous - // tslint:disable-next-line:new-parens - }, new Map).values()] - - // Sort the title list by desc of entry counts and then take first 5 of them (Because trending category count will be 5) - const topFiveTitlesIds = topTitlesOfLatestEntries.sort((x, y) => y.entryCount - x.entryCount).slice(0, 5) - - // Make flat slug list and query them to get titles belongs to that slugs - const idList = topFiveTitlesIds.map(item => ObjectId(item.id)) - const topFiveTitles = await this.titlesRepository.getTitleListByIds(idList) - - // Make flat category_id list to get trending categories - const categoryIdList = topFiveTitles.titles.map(item => ObjectId(item.category_id)) - const trendingCategories = await this.categoriesRepository.getCategoryListByIds(categoryIdList) - - return serializerService.serializeResponse('trending_categories', trendingCategories) - } - - async createCategory(dto: CreateCategoryDto): Promise { - const newCategory: CategoriesEntity = await this.categoriesRepository.createCategory(dto) - return serializerService.serializeResponse('category_detail', newCategory) - } - - async updateCategory(categoryId: string, dto: UpdateCategoryDto): Promise { - if (!this.validator.isMongoId(categoryId)) throw new BadRequestException('Id must be a type of MongoId') - - const category: CategoriesEntity = await this.categoriesRepository.updateCategory(categoryId, dto) - return serializerService.serializeResponse('category_detail', category) - } - - async deleteCategory(categoryId: string): Promise { - if (!this.validator.isMongoId(categoryId)) throw new BadRequestException('Id must be a type of MongoId') - - await this.categoriesRepository.deleteCategory(categoryId) - return { status: 'ok', message: 'Category has been deleted' } - } -} diff --git a/server/src/v1/Category/category.module.ts b/server/src/v1/Category/category.module.ts deleted file mode 100755 index 3baef380..00000000 --- a/server/src/v1/Category/category.module.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Nest dependencies -import { APP_GUARD } from '@nestjs/core' -import { Module } from '@nestjs/common' -import { TypeOrmModule } from '@nestjs/typeorm' - -// Local files -import { CategoriesEntity } from 'src/shared/Entities/categories.entity' -import { CategoriesRepository } from 'src/shared/Repositories/categories.repository' -import { CategoryService } from './Service/category.service' -import { CategoryController } from './Controller/category.controller' -import { EntriesRepository } from 'src/shared/Repositories/entries.repository' -import { TitlesRepository } from 'src/shared/Repositories/title.repository' -import { RolesGuard } from 'src/shared/Guards/roles.guard' - -@Module({ - imports: [ - TypeOrmModule.forFeature([CategoriesEntity, CategoriesRepository, EntriesRepository, TitlesRepository]) - ], - controllers: [CategoryController], - providers: [ - CategoryService, - { - provide: APP_GUARD, - useClass: RolesGuard - } - ], - exports: [CategoryService] -}) - -export class CategoryModule {} diff --git a/server/src/v1/Title/Controller/title.controller.ts b/server/src/v1/Title/Controller/title.controller.ts index d1ee5594..b8f08563 100644 --- a/server/src/v1/Title/Controller/title.controller.ts +++ b/server/src/v1/Title/Controller/title.controller.ts @@ -54,12 +54,12 @@ export class TitleController { getTitleList( @Query() query: { author: string, - categoryIds: any, + tags: any, sortBy: 'hot' | 'top', skip: number, } ): Promise { - if (query.categoryIds) query.categoryIds = query.categoryIds.split(',') + if (query.tags) query.tags = query.tags.split(',') return this.titleService.getTitleList(query) } diff --git a/server/src/v1/Title/Dto/create-title.dto.ts b/server/src/v1/Title/Dto/create-title.dto.ts index 3dde33bd..15e82486 100644 --- a/server/src/v1/Title/Dto/create-title.dto.ts +++ b/server/src/v1/Title/Dto/create-title.dto.ts @@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger' // Other dependencies -import { IsNotEmpty, IsMongoId, Length } from 'class-validator' +import { IsNotEmpty, Length, IsArray } from 'class-validator' export class CreateTitleDto { @ApiProperty({ @@ -15,8 +15,8 @@ export class CreateTitleDto { @ApiProperty({ required: true, - example: '507f1f77bcf86cd799439011', + example: '["electronics", "phone", "samsung"]' }) - @IsMongoId() - categoryId: string + @IsArray() + tags: string[] } diff --git a/server/src/v1/Title/Dto/update-title.dto.ts b/server/src/v1/Title/Dto/update-title.dto.ts index b76d5dec..8237e11b 100644 --- a/server/src/v1/Title/Dto/update-title.dto.ts +++ b/server/src/v1/Title/Dto/update-title.dto.ts @@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger' // Other dependencies -import { IsNotEmpty, IsMongoId, MaxLength, IsOptional } from 'class-validator' +import { IsNotEmpty, MaxLength, IsOptional } from 'class-validator' export class UpdateTitleDto { @ApiProperty({ @@ -15,9 +15,8 @@ export class UpdateTitleDto { @ApiProperty({ required: false, - example: '507f1f77bcf86cd799439011', + example: '"electronics", "phone", "samsung"' }) @IsOptional() - @IsMongoId() - categoryId: string + tags: string[] } diff --git a/server/src/v1/Title/Service/title.service.ts b/server/src/v1/Title/Service/title.service.ts index 642b98ed..89750ad3 100644 --- a/server/src/v1/Title/Service/title.service.ts +++ b/server/src/v1/Title/Service/title.service.ts @@ -10,12 +10,10 @@ import { createReadStream } from 'fs' import { TitlesRepository } from 'src/shared/Repositories/title.repository' import { CreateTitleDto } from '../Dto/create-title.dto' import { TitlesEntity } from 'src/shared/Entities/titles.entity' -import { CategoriesRepository } from 'src/shared/Repositories/categories.repository' import { UpdateTitleDto } from '../Dto/update-title.dto' import { serializerService, ISerializeResponse } from 'src/shared/Services/serializer.service' import { EntriesRepository } from 'src/shared/Repositories/entries.repository' import { UsersRepository } from 'src/shared/Repositories/users.repository' -import { CategoriesEntity } from 'src/shared/Entities/categories.entity' import { AwsService } from 'src/shared/Services/aws.service' import { configService } from 'src/shared/Services/config.service' import { sitemapManipulationService } from 'src/shared/Services/sitemap.manipulation.service' @@ -28,8 +26,6 @@ export class TitleService { constructor( @InjectRepository(TitlesRepository) private readonly titlesRepository: TitlesRepository, - @InjectRepository(CategoriesRepository) - private readonly categoriesRepository: CategoriesRepository, @InjectRepository(EntriesRepository) private readonly entriesRepository: EntriesRepository, @InjectRepository(UsersRepository) @@ -61,7 +57,7 @@ export class TitleService { async getTitleList( query: { author: string, - categoryIds: string[], + tags: string[], sortBy: 'hot' | 'top', skip: number, } @@ -73,29 +69,22 @@ export class TitleService { return serializerService.serializeResponse('title_list', result) } - async createTitle(openedBy: string, payload: CreateTitleDto, buffer: Buffer): Promise { + async createTitle(openedBy: string, payload: any, buffer: Buffer): Promise { payload.name = payload.name.replace(/^\s+|\s+$/g, '') if (payload.name.length === 0) throw new BadRequestException('Title name can not be whitespace') + if (!payload.tags) throw new BadRequestException('tags must be provided') const dto = new CreateTitleDto() dto.name = payload.name - dto.categoryId = payload.categoryId + dto.tags = payload.tags.split(',') return await validate(dto, { validationError: { target: false } }).then(async errors => { if (errors.length > 0) { throw new BadRequestException(errors) } - let category: CategoriesEntity - try { - category = await this.categoriesRepository.findOneOrFail(dto.categoryId) - } catch (err) { - throw new NotFoundException('Category could not found by given id') - } - - if (!category.is_leaf) throw new BadRequestException('Category that is not leaf can not have titles') - const newTitle: TitlesEntity = await this.titlesRepository.createTitle(openedBy, dto, category.ancestors) + const newTitle: TitlesEntity = await this.titlesRepository.createTitle(openedBy, dto) if (buffer) this.awsService.uploadImage(String(newTitle.id), 'titles', buffer) if (configService.isProduction()) sitemapManipulationService.addToIndexedSitemap(newTitle.slug, new Date().toJSON().slice(0,10)) @@ -166,20 +155,7 @@ export class TitleService { throw new NotFoundException('Title could not found by given id') } - if (dto.categoryId && !this.validator.isMongoId(dto.categoryId)) { - throw new BadRequestException('Id must be a type of MongoId') - } - - let category - if (dto.categoryId) { - try { - category = await this.categoriesRepository.findOneOrFail(dto.categoryId) - } catch (err) { - throw new NotFoundException('Category could not found by given id') - } - } - - const updatedTitle: TitlesEntity = await this.titlesRepository.updateTitle(updatedBy, title, dto, category?.ancestors) + const updatedTitle: TitlesEntity = await this.titlesRepository.updateTitle(updatedBy, title, dto) if (configService.isProduction()) sitemapManipulationService.addToIndexedSitemap(updatedTitle.slug, new Date().toJSON().slice(0,10)) return serializerService.serializeResponse('title_detail', updatedTitle) diff --git a/server/src/v1/Title/title.module.ts b/server/src/v1/Title/title.module.ts index be24f781..7e0dd42c 100755 --- a/server/src/v1/Title/title.module.ts +++ b/server/src/v1/Title/title.module.ts @@ -7,7 +7,6 @@ import { TypeOrmModule } from '@nestjs/typeorm' import { TitlesEntity } from 'src/shared/Entities/titles.entity' import { TitlesRepository } from 'src/shared/Repositories/title.repository' import { TitleService } from './Service/title.service' -import { CategoriesRepository } from 'src/shared/Repositories/categories.repository' import { TitleController } from './Controller/title.controller' import { EntriesRepository } from 'src/shared/Repositories/entries.repository' import { UsersRepository } from 'src/shared/Repositories/users.repository' @@ -17,7 +16,7 @@ import { RolesGuard } from 'src/shared/Guards/roles.guard' @Module({ imports: [ TypeOrmModule.forFeature([ - TitlesEntity, TitlesRepository, CategoriesRepository, UsersRepository, EntriesRepository + TitlesEntity, TitlesRepository, UsersRepository, EntriesRepository ]) ], controllers: [TitleController], diff --git a/server/src/v1/v1.module.ts b/server/src/v1/v1.module.ts index fff688b2..add1ba71 100644 --- a/server/src/v1/v1.module.ts +++ b/server/src/v1/v1.module.ts @@ -6,7 +6,6 @@ import { BlacklistMiddleware } from 'src/shared/Middleware/blacklist.middleware' import { RedisService } from 'src/shared/Services/redis.service' import { UserModule } from './User/user.module' import { AuthModule } from './Auth/auth.module' -import { CategoryModule } from './Category/category.module' import { EntryModule } from './Entry/entry.module' import { TitleModule } from './Title/title.module' import { MessageModule } from './Message/message.module' @@ -15,7 +14,6 @@ import { MessageModule } from './Message/message.module' imports: [ UserModule, AuthModule, - CategoryModule, EntryModule, TitleModule, MessageModule diff --git a/server/src/version.routes.ts b/server/src/version.routes.ts index 737876c8..2ec56dc3 100644 --- a/server/src/version.routes.ts +++ b/server/src/version.routes.ts @@ -4,7 +4,6 @@ import { Routes } from 'nest-router' // Local files import { V1Module } from './v1/v1.module' import { AuthModule } from './v1/Auth/auth.module' -import { CategoryModule } from './v1/Category/category.module' import { EntryModule } from './v1/Entry/entry.module' import { UserModule } from './v1/User/user.module' import { TitleModule } from './v1/Title/title.module' @@ -19,10 +18,6 @@ export const versionRoutes: Routes = [ path: '/auth', module: AuthModule, }, - { - path: '/category', - module: CategoryModule, - }, { path: '/entry', module: EntryModule, From 49e52e676f396744b447db1266cd932e296c86e3 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Tue, 15 Sep 2020 21:25:21 +0300 Subject: [PATCH 03/42] Create tags entity and repository --- server/src/shared/Entities/tags.entity.ts | 31 +++++++++++++++++++ .../shared/Repositories/tags.repository.ts | 10 ++++++ server/src/shared/Services/config.service.ts | 3 +- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 server/src/shared/Entities/tags.entity.ts create mode 100644 server/src/shared/Repositories/tags.repository.ts diff --git a/server/src/shared/Entities/tags.entity.ts b/server/src/shared/Entities/tags.entity.ts new file mode 100644 index 00000000..0cdc1478 --- /dev/null +++ b/server/src/shared/Entities/tags.entity.ts @@ -0,0 +1,31 @@ +// Other dependencies +import { + Column, + Entity, + ObjectID, + ObjectIdColumn, + CreateDateColumn, + UpdateDateColumn, +} from 'typeorm' + +@Entity('Tags') +export class TagsEntity { + constructor(partial: Partial) { + Object.assign(this, partial) + } + + @ObjectIdColumn() + _id: ObjectID + + @Column({ type: 'string' }) + name: string + + @Column({ type: 'int' }) + total_title: number + + @CreateDateColumn({ type: 'date' }) + created_at: Date + + @UpdateDateColumn({ type: 'date' }) + updated_at: Date +} \ No newline at end of file diff --git a/server/src/shared/Repositories/tags.repository.ts b/server/src/shared/Repositories/tags.repository.ts new file mode 100644 index 00000000..f2c0c1bc --- /dev/null +++ b/server/src/shared/Repositories/tags.repository.ts @@ -0,0 +1,10 @@ +// Other dependencies +import { Repository, EntityRepository } from 'typeorm' + +// Local files +import { TagsEntity } from '../Entities/tags.entity' + +@EntityRepository(TagsEntity) +export class TagsRepository extends Repository { + +} \ No newline at end of file diff --git a/server/src/shared/Services/config.service.ts b/server/src/shared/Services/config.service.ts index 3c2a2ac7..eecc30dd 100755 --- a/server/src/shared/Services/config.service.ts +++ b/server/src/shared/Services/config.service.ts @@ -10,6 +10,7 @@ import { EntriesEntity } from '../Entities/entries.entity' import { TitlesEntity } from '../Entities/titles.entity' import { ConversationsEntity } from '../Entities/conversations.entity' import { MessagesEntity } from '../Entities/messages.entity' +import { TagsEntity } from '../Entities/tags.entity' env.config() @@ -32,7 +33,7 @@ export class ConfigService { synchronize: true, useUnifiedTopology: true, entities: [ - UsersEntity, EntriesEntity, TitlesEntity, ConversationsEntity, MessagesEntity + UsersEntity, TagsEntity, TitlesEntity, EntriesEntity, ConversationsEntity, MessagesEntity ], ssl: false, } From 6bb50475e59ecca4a6f8d861301b24b0fdf0b343 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Tue, 15 Sep 2020 21:25:49 +0300 Subject: [PATCH 04/42] Update createTitle func of Title module --- server/src/v1/Title/Service/title.service.ts | 21 ++++++++++++++++++-- server/src/v1/Title/title.module.ts | 3 ++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/server/src/v1/Title/Service/title.service.ts b/server/src/v1/Title/Service/title.service.ts index 89750ad3..76794986 100644 --- a/server/src/v1/Title/Service/title.service.ts +++ b/server/src/v1/Title/Service/title.service.ts @@ -18,6 +18,7 @@ import { AwsService } from 'src/shared/Services/aws.service' import { configService } from 'src/shared/Services/config.service' import { sitemapManipulationService } from 'src/shared/Services/sitemap.manipulation.service' import { StatusOk } from 'src/shared/Types' +import { TagsRepository } from 'src/shared/Repositories/tags.repository' @Injectable() export class TitleService { @@ -26,6 +27,8 @@ export class TitleService { constructor( @InjectRepository(TitlesRepository) private readonly titlesRepository: TitlesRepository, + @InjectRepository(TagsRepository) + private readonly tagsRepository: TagsRepository, @InjectRepository(EntriesRepository) private readonly entriesRepository: EntriesRepository, @InjectRepository(UsersRepository) @@ -78,18 +81,32 @@ export class TitleService { dto.name = payload.name dto.tags = payload.tags.split(',') - return await validate(dto, { validationError: { target: false } }).then(async errors => { + dto.tags.forEach(async element => { + const tag = await this.tagsRepository.findOne({ name: element }) + if (!tag) { + this.tagsRepository.save({ + name: element, + total_title: 0 + }) + } else { + tag.total_title++ + this.tagsRepository.save(tag) + } + }) + + const result = await validate(dto, { validationError: { target: false } }).then(async errors => { if (errors.length > 0) { throw new BadRequestException(errors) } - const newTitle: TitlesEntity = await this.titlesRepository.createTitle(openedBy, dto) if (buffer) this.awsService.uploadImage(String(newTitle.id), 'titles', buffer) if (configService.isProduction()) sitemapManipulationService.addToIndexedSitemap(newTitle.slug, new Date().toJSON().slice(0,10)) return serializerService.serializeResponse('title_detail', newTitle) }) + + return result } async getTitleImage(titleId: string): Promise { diff --git a/server/src/v1/Title/title.module.ts b/server/src/v1/Title/title.module.ts index 7e0dd42c..da1d55d0 100755 --- a/server/src/v1/Title/title.module.ts +++ b/server/src/v1/Title/title.module.ts @@ -10,13 +10,14 @@ import { TitleService } from './Service/title.service' import { TitleController } from './Controller/title.controller' import { EntriesRepository } from 'src/shared/Repositories/entries.repository' import { UsersRepository } from 'src/shared/Repositories/users.repository' +import { TagsRepository } from 'src/shared/Repositories/tags.repository' import { AwsService } from 'src/shared/Services/aws.service' import { RolesGuard } from 'src/shared/Guards/roles.guard' @Module({ imports: [ TypeOrmModule.forFeature([ - TitlesEntity, TitlesRepository, UsersRepository, EntriesRepository + TitlesEntity, TagsRepository, TitlesRepository, UsersRepository, EntriesRepository ]) ], controllers: [TitleController], From 7dd8e6900f66f0438e78d7c7d97e1cc49c7f46b3 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 20 Sep 2020 21:15:55 +0300 Subject: [PATCH 05/42] Update nestjs-rate-limiter version to 2.5.0 --- server/package-lock.json | 7 ++++--- server/package.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/server/package-lock.json b/server/package-lock.json index 952e6f26..a7487ef4 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -11728,10 +11728,11 @@ "integrity": "sha512-ZyRdSVs9GczI+39B7tNXsxfBXQOYnEF6l/q2aLYG8wSEvRHRDXAlzZ1SIosDibM02pLahGkDNLFC+nZ8uzJGDQ==" }, "nestjs-rate-limiter": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/nestjs-rate-limiter/-/nestjs-rate-limiter-2.4.0.tgz", - "integrity": "sha512-0oEhTK/QiiC/ioicYlgHzd54WAZvo8FFPmt6lxzNyelaz+yb3iOl5wPP6fG41s3aS5+CRym7LAyiVXo/e+tObQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/nestjs-rate-limiter/-/nestjs-rate-limiter-2.5.0.tgz", + "integrity": "sha512-v5sQLCzKPUMuOdCS1xD15/Rx++RrTpD26k3KG3Ny34E0B2A5rDZyjnEPmG5zYE3cJrzlNM+LYT9ZJb89K5KVyA==", "requires": { + "dotenv": "^8.2.0", "rate-limiter-flexible": "2.1.10" } }, diff --git a/server/package.json b/server/package.json index 50c6ed46..3e4ec009 100644 --- a/server/package.json +++ b/server/package.json @@ -50,7 +50,7 @@ "nan": "^2.14.1", "nest-raven": "^5.0.0", "nest-router": "^1.0.9", - "nestjs-rate-limiter": "^2.4.0", + "nestjs-rate-limiter": "^2.5.0", "nodemailer": "^6.4.10", "passport": "^0.4.1", "passport-jwt": "^4.0.0", From 82e2b4ea6075edb0811ccbb533ea229015d95583 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 20 Sep 2020 21:50:20 +0300 Subject: [PATCH 06/42] Create basic infrastructure of Tag module --- server/src/v1/Tag/tag.controller.ts | 19 +++++++++++++++++++ server/src/v1/Tag/tag.module.ts | 15 +++++++++++++++ server/src/v1/Tag/tag.service.ts | 10 ++++++++++ server/src/v1/v1.module.ts | 10 ++++++---- server/src/version.routes.ts | 15 ++++++++++----- 5 files changed, 60 insertions(+), 9 deletions(-) create mode 100644 server/src/v1/Tag/tag.controller.ts create mode 100644 server/src/v1/Tag/tag.module.ts create mode 100644 server/src/v1/Tag/tag.service.ts diff --git a/server/src/v1/Tag/tag.controller.ts b/server/src/v1/Tag/tag.controller.ts new file mode 100644 index 00000000..b0d15de2 --- /dev/null +++ b/server/src/v1/Tag/tag.controller.ts @@ -0,0 +1,19 @@ +// Nest dependencies +import { Controller, Get } from '@nestjs/common' +import { ApiTags, ApiBearerAuth } from '@nestjs/swagger' +import { TagService } from './tag.service' + +// Local files + +@ApiTags('v1/tag') +@Controller() +export class TagController { + constructor(private readonly tagService: TagService) {} + + @ApiBearerAuth() + @Get('trending') + getString(): Promise { + return this.tagService.getTrending() + } + +} diff --git a/server/src/v1/Tag/tag.module.ts b/server/src/v1/Tag/tag.module.ts new file mode 100644 index 00000000..80eebea7 --- /dev/null +++ b/server/src/v1/Tag/tag.module.ts @@ -0,0 +1,15 @@ +// Nest dependencies +import { Module } from '@nestjs/common' + +// Local files +import { TagController } from './tag.controller' +import { TagService } from './tag.service' + +@Module({ + imports: [], + controllers: [TagController], + providers: [TagService], + exports: [TagService] +}) + +export class TagModule {} diff --git a/server/src/v1/Tag/tag.service.ts b/server/src/v1/Tag/tag.service.ts new file mode 100644 index 00000000..8d46fe06 --- /dev/null +++ b/server/src/v1/Tag/tag.service.ts @@ -0,0 +1,10 @@ +// Nest dependencies +import { Injectable} from '@nestjs/common' + +@Injectable() +export class TagService { + async getTrending(): Promise { + // TODO + return 'hey' + } +} diff --git a/server/src/v1/v1.module.ts b/server/src/v1/v1.module.ts index add1ba71..0017734c 100644 --- a/server/src/v1/v1.module.ts +++ b/server/src/v1/v1.module.ts @@ -4,18 +4,20 @@ import { Module, MiddlewareConsumer } from '@nestjs/common' // Local files import { BlacklistMiddleware } from 'src/shared/Middleware/blacklist.middleware' import { RedisService } from 'src/shared/Services/redis.service' -import { UserModule } from './User/user.module' import { AuthModule } from './Auth/auth.module' -import { EntryModule } from './Entry/entry.module' +import { UserModule } from './User/user.module' +import { TagModule } from './Tag/tag.module' import { TitleModule } from './Title/title.module' +import { EntryModule } from './Entry/entry.module' import { MessageModule } from './Message/message.module' @Module({ imports: [ - UserModule, AuthModule, - EntryModule, + UserModule, + TagModule, TitleModule, + EntryModule, MessageModule ], providers: [RedisService], diff --git a/server/src/version.routes.ts b/server/src/version.routes.ts index 2ec56dc3..c7247284 100644 --- a/server/src/version.routes.ts +++ b/server/src/version.routes.ts @@ -8,6 +8,7 @@ import { EntryModule } from './v1/Entry/entry.module' import { UserModule } from './v1/User/user.module' import { TitleModule } from './v1/Title/title.module' import { MessageModule } from './v1/Message/message.module' +import { TagModule } from './v1/Tag/tag.module' export const versionRoutes: Routes = [ { @@ -19,21 +20,25 @@ export const versionRoutes: Routes = [ module: AuthModule, }, { - path: '/entry', - module: EntryModule, + path: '/user', + module: UserModule, + }, + { + path: '/tag', + module: TagModule }, { path: '/title', module: TitleModule, }, { - path: '/user', - module: UserModule, + path: '/entry', + module: EntryModule, }, { path: '/message', module: MessageModule, - }, + } ], }, ] From b2fa0f429834f84d7b474dd1be9147dc9f6b7016 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 20 Sep 2020 22:11:34 +0300 Subject: [PATCH 07/42] [server] Update nestjs-rate-limiter version --- server/package-lock.json | 7 +++---- server/package.json | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/server/package-lock.json b/server/package-lock.json index a7487ef4..5482fd13 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -11728,11 +11728,10 @@ "integrity": "sha512-ZyRdSVs9GczI+39B7tNXsxfBXQOYnEF6l/q2aLYG8wSEvRHRDXAlzZ1SIosDibM02pLahGkDNLFC+nZ8uzJGDQ==" }, "nestjs-rate-limiter": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/nestjs-rate-limiter/-/nestjs-rate-limiter-2.5.0.tgz", - "integrity": "sha512-v5sQLCzKPUMuOdCS1xD15/Rx++RrTpD26k3KG3Ny34E0B2A5rDZyjnEPmG5zYE3cJrzlNM+LYT9ZJb89K5KVyA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/nestjs-rate-limiter/-/nestjs-rate-limiter-2.5.1.tgz", + "integrity": "sha512-lFaDe9kJeoNrbDTiJnzpLQacNqf8Yv3vR3spNmWtMe2ipyK3HsOXjvPxJ5g6qFb1sDVObMKALcv8bAMjPhB9Hw==", "requires": { - "dotenv": "^8.2.0", "rate-limiter-flexible": "2.1.10" } }, diff --git a/server/package.json b/server/package.json index 3e4ec009..1e49d48e 100644 --- a/server/package.json +++ b/server/package.json @@ -50,7 +50,7 @@ "nan": "^2.14.1", "nest-raven": "^5.0.0", "nest-router": "^1.0.9", - "nestjs-rate-limiter": "^2.5.0", + "nestjs-rate-limiter": "^2.5.1", "nodemailer": "^6.4.10", "passport": "^0.4.1", "passport-jwt": "^4.0.0", From 395c1d1d5e778701df69796f2c76834e569cfecb Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Wed, 23 Sep 2020 22:39:14 +0300 Subject: [PATCH 08/42] [server] Upgrade nestjs-rate-limiter version --- server/package-lock.json | 6 +++--- server/package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/package-lock.json b/server/package-lock.json index 5482fd13..67869cea 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -11728,9 +11728,9 @@ "integrity": "sha512-ZyRdSVs9GczI+39B7tNXsxfBXQOYnEF6l/q2aLYG8wSEvRHRDXAlzZ1SIosDibM02pLahGkDNLFC+nZ8uzJGDQ==" }, "nestjs-rate-limiter": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/nestjs-rate-limiter/-/nestjs-rate-limiter-2.5.1.tgz", - "integrity": "sha512-lFaDe9kJeoNrbDTiJnzpLQacNqf8Yv3vR3spNmWtMe2ipyK3HsOXjvPxJ5g6qFb1sDVObMKALcv8bAMjPhB9Hw==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/nestjs-rate-limiter/-/nestjs-rate-limiter-2.5.2.tgz", + "integrity": "sha512-Ssuj5sv3zyrrbQWEGcuQow3gC4qEbzSVGSdb2yn4tK5lDiuAEgZQODtel5AK7/zgRKxK/pfJzT7GkFRmhipkPg==", "requires": { "rate-limiter-flexible": "2.1.10" } diff --git a/server/package.json b/server/package.json index 1e49d48e..5c02c868 100644 --- a/server/package.json +++ b/server/package.json @@ -50,7 +50,7 @@ "nan": "^2.14.1", "nest-raven": "^5.0.0", "nest-router": "^1.0.9", - "nestjs-rate-limiter": "^2.5.1", + "nestjs-rate-limiter": "^2.5.2", "nodemailer": "^6.4.10", "passport": "^0.4.1", "passport-jwt": "^4.0.0", From 38b332e8dd3d9a2fcd437b26c70f95cb3234a6d7 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Wed, 23 Sep 2020 22:39:38 +0300 Subject: [PATCH 09/42] [server] Add new field 'popularity_ratio' to TagsEntity --- server/src/shared/Entities/tags.entity.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/shared/Entities/tags.entity.ts b/server/src/shared/Entities/tags.entity.ts index 0cdc1478..ce285506 100644 --- a/server/src/shared/Entities/tags.entity.ts +++ b/server/src/shared/Entities/tags.entity.ts @@ -23,6 +23,9 @@ export class TagsEntity { @Column({ type: 'int' }) total_title: number + @Column({ type: 'double' }) + popularity_ratio: number + @CreateDateColumn({ type: 'date' }) created_at: Date From 56710193ab37c1384fc0fb0de846d16e9bb69c2e Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Wed, 23 Sep 2020 22:39:56 +0300 Subject: [PATCH 10/42] [server] Code optimization on Title-Tag modules --- .../src/shared/Repositories/tags.repository.ts | 18 ++++++++++++++++++ server/src/v1/Title/Service/title.service.ts | 15 ++------------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/server/src/shared/Repositories/tags.repository.ts b/server/src/shared/Repositories/tags.repository.ts index f2c0c1bc..fe85a63b 100644 --- a/server/src/shared/Repositories/tags.repository.ts +++ b/server/src/shared/Repositories/tags.repository.ts @@ -7,4 +7,22 @@ import { TagsEntity } from '../Entities/tags.entity' @EntityRepository(TagsEntity) export class TagsRepository extends Repository { + async tagActionOnTitleCreate(tagName: string): Promise { + const tag = await this.findOne({ name: tagName }) + + if (!tag) { + this.save({ + name: tagName, + popularity_ratio: 0.01, + total_title: 0 + }) + } else { + // TODO popularity_ratio logic + tag.total_title++ + this.save(tag) + } + + return + } + } \ No newline at end of file diff --git a/server/src/v1/Title/Service/title.service.ts b/server/src/v1/Title/Service/title.service.ts index 76794986..57f3d60f 100644 --- a/server/src/v1/Title/Service/title.service.ts +++ b/server/src/v1/Title/Service/title.service.ts @@ -81,19 +81,6 @@ export class TitleService { dto.name = payload.name dto.tags = payload.tags.split(',') - dto.tags.forEach(async element => { - const tag = await this.tagsRepository.findOne({ name: element }) - if (!tag) { - this.tagsRepository.save({ - name: element, - total_title: 0 - }) - } else { - tag.total_title++ - this.tagsRepository.save(tag) - } - }) - const result = await validate(dto, { validationError: { target: false } }).then(async errors => { if (errors.length > 0) { throw new BadRequestException(errors) @@ -106,6 +93,8 @@ export class TitleService { return serializerService.serializeResponse('title_detail', newTitle) }) + dto.tags.forEach(async element => this.tagsRepository.tagActionOnTitleCreate(element)) + return result } From 7670513d4056e569c6dc347679f20a0bd0e137d9 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 27 Sep 2020 11:41:00 +0300 Subject: [PATCH 11/42] Implement popularity calculation logic of tags --- server/src/shared/Repositories/tags.repository.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/server/src/shared/Repositories/tags.repository.ts b/server/src/shared/Repositories/tags.repository.ts index fe85a63b..2a4a65d1 100644 --- a/server/src/shared/Repositories/tags.repository.ts +++ b/server/src/shared/Repositories/tags.repository.ts @@ -8,7 +8,7 @@ import { TagsEntity } from '../Entities/tags.entity' export class TagsRepository extends Repository { async tagActionOnTitleCreate(tagName: string): Promise { - const tag = await this.findOne({ name: tagName }) + const tag: any = await this.findOne({ name: tagName }) if (!tag) { this.save({ @@ -16,8 +16,15 @@ export class TagsRepository extends Repository { popularity_ratio: 0.01, total_title: 0 }) - } else { - // TODO popularity_ratio logic + } + + else { + const diff = new Date().getTime() - tag.updated_at + const diffAsMin = Math.round((diff / 1000) / 60) + + if (diffAsMin <= 1440 && tag.popularity_ratio < 1.00) tag.popularity_ratio += 0.01 + else tag.popularity_ratio = 0.02 + tag.total_title++ this.save(tag) } From 05f52e5109ed1731d6ec0630e8e325ae2281931f Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 27 Sep 2020 12:13:20 +0300 Subject: [PATCH 12/42] Add 'Read one by id' logic to Tag module --- server/src/v1/Tag/tag.controller.ts | 12 +++++++--- server/src/v1/Tag/tag.module.ts | 8 ++++++- server/src/v1/Tag/tag.service.ts | 35 +++++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/server/src/v1/Tag/tag.controller.ts b/server/src/v1/Tag/tag.controller.ts index b0d15de2..317bf88a 100644 --- a/server/src/v1/Tag/tag.controller.ts +++ b/server/src/v1/Tag/tag.controller.ts @@ -1,19 +1,25 @@ // Nest dependencies -import { Controller, Get } from '@nestjs/common' +import { Controller, Get, Param } from '@nestjs/common' import { ApiTags, ApiBearerAuth } from '@nestjs/swagger' -import { TagService } from './tag.service' // Local files +import { ISerializeResponse } from 'src/shared/Services/serializer.service' +import { TagService } from './tag.service' @ApiTags('v1/tag') @Controller() export class TagController { constructor(private readonly tagService: TagService) {} + @Get(':categoryId') + getCategory(@Param('categoryId') tagId: string): Promise { + return this.tagService.getTag(tagId) + } + @ApiBearerAuth() @Get('trending') getString(): Promise { return this.tagService.getTrending() } -} +} \ No newline at end of file diff --git a/server/src/v1/Tag/tag.module.ts b/server/src/v1/Tag/tag.module.ts index 80eebea7..eb16a0fe 100644 --- a/server/src/v1/Tag/tag.module.ts +++ b/server/src/v1/Tag/tag.module.ts @@ -1,12 +1,18 @@ // Nest dependencies import { Module } from '@nestjs/common' +import { TypeOrmModule } from '@nestjs/typeorm' // Local files +import { TagsRepository } from 'src/shared/Repositories/tags.repository' import { TagController } from './tag.controller' import { TagService } from './tag.service' @Module({ - imports: [], + imports: [ + TypeOrmModule.forFeature([ + TagsRepository + ]) + ], controllers: [TagController], providers: [TagService], exports: [TagService] diff --git a/server/src/v1/Tag/tag.service.ts b/server/src/v1/Tag/tag.service.ts index 8d46fe06..d7f8236d 100644 --- a/server/src/v1/Tag/tag.service.ts +++ b/server/src/v1/Tag/tag.service.ts @@ -1,10 +1,41 @@ // Nest dependencies -import { Injectable} from '@nestjs/common' +import { BadRequestException, Injectable, NotFoundException} from '@nestjs/common' +import { InjectRepository } from '@nestjs/typeorm' + +// Other dependencies +import { Validator } from 'class-validator' + +// Local files +import { TagsRepository } from 'src/shared/Repositories/tags.repository' +import { ISerializeResponse, serializerService } from 'src/shared/Services/serializer.service' @Injectable() export class TagService { + private validator: Validator + + constructor( + @InjectRepository(TagsRepository) + private readonly tagRepository: TagsRepository, + ) { + this.validator = new Validator() + } + + async getTag(tagId: string): Promise { + if (!this.validator.isMongoId(tagId)) throw new BadRequestException('Id must be a type of MongoId') + + let tag + try { + tag = await this.tagRepository.findOneOrFail(tagId) + } + catch { + throw new NotFoundException('Tag could not found by given id') + } + + return serializerService.serializeResponse('tag_detail', tag) + } + async getTrending(): Promise { // TODO return 'hey' } -} +} \ No newline at end of file From 184fb8bf8a85daf68ec8dfae29b58a58172c8c15 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 27 Sep 2020 15:18:10 +0300 Subject: [PATCH 13/42] Add Delete operation to Tag module --- .../shared/Repositories/tags.repository.ts | 5 ++++ .../shared/Repositories/title.repository.ts | 24 +++++++++++++++---- server/src/v1/Tag/tag.controller.ts | 18 +++++++++++--- server/src/v1/Tag/tag.module.ts | 4 +++- server/src/v1/Tag/tag.service.ts | 24 ++++++++++++++++++- 5 files changed, 66 insertions(+), 9 deletions(-) diff --git a/server/src/shared/Repositories/tags.repository.ts b/server/src/shared/Repositories/tags.repository.ts index 2a4a65d1..9afe9118 100644 --- a/server/src/shared/Repositories/tags.repository.ts +++ b/server/src/shared/Repositories/tags.repository.ts @@ -32,4 +32,9 @@ export class TagsRepository extends Repository { return } + async deleteTag(tag: TagsEntity): Promise { + await this.delete(tag) + return + } + } \ No newline at end of file diff --git a/server/src/shared/Repositories/title.repository.ts b/server/src/shared/Repositories/title.repository.ts index a3734b4b..40f4b4c3 100644 --- a/server/src/shared/Repositories/title.repository.ts +++ b/server/src/shared/Repositories/title.repository.ts @@ -15,7 +15,7 @@ import { UpdateTitleDto } from 'src/v1/Title/Dto/update-title.dto' export class TitlesRepository extends Repository { async getTitleBySlug(titleSlug: string): Promise { try { - const title: TitlesEntity = await this.findOneOrFail({slug: titleSlug}) + const title: TitlesEntity = await this.findOneOrFail({ slug: titleSlug }) return title } catch (err) { throw new NotFoundException('Title could not found by given slug') @@ -31,7 +31,7 @@ export class TitlesRepository extends Repository { } } - async searchTitle({ searchValue } : { searchValue: string }): Promise<{ titles: TitlesEntity[] }> { + async searchTitle({ searchValue }: { searchValue: string }): Promise<{ titles: TitlesEntity[] }> { const [titles] = await this.findAndCount({ where: { name: new RegExp(searchValue, 'i') @@ -137,7 +137,7 @@ export class TitlesRepository extends Repository { const docIfAlreadyRated = title.rate.find(item => item.username === ratedBy) if (docIfAlreadyRated) docIfAlreadyRated.rateValue = rateValue - else title.rate.push({ username: ratedBy, rateValue}) + else title.rate.push({ username: ratedBy, rateValue }) this.save(title) } @@ -151,7 +151,7 @@ export class TitlesRepository extends Repository { } const userRate: { rateValue: number } | undefined = title.rate.find(( - item: {username: string, rateValue: number } + item: { username: string, rateValue: number } ) => item.username === username) if (userRate) return userRate!.rateValue @@ -191,6 +191,22 @@ export class TitlesRepository extends Repository { } } + async deleteTagFromTitle(tagName: string): Promise { + const titles = await this.find({ + where: { + tags: { $in: [tagName] } + } + }) + + titles.map(title => { + const updatedTagList = title.tags.filter(tag => tag !== tagName) + title.tags = updatedTagList + this.save(title) + }) + + return + } + async deleteTitle(titleId: string): Promise { try { const title: TitlesEntity = await this.findOneOrFail(titleId) diff --git a/server/src/v1/Tag/tag.controller.ts b/server/src/v1/Tag/tag.controller.ts index 317bf88a..abb81a42 100644 --- a/server/src/v1/Tag/tag.controller.ts +++ b/server/src/v1/Tag/tag.controller.ts @@ -1,9 +1,13 @@ // Nest dependencies -import { Controller, Get, Param } from '@nestjs/common' +import { Controller, Delete, Get, Param, UseGuards } from '@nestjs/common' +import { AuthGuard } from '@nestjs/passport' import { ApiTags, ApiBearerAuth } from '@nestjs/swagger' // Local files import { ISerializeResponse } from 'src/shared/Services/serializer.service' +import { Roles } from 'src/shared/Decorators/roles.decorator' +import { Role } from 'src/shared/Enums/Roles' +import { StatusOk } from 'src/shared/Types' import { TagService } from './tag.service' @ApiTags('v1/tag') @@ -11,8 +15,8 @@ import { TagService } from './tag.service' export class TagController { constructor(private readonly tagService: TagService) {} - @Get(':categoryId') - getCategory(@Param('categoryId') tagId: string): Promise { + @Get(':tagId') + getCategory(@Param('tagId') tagId: string): Promise { return this.tagService.getTag(tagId) } @@ -22,4 +26,12 @@ export class TagController { return this.tagService.getTrending() } + @ApiBearerAuth() + @UseGuards(AuthGuard('jwt')) + @Delete(':tagId') + @Roles(Role.SuperAdmin) + deleteTag(@Param('tagId') tagId: string): Promise { + return this.tagService.deleteTag(tagId) + } + } \ No newline at end of file diff --git a/server/src/v1/Tag/tag.module.ts b/server/src/v1/Tag/tag.module.ts index eb16a0fe..6565bbb1 100644 --- a/server/src/v1/Tag/tag.module.ts +++ b/server/src/v1/Tag/tag.module.ts @@ -3,6 +3,7 @@ import { Module } from '@nestjs/common' import { TypeOrmModule } from '@nestjs/typeorm' // Local files +import { TitlesRepository } from 'src/shared/Repositories/title.repository' import { TagsRepository } from 'src/shared/Repositories/tags.repository' import { TagController } from './tag.controller' import { TagService } from './tag.service' @@ -10,7 +11,8 @@ import { TagService } from './tag.service' @Module({ imports: [ TypeOrmModule.forFeature([ - TagsRepository + TagsRepository, + TitlesRepository ]) ], controllers: [TagController], diff --git a/server/src/v1/Tag/tag.service.ts b/server/src/v1/Tag/tag.service.ts index d7f8236d..56823a69 100644 --- a/server/src/v1/Tag/tag.service.ts +++ b/server/src/v1/Tag/tag.service.ts @@ -6,8 +6,11 @@ import { InjectRepository } from '@nestjs/typeorm' import { Validator } from 'class-validator' // Local files -import { TagsRepository } from 'src/shared/Repositories/tags.repository' import { ISerializeResponse, serializerService } from 'src/shared/Services/serializer.service' +import { TitlesRepository } from 'src/shared/Repositories/title.repository' +import { TagsRepository } from 'src/shared/Repositories/tags.repository' +import { TagsEntity } from 'src/shared/Entities/tags.entity' +import { StatusOk } from 'src/shared/Types' @Injectable() export class TagService { @@ -16,6 +19,8 @@ export class TagService { constructor( @InjectRepository(TagsRepository) private readonly tagRepository: TagsRepository, + @InjectRepository(TitlesRepository) + private readonly titleRepository: TitlesRepository, ) { this.validator = new Validator() } @@ -38,4 +43,21 @@ export class TagService { // TODO return 'hey' } + + async deleteTag(tagId: string): Promise { + if (!this.validator.isMongoId(tagId)) throw new BadRequestException('Id must be a type of MongoId') + + let tag: TagsEntity | null + try { + tag = await this.tagRepository.findOneOrFail(tagId) + } + catch { + throw new NotFoundException('Tag could not found by given id') + } + + await this.titleRepository.deleteTagFromTitle(tag.name) + await this.tagRepository.deleteTag(tag) + + return { status: 'ok', message: 'Tag has been deleted' } + } } \ No newline at end of file From ced2fe466a58a5bdf15b7ccee2a7a5d4a794ae0a Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Mon, 28 Sep 2020 20:17:58 +0300 Subject: [PATCH 14/42] [server] Finalize getTrendingTags() --- .../shared/Repositories/tags.repository.ts | 19 +++++++++++++++++++ server/src/v1/Tag/tag.controller.ts | 4 ++-- server/src/v1/Tag/tag.service.ts | 9 ++++++--- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/server/src/shared/Repositories/tags.repository.ts b/server/src/shared/Repositories/tags.repository.ts index 9afe9118..2c42925c 100644 --- a/server/src/shared/Repositories/tags.repository.ts +++ b/server/src/shared/Repositories/tags.repository.ts @@ -7,6 +7,25 @@ import { TagsEntity } from '../Entities/tags.entity' @EntityRepository(TagsEntity) export class TagsRepository extends Repository { + async getTrendingTags(): Promise<{ tags: TagsEntity[], count: number }> { + const [tags, total] = await this.findAndCount({ + where: { + updated_at: { + // Last 24 hours + $gte: new Date(new Date().setDate(new Date().getDate() - 1)) + } + }, + order: { + popularity_ratio: 'DESC', + updated_at: 'DESC' + }, + take: 30, + skip: 0, + }) + + return { tags, count: total } + } + async tagActionOnTitleCreate(tagName: string): Promise { const tag: any = await this.findOne({ name: tagName }) diff --git a/server/src/v1/Tag/tag.controller.ts b/server/src/v1/Tag/tag.controller.ts index abb81a42..f20fbc06 100644 --- a/server/src/v1/Tag/tag.controller.ts +++ b/server/src/v1/Tag/tag.controller.ts @@ -22,8 +22,8 @@ export class TagController { @ApiBearerAuth() @Get('trending') - getString(): Promise { - return this.tagService.getTrending() + getString(): Promise { + return this.tagService.getTrendingTags() } @ApiBearerAuth() diff --git a/server/src/v1/Tag/tag.service.ts b/server/src/v1/Tag/tag.service.ts index 56823a69..2ce31a32 100644 --- a/server/src/v1/Tag/tag.service.ts +++ b/server/src/v1/Tag/tag.service.ts @@ -39,9 +39,12 @@ export class TagService { return serializerService.serializeResponse('tag_detail', tag) } - async getTrending(): Promise { - // TODO - return 'hey' + async getTrendingTags(): Promise { + const result: { + tags: TagsEntity[], + count: number + } = await this.tagRepository.getTrendingTags() + return serializerService.serializeResponse('trending_tag_list', result) } async deleteTag(tagId: string): Promise { From 1eb772be50024260434b447a9b0924a1e8be07b4 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Mon, 28 Sep 2020 21:37:49 +0300 Subject: [PATCH 15/42] [server] some optimizations --- server/src/v1/Tag/tag.controller.ts | 2 +- server/src/v1/Title/Controller/title.controller.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/v1/Tag/tag.controller.ts b/server/src/v1/Tag/tag.controller.ts index f20fbc06..77925114 100644 --- a/server/src/v1/Tag/tag.controller.ts +++ b/server/src/v1/Tag/tag.controller.ts @@ -16,7 +16,7 @@ export class TagController { constructor(private readonly tagService: TagService) {} @Get(':tagId') - getCategory(@Param('tagId') tagId: string): Promise { + getTag(@Param('tagId') tagId: string): Promise { return this.tagService.getTag(tagId) } diff --git a/server/src/v1/Title/Controller/title.controller.ts b/server/src/v1/Title/Controller/title.controller.ts index b8f08563..a66d27ef 100644 --- a/server/src/v1/Title/Controller/title.controller.ts +++ b/server/src/v1/Title/Controller/title.controller.ts @@ -59,7 +59,7 @@ export class TitleController { skip: number, } ): Promise { - if (query.tags) query.tags = query.tags.split(',') + if (query.tags?.split) query.tags = query.tags.split(',') return this.titleService.getTitleList(query) } From bc54a9c60585ff801a4ff5cb91efec9df0e4742c Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Mon, 28 Sep 2020 22:35:24 +0300 Subject: [PATCH 16/42] [client] Add new package 'string-to-color' --- client/package-lock.json | 43 ++++++++++++++++++++++++++++++++++++++++ client/package.json | 1 + 2 files changed, 44 insertions(+) diff --git a/client/package-lock.json b/client/package-lock.json index 2cbf06f2..eda7849e 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -2594,6 +2594,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -4020,6 +4025,11 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" }, + "hex-rgb": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hex-rgb/-/hex-rgb-4.2.0.tgz", + "integrity": "sha512-I7DkKeQ2kR2uyqgbxPgNgClH/rfs1ioKZhZW8VTIAirsxCR5EyhYeywgZbhMScgUbKCkgo6bb6JwA0CLTn9beA==" + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -4555,16 +4565,31 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=" + }, "lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" }, + "lodash.trimstart": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.trimstart/-/lodash.trimstart-4.5.1.tgz", + "integrity": "sha1-j/TexTLYJIavWVc8OURZFOlEp/E=" + }, "lodash.upperfirst": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", "integrity": "sha1-E2Xt9DFIBIHvDRxolXpe2Z1J984=" }, + "lodash.words": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.words/-/lodash.words-4.2.0.tgz", + "integrity": "sha1-Xs/q+Oz4rKqODIOGKV8Zk8nPQDY=" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -7138,6 +7163,11 @@ "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=" }, + "rgb-hex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-3.0.0.tgz", + "integrity": "sha512-8h7ZcwxCBDKvchSWbWngJuSCqJGQ6nDuLLg+QcRyQDbX9jMWt+PpPeXAhSla0GOooEomk3lCprUpGkMdsLjKyg==" + }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -7653,6 +7683,19 @@ "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=" }, + "string-to-color": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/string-to-color/-/string-to-color-2.2.2.tgz", + "integrity": "sha512-XeA2goP7PNsSlz8RRn6KhYswnMf5Tl+38ajfy8n4oZJyMGC4qqKgHNHsZ/3qwvr42NRIjf9eSr721SyetDeMkA==", + "requires": { + "colornames": "^1.1.1", + "hex-rgb": "^4.1.0", + "lodash.padend": "^4.6.1", + "lodash.trimstart": "^4.5.1", + "lodash.words": "^4.2.0", + "rgb-hex": "^3.0.0" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", diff --git a/client/package.json b/client/package.json index ef4cabcb..c835a7b3 100644 --- a/client/package.json +++ b/client/package.json @@ -37,6 +37,7 @@ "redux-persist": "^6.0.0", "redux-thunk": "^2.3.0", "socket.io-client": "^2.3.0", + "string-to-color": "^2.2.2", "webpack-filter-warnings-plugin": "1.2.1" }, "devDependencies": { From b1e2b8e1e9e4d81beb98149647087c1d5b2754e8 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Wed, 30 Sep 2020 21:56:53 +0300 Subject: [PATCH 17/42] [server] Update tags on titleUpdate --- .../shared/Repositories/tags.repository.ts | 22 ++++++++++++++++--- server/src/v1/Title/Dto/update-title.dto.ts | 1 + server/src/v1/Title/Service/title.service.ts | 15 ++++++++----- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/server/src/shared/Repositories/tags.repository.ts b/server/src/shared/Repositories/tags.repository.ts index 2c42925c..5c8f5f4c 100644 --- a/server/src/shared/Repositories/tags.repository.ts +++ b/server/src/shared/Repositories/tags.repository.ts @@ -26,18 +26,19 @@ export class TagsRepository extends Repository { return { tags, count: total } } - async tagActionOnTitleCreate(tagName: string): Promise { - const tag: any = await this.findOne({ name: tagName }) + async tagActionOnTitleCreateOrUpdate(tagName: string): Promise { + const tag = await this.findOne({ name: tagName }) if (!tag) { this.save({ name: tagName, popularity_ratio: 0.01, - total_title: 0 + total_title: 1 }) } else { + // @ts-ignore const diff = new Date().getTime() - tag.updated_at const diffAsMin = Math.round((diff / 1000) / 60) @@ -51,6 +52,21 @@ export class TagsRepository extends Repository { return } + async updateTagWhenRemovedFromTitle(tagName: string): Promise { + const tag = await this.findOne({ name: tagName }) + if (!tag) return + + if (tag.total_title > 1) { + tag.total_title-- + if (tag.popularity_ratio > 0.01) (tag.popularity_ratio -= 0.01).toFixed(1) + tag.updated_at = tag.updated_at + this.save(tag) + } + else this.deleteTag(tag) + + return + } + async deleteTag(tag: TagsEntity): Promise { await this.delete(tag) return diff --git a/server/src/v1/Title/Dto/update-title.dto.ts b/server/src/v1/Title/Dto/update-title.dto.ts index 8237e11b..3b08ce28 100644 --- a/server/src/v1/Title/Dto/update-title.dto.ts +++ b/server/src/v1/Title/Dto/update-title.dto.ts @@ -9,6 +9,7 @@ export class UpdateTitleDto { required: true, example: 'Phone Y', }) + @IsOptional() @IsNotEmpty() @MaxLength(60) name: string diff --git a/server/src/v1/Title/Service/title.service.ts b/server/src/v1/Title/Service/title.service.ts index 57f3d60f..841e135c 100644 --- a/server/src/v1/Title/Service/title.service.ts +++ b/server/src/v1/Title/Service/title.service.ts @@ -89,11 +89,11 @@ export class TitleService { const newTitle: TitlesEntity = await this.titlesRepository.createTitle(openedBy, dto) if (buffer) this.awsService.uploadImage(String(newTitle.id), 'titles', buffer) - if (configService.isProduction()) sitemapManipulationService.addToIndexedSitemap(newTitle.slug, new Date().toJSON().slice(0,10)) + if (configService.isProduction()) sitemapManipulationService.addToIndexedSitemap(newTitle.slug, new Date().toJSON().slice(0, 10)) return serializerService.serializeResponse('title_detail', newTitle) }) - dto.tags.forEach(async element => this.tagsRepository.tagActionOnTitleCreate(element)) + dto.tags.forEach(async element => this.tagsRepository.tagActionOnTitleCreateOrUpdate(element)) return result } @@ -149,8 +149,8 @@ export class TitleService { } async updateTitle(updatedBy: string, titleId: string, dto: UpdateTitleDto): Promise { - dto.name = dto.name.replace(/^\s+|\s+$/g, '') - if (dto.name.length === 0) throw new BadRequestException('Title name can not be whitespace') + if (dto.name) dto.name = dto.name.replace(/^\s+|\s+$/g, '') + if (dto.name?.length === 0) throw new BadRequestException('Title name can not be whitespace') if (!this.validator.isMongoId(titleId)) throw new BadRequestException('Id must be a type of MongoId') @@ -161,8 +161,13 @@ export class TitleService { throw new NotFoundException('Title could not found by given id') } + if (dto.tags) { + dto.tags.forEach(async element => this.tagsRepository.tagActionOnTitleCreateOrUpdate(element)) + title.tags.forEach(async element => this.tagsRepository.updateTagWhenRemovedFromTitle(element)) + } + const updatedTitle: TitlesEntity = await this.titlesRepository.updateTitle(updatedBy, title, dto) - if (configService.isProduction()) sitemapManipulationService.addToIndexedSitemap(updatedTitle.slug, new Date().toJSON().slice(0,10)) + if (configService.isProduction()) sitemapManipulationService.addToIndexedSitemap(updatedTitle.slug, new Date().toJSON().slice(0, 10)) return serializerService.serializeResponse('title_detail', updatedTitle) } From 8a83ee035ed47f9154ccfbd70950d98ef09db096 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Thu, 1 Oct 2020 22:32:46 +0300 Subject: [PATCH 18/42] Update tag style and fetch trendingTags --- client/src/@types/api/Category/index.d.ts | 23 ------- client/src/@types/api/Tag/index.d.ts | 21 ++++++ client/src/@types/api/index.d.ts | 2 +- .../@types/initializations/feeds/index.d.ts | 4 +- client/src/@types/pages/feeds/index.d.ts | 2 +- client/src/pages/index.tsx | 69 ++++++++++--------- .../services/api/{Category => Tag}/index.ts | 2 +- client/src/services/api/Title/index.ts | 4 +- client/src/services/api/index.ts | 2 +- .../services/initializations/feeds/index.ts | 10 +-- client/src/styles/antd/global.less | 10 +-- 11 files changed, 75 insertions(+), 74 deletions(-) delete mode 100644 client/src/@types/api/Category/index.d.ts create mode 100644 client/src/@types/api/Tag/index.d.ts rename client/src/services/api/{Category => Tag}/index.ts (78%) diff --git a/client/src/@types/api/Category/index.d.ts b/client/src/@types/api/Category/index.d.ts deleted file mode 100644 index a9bbc11d..00000000 --- a/client/src/@types/api/Category/index.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -export interface CategoryResponseData { - type: 'category_detail', - attributes: { - id: string, - name: string, - is_leaf: boolean, - parent_category: string, - ancestors: string[], - created_at: string, - updated_at: string - } -} - -export interface TrendingCategoriesResponseData { - id: string, - name: string, - is_leaf: boolean, - parent_category: string, - ancestors: string[], - created_at: string, - updated_at: string -} - diff --git a/client/src/@types/api/Tag/index.d.ts b/client/src/@types/api/Tag/index.d.ts new file mode 100644 index 00000000..459b84a2 --- /dev/null +++ b/client/src/@types/api/Tag/index.d.ts @@ -0,0 +1,21 @@ +export interface TagResponseData { + type: 'tag_detail', + attributes: { + _id: string, + name: string, + total_title: number, + popularity_ratio: number, + created_at: string, + updated_at: string + } +} + +export interface TrendingTagsResponseData { + _id: string, + name: string, + total_title: number, + popularity_ratio: number, + created_at: string, + updated_at: string +} + diff --git a/client/src/@types/api/index.d.ts b/client/src/@types/api/index.d.ts index daea2830..0ec8f729 100644 --- a/client/src/@types/api/index.d.ts +++ b/client/src/@types/api/index.d.ts @@ -1,5 +1,5 @@ export * from './Title' -export * from './Category' +export * from './Tag' export * from './Entry' export * from './Message' export * from './User' diff --git a/client/src/@types/initializations/feeds/index.d.ts b/client/src/@types/initializations/feeds/index.d.ts index 72fe8d62..943d1a45 100644 --- a/client/src/@types/initializations/feeds/index.d.ts +++ b/client/src/@types/initializations/feeds/index.d.ts @@ -1,6 +1,6 @@ // Local files -import { TrendingCategoriesResponseData } from '@/@types/api' +import { TrendingTagsResponseData } from '@/@types/api' export interface FeedsPageInitials { - trendingCategories: TrendingCategoriesResponseData[] + trendingTags: TrendingTagsResponseData[] } \ No newline at end of file diff --git a/client/src/@types/pages/feeds/index.d.ts b/client/src/@types/pages/feeds/index.d.ts index 514f3741..2cb22f0a 100644 --- a/client/src/@types/pages/feeds/index.d.ts +++ b/client/src/@types/pages/feeds/index.d.ts @@ -3,7 +3,7 @@ export interface FeedList { name: string, slug: string, href: string, - categoryName: string, + tags: string[], entryCount: number, featuredEntry: { id: string, diff --git a/client/src/pages/index.tsx b/client/src/pages/index.tsx index 6016c423..b8270516 100644 --- a/client/src/pages/index.tsx +++ b/client/src/pages/index.tsx @@ -8,14 +8,15 @@ import { AxiosError, AxiosResponse } from 'axios' import { NextPage } from 'next' import { Img } from 'react-image' import Link from 'next/link' +import * as stringToColor from 'string-to-color' // Local files -import { fetchAllFeeds, fetchFeaturedEntryByTitleId, fetchTrendingCategories, fetchOneCategory } from '@/services/api' +import { fetchAllFeeds, fetchFeaturedEntryByTitleId, fetchTrendingTags, fetchOneCategory } from '@/services/api' import { CategorySelect } from '@/components/global/CategorySelect' import { API_URL, Guest } from '@/../config/constants' import { PageHelmet } from '@/components/global/PageHelmet' import { AdditionalBlock } from '@/components/pages/feeds/AdditionalBlock' -import { TrendingCategoriesResponseData } from '@/@types/api' +import { TrendingTagsResponseData } from '@/@types/api' import { FeedList } from '@/@types/pages/feeds' import { getFeedsPageInitialValues } from '@/services/initializations' import { FeedsPageInitials } from '@/@types/initializations' @@ -25,8 +26,8 @@ import FlowHeader from '@/components/pages/feeds/FlowHeader' const Homepage: NextPage = (props): JSX.Element => { const [displayFilterModal, setDisplayFilterModal] = useState(false) - const [trendingCategories, setTrendingCategories] = useState(props.trendingCategories) - const [categoryFilter, setCategoryFilter] = useState(undefined) + const [trendingTags, setTrendingTags] = useState(props.trendingTags) + const [tagFilter, setTagFilter] = useState(undefined) const [feedList, setFeed] = useState([]) const [sortBy, setSortBy] = useState<'hot' | 'top' | undefined>(undefined) const [skipValueForPagination, setSkipValueForPagination] = useState(0) @@ -35,12 +36,12 @@ const Homepage: NextPage = (props): JSX.Element => { const [isLoading, setIsLoading] = useState(true) const [isLoadMoreTriggered, setIsLoadMoreTriggered] = useState(false) - const handleCategoryFilterSet = (id) => { + const handleTagFilterSet = (id) => { setIsLoading(true) setFeed([]) setSkipValueForPagination(0) setIsJustInitialized(false) - setCategoryFilter(id) + setTagFilter(id) } const handleSortBySet = (val) => { @@ -52,15 +53,15 @@ const Homepage: NextPage = (props): JSX.Element => { } const handleDataFetching = async (): Promise => { - if (!trendingCategories) { - fetchTrendingCategories() - .then(res => setTrendingCategories(res.data.attributes.categories)) + if (!trendingTags) { + fetchTrendingTags() + .then(res => setTrendingTags(res.data.attributes.tags)) } - await fetchAllFeeds(skipValueForPagination, undefined, categoryFilter, sortBy) + await fetchAllFeeds(skipValueForPagination, undefined, tagFilter, sortBy) .then(async (feedsResponse: AxiosResponse) => { const promises = await feedsResponse.data.attributes.titles.map(async (title: any) => { - const categoryName = await fetchOneCategory(title.category_id).then(({ data }) => data.attributes.name) + const categoryName = null // await fetchOneCategory(title.category_id).then(({ data }) => data.attributes.name) const featuredEntry: any = await fetchFeaturedEntryByTitleId(title.id).then(featuredEntryResponse => featuredEntryResponse.data.attributes) .catch(_error => { }) @@ -69,6 +70,7 @@ const Homepage: NextPage = (props): JSX.Element => { slug: title.slug, name: title.name, href: `/${title.slug}`, + tags: title.tags, categoryName: categoryName, createdAt: title.created_at, updatedAt: title.updated_at, @@ -167,7 +169,17 @@ const Homepage: NextPage = (props): JSX.Element => { alt="Title Image" /> } - description={

{item.categoryName.toUpperCase()}

} + description={ + item.tags.map(tag => { + return ( +
+ 0xffffff / 2) ? '#000' : '#fff', background: (parseInt(stringToColor(tag).replace('#', ''), 16) > 0xffffff / 2) ? '#fff' : '#000', opacity: 0.9 }}> + #{tag} + +
+ ) + }) + } /> {item.featuredEntry ? @@ -180,9 +192,8 @@ const Homepage: NextPage = (props): JSX.Element => { ) } - const handleTrendingCategoriesRender = (): JSX.Element => { - - if (!trendingCategories) { + const handleTrendingTagsRender = (): JSX.Element => { + if (!trendingTags) { return (
@@ -191,22 +202,14 @@ const Homepage: NextPage = (props): JSX.Element => { } return ( -
- {trendingCategories.map(category => { +
+ {trendingTags.map(tag => { return ( - - - {category.name.toUpperCase()} +
alert(tag._id)} className={'custom-tag'} style={{ backgroundColor: stringToColor(tag.name), cursor: 'pointer' }}> + 0xffffff / 2) ? '#000' : '#fff', background: (parseInt(stringToColor(tag.name).replace('#', ''), 16) > 0xffffff / 2) ? '#fff' : '#000', opacity: 0.9 }}> + #{tag.name} -
) })}
@@ -215,7 +218,7 @@ const Homepage: NextPage = (props): JSX.Element => { useEffect(() => { handleDataFetching() - }, [skipValueForPagination, categoryFilter, sortBy, isJustInitialized]) + }, [skipValueForPagination, tagFilter, sortBy, isJustInitialized]) const handleFetchMore = (): void => { setIsLoadMoreTriggered(true) @@ -248,7 +251,7 @@ const Homepage: NextPage = (props): JSX.Element => { > handleCategoryFilterSet(String(id))} + onSelect={(id): void => handleTagFilterSet(String(id))} style={{ width: '100%' }} placeHolder="All Categories" allowClear @@ -278,7 +281,7 @@ const Homepage: NextPage = (props): JSX.Element => { setDisplayFilterModal(true)} setSortBy={(val: 'top' | 'hot' | undefined): void => handleSortBySet(val)} - resetCategoryFilter={(): void => handleCategoryFilterSet(undefined)} + resetCategoryFilter={(): void => handleTagFilterSet(undefined)} sortBy={sortBy} /> {handleModalScreen()} @@ -287,7 +290,7 @@ const Homepage: NextPage = (props): JSX.Element => { - {handleTrendingCategoriesRender()} + {handleTrendingTagsRender()} diff --git a/client/src/services/api/Category/index.ts b/client/src/services/api/Tag/index.ts similarity index 78% rename from client/src/services/api/Category/index.ts rename to client/src/services/api/Tag/index.ts index e07539be..df91dc1c 100644 --- a/client/src/services/api/Category/index.ts +++ b/client/src/services/api/Tag/index.ts @@ -6,4 +6,4 @@ export const fetchMainCategories = (): Promise => axios.get('/v1/ export const fetchChildCategories = (categoryId: string): Promise => axios.get(`/v1/category/${categoryId}/child-categories`) -export const fetchTrendingCategories = (): Promise => axios.get('/v1/category/trending-categories') +export const fetchTrendingTags = (): Promise => axios.get('/v1/tag/trending') diff --git a/client/src/services/api/Title/index.ts b/client/src/services/api/Title/index.ts index 5e8dd733..7eb9622e 100644 --- a/client/src/services/api/Title/index.ts +++ b/client/src/services/api/Title/index.ts @@ -4,13 +4,13 @@ import axios, { AxiosResponse } from 'axios' export const fetchAllFeeds = ( skip: number, username: string | undefined, - categoryIds: string | undefined, + tags: string | undefined, sortBy?: 'hot' | 'top' | undefined ): Promise => axios.get( '/v1/title/all', { params: { ...username && { author: username }, - ...categoryIds && { categoryIds }, + ...tags && { tags }, ...sortBy && { sortBy }, skip } diff --git a/client/src/services/api/index.ts b/client/src/services/api/index.ts index 1189cab9..88f17e7c 100644 --- a/client/src/services/api/index.ts +++ b/client/src/services/api/index.ts @@ -7,7 +7,7 @@ import { API_URL } from '@/../config/constants' axios.defaults.baseURL = API_URL export * from './Auth' -export * from './Category' +export * from './Tag' export * from './Entry' export * from './Message' export * from './Title' diff --git a/client/src/services/initializations/feeds/index.ts b/client/src/services/initializations/feeds/index.ts index f425ea5e..c76356cf 100644 --- a/client/src/services/initializations/feeds/index.ts +++ b/client/src/services/initializations/feeds/index.ts @@ -1,13 +1,13 @@ // Local files -import { fetchTrendingCategories } from '@/services/api' -import { TrendingCategoriesResponseData } from '@/@types/api' +import { fetchTrendingTags } from '@/services/api' +import { TrendingTagsResponseData } from '@/@types/api' import { FeedsPageInitials } from '@/@types/initializations' export const getFeedsPageInitialValues = async (): Promise => { - let trendingCategories: TrendingCategoriesResponseData[] + let trendingTags: TrendingTagsResponseData[] - await fetchTrendingCategories().then(res => trendingCategories = res.data.attributes.categories) + await fetchTrendingTags().then(res => trendingTags = res.data.attributes.tags) .catch((_error) => { }) - return { trendingCategories } + return { trendingTags } } \ No newline at end of file diff --git a/client/src/styles/antd/global.less b/client/src/styles/antd/global.less index e35704d8..3bf15a8d 100644 --- a/client/src/styles/antd/global.less +++ b/client/src/styles/antd/global.less @@ -19,12 +19,12 @@ body, } .custom-tag { - background: #6ec49a; font-weight: bold; - color: white; - padding: 3px 5px; - display: inline; - line-height: 1.75; + opacity: 0.85; + padding: 0px 5px 0px 5px; + margin: 0px 0px 5px 3px; + border-radius: 4px; + display: inline-table; font-family: 'Courier New', Courier, monospace; } From c74bb8b43c19a6b078bca715e8bfacc14f19d24e Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Fri, 2 Oct 2020 23:48:31 +0300 Subject: [PATCH 19/42] Add new block for Tag searching --- client/src/pages/index.tsx | 26 ++++++++++++++++---------- client/src/styles/antd/global.less | 4 ++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/client/src/pages/index.tsx b/client/src/pages/index.tsx index b8270516..476f6507 100644 --- a/client/src/pages/index.tsx +++ b/client/src/pages/index.tsx @@ -1,6 +1,6 @@ // Antd dependencies -import { Button, Card, List, message, BackTop, Row, Col, Typography, Modal, Skeleton } from 'antd' -import { LoadingOutlined, ArrowUpOutlined, EyeOutlined } from '@ant-design/icons' +import { Button, Card, List, message, BackTop, Row, Col, Typography, Modal, Skeleton, Select } from 'antd' +import { LoadingOutlined, ArrowUpOutlined } from '@ant-design/icons' // Other dependencies import React, { useEffect, useState } from 'react' @@ -11,7 +11,7 @@ import Link from 'next/link' import * as stringToColor from 'string-to-color' // Local files -import { fetchAllFeeds, fetchFeaturedEntryByTitleId, fetchTrendingTags, fetchOneCategory } from '@/services/api' +import { fetchAllFeeds, fetchFeaturedEntryByTitleId, fetchTrendingTags } from '@/services/api' import { CategorySelect } from '@/components/global/CategorySelect' import { API_URL, Guest } from '@/../config/constants' import { PageHelmet } from '@/components/global/PageHelmet' @@ -27,7 +27,7 @@ import FlowHeader from '@/components/pages/feeds/FlowHeader' const Homepage: NextPage = (props): JSX.Element => { const [displayFilterModal, setDisplayFilterModal] = useState(false) const [trendingTags, setTrendingTags] = useState(props.trendingTags) - const [tagFilter, setTagFilter] = useState(undefined) + const [tagFilter, setTagFilter] = useState('') const [feedList, setFeed] = useState([]) const [sortBy, setSortBy] = useState<'hot' | 'top' | undefined>(undefined) const [skipValueForPagination, setSkipValueForPagination] = useState(0) @@ -36,12 +36,12 @@ const Homepage: NextPage = (props): JSX.Element => { const [isLoading, setIsLoading] = useState(true) const [isLoadMoreTriggered, setIsLoadMoreTriggered] = useState(false) - const handleTagFilterSet = (id) => { + const handleTagFilterSet = (name: string) => { setIsLoading(true) setFeed([]) setSkipValueForPagination(0) setIsJustInitialized(false) - setTagFilter(id) + setTagFilter(name) } const handleSortBySet = (val) => { @@ -60,6 +60,7 @@ const Homepage: NextPage = (props): JSX.Element => { await fetchAllFeeds(skipValueForPagination, undefined, tagFilter, sortBy) .then(async (feedsResponse: AxiosResponse) => { + console.log('asdas') const promises = await feedsResponse.data.attributes.titles.map(async (title: any) => { const categoryName = null // await fetchOneCategory(title.category_id).then(({ data }) => data.attributes.name) const featuredEntry: any = await fetchFeaturedEntryByTitleId(title.id).then(featuredEntryResponse => featuredEntryResponse.data.attributes) @@ -97,7 +98,8 @@ const Homepage: NextPage = (props): JSX.Element => { * Updating feeds should be refactored. */ // @ts-ignore - result.map(item => setFeed((feedList: FeedList[]) => [...feedList, item])) + // result.map(item => setFeed((feedList: FeedList[]) => [...feedList, item])) + setFeed(result) if (feedsResponse.data.attributes.count > (feedsResponse.data.attributes.titles.length + skipValueForPagination)) setCanLoadMore(true) else setCanLoadMore(false) @@ -205,7 +207,7 @@ const Homepage: NextPage = (props): JSX.Element => {
{trendingTags.map(tag => { return ( -
alert(tag._id)} className={'custom-tag'} style={{ backgroundColor: stringToColor(tag.name), cursor: 'pointer' }}> +
setTagFilter(`${tagFilter},${tag.name}`)} className={'custom-tag'} style={{ backgroundColor: stringToColor(tag.name), cursor: 'pointer' }}> 0xffffff / 2) ? '#000' : '#fff', background: (parseInt(stringToColor(tag.name).replace('#', ''), 16) > 0xffffff / 2) ? '#fff' : '#000', opacity: 0.9 }}> #{tag.name} @@ -281,7 +283,7 @@ const Homepage: NextPage = (props): JSX.Element => { setDisplayFilterModal(true)} setSortBy={(val: 'top' | 'hot' | undefined): void => handleSortBySet(val)} - resetCategoryFilter={(): void => handleTagFilterSet(undefined)} + resetCategoryFilter={(): void => handleTagFilterSet('')} sortBy={sortBy} /> {handleModalScreen()} @@ -289,9 +291,13 @@ const Homepage: NextPage = (props): JSX.Element => { - + {handleTrendingTagsRender()} + + + diff --git a/client/src/styles/antd/global.less b/client/src/styles/antd/global.less index 3bf15a8d..e346cf90 100644 --- a/client/src/styles/antd/global.less +++ b/client/src/styles/antd/global.less @@ -32,6 +32,10 @@ body, border: solid rgba(0, 0, 0, .4); border-radius: 5px !important; border-width: 0.5px; + + .ant-card-head { + border: 0; + } } .ant-tabs > .ant-tabs-nav .ant-tabs-nav-more, .ant-tabs > div > .ant-tabs-nav .ant-tabs-nav-more { From 593856d0394d2240d26eb57c70e9eda409321395 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sat, 3 Oct 2020 09:42:54 +0300 Subject: [PATCH 20/42] [server] Create tag/search endpoint --- server/src/shared/Repositories/tags.repository.ts | 14 ++++++++++++++ server/src/v1/Tag/tag.controller.ts | 7 ++++++- server/src/v1/Tag/tag.service.ts | 6 ++++++ server/src/v1/Title/Dto/create-title.dto.ts | 8 +++++++- server/src/v1/Title/Dto/update-title.dto.ts | 8 +++++++- 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/server/src/shared/Repositories/tags.repository.ts b/server/src/shared/Repositories/tags.repository.ts index 5c8f5f4c..cd04c181 100644 --- a/server/src/shared/Repositories/tags.repository.ts +++ b/server/src/shared/Repositories/tags.repository.ts @@ -26,6 +26,20 @@ export class TagsRepository extends Repository { return { tags, count: total } } + async searchTag(searchValue: string): Promise<{ tags: TagsEntity[] }> { + const [tags] = await this.findAndCount({ + where: { + name: new RegExp(searchValue, 'i') + }, + take: 25, + order: { + popularity_ratio: 'DESC' + } + }) + + return { tags } + } + async tagActionOnTitleCreateOrUpdate(tagName: string): Promise { const tag = await this.findOne({ name: tagName }) diff --git a/server/src/v1/Tag/tag.controller.ts b/server/src/v1/Tag/tag.controller.ts index 77925114..97c44a9b 100644 --- a/server/src/v1/Tag/tag.controller.ts +++ b/server/src/v1/Tag/tag.controller.ts @@ -1,5 +1,5 @@ // Nest dependencies -import { Controller, Delete, Get, Param, UseGuards } from '@nestjs/common' +import { Controller, Delete, Get, Param, Query, UseGuards } from '@nestjs/common' import { AuthGuard } from '@nestjs/passport' import { ApiTags, ApiBearerAuth } from '@nestjs/swagger' @@ -20,6 +20,11 @@ export class TagController { return this.tagService.getTag(tagId) } + @Get('search') + searchTag(@Query('searchValue') searchValue: string): Promise { + return this.tagService.searchTag(searchValue) + } + @ApiBearerAuth() @Get('trending') getString(): Promise { diff --git a/server/src/v1/Tag/tag.service.ts b/server/src/v1/Tag/tag.service.ts index 2ce31a32..bcd955a8 100644 --- a/server/src/v1/Tag/tag.service.ts +++ b/server/src/v1/Tag/tag.service.ts @@ -39,6 +39,12 @@ export class TagService { return serializerService.serializeResponse('tag_detail', tag) } + async searchTag(searchValue: string): Promise { + if (searchValue.length < 3) throw new BadRequestException('Search value must be greater than 2 characters') + const result = await this.tagRepository.searchTag(searchValue) + return serializerService.serializeResponse('tag_search_result', result) + } + async getTrendingTags(): Promise { const result: { tags: TagsEntity[], diff --git a/server/src/v1/Title/Dto/create-title.dto.ts b/server/src/v1/Title/Dto/create-title.dto.ts index 15e82486..5aafd84a 100644 --- a/server/src/v1/Title/Dto/create-title.dto.ts +++ b/server/src/v1/Title/Dto/create-title.dto.ts @@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger' // Other dependencies -import { IsNotEmpty, Length, IsArray } from 'class-validator' +import { IsNotEmpty, Length, IsArray, MinLength, NotContains } from 'class-validator' export class CreateTitleDto { @ApiProperty({ @@ -17,6 +17,12 @@ export class CreateTitleDto { required: true, example: '["electronics", "phone", "samsung"]' }) + @NotContains(' ', { + each: true, + }) + @MinLength(3, { + each: true, + }) @IsArray() tags: string[] } diff --git a/server/src/v1/Title/Dto/update-title.dto.ts b/server/src/v1/Title/Dto/update-title.dto.ts index 3b08ce28..9852d89d 100644 --- a/server/src/v1/Title/Dto/update-title.dto.ts +++ b/server/src/v1/Title/Dto/update-title.dto.ts @@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger' // Other dependencies -import { IsNotEmpty, MaxLength, IsOptional } from 'class-validator' +import { IsNotEmpty, MaxLength, IsOptional, MinLength, NotContains } from 'class-validator' export class UpdateTitleDto { @ApiProperty({ @@ -18,6 +18,12 @@ export class UpdateTitleDto { required: false, example: '"electronics", "phone", "samsung"' }) + @NotContains(' ', { + each: true, + }) + @MinLength(3, { + each: true, + }) @IsOptional() tags: string[] } From 0d7fac0d288cdd08ab4ff83f09b16d991ccb0f6c Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sat, 3 Oct 2020 20:15:15 +0300 Subject: [PATCH 21/42] Create new component TagSearchingBlock --- .../pages/feeds/TagSearchingBlock/index.tsx | 58 ++++++++++++++ client/src/pages/index.tsx | 76 +++++++++---------- client/src/services/api/Tag/index.ts | 2 + 3 files changed, 98 insertions(+), 38 deletions(-) create mode 100644 client/src/components/pages/feeds/TagSearchingBlock/index.tsx diff --git a/client/src/components/pages/feeds/TagSearchingBlock/index.tsx b/client/src/components/pages/feeds/TagSearchingBlock/index.tsx new file mode 100644 index 00000000..3a135189 --- /dev/null +++ b/client/src/components/pages/feeds/TagSearchingBlock/index.tsx @@ -0,0 +1,58 @@ +// Antd dependencies +import { Card, Select, Typography, Col, Divider } from 'antd' + +// Other dependencies +import React, { useEffect, useState } from 'react' +import Link from 'next/link' +import { searchTagByName } from '@/services/api' + +// Local files + +export const TagSearchingBlock = (props): JSX.Element => { + const [tagResult, setTagResult] = useState([]) + const [selectedValues, setSelectedValues] = useState(props.tagFilter) + + useEffect(() => { + setSelectedValues(props.tagFilter) + }, [props.tagFilter]) + + const handleTagSelect = (value: string): void => { + props.setTagFilter(value) + } + + const handleTagSearching = (value: string): void => { + if (value.length > 2) { + searchTagByName(value).then(({ data }) => { + const result = [] + + data.attributes.tags.map(tag => { + result.push({tag.name}) + }) + + setTagResult(result) + }) + } + } + + const handleDeSelect = (tag: string) => { + const updatedList = selectedValues.filter(value => value !== tag) + props.updateTagFilterList(updatedList.toString()) + } + + return ( + + + + ) +} diff --git a/client/src/pages/index.tsx b/client/src/pages/index.tsx index 476f6507..15d590c8 100644 --- a/client/src/pages/index.tsx +++ b/client/src/pages/index.tsx @@ -23,11 +23,12 @@ import { FeedsPageInitials } from '@/@types/initializations' import { AppLayout } from '@/layouts/AppLayout' import { ArticleListContent } from '@/components/pages/feeds/ArticleListContent' import FlowHeader from '@/components/pages/feeds/FlowHeader' +import { TagSearchingBlock } from '@/components/pages/feeds/TagSearchingBlock' const Homepage: NextPage = (props): JSX.Element => { const [displayFilterModal, setDisplayFilterModal] = useState(false) const [trendingTags, setTrendingTags] = useState(props.trendingTags) - const [tagFilter, setTagFilter] = useState('') + const [tagFilter, setTagFilter] = useState(null) const [feedList, setFeed] = useState([]) const [sortBy, setSortBy] = useState<'hot' | 'top' | undefined>(undefined) const [skipValueForPagination, setSkipValueForPagination] = useState(0) @@ -36,20 +37,34 @@ const Homepage: NextPage = (props): JSX.Element => { const [isLoading, setIsLoading] = useState(true) const [isLoadMoreTriggered, setIsLoadMoreTriggered] = useState(false) - const handleTagFilterSet = (name: string) => { + useEffect(() => { + handleDataFetching().then(() => setIsJustInitialized(false)) + }, []) + + useEffect(() => { + if (!isJustInitialized) { + handleDataFetching() + } + }, [skipValueForPagination, tagFilter, sortBy]) + + const handleFlowReset = (): void => { setIsLoading(true) setFeed([]) setSkipValueForPagination(0) - setIsJustInitialized(false) - setTagFilter(name) } - const handleSortBySet = (val) => { - setIsLoading(true) - setFeed([]) - setSkipValueForPagination(0) - setIsJustInitialized(false) - setSortBy(val) + const handleFilteringTags = (tag: string): void => { + if (tagFilter) { + if (!tagFilter.includes(tag)) { + handleFlowReset() + setTagFilter(`${tagFilter},${tag}`) + } + } + + else { + handleFlowReset() + setTagFilter(tag) + } } const handleDataFetching = async (): Promise => { @@ -60,7 +75,6 @@ const Homepage: NextPage = (props): JSX.Element => { await fetchAllFeeds(skipValueForPagination, undefined, tagFilter, sortBy) .then(async (feedsResponse: AxiosResponse) => { - console.log('asdas') const promises = await feedsResponse.data.attributes.titles.map(async (title: any) => { const categoryName = null // await fetchOneCategory(title.category_id).then(({ data }) => data.attributes.name) const featuredEntry: any = await fetchFeaturedEntryByTitleId(title.id).then(featuredEntryResponse => featuredEntryResponse.data.attributes) @@ -92,14 +106,10 @@ const Homepage: NextPage = (props): JSX.Element => { }) const result = await Promise.all(promises) - - /* TODO - * This is a workaround to fix wrong list order of Feeds Flow. - * Updating feeds should be refactored. - */ - // @ts-ignore - // result.map(item => setFeed((feedList: FeedList[]) => [...feedList, item])) - setFeed(result) + result.map((item: FeedList) => { + if (feedList.find(i => i.id === item.id)) return + setFeed((feedList: FeedList[]) => [...feedList, item]) + }) if (feedsResponse.data.attributes.count > (feedsResponse.data.attributes.titles.length + skipValueForPagination)) setCanLoadMore(true) else setCanLoadMore(false) @@ -207,7 +217,7 @@ const Homepage: NextPage = (props): JSX.Element => {
{trendingTags.map(tag => { return ( -
setTagFilter(`${tagFilter},${tag.name}`)} className={'custom-tag'} style={{ backgroundColor: stringToColor(tag.name), cursor: 'pointer' }}> +
handleFilteringTags(tag.name)} className={'custom-tag'} style={{ backgroundColor: stringToColor(tag.name), cursor: 'pointer' }}> 0xffffff / 2) ? '#000' : '#fff', background: (parseInt(stringToColor(tag.name).replace('#', ''), 16) > 0xffffff / 2) ? '#fff' : '#000', opacity: 0.9 }}> #{tag.name} @@ -218,14 +228,9 @@ const Homepage: NextPage = (props): JSX.Element => { ) } - useEffect(() => { - handleDataFetching() - }, [skipValueForPagination, tagFilter, sortBy, isJustInitialized]) - const handleFetchMore = (): void => { setIsLoadMoreTriggered(true) setSkipValueForPagination(skipValueForPagination + 10) - setIsJustInitialized(false) } const loadMore = canLoadMore && ( @@ -251,13 +256,7 @@ const Homepage: NextPage = (props): JSX.Element => { footer={null} onCancel={(): void => setDisplayFilterModal(false)} > - handleTagFilterSet(String(id))} - style={{ width: '100%' }} - placeHolder="All Categories" - allowClear - /> + ) @@ -282,8 +281,8 @@ const Homepage: NextPage = (props): JSX.Element => { > setDisplayFilterModal(true)} - setSortBy={(val: 'top' | 'hot' | undefined): void => handleSortBySet(val)} - resetCategoryFilter={(): void => handleTagFilterSet('')} + setSortBy={(val: 'top' | 'hot' | undefined): void => setSortBy(val)} + resetCategoryFilter={(): void => setTagFilter(null)} sortBy={sortBy} /> {handleModalScreen()} @@ -294,10 +293,11 @@ const Homepage: NextPage = (props): JSX.Element => { {handleTrendingTagsRender()} - - - + diff --git a/client/src/services/api/Tag/index.ts b/client/src/services/api/Tag/index.ts index df91dc1c..0c73bd3c 100644 --- a/client/src/services/api/Tag/index.ts +++ b/client/src/services/api/Tag/index.ts @@ -2,6 +2,8 @@ import axios, { AxiosResponse } from 'axios' export const fetchOneCategory = (categoryId: string): Promise => axios.get(`/v1/category/${categoryId}`) +export const searchTagByName = (searchValue: string): Promise => axios.get(`/v1/tag/search?searchValue=${searchValue}`) + export const fetchMainCategories = (): Promise => axios.get('/v1/category/main-categories') export const fetchChildCategories = (categoryId: string): Promise => axios.get(`/v1/category/${categoryId}/child-categories`) From a80683aebf20a9a8e517b3686fa720ab902de9ad Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sat, 3 Oct 2020 23:23:42 +0300 Subject: [PATCH 22/42] [client] version upgrade to 0.4-alpha --- client/package-lock.json | 2 +- client/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index eda7849e..e5995ebe 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,6 +1,6 @@ { "name": "feednext-client", - "version": "0.3.0-alpha", + "version": "0.4.0-alpha", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/client/package.json b/client/package.json index c835a7b3..34398400 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "feednext-client", - "version": "0.3.0-alpha", + "version": "0.4.0-alpha", "private": true, "description": "Client side of feednext.io", "author": "Onur Ozkan", From 2d25c1af0fff8c535aa0c44a93d57c4a6705f831 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sat, 3 Oct 2020 23:29:30 +0300 Subject: [PATCH 23/42] [client] Optimize TagSearchingBlock --- .../src/@types/components/TagSearchingBlock/index.d.ts | 6 ++++++ .../components/pages/feeds/TagSearchingBlock/index.tsx | 9 +++++---- client/src/pages/index.tsx | 4 ++-- 3 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 client/src/@types/components/TagSearchingBlock/index.d.ts diff --git a/client/src/@types/components/TagSearchingBlock/index.d.ts b/client/src/@types/components/TagSearchingBlock/index.d.ts new file mode 100644 index 00000000..f5fd9ae4 --- /dev/null +++ b/client/src/@types/components/TagSearchingBlock/index.d.ts @@ -0,0 +1,6 @@ +export interface TagSearchingBlockProps { + tagFilter: string[] + setTagFilter: (tag: string) => void + beforeTagDeSelect: () => void + updateTagFilterList: React.Dispatch> +} \ No newline at end of file diff --git a/client/src/components/pages/feeds/TagSearchingBlock/index.tsx b/client/src/components/pages/feeds/TagSearchingBlock/index.tsx index 3a135189..6113460f 100644 --- a/client/src/components/pages/feeds/TagSearchingBlock/index.tsx +++ b/client/src/components/pages/feeds/TagSearchingBlock/index.tsx @@ -1,14 +1,14 @@ // Antd dependencies -import { Card, Select, Typography, Col, Divider } from 'antd' +import { Card, Select } from 'antd' // Other dependencies import React, { useEffect, useState } from 'react' -import Link from 'next/link' -import { searchTagByName } from '@/services/api' // Local files +import { searchTagByName } from '@/services/api' +import { TagSearchingBlockProps } from '@/@types/components/TagSearchingBlock' -export const TagSearchingBlock = (props): JSX.Element => { +export const TagSearchingBlock: React.FC = (props): JSX.Element => { const [tagResult, setTagResult] = useState([]) const [selectedValues, setSelectedValues] = useState(props.tagFilter) @@ -35,6 +35,7 @@ export const TagSearchingBlock = (props): JSX.Element => { } const handleDeSelect = (tag: string) => { + props.beforeTagDeSelect() const updatedList = selectedValues.filter(value => value !== tag) props.updateTagFilterList(updatedList.toString()) } diff --git a/client/src/pages/index.tsx b/client/src/pages/index.tsx index 15d590c8..d7f9438e 100644 --- a/client/src/pages/index.tsx +++ b/client/src/pages/index.tsx @@ -12,7 +12,6 @@ import * as stringToColor from 'string-to-color' // Local files import { fetchAllFeeds, fetchFeaturedEntryByTitleId, fetchTrendingTags } from '@/services/api' -import { CategorySelect } from '@/components/global/CategorySelect' import { API_URL, Guest } from '@/../config/constants' import { PageHelmet } from '@/components/global/PageHelmet' import { AdditionalBlock } from '@/components/pages/feeds/AdditionalBlock' @@ -55,7 +54,7 @@ const Homepage: NextPage = (props): JSX.Element => { const handleFilteringTags = (tag: string): void => { if (tagFilter) { - if (!tagFilter.includes(tag)) { + if (tagFilter.split(',').includes(tag) === false) { handleFlowReset() setTagFilter(`${tagFilter},${tag}`) } @@ -296,6 +295,7 @@ const Homepage: NextPage = (props): JSX.Element => { handleFlowReset()} updateTagFilterList={setTagFilter} /> From 5af975b2c806bb2dff2de0ea93546c9e6e5941df Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 4 Oct 2020 09:29:32 +0300 Subject: [PATCH 24/42] [client] Upgrade antd version to 4.6 --- client/package-lock.json | 598 ++++++++++++++++++++++----------------- client/package.json | 2 +- 2 files changed, 334 insertions(+), 266 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index e5995ebe..85878fef 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -180,9 +180,9 @@ "integrity": "sha512-Fi03PfuUqRs76aI3UWYpP864lkrfPo0hluwGqh7NJdLhvH4iRDc3jbJqZIvRDLHKbXrvAfPPV3+zjUccfFvWOQ==" }, "@ant-design/react-slick": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-0.27.0.tgz", - "integrity": "sha512-dq/p/1oKgew99cNrhT6/BA4v7c7nAhPlS6IcVGVTMsp175bYxbHBT1GfY5vxZyz97YaTnzJ8s2Wql4AOnFQ+9g==", + "version": "0.27.10", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-0.27.10.tgz", + "integrity": "sha512-Lg/9RlGaYGeFjB1UkvK50xUKf7XgIVpxXVPkm+45/VoA66c3uC1KN5yRxx7AEayHcSPZDqO9TGvMXu1WbbY2vw==", "requires": { "@babel/runtime": "^7.10.4", "classnames": "^2.2.5", @@ -1777,76 +1777,100 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "antd": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/antd/-/antd-4.5.4.tgz", - "integrity": "sha512-ToBwPaEfRXpDwkFZwEeQc8TynqVLMRX/P4V2IA2cfS4H+w4HXi89kQik4/Gx48UphHmt6fcfwtfm8QZIn3nerA==", + "version": "4.6.6", + "resolved": "https://registry.npmjs.org/antd/-/antd-4.6.6.tgz", + "integrity": "sha512-ruqzFFyohjEEp+Qg5VzBzFgDjqdj0FoPt3V/bGtLjeuQXPqFrPs+y4WWWmqi3ydGmN4VPIGBwd3CybQDrZAN3g==", "requires": { + "@ant-design/colors": "^4.0.5", "@ant-design/css-animation": "^1.7.2", "@ant-design/icons": "^4.2.1", "@ant-design/react-slick": "~0.27.0", - "@babel/runtime": "^7.10.4", + "@babel/runtime": "^7.11.2", "array-tree-filter": "^2.1.0", "classnames": "^2.2.6", "copy-to-clipboard": "^3.2.0", - "lodash": "^4.17.13", + "lodash": "^4.17.20", "moment": "^2.25.3", "omit.js": "^2.0.2", "raf": "^3.4.1", "rc-animate": "~3.1.0", - "rc-cascader": "~1.3.0", + "rc-cascader": "~1.4.0", "rc-checkbox": "~2.3.0", "rc-collapse": "~2.0.0", - "rc-dialog": "~8.1.0", + "rc-dialog": "~8.2.1", "rc-drawer": "~4.1.0", - "rc-dropdown": "~3.1.2", - "rc-field-form": "~1.8.0", + "rc-dropdown": "~3.2.0", + "rc-field-form": "~1.10.0", + "rc-image": "~3.0.6", "rc-input-number": "~6.0.0", - "rc-mentions": "~1.4.0", - "rc-menu": "~8.5.2", - "rc-motion": "^1.0.0", + "rc-mentions": "~1.5.0", + "rc-menu": "~8.7.1", + "rc-motion": "^2.0.0", "rc-notification": "~4.4.0", - "rc-pagination": "~2.4.5", - "rc-picker": "~1.15.1", - "rc-progress": "~3.0.0", + "rc-pagination": "~3.0.3", + "rc-picker": "~2.1.0", + "rc-progress": "~3.1.0", "rc-rate": "~2.8.2", "rc-resize-observer": "^0.2.3", - "rc-select": "~11.0.12", - "rc-slider": "~9.3.0", + "rc-select": "~11.3.2", + "rc-slider": "~9.5.1", "rc-steps": "~4.1.0", "rc-switch": "~3.2.0", - "rc-table": "~7.8.0", - "rc-tabs": "~11.5.0", + "rc-table": "~7.9.2", + "rc-tabs": "~11.6.0", "rc-textarea": "~0.3.0", - "rc-tooltip": "~4.2.0", - "rc-tree": "~3.9.0", + "rc-tooltip": "~5.0.0", + "rc-tree": "~3.10.0", "rc-tree-select": "~4.1.1", - "rc-trigger": "~4.4.0", - "rc-upload": "~3.2.0", - "rc-util": "^5.0.1", + "rc-trigger": "~5.0.3", + "rc-upload": "~3.3.1", + "rc-util": "^5.1.0", "scroll-into-view-if-needed": "^2.2.25", "warning": "^4.0.3" }, "dependencies": { + "@ant-design/colors": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-4.0.5.tgz", + "integrity": "sha512-3mnuX2prnWOWvpFTS2WH2LoouWlOgtnIpc6IarWN6GOzzLF8dW/U8UctuvIPhoboETehZfJ61XP+CGakBEPJ3Q==", + "requires": { + "tinycolor2": "^1.4.1" + } + }, "omit.js": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/omit.js/-/omit.js-2.0.2.tgz", "integrity": "sha512-hJmu9D+bNB40YpL9jYebQl4lsTW6yEHRTroJzNLqQJYHm7c+NQnJGfZmIWh8S3q3KoaxV1aLhV6B3+0N0/kyJg==" }, "rc-animate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.0.tgz", - "integrity": "sha512-8FsM+3B1H+0AyTyGggY6JyVldHTs1CyYT8CfTmG/nGHHXlecvSLeICJhcKgRLjUiQlctNnRtB1rwz79cvBVmrw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.1.tgz", + "integrity": "sha512-8wg2Zg3EETy0k/9kYuis30NJNQg1D6/WSQwnCiz6SvyxQXNet/rVraRz3bPngwY6rcU2nlRvoShiYOorXyF7Sg==", "requires": { "@ant-design/css-animation": "^1.7.2", "classnames": "^2.2.6", "raf": "^3.4.0", - "rc-util": "^5.0.1" + "rc-util": "^4.15.3" + }, + "dependencies": { + "rc-util": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.21.1.tgz", + "integrity": "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==", + "requires": { + "add-dom-event-listener": "^1.1.0", + "prop-types": "^15.5.10", + "react-is": "^16.12.0", + "react-lifecycles-compat": "^3.0.4", + "shallowequal": "^1.1.0" + } + } } }, "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -2655,9 +2679,9 @@ } }, "compute-scroll-into-view": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.14.tgz", - "integrity": "sha512-mKDjINe3tc6hGelUMNDzuhorIUZ7kS7BwyY0r2wQd2HOH2tRuJykiC06iSEX8y1TuhNzvz4GcJnK16mM2J1NMQ==" + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.16.tgz", + "integrity": "sha512-a85LHKY81oQnikatZYA90pufpZ6sQx++BoCxOEMsjpZx+ZnaKGQnCyCehTRr/1p9GBIAHTjcU9k71kSYWloLiQ==" }, "concat-map": { "version": "0.0.1", @@ -3070,9 +3094,9 @@ "integrity": "sha512-ZCPzAMJZn3rNUvvQIMlXhDr4A+Ar07eLeGsGREoWU19a3Pqf5oYa+ccd+B3F6XVtQY6HANMFdOQ8A+ipFnvJdQ==" }, "dayjs": { - "version": "1.8.34", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.34.tgz", - "integrity": "sha512-Olb+E6EoMvdPmAMq2QoucuyZycKHjTlBXmRx8Ada+wGtq4SIXuDCdtoaX4KkK0yjf1fJLnwXQURr8gQKWKaybw==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.9.1.tgz", + "integrity": "sha512-01NCTBg8cuMJG1OQc6PR7T66+AFYiPwgDvdJmvJBn29NGzIG+DIFxPLNjHzwz3cpFIvG+NcwIjP9hSaPVoOaDg==" }, "debug": { "version": "4.1.1", @@ -4832,9 +4856,9 @@ } }, "moment": { - "version": "2.27.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", - "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.0.tgz", + "integrity": "sha512-z6IJ5HXYiuxvFTI6eiQ9dm77uE0gyy1yXNApVHqTcnIKfY9tIwEjlzsZ6u1LQXvVgKeTnv9Xm7NDvJ7lso3MtA==" }, "move-concurrently": { "version": "1.0.1", @@ -6038,21 +6062,21 @@ } }, "rc-align": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.2.tgz", - "integrity": "sha512-HoTOCLXQehTOxy+Iiy6z0cDRssTSq+0UJuttMLoxtWpn6yorJO7k59ru74HZ7Pad3p0HDOD8v0m/4FQ+bANnsg==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.8.tgz", + "integrity": "sha512-2sRUkmB8z4UEXzaS+lDHzXMoR8HrtKH9nn2yHlHVNyUTnaucjMFbdEoCk+hO1g7cpIgW0MphG8i0EH2scSesfw==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "2.x", "dom-align": "^1.7.0", - "rc-util": "^5.0.1", + "rc-util": "^5.3.0", "resize-observer-polyfill": "^1.5.1" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6075,20 +6099,20 @@ } }, "rc-cascader": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-1.3.0.tgz", - "integrity": "sha512-wayuMo/dSZixvdpiRFZB4Q6A3omKRXQcJ3CxN02+PNiTEcRnK2KDqKUzrx7GwgMsyH5tz90lUZ91lLaEPNFv0A==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-1.4.0.tgz", + "integrity": "sha512-6kgQljDQEKjVAVRkZtvvoi+2qv4u42M6oLuvt4ZDBa16r3X9ZN8TAq3atVyC840ivbGKlHT50OcdVx/iwiHc1w==", "requires": { "array-tree-filter": "^2.1.0", - "rc-trigger": "^4.0.0", + "rc-trigger": "^5.0.4", "rc-util": "^5.0.1", "warning": "^4.0.1" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6106,32 +6130,46 @@ } }, "rc-collapse": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-2.0.0.tgz", - "integrity": "sha512-R5+Ge1uzwK9G1wZPRPhqQsed4FXTDmU0BKzsqfNBtZdk/wd+yey8ZutmJmSozYc5hQwjPkCvJHV7gOIRZKIlJg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-2.0.1.tgz", + "integrity": "sha512-sRNqwQovzQoptTh7dCwj3kfxrdor2oNXrGSBz+QJxSFS7N3Ujgf8X/KlN2ElCkwBKf7nNv36t9dwH0HEku4wJg==", "requires": { "@ant-design/css-animation": "^1.7.2", "classnames": "2.x", "rc-animate": "3.x", - "react-is": "^16.7.0", + "rc-util": "^5.2.1", "shallowequal": "^1.1.0" }, "dependencies": { "rc-animate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.0.tgz", - "integrity": "sha512-8FsM+3B1H+0AyTyGggY6JyVldHTs1CyYT8CfTmG/nGHHXlecvSLeICJhcKgRLjUiQlctNnRtB1rwz79cvBVmrw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.1.tgz", + "integrity": "sha512-8wg2Zg3EETy0k/9kYuis30NJNQg1D6/WSQwnCiz6SvyxQXNet/rVraRz3bPngwY6rcU2nlRvoShiYOorXyF7Sg==", "requires": { "@ant-design/css-animation": "^1.7.2", "classnames": "^2.2.6", "raf": "^3.4.0", - "rc-util": "^5.0.1" + "rc-util": "^4.15.3" + }, + "dependencies": { + "rc-util": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.21.1.tgz", + "integrity": "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==", + "requires": { + "add-dom-event-listener": "^1.1.0", + "prop-types": "^15.5.10", + "react-is": "^16.12.0", + "react-lifecycles-compat": "^3.0.4", + "shallowequal": "^1.1.0" + } + } } }, "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6140,29 +6178,44 @@ } }, "rc-dialog": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-8.1.1.tgz", - "integrity": "sha512-ToyHiMlV94z8LfnmeKoVvu04Pd9+HdwwSHhY2a8IWeYGA5Cjk1WyIZvS+njCsm8rSMM4NqPqFkMZA0N/Iw0NrQ==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-8.2.2.tgz", + "integrity": "sha512-U4jR5bE7XpIbMC20JAIv91254b+vQ8LODd8Kxco0XvkL+eJ1aCYkOfRqevJ1ipOIzF3s6F08jSH8YvJqxvpAvA==", "requires": { + "@babel/runtime": "^7.10.1", "rc-animate": "3.x", "rc-util": "^5.0.1" }, "dependencies": { "rc-animate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.0.tgz", - "integrity": "sha512-8FsM+3B1H+0AyTyGggY6JyVldHTs1CyYT8CfTmG/nGHHXlecvSLeICJhcKgRLjUiQlctNnRtB1rwz79cvBVmrw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.1.tgz", + "integrity": "sha512-8wg2Zg3EETy0k/9kYuis30NJNQg1D6/WSQwnCiz6SvyxQXNet/rVraRz3bPngwY6rcU2nlRvoShiYOorXyF7Sg==", "requires": { "@ant-design/css-animation": "^1.7.2", "classnames": "^2.2.6", "raf": "^3.4.0", - "rc-util": "^5.0.1" + "rc-util": "^4.15.3" + }, + "dependencies": { + "rc-util": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.21.1.tgz", + "integrity": "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==", + "requires": { + "add-dom-event-listener": "^1.1.0", + "prop-types": "^15.5.10", + "react-is": "^16.12.0", + "react-lifecycles-compat": "^3.0.4", + "shallowequal": "^1.1.0" + } + } } }, "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6181,9 +6234,9 @@ }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6192,13 +6245,13 @@ } }, "rc-dropdown": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-3.1.2.tgz", - "integrity": "sha512-s2W5jqvjTid5DxotGO5FlTBaQWeB+Bu7McQgjB8Ot3Wbl72AIKwLf11+lgbV4mA2vWC1H8DKyn6SW9TKLTi0xg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-3.2.0.tgz", + "integrity": "sha512-j1HSw+/QqlhxyTEF6BArVZnTmezw2LnSmRk6I9W7BCqNCKaRwleRmMMs1PHbuaG8dKHVqP6e21RQ7vPBLVnnNw==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.6", - "rc-trigger": "^4.0.0" + "rc-trigger": "^5.0.4" } }, "rc-editor-core": { @@ -6231,9 +6284,9 @@ } }, "rc-field-form": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.8.1.tgz", - "integrity": "sha512-OAMFhS+92+4o7Y0WyTfQ6E5EdBk7z7vEXf4dL5CpoZU2OEHv/INZP1xts2AIKNVOBligG/WcfMTuk+GvbyVsnA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.10.1.tgz", + "integrity": "sha512-aosTtNTqLYX2jsG5GyCv7axe+b57XH73T7TmmrX/cmhemhtFjvNE6RkRkmtP9VOJnZg5YGC5HfK172cnJ1Ij7Q==", "requires": { "@babel/runtime": "^7.8.4", "async-validator": "^3.0.3", @@ -6246,9 +6299,9 @@ "integrity": "sha512-VrFk4eYiJAWKskEz115iiuCf9O0ftnMMPXrOFMqyzGH2KxO7YwncKyn/FgOOP+0MDHMfXL7gLExagCutaZGigA==" }, "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6271,10 +6324,33 @@ "warning": "^4.0.3" } }, + "rc-image": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-3.0.6.tgz", + "integrity": "sha512-Dn8mTSlcgKJko417OX8+6yyNIL9+DEa81aexBfT78qWlEpcxtR4GgdsU0+zJLNqa2rnGZyjaBLFtaPw9tUuxYA==", + "requires": { + "@ant-design/icons": "^4.2.2", + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "rc-dialog": "~8.2.2", + "rc-util": "^5.0.6" + }, + "dependencies": { + "rc-util": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", + "requires": { + "react-is": "^16.12.0", + "shallowequal": "^1.1.0" + } + } + } + }, "rc-input-number": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-6.0.0.tgz", - "integrity": "sha512-vbe+g7HvR/joknSnvLkBTi9N9I+LsV4kljfuog8WNiS7OAF3aEN0QcHSOQ4+xk6+Hx9P1tU63z2+TyEx8W/j2Q==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-6.0.1.tgz", + "integrity": "sha512-cS1k6IB/V84VUQd5qWzGFrLHvZjWGHGmYbrvR0QP/C1Ju1SlBqlhqhOBTc6w+dpPs84PCH5caZtNzsHeWZ1zYA==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.5", @@ -6282,9 +6358,9 @@ }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6293,22 +6369,22 @@ } }, "rc-mentions": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.4.1.tgz", - "integrity": "sha512-MraFCsXlorfUj4/VUjRnITAnBzhM0gMH+2yj/3jmS5rIj0NjNJoTXyEUW3gTJxnw9DP22IMccMTdP3Fjz/2UgQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.5.2.tgz", + "integrity": "sha512-GqV0tOtHY3pLpOsFCxJ2i6Ad8AVfxFmz0NlD/8rb8IG8pMpthJKcdfnXlNZRx3Fa9O4YEgJpdSY1WEbmlx2DWQ==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.6", "rc-menu": "^8.0.1", "rc-textarea": "^0.3.0", - "rc-trigger": "^4.3.0", + "rc-trigger": "^5.0.4", "rc-util": "^5.0.1" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6317,16 +6393,16 @@ } }, "rc-menu": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-8.5.2.tgz", - "integrity": "sha512-GPtr7qoCynVEkFgco/9cW0z/xU33GV89Q6r8FgEkrdhaQSJzuSC+v8pv+Bll5fVGQlJyJgOVqiKk7l2Knk1jYg==", + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-8.7.1.tgz", + "integrity": "sha512-CuuJ9oS1oPAfenqAMa3CZZE7RrPcPTHV3310cf6RO2uJgE9ztqasRFMEBwtruH16OexTr0igTCXySm+e2/TBQg==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "2.x", "mini-store": "^3.0.1", "omit.js": "^2.0.0", - "rc-motion": "^1.0.1", - "rc-trigger": "^4.4.0", + "rc-motion": "^2.0.1", + "rc-trigger": "^5.0.4", "rc-util": "^5.0.1", "resize-observer-polyfill": "^1.5.0", "shallowequal": "^1.1.0" @@ -6338,9 +6414,9 @@ "integrity": "sha512-hJmu9D+bNB40YpL9jYebQl4lsTW6yEHRTroJzNLqQJYHm7c+NQnJGfZmIWh8S3q3KoaxV1aLhV6B3+0N0/kyJg==" }, "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6349,20 +6425,19 @@ } }, "rc-motion": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-1.0.2.tgz", - "integrity": "sha512-FDmC9ZdzsXerlTZ+YLu+l5erjkMU98s85SFHdQac+pMy6zQ10RuON6Ntv3ZwP0+qY/YlIsK+0uMXIWOJ9LaLIg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.3.1.tgz", + "integrity": "sha512-UAB2gwS9c1DuCFKVCimAkL2JUEGCwzgCbb+VslhIMFg6vY7oyMxYIQ6hkoji1PzgDEw0tHIhP+a17R6Y5DGMrQ==", "requires": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", - "raf": "^3.4.1", - "rc-util": "^5.0.6" + "rc-util": "^5.2.1" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6382,20 +6457,34 @@ }, "dependencies": { "rc-animate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.0.tgz", - "integrity": "sha512-8FsM+3B1H+0AyTyGggY6JyVldHTs1CyYT8CfTmG/nGHHXlecvSLeICJhcKgRLjUiQlctNnRtB1rwz79cvBVmrw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.1.1.tgz", + "integrity": "sha512-8wg2Zg3EETy0k/9kYuis30NJNQg1D6/WSQwnCiz6SvyxQXNet/rVraRz3bPngwY6rcU2nlRvoShiYOorXyF7Sg==", "requires": { "@ant-design/css-animation": "^1.7.2", "classnames": "^2.2.6", "raf": "^3.4.0", - "rc-util": "^5.0.1" + "rc-util": "^4.15.3" + }, + "dependencies": { + "rc-util": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.21.1.tgz", + "integrity": "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==", + "requires": { + "add-dom-event-listener": "^1.1.0", + "prop-types": "^15.5.10", + "react-is": "^16.12.0", + "react-lifecycles-compat": "^3.0.4", + "shallowequal": "^1.1.0" + } + } } }, "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6404,33 +6493,33 @@ } }, "rc-pagination": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-2.4.6.tgz", - "integrity": "sha512-1ykd3Jti+JuOFdzEFXGfVpkuH+hKxLYz3FKV6BSwnnWXLr9Y8bbm7YiTSwBmdDcOg6tinH8b4IYaKzxBWRC6EA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-3.0.4.tgz", + "integrity": "sha512-9v9mmB7FTWS4kWRLFfWafm6LtvB+xdNi+pTIwUODSevzImrlrmMOIhDrOB3u2tEXiy8LyqvCnoyPYt5jQBapxA==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1" } }, "rc-picker": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-1.15.4.tgz", - "integrity": "sha512-GYgSyoSJy/Zp9ZF75eJ/fv1P88IrWzrGCtefZW47POw6UXz5Yh+6O+pJZcTbx0HwiAE9HHb8nyOjciS6XjYszg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-2.1.0.tgz", + "integrity": "sha512-Tu8+yR0qnBVND4v+eta8GRkLu4OvTUaxlk7ZHDAkVFm1RHLAl1GzA6Foni9vcpkMnFMFD6EzpaOlkArI0ryuDA==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1", "date-fns": "^2.15.0", "dayjs": "^1.8.30", "moment": "^2.24.0", - "rc-trigger": "^4.0.0", + "rc-trigger": "^5.0.4", "rc-util": "^5.0.1", "shallowequal": "^1.1.0" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6439,10 +6528,11 @@ } }, "rc-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.0.0.tgz", - "integrity": "sha512-dQv1KU3o6Vay604FMYMF4S0x4GNXAgXf1tbQ1QoxeIeQt4d5fUeB7Ri82YPu+G+aRvH/AtxYAlEcnxyVZ1/4Hw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.1.0.tgz", + "integrity": "sha512-DIe9CFkGA4R/pLZ/4nPChQFmIeB8/4tVCr2knlSf9he71j8Fky469zZHhtCFyNwvNGjw/GVDeoTn4BqU4S0ylw==", "requires": { + "@babel/runtime": "^7.10.1", "classnames": "^2.2.6" } }, @@ -6457,9 +6547,9 @@ }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6479,9 +6569,9 @@ }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6490,23 +6580,23 @@ } }, "rc-select": { - "version": "11.0.13", - "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-11.0.13.tgz", - "integrity": "sha512-4/GDmBkGnDhYre3Dvq5UkIRXQJW8hbGdpdH8SjquSbCktAVitYV+opd/lKI28qMcBxCgjOHgYXwZ18TF+kP2VQ==", + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-11.3.3.tgz", + "integrity": "sha512-YMsGVEZxXctj15nIZKlFCkiOxMe0PNBeACN6nHqDozDYKR/aqP8J3XZqZ5Gw/fcgS4bI50zPVMieJKlY8/6Wfw==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "2.x", - "rc-motion": "^1.0.1", - "rc-trigger": "^4.3.0", + "rc-motion": "^2.0.1", + "rc-trigger": "^5.0.4", "rc-util": "^5.0.1", - "rc-virtual-list": "^1.1.2", + "rc-virtual-list": "^3.0.3", "warning": "^4.0.3" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6515,21 +6605,21 @@ } }, "rc-slider": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-9.3.1.tgz", - "integrity": "sha512-c52PWPyrfJWh28K6dixAm0906L3/4MUIxqrNQA4TLnC/Z+cBNycWJUZoJerpwSOE1HdM3XDwixCsmtFc/7aWlQ==", + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-9.5.1.tgz", + "integrity": "sha512-MbGH2f2/Kv7jUeBHQp8rcXLUrNdFR3YLyuMR77WcjQrEIMly/zoBuie/VZaWoPXWHlsB3H91ETktF88EfS/PkQ==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.5", - "rc-tooltip": "^4.0.0", + "rc-tooltip": "^5.0.1", "rc-util": "^5.0.0", "shallowequal": "^1.1.0" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6548,9 +6638,9 @@ }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6559,9 +6649,9 @@ } }, "rc-switch": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-3.2.0.tgz", - "integrity": "sha512-WQZnRrWZ+KGh4Cd98FpP1ZgvMmebctoHzKAO2n1Xsry1FQBSGgIw4rQJRxET31VS/dR1LIKb5md/k0UzcXXc0g==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-3.2.1.tgz", + "integrity": "sha512-ZXYSmx2U+bpHjljjqS5LGj2UIPcQk0EAq6japkaOzQ/OcyzMwWVD9oXMjcRZdO5W1g/pClIV70uEBOWuBMqP4g==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.1", @@ -6569,9 +6659,9 @@ }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6580,22 +6670,22 @@ } }, "rc-table": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.8.6.tgz", - "integrity": "sha512-rHRStVTO6FYlxs5Bk9S56Vo/Jn7pX3hOtHTHP+Vu++i9SF7DroOReMIi+OJ7RA9n3jVBxyT/9+NESXgTFvPbYA==", + "version": "7.9.10", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.9.10.tgz", + "integrity": "sha512-WtPBxYsBU/a5MIglilbMlVkiXkPKXpUM/CPCFaqA2veh1b7J40mbTGQmU8VT6S0FClkI5jm0QBtSp6LstPkOMQ==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "^2.2.5", "raf": "^3.4.1", "rc-resize-observer": "^0.2.0", - "rc-util": "^5.0.0", + "rc-util": "^5.0.4", "shallowequal": "^1.1.0" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6604,24 +6694,23 @@ } }, "rc-tabs": { - "version": "11.5.7", - "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-11.5.7.tgz", - "integrity": "sha512-KQcE4FNmERyhtj81wWOlM6z5HrQDxFsdp47qqbXJwOMTVup8/57pmd63ptvnAmY/5CmjTuDMG/4g+NuZzk/dnA==", + "version": "11.6.2", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-11.6.2.tgz", + "integrity": "sha512-7Z5Lg+nP/H4V7dIlewrOC0+aogRVH3ASjTy4VIletYOeStGPWYSfwBnUTBdcCXcUuWuyyKnNkYrUD0yaRqUCIA==", "requires": { - "@babel/runtime": "^7.10.1", + "@babel/runtime": "^7.11.2", "classnames": "2.x", "raf": "^3.4.1", - "rc-dropdown": "^3.1.0", - "rc-menu": "^8.2.1", + "rc-dropdown": "^3.1.3", + "rc-menu": "^8.6.1", "rc-resize-observer": "^0.2.1", - "rc-trigger": "^4.2.1", "rc-util": "^5.0.0" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6648,50 +6737,41 @@ } }, "rc-tooltip": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-4.2.1.tgz", - "integrity": "sha512-oykuaGsHg7RFvPUaxUpxo7ScEqtH61C66x4JUmjlFlSS8gSx2L8JFtfwM1D68SLBxUqGqJObtxj4TED75gQTiA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-5.0.1.tgz", + "integrity": "sha512-3AnxhUS0j74xAV3khrKw8o6rg+Ima3nw09DJBezMPnX3ImQUAnayWsPSlN1mEnihjA43rcFkGM1emiKE+CXyMQ==", "requires": { - "rc-trigger": "^4.2.1" + "@babel/runtime": "^7.11.2", + "rc-trigger": "^5.0.0" } }, "rc-tree": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-3.9.2.tgz", - "integrity": "sha512-r9Kox/2btnM5+FU//j8vslv9MqSn3pFc27FzwRXUl4dGHncSXfkjf/mJNu3WHlzwJZ5nqFlx4qGpgdy4kPHdwQ==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-3.10.0.tgz", + "integrity": "sha512-kf7J/f2E2T8Kfta3/1BIg65AzTmXOgOjn0KOpvD3KI/gqkfKMRKUS1ybkxW39JUPpKwdeOHFnYH+nFFMq7tkfg==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "2.x", - "rc-motion": "^1.0.0", + "rc-motion": "^2.0.1", "rc-util": "^5.0.0", "rc-virtual-list": "^3.0.1" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" } - }, - "rc-virtual-list": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.0.3.tgz", - "integrity": "sha512-LLW2D/8N7GBOrEybN3Oqn0FVaQ4Tx3MABmlnWrmKJuPXYqJncQ1/Guxo/BQq8FEmPMIMhWaJFWAeNQOsDZvf1A==", - "requires": { - "classnames": "^2.2.6", - "rc-resize-observer": "^0.2.3", - "rc-util": "^5.0.7" - } } } }, "rc-tree-select": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-4.1.1.tgz", - "integrity": "sha512-pawxt/W1chLpjtAEQe8mXI9C9DYNMGS/BR6eBmOY8cJDK6OWSa6M88S6F0jXc+A10D/CLfHAfF1ZIj7VGse+5Q==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-4.1.2.tgz", + "integrity": "sha512-2tRwZ4ChY+BarVKHoPR65kSZtopgwKCig6ngJiiTVgYfRdAhfdQp2j2+L8YW9TkosYGmwgTOhmlphlG3QNy7Pg==", "requires": { "@babel/runtime": "^7.10.1", "classnames": "2.x", @@ -6700,58 +6780,33 @@ "rc-util": "^5.0.5" }, "dependencies": { - "rc-select": { - "version": "11.1.6", - "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-11.1.6.tgz", - "integrity": "sha512-X5kCwUGIe3uF5las4bFiXzD3F/hxs5Nz+wpf3xG6esg352ThP5kBROmMOeb91Yo2nOPZyiH6jnLsZLecnyWbZQ==", - "requires": { - "@babel/runtime": "^7.10.1", - "classnames": "2.x", - "rc-motion": "^1.0.1", - "rc-trigger": "^4.3.0", - "rc-util": "^5.0.1", - "rc-virtual-list": "^3.0.3", - "warning": "^4.0.3" - } - }, "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" } - }, - "rc-virtual-list": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.0.3.tgz", - "integrity": "sha512-LLW2D/8N7GBOrEybN3Oqn0FVaQ4Tx3MABmlnWrmKJuPXYqJncQ1/Guxo/BQq8FEmPMIMhWaJFWAeNQOsDZvf1A==", - "requires": { - "classnames": "^2.2.6", - "rc-resize-observer": "^0.2.3", - "rc-util": "^5.0.7" - } } } }, "rc-trigger": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-4.4.0.tgz", - "integrity": "sha512-09562wc5I1JUbCdWohcFYJeLTpjKjEqH+0lY7plDtyI9yFXRngrvmqsrSJyT6Nat+C35ymD7fhwCCPq3cfUI4g==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-5.0.6.tgz", + "integrity": "sha512-L/xIX5OO7a/bdTH0yYT9mwAsV6oM1inAqAbLjoUzpcIW+UUE3jjVOjm5VaKDfHd41rzDzOfN05URmhet5QzXKQ==", "requires": { - "@babel/runtime": "^7.10.1", + "@babel/runtime": "^7.11.2", "classnames": "^2.2.6", - "raf": "^3.4.1", "rc-align": "^4.0.0", - "rc-motion": "^1.0.0", - "rc-util": "^5.0.1" + "rc-motion": "^2.0.0", + "rc-util": "^5.3.4" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -6760,11 +6815,24 @@ } }, "rc-upload": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-3.2.0.tgz", - "integrity": "sha512-/vyOGVxl5QVM3ZE7s+GqYPbCLC/Q/vJq0sjdwnvJw01KvAR5kVOC4jbHEaU56dMss7PFGDfNzc8zO5bWYLDzVQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-3.3.1.tgz", + "integrity": "sha512-KWkJbVM9BwU8qi/2jZwmZpAcdRzDkuyfn/yAOLu+nm47dyd6//MtxzQD3XZDFkC6jQ6D5FmlKn6DhmOfV3v43w==", "requires": { - "classnames": "^2.2.5" + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + }, + "dependencies": { + "rc-util": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", + "requires": { + "react-is": "^16.12.0", + "shallowequal": "^1.1.0" + } + } } }, "rc-util": { @@ -6780,19 +6848,19 @@ } }, "rc-virtual-list": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-1.1.6.tgz", - "integrity": "sha512-u3+izqWL8p8bQy8nYH48qWpiGyxR/ye8D2k0zJlXmfYeL55/xh83YrzHqiDzO78uj0Ewag3nXDA0JTVrYO7ygQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.1.0.tgz", + "integrity": "sha512-DYU3wOjVuQo4hzYvmmpnoNtxrd8OIcutazA90x374ZFGGm4xYoSjCdh6UhBLi47IJI2BRry4l583nuoi7+06GA==", "requires": { "classnames": "^2.2.6", - "raf": "^3.4.1", - "rc-util": "^5.0.0" + "rc-resize-observer": "^0.2.3", + "rc-util": "^5.0.7" }, "dependencies": { "rc-util": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.0.7.tgz", - "integrity": "sha512-nr98b5aMqqvIqxm16nF+zC3K3f81r+HsflT5E9Encr5itRwV7Vo/5GjJMNds/WiFV33rilq7vzb3xeAbCycmwg==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.4.0.tgz", + "integrity": "sha512-kXDn1JyLJTAWLBFt+fjkTcUtXhxKkipQCobQmxIEVrX62iXgo24z8YKoWehWfMxPZFPE+RXqrmEu9j5kHz/Lrg==", "requires": { "react-is": "^16.12.0", "shallowequal": "^1.1.0" @@ -7260,11 +7328,11 @@ } }, "scroll-into-view-if-needed": { - "version": "2.2.25", - "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.25.tgz", - "integrity": "sha512-C8RKJPq9lK7eubwGpLbUkw3lklcG3Ndjmea2PyauzrA0i4DPlzAmVMGxaZrBFqCrVLfvJmP80IyHnv4jxvg1OQ==", + "version": "2.2.26", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.26.tgz", + "integrity": "sha512-SQ6AOKfABaSchokAmmaxVnL9IArxEnLEX9j4wAZw+x4iUTb40q7irtHG3z4GtAWz5veVZcCnubXDBRyLVQaohw==", "requires": { - "compute-scroll-into-view": "^1.0.14" + "compute-scroll-into-view": "^1.0.16" } }, "semver": { diff --git a/client/package.json b/client/package.json index 34398400..67ffa36e 100644 --- a/client/package.json +++ b/client/package.json @@ -16,7 +16,7 @@ "@typescript-eslint/eslint-plugin": "^2.20.0", "@typescript-eslint/parser": "^2.20.0", "@zeit/next-less": "^1.0.1", - "antd": "^4.3.1", + "antd": "4.6.6", "axios": "^0.19.2", "babel-plugin-import": "^1.13.0", "classnames": "^2.2.6", From 82438f23cdbf0e6f80cc26451411771f9cca4a6d Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 4 Oct 2020 09:33:08 +0300 Subject: [PATCH 25/42] [client] Delete filter modal on feed flow --- client/src/@types/pages/feeds/index.d.ts | 2 +- .../pages/feeds/AdditionalBlock/index.tsx | 2 +- .../pages/feeds/FlowHeader/index.tsx | 10 +----- .../pages/feeds/TagSearchingBlock/index.tsx | 31 +++++++++++++++---- client/src/pages/index.tsx | 31 +++++++------------ client/src/styles/antd/global.less | 4 +++ 6 files changed, 43 insertions(+), 37 deletions(-) diff --git a/client/src/@types/pages/feeds/index.d.ts b/client/src/@types/pages/feeds/index.d.ts index 2cb22f0a..7bbbb90c 100644 --- a/client/src/@types/pages/feeds/index.d.ts +++ b/client/src/@types/pages/feeds/index.d.ts @@ -22,5 +22,5 @@ export interface FlowHeaderProps { sortBy: "top" | "hot" | undefined, setSortBy: (val: "top" | "hot" | undefined) => void, resetCategoryFilter: () => void, - openFilterModal: () => void + beforeFilterReset: () => void } diff --git a/client/src/components/pages/feeds/AdditionalBlock/index.tsx b/client/src/components/pages/feeds/AdditionalBlock/index.tsx index dcca2559..a875c7cf 100644 --- a/client/src/components/pages/feeds/AdditionalBlock/index.tsx +++ b/client/src/components/pages/feeds/AdditionalBlock/index.tsx @@ -61,7 +61,7 @@ export const AdditionalBlock = (): JSX.Element => { Feednext © 2020. All rights reserved - + v{packageJson.version} diff --git a/client/src/components/pages/feeds/FlowHeader/index.tsx b/client/src/components/pages/feeds/FlowHeader/index.tsx index 508ae578..152ab2b8 100644 --- a/client/src/components/pages/feeds/FlowHeader/index.tsx +++ b/client/src/components/pages/feeds/FlowHeader/index.tsx @@ -22,6 +22,7 @@ const FlowHeader: React.FC = (props): JSX.Element => { } const handleFilterReset = (): void => { + props.beforeFilterReset() props.resetCategoryFilter() props.setSortBy(undefined) } @@ -29,15 +30,6 @@ const FlowHeader: React.FC = (props): JSX.Element => { return ( - = (props): JSX.Element => { const [tagResult, setTagResult] = useState([]) const [selectedValues, setSelectedValues] = useState(props.tagFilter) + const [noDataMessage, setNoDataMessage] = useState('Enter at least 3 characters to search') useEffect(() => { setSelectedValues(props.tagFilter) @@ -21,7 +22,12 @@ export const TagSearchingBlock: React.FC = (props): JSX. } const handleTagSearching = (value: string): void => { - if (value.length > 2) { + if (value.length < 3) { + setTagResult([]) + setNoDataMessage('Enter at least 3 characters to search') + } + + else { searchTagByName(value).then(({ data }) => { const result = [] @@ -29,7 +35,8 @@ export const TagSearchingBlock: React.FC = (props): JSX. result.push({tag.name}) }) - setTagResult(result) + if (result.length === 0) setNoDataMessage('Couldn\'t find any tag') + else setTagResult(result) }) } } @@ -40,13 +47,25 @@ export const TagSearchingBlock: React.FC = (props): JSX. props.updateTagFilterList(updatedList.toString()) } + const handleOnTagClear = () => { + props.beforeTagDeSelect() + setTagResult([]) + setNoDataMessage('Enter at least 3 characters to search') + props.updateTagFilterList('') + } + return ( - + + Search & Filter Tags {noTagDataMessage} + } + > + {tagResult} + diff --git a/client/src/components/pages/create-feed/Step2/index.tsx b/client/src/components/pages/create-feed/Step2/index.tsx index c572f616..6b0b0644 100644 --- a/client/src/components/pages/create-feed/Step2/index.tsx +++ b/client/src/components/pages/create-feed/Step2/index.tsx @@ -1,10 +1,11 @@ // Antd dependencies -import { Form, Button, Descriptions, Divider, Modal, Avatar, Rate } from 'antd' +import { Form, Button, Descriptions, Divider, Modal, Avatar, Rate, Typography } from 'antd' import { ExclamationCircleOutlined, LoadingOutlined } from '@ant-design/icons' import TextArea from 'antd/lib/input/TextArea' // Other dependencies import React, { useContext, useState } from 'react' +import * as stringToColor from 'string-to-color' // Local files import { PageHelmet } from '@/components/global/PageHelmet' @@ -23,7 +24,7 @@ const formItemLayout = { const Step2 = (props: Step2Props): JSX.Element => { const [form] = Form.useForm() - const { createTitleFormData, readableCategoryValue, firstEntryForm, titleRate } = useContext(StepContext) + const { createTitleFormData, readableTagValue, firstEntryForm, titleRate } = useContext(StepContext) const { stepMovementTo, setFirstEntryForm, setIsRequestReady, setTitleRate } = props const [isRequestStarted, setIsRequestStarted] = useState(false) @@ -79,8 +80,16 @@ const Step2 = (props: Step2Props): JSX.Element => { alt="Title Image" /> - - { readableCategoryValue } + + {readableTagValue.map(tag => { + return ( +
+ 0xffffff / 2) ? '#000' : '#fff', background: (parseInt(stringToColor(tag).replace('#', ''), 16) > 0xffffff / 2) ? '#fff' : '#000', opacity: 0.9 }}> + #{tag} + +
+ ) + })}
{ createTitleFormData.name } diff --git a/client/src/components/pages/create-feed/Step3/index.tsx b/client/src/components/pages/create-feed/Step3/index.tsx index 7828ba6c..51367231 100644 --- a/client/src/components/pages/create-feed/Step3/index.tsx +++ b/client/src/components/pages/create-feed/Step3/index.tsx @@ -1,9 +1,10 @@ // Antd dependencies -import { Button, Result, Descriptions } from 'antd' +import { Button, Result, Descriptions, Typography } from 'antd' // Other dependencies import React, { useContext } from 'react' import { useRouter } from 'next/router' +import * as stringToColor from 'string-to-color' // Local files import { PageHelmet } from '@/components/global/PageHelmet' @@ -13,7 +14,7 @@ import '@/styles/components/StepForm/style.less' const Step3 = ({ titleSlugForRouting, feedCreatedSuccessfully }: Step3Props): JSX.Element => { const router = useRouter() - const { createTitleFormData, readableCategoryValue, firstEntryForm } = useContext(StepContext) + const { createTitleFormData, readableTagValue, firstEntryForm } = useContext(StepContext) const onFinish = () => router.push('/') const handleOnPostRoute = () => router.push('/[feed]', `/${titleSlugForRouting}`) @@ -21,8 +22,16 @@ const Step3 = ({ titleSlugForRouting, feedCreatedSuccessfully }: Step3Props): JS const information = (
- - { readableCategoryValue } + + {readableTagValue.map(tag => { + return ( +
+ 0xffffff / 2) ? '#000' : '#fff', background: (parseInt(stringToColor(tag).replace('#', ''), 16) > 0xffffff / 2) ? '#fff' : '#000', opacity: 0.9 }}> + #{tag} + +
+ ) + })}
{ createTitleFormData.name } diff --git a/client/src/pages/create-feed/index.tsx b/client/src/pages/create-feed/index.tsx index 6fdb07fa..0699dc20 100644 --- a/client/src/pages/create-feed/index.tsx +++ b/client/src/pages/create-feed/index.tsx @@ -23,7 +23,7 @@ const CreateFeed: React.FC = () => { const [currentStep, setCurrentStep] = useState(0) const [stepComponent, setStepComponent] = useState(null) const [isRequestReady, setIsRequestReady] = useState(false) - const [readableCategoryValue, setReadableCategoryValue] = useState(undefined) + const [readableTagValue, setReadableTagValue] = useState(undefined) const [firstEntryForm, setFirstEntryForm] = useState<{ text: string } | { text: any }>({ text: undefined }) @@ -32,7 +32,7 @@ const CreateFeed: React.FC = () => { name: undefined, imageBase64: undefined, imageFile: undefined, - categoryId: undefined, + tags: undefined, }) const [feedCreatedSuccessfully, setFeedCreatedSuccessfully] = useState(null) @@ -43,7 +43,7 @@ const CreateFeed: React.FC = () => { const titleFormData = new FormData() titleFormData.append('name', createTitleFormData.name) - titleFormData.append('categoryId', createTitleFormData.categoryId) + titleFormData.append('tags', createTitleFormData.tags) if (createTitleFormData.imageFile) titleFormData.append('image', createTitleFormData.imageFile) createTitle(titleFormData, accessToken).then(async (res: AxiosResponse) => { @@ -106,7 +106,7 @@ const CreateFeed: React.FC = () => { } } @@ -116,7 +116,7 @@ const CreateFeed: React.FC = () => { return ( - + diff --git a/client/src/styles/antd/global.less b/client/src/styles/antd/global.less index 0ec0852e..d13c13cc 100644 --- a/client/src/styles/antd/global.less +++ b/client/src/styles/antd/global.less @@ -26,7 +26,7 @@ body, font-weight: bold; opacity: 0.85; padding: 0px 5px 0px 5px; - margin: 0px 0px 5px 3px; + margin: 0px 0px 5px 5px; border-radius: 4px; display: inline-table; font-family: 'Courier New', Courier, monospace; From d42c9d02a3b623bb7ee7d69dd3fe7a88fc2ff51f Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Wed, 7 Oct 2020 23:53:12 +0300 Subject: [PATCH 29/42] [client] optimize validatio on feed creation --- client/src/components/pages/create-feed/Step1/index.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/src/components/pages/create-feed/Step1/index.tsx b/client/src/components/pages/create-feed/Step1/index.tsx index 5840bb62..279b33d0 100644 --- a/client/src/components/pages/create-feed/Step1/index.tsx +++ b/client/src/components/pages/create-feed/Step1/index.tsx @@ -30,8 +30,8 @@ const Step1: React.FC = (props): JSX.Element => { const { createTitleFormData } = useContext(StepContext) const { setCreateTitleFormData, stepMovementTo, setReadableTagValue } = props - const handleFormValidation = (): void => { - if (!createTitleFormData.tags || !form.getFieldValue('title')) return + const handleFormValidation = async (): Promise => { + await form.validateFields() setCreateTitleFormData({ ...createTitleFormData, name: form.getFieldValue('title') @@ -40,7 +40,6 @@ const Step1: React.FC = (props): JSX.Element => { } const handleReadableTagValue = (tags: string[]): void => { - console.log(tags.toString()) setCreateTitleFormData({ ...createTitleFormData, tags, @@ -115,7 +114,7 @@ const Step1: React.FC = (props): JSX.Element => { rules={[ () => ({ validator() { - if (!createTitleFormData.tags) return Promise.reject('Please select atleast one tag') + if (!createTitleFormData.tags || createTitleFormData.tags.length < 1) return Promise.reject('Please select atleast one tag') return Promise.resolve() } }) From 6cf2e3c1890aaa6422d3f4262f0208b18fcc3982 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Thu, 8 Oct 2020 23:57:19 +0300 Subject: [PATCH 30/42] [client] style & type optimizations --- client/src/@types/api/Title/index.d.ts | 3 +-- client/src/@types/initializations/[feed]/index.d.ts | 1 - client/src/@types/pages/[feed]/index.d.ts | 1 - client/src/@types/pages/feeds/index.d.ts | 2 +- client/src/styles/antd/global.less | 3 +++ 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/@types/api/Title/index.d.ts b/client/src/@types/api/Title/index.d.ts index 7c091724..438d1d67 100644 --- a/client/src/@types/api/Title/index.d.ts +++ b/client/src/@types/api/Title/index.d.ts @@ -5,8 +5,7 @@ export interface TitleResponseData { name: string, slug: string, entry_count: number, - category_id: string, - category_ancestors: string[], + tags: string[], opened_by: string, rate: { username: string, diff --git a/client/src/@types/initializations/[feed]/index.d.ts b/client/src/@types/initializations/[feed]/index.d.ts index d0839ba2..a1c25550 100644 --- a/client/src/@types/initializations/[feed]/index.d.ts +++ b/client/src/@types/initializations/[feed]/index.d.ts @@ -4,7 +4,6 @@ import { EntryAttributes } from '@/@types/pages' export interface FeedPageInitials { titleData: TitleResponseData, - categoryData: CategoryResponseData, featuredEntry: string, averageTitleRate: number, entryList: { diff --git a/client/src/@types/pages/[feed]/index.d.ts b/client/src/@types/pages/[feed]/index.d.ts index a8469f22..af959880 100644 --- a/client/src/@types/pages/[feed]/index.d.ts +++ b/client/src/@types/pages/[feed]/index.d.ts @@ -17,7 +17,6 @@ export interface EntryAttributes { export interface FeedHeaderProps { accessToken: string, - categoryData: CategoryResponseData, titleData: TitleResponseData, averageTitleRate: number, userRole: number, diff --git a/client/src/@types/pages/feeds/index.d.ts b/client/src/@types/pages/feeds/index.d.ts index 7bbbb90c..316944cf 100644 --- a/client/src/@types/pages/feeds/index.d.ts +++ b/client/src/@types/pages/feeds/index.d.ts @@ -21,6 +21,6 @@ export interface FeedList { export interface FlowHeaderProps { sortBy: "top" | "hot" | undefined, setSortBy: (val: "top" | "hot" | undefined) => void, - resetCategoryFilter: () => void, + resetTagFilter: () => void, beforeFilterReset: () => void } diff --git a/client/src/styles/antd/global.less b/client/src/styles/antd/global.less index d13c13cc..f363c97c 100644 --- a/client/src/styles/antd/global.less +++ b/client/src/styles/antd/global.less @@ -23,6 +23,9 @@ body, } .custom-tag { + line-height: 20px; + cursor: default; + font-size: 14px; font-weight: bold; opacity: 0.85; padding: 0px 5px 0px 5px; From e65fc2b5933df2eaf238a940eb35ef1f05e04955 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sat, 10 Oct 2020 11:11:30 +0300 Subject: [PATCH 31/42] [client] Update tag & category types --- .../@types/components/CategorySelect/index.d.ts | 17 ----------------- client/src/@types/components/index.d.ts | 1 - .../@types/initializations/[entry]/index.d.ts | 1 - .../@types/initializations/[feed]/index.d.ts | 2 +- client/src/@types/pages/[feed]/index.d.ts | 2 +- 5 files changed, 2 insertions(+), 21 deletions(-) delete mode 100644 client/src/@types/components/CategorySelect/index.d.ts diff --git a/client/src/@types/components/CategorySelect/index.d.ts b/client/src/@types/components/CategorySelect/index.d.ts deleted file mode 100644 index 0b081214..00000000 --- a/client/src/@types/components/CategorySelect/index.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -export interface CategoryData { - id: string - name: string - is_leaf: boolean - ancestors: string[] - created_at: string - updated_at: string -} - -export interface CategorySelectProps { - style?: { [key: string]: string | number } - placeHolder?: string - multiple?: boolean - allowClear?: boolean - defaultValue?: string - onSelect: (id: string | string[], title: React.ReactNode[]) => any -} diff --git a/client/src/@types/components/index.d.ts b/client/src/@types/components/index.d.ts index 5f00d41a..9fd27013 100644 --- a/client/src/@types/components/index.d.ts +++ b/client/src/@types/components/index.d.ts @@ -1,5 +1,4 @@ export * from './Aggrements' -export * from './CategorySelect' export * from './ImageUpload' export * from './PageHelmet' export * from './SignModal' \ No newline at end of file diff --git a/client/src/@types/initializations/[entry]/index.d.ts b/client/src/@types/initializations/[entry]/index.d.ts index a781049e..6a829e68 100644 --- a/client/src/@types/initializations/[entry]/index.d.ts +++ b/client/src/@types/initializations/[entry]/index.d.ts @@ -4,7 +4,6 @@ import { TitleResponseData, EntryResponseData } from '@/@types/api' export interface EntryPageInitials { title: TitleResponseData, - categoryName: string, averageTitleRate: number, entryData: EntryResponseData, } \ No newline at end of file diff --git a/client/src/@types/initializations/[feed]/index.d.ts b/client/src/@types/initializations/[feed]/index.d.ts index a1c25550..6391d07e 100644 --- a/client/src/@types/initializations/[feed]/index.d.ts +++ b/client/src/@types/initializations/[feed]/index.d.ts @@ -1,5 +1,5 @@ // Local files -import { TitleResponseData, CategoryResponseData } from '@/@types/api' +import { TitleResponseData } from '@/@types/api' import { EntryAttributes } from '@/@types/pages' export interface FeedPageInitials { diff --git a/client/src/@types/pages/[feed]/index.d.ts b/client/src/@types/pages/[feed]/index.d.ts index af959880..6ffcbff9 100644 --- a/client/src/@types/pages/[feed]/index.d.ts +++ b/client/src/@types/pages/[feed]/index.d.ts @@ -1,5 +1,5 @@ // Local files -import { CategoryResponseData, TitleResponseData, EntryResponseData} from '@/@types/api' +import { TitleResponseData, EntryResponseData} from '@/@types/api' export interface EntryAttributes { id: string, From bc080c2ed7e2138a08faec247246172d3946d758 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sat, 10 Oct 2020 11:12:47 +0300 Subject: [PATCH 32/42] [client] replace whole category feature with tags --- .../global/CategorySelect/index.tsx | 64 ---------------- .../global/CategorySelect/style.less | 12 --- .../components/pages/[feed]/FeedHeader.tsx | 21 +++++- .../pages/feeds/FlowHeader/index.tsx | 2 +- client/src/pages/[feed]/index.tsx | 74 ++++++++++++++----- client/src/pages/entry/[id]/index.tsx | 18 ++++- client/src/pages/index.tsx | 4 +- client/src/services/api/Tag/index.ts | 9 +-- client/src/services/api/Title/index.ts | 2 +- .../services/initializations/[entry]/index.ts | 8 +- .../services/initializations/[feed]/index.ts | 7 +- 11 files changed, 94 insertions(+), 127 deletions(-) delete mode 100644 client/src/components/global/CategorySelect/index.tsx delete mode 100644 client/src/components/global/CategorySelect/style.less diff --git a/client/src/components/global/CategorySelect/index.tsx b/client/src/components/global/CategorySelect/index.tsx deleted file mode 100644 index 3ab003bf..00000000 --- a/client/src/components/global/CategorySelect/index.tsx +++ /dev/null @@ -1,64 +0,0 @@ -// Antd dependencies -import { TreeSelect } from 'antd' - -// Other dependencies -import React, { useState, useEffect } from 'react' - -// Local files -import { fetchMainCategories, fetchChildCategories } from '@/services/api' -import { CategoryData, CategorySelectProps } from '@/@types/components' -import './style.less' - -export const CategorySelect: React.FC = (props): JSX.Element => { - const [categories, setCategories] = useState([]) - - useEffect(() => { - fetchMainCategories().then(async ({ data }) => { - const refactoredArray = await data.attributes.categories.map((category: CategoryData) => { - return { - id: category.id, - pId: 0, - title: category.name.toUpperCase(), - value: category.id, - disabled: (!category.is_leaf && !props.multiple), - isLeaf: category.is_leaf - } - }) - setCategories(refactoredArray) - }) - }, []) - - const handleOnCategoryChangeEvent = (id: string, title: React.ReactNode[]): void => { - props.onSelect(id, title) - } - - const handleOnCategoryLoad = async (treeNode: any) => { - await fetchChildCategories(treeNode.id).then(async ({ data }) => { - data.attributes.categories.map((item: CategoryData) => { - setCategories((currentState) => [...currentState, { - id: item.id, - pId: treeNode.id, - title: item.is_leaf ? item.name : item.name.toUpperCase(), - value: item.id, - disabled: (!item.is_leaf && !props.multiple), - isLeaf: item.is_leaf - }]) - }) - }) - } - - return ( - - ) -} diff --git a/client/src/components/global/CategorySelect/style.less b/client/src/components/global/CategorySelect/style.less deleted file mode 100644 index b568b57e..00000000 --- a/client/src/components/global/CategorySelect/style.less +++ /dev/null @@ -1,12 +0,0 @@ -@import '~antd/es/style/themes/default.less'; - -.ant-select-tree .ant-select-tree-node-content-wrapper { - color: #188fce; - font-weight: bold; -} - -.ant-select-tree .ant-select-tree-treenode-disabled .ant-select-tree-node-content-wrapper { - color: #616161 !important; - cursor: default !important; - font-weight: bold !important; -} diff --git a/client/src/components/pages/[feed]/FeedHeader.tsx b/client/src/components/pages/[feed]/FeedHeader.tsx index 4d9be48f..e7253696 100644 --- a/client/src/components/pages/[feed]/FeedHeader.tsx +++ b/client/src/components/pages/[feed]/FeedHeader.tsx @@ -26,6 +26,7 @@ import { import React, { useState } from 'react' import { format, parseISO } from 'date-fns' import { useRouter } from 'next/router' +import * as stringToColor from 'string-to-color' // Local files import { getUserRateOfTitle, rateTitle, deleteTitle } from '@/services/api' @@ -33,12 +34,12 @@ import { SignModal } from '@/components/global/SignModal' import { API_URL } from '@/../config/constants' import { FeedHeaderProps } from '@/@types/pages' import '@/styles/components/[feed]/style.less' +import { title } from 'process' const FeedHeader: React.FC = (props): JSX.Element => { const { titleData, openUpdateModal, - categoryData, accessToken, averageTitleRate, refreshTitleRate, @@ -73,6 +74,18 @@ const FeedHeader: React.FC = (props): JSX.Element => { .catch(_error => setInitialRatingModalValue(0)) } + const handleTagsView = (tags: string[]) => { + return tags.map(tag => { + return ( +
+ 0xffffff / 2) ? '#000' : '#fff', background: (parseInt(stringToColor(tag).replace('#', ''), 16) > 0xffffff / 2) ? '#fff' : '#000', opacity: 0.9 }}> + #{tag} + +
+ ) + }) + } + const handleRateModalRender = (): JSX.Element => ( = (props): JSX.Element => { value: titleData.attributes.name }, { - title: 'Category', - value: categoryData.attributes.name + title: 'Tags', + value: titleData.attributes.tags }, { title: 'Entry Count', @@ -188,7 +201,7 @@ const FeedHeader: React.FC = (props): JSX.Element => { - {categoryData.attributes.name} + {handleTagsView(titleData.attributes.tags)} diff --git a/client/src/components/pages/feeds/FlowHeader/index.tsx b/client/src/components/pages/feeds/FlowHeader/index.tsx index 152ab2b8..e95bd7f3 100644 --- a/client/src/components/pages/feeds/FlowHeader/index.tsx +++ b/client/src/components/pages/feeds/FlowHeader/index.tsx @@ -23,7 +23,7 @@ const FlowHeader: React.FC = (props): JSX.Element => { const handleFilterReset = (): void => { props.beforeFilterReset() - props.resetCategoryFilter() + props.resetTagFilter() props.setSortBy(undefined) } diff --git a/client/src/pages/[feed]/index.tsx b/client/src/pages/[feed]/index.tsx index 5a6fcb17..6151b413 100644 --- a/client/src/pages/[feed]/index.tsx +++ b/client/src/pages/[feed]/index.tsx @@ -1,5 +1,5 @@ // Antd dependencies -import { Modal, Form, Input, Button, Popconfirm, message } from 'antd' +import { Modal, Form, Input, Button, Popconfirm, message, Select, Typography } from 'antd' import { InfoCircleOutlined } from '@ant-design/icons' // Other dependencies @@ -9,10 +9,9 @@ import { useRouter, NextRouter } from 'next/router' import { NextPage } from 'next' // Local files -import { fetchEntriesByTitleId, getAverageTitleRate, updateTitle, deleteTitleImage, updateTitleImage } from '@/services/api' -import { TitleResponseData, CategoryResponseData } from '@/@types/api' +import { fetchEntriesByTitleId, getAverageTitleRate, updateTitle, deleteTitleImage, updateTitleImage, searchTagByName } from '@/services/api' +import { TitleResponseData } from '@/@types/api' import { API_URL, Guest } from '@/../config/constants' -import { CategorySelect } from '@/components/global/CategorySelect' import { PageHelmet } from '@/components/global/PageHelmet' import { EntryAttributes } from '@/@types/pages' import { getFeedPageInitialValues } from '@/services/initializations' @@ -29,12 +28,10 @@ const Feed: NextPage = (props): JSX.Element => { const globalState = useSelector((state: any) => state.global) const userRole = useSelector((state: any) => state.user?.attributes.user.role) - const [title, setTitle]: any = useState(props.titleData) - const [category, setCategory]: any = useState(props.categoryData) + const [title, setTitle] = useState(props.titleData) const [featuredEntry, setFeaturedEntry] = useState(props.featuredEntry) const [keywords, setKeywords] = useState(props.keywords) const [averageTitleRate, setAverageTitleRate] = useState(props.averageTitleRate) - const [updateCategoryId, setUpdateCategoryId] = useState(null) const [entryList, setEntryList] = useState<{ entries: EntryAttributes[], count: number @@ -44,15 +41,47 @@ const Feed: NextPage = (props): JSX.Element => { const [titleImageBlob, setTitleImageBlob] = useState(null) const [titleNotFound, setTitleNotFound] = useState(props.error) + const [tagResult, setTagResult] = useState([]) + const [noTagDataMessage, setNoTagDataMessage] = useState('Enter at least 3 characters to search') + const [tagValue, setTagValue] = useState(title.attributes.tags) + const [form] = Form.useForm() + useEffect(() => { + if (title) handleEntryFetching(10 * (Number(router.query.page) - 1) || 0) + }, [title, sortEntriesBy]) + const handleEntryFetching = (page: number): void => { fetchEntriesByTitleId(title.attributes.id, page, sortEntriesBy).then(async ({ data }) => setEntryList(data.attributes)) } - useEffect(() => { - if (title) handleEntryFetching(10 * (Number(router.query.page) - 1) || 0) - }, [title, sortEntriesBy]) + const handleTagSearching = (value: string): void => { + if (value.length < 3) { + setTagResult([]) + setNoTagDataMessage('Enter at least 3 characters to search') + } + + else { + searchTagByName(value).then(({ data }) => { + const result = [] + data.attributes.tags.map(tag => { + result.push({tag.name}) + }) + + if (result.length !== 0) setTagResult(result) + else setTagResult([{value}]) + }) + } + } + + const handleTagSelect = (value: string): void => { + setTagValue([...tagValue, value]) + } + + const handleDeSelect = (tag: string) => { + const updatedList = tagValue.filter(value => value !== tag) + setTagValue(updatedList) + } const getTitleRate = async (titleId: string): Promise => { await getAverageTitleRate(titleId).then(res => setAverageTitleRate(res.data.attributes.rate || 0)) @@ -60,8 +89,8 @@ const Feed: NextPage = (props): JSX.Element => { const handleTitleUpdate = async (values: { name: string }): Promise => { const updatePayload = { - categoryId: updateCategoryId, - name: values.name + name: values.name, + tags: tagValue, } if (!titleImageBlob) { @@ -85,7 +114,7 @@ const Feed: NextPage = (props): JSX.Element => { } if (titleNotFound) return - if (!entryList || !title || !category || (!averageTitleRate && averageTitleRate !== 0)) return + if (!entryList || !title || (!averageTitleRate && averageTitleRate !== 0)) return return ( @@ -103,7 +132,6 @@ const Feed: NextPage = (props): JSX.Element => { openUpdateModal={(): void => setUpdateModalVisibility(true)} userRole={userRole} titleData={title} - categoryData={category} averageTitleRate={averageTitleRate} refreshTitleRate={getTitleRate} /> @@ -147,12 +175,20 @@ const Feed: NextPage = (props): JSX.Element => {
- setUpdateCategoryId(id)} - /> + placeholder="please specify feed-related keywords" + onSearch={handleTagSearching} + onSelect={handleTagSelect} + onDeselect={handleDeSelect} + notFoundContent={ + {noTagDataMessage} + } + > + {tagResult} + = (props): JSX.Element => { const router = useRouter() const [title, setTitle] = useState(props.title) - const [categoryName, setCategoryName] = useState(props.categoryName) const [averageTitleRate, setAverageTitleRate] = useState(props.averageTitleRate) const [entryData, setEntryData] = useState(props.entryData) if (!title) return + const handleTagsView = (tags: string[]) => { + return tags.map(tag => { + return ( +
+ 0xffffff / 2) ? '#000' : '#fff', background: (parseInt(stringToColor(tag).replace('#', ''), 16) > 0xffffff / 2) ? '#fff' : '#000', opacity: 0.9 }}> + #{tag} + +
+ ) + }) + } + const handleHeaderTitleSection = (): JSX.Element => ( <> - {categoryName} + {handleTagsView(title.attributes.tags)} = (props): JSX.Element => { return ( = (props): JSX.Element => { await fetchAllFeeds(skipValueForPagination, undefined, tagFilter, sortBy) .then(async (feedsResponse: AxiosResponse) => { const promises = await feedsResponse.data.attributes.titles.map(async (title: any) => { - const categoryName = null // await fetchOneCategory(title.category_id).then(({ data }) => data.attributes.name) const featuredEntry: any = await fetchFeaturedEntryByTitleId(title.id).then(featuredEntryResponse => featuredEntryResponse.data.attributes) .catch(_error => { }) @@ -89,7 +88,6 @@ const Homepage: NextPage = (props): JSX.Element => { name: title.name, href: `/${title.slug}`, tags: title.tags, - categoryName: categoryName, createdAt: title.created_at, updatedAt: title.updated_at, entryCount: title.entry_count, @@ -271,7 +269,7 @@ const Homepage: NextPage = (props): JSX.Element => { > handleSorting(val)} - resetCategoryFilter={(): void => setTagFilter(null)} + resetTagFilter={(): void => setTagFilter(null)} beforeFilterReset={() => handleFlowReset()} sortBy={sortBy} /> diff --git a/client/src/services/api/Tag/index.ts b/client/src/services/api/Tag/index.ts index 0c73bd3c..0f8e403d 100644 --- a/client/src/services/api/Tag/index.ts +++ b/client/src/services/api/Tag/index.ts @@ -1,11 +1,4 @@ import axios, { AxiosResponse } from 'axios' -export const fetchOneCategory = (categoryId: string): Promise => axios.get(`/v1/category/${categoryId}`) - export const searchTagByName = (searchValue: string): Promise => axios.get(`/v1/tag/search?searchValue=${searchValue}`) - -export const fetchMainCategories = (): Promise => axios.get('/v1/category/main-categories') - -export const fetchChildCategories = (categoryId: string): Promise => axios.get(`/v1/category/${categoryId}/child-categories`) - -export const fetchTrendingTags = (): Promise => axios.get('/v1/tag/trending') +export const fetchTrendingTags = (): Promise => axios.get('/v1/tag/trending') \ No newline at end of file diff --git a/client/src/services/api/Title/index.ts b/client/src/services/api/Title/index.ts index 7eb9622e..0d4b4ec6 100644 --- a/client/src/services/api/Title/index.ts +++ b/client/src/services/api/Title/index.ts @@ -79,7 +79,7 @@ export const updateTitle = ( titleId: string, payload: { name: string, - categoryId: string | string[] | null + tags: string[] } ): Promise => axios.patch(`/v1/title/${titleId}`, payload, { headers: { diff --git a/client/src/services/initializations/[entry]/index.ts b/client/src/services/initializations/[entry]/index.ts index ed7eab13..02f8cdae 100644 --- a/client/src/services/initializations/[entry]/index.ts +++ b/client/src/services/initializations/[entry]/index.ts @@ -1,11 +1,10 @@ // Local files import { TitleResponseData, EntryResponseData } from '@/@types/api' -import { fetchEntryByEntryId, fetchTitle, fetchOneCategory, getAverageTitleRate } from '@/services/api' +import { fetchEntryByEntryId, fetchTitle, getAverageTitleRate } from '@/services/api' import { EntryPageInitials } from '@/@types/initializations' export const getEntryPageInitialValues = async (entryId: string): Promise => { let title: TitleResponseData - let categoryName: string let averageTitleRate: number let entryData: EntryResponseData @@ -16,10 +15,6 @@ export const getEntryPageInitialValues = async (entryId: string): Promise { title = sRes.data - // Get category - await fetchOneCategory(sRes.data.attributes.category_id).then(({ data }) => { - categoryName = data.attributes.name - }) // Fetch average rate of title await getAverageTitleRate(sRes.data.attributes.id) .then(trRes => averageTitleRate = trRes.data.attributes.rate || 0) @@ -31,7 +26,6 @@ export const getEntryPageInitialValues = async (entryId: string): Promise => { let titleData: TitleResponseData - let categoryData: CategoryResponseData let featuredEntry: string let averageTitleRate: number let entryList: { @@ -17,7 +16,6 @@ export const getFeedPageInitialValues = async (titleSlug: string, entryPage: num let error: boolean = false await fetchTitle(titleSlug, 'slug').then(async titleResponse => { - await fetchOneCategory(titleResponse.data.attributes.category_id).then(({ data }) => categoryData = data) await fetchFeaturedEntryByTitleId(titleResponse.data.attributes.id).then(({ data }) => featuredEntry = data.attributes.text).catch(_error => {}) await getAverageTitleRate(titleResponse.data.attributes.id).then(averageRateResponse => averageTitleRate = averageRateResponse.data.attributes.rate || 0) titleData = titleResponse.data @@ -35,7 +33,6 @@ export const getFeedPageInitialValues = async (titleSlug: string, entryPage: num return { titleData, - categoryData, featuredEntry, averageTitleRate, entryList, From 50b459027a01cab638ba3cce8ca3655b28d72781 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sat, 10 Oct 2020 18:10:16 +0300 Subject: [PATCH 33/42] [server] Upgrade nestjs-rate-limiter version to v2.5.6 --- server/package-lock.json | 1164 ++++++++++++++++++-------------------- server/package.json | 2 +- 2 files changed, 564 insertions(+), 602 deletions(-) diff --git a/server/package-lock.json b/server/package-lock.json index 60d67bb5..cfc08818 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -39,9 +39,9 @@ } }, "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true } } @@ -64,12 +64,11 @@ "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -148,9 +147,9 @@ } }, "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true } } @@ -177,12 +176,11 @@ "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -283,9 +281,9 @@ } }, "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true } } @@ -346,9 +344,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.35", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.35.tgz", - "integrity": "sha512-gXx7jAWpMddu0f7a+L+txMplp3FnHl53OhQIF9puXKq3hDGY/GjH+MF04oWnV/adPSCrbtHumDCFwzq2VhltWA==", + "version": "10.17.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.39.tgz", + "integrity": "sha512-dJLCxrpQmgyxYGcl0Ae9MTsQgI22qHHcGFj/8VKu7McJA5zQpnuGjoksnxbo1JxSjW/Nahnl13W8MYZf01CZHA==", "optional": true } } @@ -802,26 +800,25 @@ "dev": true }, "@jest/console": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.3.0.tgz", - "integrity": "sha512-/5Pn6sJev0nPUcAdpJHMVIsA8sKizL2ZkcKPE5+dJrCccks7tcM7c9wbgHudBJbxXLoTbqsHkG1Dofoem4F09w==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.5.2.tgz", + "integrity": "sha512-lJELzKINpF1v74DXHbCRIkQ/+nUV1M+ntj+X1J8LxCgpmJZjfLmhFejiMSbjjD66fayxl5Z06tbs3HMyuik6rw==", "dev": true, "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^26.3.0", - "jest-util": "^26.3.0", + "jest-message-util": "^26.5.2", + "jest-util": "^26.5.2", "slash": "^3.0.0" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -868,34 +865,34 @@ } }, "@jest/core": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.4.2.tgz", - "integrity": "sha512-sDva7YkeNprxJfepOctzS8cAk9TOekldh+5FhVuXS40+94SHbiicRO1VV2tSoRtgIo+POs/Cdyf8p76vPTd6dg==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.5.2.tgz", + "integrity": "sha512-LLTo1LQMg7eJjG/+P1NYqFof2B25EV1EqzD5FonklihG4UJKiK2JBIvWonunws6W7e+DhNLoFD+g05tCY03eyA==", "dev": true, "requires": { - "@jest/console": "^26.3.0", - "@jest/reporters": "^26.4.1", - "@jest/test-result": "^26.3.0", - "@jest/transform": "^26.3.0", - "@jest/types": "^26.3.0", + "@jest/console": "^26.5.2", + "@jest/reporters": "^26.5.2", + "@jest/test-result": "^26.5.2", + "@jest/transform": "^26.5.2", + "@jest/types": "^26.5.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.4", - "jest-changed-files": "^26.3.0", - "jest-config": "^26.4.2", - "jest-haste-map": "^26.3.0", - "jest-message-util": "^26.3.0", + "jest-changed-files": "^26.5.2", + "jest-config": "^26.5.2", + "jest-haste-map": "^26.5.2", + "jest-message-util": "^26.5.2", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.4.0", - "jest-resolve-dependencies": "^26.4.2", - "jest-runner": "^26.4.2", - "jest-runtime": "^26.4.2", - "jest-snapshot": "^26.4.2", - "jest-util": "^26.3.0", - "jest-validate": "^26.4.2", - "jest-watcher": "^26.3.0", + "jest-resolve": "^26.5.2", + "jest-resolve-dependencies": "^26.5.2", + "jest-runner": "^26.5.2", + "jest-runtime": "^26.5.2", + "jest-snapshot": "^26.5.2", + "jest-util": "^26.5.2", + "jest-validate": "^26.5.2", + "jest-watcher": "^26.5.2", "micromatch": "^4.0.2", "p-each-series": "^2.1.0", "rimraf": "^3.0.0", @@ -910,12 +907,11 @@ "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -980,53 +976,53 @@ } }, "@jest/environment": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.3.0.tgz", - "integrity": "sha512-EW+MFEo0DGHahf83RAaiqQx688qpXgl99wdb8Fy67ybyzHwR1a58LHcO376xQJHfmoXTu89M09dH3J509cx2AA==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.5.2.tgz", + "integrity": "sha512-YjhCD/Zhkz0/1vdlS/QN6QmuUdDkpgBdK4SdiVg4Y19e29g4VQYN5Xg8+YuHjdoWGY7wJHMxc79uDTeTOy9Ngw==", "dev": true, "requires": { - "@jest/fake-timers": "^26.3.0", - "@jest/types": "^26.3.0", + "@jest/fake-timers": "^26.5.2", + "@jest/types": "^26.5.2", "@types/node": "*", - "jest-mock": "^26.3.0" + "jest-mock": "^26.5.2" } }, "@jest/fake-timers": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.3.0.tgz", - "integrity": "sha512-ZL9ytUiRwVP8ujfRepffokBvD2KbxbqMhrXSBhSdAhISCw3gOkuntisiSFv+A6HN0n0fF4cxzICEKZENLmW+1A==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.5.2.tgz", + "integrity": "sha512-09Hn5Oraqt36V1akxQeWMVL0fR9c6PnEhpgLaYvREXZJAh2H2Y+QLCsl0g7uMoJeoWJAuz4tozk1prbR1Fc1sw==", "dev": true, "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "@sinonjs/fake-timers": "^6.0.1", "@types/node": "*", - "jest-message-util": "^26.3.0", - "jest-mock": "^26.3.0", - "jest-util": "^26.3.0" + "jest-message-util": "^26.5.2", + "jest-mock": "^26.5.2", + "jest-util": "^26.5.2" } }, "@jest/globals": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.4.2.tgz", - "integrity": "sha512-Ot5ouAlehhHLRhc+sDz2/9bmNv9p5ZWZ9LE1pXGGTCXBasmi5jnYjlgYcYt03FBwLmZXCZ7GrL29c33/XRQiow==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.5.2.tgz", + "integrity": "sha512-9PmnFsAUJxpPt1s/stq02acS1YHliVBDNfAWMe1bwdRr1iTCfhbNt3ERQXrO/ZfZSweftoA26Q/2yhSVSWQ3sw==", "dev": true, "requires": { - "@jest/environment": "^26.3.0", - "@jest/types": "^26.3.0", - "expect": "^26.4.2" + "@jest/environment": "^26.5.2", + "@jest/types": "^26.5.2", + "expect": "^26.5.2" } }, "@jest/reporters": { - "version": "26.4.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.4.1.tgz", - "integrity": "sha512-aROTkCLU8++yiRGVxLsuDmZsQEKO6LprlrxtAuzvtpbIFl3eIjgIf3EUxDKgomkS25R9ZzwGEdB5weCcBZlrpQ==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.5.2.tgz", + "integrity": "sha512-zvq6Wvy6MmJq/0QY0YfOPb49CXKSf42wkJbrBPkeypVa8I+XDxijvFuywo6TJBX/ILPrdrlE/FW9vJZh6Rf9vA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^26.3.0", - "@jest/test-result": "^26.3.0", - "@jest/transform": "^26.3.0", - "@jest/types": "^26.3.0", + "@jest/console": "^26.5.2", + "@jest/test-result": "^26.5.2", + "@jest/transform": "^26.5.2", + "@jest/types": "^26.5.2", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", @@ -1037,10 +1033,10 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.2", - "jest-haste-map": "^26.3.0", - "jest-resolve": "^26.4.0", - "jest-util": "^26.3.0", - "jest-worker": "^26.3.0", + "jest-haste-map": "^26.5.2", + "jest-resolve": "^26.5.2", + "jest-util": "^26.5.2", + "jest-worker": "^26.5.0", "node-notifier": "^8.0.0", "slash": "^3.0.0", "source-map": "^0.6.0", @@ -1050,12 +1046,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -1108,9 +1103,9 @@ } }, "@jest/source-map": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.3.0.tgz", - "integrity": "sha512-hWX5IHmMDWe1kyrKl7IhFwqOuAreIwHhbe44+XH2ZRHjrKIh0LO5eLQ/vxHFeAfRwJapmxuqlGAEYLadDq6ZGQ==", + "version": "26.5.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.5.0.tgz", + "integrity": "sha512-jWAw9ZwYHJMe9eZq/WrsHlwF8E3hM9gynlcDpOyCb9bR8wEd9ZNBZCi7/jZyzHxC7t3thZ10gO2IDhu0bPKS5g==", "dev": true, "requires": { "callsites": "^3.0.0", @@ -1127,46 +1122,46 @@ } }, "@jest/test-result": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.3.0.tgz", - "integrity": "sha512-a8rbLqzW/q7HWheFVMtghXV79Xk+GWwOK1FrtimpI5n1la2SY0qHri3/b0/1F0Ve0/yJmV8pEhxDfVwiUBGtgg==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.5.2.tgz", + "integrity": "sha512-E/Zp6LURJEGSCWpoMGmCFuuEI1OWuI3hmZwmULV0GsgJBh7u0rwqioxhRU95euUuviqBDN8ruX/vP/4bwYolXw==", "dev": true, "requires": { - "@jest/console": "^26.3.0", - "@jest/types": "^26.3.0", + "@jest/console": "^26.5.2", + "@jest/types": "^26.5.2", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.4.2.tgz", - "integrity": "sha512-83DRD8N3M0tOhz9h0bn6Kl6dSp+US6DazuVF8J9m21WAp5x7CqSMaNycMP0aemC/SH/pDQQddbsfHRTBXVUgog==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.5.2.tgz", + "integrity": "sha512-XmGEh7hh07H2B8mHLFCIgr7gA5Y6Hw1ZATIsbz2fOhpnQ5AnQtZk0gmP0Q5/+mVB2xygO64tVFQxOajzoptkNA==", "dev": true, "requires": { - "@jest/test-result": "^26.3.0", + "@jest/test-result": "^26.5.2", "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.3.0", - "jest-runner": "^26.4.2", - "jest-runtime": "^26.4.2" + "jest-haste-map": "^26.5.2", + "jest-runner": "^26.5.2", + "jest-runtime": "^26.5.2" } }, "@jest/transform": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.3.0.tgz", - "integrity": "sha512-Isj6NB68QorGoFWvcOjlUhpkT56PqNIsXKR7XfvoDlCANn/IANlh8DrKAA2l2JKC3yWSMH5wS0GwuQM20w3b2A==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.5.2.tgz", + "integrity": "sha512-AUNjvexh+APhhmS8S+KboPz+D3pCxPvEAGduffaAJYxIFxGi/ytZQkrqcKDUU0ERBAo5R7087fyOYr2oms1seg==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "babel-plugin-istanbul": "^6.0.0", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.3.0", + "jest-haste-map": "^26.5.2", "jest-regex-util": "^26.0.0", - "jest-util": "^26.3.0", + "jest-util": "^26.5.2", "micromatch": "^4.0.2", "pirates": "^4.0.1", "slash": "^3.0.0", @@ -1175,12 +1170,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -1233,9 +1227,9 @@ } }, "@jest/types": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.3.0.tgz", - "integrity": "sha512-BDPG23U0qDeAvU4f99haztXwdAg3hz4El95LkAM+tHAqqhiVzRpEGHHU8EDxT/AnxOrA65YjLBwDahdJ9pTLJQ==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.5.2.tgz", + "integrity": "sha512-QDs5d0gYiyetI8q+2xWdkixVQMklReZr4ltw7GFDtb4fuJIBCE6mzj2LnitGqCuAlLap6wPyb8fpoHgwZz5fdg==", "requires": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", @@ -1245,11 +1239,10 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -1321,12 +1314,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -1536,12 +1528,11 @@ "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -1620,9 +1611,9 @@ } }, "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true } } @@ -1797,68 +1788,68 @@ } }, "@sentry/core": { - "version": "5.24.2", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.24.2.tgz", - "integrity": "sha512-nuAwCGU1l9hgMinl5P/8nIQGRXDP2FI9cJnq5h1qiP/XIOvJkJz2yzBR6nTyqr4vBth0tvxQJbIpDNGd7vHJLg==", - "requires": { - "@sentry/hub": "5.24.2", - "@sentry/minimal": "5.24.2", - "@sentry/types": "5.24.2", - "@sentry/utils": "5.24.2", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.25.0.tgz", + "integrity": "sha512-hY6Zmo7t/RV+oZuvXHP6nyAj/QnZr2jW0e7EbL5YKMV8q0vlnjcE0LgqFXme726OJemoLk67z+sQOJic/Ztehg==", + "requires": { + "@sentry/hub": "5.25.0", + "@sentry/minimal": "5.25.0", + "@sentry/types": "5.25.0", + "@sentry/utils": "5.25.0", "tslib": "^1.9.3" }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, "@sentry/hub": { - "version": "5.24.2", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.24.2.tgz", - "integrity": "sha512-xmO1Ivvpb5Qr9WgekinuZZlpl9Iw7iPETUe84HQOhUrXf+2gKO+LaUYMMsYSVDwXQEmR6/tTMyOtS6iavldC6w==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.25.0.tgz", + "integrity": "sha512-kOlOiJV8wMX50lYpzMlOXBoH7MNG0Ho4RTusdZnXZBaASq5/ljngDJkLr6uylNjceZQP21wzipCQajsJMYB7EQ==", "requires": { - "@sentry/types": "5.24.2", - "@sentry/utils": "5.24.2", + "@sentry/types": "5.25.0", + "@sentry/utils": "5.25.0", "tslib": "^1.9.3" }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, "@sentry/minimal": { - "version": "5.24.2", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.24.2.tgz", - "integrity": "sha512-biFpux5bI3R8xiD/Zzvrk1kRE6bqPtfWXmZYAHRtaUMCAibprTKSY9Ta8QYHynOAEoJ5Akedy6HUsEkK5DoZfA==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.25.0.tgz", + "integrity": "sha512-9JFKuW7U+1vPO86k3+XRtJyooiVZsVOsFFO4GulBzepi3a0ckNyPgyjUY1saLH+cEHx18hu8fGgajvI8ANUF2g==", "requires": { - "@sentry/hub": "5.24.2", - "@sentry/types": "5.24.2", + "@sentry/hub": "5.25.0", + "@sentry/types": "5.25.0", "tslib": "^1.9.3" }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, "@sentry/node": { - "version": "5.24.2", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.24.2.tgz", - "integrity": "sha512-ddfU2tLTvhnY+NqzLIA/gxMt/uxq7R204Nb2J5qqE0WAgbh0dtylNAzfKZTizLdbZfRnpeISmd+CBILh3tavog==", - "requires": { - "@sentry/core": "5.24.2", - "@sentry/hub": "5.24.2", - "@sentry/tracing": "5.24.2", - "@sentry/types": "5.24.2", - "@sentry/utils": "5.24.2", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.25.0.tgz", + "integrity": "sha512-zxoUVdAFTeK9kdEGY95TMs6g8Zx/P55HxG4gHD80BG/XIEvWiGPcGCLOspO4IdGqYXkGS74KfBOIXmmCawWwLg==", + "requires": { + "@sentry/core": "5.25.0", + "@sentry/hub": "5.25.0", + "@sentry/tracing": "5.25.0", + "@sentry/types": "5.25.0", + "@sentry/utils": "5.25.0", "cookie": "^0.4.1", "https-proxy-agent": "^5.0.0", "lru_map": "^0.3.3", @@ -1866,49 +1857,49 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, "@sentry/tracing": { - "version": "5.24.2", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.24.2.tgz", - "integrity": "sha512-1uDgvGGVF8lb3hRXbhNnns+8DBUKjhRKOFR5Z3RExjrDFYTDbHmoNtV73Q12Ra+Iht9HTZnIBOqYD3oSZIbJ0w==", - "requires": { - "@sentry/hub": "5.24.2", - "@sentry/minimal": "5.24.2", - "@sentry/types": "5.24.2", - "@sentry/utils": "5.24.2", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.25.0.tgz", + "integrity": "sha512-KcyHEGFpqSDubHrdWT/vF2hKkjw/ts6NpJ6tPDjBXUNz98BHdAyMKtLOFTCeJFply7/s5fyiAYu44M+M6IG3Bw==", + "requires": { + "@sentry/hub": "5.25.0", + "@sentry/minimal": "5.25.0", + "@sentry/types": "5.25.0", + "@sentry/utils": "5.25.0", "tslib": "^1.9.3" }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, "@sentry/types": { - "version": "5.24.2", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.24.2.tgz", - "integrity": "sha512-HcOK00R0tQG5vzrIrqQ0jC28+z76jWSgQCzXiessJ5SH/9uc6NzdO7sR7K8vqMP2+nweCHckFohC8G0T1DLzuQ==" + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.25.0.tgz", + "integrity": "sha512-8M4PREbcar+15wrtEqcwfcU33SS+2wBSIOd/NrJPXJPTYxi49VypCN1mZBDyWkaK+I+AuQwI3XlRPCfsId3D1A==" }, "@sentry/utils": { - "version": "5.24.2", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.24.2.tgz", - "integrity": "sha512-oPGde4tNEDHKk0Cg9q2p0qX649jLDUOwzJXHKpd0X65w3A6eJByDevMr8CSzKV9sesjrUpxqAv6f9WWlz185tA==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.25.0.tgz", + "integrity": "sha512-Hz5spdIkMSRH5NR1YFOp5qbsY5Ud2lKhEQWlqxcVThMG5YNUc10aYv5ijL19v0YkrC2rqPjCRm7GrVtzOc7bXQ==", "requires": { - "@sentry/types": "5.24.2", + "@sentry/types": "5.25.0", "tslib": "^1.9.3" }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, @@ -2019,11 +2010,6 @@ "@types/node": "*" } }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" - }, "@types/connect": { "version": "3.4.33", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", @@ -2193,12 +2179,11 @@ "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -2322,9 +2307,9 @@ "optional": true }, "@types/node": { - "version": "14.11.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.2.tgz", - "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==" + "version": "14.11.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.8.tgz", + "integrity": "sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw==" }, "@types/node-fetch": { "version": "2.5.4", @@ -2348,9 +2333,9 @@ "dev": true }, "@types/prettier": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.1.tgz", - "integrity": "sha512-2zs+O+UkDsJ1Vcp667pd3f8xearMdopz/z54i99wtRDI5KLmngk7vlrYZD0ZjKHaROR03EznlBbVY9PfAEyJIQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.2.tgz", + "integrity": "sha512-IiPhNnenzkqdSdQH3ifk9LoX7oQe61ZlDdDO4+MUv6FyWdPGDPr26gCPVs3oguZEMq//nFZZpwUZcVuNJsG+DQ==", "dev": true }, "@types/qs": { @@ -2389,9 +2374,9 @@ "dev": true }, "@types/stack-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", - "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.0.tgz", + "integrity": "sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==", "dev": true }, "@types/superagent": { @@ -2489,9 +2474,9 @@ } }, "@types/yargs": { - "version": "15.0.7", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.7.tgz", - "integrity": "sha512-Gf4u3EjaPNcC9cTu4/j2oN14nSVhr8PQ+BvBcBQHAhDZfl0bVIiLgvnRXv/dn58XhTm9UXvBpvJpDlwV65QxOA==", + "version": "15.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.8.tgz", + "integrity": "sha512-b0BYzFUzBpOhPjpl1wtAHU994jBeKF4TKVlT7ssFv44T617XNcPdRoG4AzHLVshLzlrF7i3lTelH7UbuNYV58Q==", "requires": { "@types/yargs-parser": "*" } @@ -2686,9 +2671,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } @@ -2731,9 +2716,9 @@ } }, "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true }, "acorn-globals": { @@ -2747,9 +2732,9 @@ }, "dependencies": { "acorn": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", - "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true } } @@ -2980,9 +2965,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } @@ -3127,9 +3112,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } @@ -3384,9 +3369,9 @@ } }, "aws-sdk": { - "version": "2.766.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.766.0.tgz", - "integrity": "sha512-msEEF7veBrxU1TlhLL33du4oJdwJ6uAWogf9+S0v437AX2z6K5IFr5J78JBysBudRHO0L6aC8bat6OS3oPEQvQ==", + "version": "2.771.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.771.0.tgz", + "integrity": "sha512-fqNGusCwkdemx3yFqvQbU1+xq/PB2wGq7EQIrrTZx/zxfXUp+7+PnrHzXtViCRghN0tylLghBfWYD4VcVcqi7g==", "requires": { "buffer": "4.9.2", "events": "1.1.1", @@ -3432,28 +3417,27 @@ } }, "babel-jest": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.3.0.tgz", - "integrity": "sha512-sxPnQGEyHAOPF8NcUsD0g7hDCnvLL2XyblRBcgrzTWBB/mAIpWow3n1bEL+VghnnZfreLhFSBsFluRoK2tRK4g==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.5.2.tgz", + "integrity": "sha512-U3KvymF3SczA3vOL/cgiUFOznfMET+XDIXiWnoJV45siAp2pLMG8i2+/MGZlAC3f/F6Q40LR4M4qDrWZ9wkK8A==", "dev": true, "requires": { - "@jest/transform": "^26.3.0", - "@jest/types": "^26.3.0", + "@jest/transform": "^26.5.2", + "@jest/types": "^26.5.2", "@types/babel__core": "^7.1.7", "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^26.3.0", + "babel-preset-jest": "^26.5.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "slash": "^3.0.0" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -3513,9 +3497,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "26.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.2.0.tgz", - "integrity": "sha512-B/hVMRv8Nh1sQ1a3EY8I0n4Y1Wty3NrR5ebOyVT302op+DOAau+xNEImGMsUWOC3++ZlMooCytKz+NgN8aKGbA==", + "version": "26.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.5.0.tgz", + "integrity": "sha512-ck17uZFD3CDfuwCLATWZxkkuGGFhMij8quP8CNhwj8ek1mqFgbFzRJ30xwC04LLscj/aKsVFfRST+b5PT7rSuw==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -3525,9 +3509,9 @@ } }, "babel-preset-current-node-syntax": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.3.tgz", - "integrity": "sha512-uyexu1sVwcdFnyq9o8UQYsXwXflIh8LvrF5+cKrYam93ned1CStffB3+BEcsxGSgagoA3GEyjDqO4a/58hyPYQ==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.4.tgz", + "integrity": "sha512-5/INNCYhUGqw7VbVjT/hb3ucjgkVHKXY7lX3ZjlN4gm565VyFmJUrJ/h+h16ECVB38R/9SF6aACydpKMLZ/c9w==", "dev": true, "requires": { "@babel/plugin-syntax-async-generators": "^7.8.4", @@ -3544,12 +3528,12 @@ } }, "babel-preset-jest": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.3.0.tgz", - "integrity": "sha512-5WPdf7nyYi2/eRxCbVrE1kKCWxgWY4RsPEbdJWFm7QsesFGqjdkyLeu1zRkwM1cxK6EPIlNd6d2AxLk7J+t4pw==", + "version": "26.5.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.5.0.tgz", + "integrity": "sha512-F2vTluljhqkiGSJGBg/jOruA8vIIIL11YrxRcO7nviNTMbbofPSHwnm8mgP7d/wS7wRSexRoI6X1A6T74d4LQA==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^26.2.0", + "babel-plugin-jest-hoist": "^26.5.0", "babel-preset-current-node-syntax": "^0.1.3" } }, @@ -4065,9 +4049,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } @@ -4144,9 +4128,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true } } @@ -4252,11 +4236,10 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -5553,26 +5536,25 @@ } }, "expect": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-26.4.2.tgz", - "integrity": "sha512-IlJ3X52Z0lDHm7gjEp+m76uX46ldH5VpqmU0006vqDju/285twh7zaWMRhs67VpQhBwjjMchk+p5aA0VkERCAA==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.5.2.tgz", + "integrity": "sha512-ccTGrXZd8DZCcvCz4htGXTkd/LOoy6OEtiDS38x3/VVf6E4AQL0QoeksBiw7BtGR5xDNiRYPB8GN6pfbuTOi7w==", "dev": true, "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "ansi-styles": "^4.0.0", "jest-get-type": "^26.3.0", - "jest-matcher-utils": "^26.4.2", - "jest-message-util": "^26.3.0", + "jest-matcher-utils": "^26.5.2", + "jest-message-util": "^26.5.2", "jest-regex-util": "^26.0.0" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -5753,9 +5735,9 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-json-stringify": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.2.7.tgz", - "integrity": "sha512-XVCR/dQ6unMP7c39XUdnPoYPPnf1RqTZGL2mAnmrXDIkyF5MRJYd87nfCEmxrqhj7k61Yi35Aaeb2QlJlZU9fg==", + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.2.8.tgz", + "integrity": "sha512-/ASLcFlk998wuzAqbbspt7038fHXM1mTYk5N2Il+tOSnfVuHBwkH5tRnTMaB45Adv+SeS4McFXvAFI1+7uEkXw==", "requires": { "ajv": "^6.11.0", "deepmerge": "^4.2.2", @@ -5769,9 +5751,9 @@ "dev": true }, "fast-redact": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-2.1.0.tgz", - "integrity": "sha512-0LkHpTLyadJavq9sRzzyqIoMZemWli77K2/MGOkafrR64B9ItrvZ9aT+jluvNDsv0YEHjSNhlMBtbokuoqii4A==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.0.tgz", + "integrity": "sha512-a/S/Hp6aoIjx7EmugtzLqXmcNsyFszqbt6qQ99BdG61QjBZF6shNis0BYR6TsZOQ1twYc0FN2Xdhwwbv6+KD0w==" }, "fast-safe-stringify": { "version": "2.0.7", @@ -5880,11 +5862,11 @@ } }, "fastify-static": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-3.2.0.tgz", - "integrity": "sha512-gaN4AX1CrlhwC3cApS1uDSZOkQSbhxt32MRCjlJL3dhG7pxAIf69fmSS1nrKtZe69b5HRn/KyEqkh9qzLN8GZw==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-3.2.1.tgz", + "integrity": "sha512-5l4pTKstyawqXW0dfTwhOS91WNiI9Dr6fwSHnBMv/lNIeGjH6SMKU+5Ypf9DrgLI3N75e7fkmrYhL5tT/BwQZA==", "requires": { - "fastify-plugin": "^2.0.0", + "fastify-plugin": "^2.3.4", "glob": "^7.1.4", "readable-stream": "^3.4.0", "send": "^0.17.1" @@ -6080,12 +6062,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -6870,12 +6851,11 @@ "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -7389,14 +7369,14 @@ } }, "jest": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest/-/jest-26.4.2.tgz", - "integrity": "sha512-LLCjPrUh98Ik8CzW8LLVnSCfLaiY+wbK53U7VxnFSX7Q+kWC4noVeDvGWIFw0Amfq1lq2VfGm7YHWSLBV62MJw==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-26.5.2.tgz", + "integrity": "sha512-4HFabJVwsgDwul/7rhXJ3yFAF/aUkVIXiJWmgFxb+WMdZG39fVvOwYAs8/3r4AlFPc4m/n5sTMtuMbOL3kNtrQ==", "dev": true, "requires": { - "@jest/core": "^26.4.2", + "@jest/core": "^26.5.2", "import-local": "^3.0.2", - "jest-cli": "^26.4.2" + "jest-cli": "^26.5.2" }, "dependencies": { "ansi-regex": { @@ -7406,12 +7386,11 @@ "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -7453,24 +7432,24 @@ "dev": true }, "jest-cli": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.4.2.tgz", - "integrity": "sha512-zb+lGd/SfrPvoRSC/0LWdaWCnscXc1mGYW//NP4/tmBvRPT3VntZ2jtKUONsRi59zc5JqmsSajA9ewJKFYp8Cw==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.5.2.tgz", + "integrity": "sha512-usm48COuUvRp8YEG5OWOaxbSM0my7eHn3QeBWxiGUuFhvkGVBvl1fic4UjC02EAEQtDv8KrNQUXdQTV6ZZBsoA==", "dev": true, "requires": { - "@jest/core": "^26.4.2", - "@jest/test-result": "^26.3.0", - "@jest/types": "^26.3.0", + "@jest/core": "^26.5.2", + "@jest/test-result": "^26.5.2", + "@jest/types": "^26.5.2", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.4", "import-local": "^3.0.2", "is-ci": "^2.0.0", - "jest-config": "^26.4.2", - "jest-util": "^26.3.0", - "jest-validate": "^26.4.2", + "jest-config": "^26.5.2", + "jest-util": "^26.5.2", + "jest-validate": "^26.5.2", "prompts": "^2.0.1", - "yargs": "^15.3.1" + "yargs": "^15.4.1" } }, "string-width": { @@ -7524,12 +7503,12 @@ } }, "jest-changed-files": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.3.0.tgz", - "integrity": "sha512-1C4R4nijgPltX6fugKxM4oQ18zimS7LqQ+zTTY8lMCMFPrxqBFb7KJH0Z2fRQJvw2Slbaipsqq7s1mgX5Iot+g==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.5.2.tgz", + "integrity": "sha512-qSmssmiIdvM5BWVtyK/nqVpN3spR5YyvkvPqz1x3BR1bwIxsWmU/MGwLoCrPNLbkG2ASAKfvmJpOduEApBPh2w==", "dev": true, "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "execa": "^4.0.0", "throat": "^5.0.0" }, @@ -7619,38 +7598,37 @@ } }, "jest-config": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.4.2.tgz", - "integrity": "sha512-QBf7YGLuToiM8PmTnJEdRxyYy3mHWLh24LJZKVdXZ2PNdizSe1B/E8bVm+HYcjbEzGuVXDv/di+EzdO/6Gq80A==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.5.2.tgz", + "integrity": "sha512-dqJOnSegNdE5yDiuGHsjTM5gec7Z4AcAMHiW+YscbOYJAlb3LEtDSobXCq0or9EmGQI5SFmKy4T7P1FxetJOfg==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^26.4.2", - "@jest/types": "^26.3.0", - "babel-jest": "^26.3.0", + "@jest/test-sequencer": "^26.5.2", + "@jest/types": "^26.5.2", + "babel-jest": "^26.5.2", "chalk": "^4.0.0", "deepmerge": "^4.2.2", "glob": "^7.1.1", "graceful-fs": "^4.2.4", - "jest-environment-jsdom": "^26.3.0", - "jest-environment-node": "^26.3.0", + "jest-environment-jsdom": "^26.5.2", + "jest-environment-node": "^26.5.2", "jest-get-type": "^26.3.0", - "jest-jasmine2": "^26.4.2", + "jest-jasmine2": "^26.5.2", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.4.0", - "jest-util": "^26.3.0", - "jest-validate": "^26.4.2", + "jest-resolve": "^26.5.2", + "jest-util": "^26.5.2", + "jest-validate": "^26.5.2", "micromatch": "^4.0.2", - "pretty-format": "^26.4.2" + "pretty-format": "^26.5.2" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -7743,12 +7721,11 @@ "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -7816,25 +7793,24 @@ } }, "jest-each": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.4.2.tgz", - "integrity": "sha512-p15rt8r8cUcRY0Mvo1fpkOGYm7iI8S6ySxgIdfh3oOIv+gHwrHTy5VWCGOecWUhDsit4Nz8avJWdT07WLpbwDA==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.5.2.tgz", + "integrity": "sha512-w7D9FNe0m2D3yZ0Drj9CLkyF/mGhmBSULMQTypzAKR746xXnjUrK8GUJdlLTWUF6dd0ks3MtvGP7/xNFr9Aphg==", "dev": true, "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "chalk": "^4.0.0", "jest-get-type": "^26.3.0", - "jest-util": "^26.3.0", - "pretty-format": "^26.4.2" + "jest-util": "^26.5.2", + "pretty-format": "^26.5.2" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -7887,32 +7863,32 @@ } }, "jest-environment-jsdom": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.3.0.tgz", - "integrity": "sha512-zra8He2btIMJkAzvLaiZ9QwEPGEetbxqmjEBQwhH3CA+Hhhu0jSiEJxnJMbX28TGUvPLxBt/zyaTLrOPF4yMJA==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.5.2.tgz", + "integrity": "sha512-fWZPx0bluJaTQ36+PmRpvUtUlUFlGGBNyGX1SN3dLUHHMcQ4WseNEzcGGKOw4U5towXgxI4qDoI3vwR18H0RTw==", "dev": true, "requires": { - "@jest/environment": "^26.3.0", - "@jest/fake-timers": "^26.3.0", - "@jest/types": "^26.3.0", + "@jest/environment": "^26.5.2", + "@jest/fake-timers": "^26.5.2", + "@jest/types": "^26.5.2", "@types/node": "*", - "jest-mock": "^26.3.0", - "jest-util": "^26.3.0", - "jsdom": "^16.2.2" + "jest-mock": "^26.5.2", + "jest-util": "^26.5.2", + "jsdom": "^16.4.0" } }, "jest-environment-node": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.3.0.tgz", - "integrity": "sha512-c9BvYoo+FGcMj5FunbBgtBnbR5qk3uky8PKyRVpSfe2/8+LrNQMiXX53z6q2kY+j15SkjQCOSL/6LHnCPLVHNw==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.5.2.tgz", + "integrity": "sha512-YHjnDsf/GKFCYMGF1V+6HF7jhY1fcLfLNBDjhAOvFGvt6d8vXvNdJGVM7uTZ2VO/TuIyEFhPGaXMX5j3h7fsrA==", "dev": true, "requires": { - "@jest/environment": "^26.3.0", - "@jest/fake-timers": "^26.3.0", - "@jest/types": "^26.3.0", + "@jest/environment": "^26.5.2", + "@jest/fake-timers": "^26.5.2", + "@jest/types": "^26.5.2", "@types/node": "*", - "jest-mock": "^26.3.0", - "jest-util": "^26.3.0" + "jest-mock": "^26.5.2", + "jest-util": "^26.5.2" } }, "jest-get-type": { @@ -7922,12 +7898,12 @@ "dev": true }, "jest-haste-map": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.3.0.tgz", - "integrity": "sha512-DHWBpTJgJhLLGwE5Z1ZaqLTYqeODQIZpby0zMBsCU9iRFHYyhklYqP4EiG73j5dkbaAdSZhgB938mL51Q5LeZA==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.5.2.tgz", + "integrity": "sha512-lJIAVJN3gtO3k4xy+7i2Xjtwh8CfPcH08WYjZpe9xzveDaqGw9fVNCpkYu6M525wKFVkLmyi7ku+DxCAP1lyMA==", "dev": true, "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "@types/graceful-fs": "^4.1.2", "@types/node": "*", "anymatch": "^3.0.3", @@ -7935,47 +7911,46 @@ "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", "jest-regex-util": "^26.0.0", - "jest-serializer": "^26.3.0", - "jest-util": "^26.3.0", - "jest-worker": "^26.3.0", + "jest-serializer": "^26.5.0", + "jest-util": "^26.5.2", + "jest-worker": "^26.5.0", "micromatch": "^4.0.2", "sane": "^4.0.3", "walker": "^1.0.7" } }, "jest-jasmine2": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.4.2.tgz", - "integrity": "sha512-z7H4EpCldHN1J8fNgsja58QftxBSL+JcwZmaXIvV9WKIM+x49F4GLHu/+BQh2kzRKHAgaN/E82od+8rTOBPyPA==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.5.2.tgz", + "integrity": "sha512-2J+GYcgLVPTkpmvHEj0/IDTIAuyblGNGlyGe4fLfDT2aktEPBYvoxUwFiOmDDxxzuuEAD2uxcYXr0+1Yw4tjFA==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^26.3.0", - "@jest/source-map": "^26.3.0", - "@jest/test-result": "^26.3.0", - "@jest/types": "^26.3.0", + "@jest/environment": "^26.5.2", + "@jest/source-map": "^26.5.0", + "@jest/test-result": "^26.5.2", + "@jest/types": "^26.5.2", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "expect": "^26.4.2", + "expect": "^26.5.2", "is-generator-fn": "^2.0.0", - "jest-each": "^26.4.2", - "jest-matcher-utils": "^26.4.2", - "jest-message-util": "^26.3.0", - "jest-runtime": "^26.4.2", - "jest-snapshot": "^26.4.2", - "jest-util": "^26.3.0", - "pretty-format": "^26.4.2", + "jest-each": "^26.5.2", + "jest-matcher-utils": "^26.5.2", + "jest-message-util": "^26.5.2", + "jest-runtime": "^26.5.2", + "jest-snapshot": "^26.5.2", + "jest-util": "^26.5.2", + "pretty-format": "^26.5.2", "throat": "^5.0.0" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -8022,13 +7997,13 @@ } }, "jest-leak-detector": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.4.2.tgz", - "integrity": "sha512-akzGcxwxtE+9ZJZRW+M2o+nTNnmQZxrHJxX/HjgDaU5+PLmY1qnQPnMjgADPGCRPhB+Yawe1iij0REe+k/aHoA==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.5.2.tgz", + "integrity": "sha512-h7ia3dLzBFItmYERaLPEtEKxy3YlcbcRSjj0XRNJgBEyODuu+3DM2o62kvIFvs3PsaYoIIv+e+nLRI61Dj1CNw==", "dev": true, "requires": { "jest-get-type": "^26.3.0", - "pretty-format": "^26.4.2" + "pretty-format": "^26.5.2" }, "dependencies": { "jest-get-type": { @@ -8040,24 +8015,23 @@ } }, "jest-matcher-utils": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.4.2.tgz", - "integrity": "sha512-KcbNqWfWUG24R7tu9WcAOKKdiXiXCbMvQYT6iodZ9k1f7065k0keUOW6XpJMMvah+hTfqkhJhRXmA3r3zMAg0Q==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.5.2.tgz", + "integrity": "sha512-W9GO9KBIC4gIArsNqDUKsLnhivaqf8MSs6ujO/JDcPIQrmY+aasewweXVET8KdrJ6ADQaUne5UzysvF/RR7JYA==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^26.4.2", + "jest-diff": "^26.5.2", "jest-get-type": "^26.3.0", - "pretty-format": "^26.4.2" + "pretty-format": "^26.5.2" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -8087,9 +8061,9 @@ "dev": true }, "diff-sequences": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.3.0.tgz", - "integrity": "sha512-5j5vdRcw3CNctePNYN0Wy2e/JbWT6cAYnXv5OuqPhDpyCGc0uLu2TK0zOCJWNB9kOIfYMSpIulRaDgIi4HJ6Ig==", + "version": "26.5.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.5.0.tgz", + "integrity": "sha512-ZXx86srb/iYy6jG71k++wBN9P9J05UNQ5hQHQd9MtMPvcqXPx/vKU69jfHV637D00Q2gSgPk2D+jSx3l1lDW/Q==", "dev": true }, "has-flag": { @@ -8099,15 +8073,15 @@ "dev": true }, "jest-diff": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.4.2.tgz", - "integrity": "sha512-6T1XQY8U28WH0Z5rGpQ+VqZSZz8EN8rZcBtfvXaOkbwxIEeRre6qnuZQlbY1AJ4MKDxQF8EkrCvK+hL/VkyYLQ==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.5.2.tgz", + "integrity": "sha512-HCSWDUGwsov5oTlGzrRM+UPJI/Dpqi9jzeV0fdRNi3Ch5bnoXhnyJMmVg2juv9081zLIy3HGPI5mcuGgXM2xRA==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^26.3.0", + "diff-sequences": "^26.5.0", "jest-get-type": "^26.3.0", - "pretty-format": "^26.4.2" + "pretty-format": "^26.5.2" } }, "jest-get-type": { @@ -8128,14 +8102,14 @@ } }, "jest-message-util": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.3.0.tgz", - "integrity": "sha512-xIavRYqr4/otGOiLxLZGj3ieMmjcNE73Ui+LdSW/Y790j5acqCsAdDiLIbzHCZMpN07JOENRWX5DcU+OQ+TjTA==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.5.2.tgz", + "integrity": "sha512-Ocp9UYZ5Jl15C5PNsoDiGEk14A4NG0zZKknpWdZGoMzJuGAkVt10e97tnEVMYpk7LnQHZOfuK2j/izLBMcuCZw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/types": "^26.3.0", - "@types/stack-utils": "^1.0.1", + "@jest/types": "^26.5.2", + "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.2", @@ -8144,12 +8118,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -8196,12 +8169,12 @@ } }, "jest-mock": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.3.0.tgz", - "integrity": "sha512-PeaRrg8Dc6mnS35gOo/CbZovoDPKAeB1FICZiuagAgGvbWdNNyjQjkOaGUa/3N3JtpQ/Mh9P4A2D4Fv51NnP8Q==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.5.2.tgz", + "integrity": "sha512-9SiU4b5PtO51v0MtJwVRqeGEroH66Bnwtq4ARdNP7jNXbpT7+ByeWNAk4NeT/uHfNSVDXEXgQo1XRuwEqS6Rdw==", "dev": true, "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "@types/node": "*" } }, @@ -8218,28 +8191,27 @@ "dev": true }, "jest-resolve": { - "version": "26.4.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.4.0.tgz", - "integrity": "sha512-bn/JoZTEXRSlEx3+SfgZcJAVuTMOksYq9xe9O6s4Ekg84aKBObEaVXKOEilULRqviSLAYJldnoWV9c07kwtiCg==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.5.2.tgz", + "integrity": "sha512-XsPxojXGRA0CoDD7Vis59ucz2p3cQFU5C+19tz3tLEAlhYKkK77IL0cjYjikY9wXnOaBeEdm1rOgSJjbZWpcZg==", "dev": true, "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^26.3.0", + "jest-util": "^26.5.2", "read-pkg-up": "^7.0.1", "resolve": "^1.17.0", "slash": "^3.0.0" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -8286,51 +8258,50 @@ } }, "jest-resolve-dependencies": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.4.2.tgz", - "integrity": "sha512-ADHaOwqEcVc71uTfySzSowA/RdxUpCxhxa2FNLiin9vWLB1uLPad3we+JSSROq5+SrL9iYPdZZF8bdKM7XABTQ==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.5.2.tgz", + "integrity": "sha512-LLkc8LuRtxqOx0AtX/Npa2C4I23WcIrwUgNtHYXg4owYF/ZDQShcwBAHjYZIFR06+HpQcZ43+kCTMlQ3aDCYTg==", "dev": true, "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "jest-regex-util": "^26.0.0", - "jest-snapshot": "^26.4.2" + "jest-snapshot": "^26.5.2" } }, "jest-runner": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.4.2.tgz", - "integrity": "sha512-FgjDHeVknDjw1gRAYaoUoShe1K3XUuFMkIaXbdhEys+1O4bEJS8Avmn4lBwoMfL8O5oFTdWYKcf3tEJyyYyk8g==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.5.2.tgz", + "integrity": "sha512-GKhYxtSX5+tXZsd2QwfkDqPIj5C2HqOdXLRc2x2qYqWE26OJh17xo58/fN/mLhRkO4y6o60ZVloan7Kk5YA6hg==", "dev": true, "requires": { - "@jest/console": "^26.3.0", - "@jest/environment": "^26.3.0", - "@jest/test-result": "^26.3.0", - "@jest/types": "^26.3.0", + "@jest/console": "^26.5.2", + "@jest/environment": "^26.5.2", + "@jest/test-result": "^26.5.2", + "@jest/types": "^26.5.2", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.7.1", "exit": "^0.1.2", "graceful-fs": "^4.2.4", - "jest-config": "^26.4.2", + "jest-config": "^26.5.2", "jest-docblock": "^26.0.0", - "jest-haste-map": "^26.3.0", - "jest-leak-detector": "^26.4.2", - "jest-message-util": "^26.3.0", - "jest-resolve": "^26.4.0", - "jest-runtime": "^26.4.2", - "jest-util": "^26.3.0", - "jest-worker": "^26.3.0", + "jest-haste-map": "^26.5.2", + "jest-leak-detector": "^26.5.2", + "jest-message-util": "^26.5.2", + "jest-resolve": "^26.5.2", + "jest-runtime": "^26.5.2", + "jest-util": "^26.5.2", + "jest-worker": "^26.5.0", "source-map-support": "^0.5.6", "throat": "^5.0.0" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -8377,37 +8348,37 @@ } }, "jest-runtime": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.4.2.tgz", - "integrity": "sha512-4Pe7Uk5a80FnbHwSOk7ojNCJvz3Ks2CNQWT5Z7MJo4tX0jb3V/LThKvD9tKPNVNyeMH98J/nzGlcwc00R2dSHQ==", - "dev": true, - "requires": { - "@jest/console": "^26.3.0", - "@jest/environment": "^26.3.0", - "@jest/fake-timers": "^26.3.0", - "@jest/globals": "^26.4.2", - "@jest/source-map": "^26.3.0", - "@jest/test-result": "^26.3.0", - "@jest/transform": "^26.3.0", - "@jest/types": "^26.3.0", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.5.2.tgz", + "integrity": "sha512-zArr4DatX/Sn0wswX/AnAuJgmwgAR5rNtrUz36HR8BfMuysHYNq5sDbYHuLC4ICyRdy5ae/KQ+sczxyS9G6Qvw==", + "dev": true, + "requires": { + "@jest/console": "^26.5.2", + "@jest/environment": "^26.5.2", + "@jest/fake-timers": "^26.5.2", + "@jest/globals": "^26.5.2", + "@jest/source-map": "^26.5.0", + "@jest/test-result": "^26.5.2", + "@jest/transform": "^26.5.2", + "@jest/types": "^26.5.2", "@types/yargs": "^15.0.0", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.4", - "jest-config": "^26.4.2", - "jest-haste-map": "^26.3.0", - "jest-message-util": "^26.3.0", - "jest-mock": "^26.3.0", + "jest-config": "^26.5.2", + "jest-haste-map": "^26.5.2", + "jest-message-util": "^26.5.2", + "jest-mock": "^26.5.2", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.4.0", - "jest-snapshot": "^26.4.2", - "jest-util": "^26.3.0", - "jest-validate": "^26.4.2", + "jest-resolve": "^26.5.2", + "jest-snapshot": "^26.5.2", + "jest-util": "^26.5.2", + "jest-validate": "^26.5.2", "slash": "^3.0.0", "strip-bom": "^4.0.0", - "yargs": "^15.3.1" + "yargs": "^15.4.1" }, "dependencies": { "ansi-regex": { @@ -8417,12 +8388,11 @@ "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -8520,9 +8490,9 @@ } }, "jest-serializer": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.3.0.tgz", - "integrity": "sha512-IDRBQBLPlKa4flg77fqg0n/pH87tcRKwe8zxOVTWISxGpPHYkRZ1dXKyh04JOja7gppc60+soKVZ791mruVdow==", + "version": "26.5.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.5.0.tgz", + "integrity": "sha512-+h3Gf5CDRlSLdgTv7y0vPIAoLgX/SI7T4v6hy+TEXMgYbv+ztzbg5PSN6mUXAT/hXYHvZRWm+MaObVfqkhCGxA==", "dev": true, "requires": { "@types/node": "*", @@ -8530,35 +8500,35 @@ } }, "jest-snapshot": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.4.2.tgz", - "integrity": "sha512-N6Uub8FccKlf5SBFnL2Ri/xofbaA68Cc3MGjP/NuwgnsvWh+9hLIR/DhrxbSiKXMY9vUW5dI6EW1eHaDHqe9sg==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.5.2.tgz", + "integrity": "sha512-MkXIDvEefzDubI/WaDVSRH4xnkuirP/Pz8LhAIDXcVQTmcEfwxywj5LGwBmhz+kAAIldA7XM4l96vbpzltSjqg==", "dev": true, "requires": { "@babel/types": "^7.0.0", - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", + "@types/babel__traverse": "^7.0.4", "@types/prettier": "^2.0.0", "chalk": "^4.0.0", - "expect": "^26.4.2", + "expect": "^26.5.2", "graceful-fs": "^4.2.4", - "jest-diff": "^26.4.2", + "jest-diff": "^26.5.2", "jest-get-type": "^26.3.0", - "jest-haste-map": "^26.3.0", - "jest-matcher-utils": "^26.4.2", - "jest-message-util": "^26.3.0", - "jest-resolve": "^26.4.0", + "jest-haste-map": "^26.5.2", + "jest-matcher-utils": "^26.5.2", + "jest-message-util": "^26.5.2", + "jest-resolve": "^26.5.2", "natural-compare": "^1.4.0", - "pretty-format": "^26.4.2", + "pretty-format": "^26.5.2", "semver": "^7.3.2" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -8588,9 +8558,9 @@ "dev": true }, "diff-sequences": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.3.0.tgz", - "integrity": "sha512-5j5vdRcw3CNctePNYN0Wy2e/JbWT6cAYnXv5OuqPhDpyCGc0uLu2TK0zOCJWNB9kOIfYMSpIulRaDgIi4HJ6Ig==", + "version": "26.5.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.5.0.tgz", + "integrity": "sha512-ZXx86srb/iYy6jG71k++wBN9P9J05UNQ5hQHQd9MtMPvcqXPx/vKU69jfHV637D00Q2gSgPk2D+jSx3l1lDW/Q==", "dev": true }, "has-flag": { @@ -8600,15 +8570,15 @@ "dev": true }, "jest-diff": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.4.2.tgz", - "integrity": "sha512-6T1XQY8U28WH0Z5rGpQ+VqZSZz8EN8rZcBtfvXaOkbwxIEeRre6qnuZQlbY1AJ4MKDxQF8EkrCvK+hL/VkyYLQ==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.5.2.tgz", + "integrity": "sha512-HCSWDUGwsov5oTlGzrRM+UPJI/Dpqi9jzeV0fdRNi3Ch5bnoXhnyJMmVg2juv9081zLIy3HGPI5mcuGgXM2xRA==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^26.3.0", + "diff-sequences": "^26.5.0", "jest-get-type": "^26.3.0", - "pretty-format": "^26.4.2" + "pretty-format": "^26.5.2" } }, "jest-get-type": { @@ -8635,12 +8605,12 @@ } }, "jest-util": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.3.0.tgz", - "integrity": "sha512-4zpn6bwV0+AMFN0IYhH/wnzIQzRaYVrz1A8sYnRnj4UXDXbOVtWmlaZkO9mipFqZ13okIfN87aDoJWB7VH6hcw==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.5.2.tgz", + "integrity": "sha512-WTL675bK+GSSAYgS8z9FWdCT2nccO1yTIplNLPlP0OD8tUk/H5IrWKMMRudIQQ0qp8bb4k+1Qa8CxGKq9qnYdg==", "dev": true, "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -8649,12 +8619,11 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -8701,26 +8670,25 @@ } }, "jest-validate": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.4.2.tgz", - "integrity": "sha512-blft+xDX7XXghfhY0mrsBCYhX365n8K5wNDC4XAcNKqqjEzsRUSXP44m6PL0QJEW2crxQFLLztVnJ4j7oPlQrQ==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.5.2.tgz", + "integrity": "sha512-FmJks0zY36mp6Af/5sqO6CTL9bNMU45yKCJk3hrz8d2aIqQIlN1pr9HPIwZE8blLaewOla134nt5+xAmWsx3SQ==", "dev": true, "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "camelcase": "^6.0.0", "chalk": "^4.0.0", "jest-get-type": "^26.3.0", "leven": "^3.1.0", - "pretty-format": "^26.4.2" + "pretty-format": "^26.5.2" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -8779,27 +8747,26 @@ } }, "jest-watcher": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.3.0.tgz", - "integrity": "sha512-XnLdKmyCGJ3VoF6G/p5ohbJ04q/vv5aH9ENI+i6BL0uu9WWB6Z7Z2lhQQk0d2AVZcRGp1yW+/TsoToMhBFPRdQ==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.5.2.tgz", + "integrity": "sha512-i3m1NtWzF+FXfJ3ljLBB/WQEp4uaNhX7QcQUWMokcifFTUQBDFyUMEwk0JkJ1kopHbx7Een3KX0Q7+9koGM/Pw==", "dev": true, "requires": { - "@jest/test-result": "^26.3.0", - "@jest/types": "^26.3.0", + "@jest/test-result": "^26.5.2", + "@jest/types": "^26.5.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^26.3.0", + "jest-util": "^26.5.2", "string-length": "^4.0.1" }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -8846,9 +8813,9 @@ } }, "jest-worker": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.3.0.tgz", - "integrity": "sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw==", + "version": "26.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.5.0.tgz", + "integrity": "sha512-kTw66Dn4ZX7WpjZ7T/SUDgRhapFRKWmisVAF0Rv4Fu8SLFD7eLbqpLvbxVqYhSgaWa7I+bW7pHnbyfNsH6stug==", "dev": true, "requires": { "@types/node": "*", @@ -8934,9 +8901,9 @@ }, "dependencies": { "acorn": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", - "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true } } @@ -9231,9 +9198,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } @@ -9291,9 +9258,9 @@ "dev": true }, "make-fetch-happen": { - "version": "8.0.9", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.9.tgz", - "integrity": "sha512-uHa4gv/NIdm9cUvfOhYb57nxrCY08iyMRXru0jbpaH57Q3NCge/ypY7fOvgCr8tPyucKrGbVndKhjXE0IX0VfQ==", + "version": "8.0.10", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.10.tgz", + "integrity": "sha512-jPLPKQjBmDLK5r1BdyDyNKBytmkv2AsDWm2CxHJh+fqhSmC9Pmb7RQxwOq8xQig9+AWIS49+51k4f6vDQ3VnrQ==", "optional": true, "requires": { "agentkeepalive": "^4.1.0", @@ -9958,9 +9925,9 @@ "integrity": "sha512-ZyRdSVs9GczI+39B7tNXsxfBXQOYnEF6l/q2aLYG8wSEvRHRDXAlzZ1SIosDibM02pLahGkDNLFC+nZ8uzJGDQ==" }, "nestjs-rate-limiter": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/nestjs-rate-limiter/-/nestjs-rate-limiter-2.5.3.tgz", - "integrity": "sha512-mSWW/A63lg8O3ISll5fFONy6HFUyrieBFJxDsfAct+YiXToUNF+yVXLhytqZ37H1eEls1Ln4yl+jUmkaVijhVQ==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/nestjs-rate-limiter/-/nestjs-rate-limiter-2.5.6.tgz", + "integrity": "sha512-daBDy6HS1PKrFVxbwQRYkcQ/m0Jh4Th9V2qmYE7t44H3t00dK9z55pmdzSvqQ/4ITHxmlTe0KbcapeUbz4Wahg==", "requires": { "rate-limiter-flexible": "2.1.10" } @@ -9987,9 +9954,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } @@ -10473,12 +10440,11 @@ "dev": true }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -10753,9 +10719,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } @@ -10864,11 +10830,11 @@ "dev": true }, "pino": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.6.1.tgz", - "integrity": "sha512-DOgm7rn6ctBkBYemHXSLj7+j3o3U1q1FWBXbHcprur8mA93QcJSycEkEqhqKiFB9Mx/3Qld2FGr6+9yfQza0kA==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-6.7.0.tgz", + "integrity": "sha512-vPXJ4P9rWCwzlTJt+f0Ni4THc3DWyt8iDDCO4edQ8narTu6hnpzdXu8FqeSJCGndl1W6lfbYQUQihUO54y66Lw==", "requires": { - "fast-redact": "^2.0.0", + "fast-redact": "^3.0.0", "fast-safe-stringify": "^2.0.7", "flatstr": "^1.0.12", "pino-std-serializers": "^2.4.2", @@ -10960,11 +10926,11 @@ "dev": true }, "pretty-format": { - "version": "26.4.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.4.2.tgz", - "integrity": "sha512-zK6Gd8zDsEiVydOCGLkoBoZuqv8VTiHyAbKznXe/gaph/DAeZOmit9yMfgIz5adIgAMMs5XfoYSwAX3jcCO1tA==", + "version": "26.5.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.5.2.tgz", + "integrity": "sha512-VizyV669eqESlkOikKJI8Ryxl/kPpbdLwNdPs2GrbQs18MpySB5S0Yo0N7zkg2xTRiFq4CFw8ct5Vg4a0xP0og==", "requires": { - "@jest/types": "^26.3.0", + "@jest/types": "^26.5.2", "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", "react-is": "^16.12.0" @@ -10976,11 +10942,10 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -11551,9 +11516,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" } } }, @@ -13123,9 +13088,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } @@ -13273,9 +13238,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true } } @@ -13290,9 +13255,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true } } @@ -13382,11 +13347,10 @@ }, "dependencies": { "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -13440,9 +13404,9 @@ } }, "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "xml2js": { "version": "0.4.23", @@ -13985,9 +13949,9 @@ "dev": true }, "whatwg-url": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.3.0.tgz", - "integrity": "sha512-BQRf/ej5Rp3+n7k0grQXZj9a1cHtsp4lqj01p59xBWFKdezR8sO37XnpafwNqiFac/v2Il12EIMjX/Y4VZtT8Q==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.4.0.tgz", + "integrity": "sha512-vwTUFf6V4zhcPkWp/4CQPr1TW9Ml6SF4lVyaIMBdJw5i6qUUJ1QWM4Z6YYVkfka0OUIzVo/0aNtGVGk256IKWw==", "dev": true, "requires": { "lodash.sortby": "^4.7.0", @@ -14057,11 +14021,10 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -14250,11 +14213,10 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" } }, @@ -14363,9 +14325,9 @@ }, "dependencies": { "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "optional": true } } diff --git a/server/package.json b/server/package.json index 49165ec5..c1467e33 100644 --- a/server/package.json +++ b/server/package.json @@ -49,7 +49,7 @@ "nan": "^2.14.1", "nest-raven": "^7.0.0", "nest-router": "^1.0.9", - "nestjs-rate-limiter": "2.5.3", + "nestjs-rate-limiter": "^2.5.6", "nodemailer": "^6.4.13", "passport": "^0.4.1", "passport-jwt": "^4.0.0", From 356c46fedd6a160dab028a012d6b9c953f7ffe0b Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 11 Oct 2020 18:10:17 +0300 Subject: [PATCH 34/42] [client] Update structure of less files --- client/config/constants.ts | 4 +- .../{src/styles/antd => config}/override.less | 0 client/next.config.js | 2 +- .../components/pages/[feed]/FeedHeader.tsx | 3 +- .../pages}/[feed]/style.less | 0 .../pages/create-feed/Step1/index.tsx | 2 +- .../pages/create-feed/Step2/index.tsx | 2 +- .../pages/create-feed/Step3/index.tsx | 2 +- .../pages/create-feed}/style.less | 0 .../src/components/pages/help/helpMenus.tsx | 2 +- .../pages/help/style.less | 0 client/src/pages/_app.tsx | 2 +- .../pages/auth/email-confirmation/index.tsx | 2 +- .../pages/auth/email-confirmation/style.less | 0 .../auth/sign-in/account-recover/index.tsx | 2 +- .../auth/sign-in/account-recover/style.less | 0 .../auth/sign-in/forgot-password/index.tsx | 2 +- .../auth/sign-in/forgot-password/style.less | 0 client/src/pages/auth/sign-in/index.tsx | 2 +- .../pages/auth/sign-in/style.less | 0 .../sign-up/account-verification/index.tsx | 2 +- .../sign-up/account-verification/style.less | 0 client/src/pages/auth/sign-up/index.tsx | 2 +- .../pages/auth/sign-up/style.less | 0 client/src/pages/create-feed/index.tsx | 2 +- .../{styles => }/pages/create-feed/style.less | 0 client/src/{styles/antd => pages}/global.less | 0 client/src/pages/help/[topic-slug]/index.tsx | 2 +- .../pages/help/[topic-slug]/style.less | 0 client/src/pages/messages/index.tsx | 2 +- .../{styles => }/pages/messages/style.less | 0 client/src/pages/settings/index.tsx | 2 +- .../{styles => }/pages/settings/style.less | 0 client/src/services/utils.less | 50 ------------------- 34 files changed, 19 insertions(+), 70 deletions(-) rename client/{src/styles/antd => config}/override.less (100%) rename client/src/{styles/components => components/pages}/[feed]/style.less (100%) rename client/src/{styles/components/StepForm => components/pages/create-feed}/style.less (100%) rename client/src/{styles => components}/pages/help/style.less (100%) rename client/src/{styles => }/pages/auth/email-confirmation/style.less (100%) rename client/src/{styles => }/pages/auth/sign-in/account-recover/style.less (100%) rename client/src/{styles => }/pages/auth/sign-in/forgot-password/style.less (100%) rename client/src/{styles => }/pages/auth/sign-in/style.less (100%) rename client/src/{styles => }/pages/auth/sign-up/account-verification/style.less (100%) rename client/src/{styles => }/pages/auth/sign-up/style.less (100%) rename client/src/{styles => }/pages/create-feed/style.less (100%) rename client/src/{styles/antd => pages}/global.less (100%) rename client/src/{styles => }/pages/help/[topic-slug]/style.less (100%) rename client/src/{styles => }/pages/messages/style.less (100%) rename client/src/{styles => }/pages/settings/style.less (100%) delete mode 100644 client/src/services/utils.less diff --git a/client/config/constants.ts b/client/config/constants.ts index 038dfd9a..2b881b0c 100644 --- a/client/config/constants.ts +++ b/client/config/constants.ts @@ -1,6 +1,6 @@ // APP -export const API_URL = process.env.NODE_ENV === 'production' ? 'https://server.feednext.io/api' : 'http://localhost/api' -export const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'https://server.feednext.io' : 'http://localhost' +export const API_URL = process.env.NODE_ENV === 'production' ? 'https://server.feednext.io/api' : 'http://localhost:3000/api' +export const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'https://server.feednext.io' : 'http://localhost:3000' // ROLES export const Guest = -1 diff --git a/client/src/styles/antd/override.less b/client/config/override.less similarity index 100% rename from client/src/styles/antd/override.less rename to client/config/override.less diff --git a/client/next.config.js b/client/next.config.js index 58c3b409..6422c01b 100644 --- a/client/next.config.js +++ b/client/next.config.js @@ -4,7 +4,7 @@ const withLess = require('@zeit/next-less') const lessToJS = require('less-vars-to-js') const fs = require('fs') const path = require('path') -const themeVariables = lessToJS(fs.readFileSync(path.resolve(__dirname, './src/styles/antd/override.less'), 'utf8')) +const themeVariables = lessToJS(fs.readFileSync(path.resolve(__dirname, './config/override.less'), 'utf8')) module.exports = withCSS(withLess({ lessLoaderOptions: { diff --git a/client/src/components/pages/[feed]/FeedHeader.tsx b/client/src/components/pages/[feed]/FeedHeader.tsx index e7253696..5c9e7270 100644 --- a/client/src/components/pages/[feed]/FeedHeader.tsx +++ b/client/src/components/pages/[feed]/FeedHeader.tsx @@ -33,8 +33,7 @@ import { getUserRateOfTitle, rateTitle, deleteTitle } from '@/services/api' import { SignModal } from '@/components/global/SignModal' import { API_URL } from '@/../config/constants' import { FeedHeaderProps } from '@/@types/pages' -import '@/styles/components/[feed]/style.less' -import { title } from 'process' +import './style.less' const FeedHeader: React.FC = (props): JSX.Element => { const { diff --git a/client/src/styles/components/[feed]/style.less b/client/src/components/pages/[feed]/style.less similarity index 100% rename from client/src/styles/components/[feed]/style.less rename to client/src/components/pages/[feed]/style.less diff --git a/client/src/components/pages/create-feed/Step1/index.tsx b/client/src/components/pages/create-feed/Step1/index.tsx index 279b33d0..72f86eb4 100644 --- a/client/src/components/pages/create-feed/Step1/index.tsx +++ b/client/src/components/pages/create-feed/Step1/index.tsx @@ -10,8 +10,8 @@ import { Step1Props } from '@/@types/pages' import { ImageUpload } from '@/components/global/ImageUpload' import { ListOfSimilarFeeds } from '@/components/global/ListOfSimilarFeeds' import { StepContext } from '@/services/step.context.service' -import '@/styles/components/StepForm/style.less' import { searchTagByName } from '@/services/api' +import '../style.less' const formItemLayout = { labelCol: { diff --git a/client/src/components/pages/create-feed/Step2/index.tsx b/client/src/components/pages/create-feed/Step2/index.tsx index 6b0b0644..5072a201 100644 --- a/client/src/components/pages/create-feed/Step2/index.tsx +++ b/client/src/components/pages/create-feed/Step2/index.tsx @@ -11,7 +11,7 @@ import * as stringToColor from 'string-to-color' import { PageHelmet } from '@/components/global/PageHelmet' import { StepContext } from '@/services/step.context.service' import { Step2Props } from '@/@types/pages' -import '@/styles/components/StepForm/style.less' +import '../style.less' const formItemLayout = { labelCol: { diff --git a/client/src/components/pages/create-feed/Step3/index.tsx b/client/src/components/pages/create-feed/Step3/index.tsx index 51367231..9231c1d7 100644 --- a/client/src/components/pages/create-feed/Step3/index.tsx +++ b/client/src/components/pages/create-feed/Step3/index.tsx @@ -10,7 +10,7 @@ import * as stringToColor from 'string-to-color' import { PageHelmet } from '@/components/global/PageHelmet' import { StepContext } from '@/services/step.context.service' import { Step3Props } from '@/@types/pages' -import '@/styles/components/StepForm/style.less' +import '../style.less' const Step3 = ({ titleSlugForRouting, feedCreatedSuccessfully }: Step3Props): JSX.Element => { const router = useRouter() diff --git a/client/src/styles/components/StepForm/style.less b/client/src/components/pages/create-feed/style.less similarity index 100% rename from client/src/styles/components/StepForm/style.less rename to client/src/components/pages/create-feed/style.less diff --git a/client/src/components/pages/help/helpMenus.tsx b/client/src/components/pages/help/helpMenus.tsx index 620301cc..1f13bf21 100644 --- a/client/src/components/pages/help/helpMenus.tsx +++ b/client/src/components/pages/help/helpMenus.tsx @@ -11,7 +11,7 @@ import guidePng from '@/assets/guide.png' import securityPng from '@/assets/privacyAndSecurity.png' import rulesPng from '@/assets/rulesAndReporting.png' import content from './content.json' -import '@/styles/pages/help/style.less' +import './style.less' const helpMenus = [ { titleReadable: 'F.A.Q', title: 'f.a.q', logo: faqPng }, diff --git a/client/src/styles/pages/help/style.less b/client/src/components/pages/help/style.less similarity index 100% rename from client/src/styles/pages/help/style.less rename to client/src/components/pages/help/style.less diff --git a/client/src/pages/_app.tsx b/client/src/pages/_app.tsx index 4c294b4b..5f0f2340 100644 --- a/client/src/pages/_app.tsx +++ b/client/src/pages/_app.tsx @@ -10,7 +10,7 @@ import 'nprogress/nprogress.css' // Local files import { store, persistor } from '@/redux/store' -import '@/styles/antd/global.less' +import './global.less' NProgress.configure({ showSpinner: false }) Router.events.on('routeChangeStart', () => NProgress.start()) diff --git a/client/src/pages/auth/email-confirmation/index.tsx b/client/src/pages/auth/email-confirmation/index.tsx index 63ff0c89..a99e19e4 100644 --- a/client/src/pages/auth/email-confirmation/index.tsx +++ b/client/src/pages/auth/email-confirmation/index.tsx @@ -11,8 +11,8 @@ import { useRouter, NextRouter } from 'next/router' import { PageHelmet } from '@/components/global/PageHelmet' import { verifyUpdatedEmail } from '@/services/api' import NotFoundPage from '@/pages/404' -import '@/styles/pages/auth/email-confirmation/style.less' import AuthLayout from '@/layouts/AuthLayout' +import './style.less' const EmailConfirmation: React.FunctionComponent = () => { const router: NextRouter & { query: { token?: string } } = useRouter() diff --git a/client/src/styles/pages/auth/email-confirmation/style.less b/client/src/pages/auth/email-confirmation/style.less similarity index 100% rename from client/src/styles/pages/auth/email-confirmation/style.less rename to client/src/pages/auth/email-confirmation/style.less diff --git a/client/src/pages/auth/sign-in/account-recover/index.tsx b/client/src/pages/auth/sign-in/account-recover/index.tsx index ed7c2cd5..3ad888ec 100644 --- a/client/src/pages/auth/sign-in/account-recover/index.tsx +++ b/client/src/pages/auth/sign-in/account-recover/index.tsx @@ -11,7 +11,7 @@ import { PageHelmet } from '@/components/global/PageHelmet' import { recoverAccountWithKey } from '@/services/api' import NotFoundPage from '@/pages/404' import AuthLayout from '@/layouts/AuthLayout' -import '@/styles/pages/auth/sign-in/account-recover/style.less' +import './style.less' const AccountRecover: React.FunctionComponent = () => { const router: NextRouter & { diff --git a/client/src/styles/pages/auth/sign-in/account-recover/style.less b/client/src/pages/auth/sign-in/account-recover/style.less similarity index 100% rename from client/src/styles/pages/auth/sign-in/account-recover/style.less rename to client/src/pages/auth/sign-in/account-recover/style.less diff --git a/client/src/pages/auth/sign-in/forgot-password/index.tsx b/client/src/pages/auth/sign-in/forgot-password/index.tsx index 22330586..012a8004 100644 --- a/client/src/pages/auth/sign-in/forgot-password/index.tsx +++ b/client/src/pages/auth/sign-in/forgot-password/index.tsx @@ -9,7 +9,7 @@ import React, { useState } from 'react' import { PageHelmet } from '@/components/global/PageHelmet' import { generateRecoveryKey } from '@/services/api' import AuthLayout from '@/layouts/AuthLayout' -import '@/styles/pages/auth/sign-in/forgot-password/style.less' +import './style.less' const ForgotPassword: React.FunctionComponent = () => { const [requestOnGoing, setRequestOnGoing] = useState(false) diff --git a/client/src/styles/pages/auth/sign-in/forgot-password/style.less b/client/src/pages/auth/sign-in/forgot-password/style.less similarity index 100% rename from client/src/styles/pages/auth/sign-in/forgot-password/style.less rename to client/src/pages/auth/sign-in/forgot-password/style.less diff --git a/client/src/pages/auth/sign-in/index.tsx b/client/src/pages/auth/sign-in/index.tsx index f3da03a1..fc9db024 100644 --- a/client/src/pages/auth/sign-in/index.tsx +++ b/client/src/pages/auth/sign-in/index.tsx @@ -14,7 +14,7 @@ import { SET_ACCESS_TOKEN } from '@/redux/Actions/Global' import { PageHelmet } from '@/components/global/PageHelmet' import { signIn } from '@/services/api' import AuthLayout from '@/layouts/AuthLayout' -import '@/styles/pages/auth/sign-in/style.less' +import './style.less' export declare interface FormDataType { usernameOrEmail: string diff --git a/client/src/styles/pages/auth/sign-in/style.less b/client/src/pages/auth/sign-in/style.less similarity index 100% rename from client/src/styles/pages/auth/sign-in/style.less rename to client/src/pages/auth/sign-in/style.less diff --git a/client/src/pages/auth/sign-up/account-verification/index.tsx b/client/src/pages/auth/sign-up/account-verification/index.tsx index 896bcfdc..de2ded55 100644 --- a/client/src/pages/auth/sign-up/account-verification/index.tsx +++ b/client/src/pages/auth/sign-up/account-verification/index.tsx @@ -11,7 +11,7 @@ import { PageHelmet } from '@/components/global/PageHelmet' import { verifyAccount } from '@/services/api' import NotFoundPage from '@/pages/404' import AuthLayout from '@/layouts/AuthLayout' -import '@/styles/pages/auth/sign-up/account-verification/style.less' +import './style.less' const AccountVerification: React.FunctionComponent = () => { const router: NextRouter & { query: { token?: string } } = useRouter() diff --git a/client/src/styles/pages/auth/sign-up/account-verification/style.less b/client/src/pages/auth/sign-up/account-verification/style.less similarity index 100% rename from client/src/styles/pages/auth/sign-up/account-verification/style.less rename to client/src/pages/auth/sign-up/account-verification/style.less diff --git a/client/src/pages/auth/sign-up/index.tsx b/client/src/pages/auth/sign-up/index.tsx index 9ae11fc0..62550e75 100644 --- a/client/src/pages/auth/sign-up/index.tsx +++ b/client/src/pages/auth/sign-up/index.tsx @@ -12,7 +12,7 @@ import { PageHelmet } from '@/components/global/PageHelmet' import RegisterResult from '@/components/pages/sign-up/result' import { Aggrements } from '@/components/global/Aggrements' import AuthLayout from '@/layouts/AuthLayout' -import '@/styles/pages/auth/sign-up/style.less' +import './style.less' export declare interface FormDataType { fullName: string diff --git a/client/src/styles/pages/auth/sign-up/style.less b/client/src/pages/auth/sign-up/style.less similarity index 100% rename from client/src/styles/pages/auth/sign-up/style.less rename to client/src/pages/auth/sign-up/style.less diff --git a/client/src/pages/create-feed/index.tsx b/client/src/pages/create-feed/index.tsx index 0699dc20..1e9de6af 100644 --- a/client/src/pages/create-feed/index.tsx +++ b/client/src/pages/create-feed/index.tsx @@ -15,7 +15,7 @@ import { AppLayout } from '@/layouts/AppLayout' import Step1 from '@/components/pages/create-feed/Step1' import Step2 from '@/components/pages/create-feed/Step2' import Step3 from '@/components/pages/create-feed/Step3' -import '@/styles/pages/create-feed/style.less' +import './style.less' const CreateFeed: React.FC = () => { const accessToken = useSelector((state: any) => state.global.accessToken) diff --git a/client/src/styles/pages/create-feed/style.less b/client/src/pages/create-feed/style.less similarity index 100% rename from client/src/styles/pages/create-feed/style.less rename to client/src/pages/create-feed/style.less diff --git a/client/src/styles/antd/global.less b/client/src/pages/global.less similarity index 100% rename from client/src/styles/antd/global.less rename to client/src/pages/global.less diff --git a/client/src/pages/help/[topic-slug]/index.tsx b/client/src/pages/help/[topic-slug]/index.tsx index eb49c8a6..76cf3e39 100644 --- a/client/src/pages/help/[topic-slug]/index.tsx +++ b/client/src/pages/help/[topic-slug]/index.tsx @@ -14,7 +14,7 @@ import faqPng from '@/assets/faq.png' import guidePng from '@/assets/guide.png' import securityPng from '@/assets/privacyAndSecurity.png' import rulesPng from '@/assets/rulesAndReporting.png' -import '@/styles/pages/help/[topic-slug]/style.less' +import './style.less' const topicData = { 'f.a.q': { titleReadable: 'F.A.Q', logo: faqPng }, diff --git a/client/src/styles/pages/help/[topic-slug]/style.less b/client/src/pages/help/[topic-slug]/style.less similarity index 100% rename from client/src/styles/pages/help/[topic-slug]/style.less rename to client/src/pages/help/[topic-slug]/style.less diff --git a/client/src/pages/messages/index.tsx b/client/src/pages/messages/index.tsx index c68a2e63..bfe058d8 100644 --- a/client/src/pages/messages/index.tsx +++ b/client/src/pages/messages/index.tsx @@ -15,7 +15,7 @@ import { PageHelmet } from '@/components/global/PageHelmet' import { User } from '@/../config/constants' import { ConversationAttributes } from '@/@types/pages' import { AppLayout } from '@/layouts/AppLayout' -import '@/styles/pages/messages/style.less' +import './style.less' const Messages = (): JSX.Element => { const [currentConversations, setCurrentConversations] = useState<{ diff --git a/client/src/styles/pages/messages/style.less b/client/src/pages/messages/style.less similarity index 100% rename from client/src/styles/pages/messages/style.less rename to client/src/pages/messages/style.less diff --git a/client/src/pages/settings/index.tsx b/client/src/pages/settings/index.tsx index baa6596a..99c8edf3 100644 --- a/client/src/pages/settings/index.tsx +++ b/client/src/pages/settings/index.tsx @@ -11,7 +11,7 @@ import { AccountSettings } from '../../components/pages/settings/account-setting import { PageHelmet } from '@/components/global/PageHelmet' import { User } from '@/../config/constants' import { AppLayout } from '@/layouts/AppLayout' -import '@/styles/pages/settings/style.less' +import './style.less' const Settings = (): JSX.Element => { const user = useSelector((state: any) => state.user?.attributes.user) diff --git a/client/src/styles/pages/settings/style.less b/client/src/pages/settings/style.less similarity index 100% rename from client/src/styles/pages/settings/style.less rename to client/src/pages/settings/style.less diff --git a/client/src/services/utils.less b/client/src/services/utils.less deleted file mode 100644 index 13ee0df5..00000000 --- a/client/src/services/utils.less +++ /dev/null @@ -1,50 +0,0 @@ -.textOverflow() { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - word-break: break-all; -} - -.textOverflowMulti(@line: 3, @bg: #fff) { - position: relative; - max-height: @line * 1.5em; - margin-right: -1em; - padding-right: 1em; - overflow: hidden; - line-height: 1.5em; - text-align: justify; - &::before { - position: absolute; - right: 14px; - bottom: 0; - padding: 0 1px; - background: @bg; - content: '...'; - } - &::after { - position: absolute; - right: 14px; - width: 1em; - height: 1em; - margin-top: 0.2em; - background: white; - content: ''; - } -} - -// mixins for clearfix -// ------------------------ -.clearfix() { - zoom: 1; - &::before, - &::after { - display: table; - content: ' '; - } - &::after { - clear: both; - height: 0; - font-size: 0; - visibility: hidden; - } -} From b7240ecbb4bb91ed2e842275e1478a4b99055c41 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 11 Oct 2020 18:34:19 +0300 Subject: [PATCH 35/42] [client] create environment variables & update constants --- client/.env.development | 2 ++ client/.env.production | 2 ++ client/config/constants.ts | 14 ++------------ 3 files changed, 6 insertions(+), 12 deletions(-) create mode 100644 client/.env.development create mode 100644 client/.env.production diff --git a/client/.env.development b/client/.env.development new file mode 100644 index 00000000..a63c51fc --- /dev/null +++ b/client/.env.development @@ -0,0 +1,2 @@ +API_URL=http://localhost:3000/api +SOCKET_URL=http://localhost:3000 \ No newline at end of file diff --git a/client/.env.production b/client/.env.production new file mode 100644 index 00000000..0cafd68f --- /dev/null +++ b/client/.env.production @@ -0,0 +1,2 @@ +API_URL=https://server.feednext.io/api +SOCKET_URL=https://server.feednext.io \ No newline at end of file diff --git a/client/config/constants.ts b/client/config/constants.ts index 2b881b0c..ce2ab242 100644 --- a/client/config/constants.ts +++ b/client/config/constants.ts @@ -1,12 +1,2 @@ -// APP -export const API_URL = process.env.NODE_ENV === 'production' ? 'https://server.feednext.io/api' : 'http://localhost:3000/api' -export const SOCKET_URL = process.env.NODE_ENV === 'production' ? 'https://server.feednext.io' : 'http://localhost:3000' - -// ROLES -export const Guest = -1 -export const User = 0 -export const JuniorAuthor = 1 -export const MidLevelAuthor = 2 -export const SeniorAuthor = 3 -export const Admin = 4 -export const SuperAdmin = 5 +export const API_URL = process.env.API_URL +export const SOCKET_URL = process.env.SOCKET_URL From d5b361501b0494968197ec9c2d83b45176495fca Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 11 Oct 2020 18:35:08 +0300 Subject: [PATCH 36/42] [client] create enum for Roles --- client/src/components/pages/[feed]/FeedEntries.tsx | 5 +++-- client/src/enums/Roles/roles.ts | 9 +++++++++ client/src/enums/index.ts | 1 + client/src/middleware/RouteHandler.tsx | 4 ++-- client/src/pages/404.tsx | 4 ++-- client/src/pages/[feed]/index.tsx | 5 +++-- client/src/pages/create-feed/index.tsx | 4 ++-- client/src/pages/entry/[id]/index.tsx | 5 +++-- client/src/pages/help/[topic-slug]/index.tsx | 4 ++-- client/src/pages/help/index.tsx | 4 ++-- client/src/pages/index.tsx | 7 ++++--- client/src/pages/messages/compose/index.tsx | 5 +++-- client/src/pages/messages/index.tsx | 4 ++-- client/src/pages/settings/index.tsx | 4 ++-- client/src/pages/user/[username]/index.tsx | 5 +++-- 15 files changed, 43 insertions(+), 27 deletions(-) create mode 100644 client/src/enums/Roles/roles.ts create mode 100644 client/src/enums/index.ts diff --git a/client/src/components/pages/[feed]/FeedEntries.tsx b/client/src/components/pages/[feed]/FeedEntries.tsx index 37de6fea..6d472a4a 100644 --- a/client/src/components/pages/[feed]/FeedEntries.tsx +++ b/client/src/components/pages/[feed]/FeedEntries.tsx @@ -33,8 +33,9 @@ import { PaginationProps } from 'antd/lib/pagination' // Local files import { voteEntry, undoEntryVote, updateEntry, deleteEntry } from '@/services/api' import { SignModal } from '@/components/global/SignModal' -import { API_URL, Admin } from '@/../config/constants' +import { API_URL } from '@/../config/constants' import { FeedEntriesProps } from '@/@types/pages' +import { Roles } from '@/enums' import AddEntry from './AddEntry' const FeedEntries: React.FC = (props): JSX.Element => { @@ -281,7 +282,7 @@ const FeedEntries: React.FC = (props): JSX.Element => { > {item.text} - {(userState?.username === item.written_by || userState?.role >= Admin) && ( + {(userState?.username === item.written_by || userState?.role >= Roles.Admin) && ( = (props) => { const router = useRouter() @@ -98,7 +98,7 @@ export const RouteHandler: React.FC<{ authority: number, children: any }> = (pro } }, [lastMessageFromSocket]) - if (process.browser && !user && props.authority >= User && router.route !== '/') { + if (process.browser && !user && props.authority >= Roles.User && router.route !== '/') { router.push('/auth/sign-in') return null } diff --git a/client/src/pages/404.tsx b/client/src/pages/404.tsx index 20e29e71..31940cd7 100644 --- a/client/src/pages/404.tsx +++ b/client/src/pages/404.tsx @@ -8,12 +8,12 @@ import { useRouter } from 'next/router' // Local files import { AppLayout } from '@/layouts/AppLayout' import { PageHelmet } from '@/components/global/PageHelmet' -import { Guest } from '@/../config/constants' +import { Roles } from '@/enums' const NotFoundPage: React.FC<{}> = () => { const router = useRouter() return ( - + = (props): JSX.Element => { if (!entryList || !title || (!averageTitleRate && averageTitleRate !== 0)) return return ( - + { const accessToken = useSelector((state: any) => state.global.accessToken) @@ -115,7 +115,7 @@ const CreateFeed: React.FC = () => { if (!stepComponent) handleStepMovement() return ( - + diff --git a/client/src/pages/entry/[id]/index.tsx b/client/src/pages/entry/[id]/index.tsx index ea55195d..f60f5858 100644 --- a/client/src/pages/entry/[id]/index.tsx +++ b/client/src/pages/entry/[id]/index.tsx @@ -8,13 +8,14 @@ import { useRouter } from 'next/router' import * as stringToColor from 'string-to-color' // Local files -import { API_URL, Guest } from '@/../config/constants' +import { API_URL } from '@/../config/constants' import { TitleResponseData, EntryResponseData } from '@/@types/api' import { PageHelmet } from '@/components/global/PageHelmet' import { getEntryPageInitialValues } from '@/services/initializations/[entry]' import { NextPage } from 'next' import { EntryPageInitials } from '@/@types/initializations' import { AppLayout } from '@/layouts/AppLayout' +import { Roles } from '@/enums' import NotFoundPage from '../../404' const Entry: NextPage = (props): JSX.Element => { @@ -78,7 +79,7 @@ const Entry: NextPage = (props): JSX.Element => { ) return ( - + { } return ( - + { return ( - + = (props): JSX.Element => { const [trendingTags, setTrendingTags] = useState(props.trendingTags) @@ -249,7 +250,7 @@ const Homepage: NextPage = (props): JSX.Element => { ) return ( - + { @@ -77,7 +78,7 @@ const Compose: React.FC = (): JSX.Element => { const handleOnSelect = (username: string): void => setMessageForm({ ...messageForm, to: username }) return ( - + { const [currentConversations, setCurrentConversations] = useState<{ @@ -40,7 +40,7 @@ const Messages = (): JSX.Element => { } return ( - + { @@ -18,7 +18,7 @@ const Settings = (): JSX.Element => { const accessToken = useSelector((state: any) => state.global.accessToken) return ( - + = (props): JSX.Element => { if (!user) return return ( - + Date: Sun, 11 Oct 2020 18:38:11 +0300 Subject: [PATCH 37/42] [client] update component folders --- .../{components/PrivacyPolicy/index.tsx => PrivacyPolicy.tsx} | 0 .../TermsAndConditions/index.tsx => TermsAndConditions.tsx} | 0 client/src/components/global/Aggrements/index.tsx | 4 ++-- .../global/SignModal/{components => }/LoginForm.tsx | 0 client/src/components/global/SignModal/index.tsx | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) rename client/src/components/global/Aggrements/{components/PrivacyPolicy/index.tsx => PrivacyPolicy.tsx} (100%) rename client/src/components/global/Aggrements/{components/TermsAndConditions/index.tsx => TermsAndConditions.tsx} (100%) rename client/src/components/global/SignModal/{components => }/LoginForm.tsx (100%) diff --git a/client/src/components/global/Aggrements/components/PrivacyPolicy/index.tsx b/client/src/components/global/Aggrements/PrivacyPolicy.tsx similarity index 100% rename from client/src/components/global/Aggrements/components/PrivacyPolicy/index.tsx rename to client/src/components/global/Aggrements/PrivacyPolicy.tsx diff --git a/client/src/components/global/Aggrements/components/TermsAndConditions/index.tsx b/client/src/components/global/Aggrements/TermsAndConditions.tsx similarity index 100% rename from client/src/components/global/Aggrements/components/TermsAndConditions/index.tsx rename to client/src/components/global/Aggrements/TermsAndConditions.tsx diff --git a/client/src/components/global/Aggrements/index.tsx b/client/src/components/global/Aggrements/index.tsx index 0da9f536..02127e81 100644 --- a/client/src/components/global/Aggrements/index.tsx +++ b/client/src/components/global/Aggrements/index.tsx @@ -5,8 +5,8 @@ import { Modal } from 'antd' import React from 'react' // Local files -import { PrivacyPolicy } from './components/PrivacyPolicy' -import { TermsAndConditions } from './components/TermsAndConditions' +import { PrivacyPolicy } from './PrivacyPolicy' +import { TermsAndConditions } from './TermsAndConditions' import { AggrementsProps } from '@/@types/components' export const Aggrements: React.FC = (props): JSX.Element => ( diff --git a/client/src/components/global/SignModal/components/LoginForm.tsx b/client/src/components/global/SignModal/LoginForm.tsx similarity index 100% rename from client/src/components/global/SignModal/components/LoginForm.tsx rename to client/src/components/global/SignModal/LoginForm.tsx diff --git a/client/src/components/global/SignModal/index.tsx b/client/src/components/global/SignModal/index.tsx index 3daac360..cabed9de 100644 --- a/client/src/components/global/SignModal/index.tsx +++ b/client/src/components/global/SignModal/index.tsx @@ -5,7 +5,7 @@ import { Modal, Typography, Divider } from 'antd' import React from 'react' // Local files -import { LoginForm } from './components/LoginForm' +import { LoginForm } from './LoginForm' import { SignModalProps } from '@/@types/components' import './style.less' From 2c24338fc0599d854f4f01aad9eeadcedd09f96d Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 11 Oct 2020 23:00:52 +0300 Subject: [PATCH 38/42] [client] add new package 'next-i18next' --- client/package-lock.json | 199 ++++++++++++++++++++++++++++++++++++++- client/package.json | 1 + 2 files changed, 198 insertions(+), 2 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 4885341b..cba7356b 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1458,21 +1458,63 @@ "fastq": "^1.6.0" } }, + "@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, + "@types/connect": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", + "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.8", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz", + "integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz", + "integrity": "sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, "@types/json-schema": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==" }, + "@types/mime": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", + "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==" + }, "@types/node": { "version": "14.11.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.2.tgz", - "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==", - "dev": true + "integrity": "sha512-jiE3QIxJ8JLNcb1Ps6rDbysDhN4xa8DJJvuC9prr6w+1tIh+QAbYyNF3tyiZNLDBIuBCf4KEcV2UvQm/V60xfA==" }, "@types/prop-types": { "version": "15.7.3", @@ -1480,6 +1522,16 @@ "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==", "dev": true }, + "@types/qs": { + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", + "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==" + }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" + }, "@types/react": { "version": "16.9.50", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.50.tgz", @@ -1490,6 +1542,15 @@ "csstype": "^3.0.2" } }, + "@types/serve-static": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.5.tgz", + "integrity": "sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ==", + "requires": { + "@types/express-serve-static-core": "*", + "@types/mime": "*" + } + }, "@typescript-eslint/eslint-plugin": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.3.0.tgz", @@ -4281,6 +4342,14 @@ "react-is": "^16.7.0" } }, + "html-parse-stringify2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz", + "integrity": "sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=", + "requires": { + "void-elements": "^2.0.1" + } + }, "htmlparser2": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz", @@ -4292,6 +4361,22 @@ "entities": "^2.0.0" } }, + "http-errors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.4.0.tgz", + "integrity": "sha1-bAJC3qaz33r9oVPHEImzHG6Cqr8=", + "requires": { + "inherits": "2.0.1", + "statuses": ">= 1.2.1 < 2" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + } + } + }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -4306,6 +4391,47 @@ "debug": "4" } }, + "i18next": { + "version": "19.8.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-19.8.2.tgz", + "integrity": "sha512-YWqkUpwnmeZxbNxhQ4BENC27BlXnq4kD6NlqMUwX7T6ZN3alNnBXsWrh/8mJ37BL5cKMZaqA0k/YUo4o6rLfpA==", + "requires": { + "@babel/runtime": "^7.10.1" + } + }, + "i18next-browser-languagedetector": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-5.0.1.tgz", + "integrity": "sha512-7K4A6DJ2rNz3Yd835Y493UgkzUxgpGsCeIMKLGkt6Ps0cbgSaJ+LdATFNFA+ujp2brmsUM9BeDThXKhabXUbUw==", + "requires": { + "@babel/runtime": "^7.5.5" + } + }, + "i18next-fs-backend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-1.0.7.tgz", + "integrity": "sha512-aAZ3rvshe1Zbl6JSCWrWWqbZS5JpmVNG+84YqLcgdYcm9uAxzw4xWxnA/a3044Nm2PKXE62CT+pIZjk7OEYtTw==" + }, + "i18next-http-backend": { + "version": "1.0.21", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-1.0.21.tgz", + "integrity": "sha512-UDeHoV2B+31Gr++0KFAVjM5l+SEwePpF6sfDyaDq5ennM9QNJ78PBEMPStwkreEm4h5C8sT7M1JdNQrLcU1Wdg==", + "requires": { + "node-fetch": "2.6.1" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + } + } + }, + "i18next-http-middleware": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/i18next-http-middleware/-/i18next-http-middleware-3.0.6.tgz", + "integrity": "sha512-zXZyLF+s2NexjFiJ9qV7GPdN8MCEaEk6NGirTQR994eT/PzOqSODlizewsl3n/BvfhTALgYclr1xPV50i+zxCA==" + }, "iconv-lite": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", @@ -5325,6 +5451,32 @@ } } }, + "next-i18next": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/next-i18next/-/next-i18next-6.0.3.tgz", + "integrity": "sha512-zyh1bDFmNexF45PsU+pdxlQ87UYadkRCjR7Co7YXsmnpsikWtarOhu6qJrVe0IAXC1Ns+IoyS9dCPlE3CvuQxA==", + "requires": { + "@types/express": "^4.16.1", + "core-js": "^3", + "hoist-non-react-statics": "^3.2.0", + "i18next": "^19.6.3", + "i18next-browser-languagedetector": "^5.0.0", + "i18next-fs-backend": "^1.0.7", + "i18next-http-backend": "^1.0.17", + "i18next-http-middleware": "^3.0.2", + "path-match": "^1.2.4", + "prop-types": "^15.6.2", + "react-i18next": "^11.7.3", + "url": "^0.11.0" + }, + "dependencies": { + "core-js": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" + } + } + }, "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", @@ -5678,11 +5830,35 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "path-match": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/path-match/-/path-match-1.2.4.tgz", + "integrity": "sha1-pidH88fgwlFHYml/JEQ1hbCRAOo=", + "requires": { + "http-errors": "~1.4.0", + "path-to-regexp": "^1.0.0" + } + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + } + } + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -6960,6 +7136,15 @@ "resolved": "https://registry.npmjs.org/react-ga/-/react-ga-3.1.2.tgz", "integrity": "sha512-OJrMqaHEHbodm+XsnjA6ISBEHTwvpFrxco65mctzl/v3CASMSLSyUkFqz9yYrPDKGBUfNQzKCjuMJwctjlWBbw==" }, + "react-i18next": { + "version": "11.7.3", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.7.3.tgz", + "integrity": "sha512-7sYZqVZgdaS9Z0ZH6nuJFErCD0zz5wK3jR4/xCrWjZcxHHF3GRu7BXdicbSPprZV4ZYz7LJzxxMHO7dg5Qb70A==", + "requires": { + "@babel/runtime": "^7.3.1", + "html-parse-stringify2": "2.0.1" + } + }, "react-image": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/react-image/-/react-image-4.0.3.tgz", @@ -7802,6 +7987,11 @@ } } }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, "stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -8538,6 +8728,11 @@ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" + }, "warning": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", diff --git a/client/package.json b/client/package.json index b9595a01..d9c250b8 100644 --- a/client/package.json +++ b/client/package.json @@ -26,6 +26,7 @@ "less": "3.12.2", "less-vars-to-js": "1.3.0", "next": "9", + "next-i18next": "^6.0.3", "nprogress": "^0.2.0", "null-loader": "4.0.0", "react": "^16.13.1", From a7fb17690bfd6111afabfe3380d1d125986535d2 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Sun, 11 Oct 2020 23:28:04 +0300 Subject: [PATCH 39/42] [client] update stringToColor importing sectence --- client/src/components/pages/[feed]/FeedHeader.tsx | 3 ++- client/src/components/pages/create-feed/Step2/index.tsx | 2 +- client/src/components/pages/create-feed/Step3/index.tsx | 2 +- .../src/components/pages/messages/ConversationList/index.tsx | 1 - .../src/components/pages/settings/account-settings/index.tsx | 1 - client/src/pages/entry/[id]/index.tsx | 2 +- client/src/pages/index.tsx | 2 +- 7 files changed, 6 insertions(+), 7 deletions(-) diff --git a/client/src/components/pages/[feed]/FeedHeader.tsx b/client/src/components/pages/[feed]/FeedHeader.tsx index 5c9e7270..db9c3827 100644 --- a/client/src/components/pages/[feed]/FeedHeader.tsx +++ b/client/src/components/pages/[feed]/FeedHeader.tsx @@ -26,7 +26,7 @@ import { import React, { useState } from 'react' import { format, parseISO } from 'date-fns' import { useRouter } from 'next/router' -import * as stringToColor from 'string-to-color' +import stringToColor from 'string-to-color' // Local files import { getUserRateOfTitle, rateTitle, deleteTitle } from '@/services/api' @@ -171,6 +171,7 @@ const FeedHeader: React.FC = (props): JSX.Element => { diff --git a/client/src/components/pages/create-feed/Step2/index.tsx b/client/src/components/pages/create-feed/Step2/index.tsx index 5072a201..7ff91f5c 100644 --- a/client/src/components/pages/create-feed/Step2/index.tsx +++ b/client/src/components/pages/create-feed/Step2/index.tsx @@ -5,7 +5,7 @@ import TextArea from 'antd/lib/input/TextArea' // Other dependencies import React, { useContext, useState } from 'react' -import * as stringToColor from 'string-to-color' +import stringToColor from 'string-to-color' // Local files import { PageHelmet } from '@/components/global/PageHelmet' diff --git a/client/src/components/pages/create-feed/Step3/index.tsx b/client/src/components/pages/create-feed/Step3/index.tsx index 9231c1d7..8f8550d0 100644 --- a/client/src/components/pages/create-feed/Step3/index.tsx +++ b/client/src/components/pages/create-feed/Step3/index.tsx @@ -4,7 +4,7 @@ import { Button, Result, Descriptions, Typography } from 'antd' // Other dependencies import React, { useContext } from 'react' import { useRouter } from 'next/router' -import * as stringToColor from 'string-to-color' +import stringToColor from 'string-to-color' // Local files import { PageHelmet } from '@/components/global/PageHelmet' diff --git a/client/src/components/pages/messages/ConversationList/index.tsx b/client/src/components/pages/messages/ConversationList/index.tsx index a6837738..7283fc3e 100644 --- a/client/src/components/pages/messages/ConversationList/index.tsx +++ b/client/src/components/pages/messages/ConversationList/index.tsx @@ -13,7 +13,6 @@ import { API_URL } from '@/../config/constants' import PageLoading from '@/components/global/PageLoading' import { ConversationListProps } from '@/@types/pages' import newMessagePng from '@/assets/newMessage.png' -import '@/styles/pages/messages/style.less' export const ConversationList: React.FC = (props): JSX.Element => { const router = useRouter() diff --git a/client/src/components/pages/settings/account-settings/index.tsx b/client/src/components/pages/settings/account-settings/index.tsx index 074d6388..f2aba8e5 100644 --- a/client/src/components/pages/settings/account-settings/index.tsx +++ b/client/src/components/pages/settings/account-settings/index.tsx @@ -10,7 +10,6 @@ import { useDispatch } from 'react-redux' import { uploadProfilePicture, updateUser } from '@/services/api' import { UPDATE_USER } from '@/redux/Actions/User' import { API_URL } from '@/../config/constants' -import '@/styles/pages/settings/style.less' export const AccountSettings = (params: AccountSettingsParams): JSX.Element => { const [imageUri, setImageUri] = useState(`${API_URL}/v1/user/pp?username=${params.user.username}`) diff --git a/client/src/pages/entry/[id]/index.tsx b/client/src/pages/entry/[id]/index.tsx index f60f5858..c88cdea9 100644 --- a/client/src/pages/entry/[id]/index.tsx +++ b/client/src/pages/entry/[id]/index.tsx @@ -5,7 +5,7 @@ import { ArrowUpOutlined } from '@ant-design/icons' // Other dependencies import React, { useState } from 'react' import { useRouter } from 'next/router' -import * as stringToColor from 'string-to-color' +import stringToColor from 'string-to-color' // Local files import { API_URL } from '@/../config/constants' diff --git a/client/src/pages/index.tsx b/client/src/pages/index.tsx index e9fa0a87..42b00c3c 100644 --- a/client/src/pages/index.tsx +++ b/client/src/pages/index.tsx @@ -8,7 +8,7 @@ import { AxiosError, AxiosResponse } from 'axios' import { NextPage } from 'next' import { Img } from 'react-image' import Link from 'next/link' -import * as stringToColor from 'string-to-color' +import stringToColor from 'string-to-color' // Local files import { fetchAllFeeds, fetchFeaturedEntryByTitleId, fetchTrendingTags } from '@/services/api' From 492b43e0814a6e978ff55713da737c80a8e4e9c6 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Mon, 12 Oct 2020 23:53:02 +0300 Subject: [PATCH 40/42] [client] implement i18n to login page --- client/i18n.ts | 12 ++++++++++++ client/next.config.js | 9 +++++++++ client/public/locales/en/loginPage.json | 11 +++++++++++ client/public/locales/tr/loginPage.json | 11 +++++++++++ client/src/pages/_app.tsx | 3 ++- client/src/pages/auth/sign-in/index.tsx | 23 ++++++++++++----------- 6 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 client/i18n.ts create mode 100644 client/public/locales/en/loginPage.json create mode 100644 client/public/locales/tr/loginPage.json diff --git a/client/i18n.ts b/client/i18n.ts new file mode 100644 index 00000000..7c96ef55 --- /dev/null +++ b/client/i18n.ts @@ -0,0 +1,12 @@ +import NextI18Next from "next-i18next"; + +const NextI18NextInstance = new NextI18Next({ + defaultLanguage: "en", + defaultNS: "loginPage", + otherLanguages: ["tr"], + localePath: typeof window === "undefined" ? "public/locales" : "locales" +}) + +export const { appWithTranslation, withTranslation } = NextI18NextInstance + +export default NextI18NextInstance; \ No newline at end of file diff --git a/client/next.config.js b/client/next.config.js index 6422c01b..f7b8c52e 100644 --- a/client/next.config.js +++ b/client/next.config.js @@ -1,12 +1,21 @@ const webpack = require('webpack') + const withCSS = require('@zeit/next-css') const withLess = require('@zeit/next-less') const lessToJS = require('less-vars-to-js') + const fs = require('fs') const path = require('path') const themeVariables = lessToJS(fs.readFileSync(path.resolve(__dirname, './config/override.less'), 'utf8')) +const { nextI18NextRewrites } = require('next-i18next/rewrites') +const localeSubpaths = {} + module.exports = withCSS(withLess({ + rewrites: async () => nextI18NextRewrites(localeSubpaths), + publicRuntimeConfig: { + localeSubpaths, + }, lessLoaderOptions: { javascriptEnabled: true, modifyVars: themeVariables // make your antd custom effective diff --git a/client/public/locales/en/loginPage.json b/client/public/locales/en/loginPage.json new file mode 100644 index 00000000..535d9a62 --- /dev/null +++ b/client/public/locales/en/loginPage.json @@ -0,0 +1,11 @@ +{ + "title": "Login Form", + "signIn": "Sign In", + "validationErrorEmailOrUsername": "Please input your username or email", + "validationErrorPassword": "Please input your password", + "rememberMe": "Remember Me", + "createAccount": "Create a new account", + "forgotPassword": "Forgot Password", + "usernameOrEmail": "Username or Email", + "password": "Password" +} \ No newline at end of file diff --git a/client/public/locales/tr/loginPage.json b/client/public/locales/tr/loginPage.json new file mode 100644 index 00000000..e7087c42 --- /dev/null +++ b/client/public/locales/tr/loginPage.json @@ -0,0 +1,11 @@ +{ + "title": "Giriş Formu", + "signIn": "Giriş Yap", + "validationErrorEmailOrUsername": "Lütfen kullanıcı adı ya da eposta girin", + "validationErrorPassword": "Lütfen parolanızı girin", + "rememberMe": "Beni Hatırla", + "createAccount": "Yeni bir hesap oluştur", + "forgotPassword": "Şifremi Unuttum", + "usernameOrEmail": "Kullanıcı adı ya da Eposta", + "password": "Parola" +} \ No newline at end of file diff --git a/client/src/pages/_app.tsx b/client/src/pages/_app.tsx index 5f0f2340..b1a0d8a5 100644 --- a/client/src/pages/_app.tsx +++ b/client/src/pages/_app.tsx @@ -10,6 +10,7 @@ import 'nprogress/nprogress.css' // Local files import { store, persistor } from '@/redux/store' +import { appWithTranslation } from '@/../i18n' import './global.less' NProgress.configure({ showSpinner: false }) @@ -45,4 +46,4 @@ AppBase.getInitialProps = async (appContext) => { return { ...appProps } } -export default AppBase \ No newline at end of file +export default appWithTranslation(AppBase) \ No newline at end of file diff --git a/client/src/pages/auth/sign-in/index.tsx b/client/src/pages/auth/sign-in/index.tsx index fc9db024..067de8da 100644 --- a/client/src/pages/auth/sign-in/index.tsx +++ b/client/src/pages/auth/sign-in/index.tsx @@ -13,6 +13,7 @@ import { SIGN_IN } from '@/redux/Actions/User' import { SET_ACCESS_TOKEN } from '@/redux/Actions/Global' import { PageHelmet } from '@/components/global/PageHelmet' import { signIn } from '@/services/api' +import { withTranslation } from '@/../i18n' import AuthLayout from '@/layouts/AuthLayout' import './style.less' @@ -22,7 +23,7 @@ export declare interface FormDataType { remember: boolean } -const Login: React.FunctionComponent = () => { +const Login: React.FunctionComponent = ({ t }) => { const router = useRouter() const [form] = Form.useForm() @@ -73,30 +74,30 @@ const Login: React.FunctionComponent = () => { - } placeholder="Username or Email" /> + } placeholder={t("loginPage:usernameOrEmail")} /> - - } placeholder="Password" /> + + } placeholder={t("loginPage:password")} /> - Remember me + {t("loginPage:rememberMe")} - Forgot Password + {t("loginPage:forgotPassword")} @@ -105,11 +106,11 @@ const Login: React.FunctionComponent = () => { - Create an Account + {t("loginPage:createAccount")} @@ -121,4 +122,4 @@ const Login: React.FunctionComponent = () => { ) } -export default Login +export default withTranslation('loginPage')(Login) From ed60cee568da1fced22e20d5c23b27a3e57fa607 Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Tue, 13 Oct 2020 20:40:04 +0300 Subject: [PATCH 41/42] [client] Add localization on sign-up page --- client/public/locales/en/registerPage.json | 21 ++++++++++ client/public/locales/tr/registerPage.json | 21 ++++++++++ client/src/pages/auth/sign-up/index.tsx | 47 +++++++++++----------- 3 files changed, 66 insertions(+), 23 deletions(-) create mode 100644 client/public/locales/en/registerPage.json create mode 100644 client/public/locales/tr/registerPage.json diff --git a/client/public/locales/en/registerPage.json b/client/public/locales/en/registerPage.json new file mode 100644 index 00000000..a03b1ea9 --- /dev/null +++ b/client/public/locales/en/registerPage.json @@ -0,0 +1,21 @@ +{ + "title": "Register Form", + "signUp": "Sign Up", + "fullName": "Full Name", + "username": "Username", + "email": "Email", + "password": "Password", + "confirmPassword": "Confirm Password", + "validationErrorFullName": "Please enter your full name", + "validationErrorUsername": "Please enter your username", + "validationErrorEmail": "Please enter your email", + "validationErrorEmail2": "Email format is not valid", + "validationErrorPassword": "Please enter your password", + "validationErrorConfirmPassword": "Please confirm your password", + "validationErrorPasswordMatch": "The two passwords that you entered do not match", + "validationErrorTermsAndPolicy": "You must accept the privacy policy and terms & conditions", + "alreadyHaveAnAccount": "Already have an account?", + "privacyPolicy": "Privacy Policy", + "termsAndConditions": "Terms & Conditions", + "readAndUnderstood": "read and understood." +} \ No newline at end of file diff --git a/client/public/locales/tr/registerPage.json b/client/public/locales/tr/registerPage.json new file mode 100644 index 00000000..94b13732 --- /dev/null +++ b/client/public/locales/tr/registerPage.json @@ -0,0 +1,21 @@ +{ + "title": "Kayıt Formu", + "signUp": "Kayıt Ol", + "fullName": "Ad Soyad", + "username": "Kullanıcı Adı", + "email": "E Posta", + "password": "Parola", + "confirmPassword": "Parolayı Onayla", + "validationErrorFullName": "Lütfen ad soyad alanına değer girin", + "validationErrorUsername": "Lütfen kullanıcı adı alanına değer girin", + "validationErrorEmail": "Lütfen e posta alanına değer girin", + "validationErrorEmail2": "E posta formatı uygun değil", + "validationErrorPassword": "Lütfen parola alanına değer girin", + "validationErrorConfirmPassword": "Lütfen parolanızı onaylayın", + "validationErrorPasswordMatch": "Girilen iki parola birbiri ile eşleşmiyor", + "validationErrorTermsAndPolicy": "Gizlilik politikasını ve hüküm & koşulları kabul etmelisiniz", + "alreadyHaveAnAccount": "Zaten hesabınız var mı?", + "privacyPolicy": "Gizlilik politikası", + "termsAndConditions": "Hüküm & Koşullar", + "readAndUnderstood": "okudum ve anladım." +} \ No newline at end of file diff --git a/client/src/pages/auth/sign-up/index.tsx b/client/src/pages/auth/sign-up/index.tsx index 62550e75..2ef93e7d 100644 --- a/client/src/pages/auth/sign-up/index.tsx +++ b/client/src/pages/auth/sign-up/index.tsx @@ -11,6 +11,7 @@ import { signUp } from '@/services/api' import { PageHelmet } from '@/components/global/PageHelmet' import RegisterResult from '@/components/pages/sign-up/result' import { Aggrements } from '@/components/global/Aggrements' +import { withTranslation } from '@/../i18n' import AuthLayout from '@/layouts/AuthLayout' import './style.less' @@ -21,7 +22,7 @@ export declare interface FormDataType { password: string } -const Register = () => { +const Register: React.FunctionComponent = ({ t }) => { const [requestOnGoing, setRequestOnGoing] = useState(false) const [signedAccount, setSignedAccount] = useState(null) const [aggrementModalVisibility, setAggrementModalVisibilit] = useState(null) @@ -46,7 +47,7 @@ const Register = () => { const handleSubmitButtonView = () => ( ) @@ -72,34 +73,34 @@ const Register = () => { - } placeholder="Full Name" /> + } placeholder={t("registerPage:fullName")} /> - } placeholder="Username" /> + } placeholder={t("registerPage:username")} /> - } placeholder="Email" /> + } placeholder={t("registerPage:email")} /> { rules={[ { required: true, - message: 'Please input your password!', + message: t("registerPage:validationErrorPassword"), }, ]} hasFeedback > - } placeholder="Password" /> + } placeholder={t("registerPage:password")} /> { rules={[ { required: true, - message: 'Please confirm your password!', + message: t("registerPage:validationErrorConfirmPassword"), }, ({ getFieldValue }) => ({ validator(rule, value) { if (!value || getFieldValue('password') === value) { return Promise.resolve() } - return Promise.reject('The two passwords that you entered do not match!') + return Promise.reject(t("registerPage:validationErrorPasswordMatch")) }, }), ]} > - } placeholder="Confirm Password" /> + } placeholder={t("registerPage:confirmPassword")} /> { rules={[ { validator: (_, value) => - value ? Promise.resolve() : Promise.reject('You must accept the privacy policy and terms & conditions'), + value ? Promise.resolve() : Promise.reject(t("registerPage:validationErrorTermsAndPolicy")), }, ]} > - I have read the - {' '} {' '} - and + , {' '} + {' '} + {t("registerPage:readAndUnderstood")} {handleSubmitButtonView()} - Already have an Account? + {t("registerPage:alreadyHaveAnAccount")} @@ -185,4 +186,4 @@ const Register = () => { ) } -export default Register +export default withTranslation('registerPage')(Register) From 4c8ec5b7520f4fadaa19fc971530cfda4127825b Mon Sep 17 00:00:00 2001 From: ozkanonur Date: Tue, 13 Oct 2020 20:40:14 +0300 Subject: [PATCH 42/42] [client] Add localization on auth layout --- client/public/locales/en/authLayout.json | 3 +++ client/public/locales/tr/authLayout.json | 3 +++ client/src/layouts/AuthLayout.tsx | 5 +++-- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 client/public/locales/en/authLayout.json create mode 100644 client/public/locales/tr/authLayout.json diff --git a/client/public/locales/en/authLayout.json b/client/public/locales/en/authLayout.json new file mode 100644 index 00000000..70a011e3 --- /dev/null +++ b/client/public/locales/en/authLayout.json @@ -0,0 +1,3 @@ +{ + "copyright": "Feednext © 2020. All rights reserved" +} \ No newline at end of file diff --git a/client/public/locales/tr/authLayout.json b/client/public/locales/tr/authLayout.json new file mode 100644 index 00000000..4ea55419 --- /dev/null +++ b/client/public/locales/tr/authLayout.json @@ -0,0 +1,3 @@ +{ + "copyright": "Feednext © 2020. Tüm hakları saklıdır" +} \ No newline at end of file diff --git a/client/src/layouts/AuthLayout.tsx b/client/src/layouts/AuthLayout.tsx index 2ca17383..9b33435c 100644 --- a/client/src/layouts/AuthLayout.tsx +++ b/client/src/layouts/AuthLayout.tsx @@ -8,6 +8,7 @@ import { useRouter } from 'next/router' import Link from 'next/link' // Local files +import { withTranslation } from '@/../i18n' import logo from '@/assets/logo-square.svg' import './AuthLayout.less' @@ -37,7 +38,7 @@ const AuthLayout: React.FC = props => {
- Feednext © 2020. All rights reserved + {props.t("authLayout:copyright")}
@@ -45,4 +46,4 @@ const AuthLayout: React.FC = props => { } } -export default AuthLayout +export default withTranslation('authLayout')(AuthLayout)