diff --git a/packages/api/src/@core/auth/auth.controller.ts b/packages/api/src/@core/auth/auth.controller.ts new file mode 100644 index 000000000..157156868 --- /dev/null +++ b/packages/api/src/@core/auth/auth.controller.ts @@ -0,0 +1,51 @@ +import { + Controller, + Request, + Post, + Body, + Get, + UseGuards, +} from '@nestjs/common'; +import { CreateUserDto, LoginCredentials } from './dto/create-user.dto'; +import { AuthService } from './auth.service'; +import { JwtAuthGuard } from './guards/jwt-auth.guard'; +import { LoggerService } from '@@core/logger/logger.service'; + +@Controller('auth') +export class AuthController { + constructor( + private readonly authService: AuthService, + private logger: LoggerService, + ) {} + + @Post('register') + async registerUser(@Body() user: CreateUserDto) { + return this.authService.register(user); + } + + @Post('login') + async login(@Body() user: LoginCredentials) { + return this.authService.login(user); + } + + @Get('users') + async users() { + return this.authService.getUsers(); + } + + @Get('api-keys') + async apiKeys() { + return this.authService.getApiKeys(); + } + + @UseGuards(JwtAuthGuard) + @Post('generate-apikey') + async generateApiKey( + @Request() req, + @Body() data: { projectId: number }, + ): Promise<{ api_key: string }> { + const userId = req.user.userId; + this.logger.log('user id is ' + userId); + return await this.authService.generateApiKeyForUser(userId, data.projectId); + } +} diff --git a/packages/api/src/@core/auth/auth.module.ts b/packages/api/src/@core/auth/auth.module.ts index 27482f372..9ef03c5ae 100644 --- a/packages/api/src/@core/auth/auth.module.ts +++ b/packages/api/src/@core/auth/auth.module.ts @@ -7,8 +7,10 @@ import { ApiKeyStrategy } from './strategies/auth-header-api-key.strategy'; import { PrismaService } from '../prisma/prisma.service'; import { ConfigService } from '@nestjs/config'; import { LoggerService } from '@@core/logger/logger.service'; +import { AuthController } from './auth.controller'; @Module({ + controllers: [AuthController], providers: [ AuthService, JwtStrategy, diff --git a/packages/api/src/@core/utils/unification/crm/freshsales/index.ts b/packages/api/src/@core/utils/unification/crm/freshsales/index.ts deleted file mode 100644 index ca4b2c187..000000000 --- a/packages/api/src/@core/utils/unification/crm/freshsales/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { CrmObject, FreshsalesContactOutput } from 'src/crm/@types'; -import { CrmObjectInput, Unified, UnifySourceType } from '../../../types'; -import { mapToFreshsalesContact, mapToUnifiedContact } from './mappers/contact'; -import { UnifiedContactInput } from '@contact/types/model.unified'; - -export async function desunifyFreshsales({ - sourceObject, - targetType_, -}: { - sourceObject: T; - targetType_: CrmObject; -}): Promise { - switch (targetType_) { - case CrmObject.contact: - return mapToFreshsalesContact(sourceObject as UnifiedContactInput); - case CrmObject.deal: - //return mapToHubspotDeal(sourceObject); - case CrmObject.company: - //return mapToHubspotCompany(sourceObject); - // Add other cases for different CrmObject types - default: - throw new Error(`Unsupported target type for Hubspot: ${targetType_}`); - } -} -export async function unifyFreshsales< - T extends UnifySourceType | UnifySourceType[], ->({ sourceObject, targetType_ }: { sourceObject: T; targetType_: CrmObject }) { - switch (targetType_) { - case CrmObject.contact: - return mapToUnifiedContact( - sourceObject as FreshsalesContactOutput | FreshsalesContactOutput[], - ); - case CrmObject.deal: - //return mapToHubspotDeal(sourceObject); - case CrmObject.company: - //return mapToHubspotCompany(sourceObject); - // Add other cases for different CrmObject types - default: - throw new Error(`Unsupported target type for Freshsales: ${targetType_}`); - } -} diff --git a/packages/api/src/@core/utils/unification/crm/hubspot/index.ts b/packages/api/src/@core/utils/unification/crm/hubspot/index.ts deleted file mode 100644 index 99aa9a91b..000000000 --- a/packages/api/src/@core/utils/unification/crm/hubspot/index.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { CrmObject, HubspotContactOutput } from 'src/crm/@types'; -import { CrmObjectInput, Unified, UnifySourceType } from '../../../types'; -import { mapToHubspotContact, mapToUnifiedContact } from './mappers/contact'; -import { UnifiedContactInput } from '@contact/types/model.unified'; - -export async function desunifyHubspot({ - sourceObject, - targetType_, - customFieldMappings, -}: { - sourceObject: T; - targetType_: CrmObject; - customFieldMappings?: { - slug: string; - remote_id: string; - }[]; -}): Promise { - switch (targetType_) { - case CrmObject.contact: - return mapToHubspotContact( - sourceObject as UnifiedContactInput, - customFieldMappings, - ); - case CrmObject.deal: - //return mapToHubspotDeal(sourceObject); - case CrmObject.company: - //return mapToHubspotCompany(sourceObject); - // Add other cases for different CrmObject types - default: - throw new Error(`Unsupported target type for Hubspot: ${targetType_}`); - } -} -export async function unifyHubspot< - T extends UnifySourceType | UnifySourceType[], ->({ - sourceObject, - targetType_, - customFieldMappings, -}: { - sourceObject: T; - targetType_: CrmObject; - customFieldMappings?: { - slug: string; - remote_id: string; - }[]; -}) { - switch (targetType_) { - case CrmObject.contact: - return mapToUnifiedContact( - sourceObject as HubspotContactOutput | HubspotContactOutput[], - customFieldMappings, - ); - case CrmObject.deal: - //return mapToHubspotDeal(sourceObject); - case CrmObject.company: - //return mapToHubspotCompany(sourceObject); - // Add other cases for different CrmObject types - default: - throw new Error(`Unsupported target type for Hubspot: ${targetType_}`); - } -} diff --git a/packages/api/src/@core/utils/unification/crm/index.ts b/packages/api/src/@core/utils/unification/crm/index.ts deleted file mode 100644 index 2b9f89675..000000000 --- a/packages/api/src/@core/utils/unification/crm/index.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { CrmObject } from '@crm/@types'; -import { desunifyHubspot, unifyHubspot } from './hubspot'; -import { - CrmObjectInput, - Unified, - UnifyReturnType, - UnifySourceType, -} from '../../types'; -import { desunifyPipedrive, unifyPipedrive } from './pipedrive'; -import { desunifyZoho, unifyZoho } from './zoho'; -import { desunifyZendesk, unifyZendesk } from './zendesk'; -import { desunifyFreshsales, unifyFreshsales } from './freshsales'; - -export async function desunifyCrm({ - sourceObject, - targetType_, - providerName, - customFieldMappings, -}: { - sourceObject: T; - targetType_: CrmObject; - providerName: string; - customFieldMappings?: { - slug: string; - remote_id: string; - }[]; -}): Promise { - switch (providerName) { - case 'hubspot': - return desunifyHubspot({ - sourceObject, - targetType_, - customFieldMappings, - }); - case 'pipedrive': - return desunifyPipedrive({ sourceObject, targetType_ }); - case 'zoho': - return desunifyZoho({ sourceObject, targetType_ }); - case 'zendesk': - return desunifyZendesk({ sourceObject, targetType_ }); - case 'freshsales': - return desunifyFreshsales({ sourceObject, targetType_ }); - } - return; -} - -export async function unifyCrm({ - sourceObject, - targetType_, - providerName, - customFieldMappings, -}: { - sourceObject: T; - targetType_: CrmObject; - providerName: string; - customFieldMappings?: { - slug: string; - remote_id: string; - }[]; -}): Promise { - switch (providerName) { - case 'hubspot': - return unifyHubspot({ sourceObject, targetType_, customFieldMappings }); - case 'pipedrive': - return unifyPipedrive({ sourceObject, targetType_ }); - case 'zoho': - return unifyZoho({ sourceObject, targetType_ }); - case 'zendesk': - return unifyZendesk({ sourceObject, targetType_ }); - case 'freshsales': - return unifyFreshsales({ sourceObject, targetType_ }); - } - return; -} diff --git a/packages/api/src/@core/utils/unification/crm/pipedrive/index.ts b/packages/api/src/@core/utils/unification/crm/pipedrive/index.ts deleted file mode 100644 index e568faf83..000000000 --- a/packages/api/src/@core/utils/unification/crm/pipedrive/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { CrmObject, PipedriveContactOutput } from 'src/crm/@types'; -import { CrmObjectInput, Unified, UnifySourceType } from '../../../types'; -import { mapToPipedriveContact, mapToUnifiedContact } from './mappers/contact'; -import { UnifiedContactInput } from '@contact/types/model.unified'; - -export async function desunifyPipedrive({ - sourceObject, - targetType_, -}: { - sourceObject: T; - targetType_: CrmObject; -}): Promise { - switch (targetType_) { - case CrmObject.contact: - return mapToPipedriveContact(sourceObject as UnifiedContactInput); - case CrmObject.deal: - //return mapToHubspotDeal(sourceObject); - case CrmObject.company: - //return mapToHubspotCompany(sourceObject); - // Add other cases for different CrmObject types - default: - throw new Error(`Unsupported target type for Pipedrive: ${targetType_}`); - } -} -export async function unifyPipedrive< - T extends UnifySourceType | UnifySourceType[], ->({ sourceObject, targetType_ }: { sourceObject: T; targetType_: CrmObject }) { - switch (targetType_) { - case CrmObject.contact: - return mapToUnifiedContact( - sourceObject as PipedriveContactOutput | PipedriveContactOutput[], - ); - case CrmObject.deal: - //return mapToHubspotDeal(sourceObject); - case CrmObject.company: - //return mapToHubspotCompany(sourceObject); - // Add other cases for different CrmObject types - default: - throw new Error(`Unsupported target type for Pipedrive: ${targetType_}`); - } -} diff --git a/packages/api/src/@core/utils/unification/crm/zendesk/index.ts b/packages/api/src/@core/utils/unification/crm/zendesk/index.ts deleted file mode 100644 index a32c314c2..000000000 --- a/packages/api/src/@core/utils/unification/crm/zendesk/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { CrmObject, ZendeskContactOutput } from 'src/crm/@types'; -import { CrmObjectInput, Unified, UnifySourceType } from '../../../types'; -import { mapToUnifiedContact, mapToZendeskContact } from './mappers/contact'; -import { UnifiedContactInput } from '@contact/types/model.unified'; - -export async function desunifyZendesk({ - sourceObject, - targetType_, -}: { - sourceObject: T; - targetType_: CrmObject; -}): Promise { - switch (targetType_) { - case CrmObject.contact: - return mapToZendeskContact(sourceObject as UnifiedContactInput); - case CrmObject.deal: - //return mapToHubspotDeal(sourceObject); - case CrmObject.company: - //return mapToHubspotCompany(sourceObject); - // Add other cases for different CrmObject types - default: - throw new Error(`Unsupported target type for Zendesk: ${targetType_}`); - } -} -export async function unifyZendesk< - T extends UnifySourceType | UnifySourceType[], ->({ sourceObject, targetType_ }: { sourceObject: T; targetType_: CrmObject }) { - switch (targetType_) { - case CrmObject.contact: - return mapToUnifiedContact( - sourceObject as ZendeskContactOutput | ZendeskContactOutput[], - ); - case CrmObject.deal: - //return mapToHubspotDeal(sourceObject); - case CrmObject.company: - //return mapToHubspotCompany(sourceObject); - // Add other cases for different CrmObject types - default: - throw new Error(`Unsupported target type for Zendesk : ${targetType_}`); - } -} diff --git a/packages/api/src/@core/utils/unification/crm/zoho/index.ts b/packages/api/src/@core/utils/unification/crm/zoho/index.ts deleted file mode 100644 index c8530489f..000000000 --- a/packages/api/src/@core/utils/unification/crm/zoho/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { CrmObject, ZohoContactOutput } from 'src/crm/@types'; -import { CrmObjectInput, Unified, UnifySourceType } from '../../../types'; -import { mapToUnifiedContact, mapToZohoContact } from './mappers/contact'; -import { UnifiedContactInput } from '@contact/types/model.unified'; - -export async function desunifyZoho({ - sourceObject, - targetType_, -}: { - sourceObject: T; - targetType_: CrmObject; -}): Promise { - switch (targetType_) { - case CrmObject.contact: - return mapToZohoContact(sourceObject as UnifiedContactInput); - case CrmObject.deal: - //return mapToHubspotDeal(sourceObject); - case CrmObject.company: - //return mapToHubspotCompany(sourceObject); - // Add other cases for different CrmObject types - default: - throw new Error(`Unsupported target type for Zoho: ${targetType_}`); - } -} -export async function unifyZoho({ - sourceObject, - targetType_, -}: { - sourceObject: T; - targetType_: CrmObject; -}) { - switch (targetType_) { - case CrmObject.contact: - return mapToUnifiedContact( - sourceObject as ZohoContactOutput | ZohoContactOutput[], - ); - case CrmObject.deal: - //return mapToHubspotDeal(sourceObject); - case CrmObject.company: - //return mapToHubspotCompany(sourceObject); - // Add other cases for different CrmObject types - default: - throw new Error(`Unsupported target type for Zoho: ${targetType_}`); - } -} diff --git a/packages/api/src/@core/utils/unification/desunify.ts b/packages/api/src/@core/utils/unification/desunify.ts index 9d50ab028..7e01af5ba 100644 --- a/packages/api/src/@core/utils/unification/desunify.ts +++ b/packages/api/src/@core/utils/unification/desunify.ts @@ -1,7 +1,7 @@ import { CrmObject } from '@crm/@types'; import { ProviderVertical, getProviderVertical } from '../providers'; -import { desunifyCrm } from './crm'; import { DesunifyReturnType, TargetObject, Unified } from '../types'; +import { desunifyCrm } from '@crm/@unification'; /* to insert data diff --git a/packages/api/src/@core/utils/unification/unify.ts b/packages/api/src/@core/utils/unification/unify.ts index 984efa099..00911f829 100644 --- a/packages/api/src/@core/utils/unification/unify.ts +++ b/packages/api/src/@core/utils/unification/unify.ts @@ -1,7 +1,7 @@ import { CrmObject } from '@crm/@types'; import { ProviderVertical, getProviderVertical } from '../providers'; import { TargetObject, UnifyReturnType, UnifySourceType } from '../types'; -import { unifyCrm } from './crm'; +import { unifyCrm } from '@crm/@unification'; /* to fetch data diff --git a/packages/api/src/app.controller.ts b/packages/api/src/app.controller.ts index 0d3478069..0d65624b5 100644 --- a/packages/api/src/app.controller.ts +++ b/packages/api/src/app.controller.ts @@ -1,63 +1,14 @@ -import { - Controller, - Get, - Request, - Post, - UseGuards, - Body, -} from '@nestjs/common'; +import { Controller, Get, UseGuards } from '@nestjs/common'; import { AppService } from './app.service'; -import { AuthService } from './@core/auth/auth.service'; -import { JwtAuthGuard } from './@core/auth/guards/jwt-auth.guard'; import { ApiKeyAuthGuard } from './@core/auth/guards/api-key.guard'; -import { - CreateUserDto, - LoginCredentials, -} from './@core/auth/dto/create-user.dto'; -import { LoggerService } from './@core/logger/logger.service'; @Controller() export class AppController { - constructor( - private readonly appService: AppService, - private authService: AuthService, - private logger: LoggerService, - ) {} + constructor(private readonly appService: AppService) {} @UseGuards(ApiKeyAuthGuard) @Get() getHello(): string { return this.appService.getHello(); } - - @Post('auth/register') - async registerUser(@Body() user: CreateUserDto) { - return this.authService.register(user); - } - - @Post('auth/login') - async login(@Body() user: LoginCredentials) { - return this.authService.login(user); - } - - @Get('auth') - async users() { - return this.authService.getUsers(); - } - - @Get('auth/api-keys') - async apiKeys() { - return this.authService.getApiKeys(); - } - - @UseGuards(JwtAuthGuard) - @Post('generate-apikey') - async generateApiKey( - @Request() req, - @Body() data: { projectId: number }, - ): Promise<{ api_key: string }> { - const userId = req.user.userId; - this.logger.log('user id is ' + userId); - return await this.authService.generateApiKeyForUser(userId, data.projectId); - } } diff --git a/packages/api/src/app.module.ts b/packages/api/src/app.module.ts index a12c4f267..57fe1ea24 100644 --- a/packages/api/src/app.module.ts +++ b/packages/api/src/app.module.ts @@ -3,14 +3,12 @@ import { AppController } from './app.controller'; import { AppService } from './app.service'; import { CrmModule } from './crm/crm.module'; import { AuthModule } from './@core/auth/auth.module'; -import { AuthService } from './@core/auth/auth.service'; import { ConfigModule } from '@nestjs/config'; import { ConnectionsModule } from './@core/connections/connections.module'; import { ScheduleModule } from '@nestjs/schedule'; import { TasksService } from './@core/tasks/tasks.service'; import { CrmConnectionModule } from './@core/connections/crm/crm-connection.module'; import { LoggerModule } from 'nestjs-pino'; -import { LoggerService } from './@core/logger/logger.service'; import { TicketingModule } from './ticketing/ticketing.module'; import { HrisModule } from './hris/hris.module'; import { MarketingAutomationModule } from './marketing-automation/marketing-automation.module'; @@ -66,9 +64,7 @@ import { FieldMappingModule } from './@core/field-mapping/field-mapping.module'; controllers: [AppController], providers: [ AppService, - AuthService, TasksService, - LoggerService, { provide: APP_INTERCEPTOR, useFactory: () => diff --git a/packages/api/src/crm/@types/index.ts b/packages/api/src/crm/@types/index.ts index 914d1749a..93e878aaf 100644 --- a/packages/api/src/crm/@types/index.ts +++ b/packages/api/src/crm/@types/index.ts @@ -1,3 +1,23 @@ +import { + mapToContact_Freshsales, + mapToUnifiedContact_Freshsales, +} from '@contact/services/freshsales/mappers'; +import { + mapToContact_Hubspot, + mapToUnifiedContact_Hubspot, +} from '@contact/services/hubspot/mappers'; +import { + mapToContact_Pipedrive, + mapToUnifiedContact_Pipedrive, +} from '@contact/services/pipedrive/mappers'; +import { + mapToContact_Zendesk, + mapToUnifiedContact_Zendesk, +} from '@contact/services/zendesk/mappers'; +import { + mapToContact_Zoho, + mapToUnifiedContact_Zoho, +} from '@contact/services/zoho/mappers'; import { UnifiedContactInput, UnifiedContactOutput, @@ -20,6 +40,41 @@ export type UnifiedCrm = | UnifiedContactOutput | UnifiedDealInput; +export const providerUnificationMapping = { + hubspot: { + [CrmObject.contact]: { + unify: mapToUnifiedContact_Hubspot, + desunify: mapToContact_Hubspot, + }, + //[CrmObject.deal]: , + //[CrmObject.company]:, + }, + pipedrive: { + [CrmObject.contact]: { + unify: mapToUnifiedContact_Pipedrive, + desunify: mapToContact_Pipedrive, + }, + }, + zoho: { + [CrmObject.contact]: { + unify: mapToUnifiedContact_Zoho, + desunify: mapToContact_Zoho, + }, + }, + zendesk: { + [CrmObject.contact]: { + unify: mapToUnifiedContact_Zendesk, + desunify: mapToContact_Zendesk, + }, + }, + freshsales: { + [CrmObject.contact]: { + unify: mapToUnifiedContact_Freshsales, + desunify: mapToContact_Freshsales, + }, + }, +}; + export class PassThroughRequestDto { method: 'GET' | 'POST'; path: string; diff --git a/packages/api/src/crm/@unification/index.ts b/packages/api/src/crm/@unification/index.ts new file mode 100644 index 000000000..190575320 --- /dev/null +++ b/packages/api/src/crm/@unification/index.ts @@ -0,0 +1,65 @@ +import { CrmObject, providerUnificationMapping } from '@crm/@types'; +import { + CrmObjectInput, + Unified, + UnifyReturnType, + UnifySourceType, +} from '@@core/utils/types'; + +export async function desunifyCrm({ + sourceObject, + targetType_, + providerName, + customFieldMappings, +}: { + sourceObject: T; + targetType_: CrmObject; + providerName: string; + customFieldMappings?: { + slug: string; + remote_id: string; + }[]; +}): Promise { + if ( + providerUnificationMapping[providerName] && + providerUnificationMapping[providerName][targetType_] + ) { + return providerUnificationMapping[providerName][targetType_]['desunify']( + sourceObject, + customFieldMappings, + ); + } + + throw new Error( + `Unsupported target type for ${providerName}: ${targetType_}`, + ); +} + +export async function unifyCrm({ + sourceObject, + targetType_, + providerName, + customFieldMappings, +}: { + sourceObject: T; + targetType_: CrmObject; + providerName: string; + customFieldMappings?: { + slug: string; + remote_id: string; + }[]; +}): Promise { + if ( + providerUnificationMapping[providerName] && + providerUnificationMapping[providerName][targetType_] + ) { + return providerUnificationMapping[providerName][targetType_]['unify']( + sourceObject, + customFieldMappings, + ); + } + + throw new Error( + `Unsupported target type for ${providerName}: ${targetType_}`, + ); +} diff --git a/packages/api/src/crm/contact/contact.controller.ts b/packages/api/src/crm/contact/contact.controller.ts index 08642545d..784ffc086 100644 --- a/packages/api/src/crm/contact/contact.controller.ts +++ b/packages/api/src/crm/contact/contact.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Post, Body, Query, Get } from '@nestjs/common'; +import { Controller, Post, Body, Query, Get, Patch } from '@nestjs/common'; import { ContactService } from './services/contact.service'; import { LoggerService } from '@@core/logger/logger.service'; import { UnifiedContactInput } from './types/model.unified'; @@ -12,6 +12,7 @@ export class ContactController { this.logger.setContext(ContactController.name); } + //todo @Get('properties') getCustomProperties(@Query('linkedUserId') linkedUserId: string) { return this.contactService.getCustomProperties(linkedUserId); @@ -31,13 +32,13 @@ export class ContactController { } @Post() - addContact( - @Body() unfiedContactData: UnifiedContactInput, + addContacts( + @Body() unfiedContactData: UnifiedContactInput[], @Query('integrationId') integrationId: string, @Query('linkedUserId') linkedUserId: string, @Query('remote_data') remote_data?: boolean, ) { - return this.contactService.addContact( + return this.contactService.batchAddContacts( unfiedContactData, integrationId, linkedUserId, @@ -45,7 +46,13 @@ export class ContactController { ); } - //TODO: batch add Contact + @Patch() + updateContact( + @Query('id') id: string, + @Body() updateContactData: Partial, + ) { + return this.contactService.updateContact(id, updateContactData); + } + // TODO: update contact - // TODO: delete a contact } diff --git a/packages/api/src/crm/contact/services/contact.service.ts b/packages/api/src/crm/contact/services/contact.service.ts index f90bd67af..ac7cf3da8 100644 --- a/packages/api/src/crm/contact/services/contact.service.ts +++ b/packages/api/src/crm/contact/services/contact.service.ts @@ -100,6 +100,7 @@ export class ContactService { }, }); + //TODO: check why it doest iterate if (field_mappings && field_mappings.length > 0) { const entity = await this.prisma.entity.findFirst({ where: { ressource_owner_id: 'contact' }, @@ -163,6 +164,33 @@ export class ContactService { } } + async batchAddContacts( + unifiedContactData: UnifiedContactInput[], + integrationId: string, + linkedUserId: string, + remote_data?: boolean, + ): Promise> { + const responses = await Promise.all( + unifiedContactData.map((unifiedData) => + this.addContact(unifiedData, integrationId, linkedUserId, remote_data), + ), + ); + + const allContacts = responses.flatMap((response) => response.data.contacts); + const allRemoteData = responses.flatMap( + (response) => response.data.remote_data || [], + ); + + return { + data: { + contacts: allContacts, + remote_data: allRemoteData, + }, + message: 'All contacts inserted successfully', + statusCode: 201, + }; + } + async addContact( unifiedContactData: UnifiedContactInput, integrationId: string, @@ -368,4 +396,15 @@ export class ContactService { }); return { ...resp, data: res }; } + + async updateContact( + id: string, + updateContactData: Partial, + ): Promise> { + // TODO: fetch the contact from the database using 'id' + // TODO: update the contact with 'updateContactData' + // TODO: save the updated contact back to the database + // TODO: return the updated contact + return; + } } diff --git a/packages/api/src/@core/utils/unification/crm/freshsales/mappers/contact.ts b/packages/api/src/crm/contact/services/freshsales/mappers.ts similarity index 94% rename from packages/api/src/@core/utils/unification/crm/freshsales/mappers/contact.ts rename to packages/api/src/crm/contact/services/freshsales/mappers.ts index 5eb0d7eb3..fa2064621 100644 --- a/packages/api/src/@core/utils/unification/crm/freshsales/mappers/contact.ts +++ b/packages/api/src/crm/contact/services/freshsales/mappers.ts @@ -7,7 +7,7 @@ import { UnifiedContactOutput, } from '@contact/types/model.unified'; -export function mapToFreshsalesContact( +export function mapToContact_Freshsales( source: UnifiedContactInput, ): FreshsalesContactInput { // Assuming 'email_addresses' array contains at least one email and 'phone_numbers' array contains at least one phone number @@ -21,7 +21,7 @@ export function mapToFreshsalesContact( }; } -export function mapToUnifiedContact( +export function mapToUnifiedContact_Freshsales( source: FreshsalesContactOutput | FreshsalesContactOutput[], ): UnifiedContactOutput | UnifiedContactOutput[] { // Handling single FreshsalesContactOutput diff --git a/packages/api/src/@core/utils/unification/crm/hubspot/mappers/contact.ts b/packages/api/src/crm/contact/services/hubspot/mappers.ts similarity index 81% rename from packages/api/src/@core/utils/unification/crm/hubspot/mappers/contact.ts rename to packages/api/src/crm/contact/services/hubspot/mappers.ts index efa8779f0..cf71dcf7e 100644 --- a/packages/api/src/@core/utils/unification/crm/hubspot/mappers/contact.ts +++ b/packages/api/src/crm/contact/services/hubspot/mappers.ts @@ -1,10 +1,11 @@ -import { HubspotContactInput, HubspotContactOutput } from 'src/crm/@types'; +import { HubspotContactInput, HubspotContactOutput } from '@crm/@types'; import { UnifiedContactInput, UnifiedContactOutput, } from '@contact/types/model.unified'; +import { UnifySourceType } from '@@core/utils/types'; -export function mapToHubspotContact( +export function mapToContact_Hubspot( source: UnifiedContactInput, customFieldMappings?: { slug: string; @@ -37,18 +38,22 @@ export function mapToHubspotContact( return result; } -export function mapToUnifiedContact( - source: HubspotContactOutput | HubspotContactOutput[], +export function mapToUnifiedContact_Hubspot< + T extends UnifySourceType | UnifySourceType[], +>( + source: T, customFieldMappings?: { slug: string; remote_id: string; }[], ): UnifiedContactOutput | UnifiedContactOutput[] { - if (!Array.isArray(source)) { - return _mapSingleContact(source); + const source_ = source as HubspotContactOutput | HubspotContactOutput[]; + + if (!Array.isArray(source_)) { + return _mapSingleContact(source_); } // Handling array of HubspotContactOutput - return source.map((contact) => + return source_.map((contact) => _mapSingleContact(contact, customFieldMappings), ); } diff --git a/packages/api/src/@core/utils/unification/crm/pipedrive/mappers/contact.ts b/packages/api/src/crm/contact/services/pipedrive/mappers.ts similarity index 95% rename from packages/api/src/@core/utils/unification/crm/pipedrive/mappers/contact.ts rename to packages/api/src/crm/contact/services/pipedrive/mappers.ts index d71cb967a..aa79abd2b 100644 --- a/packages/api/src/@core/utils/unification/crm/pipedrive/mappers/contact.ts +++ b/packages/api/src/crm/contact/services/pipedrive/mappers.ts @@ -4,7 +4,7 @@ import { UnifiedContactOutput, } from '@contact/types/model.unified'; -export function mapToPipedriveContact( +export function mapToContact_Pipedrive( source: UnifiedContactInput, ): PipedriveContactInput { // Assuming 'email_addresses' and 'phone_numbers' arrays contain at least one entry @@ -28,7 +28,7 @@ export function mapToPipedriveContact( }; } -export function mapToUnifiedContact( +export function mapToUnifiedContact_Pipedrive( source: PipedriveContactOutput | PipedriveContactOutput[], ): UnifiedContactOutput | UnifiedContactOutput[] { if (!Array.isArray(source)) { diff --git a/packages/api/src/@core/utils/unification/crm/zendesk/mappers/contact.ts b/packages/api/src/crm/contact/services/zendesk/mappers.ts similarity index 95% rename from packages/api/src/@core/utils/unification/crm/zendesk/mappers/contact.ts rename to packages/api/src/crm/contact/services/zendesk/mappers.ts index a1c4f3cb8..96060bd0a 100644 --- a/packages/api/src/@core/utils/unification/crm/zendesk/mappers/contact.ts +++ b/packages/api/src/crm/contact/services/zendesk/mappers.ts @@ -4,7 +4,7 @@ import { UnifiedContactOutput, } from '@contact/types/model.unified'; -export function mapToZendeskContact( +export function mapToContact_Zendesk( source: UnifiedContactInput, ): ZendeskContactInput { // Assuming 'email_addresses' array contains at least one email and 'phone_numbers' array contains at least one phone number @@ -20,7 +20,7 @@ export function mapToZendeskContact( }; } -export function mapToUnifiedContact( +export function mapToUnifiedContact_Zendesk( source: ZendeskContactOutput | ZendeskContactOutput[], ): UnifiedContactOutput | UnifiedContactOutput[] { if (!Array.isArray(source)) { diff --git a/packages/api/src/@core/utils/unification/crm/zoho/mappers/contact.ts b/packages/api/src/crm/contact/services/zoho/mappers.ts similarity index 96% rename from packages/api/src/@core/utils/unification/crm/zoho/mappers/contact.ts rename to packages/api/src/crm/contact/services/zoho/mappers.ts index 0dbdf71d1..c27001584 100644 --- a/packages/api/src/@core/utils/unification/crm/zoho/mappers/contact.ts +++ b/packages/api/src/crm/contact/services/zoho/mappers.ts @@ -4,7 +4,7 @@ import { UnifiedContactOutput, } from '@contact/types/model.unified'; -export function mapToZohoContact( +export function mapToContact_Zoho( source: UnifiedContactInput, ): ZohoContactInput { // Assuming 'email_addresses' array contains at least one email and 'phone_numbers' array contains at least one phone number @@ -22,7 +22,7 @@ export function mapToZohoContact( };*/ } //TODO -export function mapToUnifiedContact( +export function mapToUnifiedContact_Zoho( source: ZohoContactOutput | ZohoContactOutput[], ): UnifiedContactOutput | UnifiedContactOutput[] { if (!Array.isArray(source)) { diff --git a/packages/webapp/package.json b/packages/webapp/package.json index 25db3427f..75446c819 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -10,15 +10,23 @@ "preview": "vite preview" }, "dependencies": { + "@ant-design/icons": "^5.2.6", + "@faker-js/faker": "^8.3.1", "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-navigation-menu": "^1.1.4", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-select": "^2.0.0", + "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-tabs": "^1.0.4", + "@radix-ui/react-tooltip": "^1.0.7", + "@tanstack/react-table": "^8.10.7", + "antd": "^5.11.5", "class-variance-authority": "^0.7.0", "clsx": "^1.2.1", "cmdk": "^0.2.0", @@ -27,6 +35,8 @@ "react": "^18.2.0", "react-day-picker": "^8.9.1", "react-dom": "^18.2.0", + "react-dropzone": "^14.2.3", + "react-router-dom": "^6.20.0", "recharts": "^2.10.1", "tailwind-merge": "^2.0.0", "tailwindcss-animate": "^1.0.7" diff --git a/packages/webapp/src/App.tsx b/packages/webapp/src/App.tsx index 72a96ff77..e0ce6d64f 100644 --- a/packages/webapp/src/App.tsx +++ b/packages/webapp/src/App.tsx @@ -1,13 +1,22 @@ import './App.css' import { ThemeProvider } from '@/components/theme-provider' import DashboardPage from './components/dashboard' +import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; +import JobsPage from './components/jobs'; +import ConnectionsPage from './components/connections'; +import TaskPage from './components/jobs/Task'; function App() { return ( -
- -
+ + + } /> + } /> + } /> + } /> + +
) } diff --git a/packages/webapp/src/components/api-keys/components/choose-project.tsx b/packages/webapp/src/components/api-keys/components/choose-project.tsx new file mode 100644 index 000000000..d6d5675a5 --- /dev/null +++ b/packages/webapp/src/components/api-keys/components/choose-project.tsx @@ -0,0 +1,204 @@ +"use client" + +import * as React from "react" +import { + CaretSortIcon, + CheckIcon, + PlusCircledIcon, +} from "@radix-ui/react-icons" + +import { cn } from "@/lib/utils" +import { + Avatar, + AvatarFallback, + AvatarImage, +} from "@/components/ui/avatar" +import { Button } from "@/components/ui/button" +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandSeparator, +} from "@/components/ui/command" +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" + +const groups = [ + { + label: "Teams", + teams: [ + { + label: "Acme Inc.", + value: "acme-inc", + }, + { + label: "Monsters Inc.", + value: "monsters", + }, + ], + }, +] + +type Team = (typeof groups)[number]["teams"][number] + +type PopoverTriggerProps = React.ComponentPropsWithoutRef + +interface TeamSwitcherProps extends PopoverTriggerProps {} + +export default function ChooseProjectSwitcher({ className }: TeamSwitcherProps) { + const [open, setOpen] = React.useState(false) + const [showNewTeamDialog, setShowNewTeamDialog] = React.useState(false) + const [selectedTeam, setSelectedTeam] = React.useState( + groups[0].teams[0] + ) + + return ( + + + + + + + + + + No team found. + {groups.map((group) => ( + + {group.teams.map((team) => ( + { + setSelectedTeam(team) + setOpen(false) + }} + className="text-sm" + > + + + SC + + {team.label} + + + ))} + + ))} + + + + + + { + setOpen(false) + setShowNewTeamDialog(true) + }} + > + + Create Team + + + + + + + + + + Create team + + Add a new team to manage products and customers. + + +
+
+
+ + +
+
+ + +
+
+
+ + + + +
+
+ ) +} \ No newline at end of file diff --git a/packages/webapp/src/components/api-keys/data/api-keys.ts b/packages/webapp/src/components/api-keys/data/api-keys.ts new file mode 100644 index 000000000..c31e53e38 --- /dev/null +++ b/packages/webapp/src/components/api-keys/data/api-keys.ts @@ -0,0 +1,22 @@ +export const API_KEYS = [ + { + "name": "API Key 1", + "token": "sk_test_e74394c2-f063-4693-af5f-84b7281de5e8", + "created": "Jul 31, 2019" + }, + { + "name": "API Key 1", + "token": "sk_test_e74394c2-f063-4693-af5f-84b7281de5e8", + "created": "Jul 31, 2019" + }, + { + "name": "API Key 1", + "token": "sk_test_e74394c2-f063-4693-af5f-84b7281de5e8", + "created": "Jul 31, 2019" + }, + { + "name": "API Key 1", + "token": "sk_test_e74394c2-f063-4693-af5f-84b7281de5e8", + "created": "Jul 31, 2019" + } +] \ No newline at end of file diff --git a/packages/webapp/src/components/api-keys/data/columns.tsx b/packages/webapp/src/components/api-keys/data/columns.tsx new file mode 100644 index 000000000..11f826c20 --- /dev/null +++ b/packages/webapp/src/components/api-keys/data/columns.tsx @@ -0,0 +1,43 @@ +"use client" + +import { ColumnDef } from "@tanstack/react-table" + +import { Checkbox } from "@/components/ui/checkbox" + +import { ApiKey } from "./schema" +import { DataTableColumnHeader } from "./../../jobs/components/data-table-column-header" +import { DataTableRowActions } from "./../../jobs/components/data-table-row-actions" + +export const columns: ColumnDef[] = [ + { + accessorKey: "name", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("name")}
, + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: "token", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("token")}
, + + }, + { + accessorKey: "created", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.getValue("created")}
, + filterFn: (row, id, value) => { + return value.includes(row.getValue(id)) + }, + }, + { + id: "actions", + cell: ({ row }) => , + }, +] \ No newline at end of file diff --git a/packages/webapp/src/components/api-keys/data/data.tsx b/packages/webapp/src/components/api-keys/data/data.tsx new file mode 100644 index 000000000..03743ba86 --- /dev/null +++ b/packages/webapp/src/components/api-keys/data/data.tsx @@ -0,0 +1,71 @@ +import { + ArrowDownIcon, + ArrowRightIcon, + ArrowUpIcon, + CheckCircledIcon, + CircleIcon, + CrossCircledIcon, + QuestionMarkCircledIcon, + StopwatchIcon, + } from "@radix-ui/react-icons" + + export const labels = [ + { + value: "bug", + label: "Bug", + }, + { + value: "feature", + label: "Feature", + }, + { + value: "documentation", + label: "Documentation", + }, + ] + + export const statuses = [ + { + value: "backlog", + label: "Backlog", + icon: QuestionMarkCircledIcon, + }, + { + value: "todo", + label: "Todo", + icon: CircleIcon, + }, + { + value: "in progress", + label: "In Progress", + icon: StopwatchIcon, + }, + { + value: "done", + label: "Done", + icon: CheckCircledIcon, + }, + { + value: "canceled", + label: "Canceled", + icon: CrossCircledIcon, + }, + ] + + export const priorities = [ + { + label: "Low", + value: "low", + icon: ArrowDownIcon, + }, + { + label: "Medium", + value: "medium", + icon: ArrowRightIcon, + }, + { + label: "High", + value: "high", + icon: ArrowUpIcon, + }, + ] \ No newline at end of file diff --git a/packages/webapp/src/components/api-keys/data/schema.ts b/packages/webapp/src/components/api-keys/data/schema.ts new file mode 100644 index 000000000..eb8015db0 --- /dev/null +++ b/packages/webapp/src/components/api-keys/data/schema.ts @@ -0,0 +1,11 @@ +import { z } from "zod" + +// We're keeping a simple non-relational schema here. +// IRL, you will have a schema for your data models. +export const apiKeySchema = z.object({ + name: z.string(), + token: z.string(), + created: z.string(), +}) + +export type ApiKey = z.infer \ No newline at end of file diff --git a/packages/webapp/src/components/api-keys/data/seed.ts b/packages/webapp/src/components/api-keys/data/seed.ts new file mode 100644 index 000000000..b35a5ef17 --- /dev/null +++ b/packages/webapp/src/components/api-keys/data/seed.ts @@ -0,0 +1,20 @@ +import fs from "fs" +import path from "path" +import { faker } from "@faker-js/faker" + +import { labels, priorities, statuses } from "./data" + +const tasks = Array.from({ length: 100 }, () => ({ + id: `TASK-${faker.number.int({ min: 1000, max: 9999 })}`, + title: faker.hacker.phrase().replace(/^./, (letter) => letter.toUpperCase()), + status: faker.helpers.arrayElement(statuses).value, + label: faker.helpers.arrayElement(labels).value, + direction: faker.helpers.arrayElement(priorities).value, +})) + +fs.writeFileSync( + path.join(__dirname, "tasks.json"), + JSON.stringify(tasks, null, 2) +) + +console.log("✅ Tasks data generated.") \ No newline at end of file diff --git a/packages/webapp/src/components/api-keys/index.tsx b/packages/webapp/src/components/api-keys/index.tsx new file mode 100644 index 000000000..d910a1eab --- /dev/null +++ b/packages/webapp/src/components/api-keys/index.tsx @@ -0,0 +1,75 @@ +import { PlusCircledIcon } from "@radix-ui/react-icons"; +import { Button } from "../ui/button"; +import ChooseProjectSwitcher from "./components/choose-project"; +import { useEffect, useState } from "react"; +import { API_KEYS } from "./data/api-keys"; +import { columns } from "./data/columns"; +import { DataTable } from "../jobs/components/data-table"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" +import { Label } from "../ui/label"; +import { Input } from "../ui/input"; +export interface ApiKey { + name: string; + token: string; + created: string; +} + +export default function ApiKeysPage() { + const [apiKeys, setApiKeys] = useState(); + + useEffect(() => { + async function loadTasks() { + //const fetchedTasks = await getTasks(); + setApiKeys(API_KEYS); + } + loadTasks(); + }, []); + return ( + +
+
+
+

Api Keys

+

Manage your api keys.

+
+
+
+ + + + + + + + Add New Api Key + + Never share this key, you must saved it it will be displayed once ! + + +
+
+ + +
+
+ + + +
+
+
+ {apiKeys && }
+
+ ); + } \ No newline at end of file diff --git a/packages/webapp/src/components/configuration/NavMenu.tsx b/packages/webapp/src/components/configuration/NavMenu.tsx new file mode 100644 index 000000000..b9669fb6c --- /dev/null +++ b/packages/webapp/src/components/configuration/NavMenu.tsx @@ -0,0 +1,128 @@ +"use client" + +import * as React from "react" + +import { cn } from "@/lib/utils" +import { + NavigationMenu, + NavigationMenuContent, + NavigationMenuItem, + NavigationMenuLink, + NavigationMenuList, + NavigationMenuTrigger, + navigationMenuTriggerStyle, +} from "@/components/ui/navigation-menu" +import { Separator } from "../ui/separator" + +const components: { title: string; href: string; description: string }[] = [ + { + title: "Create new oAuth connection", + href: "/docs/primitives/alert-dialog", + description: + "A modal dialog that interrupts the user with important content and expects a response.", + }, + { + title: "Manage my oAuth connections", + href: "/docs/primitives/hover-card", + description: + "For sighted users to preview content available behind a link.", + } +] + +const components2: { title: string; href: string; description: string }[] = [ + { + title: "Define a new field mapping", + href: "/docs/primitives/alert-dialog", + description: + "A modal dialog that interrupts the user with important content and expects a response.", + }, + { + title: "Map a field mapping", + href: "/docs/primitives/hover-card", + description: + "For sighted users to preview content available behind a link.", + } + ] + +export function NavMenu() { + return ( + + + + Linked Accounts + +
    + {components.map((component) => ( + + {component.description} + + ))} +
+
+
+ + Field Mappings + +
    + {components2.map((component) => ( + + {component.description} + + ))} +
+
+
+ + OAuth + +
    + {components.map((component) => ( + + {component.description} + + ))} +
+
+
+
+
+ ) +} + +const ListItem = React.forwardRef< + React.ElementRef<"a">, + React.ComponentPropsWithoutRef<"a"> +>(({ className, title, children, ...props }, ref) => { + return ( +
  • + + +
    {title}
    +

    + {children} +

    +
    +
    +
  • + ) +}) +ListItem.displayName = "ListItem" diff --git a/packages/webapp/src/components/configuration/components/DragDrop.tsx b/packages/webapp/src/components/configuration/components/DragDrop.tsx new file mode 100644 index 000000000..380ec8912 --- /dev/null +++ b/packages/webapp/src/components/configuration/components/DragDrop.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { InboxOutlined } from '@ant-design/icons'; +import type { UploadProps } from 'antd'; +import { message, Upload } from 'antd'; + +const { Dragger } = Upload; + +const props: UploadProps = { + name: 'file', + multiple: true, + action: 'https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188', + onChange(info) { + const { status } = info.file; + if (status !== 'uploading') { + console.log(info.file, info.fileList); + } + if (status === 'done') { + message.success(`${info.file.name} file uploaded successfully.`); + } else if (status === 'error') { + message.error(`${info.file.name} file upload failed.`); + } + }, + onDrop(e) { + console.log('Dropped files', e.dataTransfer.files); + }, +}; + +const DragDrop = ({children}) => ( + +

    +

    + {children} +
    +); + +export default DragDrop; \ No newline at end of file diff --git a/packages/webapp/src/components/configuration/components/FieldMappingModal.tsx b/packages/webapp/src/components/configuration/components/FieldMappingModal.tsx new file mode 100644 index 000000000..e5e8fd2df --- /dev/null +++ b/packages/webapp/src/components/configuration/components/FieldMappingModal.tsx @@ -0,0 +1,74 @@ +import { Button } from "@/components/ui/button" +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "@/components/ui/tabs" + +export function FModal() { + return ( + + + Define Fields + Map Fields + + + + + Account + + Make changes to your account here. Click save when you're done. + + + +
    + + +
    +
    + + +
    +
    + + + +
    +
    + + + + Password + + Change your password here. After saving, you'll be logged out. + + + +
    + + +
    +
    + + +
    +
    + + + +
    +
    +
    + ) +} diff --git a/packages/webapp/src/components/configuration/index.tsx b/packages/webapp/src/components/configuration/index.tsx new file mode 100644 index 000000000..ba3a642d9 --- /dev/null +++ b/packages/webapp/src/components/configuration/index.tsx @@ -0,0 +1,173 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card" +import { + Dialog, + DialogContent, + DialogTrigger, +} from "@/components/ui/dialog" +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "@/components/ui/tabs" +import { RecentSales } from "../dashboard/components/recent-sales"; +import { Button } from "../ui/button"; +import { PlusCircledIcon } from "@radix-ui/react-icons"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { FModal } from "./components/FieldMappingModal" +import { Separator } from "../ui/separator"; + +export default function ConfigurationPage() { + /*const {getRootProps, getInputProps} = useDropzone({ + // Implement file upload handling here + onDrop: (acceptedFiles) => { + acceptedFiles.forEach((file) => { + // Handle file upload here + console.log(file); + }); + } + });*/ + + + return ( +
    +
    +
    +

    Configuration

    +
    + + + Linked Accounts + + Field Mapping + + + oAuth + + + + +
    + {/* + + + Import your origin users + + + + +

    Drag 'n' drop some files here, or click to select files

    +
    +
    */} + + + + + + + + +

    Add a new linked user

    +
    + + Import your own linked users + + +
    +
    +
    + + + + Your Linked Accounts + + You connected 1389 linked accounts. + + + + + + + +
    +
    + +
    + + + + + + {/* + Edit profile + + Make changes to your profile here. Click save when you're done. + + +
    +
    + + +
    +
    + + +
    +
    + + + */} + +
    +
    + + + + Your Fields Mapping + + You built 30 fields mapping. + + + + + + + +
    +
    +
    +
    + +
    + ); + } \ No newline at end of file diff --git a/packages/webapp/src/components/connections/Connection.tsx b/packages/webapp/src/components/connections/Connection.tsx new file mode 100644 index 000000000..d07671d6d --- /dev/null +++ b/packages/webapp/src/components/connections/Connection.tsx @@ -0,0 +1,116 @@ +import { columns } from "./data/columns" +import { DataTable } from "./../jobs/components/data-table" +import { useEffect, useState } from "react" +import { CONNECTIONS } from "./data/connection"; +import { + Card, + CardContent, + CardHeader, + CardTitle, + } from "@/components/ui/card" +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "../ui/dialog"; +import { Button } from "../ui/button"; +import { PlusCircledIcon } from "@radix-ui/react-icons"; +import { Label } from "../ui/label"; +import { Input } from "../ui/input"; + +export interface Connection { + organisation: string; + app: string; + status: string; + category: string; + linkedUser: string; + date: string; +} + +export default function ConnectionTable() { + const [connections, setTasks] = useState(); + + useEffect(() => { + async function loadTasks() { + //const fetchedTasks = await getTasks(); + setTasks(CONNECTIONS); + } + + loadTasks(); + }, []); + return ( + <> +
    +
    + + + Linked + + +

    0

    +
    + +
    + + + Incomplete Link + + +

    3

    +
    +
    + + + Relink Needed + + +

    1

    +
    + +
    + + +
    + + + + + + + Edit profile + + Make changes to your profile here. Click save when you're done. + + +
    +
    + + +
    +
    + + +
    +
    + + + +
    +
    + + {connections && } +
    + + ) +} \ No newline at end of file diff --git a/packages/webapp/src/components/connections/data/columns.tsx b/packages/webapp/src/components/connections/data/columns.tsx new file mode 100644 index 000000000..8de22d898 --- /dev/null +++ b/packages/webapp/src/components/connections/data/columns.tsx @@ -0,0 +1,168 @@ +"use client" + +import { ColumnDef } from "@tanstack/react-table" + +import { Badge } from "@/components/ui/badge" +import { Checkbox } from "@/components/ui/checkbox" + +import { labels, priorities, statuses } from "../data/data" +import { Connection } from "./schema" +import { DataTableColumnHeader } from "./../../jobs/components/data-table-column-header" +import { DataTableRowActions } from "./../../jobs/components/data-table-row-actions" + +export const columns: ColumnDef[] = [ + { + id: "select", + header: ({ table }) => ( + table.toggleAllPageRowsSelected(!!value)} + aria-label="Select all" + className="translate-y-[2px]" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + aria-label="Select row" + className="translate-y-[2px]" + /> + ), + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: "Organisation", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
    {row.getValue("Organisation")}
    , + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: "app", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const label = labels.find((label) => label.value === row.original.app) + + return ( +
    + {label && {label.label}} + {/* + {row.getValue("url")} + */} +
    + ) + }, + }, + { + accessorKey: "category", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const status = statuses.find( + (status) => status.value === row.getValue("category") + ) + + if (!status) { + return null + } + + return ( +
    + {status.icon && ( + + )} + {status.label} +
    + ) + }, + filterFn: (row, id, value) => { + return value.includes(row.getValue(id)) + }, + }, + { + accessorKey: "status", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const direction = priorities.find( + (direction) => direction.value === row.getValue("status") + ) + + if (!direction) { + return null + } + + return ( +
    + {direction.icon && ( + + )} + {direction.label} +
    + ) + }, + filterFn: (row, id, value) => { + return value.includes(row.getValue(id)) + }, + }, + { + accessorKey: "linkedUser", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const status = statuses.find( + (status) => status.value === row.getValue("linkedUser") + ) + + if (!status) { + return null + } + + return ( +
    + {status.icon && ( + + )} + {status.label} +
    + ) + }, + filterFn: (row, id, value) => { + return value.includes(row.getValue(id)) + }, + }, + { + accessorKey: "date", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const label = labels.find((label) => label.value === row.original.date) + + return ( +
    + {label && {label.label}} + + {row.getValue("date")} + +
    + ) + }, + }, + { + id: "actions", + cell: ({ row }) => , + }, +] \ No newline at end of file diff --git a/packages/webapp/src/components/connections/data/connection.ts b/packages/webapp/src/components/connections/data/connection.ts new file mode 100644 index 000000000..ba6e565f3 --- /dev/null +++ b/packages/webapp/src/components/connections/data/connection.ts @@ -0,0 +1,119 @@ +export const CONNECTIONS = [ + { + "linkedUser": "TASK-8782", + "status": "in progress", + "app": "documentation", + "category": "medium", + "date": "", + "organisation": "", + + }, + { + "linkedUser": "TASK-7878", + "integration": "Try to calculate the EXE feed, maybe it will index the multi-byte pixel!", + "status": "backlog", + "app": "documentation", + "category": "medium", + "date": "", + "organisation": "", + }, + { + "linkedUser": "TASK-7839", + "integration": "We need to bypass the neural TCP card!", + "status": "todo", + "app": "bug", + "category": "high", + "date": "", + "organisation": "", + }, + { + "linkedUser": "TASK-5562", + "integration": "The SAS interface is down, bypass the open-source pixel so we can back up the PNG bandwlinkedUserth!", + "status": "backlog", + "app": "feature", + "category": "medium", + "date": "", + "organisation": "", + }, + { + "linkedUser": "TASK-8686", + "integration": "I'll parse the wireless SSL protocol, that should driver the API panel!", + "status": "canceled", + "app": "feature", + "category": "medium", + "date": "", + "organisation": "", + }, + { + "linkedUser": "TASK-1280", + "integration": "Use the digital TLS panel, then you can transmit the haptic system!", + "status": "done", + "app": "bug", + "category": "high", + "date": "", + "organisation": "", + }, + { + "linkedUser": "TASK-7262", + "integration": "The UTF8 application is down, parse the neural bandwlinkedUserth so we can back up the PNG firewall!", + "status": "done", + "app": "feature", + "category": "high", + "date": "", + "organisation": "", + }, + { + "linkedUser": "TASK-1138", + "integration": "Generating the driver won't do anything, we need to quantify the 1080p SMTP bandwlinkedUserth!", + "status": "in progress", + "app": "feature", + "category": "medium", + "date": "", + "organisation": "", + }, + { + "linkedUser": "TASK-7184", + "integration": "We need to program the back-end THX pixel!", + "status": "todo", + "app": "feature", + "category": "low", + "date": "", + "organisation": "", + }, + { + "linkedUser": "TASK-5160", + "integration": "Calculating the bus won't do anything, we need to navigate the back-end JSON protocol!", + "status": "in progress", + "app": "documentation", + "category": "high", + "date": "", + "organisation": "", + }, + { + "linkedUser": "TASK-5618", + "integration": "Generating the driver won't do anything, we need to index the online SSL application!", + "status": "done", + "app": "documentation", + "category": "medium", + "date": "", + "organisation": "", + }, + { + "linkedUser": "TASK-6699", + "integration": "I'll transmit the wireless JBOD capacitor, that should hard drive the SSD feed!", + "status": "backlog", + "app": "documentation", + "category": "medium", + "date": "", + "organisation": "", + }, + { + "linkedUser": "TASK-2858", + "integration": "We need to overrlinkedUsere the online UDP bus!", + "status": "backlog", + "app": "bug", + "category": "medium", + "date": "", + "organisation": "", + }, +] \ No newline at end of file diff --git a/packages/webapp/src/components/connections/data/data.tsx b/packages/webapp/src/components/connections/data/data.tsx new file mode 100644 index 000000000..03743ba86 --- /dev/null +++ b/packages/webapp/src/components/connections/data/data.tsx @@ -0,0 +1,71 @@ +import { + ArrowDownIcon, + ArrowRightIcon, + ArrowUpIcon, + CheckCircledIcon, + CircleIcon, + CrossCircledIcon, + QuestionMarkCircledIcon, + StopwatchIcon, + } from "@radix-ui/react-icons" + + export const labels = [ + { + value: "bug", + label: "Bug", + }, + { + value: "feature", + label: "Feature", + }, + { + value: "documentation", + label: "Documentation", + }, + ] + + export const statuses = [ + { + value: "backlog", + label: "Backlog", + icon: QuestionMarkCircledIcon, + }, + { + value: "todo", + label: "Todo", + icon: CircleIcon, + }, + { + value: "in progress", + label: "In Progress", + icon: StopwatchIcon, + }, + { + value: "done", + label: "Done", + icon: CheckCircledIcon, + }, + { + value: "canceled", + label: "Canceled", + icon: CrossCircledIcon, + }, + ] + + export const priorities = [ + { + label: "Low", + value: "low", + icon: ArrowDownIcon, + }, + { + label: "Medium", + value: "medium", + icon: ArrowRightIcon, + }, + { + label: "High", + value: "high", + icon: ArrowUpIcon, + }, + ] \ No newline at end of file diff --git a/packages/webapp/src/components/connections/data/schema.ts b/packages/webapp/src/components/connections/data/schema.ts new file mode 100644 index 000000000..7ccf69cc8 --- /dev/null +++ b/packages/webapp/src/components/connections/data/schema.ts @@ -0,0 +1,14 @@ +import { z } from "zod" + +// We're keeping a simple non-relational schema here. +// IRL, you will have a schema for your data models. +export const connectionSchema = z.object({ + organisation: z.string(), + app: z.string(), + category: z.string(), + status: z.string(), + linkedUser: z.string(), + date: z.string() +}) + +export type Connection = z.infer \ No newline at end of file diff --git a/packages/webapp/src/components/connections/data/seed.ts b/packages/webapp/src/components/connections/data/seed.ts new file mode 100644 index 000000000..b35a5ef17 --- /dev/null +++ b/packages/webapp/src/components/connections/data/seed.ts @@ -0,0 +1,20 @@ +import fs from "fs" +import path from "path" +import { faker } from "@faker-js/faker" + +import { labels, priorities, statuses } from "./data" + +const tasks = Array.from({ length: 100 }, () => ({ + id: `TASK-${faker.number.int({ min: 1000, max: 9999 })}`, + title: faker.hacker.phrase().replace(/^./, (letter) => letter.toUpperCase()), + status: faker.helpers.arrayElement(statuses).value, + label: faker.helpers.arrayElement(labels).value, + direction: faker.helpers.arrayElement(priorities).value, +})) + +fs.writeFileSync( + path.join(__dirname, "tasks.json"), + JSON.stringify(tasks, null, 2) +) + +console.log("✅ Tasks data generated.") \ No newline at end of file diff --git a/packages/webapp/src/components/connections/index.tsx b/packages/webapp/src/components/connections/index.tsx new file mode 100644 index 000000000..59dc8edc7 --- /dev/null +++ b/packages/webapp/src/components/connections/index.tsx @@ -0,0 +1,15 @@ +import ConnectionTable from "./Connection"; + +export default function ConnectionsPage() { + return ( +
    +
    +
    +

    Connections

    +

    Integrations between your users’ accounts and third-party apps.

    +
    + +
    +
    + ); + } \ No newline at end of file diff --git a/packages/webapp/src/components/dashboard/components/main-nav.tsx b/packages/webapp/src/components/dashboard/components/main-nav.tsx index b56e1ae08..f8a1f59c0 100644 --- a/packages/webapp/src/components/dashboard/components/main-nav.tsx +++ b/packages/webapp/src/components/dashboard/components/main-nav.tsx @@ -1,38 +1,76 @@ -import { cn } from "@/lib/utils" +import { useState } from "react"; export function MainNav({ + onLinkClick, className, ...props -}: React.HTMLAttributes) { +}: { + onLinkClick: (name: string) => void; + className: string; +}) { + const [selectedItem, setSelectedItem] = useState("dashboard"); + + const navItemClassName = (itemName: string) => + `text-sm border-b font-medium w-full text-left px-4 py-2 hover:bg-gray-900 cursor-pointer ${ + selectedItem === itemName ? "bg-gray-900" : "text-muted-foreground" + } transition-colors`; + + function click(name: string) { + setSelectedItem(name); + onLinkClick(name); + } + return ( - ) -} \ No newline at end of file + ); +} diff --git a/packages/webapp/src/components/dashboard/components/recent-sales.tsx b/packages/webapp/src/components/dashboard/components/recent-sales.tsx index 0ac9d3462..e989a8bbc 100644 --- a/packages/webapp/src/components/dashboard/components/recent-sales.tsx +++ b/packages/webapp/src/components/dashboard/components/recent-sales.tsx @@ -3,6 +3,7 @@ import { AvatarFallback, AvatarImage, } from "@/components/ui/avatar" +import { Badge } from "@/components/ui/badge" export function RecentSales() { return ( @@ -15,10 +16,12 @@ import {

    Olivia Martin

    - olivia.martin@email.com + @ACME.ORG

    -
    +$1,999.00
    +
    + user-123-iko +
    @@ -27,9 +30,9 @@ import {

    Jackson Lee

    -

    jackson.lee@email.com

    +

    @ACME.ORG

    -
    +$39.00
    + user-123-iko
    @@ -39,10 +42,10 @@ import {

    Isabella Nguyen

    - isabella.nguyen@email.com + @ACME.ORG

    -
    +$299.00
    + user-123-iko
    @@ -51,9 +54,9 @@ import {

    William Kim

    -

    will@email.com

    +

    @ACME.ORG

    -
    +$99.00
    + user-123-iko
    @@ -62,9 +65,9 @@ import {

    Sofia Davis

    -

    sofia.davis@email.com

    +

    @ACME.ORG

    -
    +$39.00
    + user-123-iko
    ) diff --git a/packages/webapp/src/components/dashboard/components/search.tsx b/packages/webapp/src/components/dashboard/components/search.tsx index 8fcc71320..354b6a7be 100644 --- a/packages/webapp/src/components/dashboard/components/search.tsx +++ b/packages/webapp/src/components/dashboard/components/search.tsx @@ -6,7 +6,7 @@ export function Search() { ) diff --git a/packages/webapp/src/components/dashboard/components/team-switcher.tsx b/packages/webapp/src/components/dashboard/components/team-switcher.tsx index ffcff6788..ad7760cc6 100644 --- a/packages/webapp/src/components/dashboard/components/team-switcher.tsx +++ b/packages/webapp/src/components/dashboard/components/team-switcher.tsx @@ -48,15 +48,6 @@ import { } from "@/components/ui/select" const groups = [ - { - label: "Personal Account", - teams: [ - { - label: "Alicia Koch", - value: "personal", - }, - ], - }, { label: "Teams", teams: [ @@ -96,7 +87,7 @@ export default function TeamSwitcher({ className }: TeamSwitcherProps) { aria-label="Select a team" className={cn("w-[200px] justify-between", className)} > - + - + diff --git a/packages/webapp/src/components/dashboard/components/user-nav.tsx b/packages/webapp/src/components/dashboard/components/user-nav.tsx index 63ffe7be5..8baf833a0 100644 --- a/packages/webapp/src/components/dashboard/components/user-nav.tsx +++ b/packages/webapp/src/components/dashboard/components/user-nav.tsx @@ -11,7 +11,6 @@ import { DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, - DropdownMenuShortcut, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" @@ -26,7 +25,7 @@ import { - +

    shadcn

    @@ -37,24 +36,20 @@ import { + Profile - ⇧⌘P Billing - ⌘B Settings - ⌘S - New Team Log out - ⇧⌘Q diff --git a/packages/webapp/src/components/dashboard/index.tsx b/packages/webapp/src/components/dashboard/index.tsx index 26fb6ca20..d2d4b2e4d 100644 --- a/packages/webapp/src/components/dashboard/index.tsx +++ b/packages/webapp/src/components/dashboard/index.tsx @@ -1,188 +1,55 @@ -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "@/components/ui/card" -import { - Tabs, - TabsContent, - TabsList, - TabsTrigger, -} from "@/components/ui/tabs" -import { CalendarDateRangePicker } from "./components/date-range-picker" import { MainNav } from "./components/main-nav" -import { Overview } from "./components/overview" -import { RecentSales } from "./components/recent-sales" -import { Search } from "./components/search" import TeamSwitcher from "./components/team-switcher" import { UserNav } from "./components/user-nav" -import { Button } from "../ui/button" +import { useState } from "react" +import JobsPage from "../jobs" +import ConnectionsPage from "../connections" +import MainPage from "../main-component" +import ConfigurationPage from "../configuration" +import ApiKeysPage from "../api-keys" +import QuickStartPage from "../quickstart" export default function DashboardPage() { + const [activePage, setActivePage] = useState('dashboard'); + + let ContentComponent; + switch (activePage) { + case 'quickstart': + ContentComponent = QuickStartPage; + break; + case 'jobs': + ContentComponent = JobsPage; + break; + case 'connections': + ContentComponent = ConnectionsPage; + break; + case 'configuration': + ContentComponent = ConfigurationPage; + break; + case 'dashboard': + ContentComponent = MainPage; + break; + case 'api-keys': + ContentComponent = ApiKeysPage; + break; + default: + ContentComponent = MainPage; // The default page content + } return ( <> -
    -
    -
    - - - -
    - +
    +
    +
    + Panora. + + +
    -
    -
    -

    Dashboard

    -
    - - -
    -
    - - - Overview - - Analytics - - - Reports - - - Notifications - - - -
    - - - - Total Revenue - - - - - - -
    $45,231.89
    -

    - +20.1% from last month -

    -
    -
    - - - - Subscriptions - - - - - - - - -
    +2350
    -

    - +180.1% from last month -

    -
    -
    - - - Sales - - - - - - -
    +12,234
    -

    - +19% from last month -

    -
    -
    - - - - Active Now - - - - - - -
    +573
    -

    - +201 since last hour -

    -
    -
    -
    -
    - - - Overview - - - - - - - - Recent Sales - - You made 265 sales this month. - - - - - - -
    -
    -
    +
    +
    diff --git a/packages/webapp/src/components/integrations/index.tsx b/packages/webapp/src/components/integrations/index.tsx new file mode 100644 index 000000000..d10eff3f8 --- /dev/null +++ b/packages/webapp/src/components/integrations/index.tsx @@ -0,0 +1,14 @@ +export default function IntegrationssPage() { + return ( +
    +
    +

    Integrations

    +
    +
    +
    +
    + +
    +
    + ); + } \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/Task.tsx b/packages/webapp/src/components/jobs/Task.tsx new file mode 100644 index 000000000..dfc275299 --- /dev/null +++ b/packages/webapp/src/components/jobs/Task.tsx @@ -0,0 +1,34 @@ +import { columns } from "./components/columns" +import { DataTable } from "./components/data-table" +import { useEffect, useState } from "react" +import { TASKS } from "./data/task"; + +export interface Task { + method: string; + url: string; + status: string; + direction: string; + integration: string; + organisation: string; + date: string; +} + +export default function TaskPage() { + const [tasks, setTasks] = useState(); + + useEffect(() => { + async function loadTasks() { + //const fetchedTasks = await getTasks(); + setTasks(TASKS); + } + + loadTasks(); + }, []); + return ( + <> + + {tasks && } + + + ) +} \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/components/columns.tsx b/packages/webapp/src/components/jobs/components/columns.tsx new file mode 100644 index 000000000..9648b62f5 --- /dev/null +++ b/packages/webapp/src/components/jobs/components/columns.tsx @@ -0,0 +1,191 @@ +"use client" + +import { ColumnDef } from "@tanstack/react-table" + +import { Badge } from "@/components/ui/badge" +import { Checkbox } from "@/components/ui/checkbox" + +import { labels, labels2, priorities, statuses } from "../data/data" +import { Task } from "../data/schema" +import { DataTableColumnHeader } from "./data-table-column-header" +import { DataTableRowActions } from "./data-table-row-actions" + +export const columns: ColumnDef[] = [ + { + id: "select", + header: ({ table }) => ( + table.toggleAllPageRowsSelected(!!value)} + aria-label="Select all" + className="translate-y-[2px]" + /> + ), + cell: ({ row }) => ( + row.toggleSelected(!!value)} + aria-label="Select row" + className="translate-y-[2px]" + /> + ), + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: "Method", + header: ({ column }) => ( + + ), + cell: ({ row }) =>{ + const label = labels2.find((label) => label.value === row.original.method) + + return ( +
    + {label && {label.label}} +
    + ) + }, + enableSorting: false, + enableHiding: false, + }, + { + accessorKey: "url", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const label = labels.find((label) => label.value === row.original.url) + + return ( +
    + {label && {label.label}} +
    + ) + }, + }, + { + accessorKey: "status", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const status = statuses.find( + (status) => status.value === row.getValue("status") + ) + + if (!status) { + return null + } + + return ( +
    + {status.icon && ( + + )} + {status.label} +
    + ) + }, + filterFn: (row, id, value) => { + return value.includes(row.getValue(id)) + }, + }, + { + accessorKey: "direction", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const direction = priorities.find( + (direction) => direction.value === row.getValue("direction") + ) + + if (!direction) { + return null + } + + return ( +
    + {direction.icon && ( + + )} + {direction.label} +
    + ) + }, + filterFn: (row, id, value) => { + return value.includes(row.getValue(id)) + }, + }, + { + accessorKey: "integration", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const status = statuses.find( + (status) => status.value === row.getValue("integration") + ) + + if (!status) { + return null + } + + return ( +
    + {status.icon && ( + + )} + {status.label} +
    + ) + }, + filterFn: (row, id, value) => { + return value.includes(row.getValue(id)) + }, + }, + { + accessorKey: "organisation", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const label = labels.find((label) => label.value === row.original.organisation) + + return ( +
    + {label && {label.label}} + + {row.getValue("organisation")} + +
    + ) + }, + }, + { + accessorKey: "date", + header: ({ column }) => ( + + ), + cell: ({ row }) => { + const label = labels.find((label) => label.value === row.original.date) + + return ( +
    + {label && {label.label}} + + {row.getValue("date")} + +
    + ) + }, + }, + { + id: "actions", + cell: ({ row }) => , + }, +] \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/components/data-table-column-header.tsx b/packages/webapp/src/components/jobs/components/data-table-column-header.tsx new file mode 100644 index 000000000..3f7e73b81 --- /dev/null +++ b/packages/webapp/src/components/jobs/components/data-table-column-header.tsx @@ -0,0 +1,71 @@ +import { + ArrowDownIcon, + ArrowUpIcon, + CaretSortIcon, + EyeNoneIcon, + } from "@radix-ui/react-icons" + import { Column } from "@tanstack/react-table" + + import { cn } from "@/lib/utils" + import { Button } from "@/components/ui/button" + import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, + } from "@/components/ui/dropdown-menu" + + interface DataTableColumnHeaderProps + extends React.HTMLAttributes { + column: Column + title: string + } + + export function DataTableColumnHeader({ + column, + title, + className, + }: DataTableColumnHeaderProps) { + if (!column.getCanSort()) { + return
    {title}
    + } + + return ( +
    + + + + + + column.toggleSorting(false)}> + + Asc + + column.toggleSorting(true)}> + + Desc + + + column.toggleVisibility(false)}> + + Hide + + + +
    + ) + } \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/components/data-table-faceted-filter.tsx b/packages/webapp/src/components/jobs/components/data-table-faceted-filter.tsx new file mode 100644 index 000000000..a5efee277 --- /dev/null +++ b/packages/webapp/src/components/jobs/components/data-table-faceted-filter.tsx @@ -0,0 +1,147 @@ +import * as React from "react" +import { CheckIcon, PlusCircledIcon } from "@radix-ui/react-icons" +import { Column } from "@tanstack/react-table" + +import { cn } from "@/lib/utils" +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandSeparator, +} from "@/components/ui/command" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover" +import { Separator } from "@/components/ui/separator" + +interface DataTableFacetedFilterProps { + column?: Column + title?: string + options: { + label: string + value: string + icon?: React.ComponentType<{ className?: string }> + }[] +} + +export function DataTableFacetedFilter({ + column, + title, + options, +}: DataTableFacetedFilterProps) { + const facets = column?.getFacetedUniqueValues() + const selectedValues = new Set(column?.getFilterValue() as string[]) + + return ( + + + + + + + + + No results found. + + {options.map((option) => { + const isSelected = selectedValues.has(option.value) + return ( + { + if (isSelected) { + selectedValues.delete(option.value) + } else { + selectedValues.add(option.value) + } + const filterValues = Array.from(selectedValues) + column?.setFilterValue( + filterValues.length ? filterValues : undefined + ) + }} + > +
    + +
    + {option.icon && ( + + )} + {option.label} + {facets?.get(option.value) && ( + + {facets.get(option.value)} + + )} +
    + ) + })} +
    + {selectedValues.size > 0 && ( + <> + + + column?.setFilterValue(undefined)} + className="justify-center text-center" + > + Clear filters + + + + )} +
    +
    +
    +
    + ) +} \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/components/data-table-pagination.tsx b/packages/webapp/src/components/jobs/components/data-table-pagination.tsx new file mode 100644 index 000000000..b04f3bdd4 --- /dev/null +++ b/packages/webapp/src/components/jobs/components/data-table-pagination.tsx @@ -0,0 +1,97 @@ +import { + ChevronLeftIcon, + ChevronRightIcon, + DoubleArrowLeftIcon, + DoubleArrowRightIcon, + } from "@radix-ui/react-icons" + import { Table } from "@tanstack/react-table" + + import { Button } from "@/components/ui/button" + import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, + } from "@/components/ui/select" + + interface DataTablePaginationProps { + table: Table + } + + export function DataTablePagination({ + table, + }: DataTablePaginationProps) { + return ( +
    +
    + {table.getFilteredSelectedRowModel().rows.length} of{" "} + {table.getFilteredRowModel().rows.length} row(s) selected. +
    +
    +
    +

    Rows per page

    + +
    +
    + Page {table.getState().pagination.pageIndex + 1} of{" "} + {table.getPageCount()} +
    +
    + + + + +
    +
    +
    + ) + } \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/components/data-table-row-actions.tsx b/packages/webapp/src/components/jobs/components/data-table-row-actions.tsx new file mode 100644 index 000000000..07d376c2c --- /dev/null +++ b/packages/webapp/src/components/jobs/components/data-table-row-actions.tsx @@ -0,0 +1,69 @@ +"use client" + +import { DotsHorizontalIcon } from "@radix-ui/react-icons" +import { Row } from "@tanstack/react-table" + +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" + +import { labels } from "../data/data" +import { taskSchema } from "../data/schema" + +interface DataTableRowActionsProps { + row: Row +} + +export function DataTableRowActions({ + row, +}: DataTableRowActionsProps) { + //const task = taskSchema.parse(row.original) + + return ( + + + + + + Edit + Make a copy + Favorite + + + Labels + + {/* + {labels.map((label) => ( + + {label.label} + + ))} + */} + + + + + Delete + ⌘⌫ + + + + ) +} \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/components/data-table-toolbar.tsx b/packages/webapp/src/components/jobs/components/data-table-toolbar.tsx new file mode 100644 index 000000000..915bc39a8 --- /dev/null +++ b/packages/webapp/src/components/jobs/components/data-table-toolbar.tsx @@ -0,0 +1,61 @@ +"use client" + +import { Cross2Icon } from "@radix-ui/react-icons" +import { Table } from "@tanstack/react-table" + +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { DataTableViewOptions } from "./data-table-view-options" + +import { priorities, statuses } from "../data/data" +import { DataTableFacetedFilter } from "./data-table-faceted-filter" + +interface DataTableToolbarProps { + table: Table +} + +export function DataTableToolbar({ + table, +}: DataTableToolbarProps) { + const isFiltered = table.getState().columnFilters.length > 0 + + return ( +
    +
    + + table.getColumn("title")?.setFilterValue(event.target.value) + } + className="h-8 w-[150px] lg:w-[250px]" + /> + {table.getColumn("status") && ( + + )} + {table.getColumn("direction") && ( + + )} + {isFiltered && ( + + )} +
    + +
    + ) +} \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/components/data-table-view-options.tsx b/packages/webapp/src/components/jobs/components/data-table-view-options.tsx new file mode 100644 index 000000000..6d563472f --- /dev/null +++ b/packages/webapp/src/components/jobs/components/data-table-view-options.tsx @@ -0,0 +1,59 @@ +"use client" + +import { DropdownMenuTrigger } from "@radix-ui/react-dropdown-menu" +import { MixerHorizontalIcon } from "@radix-ui/react-icons" +import { Table } from "@tanstack/react-table" + +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuLabel, + DropdownMenuSeparator, +} from "@/components/ui/dropdown-menu" + +interface DataTableViewOptionsProps { + table: Table +} + +export function DataTableViewOptions({ + table, +}: DataTableViewOptionsProps) { + return ( + + + + + + Toggle columns + + {table + .getAllColumns() + .filter( + (column) => + typeof column.accessorFn !== "undefined" && column.getCanHide() + ) + .map((column) => { + return ( + column.toggleVisibility(!!value)} + > + {column.id} + + ) + })} + + + ) +} \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/components/data-table.tsx b/packages/webapp/src/components/jobs/components/data-table.tsx new file mode 100644 index 000000000..c57986200 --- /dev/null +++ b/packages/webapp/src/components/jobs/components/data-table.tsx @@ -0,0 +1,126 @@ +"use client" + +import * as React from "react" +import { + ColumnDef, + ColumnFiltersState, + SortingState, + VisibilityState, + flexRender, + getCoreRowModel, + getFacetedRowModel, + getFacetedUniqueValues, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table" + +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table" + +import { DataTablePagination } from "../components/data-table-pagination" +import { DataTableToolbar } from "../components/data-table-toolbar" + +interface DataTableProps { + columns: ColumnDef[] + data: TData[] +} + +export function DataTable({ + columns, + data, +}: DataTableProps) { + const [rowSelection, setRowSelection] = React.useState({}) + const [columnVisibility, setColumnVisibility] = + React.useState({}) + const [columnFilters, setColumnFilters] = React.useState( + [] + ) + const [sorting, setSorting] = React.useState([]) + + const table = useReactTable({ + data, + columns, + state: { + sorting, + columnVisibility, + rowSelection, + columnFilters, + }, + enableRowSelection: true, + onRowSelectionChange: setRowSelection, + onSortingChange: setSorting, + onColumnFiltersChange: setColumnFilters, + onColumnVisibilityChange: setColumnVisibility, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFacetedRowModel: getFacetedRowModel(), + getFacetedUniqueValues: getFacetedUniqueValues(), + }) + + return ( +
    + +
    + + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + return ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ) + })} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
    +
    + +
    + ) +} \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/components/user-nav.tsx b/packages/webapp/src/components/jobs/components/user-nav.tsx new file mode 100644 index 000000000..088cfc9b3 --- /dev/null +++ b/packages/webapp/src/components/jobs/components/user-nav.tsx @@ -0,0 +1,62 @@ +import { + Avatar, + AvatarFallback, + AvatarImage, + } from "@/components/ui/avatar" + import { Button } from "@/components/ui/button" + import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuTrigger, + } from "@/components/ui/dropdown-menu" + + export function UserNav() { + return ( + + + + + + +
    +

    shadcn

    +

    + m@example.com +

    +
    +
    + + + + Profile + ⇧⌘P + + + Billing + ⌘B + + + Settings + ⌘S + + New Team + + + + Log out + ⇧⌘Q + +
    +
    + ) + } \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/data/data.tsx b/packages/webapp/src/components/jobs/data/data.tsx new file mode 100644 index 000000000..ba3c3d7f4 --- /dev/null +++ b/packages/webapp/src/components/jobs/data/data.tsx @@ -0,0 +1,86 @@ +import { + ArrowDownIcon, + ArrowRightIcon, + ArrowUpIcon, + CheckCircledIcon, + CircleIcon, + CrossCircledIcon, + QuestionMarkCircledIcon, + StopwatchIcon, + } from "@radix-ui/react-icons" + + export const labels = [ + { + value: "/crm/task", + label: "/crm/task", + }, + { + value: "/crm/notes", + label: "/crm/notes", + }, + { + value: "/crm/contact", + label: "/crm/contact", + }, + ] + + export const labels2 = [ + { + value: "GET", + label: "GET", + }, + { + value: "POST", + label: "POST", + }, + { + value: "GET", + label: "GET", + }, + ] + + export const statuses = [ + { + value: "backlog", + label: "Backlog", + icon: QuestionMarkCircledIcon, + }, + { + value: "todo", + label: "Todo", + icon: CircleIcon, + }, + { + value: "in progress", + label: "In Progress", + icon: StopwatchIcon, + }, + { + value: "done", + label: "Done", + icon: CheckCircledIcon, + }, + { + value: "canceled", + label: "Canceled", + icon: CrossCircledIcon, + }, + ] + + export const priorities = [ + { + label: "Low", + value: "low", + icon: ArrowDownIcon, + }, + { + label: "Medium", + value: "medium", + icon: ArrowRightIcon, + }, + { + label: "High", + value: "high", + icon: ArrowUpIcon, + }, + ] \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/data/schema.ts b/packages/webapp/src/components/jobs/data/schema.ts new file mode 100644 index 000000000..855a9aca0 --- /dev/null +++ b/packages/webapp/src/components/jobs/data/schema.ts @@ -0,0 +1,15 @@ +import { z } from "zod" + +// We're keeping a simple non-relational schema here. +// IRL, you will have a schema for your data models. +export const taskSchema = z.object({ + method: z.string(), + url: z.string(), + status: z.string(), + direction: z.string(), + integration: z.string(), + organisation: z.string(), + date: z.string() +}) + +export type Task = z.infer \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/data/seed.ts b/packages/webapp/src/components/jobs/data/seed.ts new file mode 100644 index 000000000..b35a5ef17 --- /dev/null +++ b/packages/webapp/src/components/jobs/data/seed.ts @@ -0,0 +1,20 @@ +import fs from "fs" +import path from "path" +import { faker } from "@faker-js/faker" + +import { labels, priorities, statuses } from "./data" + +const tasks = Array.from({ length: 100 }, () => ({ + id: `TASK-${faker.number.int({ min: 1000, max: 9999 })}`, + title: faker.hacker.phrase().replace(/^./, (letter) => letter.toUpperCase()), + status: faker.helpers.arrayElement(statuses).value, + label: faker.helpers.arrayElement(labels).value, + direction: faker.helpers.arrayElement(priorities).value, +})) + +fs.writeFileSync( + path.join(__dirname, "tasks.json"), + JSON.stringify(tasks, null, 2) +) + +console.log("✅ Tasks data generated.") \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/data/task.ts b/packages/webapp/src/components/jobs/data/task.ts new file mode 100644 index 000000000..f80d686e4 --- /dev/null +++ b/packages/webapp/src/components/jobs/data/task.ts @@ -0,0 +1,120 @@ +export const TASKS = [ + { + "method": "GET", + "integration": "You can't compress the program without quantifying the open-source SSD pixel!", + "status": "in progress", + "url": "/crm/contact", + "direction": "medium", + "date": "", + "organisation": "", + + }, + { + "method": "GET", + "integration": "Try to calculate the EXE feed, maybe it will index the multi-byte pixel!", + "status": "backlog", + "url": "/crm/contact", + "direction": "medium", + "date": "", + "organisation": "", + }, + { + "method": "GET", + "integration": "We need to bypass the neural TCP card!", + "status": "todo", + "url": "/crm/task", + "direction": "high", + "date": "", + "organisation": "", + }, + { + "method": "GET", + "integration": "The SAS interface is down, bypass the open-source pixel so we can back up the PNG bandwmethodth!", + "status": "backlog", + "url": "/crm/notes", + "direction": "medium", + "date": "", + "organisation": "", + }, + { + "method": "GET", + "integration": "I'll parse the wireless SSL protocol, that should driver the API panel!", + "status": "canceled", + "url": "/crm/notes", + "direction": "medium", + "date": "", + "organisation": "", + }, + { + "method": "POST", + "integration": "Use the digital TLS panel, then you can transmit the haptic system!", + "status": "done", + "url": "/crm/task", + "direction": "high", + "date": "", + "organisation": "", + }, + { + "method": "POST", + "integration": "The UTF8 application is down, parse the neural bandwmethodth so we can back up the PNG firewall!", + "status": "done", + "url": "/crm/notes", + "direction": "high", + "date": "", + "organisation": "", + }, + { + "method": "GET", + "integration": "Generating the driver won't do anything, we need to quantify the 1080p SMTP bandwmethodth!", + "status": "in progress", + "url": "/crm/notes", + "direction": "medium", + "date": "", + "organisation": "", + }, + { + "method": "GET", + "integration": "We need to program the back-end THX pixel!", + "status": "todo", + "url": "/crm/notes", + "direction": "low", + "date": "", + "organisation": "", + }, + { + "method": "POST", + "integration": "Calculating the bus won't do anything, we need to navigate the back-end JSON protocol!", + "status": "in progress", + "url": "/crm/contact", + "direction": "high", + "date": "", + "organisation": "", + }, + { + "method": "POST", + "integration": "Generating the driver won't do anything, we need to index the online SSL application!", + "status": "done", + "url": "/crm/contact", + "direction": "medium", + "date": "", + "organisation": "", + }, + { + "method": "GET", + "integration": "I'll transmit the wireless JBOD capacitor, that should hard drive the SSD feed!", + "status": "backlog", + "url": "/crm/contact", + "direction": "medium", + "date": "", + "organisation": "", + }, + { + "method": "POST", + "integration": "We need to overrmethode the online UDP bus!", + "status": "backlog", + "url": "/crm/task", + "direction": "medium", + "date": "", + "organisation": "", + }, +] \ No newline at end of file diff --git a/packages/webapp/src/components/jobs/index.tsx b/packages/webapp/src/components/jobs/index.tsx new file mode 100644 index 000000000..0f74e1b96 --- /dev/null +++ b/packages/webapp/src/components/jobs/index.tsx @@ -0,0 +1,14 @@ +import TaskPage from "./Task"; + +export default function JobsPage() { + return ( +
    +
    +
    +

    Jobs

    +
    + +
    +
    + ); + } \ No newline at end of file diff --git a/packages/webapp/src/components/main-component/index.tsx b/packages/webapp/src/components/main-component/index.tsx new file mode 100644 index 000000000..1b2330333 --- /dev/null +++ b/packages/webapp/src/components/main-component/index.tsx @@ -0,0 +1,94 @@ +import { Line, LineChart, ResponsiveContainer} from "recharts"; +import { Overview } from "../dashboard/components/overview"; +import { Button } from "../ui/button"; +import { CalendarDateRangePicker } from "./../dashboard/components/date-range-picker" +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card" +import { + Tabs, + TabsContent, +} from "@/components/ui/tabs" +export default function MainPage() { + + const data = [ + { name: 'Jan', revenue: 15000 }, + { name: 'Feb', revenue: 21000 }, + { name: 'Mar', revenue: 18000 }, + { name: 'Apr', revenue: 25000 }, + { name: 'May', revenue: 27000 }, + ]; + + return ( +
    + {/*

    Dashboard

    +
    + + +
    */ + } +
    +
    +

    Dashboard

    +
    + + +
    +
    + + +
    + + + Total API Requests + + + + + +
    + + + Total Connections + + +37 from last month + + + + + + + + + + + + + + Linked Accounts + + +78% from last month + + + + + + + + + + +
    + +
    +
    +
    +
    + +
    + ); + } diff --git a/packages/webapp/src/components/quickstart/index.tsx b/packages/webapp/src/components/quickstart/index.tsx new file mode 100644 index 000000000..30591db44 --- /dev/null +++ b/packages/webapp/src/components/quickstart/index.tsx @@ -0,0 +1,12 @@ +export default function QuickStartPage() { + return ( +
    +
    +
    +

    Quickstart

    +
    + +
    +
    + ); + } \ No newline at end of file diff --git a/packages/webapp/src/components/ui/badge.tsx b/packages/webapp/src/components/ui/badge.tsx new file mode 100644 index 000000000..e87d62bf1 --- /dev/null +++ b/packages/webapp/src/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
    + ) +} + +export { Badge, badgeVariants } diff --git a/packages/webapp/src/components/ui/checkbox.tsx b/packages/webapp/src/components/ui/checkbox.tsx new file mode 100644 index 000000000..f8315322d --- /dev/null +++ b/packages/webapp/src/components/ui/checkbox.tsx @@ -0,0 +1,28 @@ +import * as React from "react" +import * as CheckboxPrimitive from "@radix-ui/react-checkbox" +import { CheckIcon } from "@radix-ui/react-icons" + +import { cn } from "@/lib/utils" + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)) +Checkbox.displayName = CheckboxPrimitive.Root.displayName + +export { Checkbox } diff --git a/packages/webapp/src/components/ui/navigation-menu.tsx b/packages/webapp/src/components/ui/navigation-menu.tsx new file mode 100644 index 000000000..5841fb398 --- /dev/null +++ b/packages/webapp/src/components/ui/navigation-menu.tsx @@ -0,0 +1,128 @@ +import * as React from "react" +import { ChevronDownIcon } from "@radix-ui/react-icons" +import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu" +import { cva } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const NavigationMenu = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children} + + +)) +NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName + +const NavigationMenuList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName + +const NavigationMenuItem = NavigationMenuPrimitive.Item + +const navigationMenuTriggerStyle = cva( + "group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50" +) + +const NavigationMenuTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + {children}{" "} + +)) +NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName + +const NavigationMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName + +const NavigationMenuLink = NavigationMenuPrimitive.Link + +const NavigationMenuViewport = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
    + +
    +)) +NavigationMenuViewport.displayName = + NavigationMenuPrimitive.Viewport.displayName + +const NavigationMenuIndicator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +
    + +)) +NavigationMenuIndicator.displayName = + NavigationMenuPrimitive.Indicator.displayName + +export { + navigationMenuTriggerStyle, + NavigationMenu, + NavigationMenuList, + NavigationMenuItem, + NavigationMenuContent, + NavigationMenuTrigger, + NavigationMenuLink, + NavigationMenuIndicator, + NavigationMenuViewport, +} diff --git a/packages/webapp/src/components/ui/separator.tsx b/packages/webapp/src/components/ui/separator.tsx new file mode 100644 index 000000000..6d7f12265 --- /dev/null +++ b/packages/webapp/src/components/ui/separator.tsx @@ -0,0 +1,29 @@ +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" + +import { cn } from "@/lib/utils" + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref + ) => ( + + ) +) +Separator.displayName = SeparatorPrimitive.Root.displayName + +export { Separator } diff --git a/packages/webapp/src/components/ui/table.tsx b/packages/webapp/src/components/ui/table.tsx new file mode 100644 index 000000000..c0df655c0 --- /dev/null +++ b/packages/webapp/src/components/ui/table.tsx @@ -0,0 +1,120 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    + + +)) +Table.displayName = "Table" + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableHeader.displayName = "TableHeader" + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableBody.displayName = "TableBody" + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0", + className + )} + {...props} + /> +)) +TableFooter.displayName = "TableFooter" + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
    [role=checkbox]]:translate-y-[2px]", + className + )} + {...props} + /> +)) +TableHead.displayName = "TableHead" + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + [role=checkbox]]:translate-y-[2px]", + className + )} + {...props} + /> +)) +TableCell.displayName = "TableCell" + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
    +)) +TableCaption.displayName = "TableCaption" + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +} diff --git a/packages/webapp/src/components/ui/tooltip.tsx b/packages/webapp/src/components/ui/tooltip.tsx new file mode 100644 index 000000000..a9c71baa2 --- /dev/null +++ b/packages/webapp/src/components/ui/tooltip.tsx @@ -0,0 +1,28 @@ +import * as React from "react" +import * as TooltipPrimitive from "@radix-ui/react-tooltip" + +import { cn } from "@/lib/utils" + +const TooltipProvider = TooltipPrimitive.Provider + +const Tooltip = TooltipPrimitive.Root + +const TooltipTrigger = TooltipPrimitive.Trigger + +const TooltipContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + +)) +TooltipContent.displayName = TooltipPrimitive.Content.displayName + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ca308b0d8..3379dc5cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -199,6 +199,9 @@ importers: '@types/react-dom': specifier: ^18.2.7 version: 18.2.7 + '@types/uuid': + specifier: ^9.0.7 + version: 9.0.7 '@typescript-eslint/eslint-plugin': specifier: ^6.0.0 version: 6.9.1(@typescript-eslint/parser@6.9.1)(eslint@8.52.0)(typescript@5.1.3) @@ -257,9 +260,18 @@ importers: packages/webapp: dependencies: + '@ant-design/icons': + specifier: ^5.2.6 + version: 5.2.6(react-dom@18.2.0)(react@18.2.0) + '@faker-js/faker': + specifier: ^8.3.1 + version: 8.3.1 '@radix-ui/react-avatar': specifier: ^1.0.4 version: 1.0.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-checkbox': + specifier: ^1.0.4 + version: 1.0.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-dialog': specifier: ^1.0.5 version: 1.0.5(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) @@ -272,18 +284,33 @@ importers: '@radix-ui/react-label': specifier: ^2.0.2 version: 2.0.2(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-navigation-menu': + specifier: ^1.1.4 + version: 1.1.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-popover': specifier: ^1.0.7 version: 1.0.7(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-select': specifier: ^2.0.0 version: 2.0.0(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-separator': + specifier: ^1.0.3 + version: 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-slot': specifier: ^1.0.2 version: 1.0.2(@types/react@18.2.37)(react@18.2.0) '@radix-ui/react-tabs': specifier: ^1.0.4 version: 1.0.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-tooltip': + specifier: ^1.0.7 + version: 1.0.7(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@tanstack/react-table': + specifier: ^8.10.7 + version: 8.10.7(react-dom@18.2.0)(react@18.2.0) + antd: + specifier: ^5.11.5 + version: 5.11.5(date-fns@2.30.0)(react-dom@18.2.0)(react@18.2.0) class-variance-authority: specifier: ^0.7.0 version: 0.7.0 @@ -308,6 +335,12 @@ importers: react-dom: specifier: ^18.2.0 version: 18.2.0(react@18.2.0) + react-dropzone: + specifier: ^14.2.3 + version: 14.2.3(react@18.2.0) + react-router-dom: + specifier: ^6.20.0 + version: 6.20.0(react-dom@18.2.0)(react@18.2.0) recharts: specifier: ^2.10.1 version: 2.10.1(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0) @@ -607,6 +640,62 @@ packages: - chokidar dev: true + /@ant-design/colors@7.0.0: + resolution: {integrity: sha512-iVm/9PfGCbC0dSMBrz7oiEXZaaGH7ceU40OJEfKmyuzR9R5CRimJYPlRiFtMQGQcbNMea/ePcoIebi4ASGYXtg==} + dependencies: + '@ctrl/tinycolor': 3.6.1 + dev: false + + /@ant-design/cssinjs@1.17.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Ed2rruHMxZTVYGPec6QBZkrh00Df5K1FAufmBpONai5iGYxoxIkg1sRD8YdCw0NvPRAa4r1nJP5LbwICGHzGiQ==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.23.2 + '@emotion/hash': 0.8.0 + '@emotion/unitless': 0.7.5 + classnames: 2.3.2 + csstype: 3.1.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + stylis: 4.3.0 + dev: false + + /@ant-design/icons-svg@4.3.1: + resolution: {integrity: sha512-4QBZg8ccyC6LPIRii7A0bZUk3+lEDCLnhB+FVsflGdcWPPmV+j3fire4AwwoqHV/BibgvBmR9ZIo4s867smv+g==} + dev: false + + /@ant-design/icons@5.2.6(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-4wn0WShF43TrggskBJPRqCD0fcHbzTYjnaoskdiJrVHg86yxoZ8ZUqsXvyn4WUqehRiFKnaclOhqk9w4Ui2KVw==} + engines: {node: '>=8'} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@ant-design/colors': 7.0.0 + '@ant-design/icons-svg': 4.3.1 + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@ant-design/react-slick@1.0.2(react@18.2.0): + resolution: {integrity: sha512-Wj8onxL/T8KQLFFiCA4t8eIRGpRR+UPgOdac2sYzonv+i0n3kXHmvHLLiOYL655DQx2Umii9Y9nNgL7ssu5haQ==} + peerDependencies: + react: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + json2mq: 0.2.0 + react: 18.2.0 + resize-observer-polyfill: 1.5.1 + throttle-debounce: 5.0.0 + dev: false + /@babel/code-frame@7.22.13: resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} engines: {node: '>=6.9.0'} @@ -3318,6 +3407,11 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true + /@ctrl/tinycolor@3.6.1: + resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} + engines: {node: '>=10'} + dev: false + /@discoveryjs/json-ext@0.5.7: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} @@ -4106,6 +4200,10 @@ packages: - webpack-cli dev: false + /@emotion/hash@0.8.0: + resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} + dev: false + /@emotion/is-prop-valid@1.2.1: resolution: {integrity: sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==} dependencies: @@ -4585,6 +4683,11 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@faker-js/faker@8.3.1: + resolution: {integrity: sha512-FdgpFxY6V6rLZE9mmIBb9hM0xpfvQOSNOLnzolzKwsE1DH+gC7lEKV1p1IbR0lAYyvYd5a4u3qWJzowUkw1bIw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0, npm: '>=6.14.13'} + dev: false + /@floating-ui/core@1.5.0: resolution: {integrity: sha512-kK1h4m36DQ0UHGj5Ah4db7R0rHemTqqO0QLvUqi1/mUUp3LuAWbWxdxSIf/XsnH9VS6rRVPLJCncjRzUvyCLXg==} dependencies: @@ -5499,6 +5602,34 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-checkbox@1.0.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.2 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@types/react': 18.2.37 + '@types/react-dom': 18.2.15 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} peerDependencies: @@ -5864,6 +5995,40 @@ packages: react-remove-scroll: 2.5.5(@types/react@18.2.37)(react@18.2.0) dev: false + /@radix-ui/react-navigation-menu@1.1.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Cc+seCS3PmWmjI51ufGG7zp1cAAIRqHVw7C9LOA2TZ+R4hG6rDvHcTqIsEEFLmZO3zNVH72jOOE7kKNy8W+RtA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.2 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-collection': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-direction': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-callback-ref': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.37 + '@types/react-dom': 18.2.15 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-popover@1.0.7(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==} peerDependencies: @@ -6100,6 +6265,27 @@ packages: react-remove-scroll: 2.5.5(@types/react@18.2.37)(react@18.2.0) dev: false + /@radix-ui/react-separator@1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.2 + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.37 + '@types/react-dom': 18.2.15 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-slot@1.0.0(react@18.2.0): resolution: {integrity: sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==} peerDependencies: @@ -6153,6 +6339,38 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-tooltip@1.0.7(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@babel/runtime': 7.23.2 + '@radix-ui/primitive': 1.0.1 + '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-context': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-dismissable-layer': 1.0.5(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-id': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-popper': 1.1.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-portal': 1.0.4(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.0.2(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.37)(react@18.2.0) + '@radix-ui/react-visually-hidden': 1.0.3(@types/react-dom@18.2.15)(@types/react@18.2.37)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.37 + '@types/react-dom': 18.2.15 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-use-callback-ref@1.0.0(react@18.2.0): resolution: {integrity: sha512-GZtyzoHz95Rhs6S63D2t/eqvdFCm7I+yHMLVQheKM7nBD8mbZIt+ct1jz4536MDnaOGKIxynJ8eHTkVGVVkoTg==} peerDependencies: @@ -6320,6 +6538,105 @@ packages: '@babel/runtime': 7.23.2 dev: false + /@rc-component/color-picker@1.4.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-vh5EWqnsayZa/JwUznqDaPJz39jznx/YDbyBuVJntv735tKXKwEUZZb2jYEldOg+NKWZwtALjGMrNeGBmqFoEw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + '@ctrl/tinycolor': 3.6.1 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@rc-component/context@1.4.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@rc-component/mini-decimal@1.1.0: + resolution: {integrity: sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==} + engines: {node: '>=8.x'} + dependencies: + '@babel/runtime': 7.23.2 + dev: false + + /@rc-component/mutate-observer@1.1.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@rc-component/portal@1.1.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@rc-component/tour@1.10.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-voV0BKaTJbewB9LLgAHQ7tAGG7rgDkKQkZo82xw2gIk542hY+o7zwoqdN16oHhIKk7eG/xi+mdXrONT62Dt57A==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@rc-component/trigger@1.18.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-jRLYgFgjLEPq3MvS87fIhcfuywFSRDaDrYw1FLku7Cm4esszvzTbA0JBsyacAyLrK9rF3TiHFcvoEDMzoD3CTA==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@remix-run/router@1.13.0: + resolution: {integrity: sha512-5dMOnVnefRsl4uRnAdoWjtVTdh8e6aZqgM4puy9nmEADH72ck+uXwzpJLEKE9Q6F8ZljNewLgmTfkxUrBdv4WA==} + engines: {node: '>=14.0.0'} + dev: false + /@rollup/rollup-android-arm-eabi@4.6.0: resolution: {integrity: sha512-keHkkWAe7OtdALGoutLY3utvthkGF+Y17ws9LYT8pxMBYXaCoH/8dXS2uzo6e8+sEhY7y/zi5RFo22Dy2lFpDw==} cpu: [arm] @@ -6694,6 +7011,23 @@ packages: defer-to-connect: 1.1.3 dev: false + /@tanstack/react-table@8.10.7(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-bXhjA7xsTcsW8JPTTYlUg/FuBpn8MNjiEPhkNhIGCUR6iRQM2+WEco4OBpvDeVcR9SE+bmWLzdfiY7bCbCSVuA==} + engines: {node: '>=12'} + peerDependencies: + react: '>=16' + react-dom: '>=16' + dependencies: + '@tanstack/table-core': 8.10.7 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /@tanstack/table-core@8.10.7: + resolution: {integrity: sha512-KQk5OMg5OH6rmbHZxuNROvdI+hKDIUxANaHlV+dPlNN7ED3qYQ/WkpY2qlXww1SIdeMlkIhpN/2L00rof0fXFw==} + engines: {node: '>=12'} + dev: false + /@trysound/sax@0.2.0: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -7117,6 +7451,10 @@ packages: resolution: {integrity: sha512-zC0iXxAv1C1ERURduJueYzkzZ2zaGyc+P2c95hgkikHPr3z8EdUZOlgEQ5X0DRmwDZn+hekycQnoeiiRVrmilQ==} dev: false + /@types/uuid@9.0.7: + resolution: {integrity: sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==} + dev: true + /@types/validator@10.11.3: resolution: {integrity: sha512-GKF2VnEkMmEeEGvoo03ocrP9ySMuX1ypKazIYMlsjfslfBMhOAtC5dmEWKdJioW4lJN7MZRS88kalTsVClyQ9w==} @@ -8090,6 +8428,68 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + /antd@5.11.5(date-fns@2.30.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-qB1YmvO4Zm4r48M0Ptxn7orpaXeMPSeTrrw6dAgtTYN+ysnWD/D/zlxFc5g73GywIzZ10XGqvNC+74A+HD0yeQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@ant-design/colors': 7.0.0 + '@ant-design/cssinjs': 1.17.5(react-dom@18.2.0)(react@18.2.0) + '@ant-design/icons': 5.2.6(react-dom@18.2.0)(react@18.2.0) + '@ant-design/react-slick': 1.0.2(react@18.2.0) + '@babel/runtime': 7.23.2 + '@ctrl/tinycolor': 3.6.1 + '@rc-component/color-picker': 1.4.1(react-dom@18.2.0)(react@18.2.0) + '@rc-component/mutate-observer': 1.1.0(react-dom@18.2.0)(react@18.2.0) + '@rc-component/tour': 1.10.0(react-dom@18.2.0)(react@18.2.0) + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + copy-to-clipboard: 3.3.3 + dayjs: 1.11.10 + qrcode.react: 3.1.0(react@18.2.0) + rc-cascader: 3.20.0(react-dom@18.2.0)(react@18.2.0) + rc-checkbox: 3.1.0(react-dom@18.2.0)(react@18.2.0) + rc-collapse: 3.7.2(react-dom@18.2.0)(react@18.2.0) + rc-dialog: 9.3.4(react-dom@18.2.0)(react@18.2.0) + rc-drawer: 6.5.2(react-dom@18.2.0)(react@18.2.0) + rc-dropdown: 4.1.0(react-dom@18.2.0)(react@18.2.0) + rc-field-form: 1.40.0(react-dom@18.2.0)(react@18.2.0) + rc-image: 7.5.1(react-dom@18.2.0)(react@18.2.0) + rc-input: 1.3.6(react-dom@18.2.0)(react@18.2.0) + rc-input-number: 8.4.0(react-dom@18.2.0)(react@18.2.0) + rc-mentions: 2.9.1(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.12.2(react-dom@18.2.0)(react@18.2.0) + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-notification: 5.3.0(react-dom@18.2.0)(react@18.2.0) + rc-pagination: 3.7.0(react-dom@18.2.0)(react@18.2.0) + rc-picker: 3.14.6(date-fns@2.30.0)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0) + rc-progress: 3.5.1(react-dom@18.2.0)(react@18.2.0) + rc-rate: 2.12.0(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) + rc-segmented: 2.2.2(react-dom@18.2.0)(react@18.2.0) + rc-select: 14.10.0(react-dom@18.2.0)(react@18.2.0) + rc-slider: 10.4.0(react-dom@18.2.0)(react@18.2.0) + rc-steps: 6.0.1(react-dom@18.2.0)(react@18.2.0) + rc-switch: 4.1.0(react-dom@18.2.0)(react@18.2.0) + rc-table: 7.36.0(react-dom@18.2.0)(react@18.2.0) + rc-tabs: 12.13.1(react-dom@18.2.0)(react@18.2.0) + rc-textarea: 1.5.3(react-dom@18.2.0)(react@18.2.0) + rc-tooltip: 6.1.2(react-dom@18.2.0)(react@18.2.0) + rc-tree: 5.8.2(react-dom@18.2.0)(react@18.2.0) + rc-tree-select: 5.15.0(react-dom@18.2.0)(react@18.2.0) + rc-upload: 4.3.5(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + scroll-into-view-if-needed: 3.1.0 + throttle-debounce: 5.0.0 + transitivePeerDependencies: + - date-fns + - luxon + - moment + dev: false + /any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -8165,6 +8565,10 @@ packages: resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} dev: true + /array-tree-filter@2.1.0: + resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} + dev: false + /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -8218,6 +8622,10 @@ packages: /asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + /async-validator@4.2.5: + resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} + dev: false + /asynciterator.prototype@1.0.0: resolution: {integrity: sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==} dependencies: @@ -8237,6 +8645,11 @@ packages: engines: {node: '>=8.0.0'} dev: false + /attr-accept@2.2.2: + resolution: {integrity: sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==} + engines: {node: '>=4'} + dev: false + /autoprefixer@10.4.16(postcss@8.4.31): resolution: {integrity: sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==} engines: {node: ^10 || ^12 || >=14} @@ -8891,6 +9304,10 @@ packages: clsx: 2.0.0 dev: false + /classnames@2.3.2: + resolution: {integrity: sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==} + dev: false + /clean-css@5.3.2: resolution: {integrity: sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==} engines: {node: '>= 10.0'} @@ -9139,6 +9556,10 @@ packages: - supports-color dev: false + /compute-scroll-into-view@3.1.0: + resolution: {integrity: sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==} + dev: false + /concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -9213,6 +9634,12 @@ packages: engines: {node: '>=12'} dev: false + /copy-to-clipboard@3.3.3: + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + dependencies: + toggle-selection: 1.0.6 + dev: false + /copy-webpack-plugin@11.0.0(webpack@5.89.0): resolution: {integrity: sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==} engines: {node: '>= 14.15.0'} @@ -9655,6 +10082,10 @@ packages: resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} dev: false + /dayjs@1.11.10: + resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} + dev: false + /debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -10762,6 +11193,13 @@ packages: webpack: 5.89.0 dev: false + /file-selector@0.6.0: + resolution: {integrity: sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==} + engines: {node: '>= 12'} + dependencies: + tslib: 2.6.2 + dev: false + /filesize@8.0.7: resolution: {integrity: sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==} engines: {node: '>= 0.4.0'} @@ -12696,6 +13134,12 @@ packages: /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + /json2mq@0.2.0: + resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} + dependencies: + string-convert: 0.2.1 + dev: false + /json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -14630,6 +15074,14 @@ packages: resolution: {integrity: sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==} dev: true + /qrcode.react@3.1.0(react@18.2.0): + resolution: {integrity: sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + react: 18.2.0 + dev: false + /qs@6.11.0: resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} engines: {node: '>=0.6'} @@ -14693,14 +15145,525 @@ packages: iconv-lite: 0.4.24 unpipe: 1.0.0 - /rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true + /rc-cascader@3.20.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-lkT9EEwOcYdjZ/jvhLoXGzprK1sijT3/Tp4BLxQQcHDZkkOzzwYQC9HgmKoJz0K7CukMfgvO9KqHeBdgE+pELw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 + '@babel/runtime': 7.23.2 + array-tree-filter: 2.1.0 + classnames: 2.3.2 + rc-select: 14.10.0(react-dom@18.2.0)(react@18.2.0) + rc-tree: 5.8.2(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-checkbox@3.1.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-PAwpJFnBa3Ei+5pyqMMXdcKYKNBMS+TvSDiLdDnARnMJHC8ESxwPfm4Ao1gJiKtWLdmGfigascnCpwrHFgoOBQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-collapse@3.7.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ZRw6ipDyOnfLFySxAiCMdbHtb5ePAsB9mT17PA6y1mRD/W6KHRaZeb5qK/X9xDV1CqgyxMpzw0VdS74PCcUk4A==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-dialog@9.3.4(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-975X3018GhR+EjZFbxA2Z57SX5rnu0G0/OxFgMMvZK4/hQWEm3MHaNvP4wXpxYDoJsp+xUvVW+GB9CMMCm81jA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-drawer@6.5.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-QckxAnQNdhh4vtmKN0ZwDf3iakO83W9eZcSKWYYTDv4qcD2fHhRAZJJ/OE6v2ZlQ2kSqCJX5gYssF4HJFvsEPQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-dropdown@4.1.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-VZjMunpBdlVzYpEdJSaV7WM7O0jf8uyDjirxXLZRNZ+tAC+NzD3PXPEtliFwGzVwBBdCmGuSqiS9DWcOLxQ9tw==} + peerDependencies: + react: '>=16.11.0' + react-dom: '>=16.11.0' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-field-form@1.40.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-OM3N01X2BYFGJDJcwpk9/BBtlwgveE7eh2SQAKIxVCt9KVWlODYJ9ypTHQdxchfDbeJKJKxMBFXlLAmyvlgPHg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + async-validator: 4.2.5 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-image@7.5.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Z9loECh92SQp0nSipc0MBuf5+yVC05H/pzC+Nf8xw1BKDFUJzUeehYBjaWlxly8VGBZJcTHYri61Fz9ng1G3Ag==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/portal': 1.1.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-dialog: 9.3.4(react-dom@18.2.0)(react@18.2.0) + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-input-number@8.4.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-B6rziPOLRmeP7kcS5qbdC5hXvvDHYKV4vUxmahevYx2E6crS2bRi0xLDjhJ0E1HtOWo8rTmaE2EBJAkTCZOLdA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/mini-decimal': 1.1.0 + classnames: 2.3.2 + rc-input: 1.3.6(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-input@1.3.6(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-/HjTaKi8/Ts4zNbYaB5oWCquxFyFQO4Co1MnMgoCeGJlpe7k8Eir2HN0a0F9IHDmmo+GYiGgPpz7w/d/krzsJA==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-mentions@2.9.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cZuElWr/5Ws0PXx1uxobxfYh4mqUw2FitfabR62YnWgm+WAfDyXZXqZg5DxXW+M1cgVvntrQgDDd9LrihrXzew==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-input: 1.3.6(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.12.2(react-dom@18.2.0)(react@18.2.0) + rc-textarea: 1.5.3(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-menu@9.12.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-NzloFH2pRUYmQ3S/YbJAvRkgCZaLvq0sRa5rgJtuIHLfPPprNHNyepeSlT64+dbVqI4qRWL44VN0lUCldCbbfg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-overflow: 1.3.2(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-motion@2.9.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-XIU2+xLkdIr1/h6ohPZXyPBMvOmuyFZQ/T0xnawz+Rh+gh4FINcnZmMT5UTIj6hgI0VLDjTaPeRd+smJeSPqiQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-notification@5.3.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-WCf0uCOkZ3HGfF0p1H4Sgt7aWfipxORWTPp7o6prA3vxwtWhtug3GfpYls1pnBp4WA+j8vGIi5c2/hQRpGzPcQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-overflow@1.3.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-pagination@3.7.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-IxSzKapd13L91/195o1TPkKnCNw8gIR25UP1GCW/7c7n/slhld4npu2j2PB9IWjXm4SssaAaSAt2lscYog7wzg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-picker@3.14.6(date-fns@2.30.0)(dayjs@1.11.10)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-AdKKW0AqMwZsKvIpwUWDUnpuGKZVrbxVTZTNjcO+pViGkjC1EBcjMgxVe8tomOEaIHJL5Gd13vS8Rr3zzxWmag==} + engines: {node: '>=8.x'} + peerDependencies: + date-fns: '>= 2.x' + dayjs: '>= 1.x' + luxon: '>= 3.x' + moment: '>= 2.x' + react: '>=16.9.0' + react-dom: '>=16.9.0' + peerDependenciesMeta: + date-fns: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + date-fns: 2.30.0 + dayjs: 1.11.10 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-progress@3.5.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-V6Amx6SbLRwPin/oD+k1vbPrO8+9Qf8zW1T8A7o83HdNafEVvAxPV5YsgtKFP+Ud5HghLj33zKOcEHrcrUGkfw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-rate@2.12.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-g092v5iZCdVzbjdn28FzvWebK2IutoVoiTeqoLTj9WM7SjA/gOJIw5/JFZMRyJYYVe1jLAU2UhAfstIpCNRozg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-resize-observer@1.4.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + resize-observer-polyfill: 1.5.1 + dev: false + + /rc-segmented@2.2.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Mq52M96QdHMsNdE/042ibT5vkcGcD5jxKp7HgPC2SRofpia99P5fkfHy1pEaajLMF/kj0+2Lkq1UZRvqzo9mSA==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-select@14.10.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-TsIJTYafTTapCA32LLNpx/AD6ntepR1TG8jEVx35NiAAWCPymhUfuca8kRcUNd3WIGVMDcMKn9kkphoxEz+6Ag==} + engines: {node: '>=8.x'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-overflow: 1.3.2(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + rc-virtual-list: 3.11.3(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-slider@10.4.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ZlpWjFhOlEf0w4Ng31avFBkXNNBj60NAcTPaIoiCxBkJ29wOtHSPMqv9PZeEoqmx64bpJkgK7kPa47HG4LPzww==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-steps@6.0.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-switch@4.1.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-table@7.36.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-3xVcdCC5OLeOOhaCg+5Lps2oPreM/GWXmUXWTSX4p6vF7F76ABM4dfPpMJ9Dnf5yGRyh+8pe7FRyhRVnWw2H/w==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/context': 1.4.0(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + rc-virtual-list: 3.11.3(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-tabs@12.13.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-83u3l2QkO0UznCzdBLEk9WnNcT+imtmDmMT993sUUEOGnNQAmqOdev0XjeqrcvsAMe9CDpAWDFd7L/RZw+LVJQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-dropdown: 4.1.0(react-dom@18.2.0)(react@18.2.0) + rc-menu: 9.12.2(react-dom@18.2.0)(react@18.2.0) + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-textarea@1.5.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-oH682ghHx++stFNYrosPRBfwsypywrTXpaD0/5Z8MPkUOnyOQUaY9ueL9tMu6BP1LfsuYQ1VLpg5OtshViLNgA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-input: 1.3.6(react-dom@18.2.0)(react@18.2.0) + rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-tooltip@6.1.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-89zwvybvCxGJu3+gGF8w5AXd4HHk6hIN7K0vZbkzjilVaEAIWPqc1fcyeUeP71n3VCcw7pTL9LyFupFbrx8gHw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + '@rc-component/trigger': 1.18.2(react-dom@18.2.0)(react@18.2.0) + classnames: 2.3.2 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-tree-select@5.15.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-YJHfdO6azFnR0/JuNBZLDptGE4/RGfVeHAafUIYcm2T3RBkL1O8aVqiHvwIyLzdK59ry0NLrByd+3TkfpRM+9Q==} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-select: 14.10.0(react-dom@18.2.0)(react@18.2.0) + rc-tree: 5.8.2(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-tree@5.8.2(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-xH/fcgLHWTLmrSuNphU8XAqV7CdaOQgm4KywlLGNoTMhDAcNR3GVNP6cZzb0GrKmIZ9yae+QLot/cAgUdPRMzg==} + engines: {node: '>=10.x'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-motion: 2.9.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + rc-virtual-list: 3.11.3(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-upload@4.3.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-EHlKJbhkgFSQHliTj9v/2K5aEuFwfUQgZARzD7AmAPOneZEPiCNF3n6PEWIuqz9h7oq6FuXgdR67sC5BWFxJbA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc-util@5.38.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-e4ZMs7q9XqwTuhIK7zBIVFltUtMSjphuPPQXHoHlzRzNdOwUxDejo0Zls5HYaJfRKNURcsS/ceKVULlhjBrxng==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + dependencies: + '@babel/runtime': 7.23.2 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-is: 18.2.0 + dev: false + + /rc-virtual-list@3.11.3(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-tu5UtrMk/AXonHwHxUogdXAWynaXsrx1i6dsgg+lOo/KJSF8oBAcprh1z5J3xgnPJD5hXxTL58F8s8onokdt0Q==} + engines: {node: '>=8.x'} + peerDependencies: + react: '*' + react-dom: '*' + dependencies: + '@babel/runtime': 7.23.2 + classnames: 2.3.2 + rc-resize-observer: 1.4.0(react-dom@18.2.0)(react@18.2.0) + rc-util: 5.38.1(react-dom@18.2.0)(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 dev: false /react-base16-styling@0.6.0: @@ -14784,6 +15747,18 @@ packages: scheduler: 0.23.0 dev: false + /react-dropzone@14.2.3(react@18.2.0): + resolution: {integrity: sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug==} + engines: {node: '>= 10.13'} + peerDependencies: + react: '>= 16.8 || 18.0.0' + dependencies: + attr-accept: 2.2.2 + file-selector: 0.6.0 + prop-types: 15.8.1 + react: 18.2.0 + dev: false + /react-error-overlay@6.0.11: resolution: {integrity: sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==} dev: false @@ -14944,6 +15919,19 @@ packages: tiny-warning: 1.0.3 dev: false + /react-router-dom@6.20.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-CbcKjEyiSVpA6UtCHOIYLUYn/UJfwzp55va4yEfpk7JBN3GPqWfHrdLkAvNCcpXr8QoihcDMuk0dzWZxtlB/mQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + dependencies: + '@remix-run/router': 1.13.0 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-router: 6.20.0(react@18.2.0) + dev: false + /react-router@5.3.4(react@17.0.2): resolution: {integrity: sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==} peerDependencies: @@ -14961,6 +15949,16 @@ packages: tiny-warning: 1.0.3 dev: false + /react-router@6.20.0(react@18.2.0): + resolution: {integrity: sha512-pVvzsSsgUxxtuNfTHC4IxjATs10UaAtvLGVSA1tbUE4GDaOSU1Esu2xF5nWLz7KPiMuW8BJWuPFdlGYJ7/rW0w==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: '>=16.8' + dependencies: + '@remix-run/router': 1.13.0 + react: 18.2.0 + dev: false + /react-smooth@2.0.5(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-BMP2Ad42tD60h0JW6BFaib+RJuV5dsXJK9Baxiv/HlNFjvRLqA9xrNKxVWnUIZPQfzUwGXIlU/dSYLU+54YGQA==} peerDependencies: @@ -15330,6 +16328,10 @@ packages: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} dev: false + /resize-observer-polyfill@1.5.1: + resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} + dev: false + /resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -15559,6 +16561,12 @@ packages: ajv-keywords: 5.1.0(ajv@8.12.0) dev: false + /scroll-into-view-if-needed@3.1.0: + resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==} + dependencies: + compute-scroll-into-view: 3.1.0 + dev: false + /search-insights@2.9.0: resolution: {integrity: sha512-bkWW9nIHOFkLwjQ1xqVaMbjjO5vhP26ERsH9Y3pKr8imthofEFIxlnOabkmGcw6ksRj9jWidcI65vvjJH/nTGg==} dev: false @@ -15986,6 +16994,10 @@ packages: engines: {node: '>=0.6.19'} dev: true + /string-convert@0.2.1: + resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==} + dev: false + /string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -16162,6 +17174,10 @@ packages: postcss-selector-parser: 6.0.13 dev: false + /stylis@4.3.0: + resolution: {integrity: sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==} + dev: false + /subscriptions-transport-ws@0.11.0(graphql@16.8.1): resolution: {integrity: sha512-8D4C6DIH5tGiAIpp5I0wD/xRlNiZAPGHygzCe7VzyzUoxHtawzjNAY9SUTXU05/EY2NMY9/9GF0ycizkXr1CWQ==} deprecated: The `subscriptions-transport-ws` package is no longer maintained. We recommend you use `graphql-ws` instead. For help migrating Apollo software to `graphql-ws`, see https://www.apollographql.com/docs/apollo-server/data/subscriptions/#switching-from-subscriptions-transport-ws For general help using `graphql-ws`, see https://github.com/enisdenjo/graphql-ws/blob/master/README.md @@ -16436,6 +17452,11 @@ packages: real-require: 0.2.0 dev: false + /throttle-debounce@5.0.0: + resolution: {integrity: sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==} + engines: {node: '>=12.22'} + dev: false + /through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: true @@ -16477,6 +17498,10 @@ packages: dependencies: is-number: 7.0.0 + /toggle-selection@1.0.6: + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + dev: false + /toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'}