From 2f609d4f3eb10aae4343066222385d2fb6554870 Mon Sep 17 00:00:00 2001 From: Bradford Derby Date: Mon, 9 Sep 2024 21:00:08 -0400 Subject: [PATCH 01/11] #2971 added logoImage and featuredProjects to the organization model --- .../migration.sql | 8 ++++ src/backend/src/prisma/schema.prisma | 46 ++++++++++--------- 2 files changed, 33 insertions(+), 21 deletions(-) create mode 100644 src/backend/src/prisma/migrations/20240910005616_add_logo_image_featured_project/migration.sql diff --git a/src/backend/src/prisma/migrations/20240910005616_add_logo_image_featured_project/migration.sql b/src/backend/src/prisma/migrations/20240910005616_add_logo_image_featured_project/migration.sql new file mode 100644 index 0000000000..fe5771a6b1 --- /dev/null +++ b/src/backend/src/prisma/migrations/20240910005616_add_logo_image_featured_project/migration.sql @@ -0,0 +1,8 @@ +-- AlterTable +ALTER TABLE "Organization" ADD COLUMN "logoImage" TEXT; + +-- AlterTable +ALTER TABLE "Project" ADD COLUMN "organizationId" TEXT; + +-- AddForeignKey +ALTER TABLE "Project" ADD CONSTRAINT "Project_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/src/backend/src/prisma/schema.prisma b/src/backend/src/prisma/schema.prisma index 2c7863e013..88d671804c 100644 --- a/src/backend/src/prisma/schema.prisma +++ b/src/backend/src/prisma/schema.prisma @@ -382,16 +382,18 @@ model WBS_Element { } model Project { - projectId String @id @default(uuid()) - wbsElementId String @unique - wbsElement WBS_Element @relation(fields: [wbsElementId], references: [wbsElementId]) - budget Int @default(0) - summary String - workPackages Work_Package[] - carId String - car Car @relation(fields: [carId], references: [carId]) - teams Team[] @relation(name: "assignedBy") - favoritedBy User[] @relation(name: "favoritedBy") + projectId String @id @default(uuid()) + wbsElementId String @unique + wbsElement WBS_Element @relation(fields: [wbsElementId], references: [wbsElementId]) + budget Int @default(0) + summary String + workPackages Work_Package[] + carId String + car Car @relation(fields: [carId], references: [carId]) + teams Team[] @relation(name: "assignedBy") + favoritedBy User[] @relation(name: "favoritedBy") + organizationId String? + organization Organization? @relation(fields: [organizationId], references: [organizationId]) } model Work_Package { @@ -872,6 +874,7 @@ model Organization { description String applyInterestImageId String? @unique exploreAsGuestImageId String? @unique + logoImage String? // Relation references wbsElements WBS_Element[] @@ -893,20 +896,21 @@ model Organization { usefulLinks Link[] FrequentlyAskedQuestions FrequentlyAskedQuestion[] Milestone Milestone[] + featuredProjects Project[] } model FrequentlyAskedQuestion { - faqId String @id @default(uuid()) - question String - answer String - userCreated User @relation(fields: [userCreatedId], references: [userId], name: "frequentlyAskedQuestionCreator") - userCreatedId String - userDeleted User? @relation(fields: [userDeletedId], references: [userId], name: "frequentlyAskedQuestionDeleter") - userDeletedId String? - dateCreated DateTime @default(now()) - dateDeleted DateTime? - organizationId String - organization Organization @relation(fields: [organizationId], references: [organizationId]) + faqId String @id @default(uuid()) + question String + answer String + userCreated User @relation(fields: [userCreatedId], references: [userId], name: "frequentlyAskedQuestionCreator") + userCreatedId String + userDeleted User? @relation(fields: [userDeletedId], references: [userId], name: "frequentlyAskedQuestionDeleter") + userDeletedId String? + dateCreated DateTime @default(now()) + dateDeleted DateTime? + organizationId String + organization Organization @relation(fields: [organizationId], references: [organizationId]) } model Milestone { From b31f9aa349282e152b4df4e2171733db9e609f9f Mon Sep 17 00:00:00 2001 From: Peyton-McKee Date: Tue, 7 Jan 2025 13:05:15 -0500 Subject: [PATCH 02/11] Homepage Redesign --- .github/workflows/production-build.yml | 25 + .github/workflows/system-tests.yml | 2 +- Dockerfile | 2 +- package.json | 1 + src/backend/Dockerfile | 2 +- src/backend/index.ts | 14 +- src/backend/package.json | 4 +- .../controllers/announcements.controllers.ts | 34 + .../src/controllers/cars.controllers.ts | 8 +- .../change-requests.controllers.ts | 36 +- .../description-bullets.controllers.ts | 14 +- .../controllers/design-reviews.controllers.ts | 28 +- .../src/controllers/onboarding.controller.ts | 21 + .../controllers/organizations.controllers.ts | 138 + .../src/controllers/popUps.controllers.ts | 27 + .../src/controllers/projects.controllers.ts | 104 +- .../controllers/recruitment.controllers.ts | 12 +- .../reimbursement-requests.controllers.ts | 127 +- .../src/controllers/slack.controllers.ts | 18 + .../src/controllers/tasks.controllers.ts | 20 +- .../src/controllers/teams.controllers.ts | 48 +- .../src/controllers/users.controllers.ts | 76 +- .../work-package-templates.controllers.ts | 22 +- .../controllers/work-packages.controllers.ts | 30 +- src/backend/src/integrations/slack.ts | 75 + .../announcements.query.args.ts | 11 + .../prisma-query-args/auth-user.query-args.ts | 7 +- .../prisma-query-args/pop-up.query-args.ts | 11 + .../migration.sql | 79 + src/backend/src/prisma/schema.prisma | 30 +- src/backend/src/prisma/seed.ts | 51 +- .../src/routes/announcements.routes.ts | 9 + src/backend/src/routes/onboarding.routes.ts | 8 + .../src/routes/organizations.routes.ts | 27 +- src/backend/src/routes/pop-up.routes.ts | 9 + .../routes/reimbursement-requests.routes.ts | 2 + src/backend/src/routes/slack.routes.ts | 8 + src/backend/src/routes/teams.routes.ts | 1 - src/backend/src/routes/users.routes.ts | 8 + .../src/services/announcement.service.ts | 168 + .../src/services/change-requests.services.ts | 15 +- .../src/services/design-reviews.services.ts | 3 + .../src/services/notifications.services.ts | 11 +- .../src/services/onboarding.services.ts | 11 + .../src/services/organizations.services.ts | 173 +- src/backend/src/services/pop-up.services.ts | 102 + .../src/services/recruitment.services.ts | 2 +- .../reimbursement-requests.services.ts | 40 +- src/backend/src/services/slack.services.ts | 169 + src/backend/src/services/users.services.ts | 48 +- .../transformers/announcements.transformer.ts | 14 + .../src/transformers/auth-user.transformer.ts | 5 +- .../src/transformers/pop-up.transformer.ts | 12 + src/backend/src/utils/auth.utils.ts | 42 +- .../src/utils/change-requests.utils.ts | 7 +- src/backend/src/utils/errors.utils.ts | 3 +- src/backend/src/utils/pop-up.utils.ts | 69 + src/backend/src/utils/projects.utils.ts | 37 +- .../src/utils/reimbursement-requests.utils.ts | 7 +- src/backend/src/utils/slack.utils.ts | 119 +- src/backend/src/utils/teams.utils.ts | 24 +- src/backend/src/utils/validation.utils.ts | 7 +- .../tests/integration/slackMessages.test.ts | 399 ++ src/backend/tests/test-utils.ts | 75 +- src/backend/tests/unit/announcements.test.ts | 223 + src/backend/tests/unit/design-review.test.ts | 71 + src/backend/tests/unit/organization.test.ts | 333 ++ src/backend/tests/unit/pop-up.test.ts | 90 + src/backend/tests/unit/recruitment.test.ts | 339 ++ .../tests/unit/reimbursement-requests.test.ts | 232 + src/backend/tests/unit/team-type.test.ts | 106 + src/backend/tests/unit/users.test.ts | 51 + .../tests/unit/work-package-template.test.ts | 167 + .../tests/unmocked/announcements.test.ts | 91 + src/frontend/Dockerfile | 2 +- src/frontend/src/apis/announcements.api.ts | 26 + src/frontend/src/apis/finance.api.ts | 7 +- src/frontend/src/apis/onboarding.api.ts | 16 + src/frontend/src/apis/organizations.api.ts | 64 + src/frontend/src/apis/pop-ups.api.ts | 19 + src/frontend/src/apis/recruitment.api.ts | 8 + .../transformers/announcements.transformer.ts | 9 + src/frontend/src/apis/users.api.ts | 18 + src/frontend/src/app/AppAuthenticated.tsx | 1 + .../src/app/AppOrganizationContext.tsx | 2 +- src/frontend/src/app/AppPublic.tsx | 2 +- .../components/ChangeRequestDetailCard.tsx | 13 +- .../src/components/NERDeleteModal.tsx | 33 + src/frontend/src/components/PageLayout.tsx | 2 + src/frontend/src/components/PopUpAlert.tsx | 49 + src/frontend/src/components/PopUpCard.tsx | 74 + src/frontend/src/hooks/announcements.hooks.ts | 36 + src/frontend/src/hooks/finance.hooks.ts | 16 +- src/frontend/src/hooks/organizations.hooks.ts | 125 + src/frontend/src/hooks/pop-ups.hooks.ts | 36 + src/frontend/src/hooks/recruitment.hooks.ts | 43 +- src/frontend/src/hooks/users.hooks.ts | 31 +- .../pages/AdminToolsPage/AdminToolsPage.tsx | 6 + .../AdminToolsSlackWorkspaceId.tsx | 72 + .../EditGuestView/EditDescription.tsx | 83 + .../EditGuestView/EditDescriptionForm.tsx | 101 + .../EditGuestView/EditFeaturedProjects.tsx | 99 + .../EditFeaturedProjectsDropdown.tsx | 39 + .../EditFeaturedProjectsForm.tsx | 95 + .../AdminToolsPage/EditGuestView/EditLogo.tsx | 93 + .../EditGuestView/EditLogoForm.tsx | 111 + .../EditGuestView/GuestViewConfig.tsx | 22 + .../RecruitmentConfig/FAQTable.tsx | 40 +- .../RecruitmentConfig/MilestoneTable.tsx | 39 +- .../CalendarPage/DesignReviewSummaryModal.tsx | 16 +- .../ChangeRequestsOverview.tsx | 54 +- .../src/pages/CreditsPage/CreditsPage.tsx | 19 +- .../MarkDeliveredModal.tsx | 125 + .../ReimbursementRequestDetailsView.tsx | 40 +- .../SubmitToSaboModal.tsx | 22 +- .../ReimbursementRequestsSection.tsx | 4 +- .../src/pages/HomePage/AdminHomePage.tsx | 60 + .../src/pages/HomePage/GuestHomePage.tsx | 74 +- src/frontend/src/pages/HomePage/Home.tsx | 27 +- .../src/pages/HomePage/IntroGuestHomePage.tsx | 42 + .../src/pages/HomePage/LeadHomePage.tsx | 60 + .../src/pages/HomePage/MemberHomePage.tsx | 37 +- .../components/ChangeRequestsToReview.tsx | 51 + .../HomePage/components/DesignReviewCard.tsx | 117 + .../components/EmptyPageBlockDisplay.tsx | 30 + .../HomePage/components/FeaturedProjects.tsx | 56 + .../components/FeaturedProjectsCard.tsx | 60 + .../components/GeneralAnnouncementCard.tsx | 52 + .../components/GeneralAnnouncements.tsx | 44 + .../components/GuestOrganizationInfo.tsx | 79 + .../pages/HomePage/components/LogoDisplay.tsx | 35 + .../components/MemberEncouragement.tsx | 61 + .../src/pages/HomePage/components/MyTasks.tsx | 45 + .../components/MyTeamsOverdueTasks.tsx | 50 + .../HomePage/components/OrganizationLogo.tsx | 15 + .../components/OverdueWorkPackageCard.tsx | 145 + .../components/OverdueWorkPackageView.tsx | 96 + .../components/OverdueWorkPackages.tsx | 41 + .../components/ScrollablePageBlock.tsx | 65 + .../HomePage/components/TaskDetailCard.tsx | 123 + .../HomePage/components/TeamTaskCard.tsx | 75 + .../components/TeamWorkPackageDisplay.tsx | 57 + .../components/UpcomingDesignReviews.tsx | 67 + .../HomePage/components/WorkPackageCard.tsx | 3 +- .../HomePage/components/WorkPackageSelect.tsx | 91 + .../components/WorkPackagesSelectionView.tsx | 129 + src/frontend/src/pages/LoginPage/Login.tsx | 2 +- .../BOM/BOMTableWrapper.tsx | 17 +- .../UserScheduleSettingsEdit.tsx | 11 +- .../WorkPackageFormDetails.tsx | 4 +- .../src/utils/change-request.utils.ts | 64 +- src/frontend/src/utils/datetime.utils.ts | 15 + .../src/utils/reimbursement-request.utils.ts | 19 +- src/frontend/src/utils/routes.ts | 2 + src/frontend/src/utils/task.utils.ts | 16 + src/frontend/src/utils/urls.ts | 45 + src/frontend/src/utils/work-package.utils.ts | 37 +- src/shared/index.ts | 3 +- src/shared/src/date-utils.ts | 10 + src/shared/src/permission-utils.ts | 10 + src/shared/src/types/announcements.types.ts | 12 + src/shared/src/types/pop-up-types.ts | 6 + src/shared/src/types/user-types.ts | 4 + yarn.lock | 4182 ++++++++++------- 164 files changed, 10150 insertions(+), 2322 deletions(-) create mode 100644 .github/workflows/production-build.yml create mode 100644 src/backend/src/controllers/announcements.controllers.ts create mode 100644 src/backend/src/controllers/onboarding.controller.ts create mode 100644 src/backend/src/controllers/organizations.controllers.ts create mode 100644 src/backend/src/controllers/popUps.controllers.ts create mode 100644 src/backend/src/controllers/slack.controllers.ts create mode 100644 src/backend/src/prisma-query-args/announcements.query.args.ts create mode 100644 src/backend/src/prisma-query-args/pop-up.query-args.ts create mode 100644 src/backend/src/prisma/migrations/20241230221615_homepage_redesign/migration.sql create mode 100644 src/backend/src/routes/announcements.routes.ts create mode 100644 src/backend/src/routes/onboarding.routes.ts create mode 100644 src/backend/src/routes/pop-up.routes.ts create mode 100644 src/backend/src/routes/slack.routes.ts create mode 100644 src/backend/src/services/announcement.service.ts create mode 100644 src/backend/src/services/onboarding.services.ts create mode 100644 src/backend/src/services/pop-up.services.ts create mode 100644 src/backend/src/services/slack.services.ts create mode 100644 src/backend/src/transformers/announcements.transformer.ts create mode 100644 src/backend/src/transformers/pop-up.transformer.ts create mode 100644 src/backend/src/utils/pop-up.utils.ts create mode 100644 src/backend/tests/integration/slackMessages.test.ts create mode 100644 src/backend/tests/unit/announcements.test.ts create mode 100644 src/backend/tests/unit/design-review.test.ts create mode 100644 src/backend/tests/unit/organization.test.ts create mode 100644 src/backend/tests/unit/pop-up.test.ts create mode 100644 src/backend/tests/unit/recruitment.test.ts create mode 100644 src/backend/tests/unit/reimbursement-requests.test.ts create mode 100644 src/backend/tests/unit/team-type.test.ts create mode 100644 src/backend/tests/unit/users.test.ts create mode 100644 src/backend/tests/unit/work-package-template.test.ts create mode 100644 src/backend/tests/unmocked/announcements.test.ts create mode 100644 src/frontend/src/apis/announcements.api.ts create mode 100644 src/frontend/src/apis/onboarding.api.ts create mode 100644 src/frontend/src/apis/organizations.api.ts create mode 100644 src/frontend/src/apis/pop-ups.api.ts create mode 100644 src/frontend/src/apis/transformers/announcements.transformer.ts create mode 100644 src/frontend/src/components/NERDeleteModal.tsx create mode 100644 src/frontend/src/components/PopUpAlert.tsx create mode 100644 src/frontend/src/components/PopUpCard.tsx create mode 100644 src/frontend/src/hooks/announcements.hooks.ts create mode 100644 src/frontend/src/hooks/organizations.hooks.ts create mode 100644 src/frontend/src/hooks/pop-ups.hooks.ts create mode 100644 src/frontend/src/pages/AdminToolsPage/AdminToolsSlackWorkspaceId.tsx create mode 100644 src/frontend/src/pages/AdminToolsPage/EditGuestView/EditDescription.tsx create mode 100644 src/frontend/src/pages/AdminToolsPage/EditGuestView/EditDescriptionForm.tsx create mode 100644 src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjects.tsx create mode 100644 src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjectsDropdown.tsx create mode 100644 src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjectsForm.tsx create mode 100644 src/frontend/src/pages/AdminToolsPage/EditGuestView/EditLogo.tsx create mode 100644 src/frontend/src/pages/AdminToolsPage/EditGuestView/EditLogoForm.tsx create mode 100644 src/frontend/src/pages/AdminToolsPage/EditGuestView/GuestViewConfig.tsx create mode 100644 src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/MarkDeliveredModal.tsx create mode 100644 src/frontend/src/pages/HomePage/AdminHomePage.tsx create mode 100644 src/frontend/src/pages/HomePage/IntroGuestHomePage.tsx create mode 100644 src/frontend/src/pages/HomePage/LeadHomePage.tsx create mode 100644 src/frontend/src/pages/HomePage/components/ChangeRequestsToReview.tsx create mode 100644 src/frontend/src/pages/HomePage/components/DesignReviewCard.tsx create mode 100644 src/frontend/src/pages/HomePage/components/EmptyPageBlockDisplay.tsx create mode 100644 src/frontend/src/pages/HomePage/components/FeaturedProjects.tsx create mode 100644 src/frontend/src/pages/HomePage/components/FeaturedProjectsCard.tsx create mode 100644 src/frontend/src/pages/HomePage/components/GeneralAnnouncementCard.tsx create mode 100644 src/frontend/src/pages/HomePage/components/GeneralAnnouncements.tsx create mode 100644 src/frontend/src/pages/HomePage/components/GuestOrganizationInfo.tsx create mode 100644 src/frontend/src/pages/HomePage/components/LogoDisplay.tsx create mode 100644 src/frontend/src/pages/HomePage/components/MemberEncouragement.tsx create mode 100644 src/frontend/src/pages/HomePage/components/MyTasks.tsx create mode 100644 src/frontend/src/pages/HomePage/components/MyTeamsOverdueTasks.tsx create mode 100644 src/frontend/src/pages/HomePage/components/OrganizationLogo.tsx create mode 100644 src/frontend/src/pages/HomePage/components/OverdueWorkPackageCard.tsx create mode 100644 src/frontend/src/pages/HomePage/components/OverdueWorkPackageView.tsx create mode 100644 src/frontend/src/pages/HomePage/components/OverdueWorkPackages.tsx create mode 100644 src/frontend/src/pages/HomePage/components/ScrollablePageBlock.tsx create mode 100644 src/frontend/src/pages/HomePage/components/TaskDetailCard.tsx create mode 100644 src/frontend/src/pages/HomePage/components/TeamTaskCard.tsx create mode 100644 src/frontend/src/pages/HomePage/components/TeamWorkPackageDisplay.tsx create mode 100644 src/frontend/src/pages/HomePage/components/UpcomingDesignReviews.tsx create mode 100644 src/frontend/src/pages/HomePage/components/WorkPackageSelect.tsx create mode 100644 src/frontend/src/pages/HomePage/components/WorkPackagesSelectionView.tsx create mode 100644 src/shared/src/types/announcements.types.ts create mode 100644 src/shared/src/types/pop-up-types.ts diff --git a/.github/workflows/production-build.yml b/.github/workflows/production-build.yml new file mode 100644 index 0000000000..4af27918e1 --- /dev/null +++ b/.github/workflows/production-build.yml @@ -0,0 +1,25 @@ + +name: Production Build + +on: + push: + branches: + - main + - multitenancy + +jobs: + run-tests: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 18.17.1 + cache: 'yarn' + - name: Yarn Install + run: yarn install + - name: Run Tests + run: yarn containerize diff --git a/.github/workflows/system-tests.yml b/.github/workflows/system-tests.yml index 5126e14aa0..781f846bea 100644 --- a/.github/workflows/system-tests.yml +++ b/.github/workflows/system-tests.yml @@ -23,4 +23,4 @@ jobs: - name: Yarn Install run: yarn install - name: Run Tests - run: yarn containerize:teste2e + run: yarn containerize:test:e2e diff --git a/Dockerfile b/Dockerfile index 5fa67427a9..0a7ba5e783 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:18.17.1 +FROM node:20 WORKDIR /base COPY package.json tsconfig.build.json ./ diff --git a/package.json b/package.json index bc13987bec..6530b87e3e 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "@types/react-dom": "17.0.1" }, "dependencies": { + "@slack/events-api": "^3.0.1", "mitt": "^3.0.1", "react-hook-form-persist": "^3.0.0", "typescript": "^4.1.5" diff --git a/src/backend/Dockerfile b/src/backend/Dockerfile index 9c4a1104c3..644d9d3b11 100644 --- a/src/backend/Dockerfile +++ b/src/backend/Dockerfile @@ -1,5 +1,5 @@ # TO BE RUN FROM DOCKER COMPOSE. DO NOT RUN MANUALLY AS CONTEXT IS NOT SET CORRECTLY -FROM node:18 +FROM node:20 WORKDIR /base diff --git a/src/backend/index.ts b/src/backend/index.ts index 97d683ec5f..0f78b34b0d 100644 --- a/src/backend/index.ts +++ b/src/backend/index.ts @@ -17,8 +17,13 @@ import workPackageTemplatesRouter from './src/routes/work-package-templates.rout import carsRouter from './src/routes/cars.routes'; import organizationRouter from './src/routes/organizations.routes'; import recruitmentRouter from './src/routes/recruitment.routes'; +import { slackEvents } from './src/routes/slack.routes'; +import announcementsRouter from './src/routes/announcements.routes'; +import onboardingRouter from './src/routes/onboarding.routes'; +import popUpsRouter from './src/routes/pop-up.routes'; const app = express(); + const port = process.env.PORT || 3001; const isProd = process.env.NODE_ENV === 'production'; @@ -39,6 +44,10 @@ const options: cors.CorsOptions = { allowedHeaders }; +// so we can listen to slack messages +// NOTE: must be done before using json +app.use('/slack', slackEvents.requestListener()); + // so that we can use cookies and json app.use(cookieParser()); app.use(express.json()); @@ -67,8 +76,11 @@ app.use('/templates', workPackageTemplatesRouter); app.use('/cars', carsRouter); app.use('/organizations', organizationRouter); app.use('/recruitment', recruitmentRouter); +app.use('/pop-ups', popUpsRouter); +app.use('/announcements', announcementsRouter); +app.use('/onboarding', onboardingRouter); app.use('/', (_req, res) => { - res.json('Welcome to FinishLine'); + res.status(200).json('Welcome to FinishLine'); }); // custom error handler middleware diff --git a/src/backend/package.json b/src/backend/package.json index 17067b25a7..870b166d9e 100644 --- a/src/backend/package.json +++ b/src/backend/package.json @@ -14,7 +14,7 @@ "@types/concat-stream": "^2.0.0", "@types/cookie-parser": "^1.4.3", "@types/cors": "^2.8.12", - "@types/express": "^4.17.6", + "@types/express": "^5.0.0", "@types/multer": "^1.4.7", "@types/nodemailer": "^6.4.0", "body-parser": "^1.19.0", @@ -23,7 +23,7 @@ "cors": "^2.8.5", "decimal.js": "^10.4.3", "dotenv": "^16.0.1", - "express": "^4.17.1", + "express": "^5.0.0", "express-jwt": "^7.7.5", "express-validator": "^6.14.2", "google-auth-library": "^8.1.1", diff --git a/src/backend/src/controllers/announcements.controllers.ts b/src/backend/src/controllers/announcements.controllers.ts new file mode 100644 index 0000000000..ec18d65538 --- /dev/null +++ b/src/backend/src/controllers/announcements.controllers.ts @@ -0,0 +1,34 @@ +import { NextFunction, Request, Response } from 'express'; +import AnnouncementService from '../services/announcement.service'; + +export default class AnnouncementController { + static async getUserUnreadAnnouncements(req: Request, res: Response, next: NextFunction) { + try { + const { organization, currentUser } = req; + + const unreadAnnouncements = await AnnouncementService.getUserUnreadAnnouncements( + currentUser.userId, + organization.organizationId + ); + res.status(200).json(unreadAnnouncements); + } catch (error: unknown) { + next(error); + } + } + + static async removeUserAnnouncement(req: Request, res: Response, next: NextFunction) { + try { + const { announcementId } = req.params; + const { organization, currentUser } = req; + + const unreadAnnouncements = await AnnouncementService.removeUserAnnouncement( + currentUser.userId, + announcementId, + organization.organizationId + ); + res.status(200).json(unreadAnnouncements); + } catch (error: unknown) { + next(error); + } + } +} diff --git a/src/backend/src/controllers/cars.controllers.ts b/src/backend/src/controllers/cars.controllers.ts index c2e57aebfb..aa1865355a 100644 --- a/src/backend/src/controllers/cars.controllers.ts +++ b/src/backend/src/controllers/cars.controllers.ts @@ -6,9 +6,9 @@ export default class CarsController { try { const cars = await CarsService.getAllCars(req.organization); - return res.status(200).json(cars); + res.status(200).json(cars); } catch (error: unknown) { - return next(error); + next(error); } } @@ -17,9 +17,9 @@ export default class CarsController { const { name } = req.body; const car = await CarsService.createCar(req.organization, req.currentUser, name); - return res.status(201).json(car); + res.status(201).json(car); } catch (error: unknown) { - return next(error); + next(error); } } } diff --git a/src/backend/src/controllers/change-requests.controllers.ts b/src/backend/src/controllers/change-requests.controllers.ts index 2ad922aaa8..eea4cab5ea 100644 --- a/src/backend/src/controllers/change-requests.controllers.ts +++ b/src/backend/src/controllers/change-requests.controllers.ts @@ -7,18 +7,18 @@ export default class ChangeRequestsController { const { crId } = req.params; const cr = await ChangeRequestsService.getChangeRequestByID(crId, req.organization); - return res.status(200).json(cr); + res.status(200).json(cr); } catch (error: unknown) { - return next(error); + next(error); } } static async getAllChangeRequests(req: Request, res: Response, next: NextFunction) { try { const changeRequests = await ChangeRequestsService.getAllChangeRequests(req.organization); - return res.status(200).json(changeRequests); + res.status(200).json(changeRequests); } catch (error: unknown) { - return next(error); + next(error); } } @@ -33,9 +33,9 @@ export default class ChangeRequestsController { req.organization, psId ); - return res.status(200).json({ message: `Change request #${id} successfully reviewed.` }); + res.status(200).json({ message: `Change request #${id} successfully reviewed.` }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -55,9 +55,9 @@ export default class ChangeRequestsController { confirmDetails, req.organization ); - return res.status(200).json({ message: `Successfully created activation change request with id #${id}` }); + res.status(200).json({ message: `Successfully created activation change request with id #${id}` }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -73,9 +73,9 @@ export default class ChangeRequestsController { confirmDone, req.organization ); - return res.status(200).json({ message: `Successfully created stage gate request with id #${id}` }); + res.status(200).json({ message: `Successfully created stage gate request with id #${id}` }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -99,9 +99,9 @@ export default class ChangeRequestsController { projectProposedChanges, workPackageProposedChanges ); - return res.status(200).json(createdCR); + res.status(200).json(createdCR); } catch (error: unknown) { - return next(error); + next(error); } } @@ -117,9 +117,9 @@ export default class ChangeRequestsController { scopeImpact, req.organization ); - return res.status(200).json({ message: `Successfully added proposed solution with id #${id}` }); + res.status(200).json({ message: `Successfully added proposed solution with id #${id}` }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -128,9 +128,9 @@ export default class ChangeRequestsController { const { crId } = req.params; await ChangeRequestsService.deleteChangeRequest(req.currentUser, crId, req.organization); - return res.status(200).json({ message: `Successfully deleted change request #${crId}` }); + res.status(200).json({ message: `Successfully deleted change request #${crId}` }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -140,9 +140,9 @@ export default class ChangeRequestsController { const { crId } = req.params; await ChangeRequestsService.requestCRReview(req.currentUser, userIds, crId, req.organization); - return res.status(200).json({ message: `Successfully requested reviewer(s) to change request #${crId}` }); + res.status(200).json({ message: `Successfully requested reviewer(s) to change request #${crId}` }); } catch (error: unknown) { - return next(error); + next(error); } } } diff --git a/src/backend/src/controllers/description-bullets.controllers.ts b/src/backend/src/controllers/description-bullets.controllers.ts index ffc03cc0da..03061edbbc 100644 --- a/src/backend/src/controllers/description-bullets.controllers.ts +++ b/src/backend/src/controllers/description-bullets.controllers.ts @@ -10,18 +10,18 @@ export default class DescriptionBulletsController { descriptionId, req.organization ); - return res.status(200).json(updatedDB); + res.status(200).json(updatedDB); } catch (error: unknown) { - return next(error); + next(error); } } static async getAllDescriptionBulletTypes(req: Request, res: Response, next: NextFunction) { try { const descriptionBulletTypes = await DescriptionBulletsService.getAllDescriptionBulletTypes(req.organization); - return res.status(200).json(descriptionBulletTypes); + res.status(200).json(descriptionBulletTypes); } catch (error: unknown) { - return next(error); + next(error); } } @@ -37,7 +37,7 @@ export default class DescriptionBulletsController { ); res.status(201).json(newDescriptionBulletType); } catch (error: unknown) { - return next(error); + next(error); } } @@ -52,9 +52,9 @@ export default class DescriptionBulletsController { projectRequired, req.organization ); - return res.status(200).json(updatedDescriptionBulletType); + res.status(200).json(updatedDescriptionBulletType); } catch (error: unknown) { - return next(error); + next(error); } } } diff --git a/src/backend/src/controllers/design-reviews.controllers.ts b/src/backend/src/controllers/design-reviews.controllers.ts index 899969d92b..979ad3d1f1 100644 --- a/src/backend/src/controllers/design-reviews.controllers.ts +++ b/src/backend/src/controllers/design-reviews.controllers.ts @@ -6,9 +6,9 @@ export default class DesignReviewsController { static async getAllDesignReviews(req: Request, res: Response, next: NextFunction) { try { const designReviews = await DesignReviewsService.getAllDesignReviews(req.organization); - return res.status(200).json(designReviews); + res.status(200).json(designReviews); } catch (error: unknown) { - return next(error); + next(error); } } @@ -16,9 +16,9 @@ export default class DesignReviewsController { try { const drId: string = req.params.designReviewId; const deletedDesignReview = await DesignReviewsService.deleteDesignReview(req.currentUser, drId, req.organization); - return res.status(200).json(deletedDesignReview); + res.status(200).json(deletedDesignReview); } catch (error: unknown) { - return next(error); + next(error); } } @@ -36,9 +36,9 @@ export default class DesignReviewsController { meetingTimes, req.organization ); - return res.status(200).json(createdDesignReview); + res.status(200).json(createdDesignReview); } catch (error: unknown) { - return next(error); + next(error); } } @@ -47,9 +47,9 @@ export default class DesignReviewsController { const drId: string = req.params.designReviewId; const designReview = await DesignReviewsService.getSingleDesignReview(req.currentUser, drId, req.organization); - return res.status(200).json(designReview); + res.status(200).json(designReview); } catch (error: unknown) { - return next(error); + next(error); } } @@ -90,9 +90,9 @@ export default class DesignReviewsController { meetingTimes, req.organization ); - return res.status(200).json({ message: 'Design Review updated successfully' }); + res.status(200).json({ message: 'Design Review updated successfully' }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -109,9 +109,9 @@ export default class DesignReviewsController { user, req.organization ); - return res.status(200).json(updatedDesignReview); + res.status(200).json(updatedDesignReview); } catch (error: unknown) { - return next(error); + next(error); } } @@ -127,9 +127,9 @@ export default class DesignReviewsController { status, req.organization ); - return res.status(200).json(updatedDesignReview); + res.status(200).json(updatedDesignReview); } catch (error: unknown) { - return next(error); + next(error); } } } diff --git a/src/backend/src/controllers/onboarding.controller.ts b/src/backend/src/controllers/onboarding.controller.ts new file mode 100644 index 0000000000..2bd8660a35 --- /dev/null +++ b/src/backend/src/controllers/onboarding.controller.ts @@ -0,0 +1,21 @@ +import { NextFunction, Request, Response } from 'express'; +import OnboardingServices from '../services/onboarding.services'; + +export default class OnboardingController { + static async downloadImage(req: Request, res: Response, next: NextFunction) { + try { + const { fileId } = req.params; + + const imageData = await OnboardingServices.downloadImage(fileId); + + // Set the appropriate headers for the HTTP response + res.setHeader('content-type', String(imageData.type)); + res.setHeader('content-length', imageData.buffer.length); + + // Send the Buffer as the response body + res.send(imageData.buffer); + } catch (error: unknown) { + return next(error); + } + } +} diff --git a/src/backend/src/controllers/organizations.controllers.ts b/src/backend/src/controllers/organizations.controllers.ts new file mode 100644 index 0000000000..64a59bb0ee --- /dev/null +++ b/src/backend/src/controllers/organizations.controllers.ts @@ -0,0 +1,138 @@ +import { NextFunction, Request, Response } from 'express'; +import OrganizationsService from '../services/organizations.services'; +import { HttpException } from '../utils/errors.utils'; + +export default class OrganizationsController { + static async getCurrentOrganization(req: Request, res: Response, next: NextFunction) { + try { + const organization = await OrganizationsService.getCurrentOrganization(req.organization.organizationId); + res.status(200).json(organization); + } catch (error: unknown) { + next(error); + } + } + + static async setUsefulLinks(req: Request, res: Response, next: NextFunction) { + try { + const { links } = req.body; + const newLinks = await OrganizationsService.setUsefulLinks(req.currentUser, req.organization.organizationId, links); + res.status(200).json(newLinks); + } catch (error: unknown) { + next(error); + } + } + + static async setImages(req: Request, res: Response, next: NextFunction) { + try { + const { applyInterestImage = [], exploreAsGuestImage = [] } = req.files as { + applyInterestImage?: Express.Multer.File[]; + exploreAsGuestImage?: Express.Multer.File[]; + }; + + const applyInterestFile = applyInterestImage[0] || null; + const exploreAsGuestFile = exploreAsGuestImage[0] || null; + + const newImages = await OrganizationsService.setImages( + applyInterestFile, + exploreAsGuestFile, + req.currentUser, + req.organization + ); + + res.status(200).json(newImages); + } catch (error: unknown) { + next(error); + } + } + static async getAllUsefulLinks(req: Request, res: Response, next: NextFunction) { + try { + const links = await OrganizationsService.getAllUsefulLinks(req.organization.organizationId); + res.status(200).json(links); + } catch (error: unknown) { + next(error); + } + } + + static async getOrganizationImages(req: Request, res: Response, next: NextFunction) { + try { + const images = await OrganizationsService.getOrganizationImages(req.organization.organizationId); + res.status(200).json(images); + } catch (error: unknown) { + next(error); + } + } + + static async setOrganizationFeaturedProjects(req: Request, res: Response, next: NextFunction) { + try { + const { projectIds } = req.body; + const featuredProjects = await OrganizationsService.setFeaturedProjects(projectIds, req.organization, req.currentUser); + + res.status(200).json(featuredProjects); + } catch (error: unknown) { + next(error); + } + } + + static async setLogoImage(req: Request, res: Response, next: NextFunction) { + try { + if (!req.file) { + throw new HttpException(400, 'Invalid or undefined image data'); + } + + const updatedOrg = await OrganizationsService.setLogoImage(req.file, req.currentUser, req.organization); + + res.status(200).json(updatedOrg); + } catch (error: unknown) { + next(error); + } + } + + static async getOrganizationLogoImage(req: Request, res: Response, next: NextFunction) { + try { + const { organization } = req; + + const logoImageId = await OrganizationsService.getLogoImage(organization.organizationId); + res.status(200).json(logoImageId); + } catch (error: unknown) { + next(error); + } + } + + static async setOrganizationDescription(req: Request, res: Response, next: NextFunction) { + try { + const updatedOrg = await OrganizationsService.setOrganizationDescription( + req.body.description, + req.currentUser, + req.organization + ); + + res.status(200).json(updatedOrg); + } catch (error: unknown) { + next(error); + } + } + + static async getOrganizationFeaturedProjects(req: Request, res: Response, next: NextFunction) { + try { + const featuredProjects = await OrganizationsService.getOrganizationFeaturedProjects(req.organization.organizationId); + res.status(200).json(featuredProjects); + } catch (error: unknown) { + next(error); + } + } + + static async setSlackWorkspaceId(req: Request, res: Response, next: NextFunction) { + try { + const { workspaceId } = req.body; + + const updatedOrg = await OrganizationsService.setSlackWorkspaceId( + workspaceId, + req.currentUser, + req.organization.organizationId + ); + res.status(200).json(updatedOrg); + } catch (error: unknown) { + next(error); + } + } +} diff --git a/src/backend/src/controllers/popUps.controllers.ts b/src/backend/src/controllers/popUps.controllers.ts new file mode 100644 index 0000000000..6247a03fbd --- /dev/null +++ b/src/backend/src/controllers/popUps.controllers.ts @@ -0,0 +1,27 @@ +import { NextFunction, Request, Response } from 'express'; +import { PopUpService } from '../services/pop-up.services'; + +export default class PopUpsController { + static async getUserUnreadPopUps(req: Request, res: Response, next: NextFunction) { + try { + const { organization, currentUser } = req; + + const unreadPopUps = await PopUpService.getUserUnreadPopUps(currentUser.userId, organization.organizationId); + res.status(200).json(unreadPopUps); + } catch (error: unknown) { + next(error); + } + } + + static async removeUserPopUps(req: Request, res: Response, next: NextFunction) { + try { + const { popUpId } = req.params; + const { organization, currentUser } = req; + + const unreadPopUps = await PopUpService.removeUserPopUp(currentUser.userId, popUpId, organization.organizationId); + res.status(200).json(unreadPopUps); + } catch (error: unknown) { + next(error); + } + } +} diff --git a/src/backend/src/controllers/projects.controllers.ts b/src/backend/src/controllers/projects.controllers.ts index 1207d62703..ee391c7852 100644 --- a/src/backend/src/controllers/projects.controllers.ts +++ b/src/backend/src/controllers/projects.controllers.ts @@ -8,9 +8,9 @@ export default class ProjectsController { try { const includeDeleted = req.params.deleted === 'true'; const projects: Project[] = await ProjectsService.getAllProjects(req.organization, includeDeleted); - return res.status(200).json(projects); + res.status(200).json(projects); } catch (error: unknown) { - return next(error); + next(error); } } @@ -20,9 +20,9 @@ export default class ProjectsController { const project: Project = await ProjectsService.getSingleProject(wbsNumber, req.organization); - return res.status(200).json(project); + res.status(200).json(project); } catch (error: unknown) { - return next(error); + next(error); } } @@ -45,9 +45,9 @@ export default class ProjectsController { req.organization ); - return res.status(200).json(createdProject); + res.status(200).json(createdProject); } catch (error: unknown) { - return next(error); + next(error); } } @@ -68,9 +68,9 @@ export default class ProjectsController { req.organization ); - return res.status(200).json(editedProject); + res.status(200).json(editedProject); } catch (error: unknown) { - return next(error); + next(error); } } @@ -81,9 +81,9 @@ export default class ProjectsController { await ProjectsService.setProjectTeam(req.currentUser, wbsNumber, teamId, req.organization); - return res.status(200).json({ message: `Project ${wbsPipe(wbsNumber)}'s teams successfully updated.` }); + res.status(200).json({ message: `Project ${wbsPipe(wbsNumber)}'s teams successfully updated.` }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -91,9 +91,9 @@ export default class ProjectsController { try { const wbsNumber: WbsNumber = validateWBS(req.params.wbsNum); const deletedProject: Project = await ProjectsService.deleteProject(req.currentUser, wbsNumber, req.organization); - return res.status(200).json(deletedProject); + res.status(200).json(deletedProject); } catch (error: unknown) { - return next(error); + next(error); } } @@ -103,18 +103,18 @@ export default class ProjectsController { const targetProject = await ProjectsService.toggleFavorite(wbsNum, req.currentUser, req.organization); - return res.status(200).json(targetProject); + res.status(200).json(targetProject); } catch (error: unknown) { - return next(error); + next(error); } } static async getAllLinkTypes(req: Request, res: Response, next: NextFunction) { try { const linkTypes = await ProjectsService.getAllLinkTypes(req.organization); - return res.status(200).json(linkTypes); + res.status(200).json(linkTypes); } catch (error: unknown) { - return next(error); + next(error); } } @@ -123,9 +123,9 @@ export default class ProjectsController { const { name, iconName, required } = req.body; const newLinkType = await ProjectsService.createLinkType(req.currentUser, name, iconName, required, req.organization); - return res.status(200).json(newLinkType); + res.status(200).json(newLinkType); } catch (error: unknown) { - return next(error); + next(error); } } @@ -140,9 +140,9 @@ export default class ProjectsController { req.organization, pdmFileName ); - return res.status(200).json(createAssembly); + res.status(200).json(createAssembly); } catch (error: unknown) { - return next(error); + next(error); } } @@ -182,9 +182,9 @@ export default class ProjectsController { pdmFileName, unitName ); - return res.status(200).json(material); + res.status(200).json(material); } catch (error: unknown) { - return next(error); + next(error); } } @@ -192,9 +192,9 @@ export default class ProjectsController { try { const { name } = req.body; const createdManufacturer = await BillOfMaterialsService.createManufacturer(req.currentUser, name, req.organization); - return res.status(200).json(createdManufacturer); + res.status(200).json(createdManufacturer); } catch (error: unknown) { - return next(error); + next(error); } } @@ -206,9 +206,9 @@ export default class ProjectsController { manufacturerName, req.organization ); - return res.status(200).json(deletedManufacturer); + res.status(200).json(deletedManufacturer); } catch (error: unknown) { - return next(error); + next(error); } } @@ -216,9 +216,9 @@ export default class ProjectsController { try { const { unitId } = req.params; const deletedUnit = await BillOfMaterialsService.deleteUnit(req.currentUser, unitId, req.organization); - return res.status(200).json(deletedUnit); + res.status(200).json(deletedUnit); } catch (error: unknown) { - return next(error); + next(error); } } @@ -228,9 +228,9 @@ export default class ProjectsController { req.currentUser, req.organization ); - return res.status(200).json(manufacturers); + res.status(200).json(manufacturers); } catch (error: unknown) { - return next(error); + next(error); } } @@ -240,9 +240,9 @@ export default class ProjectsController { req.currentUser, req.organization ); - return res.status(200).json(materialTypes); + res.status(200).json(materialTypes); } catch (error: unknown) { - return next(error); + next(error); } } @@ -250,9 +250,9 @@ export default class ProjectsController { try { const { name } = req.body; const createdMaterialType = await BillOfMaterialsService.createMaterialType(name, req.currentUser, req.organization); - return res.status(200).json(createdMaterialType); + res.status(200).json(createdMaterialType); } catch (error: unknown) { - return next(error); + next(error); } } @@ -266,9 +266,9 @@ export default class ProjectsController { req.organization, assemblyId ); - return res.status(200).json(updatedMaterial); + res.status(200).json(updatedMaterial); } catch (error: unknown) { - return next(error); + next(error); } } @@ -276,9 +276,9 @@ export default class ProjectsController { try { const { assemblyId } = req.params; const deletedAssembly = await BillOfMaterialsService.deleteAssembly(assemblyId, req.currentUser, req.organization); - return res.status(200).json(deletedAssembly); + res.status(200).json(deletedAssembly); } catch (error: unknown) { - return next(error); + next(error); } } @@ -290,9 +290,9 @@ export default class ProjectsController { materialTypeName, req.organization ); - return res.status(200).json(deletedMaterial); + res.status(200).json(deletedMaterial); } catch (error: unknown) { - return next(error); + next(error); } } @@ -300,9 +300,9 @@ export default class ProjectsController { try { const { materialId } = req.params; const updatedMaterial = await BillOfMaterialsService.deleteMaterial(req.currentUser, materialId, req.organization); - return res.status(200).json(updatedMaterial); + res.status(200).json(updatedMaterial); } catch (error: unknown) { - return next(error); + next(error); } } @@ -342,18 +342,18 @@ export default class ProjectsController { assemblyId, pdmFileName ); - return res.status(200).json(updatedMaterial); + res.status(200).json(updatedMaterial); } catch (error: unknown) { - return next(error); + next(error); } } static async getAllUnits(req: Request, res: Response, next: NextFunction) { try { const units = await BillOfMaterialsService.getAllUnits(req.currentUser, req.organization); - return res.status(200).json(units); + res.status(200).json(units); } catch (error: unknown) { - return next(error); + next(error); } } @@ -361,9 +361,9 @@ export default class ProjectsController { try { const { name } = req.body; const createdUnit = await BillOfMaterialsService.createUnit(name, req.currentUser, req.organization); - return res.status(200).json(createdUnit); + res.status(200).json(createdUnit); } catch (error: unknown) { - return next(error); + next(error); } } @@ -378,9 +378,9 @@ export default class ProjectsController { name, pdmFileName ); - return res.status(200).json(updatedAssembly); + res.status(200).json(updatedAssembly); } catch (error: unknown) { - return next(error); + next(error); } } @@ -395,9 +395,9 @@ export default class ProjectsController { req.currentUser, req.organization ); - return res.status(200).json(linkTypeUpdated); + res.status(200).json(linkTypeUpdated); } catch (error: unknown) { - return next(error); + next(error); } } } diff --git a/src/backend/src/controllers/recruitment.controllers.ts b/src/backend/src/controllers/recruitment.controllers.ts index 71ebbb345a..3dfdc0eeeb 100644 --- a/src/backend/src/controllers/recruitment.controllers.ts +++ b/src/backend/src/controllers/recruitment.controllers.ts @@ -22,9 +22,9 @@ export default class RecruitmentController { dateOfEvent, req.organization ); - return res.status(200).json(milestone); + res.status(200).json(milestone); } catch (error: unknown) { - return next(error); + next(error); } } @@ -41,9 +41,9 @@ export default class RecruitmentController { milestoneId, req.organization ); - return res.status(200).json(milestone); + res.status(200).json(milestone); } catch (error: unknown) { - return next(error); + next(error); } } @@ -53,7 +53,7 @@ export default class RecruitmentController { await RecruitmentServices.deleteMilestone(req.currentUser, milestoneId, req.organization); res.status(200).json({ message: `Successfully deleted milestone with id ${milestoneId}` }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -93,7 +93,7 @@ export default class RecruitmentController { await RecruitmentServices.deleteFaq(req.currentUser, faqId, req.organization); res.status(200).json({ message: `Successfully deleted FAQ with id ${faqId}` }); } catch (error: unknown) { - return next(error); + next(error); } } } diff --git a/src/backend/src/controllers/reimbursement-requests.controllers.ts b/src/backend/src/controllers/reimbursement-requests.controllers.ts index f7e83345dd..cce6bc34c7 100644 --- a/src/backend/src/controllers/reimbursement-requests.controllers.ts +++ b/src/backend/src/controllers/reimbursement-requests.controllers.ts @@ -17,36 +17,36 @@ export default class ReimbursementRequestsController { req.currentUser, req.organization ); - return res.status(200).json(userReimbursementRequests); + res.status(200).json(userReimbursementRequests); } catch (error: unknown) { - return next(error); + next(error); } } static async getCurrentUserReimbursements(req: Request, res: Response, next: NextFunction) { try { const userReimbursements = await ReimbursementRequestService.getUserReimbursements(req.currentUser, req.organization); - return res.status(200).json(userReimbursements); + res.status(200).json(userReimbursements); } catch (error: unknown) { - return next(error); + next(error); } } static async getAllReimbursements(req: Request, res: Response, next: NextFunction) { try { const reimbursements = await ReimbursementRequestService.getAllReimbursements(req.currentUser, req.organization); - return res.status(200).json(reimbursements); + res.status(200).json(reimbursements); } catch (error: unknown) { - return next(error); + next(error); } } static async getAllVendors(req: Request, res: Response, next: NextFunction) { try { const vendors: Vendor[] = await ReimbursementRequestService.getAllVendors(req.organization); - return res.status(200).json(vendors); + res.status(200).json(vendors); } catch (error: unknown) { - return next(error); + next(error); } } @@ -74,9 +74,9 @@ export default class ReimbursementRequestsController { req.organization, dateOfExpense ); - return res.status(200).json(createdReimbursementRequest); + res.status(200).json(createdReimbursementRequest); } catch (error: unknown) { - return next(error); + next(error); } } @@ -89,9 +89,9 @@ export default class ReimbursementRequestsController { req.currentUser, req.organization ); - return res.status(200).json(reimbursement); + res.status(200).json(reimbursement); } catch (error: unknown) { - return next(error); + next(error); } } @@ -122,9 +122,9 @@ export default class ReimbursementRequestsController { req.organization, dateOfExpense ); - return res.status(200).json(updatedReimbursementRequestId); + res.status(200).json(updatedReimbursementRequestId); } catch (error: unknown) { - return next(error); + next(error); } } @@ -140,9 +140,9 @@ export default class ReimbursementRequestsController { dateReceived, req.organization ); - return res.status(200).json(updatedReimbursement); + res.status(200).json(updatedReimbursement); } catch (error: unknown) { - return next(error); + next(error); } } @@ -155,9 +155,9 @@ export default class ReimbursementRequestsController { req.currentUser, req.organization ); - return res.status(200).json(deletedReimbursementRequest); + res.status(200).json(deletedReimbursementRequest); } catch (error: unknown) { - return next(error); + next(error); } } @@ -167,9 +167,9 @@ export default class ReimbursementRequestsController { req.currentUser, req.organization ); - return res.status(200).json(requestsPendingAdvisors); + res.status(200).json(requestsPendingAdvisors); } catch (error: unknown) { - return next(error); + next(error); } } @@ -181,9 +181,9 @@ export default class ReimbursementRequestsController { saboNumbers, req.organization.organizationId ); - return res.status(200).json({ message: 'Successfully sent pending advisor list' }); + res.status(200).json({ message: 'Successfully sent pending advisor list' }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -192,9 +192,9 @@ export default class ReimbursementRequestsController { const { requestId } = req.params; const { saboNumber } = req.body; await ReimbursementRequestService.setSaboNumber(requestId, saboNumber, req.currentUser, req.organization); - return res.status(200).json({ message: 'Successfully set sabo number' }); + res.status(200).json({ message: 'Successfully set sabo number' }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -202,9 +202,9 @@ export default class ReimbursementRequestsController { try { const { name } = req.body; const createdVendor = await ReimbursementRequestService.createVendor(req.currentUser, name, req.organization); - return res.status(200).json(createdVendor); + res.status(200).json(createdVendor); } catch (error: unknown) { - return next(error); + next(error); } } @@ -219,9 +219,9 @@ export default class ReimbursementRequestsController { allowedRefundSources, req.organization ); - return res.status(200).json(createdAccountCode); + res.status(200).json(createdAccountCode); } catch (error: unknown) { - return next(error); + next(error); } } @@ -235,18 +235,18 @@ export default class ReimbursementRequestsController { const origin = isProd ? 'https://finishlinebyner.com' : 'http://localhost:3000'; res.header('Access-Control-Allow-Origin', origin); - return res.status(200).json(receipt); + res.status(200).json(receipt); } catch (error: unknown) { - return next(error); + next(error); } } static async getAllAccountCodes(req: Request, res: Response, next: NextFunction) { try { const accountCodes = await ReimbursementRequestService.getAllAccountCodes(req.organization); - return res.status(200).json(accountCodes); + res.status(200).json(accountCodes); } catch (error: unknown) { - return next(error); + next(error); } } @@ -256,9 +256,9 @@ export default class ReimbursementRequestsController { req.currentUser, req.organization ); - return res.status(200).json(reimbursementRequests); + res.status(200).json(reimbursementRequests); } catch (error: unknown) { - return next(error); + next(error); } } @@ -271,9 +271,9 @@ export default class ReimbursementRequestsController { req.currentUser, req.organization ); - return res.status(200).json(reimbursementStatus); + res.status(200).json(reimbursementStatus); } catch (error: unknown) { - return next(error); + next(error); } } @@ -286,9 +286,9 @@ export default class ReimbursementRequestsController { req.currentUser, req.organization ); - return res.status(200).json(reimbursementStatus); + res.status(200).json(reimbursementStatus); } catch (error: unknown) { - return next(error); + next(error); } } @@ -301,9 +301,9 @@ export default class ReimbursementRequestsController { req.currentUser, req.organization ); - return res.status(200).json(reimbursementStatus); + res.status(200).json(reimbursementStatus); } catch (error: unknown) { - return next(error); + next(error); } } @@ -316,24 +316,26 @@ export default class ReimbursementRequestsController { req.currentUser, req.organization ); - return res.status(200).json(updatedRequest); + res.status(200).json(updatedRequest); } catch (error: unknown) { - return next(error); + next(error); } } static async markReimbursementRequestAsDelivered(req: Request, res: Response, next: NextFunction) { try { const { requestId } = req.params; + const { dateDelivered } = req.body; const updatedRequest = await ReimbursementRequestService.markReimbursementRequestAsDelivered( req.currentUser, requestId, - req.organization + req.organization, + dateDelivered ); - return res.status(200).json(updatedRequest); + res.status(200).json(updatedRequest); } catch (error: unknown) { - return next(error); + next(error); } } @@ -346,9 +348,9 @@ export default class ReimbursementRequestsController { requestId, req.organization ); - return res.status(200).json(reimbursementRequest); + res.status(200).json(reimbursementRequest); } catch (error: unknown) { - return next(error); + next(error); } } @@ -363,9 +365,9 @@ export default class ReimbursementRequestsController { res.setHeader('content-length', imageData.buffer.length); // Send the Buffer as the response body - res.send(imageData.buffer); + res.status(200).send(imageData.buffer); } catch (error: unknown) { - return next(error); + next(error); } } @@ -383,9 +385,24 @@ export default class ReimbursementRequestsController { allowedRefundSources, req.organization ); - return res.status(200).json(accountCodeUpdated); + res.status(200).json(accountCodeUpdated); } catch (error: unknown) { - return next(error); + next(error); + } + } + + static async deleteAccountCode(req: Request, res: Response, next: NextFunction) { + try { + const { accountCodeId } = req.params; + + const deletedAccountCode = await ReimbursementRequestService.deleteAccountCode( + accountCodeId, + req.currentUser, + req.organization + ); + res.status(200).json(deletedAccountCode); + } catch (error: unknown) { + next(error); } } @@ -395,9 +412,9 @@ export default class ReimbursementRequestsController { const { name } = req.body; const editedVendor = await ReimbursementRequestService.editVendor(name, vendorId, req.currentUser, req.organization); - return res.status(200).json(editedVendor); + res.status(200).json(editedVendor); } catch (error: unknown) { - return next(error); + next(error); } } @@ -406,9 +423,9 @@ export default class ReimbursementRequestsController { const { vendorId } = req.params; const deletedVendor = await ReimbursementRequestService.deleteVendor(vendorId, req.currentUser, req.organization); - return res.status(200).json(deletedVendor); + res.status(200).json(deletedVendor); } catch (error: unknown) { - return next(error); + next(error); } } diff --git a/src/backend/src/controllers/slack.controllers.ts b/src/backend/src/controllers/slack.controllers.ts new file mode 100644 index 0000000000..e7336711d2 --- /dev/null +++ b/src/backend/src/controllers/slack.controllers.ts @@ -0,0 +1,18 @@ +import { getWorkspaceId } from '../integrations/slack'; +import OrganizationsService from '../services/organizations.services'; +import SlackServices from '../services/slack.services'; + +export default class SlackController { + static async processMessageEvent(event: any) { + try { + const organizations = await OrganizationsService.getAllOrganizations(); + const nerSlackWorkspaceId = await getWorkspaceId(); + const relatedOrganization = organizations.find((org) => org.slackWorkspaceId === nerSlackWorkspaceId); + if (relatedOrganization) { + SlackServices.processMessageSent(event, relatedOrganization.organizationId); + } + } catch (error: unknown) { + console.log(error); + } + } +} diff --git a/src/backend/src/controllers/tasks.controllers.ts b/src/backend/src/controllers/tasks.controllers.ts index 4046ad4bd3..bc79cfc152 100644 --- a/src/backend/src/controllers/tasks.controllers.ts +++ b/src/backend/src/controllers/tasks.controllers.ts @@ -20,9 +20,9 @@ export default class TasksController { req.organization ); - return res.status(200).json(task); + res.status(200).json(task); } catch (error: unknown) { - return next(error); + next(error); } } @@ -33,9 +33,9 @@ export default class TasksController { const updateTask = await TasksService.editTask(req.currentUser, taskId, title, notes, priority, deadline); - return res.status(200).json(updateTask); + res.status(200).json(updateTask); } catch (error: unknown) { - return next(error); + next(error); } } @@ -46,9 +46,9 @@ export default class TasksController { const updatedTask = await TasksService.editTaskStatus(req.currentUser, taskId, status); - return res.status(200).json(updatedTask); + res.status(200).json(updatedTask); } catch (error: unknown) { - return next(error); + next(error); } } @@ -59,9 +59,9 @@ export default class TasksController { const updatedTask = await TasksService.editTaskAssignees(req.currentUser, taskId, assignees, req.organization); - return res.status(200).json(updatedTask); + res.status(200).json(updatedTask); } catch (error: unknown) { - return next(error); + next(error); } } @@ -71,9 +71,9 @@ export default class TasksController { const updatedTask = await TasksService.deleteTask(req.currentUser, taskId, req.organization); - return res.status(200).json(updatedTask); + res.status(200).json(updatedTask); } catch (error: unknown) { - return next(error); + next(error); } } } diff --git a/src/backend/src/controllers/teams.controllers.ts b/src/backend/src/controllers/teams.controllers.ts index 881934896f..b2902aae6d 100644 --- a/src/backend/src/controllers/teams.controllers.ts +++ b/src/backend/src/controllers/teams.controllers.ts @@ -6,9 +6,9 @@ export default class TeamsController { try { const teams = await TeamsService.getAllTeams(req.organization); - return res.status(200).json(teams); + res.status(200).json(teams); } catch (error: unknown) { - return next(error); + next(error); } } @@ -18,9 +18,9 @@ export default class TeamsController { const team = await TeamsService.getSingleTeam(teamId, req.organization); - return res.status(200).json(team); + res.status(200).json(team); } catch (error: unknown) { - return next(error); + next(error); } } @@ -32,9 +32,9 @@ export default class TeamsController { const updateTeam = await TeamsService.setTeamMembers(req.currentUser, req.params.teamId, userIds, req.organization); // the updated team - return res.status(200).json(updateTeam); + res.status(200).json(updateTeam); } catch (error: unknown) { - return next(error); + next(error); } } @@ -43,9 +43,9 @@ export default class TeamsController { const { newDescription } = req.body; const team = await TeamsService.editDescription(req.currentUser, req.params.teamId, newDescription, req.organization); - return res.status(200).json(team); + res.status(200).json(team); } catch (error: unknown) { - return next(error); + next(error); } } @@ -55,9 +55,9 @@ export default class TeamsController { const { teamId } = req.params; const team = await TeamsService.setTeamHead(req.currentUser, teamId, userId, req.organization); - return res.status(200).json(team); + res.status(200).json(team); } catch (error: unknown) { - return next(error); + next(error); } } @@ -74,9 +74,9 @@ export default class TeamsController { isFinanceTeam, req.organization ); - return res.status(200).json(team); + res.status(200).json(team); } catch (error: unknown) { - return next(error); + next(error); } } @@ -86,9 +86,9 @@ export default class TeamsController { const { teamId } = req.params; const team = await TeamsService.setTeamLeads(req.currentUser, teamId, userIds, req.organization); - return res.status(200).json(team); + res.status(200).json(team); } catch (error: unknown) { - return next(error); + next(error); } } @@ -99,7 +99,7 @@ export default class TeamsController { await TeamsService.deleteTeam(req.currentUser, teamId, req.organization); res.status(204).json({ message: `Successfully deleted team with id ${teamId}` }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -108,9 +108,9 @@ export default class TeamsController { const { teamId } = req.params; const archivedTeam = await TeamsService.archiveTeam(req.currentUser, teamId, req.organization); - return res.status(200).json(archivedTeam); + res.status(200).json(archivedTeam); } catch (error: unknown) { - return next(error); + next(error); } } @@ -119,9 +119,9 @@ export default class TeamsController { const { name, iconName } = req.body; const createdTeamType = await TeamsService.createTeamType(req.currentUser, name, iconName, req.organization); - return res.status(200).json(createdTeamType); + res.status(200).json(createdTeamType); } catch (error: unknown) { - return next(error); + next(error); } } @@ -131,16 +131,16 @@ export default class TeamsController { const teamType = await TeamsService.getSingleTeamType(teamTypeId, req.organization); - return res.status(200).json(teamType); + res.status(200).json(teamType); } catch (error: unknown) { - return next(error); + next(error); } } static async getAllTeamTypes(req: Request, res: Response, next: NextFunction) { try { const teamTypes = await TeamsService.getAllTeamTypes(req.organization); - return res.status(200).json(teamTypes); + res.status(200).json(teamTypes); } catch (error: unknown) { return next(error); } @@ -153,9 +153,9 @@ export default class TeamsController { const updatedTeam = await TeamsService.setTeamType(req.currentUser, teamId, teamTypeId, req.organization); - return res.status(200).json(updatedTeam); + res.status(200).json(updatedTeam); } catch (error: unknown) { - return next(error); + next(error); } } } diff --git a/src/backend/src/controllers/users.controllers.ts b/src/backend/src/controllers/users.controllers.ts index dc2b3d88bf..8076e225d7 100644 --- a/src/backend/src/controllers/users.controllers.ts +++ b/src/backend/src/controllers/users.controllers.ts @@ -1,15 +1,16 @@ import { NextFunction, Request, Response } from 'express'; import UsersService from '../services/users.services'; import { AccessDeniedException } from '../utils/errors.utils'; +import { Task } from 'shared'; export default class UsersController { static async getAllUsers(_req: Request, res: Response, next: NextFunction) { try { const users = await UsersService.getAllUsers(); - return res.status(200).json(users); + res.status(200).json(users); } catch (error: unknown) { - return next(error); + next(error); } } @@ -19,9 +20,9 @@ export default class UsersController { const requestedUser = await UsersService.getSingleUser(userId, req.organization); - return res.status(200).json(requestedUser); + res.status(200).json(requestedUser); } catch (error: unknown) { - return next(error); + next(error); } } @@ -29,9 +30,9 @@ export default class UsersController { try { const settings = await UsersService.getUserSettings(req.currentUser.userId); - return res.status(200).json(settings); + res.status(200).json(settings); } catch (error: unknown) { - return next(error); + next(error); } } @@ -39,9 +40,9 @@ export default class UsersController { try { const secureSettings = await UsersService.getCurrentUserSecureSettings(req.currentUser); - return res.status(200).json(secureSettings); + res.status(200).json(secureSettings); } catch (error: unknown) { - return next(error); + next(error); } } @@ -49,9 +50,9 @@ export default class UsersController { try { const projects = await UsersService.getUsersFavoriteProjects(req.currentUser.userId, req.organization); - return res.status(200).json(projects); + res.status(200).json(projects); } catch (error: unknown) { - return next(error); + next(error); } } @@ -62,9 +63,9 @@ export default class UsersController { await UsersService.updateUserSettings(user, defaultTheme, slackId); - return res.status(200).json({ message: `Successfully updated settings for user ${user.userId}.` }); + res.status(200).json({ message: `Successfully updated settings for user ${user.userId}.` }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -76,9 +77,9 @@ export default class UsersController { const { user, token } = await UsersService.logUserIn(idToken, header!); res.cookie('token', token, { httpOnly: true, sameSite: 'none', secure: true }); - return res.status(200).json(user); + res.status(200).json(user); } catch (error: unknown) { - return next(error); + next(error); } } @@ -96,9 +97,9 @@ export default class UsersController { const user = await UsersService.logUserInDev(userId, header); - return res.status(200).json(user); + res.status(200).json(user); } catch (error: unknown) { - return next(error); + next(error); } } @@ -109,9 +110,9 @@ export default class UsersController { const targetUser = await UsersService.updateUserRole(userId, req.currentUser, role, req.organization); - return res.status(200).json(targetUser); + res.status(200).json(targetUser); } catch (error: unknown) { - return next(error); + next(error); } } @@ -121,9 +122,9 @@ export default class UsersController { const userSecureSettings = await UsersService.getUserSecureSetting(userId, req.currentUser, req.organization); - return res.status(200).json(userSecureSettings); + res.status(200).json(userSecureSettings); } catch (error: unknown) { - return next(error); + next(error); } } @@ -134,9 +135,9 @@ export default class UsersController { await UsersService.setUserSecureSettings(user, nuid, street, city, state, zipcode, phoneNumber); - return res.status(200).json({ message: `Successfully updated secure settings for user ${user.userId}.` }); + res.status(200).json({ message: `Successfully updated secure settings for user ${user.userId}.` }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -151,9 +152,9 @@ export default class UsersController { availability ); - return res.status(200).json(updatedScheduleSettings); + res.status(200).json(updatedScheduleSettings); } catch (error: unknown) { - return next(error); + next(error); } } @@ -162,9 +163,32 @@ export default class UsersController { const { userId } = req.params; const userScheduleSettings = await UsersService.getUserScheduleSettings(userId, req.currentUser); - return res.status(200).json(userScheduleSettings); + res.status(200).json(userScheduleSettings); } catch (error: unknown) { - return next(error); + next(error); + } + } + + static async getUserTasks(req: Request, res: Response, next: NextFunction) { + try { + const { userId } = req.params; + const { organization } = req; + + const userTasks = await UsersService.getUserTasks(userId, organization); + res.status(200).json(userTasks); + } catch (error: unknown) { + next(error); + } + } + + static async getManyUserTasks(req: Request, res: Response, next: NextFunction) { + try { + const { userIds } = req.body; + + const tasks: Task[] = await UsersService.getManyUserTasks(userIds, req.organization); + res.status(200).json(tasks); + } catch (error: unknown) { + next(error); } } } diff --git a/src/backend/src/controllers/work-package-templates.controllers.ts b/src/backend/src/controllers/work-package-templates.controllers.ts index 79718d2469..054fe2fcaf 100644 --- a/src/backend/src/controllers/work-package-templates.controllers.ts +++ b/src/backend/src/controllers/work-package-templates.controllers.ts @@ -26,9 +26,9 @@ export default class WorkPackageTemplatesController { req.organization ); - return res.status(200).json(workPackageTemplate); + res.status(200).json(workPackageTemplate); } catch (error: unknown) { - return next(error); + next(error); } } @@ -43,9 +43,9 @@ export default class WorkPackageTemplatesController { req.organization ); - return res.status(200).json(workPackageTemplate); + res.status(200).json(workPackageTemplate); } catch (error: unknown) { - return next(error); + next(error); } } // Get all work package templates @@ -56,9 +56,9 @@ export default class WorkPackageTemplatesController { req.organization ); - return res.status(200).json(workPackageTemplates); + res.status(200).json(workPackageTemplates); } catch (error: unknown) { - return next(error); + next(error); } } @@ -84,9 +84,9 @@ export default class WorkPackageTemplatesController { req.organization ); - return res.status(200).json(updatedWorkPackageTemplate); + res.status(200).json(updatedWorkPackageTemplate); } catch (error: unknown) { - return next(error); + next(error); } } @@ -96,11 +96,9 @@ export default class WorkPackageTemplatesController { const { workPackageTemplateId } = req.params; await WorkPackageTemplatesService.deleteWorkPackageTemplate(req.currentUser, workPackageTemplateId, req.organization); - return res - .status(200) - .json({ message: `Successfully deleted work package template #${req.params.workPackageTemplateId}` }); + res.status(200).json({ message: `Successfully deleted work package template #${req.params.workPackageTemplateId}` }); } catch (error: unknown) { - return next(error); + next(error); } } } diff --git a/src/backend/src/controllers/work-packages.controllers.ts b/src/backend/src/controllers/work-packages.controllers.ts index fbe1f8dbb4..2587c57e8e 100644 --- a/src/backend/src/controllers/work-packages.controllers.ts +++ b/src/backend/src/controllers/work-packages.controllers.ts @@ -11,9 +11,9 @@ export default class WorkPackagesController { const outputWorkPackages: WorkPackage[] = await WorkPackagesService.getAllWorkPackages(query, req.organization); - return res.status(200).json(outputWorkPackages); + res.status(200).json(outputWorkPackages); } catch (error: unknown) { - return next(error); + next(error); } } @@ -24,9 +24,9 @@ export default class WorkPackagesController { const wp: WorkPackage = await WorkPackagesService.getSingleWorkPackage(parsedWbs, req.organization); - return res.status(200).json(wp); + res.status(200).json(wp); } catch (error: unknown) { - return next(error); + next(error); } } @@ -35,9 +35,9 @@ export default class WorkPackagesController { const { wbsNums } = req.body; const workPackages: WorkPackage[] = await WorkPackagesService.getManyWorkPackages(wbsNums, req.organization); - return res.status(200).json(workPackages); + res.status(200).json(workPackages); } catch (error: unknown) { - return next(error); + next(error); } } @@ -61,9 +61,9 @@ export default class WorkPackagesController { req.organization ); - return res.status(200).json(workPackage); + res.status(200).json(workPackage); } catch (error: unknown) { - return next(error); + next(error); } } @@ -89,9 +89,9 @@ export default class WorkPackagesController { managerId, req.organization ); - return res.status(200).json({ message: 'Work package updated successfully' }); + res.status(200).json({ message: 'Work package updated successfully' }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -101,9 +101,9 @@ export default class WorkPackagesController { const wbsNum = validateWBS(req.params.wbsNum); await WorkPackagesService.deleteWorkPackage(req.currentUser, wbsNum, req.organization); - return res.status(200).json({ message: `Successfully deleted work package #${req.params.wbsNum}` }); + res.status(200).json({ message: `Successfully deleted work package #${req.params.wbsNum}` }); } catch (error: unknown) { - return next(error); + next(error); } } @@ -117,9 +117,9 @@ export default class WorkPackagesController { req.organization ); - return res.status(200).json(blockingWorkPackages); + res.status(200).json(blockingWorkPackages); } catch (error: unknown) { - return next(error); + next(error); } } @@ -130,7 +130,7 @@ export default class WorkPackagesController { await WorkPackagesService.slackMessageUpcomingDeadlines(req.currentUser, new Date(deadline), req.organization); } catch (error: unknown) { - return next(error); + next(error); } } } diff --git a/src/backend/src/integrations/slack.ts b/src/backend/src/integrations/slack.ts index a4c3f175ea..6e855acae7 100644 --- a/src/backend/src/integrations/slack.ts +++ b/src/backend/src/integrations/slack.ts @@ -155,4 +155,79 @@ const generateSlackTextBlock = (message: string, link?: string, linkButtonText?: }; }; +/** + * Given an id of a channel, produces the slack ids of all the users in that channel. + * @param channelId the id of the channel + * @returns an array of strings of all the slack ids of the users in the given channel + */ +export const getUsersInChannel = async (channelId: string) => { + let members: string[] = []; + let cursor: string | undefined; + + try { + do { + const response = await slack.conversations.members({ + channel: channelId, + cursor, + limit: 200 + }); + + if (response.ok && response.members) { + members = members.concat(response.members); + cursor = response.response_metadata?.next_cursor; + } else { + throw new Error(`Failed to fetch members: ${response.error}`); + } + } while (cursor); + + return members; + } catch (error) { + return members; + } +}; + +/** + * Given a slack channel id, produces the name of the channel + * @param channelId the id of the slack channel + * @returns the name of the channel or undefined if it cannot be found + */ +export const getChannelName = async (channelId: string) => { + try { + const channelRes = await slack.conversations.info({ channel: channelId }); + return channelRes.channel?.name; + } catch (error) { + return undefined; + } +}; + +/** + * Given a slack user id, prood.uces the name of the channel + * @param userId the id of the slack user + * @returns the name of the user (real name if no display name), undefined if cannot be found + */ +export const getUserName = async (userId: string) => { + try { + const userRes = await slack.users.info({ user: userId }); + return userRes.user?.profile?.display_name || userRes.user?.real_name; + } catch (error) { + return undefined; + } +}; + +/** + * Get the workspace id of the workspace this slack api is registered with + * @returns the id of the workspace + */ +export const getWorkspaceId = async () => { + try { + const response = await slack.auth.test(); + if (response.ok) { + return response.team_id; + } + throw new Error(response.error); + } catch (error) { + throw new HttpException(500, 'Error getting slack workspace id: ' + (error as any).data.error); + } +}; + export default slack; diff --git a/src/backend/src/prisma-query-args/announcements.query.args.ts b/src/backend/src/prisma-query-args/announcements.query.args.ts new file mode 100644 index 0000000000..b88c9fbf1d --- /dev/null +++ b/src/backend/src/prisma-query-args/announcements.query.args.ts @@ -0,0 +1,11 @@ +import { Prisma } from '@prisma/client'; +import { getUserQueryArgs } from './user.query-args'; + +export type AnnouncementQueryArgs = ReturnType; + +export const getAnnouncementQueryArgs = (organizationId: string) => + Prisma.validator()({ + include: { + usersReceived: getUserQueryArgs(organizationId) + } + }); diff --git a/src/backend/src/prisma-query-args/auth-user.query-args.ts b/src/backend/src/prisma-query-args/auth-user.query-args.ts index f99144f234..0c6db7bd94 100644 --- a/src/backend/src/prisma-query-args/auth-user.query-args.ts +++ b/src/backend/src/prisma-query-args/auth-user.query-args.ts @@ -1,4 +1,5 @@ import { Prisma } from '@prisma/client'; +import { getTeamQueryArgs } from './teams.query-args'; export type AuthUserQueryArgs = ReturnType; @@ -9,13 +10,15 @@ export const getAuthUserQueryArgs = (organizationId: string) => teamsAsHead: { where: { organizationId - } + }, + ...getTeamQueryArgs(organizationId) }, organizations: true, teamsAsLead: { where: { organizationId - } + }, + ...getTeamQueryArgs(organizationId) }, teamsAsMember: { where: { diff --git a/src/backend/src/prisma-query-args/pop-up.query-args.ts b/src/backend/src/prisma-query-args/pop-up.query-args.ts new file mode 100644 index 0000000000..0862956d22 --- /dev/null +++ b/src/backend/src/prisma-query-args/pop-up.query-args.ts @@ -0,0 +1,11 @@ +import { Prisma } from '@prisma/client'; +import { getUserQueryArgs } from './user.query-args'; + +export type PopUpQueryArgs = ReturnType; + +export const getPopUpQueryArgs = (organizationId: string) => + Prisma.validator()({ + include: { + users: getUserQueryArgs(organizationId) + } + }); diff --git a/src/backend/src/prisma/migrations/20241230221615_homepage_redesign/migration.sql b/src/backend/src/prisma/migrations/20241230221615_homepage_redesign/migration.sql new file mode 100644 index 0000000000..c62b11a4bb --- /dev/null +++ b/src/backend/src/prisma/migrations/20241230221615_homepage_redesign/migration.sql @@ -0,0 +1,79 @@ +-- AlterTable +ALTER TABLE "Organization" ADD COLUMN "logoImageId" TEXT, +ADD COLUMN "slackWorkspaceId" TEXT; + +-- AlterTable +ALTER TABLE "Project" ADD COLUMN "organizationId" TEXT; + +-- CreateTable +CREATE TABLE "Announcement" ( + "announcementId" TEXT NOT NULL, + "text" TEXT NOT NULL, + "dateMessageSent" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "dateDeleted" TIMESTAMP(3), + "senderName" TEXT NOT NULL, + "slackEventId" TEXT NOT NULL, + "slackChannelName" TEXT NOT NULL, + "organizationId" TEXT NOT NULL, + + CONSTRAINT "Announcement_pkey" PRIMARY KEY ("announcementId") +); + +-- CreateTable +CREATE TABLE "PopUp" ( + "popUpId" TEXT NOT NULL, + "text" TEXT NOT NULL, + "iconName" TEXT NOT NULL, + "eventLink" TEXT, + "organizationId" TEXT NOT NULL, + + CONSTRAINT "PopUp_pkey" PRIMARY KEY ("popUpId") +); + +-- CreateTable +CREATE TABLE "_receivedAnnouncements" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_userPopUps" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "Announcement_slackEventId_key" ON "Announcement"("slackEventId"); + +-- CreateIndex +CREATE UNIQUE INDEX "_receivedAnnouncements_AB_unique" ON "_receivedAnnouncements"("A", "B"); + +-- CreateIndex +CREATE INDEX "_receivedAnnouncements_B_index" ON "_receivedAnnouncements"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_userPopUps_AB_unique" ON "_userPopUps"("A", "B"); + +-- CreateIndex +CREATE INDEX "_userPopUps_B_index" ON "_userPopUps"("B"); + +-- AddForeignKey +ALTER TABLE "Project" ADD CONSTRAINT "Project_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Announcement" ADD CONSTRAINT "Announcement_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PopUp" ADD CONSTRAINT "PopUp_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_receivedAnnouncements" ADD CONSTRAINT "_receivedAnnouncements_A_fkey" FOREIGN KEY ("A") REFERENCES "Announcement"("announcementId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_receivedAnnouncements" ADD CONSTRAINT "_receivedAnnouncements_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_userPopUps" ADD CONSTRAINT "_userPopUps_A_fkey" FOREIGN KEY ("A") REFERENCES "PopUp"("popUpId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_userPopUps" ADD CONSTRAINT "_userPopUps_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/src/backend/src/prisma/schema.prisma b/src/backend/src/prisma/schema.prisma index 88d671804c..7bd7cb7fff 100644 --- a/src/backend/src/prisma/schema.prisma +++ b/src/backend/src/prisma/schema.prisma @@ -180,6 +180,8 @@ model User { deletedFrequentlyAskedQuestions FrequentlyAskedQuestion[] @relation(name: "frequentlyAskedQuestionDeleter") createdMilestones Milestone[] @relation(name: "milestoneCreator") deletedMilestones Milestone[] @relation(name: "milestoneDeleter") + unreadAnnouncements Announcement[] @relation(name: "receivedAnnouncements") + unreadPopUps PopUp[] @relation(name: "userPopUps") } model Role { @@ -874,7 +876,8 @@ model Organization { description String applyInterestImageId String? @unique exploreAsGuestImageId String? @unique - logoImage String? + logoImageId String? + slackWorkspaceId String? // Relation references wbsElements WBS_Element[] @@ -897,6 +900,8 @@ model Organization { FrequentlyAskedQuestions FrequentlyAskedQuestion[] Milestone Milestone[] featuredProjects Project[] + PopUps PopUp[] + Announcements Announcement[] } model FrequentlyAskedQuestion { @@ -927,3 +932,26 @@ model Milestone { organizationId String organization Organization @relation(fields: [organizationId], references: [organizationId]) } + +model Announcement { + announcementId String @id @default(uuid()) + text String + usersReceived User[] @relation("receivedAnnouncements") + dateMessageSent DateTime @default(now()) + dateDeleted DateTime? + senderName String + slackEventId String @unique + slackChannelName String + organizationId String + organization Organization @relation(fields: [organizationId], references: [organizationId]) +} + +model PopUp { + popUpId String @id @default(uuid()) + text String + iconName String + users User[] @relation("userPopUps") + eventLink String? + organizationId String + organization Organization @relation(fields: [organizationId], references: [organizationId]) +} diff --git a/src/backend/src/prisma/seed.ts b/src/backend/src/prisma/seed.ts index 5a583c2e38..709c398e6c 100644 --- a/src/backend/src/prisma/seed.ts +++ b/src/backend/src/prisma/seed.ts @@ -33,6 +33,7 @@ import { writeFileSync } from 'fs'; import WorkPackageTemplatesService from '../services/work-package-template.services'; import RecruitmentServices from '../services/recruitment.services'; import OrganizationsService from '../services/organizations.services'; +import AnnouncementService from '../services/announcement.service'; const prisma = new PrismaClient(); @@ -176,11 +177,11 @@ const performSeed: () => Promise = async () => { const glen = await createUser(dbSeedAllUsers.glen, RoleEnum.LEADERSHIP, organizationId); const shane = await createUser(dbSeedAllUsers.shane, RoleEnum.LEADERSHIP, organizationId); const june = await createUser(dbSeedAllUsers.june, RoleEnum.LEADERSHIP, organizationId); - const kevin = await createUser(dbSeedAllUsers.kevin, RoleEnum.LEADERSHIP, organizationId); - const norbury = await createUser(dbSeedAllUsers.norbury, RoleEnum.LEADERSHIP, organizationId); - const carr = await createUser(dbSeedAllUsers.carr, RoleEnum.LEADERSHIP, organizationId); - const trang = await createUser(dbSeedAllUsers.trang, RoleEnum.LEADERSHIP, organizationId); - const regina = await createUser(dbSeedAllUsers.regina, RoleEnum.LEADERSHIP, organizationId); + const kevin = await createUser(dbSeedAllUsers.kevin, RoleEnum.MEMBER, organizationId); + const norbury = await createUser(dbSeedAllUsers.norbury, RoleEnum.MEMBER, organizationId); + const carr = await createUser(dbSeedAllUsers.carr, RoleEnum.MEMBER, organizationId); + const trang = await createUser(dbSeedAllUsers.trang, RoleEnum.MEMBER, organizationId); + const regina = await createUser(dbSeedAllUsers.regina, RoleEnum.MEMBER, organizationId); await createUser(dbSeedAllUsers.spongebob, RoleEnum.GUEST, organizationId); await UsersService.updateUserRole(cyborg.userId, thomasEmrax, 'APP_ADMIN', ner); @@ -428,7 +429,7 @@ const performSeed: () => Promise = async () => { */ /** Project 1 */ - const { projectWbsNumber: project1WbsNumber } = await seedProject( + const { projectWbsNumber: project1WbsNumber, projectId: project1Id } = await seedProject( thomasEmrax, changeRequest1.crId, fergus.wbsElement.carNumber, @@ -456,7 +457,7 @@ const performSeed: () => Promise = async () => { ); /** Project 2 */ - const { projectWbsNumber: project2WbsNumber } = await seedProject( + const { projectWbsNumber: project2WbsNumber, projectId: project2Id } = await seedProject( thomasEmrax, changeRequest1.crId, fergus.wbsElement.carNumber, @@ -484,7 +485,7 @@ const performSeed: () => Promise = async () => { ); /** Project 3 */ - const { projectWbsNumber: project3WbsNumber } = await seedProject( + const { projectWbsNumber: project3WbsNumber, projectId: project3Id } = await seedProject( thomasEmrax, changeRequest1.crId, fergus.wbsElement.carNumber, @@ -512,7 +513,7 @@ const performSeed: () => Promise = async () => { ); /** Project 4 */ - const { projectWbsNumber: project4WbsNumber } = await seedProject( + const { projectWbsNumber: project4WbsNumber, projectId: project4Id } = await seedProject( thomasEmrax, changeRequest1.crId, fergus.wbsElement.carNumber, @@ -1869,6 +1870,8 @@ const performSeed: () => Promise = async () => { ner ); + await OrganizationsService.setFeaturedProjects([project1Id, project2Id, project3Id, project4Id], ner, thomasEmrax); + await OrganizationsService.setUsefulLinks(batman, organizationId, [ { linkId: '1', @@ -1891,6 +1894,36 @@ const performSeed: () => Promise = async () => { await RecruitmentServices.createFaq(batman, 'When was FinishLine created?', 'FinishLine was created in 2019', ner); await RecruitmentServices.createFaq(batman, 'How many developers are working on FinishLine?', '178 as of 2024', ner); + + await AnnouncementService.createAnnouncement( + 'Welcome to Finishline!', + [regina.userId], + new Date(), + 'Thomas Emrax', + '1', + 'software', + ner.organizationId + ); + + await AnnouncementService.createAnnouncement( + 'Welcome to Finishline!', + [regina.userId], + new Date(), + 'Damian', + '2', + 'mechanical', + ner.organizationId + ); + + await AnnouncementService.createAnnouncement( + 'Welcome to Finishline!', + [regina.userId], + new Date(), + 'Batman', + '3', + 'powertrain', + ner.organizationId + ); }; performSeed() diff --git a/src/backend/src/routes/announcements.routes.ts b/src/backend/src/routes/announcements.routes.ts new file mode 100644 index 0000000000..9a5cabc913 --- /dev/null +++ b/src/backend/src/routes/announcements.routes.ts @@ -0,0 +1,9 @@ +import express from 'express'; +import AnnouncementController from '../controllers/announcements.controllers'; + +const announcementsRouter = express.Router(); + +announcementsRouter.get('/current-user', AnnouncementController.getUserUnreadAnnouncements); +announcementsRouter.post('/:announcementId/remove', AnnouncementController.removeUserAnnouncement); + +export default announcementsRouter; diff --git a/src/backend/src/routes/onboarding.routes.ts b/src/backend/src/routes/onboarding.routes.ts new file mode 100644 index 0000000000..fabce68796 --- /dev/null +++ b/src/backend/src/routes/onboarding.routes.ts @@ -0,0 +1,8 @@ +import express from 'express'; +import OnboardingController from '../controllers/onboarding.controller'; + +const onboardingRouter = express.Router(); + +onboardingRouter.get('/image/:fileId', OnboardingController.downloadImage); + +export default onboardingRouter; diff --git a/src/backend/src/routes/organizations.routes.ts b/src/backend/src/routes/organizations.routes.ts index 0aca2dbfa3..991eb8f95f 100644 --- a/src/backend/src/routes/organizations.routes.ts +++ b/src/backend/src/routes/organizations.routes.ts @@ -1,11 +1,13 @@ import express from 'express'; -import { linkValidators, validateInputs } from '../utils/validation.utils'; -import OrganizationsController from '../controllers/organizations.controller'; +import { linkValidators, nonEmptyString, validateInputs } from '../utils/validation.utils'; +import OrganizationsController from '../controllers/organizations.controllers'; import multer, { memoryStorage } from 'multer'; +import { body } from 'express-validator'; const organizationRouter = express.Router(); const upload = multer({ limits: { fileSize: 30000000 }, storage: memoryStorage() }); +organizationRouter.get('/current', OrganizationsController.getCurrentOrganization); organizationRouter.post('/useful-links/set', ...linkValidators, validateInputs, OrganizationsController.setUsefulLinks); organizationRouter.get('/useful-links', OrganizationsController.getAllUsefulLinks); organizationRouter.post( @@ -18,4 +20,25 @@ organizationRouter.post( ); organizationRouter.get('/images', OrganizationsController.getOrganizationImages); +organizationRouter.post( + '/featured-projects/set', + body('projectIds').isArray(), + nonEmptyString(body('projectIds.*')), + validateInputs, + OrganizationsController.setOrganizationFeaturedProjects +); +organizationRouter.post('/logo/update', upload.single('logo'), OrganizationsController.setLogoImage); +organizationRouter.get('/logo', OrganizationsController.getOrganizationLogoImage); +organizationRouter.post( + '/description/set', + body('description').isString(), + validateInputs, + OrganizationsController.setOrganizationDescription +); +organizationRouter.get('/featured-projects', OrganizationsController.getOrganizationFeaturedProjects); +organizationRouter.post( + '/workspaceId/set', + nonEmptyString(body('workspaceId')), + OrganizationsController.setSlackWorkspaceId +); export default organizationRouter; diff --git a/src/backend/src/routes/pop-up.routes.ts b/src/backend/src/routes/pop-up.routes.ts new file mode 100644 index 0000000000..5ecaeff01f --- /dev/null +++ b/src/backend/src/routes/pop-up.routes.ts @@ -0,0 +1,9 @@ +import express from 'express'; +import PopUpsController from '../controllers/popUps.controllers'; + +const popUpsRouter = express.Router(); + +popUpsRouter.get('/current-user', PopUpsController.getUserUnreadPopUps); +popUpsRouter.post('/:popUpId/remove', PopUpsController.removeUserPopUps); + +export default popUpsRouter; diff --git a/src/backend/src/routes/reimbursement-requests.routes.ts b/src/backend/src/routes/reimbursement-requests.routes.ts index 578df36bb8..6d465db8ad 100644 --- a/src/backend/src/routes/reimbursement-requests.routes.ts +++ b/src/backend/src/routes/reimbursement-requests.routes.ts @@ -115,6 +115,8 @@ reimbursementRequestsRouter.post( ReimbursementRequestController.editAccountCode ); +reimbursementRequestsRouter.post('/account-codes/:accountCodeId/delete', ReimbursementRequestController.deleteAccountCode); + reimbursementRequestsRouter.post( '/reimburse', intMinZero(body('amount')), diff --git a/src/backend/src/routes/slack.routes.ts b/src/backend/src/routes/slack.routes.ts new file mode 100644 index 0000000000..6878b176b1 --- /dev/null +++ b/src/backend/src/routes/slack.routes.ts @@ -0,0 +1,8 @@ +import { createEventAdapter } from '@slack/events-api'; +import SlackController from '../controllers/slack.controllers'; + +export const slackEvents = createEventAdapter(process.env.SLACK_SIGNING_SECRET || ''); + +slackEvents.on('message', SlackController.processMessageEvent); + +slackEvents.on('error', console.log); diff --git a/src/backend/src/routes/teams.routes.ts b/src/backend/src/routes/teams.routes.ts index bf3f237c66..f0c6793f6a 100644 --- a/src/backend/src/routes/teams.routes.ts +++ b/src/backend/src/routes/teams.routes.ts @@ -39,7 +39,6 @@ teamsRouter.post( validateInputs, TeamsController.createTeam ); -teamsRouter.post('/:teamId/archive'); /**************** Team Type Section ****************/ diff --git a/src/backend/src/routes/users.routes.ts b/src/backend/src/routes/users.routes.ts index c9430121a1..2f95201f6f 100644 --- a/src/backend/src/routes/users.routes.ts +++ b/src/backend/src/routes/users.routes.ts @@ -46,5 +46,13 @@ userRouter.post( userRouter.get('/:userId/secure-settings', UsersController.getUserSecureSettings); userRouter.get('/:userId/schedule-settings', UsersController.getUserScheduleSettings); +userRouter.get('/:userId/tasks', UsersController.getUserTasks); +userRouter.post( + '/tasks/get-many', + body('userIds').isArray(), + nonEmptyString(body('userIds.*')), + validateInputs, + UsersController.getManyUserTasks +); export default userRouter; diff --git a/src/backend/src/services/announcement.service.ts b/src/backend/src/services/announcement.service.ts new file mode 100644 index 0000000000..6b5c758338 --- /dev/null +++ b/src/backend/src/services/announcement.service.ts @@ -0,0 +1,168 @@ +import { Announcement } from 'shared'; +import prisma from '../prisma/prisma'; +import { getAnnouncementQueryArgs } from '../prisma-query-args/announcements.query.args'; +import announcementTransformer from '../transformers/announcements.transformer'; +import { DeletedException, HttpException, NotFoundException } from '../utils/errors.utils'; + +export default class AnnouncementService { + /** + * Creates an announcement that is sent to users + * this data is populated from slack events + * @param text slack message text + * @param usersReceivedIds users to send announcements to + * @param dateMessageSent date created of slack message + * @param senderName name of user who sent slack message + * @param slackEventId id of slack event (provided by slack api) + * @param slackChannelName name of channel message was sent in + * @param organizationId id of organization of users + * @returns the created announcement + */ + static async createAnnouncement( + text: string, + usersReceivedIds: string[], + dateMessageSent: Date, + senderName: string, + slackEventId: string, + slackChannelName: string, + organizationId: string + ): Promise { + const announcement = await prisma.announcement.create({ + data: { + text, + usersReceived: { + connect: usersReceivedIds.map((id) => ({ + userId: id + })) + }, + dateMessageSent, + senderName, + slackEventId, + slackChannelName, + organizationId + }, + ...getAnnouncementQueryArgs(organizationId) + }); + + return announcementTransformer(announcement); + } + + static async updateAnnouncement( + text: string, + usersReceivedIds: string[], + senderName: string, + slackEventId: string, + slackChannelName: string, + organizationId: string + ): Promise { + const originalAnnouncement = await prisma.announcement.findUnique({ + where: { + slackEventId + } + }); + + if (!originalAnnouncement) throw new NotFoundException('Announcement', slackEventId); + + if (originalAnnouncement.dateDeleted) throw new DeletedException('Announcement', slackEventId); + + if (originalAnnouncement.organizationId !== organizationId) + throw new HttpException(400, `Announcement is not apart of the current organization`); + + const announcement = await prisma.announcement.update({ + where: { announcementId: originalAnnouncement.announcementId }, + data: { + text, + usersReceived: { + set: usersReceivedIds.map((id) => ({ + userId: id + })) + }, + slackEventId, + senderName, + slackChannelName + }, + ...getAnnouncementQueryArgs(organizationId) + }); + + return announcementTransformer(announcement); + } + + static async deleteAnnouncement(slackEventId: string, organizationId: string): Promise { + const originalAnnouncement = await prisma.announcement.findUnique({ + where: { + slackEventId + } + }); + + if (!originalAnnouncement) throw new NotFoundException('Announcement', slackEventId); + + if (originalAnnouncement.dateDeleted) throw new DeletedException('Announcement', slackEventId); + + if (originalAnnouncement.organizationId !== organizationId) + throw new HttpException(400, `Announcement is not apart of the current organization`); + + const announcement = await prisma.announcement.update({ + where: { slackEventId }, + data: { + dateDeleted: new Date(), + usersReceived: { + set: [] + } + }, + ...getAnnouncementQueryArgs(organizationId) + }); + + return announcementTransformer(announcement); + } + + /** + * Gets all of a user's unread announcements + * @param userId id of the current user + * @param organization the user's orgainzation + * @returns the unread announcements of the user + */ + static async getUserUnreadAnnouncements(userId: string, organizationId: string) { + const unreadAnnouncements = await prisma.announcement.findMany({ + where: { + dateDeleted: null, + usersReceived: { + some: { userId } + }, + organizationId + }, + ...getAnnouncementQueryArgs(organizationId) + }); + + if (!unreadAnnouncements) throw new HttpException(404, 'User Unread Announcements Not Found'); + + return unreadAnnouncements.map(announcementTransformer); + } + + /** + * Removes a announcement from the user's unread announcement + * @param userId id of the user to remove announcement from + * @param announcementId id of the announcement to remove + * @param organization the user's organization + * @returns the user's updated unread announcement + */ + static async removeUserAnnouncement(userId: string, announcementId: string, organizationId: string) { + const requestedUser = await prisma.user.findUnique({ + where: { userId } + }); + + if (!requestedUser) throw new NotFoundException('User', userId); + + const updatedUser = await prisma.user.update({ + where: { userId }, + data: { + unreadAnnouncements: { + disconnect: { + announcementId + } + } + }, + include: { unreadAnnouncements: getAnnouncementQueryArgs(organizationId) } + }); + + return updatedUser.unreadAnnouncements.map(announcementTransformer); + } +} diff --git a/src/backend/src/services/change-requests.services.ts b/src/backend/src/services/change-requests.services.ts index 4d4162dfe4..709f4b2e91 100644 --- a/src/backend/src/services/change-requests.services.ts +++ b/src/backend/src/services/change-requests.services.ts @@ -46,6 +46,7 @@ import { import { ChangeRequestQueryArgs, getChangeRequestQueryArgs } from '../prisma-query-args/change-requests.query-args'; import proposedSolutionTransformer from '../transformers/proposed-solutions.transformer'; import { getProposedSolutionQueryArgs } from '../prisma-query-args/proposed-solutions.query-args'; +import { sendCrRequestReviewPopUp, sendCrReviewedPopUp } from '../utils/pop-up.utils'; export default class ChangeRequestsService { /** @@ -132,7 +133,6 @@ export default class ChangeRequestsService { } else if (foundCR.type === CR_Type.ACTIVATION && foundCR.activationChangeRequest && accepted) { await this.reviewActivationChangeRequest(foundCR, reviewer); } - // finally we can update change request const updated = await prisma.change_Request.update({ where: { crId }, @@ -143,14 +143,15 @@ export default class ChangeRequestsService { dateReviewed: new Date() }, include: { - activationChangeRequest: true, - notificationSlackThreads: true, - wbsElement: { include: { workPackage: true } } + ...getChangeRequestQueryArgs(organization.organizationId).include, + notificationSlackThreads: true } }); - // send the creator of the cr a slack notification that their cr was reviewed - await sendCRSubmitterReviewedNotification(foundCR); + // send a notification to the submitter that their change request has been reviewed + await sendCRSubmitterReviewedNotification(updated); + + await sendCrReviewedPopUp(foundCR, updated.submitter, accepted, organization.organizationId); // send a reply to a CR's notifications of its updated status await sendSlackCRStatusToThread(updated.notificationSlackThreads, foundCR.crId, foundCR.identifier, accepted); @@ -1080,5 +1081,7 @@ export default class ChangeRequestsService { // send slack message to CR reviewers await sendSlackRequestedReviewNotification(newReviewers, changeRequestTransformer(foundCR)); + + await sendCrRequestReviewPopUp(foundCR, newReviewers, organization.organizationId); } } diff --git a/src/backend/src/services/design-reviews.services.ts b/src/backend/src/services/design-reviews.services.ts index 8f7511b73c..64363b0c61 100644 --- a/src/backend/src/services/design-reviews.services.ts +++ b/src/backend/src/services/design-reviews.services.ts @@ -39,6 +39,7 @@ import { getWorkPackageQueryArgs } from '../prisma-query-args/work-packages.quer import { UserWithSettings } from '../utils/auth.utils'; import { getUserScheduleSettingsQueryArgs } from '../prisma-query-args/user.query-args'; import { createCalendarEvent, deleteCalendarEvent, updateCalendarEvent } from '../utils/google-integration.utils'; +import { sendDrPopUp } from '../utils/pop-up.utils'; export default class DesignReviewsService { /** @@ -205,6 +206,8 @@ export default class DesignReviewsService { } } + await sendDrPopUp(designReview, members, submitter, wbsElement.name, organization.organizationId); + const project = wbsElement.workPackage?.project; const teams = project?.teams; if (teams && teams.length > 0) { diff --git a/src/backend/src/services/notifications.services.ts b/src/backend/src/services/notifications.services.ts index 88cd53e254..a443d93588 100644 --- a/src/backend/src/services/notifications.services.ts +++ b/src/backend/src/services/notifications.services.ts @@ -7,7 +7,7 @@ import { usersToSlackPings } from '../utils/notifications.utils'; import { sendMessage } from '../integrations/slack'; -import { daysBetween, wbsPipe } from 'shared'; +import { daysBetween, startOfDay, wbsPipe } from 'shared'; import { buildDueString } from '../utils/slack.utils'; import WorkPackagesService from './work-packages.services'; import { addWeeksToDate } from 'shared'; @@ -117,15 +117,14 @@ export default class NotificationsService { * Sends the design review slack notifications for all design reviews scheduled for today */ static async sendDesignReviewSlackNotifications() { - const endOfDay = startOfDayTomorrow(); - const startOfDay = new Date(); - startOfDay.setHours(0, 0, 0, 0); + const endOfToday = startOfDayTomorrow(); + const startOfToday = startOfDay(new Date()); const designReviews = await prisma.design_Review.findMany({ where: { dateScheduled: { - lt: endOfDay, - gte: startOfDay + lt: endOfToday, + gte: startOfToday }, status: 'SCHEDULED', dateDeleted: null diff --git a/src/backend/src/services/onboarding.services.ts b/src/backend/src/services/onboarding.services.ts new file mode 100644 index 0000000000..b351952bf9 --- /dev/null +++ b/src/backend/src/services/onboarding.services.ts @@ -0,0 +1,11 @@ +import { NotFoundException } from '../utils/errors.utils'; +import { downloadImageFile } from '../utils/google-integration.utils'; + +export default class OnboardingServices { + static async downloadImage(fileId: string) { + const fileData = await downloadImageFile(fileId); + + if (!fileData) throw new NotFoundException('Image File', fileId); + return fileData; + } +} diff --git a/src/backend/src/services/organizations.services.ts b/src/backend/src/services/organizations.services.ts index 689ff6a1bc..53c118086c 100644 --- a/src/backend/src/services/organizations.services.ts +++ b/src/backend/src/services/organizations.services.ts @@ -1,14 +1,45 @@ import { Organization, User } from '@prisma/client'; import { LinkCreateArgs, isAdmin } from 'shared'; import prisma from '../prisma/prisma'; -import { AccessDeniedAdminOnlyException, NotFoundException } from '../utils/errors.utils'; +import { AccessDeniedAdminOnlyException, HttpException, DeletedException, NotFoundException } from '../utils/errors.utils'; import { userHasPermission } from '../utils/users.utils'; import { createUsefulLinks } from '../utils/organizations.utils'; import { linkTransformer } from '../transformers/links.transformer'; import { getLinkQueryArgs } from '../prisma-query-args/links.query-args'; import { uploadFile } from '../utils/google-integration.utils'; +import { getProjects } from '../utils/projects.utils'; +import { getProjectQueryArgs } from '../prisma-query-args/projects.query-args'; +import projectTransformer from '../transformers/projects.transformer'; export default class OrganizationsService { + /** + * Retrieve all the organizations + * @returns an array of every organization + */ + static async getAllOrganizations(): Promise { + return prisma.organization.findMany(); + } + + /** + * Gets the current organization + * @param organizationId the organizationId to be fetched + */ + static async getCurrentOrganization(organizationId: string) { + const organization = await prisma.organization.findUnique({ + where: { organizationId } + }); + + if (!organization) { + throw new NotFoundException('Organization', organizationId); + } + + if (organization.dateDeleted) { + throw new DeletedException('Organization', organizationId); + } + + return organization; + } + /** * sets an organizations useful links * @param submitter the user who is setting the links @@ -131,4 +162,144 @@ export default class OrganizationsService { exploreAsGuestImage: organization.exploreAsGuestImageId }; } + + /** + * Updates the featured projects of an organization + * @param projectIds project ids of featured projects + * @param organization user's organization + * @param submitter user submitting featured projects + * @returns updated organization with featured projects + */ + static async setFeaturedProjects(projectIds: string[], organization: Organization, submitter: User) { + if (!(await userHasPermission(submitter.userId, organization.organizationId, isAdmin))) + throw new AccessDeniedAdminOnlyException('update featured projects'); + + //throws if all projects are not found + const featuredProjects = await getProjects(projectIds, organization.organizationId); + + const updatedOrg = await prisma.organization.update({ + where: { organizationId: organization.organizationId }, + data: { + featuredProjects: { + set: featuredProjects.map((project) => ({ projectId: project.projectId })) + } + }, + include: { featuredProjects: true } + }); + + return updatedOrg; + } + + /** + * Sets the logo for an organization, User must be admin + * @param logoImage the image which will be uploaded and have its id stored in the org + * @param submitter the user submitting the logo + * @param organization the organization who's logo is being set + * @returns the updated organization + * @throws if the user is not an admin + */ + static async setLogoImage( + logoImage: Express.Multer.File, + submitter: User, + organization: Organization + ): Promise { + if (!(await userHasPermission(submitter.userId, organization.organizationId, isAdmin))) { + throw new AccessDeniedAdminOnlyException('update logo'); + } + + const logoImageData = await uploadFile(logoImage); + + if (!logoImageData?.name) { + throw new HttpException(500, 'Image Name not found'); + } + + const updatedOrg = await prisma.organization.update({ + where: { organizationId: organization.organizationId }, + data: { + logoImageId: logoImageData.id + } + }); + + return updatedOrg; + } + + /** + * Gets the logo image of the organization + * @param organizationId the id of the organization + * @returns the id of the image + */ + static async getLogoImage(organizationId: string): Promise { + const organization = await prisma.organization.findUnique({ + where: { organizationId } + }); + + if (!organization) { + throw new NotFoundException('Organization', organizationId); + } + + return organization.logoImageId; + } + + /** + * Sets the description of a given organization. + * @param description the new description + * @param submitter the user making the change (must be admin) + * @param organization the organization whos description is changing + * @throws if the user is not an admin + */ + static async setOrganizationDescription( + description: string, + submitter: User, + organization: Organization + ): Promise { + if (!(await userHasPermission(submitter.userId, organization.organizationId, isAdmin))) { + throw new AccessDeniedAdminOnlyException('set description'); + } + const updatedOrg = prisma.organization.update({ + where: { + organizationId: organization.organizationId + }, + data: { + description + } + }); + return updatedOrg; + } + + /** + * Gets the featured projects for the given organization Id + * @param organizationId the organization to get the projects for + * @returns all the featured projects for the organization + */ + static async getOrganizationFeaturedProjects(organizationId: string) { + const organization = await prisma.organization.findUnique({ + where: { organizationId }, + include: { featuredProjects: getProjectQueryArgs(organizationId) } + }); + + if (!organization) { + throw new NotFoundException('Organization', organizationId); + } + + return organization.featuredProjects.map(projectTransformer); + } + + /** + * sets the slack workspace id of the organization + * @param workspaceId workspace id to set + * @param submitter user who submitted the workspace id + * @param organizationId id of organization to update with workspace id + * @returns updated organization + */ + static async setSlackWorkspaceId(workspaceId: string, submitter: User, organizationId: string) { + if (!(await userHasPermission(submitter.userId, organizationId, isAdmin))) { + throw new AccessDeniedAdminOnlyException('set workspace id'); + } + const updatedOrg = await prisma.organization.update({ + where: { organizationId }, + data: { slackWorkspaceId: workspaceId } + }); + + return updatedOrg; + } } diff --git a/src/backend/src/services/pop-up.services.ts b/src/backend/src/services/pop-up.services.ts new file mode 100644 index 0000000000..61bba89bd0 --- /dev/null +++ b/src/backend/src/services/pop-up.services.ts @@ -0,0 +1,102 @@ +import { getPopUpQueryArgs } from '../prisma-query-args/pop-up.query-args'; +import prisma from '../prisma/prisma'; +import popUpTransformer from '../transformers/pop-up.transformer'; +import { HttpException, NotFoundException } from '../utils/errors.utils'; + +export class PopUpService { + /** + * Gets all of a user's unread pop up + * @param userId id of user to get unread pop up from + * @param organization the user's orgainzation + * @returns the unread pop up of the user + */ + static async getUserUnreadPopUps(userId: string, organizationId: string) { + const unreadPopUps = await prisma.popUp.findMany({ + where: { + users: { + some: { userId } + }, + organizationId + }, + ...getPopUpQueryArgs(organizationId) + }); + + if (!unreadPopUps) throw new HttpException(404, 'User Unread Notifications Not Found'); + + return unreadPopUps.map(popUpTransformer); + } + + /** + * Removes a pop up from the user's unread pop up + * @param userId id of the current user + * @param popUpId id of the pop up to remove + * @param organization the user's organization + * @returns the user's updated unread pop up + */ + static async removeUserPopUp(userId: string, popUpId: string, organizationId: string) { + const updatedUser = await prisma.user.update({ + where: { userId }, + data: { + unreadPopUps: { + disconnect: { + popUpId + } + } + }, + include: { unreadPopUps: getPopUpQueryArgs(organizationId) } + }); + + if (!updatedUser) throw new HttpException(404, `Failed to remove notication: ${popUpId}`); + + return updatedUser.unreadPopUps.map(popUpTransformer); + } + + /** + * Creates and sends a pop up to all users with the given userIds + * @param text writing in the pop up + * @param iconName icon that appears in the pop up + * @param userIds ids of users to send the pop up to + * @param organizationId + * @param eventLink link the pop up will go to when clicked + * @returns the created notification + */ + static async sendPopUpToUsers( + text: string, + iconName: string, + userIds: string[], + organizationId: string, + eventLink?: string + ) { + const createdPopUp = await prisma.popUp.create({ + data: { + text, + iconName, + eventLink, + organizationId + }, + ...getPopUpQueryArgs(organizationId) + }); + + if (!createdPopUp) throw new HttpException(500, 'Failed to create notification'); + + const popUpPromises = userIds.map(async (userId) => { + const requestedUser = await prisma.user.findUnique({ + where: { userId } + }); + + if (!requestedUser) throw new NotFoundException('User', userId); + + return await prisma.user.update({ + where: { userId: requestedUser.userId }, + data: { + unreadPopUps: { + connect: { popUpId: createdPopUp.popUpId } + } + } + }); + }); + + await Promise.all(popUpPromises); + return popUpTransformer(createdPopUp); + } +} diff --git a/src/backend/src/services/recruitment.services.ts b/src/backend/src/services/recruitment.services.ts index 76376ca04f..39b1ecae13 100644 --- a/src/backend/src/services/recruitment.services.ts +++ b/src/backend/src/services/recruitment.services.ts @@ -106,7 +106,7 @@ export default class RecruitmentServices { */ static async getAllFaqs(organization: Organization) { const allFaqs = await prisma.frequentlyAskedQuestion.findMany({ - where: { organizationId: organization.organizationId } + where: { dateDeleted: null, organizationId: organization.organizationId } }); return allFaqs; diff --git a/src/backend/src/services/reimbursement-requests.services.ts b/src/backend/src/services/reimbursement-requests.services.ts index 2378208978..6f7052106c 100644 --- a/src/backend/src/services/reimbursement-requests.services.ts +++ b/src/backend/src/services/reimbursement-requests.services.ts @@ -18,7 +18,8 @@ import { WbsReimbursementProductCreateArgs, OtherReimbursementProductCreateArgs, AccountCode, - ReimbursementStatus + ReimbursementStatus, + startOfDay } from 'shared'; import prisma from '../prisma/prisma'; import { @@ -669,6 +670,31 @@ export default class ReimbursementRequestService { return accountCodeUpdated; } + /** + * Deletes the Account Code with the given id + * + * @param accountCodeId the requested account code to be deleted + * @param submitter the user deleting the account code + * @param organizationId the organization the user is currently in + * @returns the 'deleted' account code + */ + static async deleteAccountCode(accountCodeId: string, submitter: User, organization: Organization) { + await isUserAdminOrOnFinance(submitter, organization.organizationId); + + const accountCode = await ReimbursementRequestService.getSingleAccountCode(accountCodeId, organization); + + if (accountCode.dateDeleted) { + throw new DeletedException('Account Code', accountCodeId); + } + + const deletedAccountCode = await prisma.account_Code.update({ + where: { accountCodeId: accountCode.accountCodeId }, + data: { dateDeleted: new Date() } + }); + + return accountCodeTransformer(deletedAccountCode); + } + /** * Service function to upload a picture to the receipts folder in the NER google drive * @param reimbursementRequestId id for the reimbursement request we're tying the receipt to @@ -761,6 +787,7 @@ export default class ReimbursementRequestService { * @param submitter The User marking the request as delivered * @param requestId The ID of the reimbursement request to be marked as delivered * @param organizationId The organization the user is currently in + * @param dateDelivered The date the reimbursed items were delivered * @throws NotFoundException if the id is invalid or not there * @throws AccessDeniedException if the creator of the request is not the submitter * @returns the updated reimbursement request @@ -768,7 +795,8 @@ export default class ReimbursementRequestService { static async markReimbursementRequestAsDelivered( submitter: User, reimbursementRequestId: string, - organization: Organization + organization: Organization, + dateDelivered: Date ) { const reimbursementRequest = await prisma.reimbursement_Request.findUnique({ where: { reimbursementRequestId } @@ -781,12 +809,14 @@ export default class ReimbursementRequestService { throw new AccessDeniedException('Only the creator of the reimbursement request can mark as delivered'); if (reimbursementRequest.organizationId !== organization.organizationId) throw new InvalidOrganizationException('Reimbursement Request'); + if (reimbursementRequest.dateOfExpense && startOfDay(dateDelivered) < startOfDay(reimbursementRequest.dateOfExpense)) + throw new HttpException(400, 'Items cannot be delivered before the expense date.'); + if (startOfDay(dateDelivered) > startOfDay(new Date())) + throw new HttpException(400, 'Delivery date cannot be in the future.'); const reimbursementRequestDelivered = await prisma.reimbursement_Request.update({ where: { reimbursementRequestId }, - data: { - dateDelivered: new Date() - } + data: { dateDelivered } }); return reimbursementRequestDelivered; diff --git a/src/backend/src/services/slack.services.ts b/src/backend/src/services/slack.services.ts new file mode 100644 index 0000000000..f6ece7ba85 --- /dev/null +++ b/src/backend/src/services/slack.services.ts @@ -0,0 +1,169 @@ +import { getChannelName, getUserName } from '../integrations/slack'; +import AnnouncementService from './announcement.service'; +import { Announcement } from 'shared'; +import prisma from '../prisma/prisma'; +import { blockToMentionedUsers, blockToString } from '../utils/slack.utils'; +import { NotFoundException } from '../utils/errors.utils'; + +/** + * Represents a slack event for a message in a channel. + */ +export interface SlackMessageEvent { + type: 'message'; + subtype?: string; + channel: string; + event_ts: string; + channel_type: string; + [key: string]: any; +} + +/** + * Represents a slack message event for a standard sent message. + */ +export interface SlackMessage extends SlackMessageEvent { + user: string; + client_msg_id: string; + text: string; + blocks: { + type: string; + block_id: string; + elements: any[]; + }[]; +} + +/** + * Represents a slack message event for a deleted message. + */ +export interface SlackDeletedMessage extends SlackMessageEvent { + subtype: 'message_deleted'; + previous_message: SlackMessage; +} + +/** + * Represents a slack message event for an edited message. + */ +export interface SlackUpdatedMessage extends SlackMessageEvent { + subtype: 'message_changed'; + message: SlackMessage; + previous_message: SlackMessage; +} + +/** + * Represents a block of information within a message. These blocks with an array + * make up all the information needed to represent the content of a message. + */ +export interface SlackRichTextBlock { + type: 'broadcast' | 'color' | 'channel' | 'date' | 'emoji' | 'link' | 'text' | 'user' | 'usergroup'; + range?: string; + value?: string; + channel_id?: string; + timestamp?: number; + name?: string; + unicode?: string; + url?: string; + text?: string; + user_id?: string; + usergroup_id?: string; +} + +export default class SlackServices { + /** + * Given a slack event representing a message in a channel, + * make the appropriate announcement change in prisma. + * @param event the slack event that will be processed + * @param organizationId the id of the organization represented by the slack api + * @returns an annoucement if an announcement was processed and created/modified/deleted + */ + static async processMessageSent(event: SlackMessageEvent, organizationId: string): Promise { + //get the name of the channel from the slack api + const slackChannelName: string = (await getChannelName(event.channel)) ?? `Unknown_Channel:${event.channel}`; + const dateCreated = new Date(1000 * Number(event.event_ts)); + + //get the message that will be processed either as the event or within a subtype + let eventMessage: SlackMessage; + + if (event.subtype) { + switch (event.subtype) { + case 'message_deleted': + //delete the message using the client_msg_id + eventMessage = (event as SlackDeletedMessage).previous_message; + return AnnouncementService.deleteAnnouncement(eventMessage.client_msg_id, organizationId); + case 'message_changed': + eventMessage = (event as SlackUpdatedMessage).message; + break; + default: + //other events that do not effect announcements + return; + } + } else { + eventMessage = event as SlackMessage; + } + + //loop through the blocks of the meta data while accumulating the + //text and users notified + let messageText = ''; + let userIdsToNotify: string[] = []; + + //get the name of the user that sent the message from slack + let userName = (await getUserName(eventMessage.user)) ?? ''; + + //if slack could not produce the name of the user, look for their name in prisma + if (!userName) { + try { + const userWithThatSlackId = await prisma.user.findFirst({ where: { userSettings: { slackId: eventMessage.user } } }); + userName = `${userWithThatSlackId?.firstName} ${userWithThatSlackId?.lastName}`; + } catch { + userName = 'Unknown_User:' + eventMessage.user; + } + } + + //pull out the blocks of data from the metadata within the message event + const richTextBlocks = eventMessage.blocks?.filter((eventBlock: any) => eventBlock.type === 'rich_text'); + + if (richTextBlocks && richTextBlocks.length > 0 && richTextBlocks[0].elements.length > 0) { + for (const element of richTextBlocks[0].elements[0].elements) { + messageText += await blockToString(element); + userIdsToNotify = userIdsToNotify.concat(await blockToMentionedUsers(element, organizationId, event.channel)); + } + } else { + return; + } + + //get rid of duplicates within the users to notify + userIdsToNotify = [...new Set(userIdsToNotify)]; + + //if no users are notified, disregard the message + if (userIdsToNotify.length === 0) { + return; + } + + if (event.subtype === 'message_changed') { + //try to edit the announcement, if no announcement with that id exists create a new announcement + try { + return await AnnouncementService.updateAnnouncement( + messageText, + userIdsToNotify, + userName, + eventMessage.client_msg_id, + slackChannelName, + organizationId + ); + } catch (error) { + //if couldn't find the announcement to edit, create a new one below + if (!(error instanceof NotFoundException)) { + throw error; + } + } + } + + return await AnnouncementService.createAnnouncement( + messageText, + userIdsToNotify, + dateCreated, + userName, + eventMessage.client_msg_id, + slackChannelName, + organizationId + ); + } +} diff --git a/src/backend/src/services/users.services.ts b/src/backend/src/services/users.services.ts index c77292053b..d786c04137 100644 --- a/src/backend/src/services/users.services.ts +++ b/src/backend/src/services/users.services.ts @@ -36,6 +36,8 @@ import { } from '../prisma-query-args/user.query-args'; import { getAuthUserQueryArgs } from '../prisma-query-args/auth-user.query-args'; import authenticatedUserTransformer from '../transformers/auth-user.transformer'; +import { getTaskQueryArgs } from '../prisma-query-args/tasks.query-args'; +import taskTransformer from '../transformers/tasks.transformer'; export default class UsersService { /** @@ -197,14 +199,6 @@ export default class UsersService { } }); - if (!payload['given_name']) { - throw new HttpException(400, 'First Name was not Found on Google Account'); - } - - if (!payload['family_name']) { - throw new HttpException(400, 'Last Name was not Found on Google Account'); - } - if (!payload['email']) { throw new HttpException(400, 'Email was not Found on Google Account'); } @@ -214,10 +208,13 @@ export default class UsersService { const emailId = payload['email']!.includes('@husky.neu.edu') ? payload['email']!.split('@')[0] : null; const organization = await prisma.organization.findFirst(); + const firstName = payload['given_name'] ?? payload['email']!.split('@')[0]; // Defaults to id of email + const lastName = payload['family_name'] ?? ''; // Defaults to no last name + const createdUser = await prisma.user.create({ data: { - firstName: payload['given_name'], - lastName: payload['family_name'], + firstName, + lastName, googleAuthId: userId, email: payload['email'], emailId, @@ -538,4 +535,35 @@ export default class UsersService { return userScheduleSettingsTransformer(newUserScheduleSettings); } + + /** + * Get's a user's assigned tasks + * @param userId the id of the user who's tasks are being returned + * @param organization the user's organization + * @returns a list of the user's assigned tasks + */ + static async getUserTasks(userId: string, organization: Organization) { + const requestedUser = await prisma.user.findUnique({ + where: { userId }, + include: { assignedTasks: getTaskQueryArgs(organization.organizationId) } + }); + if (!requestedUser) throw new NotFoundException('User', userId); + + return requestedUser.assignedTasks.map(taskTransformer); + } + + /** + * Get all tasks from a list of userIds + * @param userIds list of users to get the tasks from + * @param organization the users' organization + * @returns a list of tasks of the given users + */ + static async getManyUserTasks(userIds: string[], organization: Organization) { + const tasksPromises = userIds.map(async (userId) => { + return UsersService.getUserTasks(userId, organization); + }); + + const resolvedTasks = await Promise.all(tasksPromises); + return resolvedTasks.flat(); + } } diff --git a/src/backend/src/transformers/announcements.transformer.ts b/src/backend/src/transformers/announcements.transformer.ts new file mode 100644 index 0000000000..8b43031390 --- /dev/null +++ b/src/backend/src/transformers/announcements.transformer.ts @@ -0,0 +1,14 @@ +import { Prisma } from '@prisma/client'; +import { AnnouncementQueryArgs } from '../prisma-query-args/announcements.query.args'; +import { Announcement } from 'shared'; +import { userTransformer } from './user.transformer'; + +const announcementTransformer = (announcement: Prisma.AnnouncementGetPayload): Announcement => { + return { + ...announcement, + usersReceived: announcement.usersReceived.map(userTransformer), + dateDeleted: announcement.dateDeleted ?? undefined + }; +}; + +export default announcementTransformer; diff --git a/src/backend/src/transformers/auth-user.transformer.ts b/src/backend/src/transformers/auth-user.transformer.ts index ed49204c54..06bab93740 100644 --- a/src/backend/src/transformers/auth-user.transformer.ts +++ b/src/backend/src/transformers/auth-user.transformer.ts @@ -6,6 +6,7 @@ import { isAuthUserOnFinance } from '../utils/reimbursement-requests.utils'; import { Prisma } from '@prisma/client'; +import teamTransformer from './teams.transformer'; const authenticatedUserTransformer = ( user: Prisma.UserGetPayload, @@ -26,7 +27,9 @@ const authenticatedUserTransformer = ( isAtLeastFinanceLead: isAuthUserAtLeastLeadForFinance(user), changeRequestsToReviewId: user.changeRequestsToReview.map((changeRequest) => changeRequest.crId), organizations: user.organizations.map((organization) => organization.organizationId), - currentOrganization: user.organizations.find((organization) => organization.organizationId === organizationId) + currentOrganization: user.organizations.find((organization) => organization.organizationId === organizationId), + teamsAsHead: user.teamsAsHead.map(teamTransformer), + teamsAsLead: user.teamsAsLead.map(teamTransformer) }; }; diff --git a/src/backend/src/transformers/pop-up.transformer.ts b/src/backend/src/transformers/pop-up.transformer.ts new file mode 100644 index 0000000000..1be7e4ec68 --- /dev/null +++ b/src/backend/src/transformers/pop-up.transformer.ts @@ -0,0 +1,12 @@ +import { Prisma } from '@prisma/client'; +import { PopUpQueryArgs } from '../prisma-query-args/pop-up.query-args'; +import { PopUp } from 'shared'; + +const popUpTransformer = (popUp: Prisma.PopUpGetPayload): PopUp => { + return { + ...popUp, + eventLink: popUp.eventLink ?? undefined + }; +}; + +export default popUpTransformer; diff --git a/src/backend/src/utils/auth.utils.ts b/src/backend/src/utils/auth.utils.ts index e8f647e57e..277010b66d 100644 --- a/src/backend/src/utils/auth.utils.ts +++ b/src/backend/src/utils/auth.utils.ts @@ -31,7 +31,8 @@ export const requireJwtProd = (req: Request, res: Response, next: NextFunction) if ( req.path === '/users/auth/login' || // logins dont have cookies yet req.path === '/' || // base route is available so aws can listen and check the health - req.method === 'OPTIONS' // this is a pre-flight request and those don't send cookies + req.method === 'OPTIONS' || // this is a pre-flight request and those don't send cookies + req.path === '/slack' // slack http endpoint is only used from slack api ) { return next(); } else if ( @@ -41,18 +42,18 @@ export const requireJwtProd = (req: Request, res: Response, next: NextFunction) } else { const { token } = req.cookies; - if (!token) return res.status(401).json({ message: 'Authentication Failed: Cookie not found!' }); - - jwt.verify(token, TOKEN_SECRET, (err: VerifyErrors | null, decoded: string | JwtPayload | undefined) => { - if (err) return res.status(401).json({ message: 'Authentication Failed: Invalid JWT!' }); - - if (!decoded || typeof decoded === 'string') { - return res.status(401).json({ message: 'Authentication Failed: Invalid JWT payload!' }); - } - res.locals.userId = decoded.userId; - - return next(); - }); + if (!token) res.status(401).json({ message: 'Authentication Failed: Cookie not found!' }); + else { + jwt.verify(token, TOKEN_SECRET, (err: VerifyErrors | null, decoded: string | JwtPayload | undefined) => { + if (err) res.status(401).json({ message: 'Authentication Failed: Invalid JWT!' }); + else if (!decoded || typeof decoded === 'string') { + res.status(401).json({ message: 'Authentication Failed: Invalid JWT payload!' }); + } else { + res.locals.userId = decoded.userId; + next(); + } + }); + } } }; @@ -62,7 +63,8 @@ export const requireJwtDev = (req: Request, res: Response, next: NextFunction) = req.path === '/users/auth/login/dev' || // logins dont have cookies yet req.path === '/' || // base route is available so aws can listen and check the health req.method === 'OPTIONS' || // this is a pre-flight request and those don't send cookies - req.path === '/users' // dev login needs the list of users to log in + req.path === '/users' || // dev login needs the list of users to log in + req.path === '/slack' // slack http endpoint is only used from slack api ) { next(); } else if ( @@ -72,11 +74,12 @@ export const requireJwtDev = (req: Request, res: Response, next: NextFunction) = } else { const devUserId = req.headers.authorization; - if (!devUserId) return res.status(401).json({ message: 'Authentication Failed: Not logged in (dev)!' }); - - res.locals.userId = devUserId; + if (!devUserId) res.status(401).json({ message: 'Authentication Failed: Not logged in (dev)!' }); + else { + res.locals.userId = devUserId; - return next(); + next(); + } } }; @@ -171,7 +174,8 @@ export const getUserAndOrganization = async (req: Request, res: Response, next: req.path === '/users/auth/login/dev' || req.path === '/' || // base route is available so aws can listen and check the health req.method === 'OPTIONS' || // this is a pre-flight request and those don't send cookies - req.path === '/users' // dev login needs the list of users to log in + req.path === '/users' || // dev login needs the list of users to log in + req.path === '/slack' // slack http endpoint is only used from slack api ) { return next(); } diff --git a/src/backend/src/utils/change-requests.utils.ts b/src/backend/src/utils/change-requests.utils.ts index ef6415dd98..9f3cee0c0d 100644 --- a/src/backend/src/utils/change-requests.utils.ts +++ b/src/backend/src/utils/change-requests.utils.ts @@ -562,7 +562,12 @@ export const sendCRSubmitterReviewedNotification = async ( const creatorUserSettings = await prisma.user_Settings.findUnique({ where: { userId: foundCR.submitterId } }); if (creatorUserSettings && creatorUserSettings.slackId) { try { - await sendSlackCRReviewedNotification(creatorUserSettings.slackId, foundCR.crId, foundCR.identifier); + await sendSlackCRReviewedNotification( + creatorUserSettings.slackId, + foundCR.crId, + foundCR.identifier, + foundCR.reviewNotes + ); } catch (err: unknown) { if (err instanceof Error) { throw new HttpException(500, `Failed to send slack notification: ${err.message}`); diff --git a/src/backend/src/utils/errors.utils.ts b/src/backend/src/utils/errors.utils.ts index ce4c3415e1..9f6b5dc7ad 100644 --- a/src/backend/src/utils/errors.utils.ts +++ b/src/backend/src/utils/errors.utils.ts @@ -138,4 +138,5 @@ export type ExceptionObjectNames = | 'Organization' | 'Car' | 'Milestone' - | 'Faq'; + | 'Faq' + | 'Announcement'; diff --git a/src/backend/src/utils/pop-up.utils.ts b/src/backend/src/utils/pop-up.utils.ts new file mode 100644 index 0000000000..30c0fecdf0 --- /dev/null +++ b/src/backend/src/utils/pop-up.utils.ts @@ -0,0 +1,69 @@ +import { Change_Request, Design_Review, User } from '@prisma/client'; +import { PopUpService } from '../services/pop-up.services'; + +/** + * Sends a pop up that a design review was scheduled + * @param designReview dr that was created + * @param members optional and required members of the dr + * @param submitter the user who created the dr + * @param workPackageName the name of the work package associated witht the dr + * @param organizationId id of the organization of the dr + */ +export const sendDrPopUp = async ( + designReview: Design_Review, + members: User[], + submitter: User, + workPackageName: string, + organizationId: string +) => { + const designReviewLink = `/settings/preferences?drId=${designReview.designReviewId}`; + + const msg = `Design Review for ${workPackageName} is being scheduled by ${submitter.firstName} ${submitter.lastName}`; + await PopUpService.sendPopUpToUsers( + msg, + 'calendar_month', + members.map((member) => member.userId), + organizationId, + designReviewLink + ); +}; + +/** + * Sends a pop up that a change request was reviewed + * @param changeRequest cr that was requested review + * @param submitter the user who submitted the cr + * @param accepted true if the cr changes were accepted, false if denied + * @param organizationId id of the organization of the cr + */ +export const sendCrReviewedPopUp = async ( + changeRequest: Change_Request, + submitter: User, + accepted: boolean, + organizationId: string +) => { + const changeRequestLink = `/change-requests/${changeRequest.crId}`; + await PopUpService.sendPopUpToUsers( + `CR #${changeRequest.identifier} has been ${accepted ? 'approved!' : 'denied.'}`, + accepted ? 'check_circle' : 'cancel', + [submitter.userId], + organizationId, + changeRequestLink + ); +}; + +/** + * Sends a finishline pop up to all requested reviewers of a change request + * @param changeRequest cr that was requested review + * @param reviewers user's reviewing the cr + * @param organizationId id of the organization of the cr + */ +export const sendCrRequestReviewPopUp = async (changeRequest: Change_Request, reviewers: User[], organizationId: string) => { + const changeRequestLink = `/change-requests/${changeRequest.crId}`; + await PopUpService.sendPopUpToUsers( + `Your review has been requested on CR #${changeRequest.identifier}`, + 'edit_note', + reviewers.map((reviewer) => reviewer.userId), + organizationId, + changeRequestLink + ); +}; diff --git a/src/backend/src/utils/projects.utils.ts b/src/backend/src/utils/projects.utils.ts index 7256468e7d..22becc4e89 100644 --- a/src/backend/src/utils/projects.utils.ts +++ b/src/backend/src/utils/projects.utils.ts @@ -1,7 +1,7 @@ -import { WBS_Element_Status } from '@prisma/client'; +import { Project, WBS_Element_Status } from '@prisma/client'; import prisma from '../prisma/prisma'; import { DescriptionBulletPreview, LinkCreateArgs, WbsElementStatus } from 'shared'; -import { DeletedException, NotFoundException } from './errors.utils'; +import { DeletedException, HttpException, NotFoundException } from './errors.utils'; import { ChangeCreateArgs, createChange, createListChanges, getDescriptionBulletChanges } from './changes.utils'; import { DescriptionBulletDestination, addRawDescriptionBullets, editDescriptionBullets } from './description-bullets.utils'; import { linkToChangeListValue, updateLinks } from './links.utils'; @@ -9,6 +9,10 @@ import { getLinkQueryArgs } from '../prisma-query-args/links.query-args'; import { getDescriptionBulletQueryArgs } from '../prisma-query-args/description-bullets.query-args'; import { getProjectQueryArgs } from '../prisma-query-args/projects.query-args'; +export type ProjectWithId = { + projectId: String; +}; + /** * calculate the project's status based on its workpacakges' status * @param proj a given project to be calculated on its status @@ -213,3 +217,32 @@ export const checkMaterialInputs = async ( if (!unit) throw new NotFoundException('Unit', unitName); } }; + +/** + * Produce a array of primsa formated projectIDs, given the array of Project + * @param projectIds the projectIds to get as users + * @returns projectIds in prisma format + */ +export const getProjects = async (projectIds: string[], organizationId: string) => { + const projects = await prisma.project.findMany({ + where: { projectId: { in: projectIds } }, + ...getProjectQueryArgs(organizationId) + }); + + validateFoundProjects(projects, projectIds); + + return projects; +}; + +/** + * Validates that the projects found in the database match the given projectIds + * @param projects the projects found in the database + * @param projectIds the requested projectIds to retrieve + */ +const validateFoundProjects = (projects: Project[], projectIds: string[]) => { + if (projects.length !== projectIds.length) { + const primsaProjectIds = projects.map((project) => project.projectId); + const missingProjectIds = projectIds.filter((id) => !primsaProjectIds.includes(id)); + throw new HttpException(404, `Projects(s) with the following ids not found: ${missingProjectIds.join(', ')}`); + } +}; diff --git a/src/backend/src/utils/reimbursement-requests.utils.ts b/src/backend/src/utils/reimbursement-requests.utils.ts index efc553644b..84a5b3373d 100644 --- a/src/backend/src/utils/reimbursement-requests.utils.ts +++ b/src/backend/src/utils/reimbursement-requests.utils.ts @@ -12,7 +12,8 @@ import { isAdmin, wbsPipe, WbsReimbursementProductCreateArgs, - ReimbursementStatusType + ReimbursementStatusType, + isHead } from 'shared'; import prisma from '../prisma/prisma'; import { AccessDeniedException, DeletedException, HttpException, NotFoundException } from './errors.utils'; @@ -369,8 +370,8 @@ export const isUserAdminOrOnFinance = async (submitter: User, organizationId: st try { await validateUserIsPartOfFinanceTeamOrAdmin(submitter, organizationId); } catch (error) { - if (!(await userHasPermission(submitter.userId, organizationId, isAdmin))) { - throw new AccessDeniedException('Only Admins, Finance Team Leads, or Heads can edit vendors'); + if (!(await userHasPermission(submitter.userId, organizationId, isHead))) { + throw new AccessDeniedException('Only Admins, Finance Team Leads, or Heads can access this endpoint'); } } }; diff --git a/src/backend/src/utils/slack.utils.ts b/src/backend/src/utils/slack.utils.ts index 8ac008d259..4019c6d6db 100644 --- a/src/backend/src/utils/slack.utils.ts +++ b/src/backend/src/utils/slack.utils.ts @@ -1,6 +1,14 @@ import { ChangeRequest, daysBetween, Task, UserPreview, wbsPipe, calculateEndDate } from 'shared'; import { User } from '@prisma/client'; -import { editMessage, reactToMessage, replyToMessageInThread, sendMessage } from '../integrations/slack'; +import { + editMessage, + getChannelName, + getUserName, + getUsersInChannel, + reactToMessage, + replyToMessageInThread, + sendMessage +} from '../integrations/slack'; import { getUserFullName, getUserSlackId } from './users.utils'; import prisma from '../prisma/prisma'; import { HttpException } from './errors.utils'; @@ -11,6 +19,8 @@ import { addHours, meetingStartTimePipe } from './design-reviews.utils'; import { WorkPackageQueryArgs } from '../prisma-query-args/work-packages.query-args'; import { Prisma } from '@prisma/client'; import { userTransformer } from '../transformers/user.transformer'; +import { SlackRichTextBlock } from '../services/slack.services'; +import UsersService from '../services/users.services'; interface SlackMessageThread { messageInfoId: string; @@ -396,10 +406,17 @@ export const sendDRScheduledSlackNotif = async ( } }; -export const sendSlackCRReviewedNotification = async (slackId: string, crId: string, identifier: number) => { +export const sendSlackCRReviewedNotification = async ( + slackId: string, + crId: string, + identifier: number, + comments: string | null +) => { if (process.env.NODE_ENV !== 'production') return; // don't send msgs unless in prod const msgs = []; - const fullMsg = `:tada: Your Change Request was just reviewed! Click the link to view! :tada:`; + const fullMsg = `:tada: Your Change Request was just reviewed!${ + comments ? `\n Comments: ${comments}` : '' + }\nClick the link to view! :tada:`; const fullLink = `https://finishlinebyner.com/cr/${crId}`; const btnText = `View CR#${identifier}`; msgs.push(sendMessage(slackId, fullMsg, fullLink, btnText)); @@ -463,3 +480,99 @@ export const addSlackThreadsToChangeRequest = async (crId: string, threads: { ch ); await Promise.all(promises); }; + +/** + * Converts a SlackRichTextBlock into a string representation for an announcement. + * @param block the block of information from slack + * @returns the string that will be combined with other block's strings to create the announcement + */ +export const blockToString = async (block: SlackRichTextBlock) => { + switch (block.type) { + case 'broadcast': + return '@' + block.range; + case 'color': + return block.value ?? ''; + case 'channel': + //channels are represented as an id, get the name from the slack api + const channelName: string = + (await getChannelName(block.channel_id ?? '')) ?? `ISSUE PARSING CHANNEL:${block.channel_id}`; + return '#' + channelName; + case 'date': + return new Date(block.timestamp ?? 0).toISOString(); + case 'emoji': + //if the emoji is a unicode emoji, convert the unicode to a string, + //if it is a slack emoji just use the name of the emoji + if (block.unicode) { + return String.fromCodePoint(parseInt(block.unicode, 16)); + } + return 'emoji:' + block.name; + case 'link': + if (block.text) { + return `${block.text}:(${block.url})`; + } + return block.url ?? ''; + case 'text': + return block.text ?? ''; + case 'user': + //users are represented as an id, get the name of the user from the slack api + const userName: string = (await getUserName(block.user_id ?? '')) ?? `Unknown User:${block.user_id}`; + return '@' + userName; + case 'usergroup': + return `usergroup:${block.usergroup_id}`; + } +}; + +/** + * Gets the users notified in a specific SlackRichTextBlock. + * @param block the block that may contain mentioned user/users + * @param orgainzationId the id of the organization corresponding to this slack channel + * @param channelId the id of the channel that the block is being sent in + * @returns an array of prisma user ids of users to be notified + */ +export const blockToMentionedUsers = async ( + block: SlackRichTextBlock, + organizationId: string, + channelId: string +): Promise => { + switch (block.type) { + case 'broadcast': + switch (block.range) { + case 'everyone': + const usersInOrg = await UsersService.getAllUsers(organizationId); + return usersInOrg.map((user) => user.userId); + case 'channel': + case 'here': + //@here behaves the same as @channel; notifies all the users in that channel + const slackIds: string[] = await getUsersInChannel(channelId); + const prismaIds: (string | undefined)[] = await Promise.all(slackIds.map(getUserIdFromSlackId)); + return prismaIds.filter((id): id is string => id !== undefined); + default: + return []; + } + case 'user': + const prismaId = await getUserIdFromSlackId(block.user_id ?? ''); + return prismaId ? [prismaId] : []; + default: + //only broadcasts and specific user mentions add recievers to announcements + return []; + } +}; + +/** + * given a slack id, produce the user id of the corresponding user + * @param slackId the slack id in the settings of the user + * @returns the user id, or undefined if no users were found + */ +export const getUserIdFromSlackId = async (slackId: string): Promise => { + const user = await prisma.user.findFirst({ + where: { + userSettings: { + slackId + } + } + }); + + if (!user) return undefined; + + return user.userId; +}; diff --git a/src/backend/src/utils/teams.utils.ts b/src/backend/src/utils/teams.utils.ts index 087ebc37ad..8fb7c7ce21 100644 --- a/src/backend/src/utils/teams.utils.ts +++ b/src/backend/src/utils/teams.utils.ts @@ -1,5 +1,7 @@ -import { Prisma, User, Team } from '@prisma/client'; +import { Prisma, User, Team, Project } from '@prisma/client'; +import prisma from '../prisma/prisma'; import { UserWithSettings } from './auth.utils'; +import { NotFoundException } from './errors.utils'; const teamQueryArgsMembersOnly = Prisma.validator()({ include: { @@ -88,3 +90,23 @@ export const removeUsersFromList = (currentUsers: UserWithId[], usersToRemove: U const userIdsToRemove = usersToRemove.map((user) => user.userId); return currentUsers.filter((user) => !userIdsToRemove.includes(user.userId)); }; + +/** + * Given a team id, produces all of the projects assigned to that team + * @param teamId the id of the team + * @returns array of projects currently assigned to the given team (errors if no team is found) + */ +export const getTeamProjects = async (teamId: string): Promise => { + const team = await prisma.team.findUnique({ + where: { + teamId + }, + include: { + projects: true + } + }); + if (!team) { + throw new NotFoundException('Team', teamId); + } + return team.projects; +}; diff --git a/src/backend/src/utils/validation.utils.ts b/src/backend/src/utils/validation.utils.ts index 39c7fdce94..6e0e4d753f 100644 --- a/src/backend/src/utils/validation.utils.ts +++ b/src/backend/src/utils/validation.utils.ts @@ -181,10 +181,11 @@ export const projectValidators = [ nonEmptyString(body('managerId').optional()) ]; -export const validateInputs = (req: Request, res: Response, next: Function): Response | void => { +export const validateInputs = (req: Request, res: Response, next: Function): void => { const errors = validationResult(req); if (!errors.isEmpty()) { - return res.status(400).json({ errors: errors.array() }); + res.status(400).json({ errors: errors.array() }); + } else { + next(); } - next(); }; diff --git a/src/backend/tests/integration/slackMessages.test.ts b/src/backend/tests/integration/slackMessages.test.ts new file mode 100644 index 0000000000..703db97c1a --- /dev/null +++ b/src/backend/tests/integration/slackMessages.test.ts @@ -0,0 +1,399 @@ +import { Organization, User } from '@prisma/client'; +import { createSlackMessageEvent, createTestOrganization, createTestUser, resetUsers } from '../test-utils'; +import { + batmanAppAdmin, + batmanSettings, + supermanAdmin, + supermanSettings, + wonderwomanGuest, + wonderwomanSettings +} from '../test-data/users.test-data'; +import * as apiFunctions from '../../src/integrations/slack'; +import AnnouncementService from '../../src/services/announcement.service'; +import slackServices from '../../src/services/slack.services'; +import { vi } from 'vitest'; +import prisma from '../../src/prisma/prisma'; + +vi.mock('../../src/integrations/slack', async (importOriginal) => { + return { + ...(await importOriginal()), + getUserName: vi.fn(), + getChannelName: vi.fn(), + getUsersInChannel: vi.fn() + }; +}); + +describe('Slack message tests', () => { + let orgId: string; + let organization: Organization; + let batman: User; + let superman: User; + let wonderwoman: User; + + beforeEach(async () => { + await resetUsers(); + organization = await createTestOrganization(); + orgId = organization.organizationId; + batman = await createTestUser(batmanAppAdmin, orgId, batmanSettings); + superman = await createTestUser(supermanAdmin, orgId, supermanSettings); + wonderwoman = await createTestUser(wonderwomanGuest, orgId, wonderwomanSettings); + await prisma.organization.update({ + where: { + organizationId: orgId + }, + data: { + users: { + set: [{ userId: batman.userId }, { userId: superman.userId }, { userId: wonderwoman.userId }] + } + } + }); + }); + + afterEach(async () => { + await resetUsers(); + vi.clearAllMocks(); + }); + + it('adds message to everyone with @everyone', async () => { + vi.mocked(apiFunctions.getUserName).mockReturnValue(Promise.resolve('Slack User Name')); + vi.mocked(apiFunctions.getChannelName).mockReturnValue(Promise.resolve('Slack Channel Name')); + + const spy = vi.spyOn(AnnouncementService, 'createAnnouncement'); + + const announcement = await slackServices.processMessageSent( + createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [ + { type: 'text', text: 'test with ' }, + { type: 'broadcast', range: 'everyone' }, + { type: 'text', text: ' broadcast (@everyone)' } + ]), + orgId + ); + + expect(spy).toBeCalledTimes(1); + expect(spy).toBeCalledWith( + 'test with @everyone broadcast (@everyone)', + [batman.userId, superman.userId, wonderwoman.userId], + new Date(1000), + 'Slack User Name', + 'id_1', + 'Slack Channel Name', + orgId + ); + + expect(announcement?.text).toBe('test with @everyone broadcast (@everyone)'); + expect(announcement?.dateMessageSent.toDateString()).toBe(new Date(1000).toDateString()); + expect(announcement?.senderName).toBe('Slack User Name'); + expect(announcement?.slackChannelName).toBe('Slack Channel Name'); + expect(announcement?.slackEventId).toBe('id_1'); + expect(announcement?.usersReceived).toHaveLength(3); + }); + + it('Adds message to people in channel with @channel and @mention (w/o duplicates)', async () => { + vi.mocked(apiFunctions.getUserName).mockReturnValue(Promise.resolve('Slack User Name')); + vi.mocked(apiFunctions.getChannelName).mockReturnValue(Promise.resolve('Slack Channel Name')); + vi.mocked(apiFunctions.getUsersInChannel).mockReturnValue(Promise.resolve(['slack', 'slackWW'])); + + const spy = vi.spyOn(AnnouncementService, 'createAnnouncement'); + + const announcement = await slackServices.processMessageSent( + createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [ + { type: 'text', text: 'test with ' }, + { type: 'broadcast', range: 'channel' }, + { type: 'text', text: ' broadcast (@channel)' }, + { type: 'user', user_id: 'slackWW' }, + { type: 'user', user_id: 'slackSM' } + ]), + orgId + ); + + expect(spy).toBeCalledTimes(1); + expect(spy).toBeCalledWith( + 'test with @channel broadcast (@channel)@Slack User Name@Slack User Name', + [batman.userId, wonderwoman.userId, superman.userId], + new Date(1000), + 'Slack User Name', + 'id_1', + 'Slack Channel Name', + orgId + ); + + expect(announcement?.text).toBe('test with @channel broadcast (@channel)@Slack User Name@Slack User Name'); + expect(announcement?.dateMessageSent.toDateString()).toBe(new Date(1000).toDateString()); + expect(announcement?.senderName).toBe('Slack User Name'); + expect(announcement?.slackChannelName).toBe('Slack Channel Name'); + expect(announcement?.slackEventId).toBe('id_1'); + expect(announcement?.usersReceived).toHaveLength(3); + }); + + it('Sends the announcement to a single person with a mention', async () => { + vi.mocked(apiFunctions.getUserName).mockReturnValue(Promise.resolve('Slack User Name')); + vi.mocked(apiFunctions.getChannelName).mockReturnValue(Promise.resolve('Slack Channel Name')); + + const spy = vi.spyOn(AnnouncementService, 'createAnnouncement'); + + const announcement = await slackServices.processMessageSent( + createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [ + { type: 'text', text: 'test with ' }, + { type: 'user', user_id: 'slackWW' }, + { type: 'text', text: ' broadcast (@wonderwoman)' } + ]), + orgId + ); + + expect(spy).toBeCalledTimes(1); + expect(spy).toBeCalledWith( + 'test with @Slack User Name broadcast (@wonderwoman)', + [wonderwoman.userId], + new Date(1000), + 'Slack User Name', + 'id_1', + 'Slack Channel Name', + orgId + ); + + expect(announcement?.text).toBe('test with @Slack User Name broadcast (@wonderwoman)'); + expect(announcement?.dateMessageSent.toDateString()).toBe(new Date(1000).toDateString()); + expect(announcement?.senderName).toBe('Slack User Name'); + expect(announcement?.slackChannelName).toBe('Slack Channel Name'); + expect(announcement?.slackEventId).toBe('id_1'); + expect(announcement?.usersReceived).toHaveLength(1); + }); + + it('Correctly processes other types of blocks', async () => { + vi.mocked(apiFunctions.getUserName).mockReturnValue(Promise.resolve('Slack User Name')); + vi.mocked(apiFunctions.getChannelName).mockReturnValue(Promise.resolve('Slack Channel Name')); + + const spy = vi.spyOn(AnnouncementService, 'createAnnouncement'); + + const announcement = await slackServices.processMessageSent( + createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [ + { type: 'text', text: 'test with: ' }, + { type: 'link', url: 'http://www.example.com', text: 'link' }, + { type: 'text', text: 'Italics', style: { italic: true } }, + { type: 'text', text: ' and a unicode emoji: ' }, + { + type: 'emoji', + name: 'stuck_out_tongue_closed_eyes', + unicode: '1f61d' + }, + { type: 'text', text: ' and a slack emoji: ' }, + { + type: 'emoji', + name: 'birthday-parrot' + }, + { type: 'user', user_id: 'slackWW' } + ]), + orgId + ); + + expect(spy).toBeCalledTimes(1); + expect(spy).toBeCalledWith( + 'test with: link:(http://www.example.com)Italics and a unicode emoji: 😝 and a slack emoji: emoji:birthday-parrot@Slack User Name', + [wonderwoman.userId], + new Date(1000), + 'Slack User Name', + 'id_1', + 'Slack Channel Name', + orgId + ); + + expect(announcement?.text).toBe( + 'test with: link:(http://www.example.com)Italics and a unicode emoji: 😝 and a slack emoji: emoji:birthday-parrot@Slack User Name' + ); + expect(announcement?.dateMessageSent.toDateString()).toBe(new Date(1000).toDateString()); + expect(announcement?.senderName).toBe('Slack User Name'); + expect(announcement?.slackChannelName).toBe('Slack Channel Name'); + expect(announcement?.slackEventId).toBe('id_1'); + expect(announcement?.usersReceived).toHaveLength(1); + }); + + it("Doesn't create an announcement if no one is mentioned", async () => { + vi.mocked(apiFunctions.getUserName).mockReturnValue(Promise.resolve('Slack User Name')); + vi.mocked(apiFunctions.getChannelName).mockReturnValue(Promise.resolve('Slack Channel Name')); + + const spy = vi.spyOn(AnnouncementService, 'createAnnouncement'); + + const announcement = await slackServices.processMessageSent( + createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [{ type: 'text', text: 'just a text message' }]), + orgId + ); + + expect(spy).toBeCalledTimes(0); + + expect(announcement).toBeUndefined(); + }); + + it('Updates an edit made to a message', async () => { + vi.mocked(apiFunctions.getUserName).mockReturnValue(Promise.resolve('Slack User Name')); + vi.mocked(apiFunctions.getChannelName).mockReturnValue(Promise.resolve('Slack Channel Name')); + + const createSpy = vi.spyOn(AnnouncementService, 'createAnnouncement'); + const updateSpy = vi.spyOn(AnnouncementService, 'updateAnnouncement'); + + await slackServices.processMessageSent( + createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [{ type: 'user', user_id: 'slackWW' }]), + orgId + ); + expect(createSpy).toBeCalledWith( + '@Slack User Name', + [wonderwoman.userId], + new Date(1000), + 'Slack User Name', + 'id_1', + 'Slack Channel Name', + orgId + ); + + const announcement2 = await slackServices.processMessageSent( + { + type: 'message', + subtype: 'message_changed', + channel: 'channel id', + event_ts: '1', + channel_type: 'channel', + message: createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [ + { type: 'user', user_id: 'slackWW' }, + { type: 'text', text: ' added text' } + ]), + previous_message: createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [ + { type: 'user', user_id: 'slackWW' } + ]) + }, + orgId + ); + + expect(updateSpy).toBeCalledWith( + '@Slack User Name added text', + [wonderwoman.userId], + 'Slack User Name', + 'id_1', + 'Slack Channel Name', + orgId + ); + + expect(announcement2?.text).toBe('@Slack User Name added text'); + expect(announcement2?.dateMessageSent.toDateString()).toBe(new Date(1000).toDateString()); + expect(announcement2?.senderName).toBe('Slack User Name'); + expect(announcement2?.slackChannelName).toBe('Slack Channel Name'); + expect(announcement2?.slackEventId).toBe('id_1'); + expect(announcement2?.usersReceived).toHaveLength(1); + + expect(createSpy).toBeCalledTimes(1); + expect(updateSpy).toBeCalledTimes(1); + }); + + it('Creates a new announcement if the announcement to update is not found', async () => { + vi.mocked(apiFunctions.getUserName).mockReturnValue(Promise.resolve('Slack User Name')); + vi.mocked(apiFunctions.getChannelName).mockReturnValue(Promise.resolve('Slack Channel Name')); + + const createSpy = vi.spyOn(AnnouncementService, 'createAnnouncement'); + const updateSpy = vi.spyOn(AnnouncementService, 'updateAnnouncement'); + + const announcement2 = await slackServices.processMessageSent( + { + type: 'message', + subtype: 'message_changed', + channel: 'channel id', + event_ts: '1', + channel_type: 'channel', + message: createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [ + { type: 'user', user_id: 'slackWW' }, + { type: 'text', text: ' added text' } + ]), + previous_message: createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [ + { type: 'user', user_id: 'slackWW' } + ]) + }, + orgId + ); + + expect(updateSpy).toBeCalledWith( + '@Slack User Name added text', + [wonderwoman.userId], + 'Slack User Name', + 'id_1', + 'Slack Channel Name', + orgId + ); + + expect(createSpy).toBeCalledWith( + '@Slack User Name added text', + [wonderwoman.userId], + new Date(1000), + 'Slack User Name', + 'id_1', + 'Slack Channel Name', + orgId + ); + + expect(announcement2?.text).toBe('@Slack User Name added text'); + expect(announcement2?.dateMessageSent.toDateString()).toBe(new Date(1000).toDateString()); + expect(announcement2?.senderName).toBe('Slack User Name'); + expect(announcement2?.slackChannelName).toBe('Slack Channel Name'); + expect(announcement2?.slackEventId).toBe('id_1'); + expect(announcement2?.usersReceived).toHaveLength(1); + + expect(createSpy).toBeCalledTimes(1); + expect(updateSpy).toBeCalledTimes(1); + }); + + it('Creates and deletes and announcement', async () => { + vi.mocked(apiFunctions.getUserName).mockReturnValue(Promise.resolve('Slack User Name')); + vi.mocked(apiFunctions.getChannelName).mockReturnValue(Promise.resolve('Slack Channel Name')); + + const createSpy = vi.spyOn(AnnouncementService, 'createAnnouncement'); + const deleteSpy = vi.spyOn(AnnouncementService, 'deleteAnnouncement'); + + await slackServices.processMessageSent( + createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [{ type: 'user', user_id: 'slackWW' }]), + orgId + ); + expect(createSpy).toBeCalledWith( + '@Slack User Name', + [wonderwoman.userId], + new Date(1000), + 'Slack User Name', + 'id_1', + 'Slack Channel Name', + orgId + ); + + await slackServices.processMessageSent( + { + type: 'message', + subtype: 'message_deleted', + channel: 'channel id', + event_ts: '1', + channel_type: 'channel', + previous_message: createSlackMessageEvent('channel id', '1', 'user name', 'id_1', [ + { type: 'user', user_id: 'slackWW' } + ]) + }, + orgId + ); + expect(createSpy).toBeCalledTimes(1); + expect(deleteSpy).toBeCalledTimes(1); + expect(deleteSpy).toBeCalledWith('id_1', orgId); + }); + + it('Does nothing if recieves other message subtype', async () => { + vi.mocked(apiFunctions.getUserName).mockReturnValue(Promise.resolve('Slack User Name')); + vi.mocked(apiFunctions.getChannelName).mockReturnValue(Promise.resolve('Slack Channel Name')); + + const createSpy = vi.spyOn(AnnouncementService, 'createAnnouncement'); + + const announcement = await slackServices.processMessageSent( + { + type: 'message', + subtype: 'other-nonprocessed-subtype', + channel: 'channel id', + event_ts: '1', + channel_type: 'channel', + bogus_data: 'other data' + }, + orgId + ); + expect(createSpy).toBeCalledTimes(0); + expect(announcement).toBeUndefined(); + }); +}); diff --git a/src/backend/tests/test-utils.ts b/src/backend/tests/test-utils.ts index cd823bdc73..29070fee07 100644 --- a/src/backend/tests/test-utils.ts +++ b/src/backend/tests/test-utils.ts @@ -12,10 +12,13 @@ import prisma from '../src/prisma/prisma'; import { dbSeedAllUsers } from '../src/prisma/seed-data/users.seed'; import TeamsService from '../src/services/teams.services'; import ReimbursementRequestService from '../src/services/reimbursement-requests.services'; -import { ClubAccount, RoleEnum } from 'shared'; +import { ClubAccount, RoleEnum, TaskPriority, TaskStatus } from 'shared'; import { batmanAppAdmin, batmanScheduleSettings, batmanSecureSettings, batmanSettings } from './test-data/users.test-data'; import { getWorkPackageTemplateQueryArgs } from '../src/prisma-query-args/work-package-template.query-args'; import DesignReviewsService from '../src/services/design-reviews.services'; +import TasksService from '../src/services/tasks.services'; +import ProjectsService from '../src/services/projects.services'; +import { SlackMessage } from '../src/services/slack.services'; export interface CreateTestUserParams { firstName: string; @@ -116,6 +119,8 @@ export const resetUsers = async () => { await prisma.wBS_Element.deleteMany(); await prisma.milestone.deleteMany(); await prisma.frequentlyAskedQuestion.deleteMany(); + await prisma.announcement.deleteMany(); + await prisma.popUp.deleteMany(); await prisma.organization.deleteMany(); await prisma.user.deleteMany(); }; @@ -414,3 +419,71 @@ export const createTestDesignReview = async () => { const orgId = organization.organizationId; return { dr, organization, orgId }; }; + +export const createTestTask = async (user: User, organization?: Organization) => { + if (!organization) organization = await createTestOrganization(); + const orgId = organization.organizationId; + const team = await TeamsService.createTeam(user, 'Test team', user.userId, 'Test', '', false, organization); + if (!team) throw new Error('Failed to create team'); + const project = await createTestProject(user, organization.organizationId); + if (!project) throw new Error('Failed to create project'); + await ProjectsService.setProjectTeam( + user, + { + carNumber: 0, + projectNumber: 1, + workPackageNumber: 0 + }, + team.teamId, + organization + ); + + const task = await TasksService.createTask( + user, + { + carNumber: 0, + projectNumber: 1, + workPackageNumber: 0 + }, + 'Test task', + 'Test', + new Date(), + TaskPriority.High, + TaskStatus.IN_PROGRESS, + [user.userId], + organization + ); + + if (!task) throw new Error('Failed to create task'); + return { task, organization, orgId }; +}; + +export const createSlackMessageEvent = ( + channel: string, + event_ts: string, + user: string, + client_msg_id: string, + elements: any[] +): SlackMessage => { + return { + type: 'message', + channel, + event_ts, + channel_type: 'channel', + user, + client_msg_id, + text: 'sample text', + blocks: [ + { + type: 'rich_text', + block_id: 'block id', + elements: [ + { + type: 'rich_text_section', + elements + } + ] + } + ] + }; +}; diff --git a/src/backend/tests/unit/announcements.test.ts b/src/backend/tests/unit/announcements.test.ts new file mode 100644 index 0000000000..8f701ec41d --- /dev/null +++ b/src/backend/tests/unit/announcements.test.ts @@ -0,0 +1,223 @@ +import { Organization, User } from '@prisma/client'; +import { createTestOrganization, createTestUser, resetUsers } from '../test-utils'; +import { + batmanAppAdmin, + batmanSettings, + supermanAdmin, + supermanSettings, + wonderwomanGuest, + wonderwomanSettings +} from '../test-data/users.test-data'; +import AnnouncementService from '../../src/services/announcement.service'; +import { NotFoundException } from '../../src/utils/errors.utils'; + +describe('announcement tests', () => { + let orgId: string; + let organization: Organization; + let batman: User; + let superman: User; + let wonderwoman: User; + + beforeEach(async () => { + await resetUsers(); + organization = await createTestOrganization(); + orgId = organization.organizationId; + batman = await createTestUser(batmanAppAdmin, orgId, batmanSettings); + superman = await createTestUser(supermanAdmin, orgId, supermanSettings); + wonderwoman = await createTestUser(wonderwomanGuest, orgId, wonderwomanSettings); + }); + + afterEach(async () => { + await resetUsers(); + }); + + it('creates announcements which can be recieved via users', async () => { + const announcement = await AnnouncementService.createAnnouncement( + 'text', + [superman.userId, batman.userId], + new Date(1000000000000), + 'sender name', + 'slack id', + 'channel name', + orgId + ); + expect(announcement?.text).toBe('text'); + expect(announcement?.usersReceived).toHaveLength(2); + expect(announcement?.senderName).toBe('sender name'); + expect(announcement?.dateMessageSent).toStrictEqual(new Date(1000000000000)); + expect(announcement?.slackEventId).toBe('slack id'); + expect(announcement?.slackChannelName).toBe('channel name'); + expect(announcement?.dateDeleted).toBeUndefined(); + + const smAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(superman.userId, orgId); + const bmAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(batman.userId, orgId); + const wwAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(wonderwoman.userId, orgId); + + expect(smAnnouncements).toHaveLength(1); + expect(smAnnouncements[0]?.text).toBe('text'); + expect(smAnnouncements[0]?.usersReceived).toHaveLength(2); + expect(smAnnouncements[0]?.senderName).toBe('sender name'); + expect(smAnnouncements[0]?.dateMessageSent).toStrictEqual(new Date(1000000000000)); + expect(smAnnouncements[0]?.slackEventId).toBe('slack id'); + expect(smAnnouncements[0]?.slackChannelName).toBe('channel name'); + expect(smAnnouncements[0]?.dateDeleted).toBeUndefined(); + + expect(bmAnnouncements).toHaveLength(1); + expect(wwAnnouncements).toHaveLength(0); + }); + + it('updates an announcement', async () => { + await AnnouncementService.createAnnouncement( + 'text', + [superman.userId, batman.userId], + new Date(1000000000000), + 'sender name', + 'slack id', + 'channel name', + orgId + ); + + let smAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(superman.userId, orgId); + let bmAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(batman.userId, orgId); + let wwAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(wonderwoman.userId, orgId); + + expect(smAnnouncements).toHaveLength(1); + expect(bmAnnouncements).toHaveLength(1); + expect(wwAnnouncements).toHaveLength(0); + + const updatedAnnouncement = await AnnouncementService.updateAnnouncement( + 'new text', + [batman.userId, wonderwoman.userId], + 'sender name', + 'slack id', + 'channel name', + orgId + ); + + smAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(superman.userId, orgId); + bmAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(batman.userId, orgId); + wwAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(wonderwoman.userId, orgId); + + expect(smAnnouncements).toHaveLength(0); + expect(bmAnnouncements).toHaveLength(1); + expect(wwAnnouncements).toHaveLength(1); + expect(bmAnnouncements[0]?.text).toBe('new text'); + expect(wwAnnouncements[0]?.text).toBe('new text'); + expect(updatedAnnouncement?.text).toBe('new text'); + }); + + it('fails to update if there is no slack id', async () => { + await expect( + async () => + await AnnouncementService.updateAnnouncement( + 'new text', + [batman.userId, wonderwoman.userId], + 'sender name', + 'slack id', + 'channel name', + orgId + ) + ).rejects.toThrow(new NotFoundException('Announcement', 'slack id')); + }); + + it('deletes an announcement', async () => { + await AnnouncementService.createAnnouncement( + 'text', + [superman.userId, batman.userId], + new Date(1000000000000), + 'sender name', + 'slack id', + 'channel name', + orgId + ); + + let smAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(superman.userId, orgId); + let bmAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(batman.userId, orgId); + + expect(smAnnouncements).toHaveLength(1); + expect(bmAnnouncements).toHaveLength(1); + + const deletedAnnouncement = await AnnouncementService.deleteAnnouncement('slack id', orgId); + + smAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(superman.userId, orgId); + bmAnnouncements = await AnnouncementService.getUserUnreadAnnouncements(batman.userId, orgId); + + expect(smAnnouncements).toHaveLength(0); + expect(bmAnnouncements).toHaveLength(0); + expect(deletedAnnouncement?.text).toBe('text'); + expect(deletedAnnouncement?.dateDeleted).toBeDefined(); + }); + + it('throws if it cannot find the announcement to delete', async () => { + await expect(async () => await AnnouncementService.deleteAnnouncement('non-existent id', orgId)).rejects.toThrow( + new NotFoundException('Announcement', 'non-existent id') + ); + }); + + describe('Get Announcements', () => { + it('Succeeds and gets user announcements', async () => { + await AnnouncementService.createAnnouncement( + 'test1', + [batman.userId], + new Date(), + 'Thomas Emrax', + '1', + 'software', + organization.organizationId + ); + await AnnouncementService.createAnnouncement( + 'test2', + [batman.userId], + new Date(), + 'Superman', + '50', + 'mechanical', + organization.organizationId + ); + + const announcements = await AnnouncementService.getUserUnreadAnnouncements(batman.userId, organization.organizationId); + + expect(announcements).toHaveLength(2); + expect(announcements[0].text).toBe('test1'); + expect(announcements[1].text).toBe('test2'); + }); + }); + + describe('Remove Announcement', () => { + it('Succeeds and removes user announcement', async () => { + await AnnouncementService.createAnnouncement( + 'test1', + [batman.userId], + new Date(), + 'Thomas Emrax', + '1', + 'software', + organization.organizationId + ); + await AnnouncementService.createAnnouncement( + 'test2', + [batman.userId], + new Date(), + 'Superman', + '50', + 'mechanical', + organization.organizationId + ); + + const announcements = await AnnouncementService.getUserUnreadAnnouncements(batman.userId, organization.organizationId); + + expect(announcements).toHaveLength(2); + expect(announcements[0].text).toBe('test1'); + expect(announcements[1].text).toBe('test2'); + + const updatedAnnouncements = await AnnouncementService.removeUserAnnouncement( + batman.userId, + announcements[0].announcementId, + organization.organizationId + ); + + expect(updatedAnnouncements).toHaveLength(1); + expect(updatedAnnouncements[0].text).toBe('test2'); + }); + }); +}); diff --git a/src/backend/tests/unit/design-review.test.ts b/src/backend/tests/unit/design-review.test.ts new file mode 100644 index 0000000000..3fb4307b44 --- /dev/null +++ b/src/backend/tests/unit/design-review.test.ts @@ -0,0 +1,71 @@ +import { financeMember, supermanAdmin } from '../test-data/users.test-data'; +import DesignReviewsService from '../../src/services/design-reviews.services'; +import { AccessDeniedException } from '../../src/utils/errors.utils'; +import { createTestDesignReview, createTestUser, resetUsers } from '../test-utils'; +import prisma from '../../src/prisma/prisma'; +import { getUserQueryArgs } from '../../src/prisma-query-args/user.query-args'; +import { DesignReviewStatus } from 'shared'; +import { Design_Review, Organization } from '@prisma/client'; + +describe('Design Reviews', () => { + let designReview: Design_Review; + let organizationId: string; + let organization: Organization; + beforeEach(async () => { + const { dr, organization: org, orgId } = await createTestDesignReview(); + designReview = dr; + organization = org; + organizationId = orgId; + }); + + afterEach(async () => { + await resetUsers(); + }); + + // change with admin who is not creator + test('Set status works when an admin who is not the creator sets', async () => { + const user = await createTestUser(supermanAdmin, organizationId); + await DesignReviewsService.setStatus(user, designReview.designReviewId, DesignReviewStatus.CONFIRMED, organization); + const updatedDR = await prisma.design_Review.findUnique({ + where: { + designReviewId: designReview.designReviewId + } + }); + // check that status changed to correct status + expect(updatedDR?.status).toBe(DesignReviewStatus.CONFIRMED); + }); + + // Set status works when creator is not admin + test('Set status works when set with creator who is not admin', async () => { + const drCreator = await prisma.user.findUnique({ + where: { + userId: designReview.userCreatedId + }, + ...getUserQueryArgs(organizationId) + }); + if (!drCreator) { + throw new Error('User not found in database'); + } + await DesignReviewsService.setStatus(drCreator, designReview.designReviewId, DesignReviewStatus.CONFIRMED, organization); + const updatedDR = await prisma.design_Review.findUnique({ + where: { + designReviewId: designReview.designReviewId + } + }); + expect(updatedDR?.status).toBe(DesignReviewStatus.CONFIRMED); + }); + + // fails when user is not admin or creator + test('Set status fails when user is not admin or creator', async () => { + await expect(async () => + DesignReviewsService.setStatus( + await createTestUser(financeMember, organizationId), + designReview.designReviewId, + DesignReviewStatus.CONFIRMED, + organization + ) + ).rejects.toThrow( + new AccessDeniedException('admin and app-admin only have the ability to set the status of a design review') + ); + }); +}); diff --git a/src/backend/tests/unit/organization.test.ts b/src/backend/tests/unit/organization.test.ts new file mode 100644 index 0000000000..798c5ed593 --- /dev/null +++ b/src/backend/tests/unit/organization.test.ts @@ -0,0 +1,333 @@ +import { LinkCreateArgs } from 'shared'; +import { AccessDeniedAdminOnlyException, HttpException, NotFoundException } from '../../src/utils/errors.utils'; +import { batmanAppAdmin, wonderwomanGuest } from '../test-data/users.test-data'; +import { createTestLinkType, createTestOrganization, createTestProject, createTestUser, resetUsers } from '../test-utils'; +import prisma from '../../src/prisma/prisma'; +import { testLink1 } from '../test-data/organizations.test-data'; +import { uploadFile } from '../../src/utils/google-integration.utils'; +import { Mock, vi } from 'vitest'; +import OrganizationsService from '../../src/services/organizations.services'; +import { Organization } from '@prisma/client'; + +vi.mock('../../src/utils/google-integration.utils', () => ({ + uploadFile: vi.fn() +})); + +describe('Organization Tests', () => { + let orgId: string; + let organization: Organization; + + beforeEach(async () => { + organization = await createTestOrganization(); + orgId = organization.organizationId; + }); + + afterEach(async () => { + await resetUsers(); + }); + + describe('Get Current Organization', () => { + it('Fails if organization does not exist', async () => { + await expect(async () => await OrganizationsService.getCurrentOrganization('1')).rejects.toThrow( + new NotFoundException('Organization', '1') + ); + }); + + it('Succeeds and gets the organization', async () => { + const org = await OrganizationsService.getCurrentOrganization(orgId); + + expect(org).not.toBeNull(); + expect(org.organizationId).toBe(orgId); + expect(org.name).toBe(organization.name); + }); + }); + + describe('Set Images', () => { + const file1 = { originalname: 'image1.png' } as Express.Multer.File; + const file2 = { originalname: 'image2.png' } as Express.Multer.File; + const file3 = { originalname: 'image3.png' } as Express.Multer.File; + it('Fails if user is not an admin', async () => { + await expect( + OrganizationsService.setImages(file1, file2, await createTestUser(wonderwomanGuest, orgId), organization) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('update images')); + }); + + it('Succeeds and updates all the images', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + (uploadFile as Mock).mockImplementation((file) => { + return Promise.resolve({ name: `${file.originalname}`, id: `uploaded-${file.originalname}` }); + }); + + await OrganizationsService.setImages(file1, file2, testBatman, organization); + + const oldOrganization = await prisma.organization.findUnique({ + where: { + organizationId: orgId + } + }); + + expect(oldOrganization).not.toBeNull(); + expect(oldOrganization?.applyInterestImageId).toBe('uploaded-image1.png'); + expect(oldOrganization?.exploreAsGuestImageId).toBe('uploaded-image2.png'); + + await OrganizationsService.setImages(file1, file3, testBatman, organization); + + const updatedOrganization = await prisma.organization.findUnique({ + where: { + organizationId: orgId + } + }); + + expect(updatedOrganization?.exploreAsGuestImageId).toBe('uploaded-image3.png'); + }); + }); + + describe('Set Useful Links', () => { + it('Fails if user is not an admin', async () => { + await expect( + OrganizationsService.setUsefulLinks(await createTestUser(wonderwomanGuest, orgId), orgId, []) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('update useful links')); + }); + + it('Fails if a link type does not exist', async () => { + await expect( + OrganizationsService.setUsefulLinks(await createTestUser(batmanAppAdmin, orgId), orgId, testLink1) + ).rejects.toThrow(new HttpException(400, `Link type with name 'example link type' not found`)); + }); + + it('Succeeds and updates all the links', async () => { + const testLinks1: LinkCreateArgs[] = [ + { + linkId: '-1', + linkTypeName: 'Link type 1', + url: 'link 1' + }, + { + linkId: '-1', + linkTypeName: 'Link type 1', + url: 'link 2' + } + ]; + const testBatman = await createTestUser(batmanAppAdmin, orgId); + await createTestLinkType(testBatman, orgId); + await OrganizationsService.setUsefulLinks(testBatman, orgId, testLinks1); + + const organization = await prisma.organization.findUnique({ + where: { + organizationId: orgId + }, + include: { + usefulLinks: true + } + }); + + expect(organization).not.toBeNull(); + expect(organization!.usefulLinks.length).toBe(2); + expect(organization!.usefulLinks[0].url).toBe('link 1'); + expect(organization!.usefulLinks[1].url).toBe('link 2'); + + // ensuring previous links are deleted and only these ones remain + const testLinks2: LinkCreateArgs[] = [ + { + linkId: '-1', + linkTypeName: 'Link type 1', + url: 'link 3' + }, + { + linkId: '-1', + linkTypeName: 'Link type 1', + url: 'link 4' + } + ]; + await OrganizationsService.setUsefulLinks(testBatman, orgId, testLinks2); + + const updatedOrganization = await prisma.organization.findUnique({ + where: { + organizationId: orgId + }, + include: { + usefulLinks: true + } + }); + + expect(updatedOrganization).not.toBeNull(); + expect(updatedOrganization!.usefulLinks.length).toBe(2); + expect(updatedOrganization!.usefulLinks[0].url).toBe('link 3'); + expect(updatedOrganization!.usefulLinks[1].url).toBe('link 4'); + }); + }); + + describe('Get all Useful Links', () => { + it('Succeeds and gets all the links', async () => { + const testLinks1: LinkCreateArgs[] = [ + { + linkId: '1', + linkTypeName: 'Link type 1', + url: 'link 1' + }, + { + linkId: '2', + linkTypeName: 'Link type 1', + url: 'link 2' + } + ]; + const testBatman = await createTestUser(batmanAppAdmin, orgId); + await createTestLinkType(testBatman, orgId); + await OrganizationsService.setUsefulLinks(testBatman, orgId, testLinks1); + const links = await OrganizationsService.getAllUsefulLinks(orgId); + + expect(links).not.toBeNull(); + expect(links.length).toBe(2); + expect(links[0].url).toBe('link 1'); + expect(links[1].url).toBe('link 2'); + }); + }); + + describe('Get all featured projects', () => { + it('Fails if an organizaion does not exist', async () => { + await expect(async () => await OrganizationsService.getOrganizationFeaturedProjects('1')).rejects.toThrow( + new NotFoundException('Organization', '1') + ); + }); + + it('Succeeds and gets featured projects', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + const testProject1 = await createTestProject(testBatman, orgId); + + await OrganizationsService.setFeaturedProjects([testProject1.projectId], organization, testBatman); + + const projects = await OrganizationsService.getOrganizationFeaturedProjects(orgId); + + expect(projects).not.toBeNull(); + expect(projects.length).toBe(1); + expect(projects[0].id).toBe(testProject1.projectId); + }); + }); + + describe('Get Organization Images', () => { + it('Fails if an organization does not exist', async () => { + await expect(async () => await OrganizationsService.getOrganizationImages('1')).rejects.toThrow( + new NotFoundException('Organization', '1') + ); + }); + + it('Succeeds and gets all the images', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + await createTestLinkType(testBatman, orgId); + await OrganizationsService.setImages( + { originalname: 'image1.png' } as Express.Multer.File, + { originalname: 'image2.png' } as Express.Multer.File, + testBatman, + organization + ); + const images = await OrganizationsService.getOrganizationImages(orgId); + + expect(images).not.toBeNull(); + expect(images.applyInterestImage).toBe('uploaded-image1.png'); + expect(images.exploreAsGuestImage).toBe('uploaded-image2.png'); + }); + }); + + describe('Set Logo', () => { + const file1 = { originalname: 'image1.png' } as Express.Multer.File; + const file2 = { originalname: 'image2.png' } as Express.Multer.File; + it('Fails if user is not an admin', async () => { + await expect( + OrganizationsService.setLogoImage(file1, await createTestUser(wonderwomanGuest, orgId), organization) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('update logo')); + }); + + it('Succeeds and updates the logo', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + (uploadFile as Mock).mockImplementation((file) => { + return Promise.resolve({ name: `${file.originalname}`, id: `uploaded-${file.originalname}` }); + }); + + await OrganizationsService.setLogoImage(file1, testBatman, organization); + + const oldOrganization = await prisma.organization.findUnique({ + where: { + organizationId: orgId + } + }); + + expect(oldOrganization).not.toBeNull(); + expect(oldOrganization?.logoImageId).toBe('uploaded-image1.png'); + + await OrganizationsService.setLogoImage(file2, testBatman, organization); + + const updatedOrganization = await prisma.organization.findUnique({ + where: { + organizationId: orgId + } + }); + + expect(updatedOrganization?.logoImageId).toBe('uploaded-image2.png'); + }); + }); + + describe('Get Organization Logo', () => { + it('Fails if an organization does not exist', async () => { + await expect(async () => await OrganizationsService.getLogoImage('1')).rejects.toThrow( + new NotFoundException('Organization', '1') + ); + }); + + it('Succeeds and gets the image', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + await OrganizationsService.setLogoImage( + { originalname: 'image1.png' } as Express.Multer.File, + testBatman, + organization + ); + const image = await OrganizationsService.getLogoImage(orgId); + + expect(image).not.toBeNull(); + expect(image).toBe('uploaded-image1.png'); + }); + }); + + describe('Set Organization Description', () => { + it('Fails if user is not an admin', async () => { + await expect( + OrganizationsService.setOrganizationDescription( + 'test description', + await createTestUser(wonderwomanGuest, orgId), + organization + ) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('set description')); + }); + + it('Succeeds and updates the description', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + + const returnedOrganization = await OrganizationsService.setOrganizationDescription( + 'sample description', + testBatman, + organization + ); + + const oldOrganization = await prisma.organization.findUnique({ + where: { + organizationId: orgId + } + }); + + expect(oldOrganization).not.toBeNull(); + expect(oldOrganization?.description).toBe('sample description'); + expect(oldOrganization?.organizationId).toBe(returnedOrganization.organizationId); + expect(oldOrganization?.description).toBe(returnedOrganization.description); + }); + }); + + describe('Set Organization Workspace Id', () => { + it('Succeeds and updates the workspace id', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + + const updatedOrganization = await OrganizationsService.setSlackWorkspaceId('1234', testBatman, orgId); + + expect(updatedOrganization).not.toBeNull(); + expect(updatedOrganization.slackWorkspaceId).toBe('1234'); + }); + }); +}); diff --git a/src/backend/tests/unit/pop-up.test.ts b/src/backend/tests/unit/pop-up.test.ts new file mode 100644 index 0000000000..4421aea4f8 --- /dev/null +++ b/src/backend/tests/unit/pop-up.test.ts @@ -0,0 +1,90 @@ +import { Organization } from '@prisma/client'; +import { createTestOrganization, createTestUser, resetUsers } from '../test-utils'; +import { batmanAppAdmin, supermanAdmin } from '../test-data/users.test-data'; +import { NotFoundException } from '../../src/utils/errors.utils'; +import prisma from '../../src/prisma/prisma'; +import { PopUpService } from '../../src/services/pop-up.services'; + +describe('Pop Ups Tests', () => { + let orgId: string; + let organization: Organization; + beforeEach(async () => { + organization = await createTestOrganization(); + orgId = organization.organizationId; + }); + + afterEach(async () => { + await resetUsers(); + }); + + describe('Send Pop Up', () => { + it('fails on invalid user id', async () => { + await expect( + async () => await PopUpService.sendPopUpToUsers('test pop up', 'star', ['1', '2'], organization.organizationId) + ).rejects.toThrow(new NotFoundException('User', '1')); + }); + + it('Succeeds and sends pop up to user', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + const testSuperman = await createTestUser(supermanAdmin, orgId); + await PopUpService.sendPopUpToUsers( + 'test pop up', + 'star', + [testBatman.userId, testSuperman.userId], + organization.organizationId + ); + + const batmanWithPopUps = await prisma.user.findUnique({ + where: { userId: testBatman.userId }, + include: { unreadPopUps: true } + }); + + const supermanWithPopUps = await prisma.user.findUnique({ + where: { userId: testBatman.userId }, + include: { unreadPopUps: true } + }); + + expect(batmanWithPopUps?.unreadPopUps).toHaveLength(1); + expect(batmanWithPopUps?.unreadPopUps[0].text).toBe('test pop up'); + expect(supermanWithPopUps?.unreadPopUps).toHaveLength(1); + expect(supermanWithPopUps?.unreadPopUps[0].text).toBe('test pop up'); + }); + }); + + describe('Get Notifications', () => { + it('Succeeds and gets user pop ups', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + await PopUpService.sendPopUpToUsers('test1', 'test1', [testBatman.userId], orgId); + await PopUpService.sendPopUpToUsers('test2', 'test2', [testBatman.userId], orgId); + + const popUps = await PopUpService.getUserUnreadPopUps(testBatman.userId, organization.organizationId); + + expect(popUps).toHaveLength(2); + expect(popUps[0].text).toBe('test1'); + expect(popUps[1].text).toBe('test2'); + }); + }); + + describe('Remove Pop Ups', () => { + it('Succeeds and removes user pop up', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + await PopUpService.sendPopUpToUsers('test1', 'test1', [testBatman.userId], orgId); + await PopUpService.sendPopUpToUsers('test2', 'test2', [testBatman.userId], orgId); + + const popUps = await PopUpService.getUserUnreadPopUps(testBatman.userId, organization.organizationId); + + expect(popUps).toHaveLength(2); + expect(popUps[0].text).toBe('test1'); + expect(popUps[1].text).toBe('test2'); + + const updatedPopUps = await PopUpService.removeUserPopUp( + testBatman.userId, + popUps[0].popUpId, + organization.organizationId + ); + + expect(updatedPopUps).toHaveLength(1); + expect(updatedPopUps[0].text).toBe('test2'); + }); + }); +}); diff --git a/src/backend/tests/unit/recruitment.test.ts b/src/backend/tests/unit/recruitment.test.ts new file mode 100644 index 0000000000..dddb6a6ba6 --- /dev/null +++ b/src/backend/tests/unit/recruitment.test.ts @@ -0,0 +1,339 @@ +import prisma from '../../src/prisma/prisma'; +import { Organization } from '@prisma/client'; +import RecruitmentServices from '../../src/services/recruitment.services'; +import { + AccessDeniedAdminOnlyException, + DeletedException, + HttpException, + NotFoundException +} from '../../src/utils/errors.utils'; +import { + createTestMilestone, + createTestFaq, + createTestFAQ, + createTestOrganization, + createTestUser, + resetUsers +} from '../test-utils'; +import { + batmanAppAdmin, + wonderwomanGuest, + supermanAdmin, + member, + theVisitorGuest, + flashAdmin, + alfred +} from '../test-data/users.test-data'; + +describe('Recruitment Tests', () => { + let orgId: string; + let organization: Organization; + beforeEach(async () => { + organization = await createTestOrganization(); + orgId = organization.organizationId; + }); + + afterEach(async () => { + await resetUsers(); + }); + + describe('Get All FAQs', () => { + it('Succeeds and gets all the FAQs', async () => { + const faq1 = await RecruitmentServices.createFaq( + await createTestUser(batmanAppAdmin, orgId), + 'question', + 'answer', + organization + ); + const faq2 = await RecruitmentServices.createFaq( + await createTestUser(supermanAdmin, orgId), + 'question2', + 'answer2', + organization + ); + const result = await RecruitmentServices.getAllFaqs(organization); + expect(result).toStrictEqual([faq1, faq2]); + }); + + describe('Edit FAQ', () => { + it('Fails if user is not an admin', async () => { + await expect( + async () => + await RecruitmentServices.editFAQ( + 'What is your return policy?', + 'You can return any item within 30 days of purchase.', + await createTestUser(wonderwomanGuest, orgId), + organization, + 'faq123' + ) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('edit frequently asked questions')); + }); + + it('Fails if FAQ does not exist', async () => { + await expect( + async () => + await RecruitmentServices.editFAQ( + 'What is your return policy?', + 'You can return any item within 30 days of purchase.', + await createTestUser(batmanAppAdmin, orgId), + organization, + 'nonExistentFaqId' + ) + ).rejects.toThrow(new NotFoundException('Faq', 'nonExistentFaqId')); + }); + + it('Succeeds and edits an FAQ', async () => { + await createTestFAQ(orgId, 'faq123'); + const result = await RecruitmentServices.editFAQ( + 'What is your return policy?', + 'You can return any item within 60 days of purchase.', + await createTestUser(batmanAppAdmin, orgId), + organization, + 'faq123' + ); + + expect(result.question).toEqual('What is your return policy?'); + expect(result.answer).toEqual('You can return any item within 60 days of purchase.'); + }); + }); + + describe('Create Milestone', () => { + it('Fails if user is not an admin', async () => { + await expect( + async () => + await RecruitmentServices.createMilestone( + await createTestUser(wonderwomanGuest, orgId), + 'name', + 'description', + new Date(), + organization + ) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('create a milestone')); + }); + + it('Succeeds and creates a milestone', async () => { + const result = await RecruitmentServices.createMilestone( + await createTestUser(batmanAppAdmin, orgId), + 'name', + 'description', + new Date('11/12/24'), + organization + ); + + expect(result.name).toEqual('name'); + expect(result.description).toEqual('description'); + expect(result.dateOfEvent).toEqual(new Date('11/12/24')); + }); + }); + + describe('Edit Milestone', () => { + it('Fails if user is not an admin', async () => { + await expect( + async () => + await RecruitmentServices.editMilestone( + await createTestUser(wonderwomanGuest, orgId), + 'name', + 'description', + new Date(), + '1', + organization + ) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('create a milestone')); + }); + + it('Fails if milestone doesn`t exist', async () => { + await expect( + async () => + await RecruitmentServices.editMilestone( + await createTestUser(batmanAppAdmin, orgId), + 'name', + 'description', + new Date('11/12/24'), + '1', + organization + ) + ).rejects.toThrow(new NotFoundException('Milestone', 1)); + }); + + it('Fails if milestone is deleted', async () => { + const milestone = await RecruitmentServices.createMilestone( + await createTestUser(batmanAppAdmin, orgId), + 'name', + 'description', + new Date('11/12/24'), + organization + ); + + await prisma.milestone.delete({ + where: { + milestoneId: milestone.milestoneId + } + }); + + await expect( + async () => + await RecruitmentServices.editMilestone( + await createTestUser(supermanAdmin, orgId), + 'name', + 'description', + new Date('11/12/24'), + milestone.milestoneId, + organization + ) + ).rejects.toThrow(new NotFoundException('Milestone', milestone.milestoneId)); + }); + + it('Succeeds and edits a milestone', async () => { + const milestone = await RecruitmentServices.createMilestone( + await createTestUser(batmanAppAdmin, orgId), + 'name', + 'description', + new Date('11/12/24'), + organization + ); + + const updatedMilestone = await RecruitmentServices.editMilestone( + await createTestUser(supermanAdmin, orgId), + 'new name', + 'new description', + new Date('11/14/24'), + milestone.milestoneId, + organization + ); + + expect(updatedMilestone.name).toEqual('new name'); + expect(updatedMilestone.description).toEqual('new description'); + expect(updatedMilestone.dateOfEvent).toEqual(new Date('11/14/24')); + }); + }); + + describe('Get All Milestones', () => { + it('Succeeds and gets all the milestones', async () => { + const milestone1 = await RecruitmentServices.createMilestone( + await createTestUser(batmanAppAdmin, orgId), + 'name', + 'description', + new Date('11/11/24'), + organization + ); + + const milestone2 = await RecruitmentServices.createMilestone( + await createTestUser(supermanAdmin, orgId), + 'name2', + 'description2', + new Date('1/1/1'), + organization + ); + const result = await RecruitmentServices.getAllMilestones(organization); + expect(result).toStrictEqual([milestone1, milestone2]); + }); + }); + + describe('Create FAQ', () => { + it('Fails if user is not an admin', async () => { + await expect( + async () => + await RecruitmentServices.createFaq(await createTestUser(member, orgId), 'question', 'answer', organization) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('create an faq')); + }); + + describe('Delete a single milestone', () => { + it('Fails if user is not admin', async () => { + await expect( + async () => + await RecruitmentServices.deleteMilestone(await createTestUser(wonderwomanGuest, orgId), 'id', organization) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('delete milestone')); + }); + + it('Fails if milestoneId is not found', async () => { + await expect( + async () => + await RecruitmentServices.deleteMilestone(await createTestUser(batmanAppAdmin, orgId), 'id1', organization) + ).rejects.toThrow(new HttpException(400, 'Milestone with id: id1 not found!')); + }); + + it('Fails if milestone is already deleted', async () => { + const testSuperman = await createTestUser(supermanAdmin, orgId); + const testMilestone = await createTestMilestone(testSuperman, orgId); + await RecruitmentServices.deleteMilestone(testSuperman, testMilestone.milestoneId, organization); + + await expect( + async () => await RecruitmentServices.deleteMilestone(testSuperman, testMilestone.milestoneId, organization) + ).rejects.toThrow(new DeletedException('Milestone', testMilestone.milestoneId)); + }); + + it('Succeeds and deletes milestone', async () => { + const testSuperman = await createTestUser(supermanAdmin, orgId); + const testMilestone1 = await createTestMilestone(testSuperman, orgId); + + await RecruitmentServices.deleteMilestone(testSuperman, testMilestone1.milestoneId, organization); + + const updatedTestMilestone1 = await prisma.milestone.findUnique({ + where: { milestoneId: testMilestone1.milestoneId } + }); + + expect(updatedTestMilestone1?.dateDeleted).not.toBe(null); + }); + + describe('Create FAQ', () => { + it('Fails if user is not an admin', async () => { + await expect( + async () => + await RecruitmentServices.createFaq(await createTestUser(member, orgId), 'question', 'answer', organization) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('create an faq')); + }); + + it('Succeeds and creates an FAQ', async () => { + const result = await RecruitmentServices.createFaq( + await createTestUser(batmanAppAdmin, orgId), + 'question', + 'answer', + organization + ); + + expect(result.question).toEqual('question'); + expect(result.answer).toEqual('answer'); + }); + }); + }); + }); + }); + + describe('Delete FAQ', () => { + it('Fails if user is not an admin', async () => { + const testFaq = await createTestFaq(await createTestUser(batmanAppAdmin, orgId), orgId); + await expect( + async () => + await RecruitmentServices.deleteFaq(await createTestUser(theVisitorGuest, orgId), testFaq.faqId, organization) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('delete an faq')); + }); + + it('Fails if faq doesn`t exist', async () => { + await expect( + async () => await RecruitmentServices.deleteFaq(await createTestUser(batmanAppAdmin, orgId), '1', organization) + ).rejects.toThrow(new NotFoundException('Faq', '1')); + }); + + it('Fails if faq is already deleted', async () => { + const testFaq = await createTestFaq(await createTestUser(batmanAppAdmin, orgId), orgId); + await RecruitmentServices.deleteFaq(await createTestUser(flashAdmin, orgId), testFaq.faqId, organization); + + await expect( + async () => + await RecruitmentServices.deleteFaq(await createTestUser(supermanAdmin, orgId), testFaq.faqId, organization) + ).rejects.toThrow(new DeletedException('Faq', testFaq.faqId)); + }); + + it('Succeeds and deletes an FAQ', async () => { + const testFaq = await createTestFaq(await createTestUser(batmanAppAdmin, orgId), orgId); + + await RecruitmentServices.deleteFaq(await createTestUser(alfred, orgId), testFaq.faqId, organization); + + const deletedTestFaq = await prisma.frequentlyAskedQuestion.findUnique({ + where: { faqId: testFaq.faqId } + }); + + expect(deletedTestFaq?.dateDeleted).not.toBe(null); + }); + }); +}); diff --git a/src/backend/tests/unit/reimbursement-requests.test.ts b/src/backend/tests/unit/reimbursement-requests.test.ts new file mode 100644 index 0000000000..f1efc8d3fe --- /dev/null +++ b/src/backend/tests/unit/reimbursement-requests.test.ts @@ -0,0 +1,232 @@ +import { alfred } from '../test-data/users.test-data'; +import ReimbursementRequestService from '../../src/services/reimbursement-requests.services'; +import { AccessDeniedException, HttpException } from '../../src/utils/errors.utils'; +import { createTestReimbursementRequest, createTestUser, resetUsers } from '../test-utils'; +import prisma from '../../src/prisma/prisma'; +import { assert } from 'console'; +import { addDaysToDate, ClubAccount, ReimbursementRequest } from 'shared'; +import { Account_Code, Organization, Vendor } from '@prisma/client'; +import { UserWithSecureSettings } from '../../src/utils/auth.utils'; + +describe('Reimbursement Requests', () => { + let org: Organization; + let reimbursementRequest: ReimbursementRequest; + let createdVendor: Vendor; + let createdAccountCode: Account_Code; + let createdUser: UserWithSecureSettings; + + beforeEach(async () => { + const result = await createTestReimbursementRequest(); + org = result.organization; + reimbursementRequest = result.rr; + createdVendor = result.vendor; + createdAccountCode = result.accountCode; + createdUser = result.user; + }); + + afterEach(async () => { + await resetUsers(); + }); + + describe('Deleting a reimbursement request', () => { + test('Delete Reimbursement Request fails when deleter is not a finance lead', async () => { + await expect(async () => + ReimbursementRequestService.deleteReimbursementRequest( + reimbursementRequest.reimbursementRequestId, + await createTestUser(alfred, org.organizationId), + org + ) + ).rejects.toThrow( + new AccessDeniedException( + 'You do not have access to delete this reimbursement request, reimbursement requests can only be deleted by their creator or finance leads and above' + ) + ); + }); + + test('Delete Reimbursement Request succeeds when the deleter is a finance lead', async () => { + const financeLead = await prisma.user.findUnique({ + where: { + googleAuthId: 'financeLead' + } + }); + + if (!financeLead) { + console.log('No finance lead found, please run createFinanceTeamAndLead before this function'); + assert(false); + throw new Error('No finance lead found, please run createFinanceTeamAndLead before this function'); + } + await ReimbursementRequestService.deleteReimbursementRequest( + reimbursementRequest.reimbursementRequestId, + financeLead, + org + ); + }); + + test('Delete Reimbursement Request succeeds when the deleter is a head of finance', async () => { + const financeHead = await prisma.user.findUnique({ + where: { + googleAuthId: 'financeHead' + } + }); + + if (!financeHead) { + console.log('No finance head found, please run createFinanceTeamAndLead before this function'); + assert(false); + throw new Error('No finance head found, please run createFinanceTeamAndLead before this function'); + } + await ReimbursementRequestService.deleteReimbursementRequest( + reimbursementRequest.reimbursementRequestId, + financeHead, + org + ); + }); + }); + + describe('Creating a reimbursement request', () => { + test('Creating a Reimbursement Request Succeeds without a date', async () => { + const rr = await ReimbursementRequestService.createReimbursementRequest( + createdUser, + createdVendor.vendorId, + ClubAccount.CASH, + [], + [ + { + name: 'GLUE', + reason: { + carNumber: 0, + projectNumber: 0, + workPackageNumber: 0 + }, + cost: 200000 + } + ], + createdAccountCode.accountCodeId, + 100, + org + ); + + expect(rr.accountCode).toStrictEqual({ ...createdAccountCode, dateDeleted: undefined }); + expect(rr.account).toEqual(ClubAccount.CASH); + expect(rr.vendor.vendorId).toEqual(createdVendor.vendorId); + expect(rr.recipient.userId).toEqual(createdUser.userId); + expect(rr.dateOfExpense).toEqual(undefined); + expect(rr.reimbursementProducts).toHaveLength(1); + expect(rr.reimbursementProducts[0].name).toEqual('GLUE'); + expect(rr.reimbursementProducts[0].cost).toEqual(200000); + expect((rr.reimbursementProducts[0].reimbursementProductReason as any).wbsNum).toEqual({ + carNumber: 0, + projectNumber: 0, + workPackageNumber: 0 + }); + expect(rr.totalCost).toEqual(100); + expect(rr.reimbursementStatuses).toHaveLength(1); + expect(rr.reimbursementStatuses[0].type).toEqual('PENDING_LEADERSHIP_APPROVAL'); + expect(rr.identifier).toEqual(2); + }); + + test('Creating a Reimbursement Request Succeeds with a date', async () => { + const rr = await ReimbursementRequestService.createReimbursementRequest( + createdUser, + createdVendor.vendorId, + ClubAccount.CASH, + [], + [ + { + name: 'GLUE', + reason: { + carNumber: 0, + projectNumber: 0, + workPackageNumber: 0 + }, + cost: 200000 + } + ], + createdAccountCode.accountCodeId, + 100, + org, + new Date('12-29-2023') + ); + + expect(rr.accountCode).toStrictEqual({ ...createdAccountCode, dateDeleted: undefined }); + expect(rr.account).toEqual(ClubAccount.CASH); + expect(rr.vendor.vendorId).toEqual(createdVendor.vendorId); + expect(rr.recipient.userId).toEqual(createdUser.userId); + expect(rr.dateOfExpense).toEqual(new Date('12-29-2023')); + expect(rr.reimbursementProducts).toHaveLength(1); + expect(rr.reimbursementProducts[0].name).toEqual('GLUE'); + expect(rr.reimbursementProducts[0].cost).toEqual(200000); + expect((rr.reimbursementProducts[0].reimbursementProductReason as any).wbsNum).toEqual({ + carNumber: 0, + projectNumber: 0, + workPackageNumber: 0 + }); + expect(rr.totalCost).toEqual(100); + expect(rr.reimbursementStatuses).toHaveLength(1); + expect(rr.reimbursementStatuses[0].type).toEqual('PENDING_LEADERSHIP_APPROVAL'); + expect(rr.identifier).toEqual(2); + }); + }); + + describe('Marking a reimbursement request as delivered', () => { + test('cannot mark as delivered if delivery is before expense date', async () => { + // to get around the type checker + const rrExpenseDate: Date = reimbursementRequest.dateOfExpense ?? new Date('2022-11-22T00:00:01'); + + await expect(async () => + ReimbursementRequestService.markReimbursementRequestAsDelivered( + createdUser, + reimbursementRequest.reimbursementRequestId, + org, + addDaysToDate(rrExpenseDate, -1) + ) + ).rejects.toThrow(new HttpException(400, 'Items cannot be delivered before the expense date.')); + }); + + test('cannot mark as delivered if delivery is after today', async () => { + await expect(async () => + ReimbursementRequestService.markReimbursementRequestAsDelivered( + createdUser, + reimbursementRequest.reimbursementRequestId, + org, + addDaysToDate(new Date(), 1) + ) + ).rejects.toThrow(new HttpException(400, 'Delivery date cannot be in the future.')); + }); + + test('adds delivered date to reimbursement request', async () => { + // we don't want to just check today - set date of expense to some time in the past + const oldReimbursementRequest = await ReimbursementRequestService.createReimbursementRequest( + createdUser, + reimbursementRequest.vendor.vendorId, + reimbursementRequest.account, + [], + [ + { + name: 'GLUE', + reason: { + carNumber: 0, + projectNumber: 0, + workPackageNumber: 0 + }, + cost: 200000 + } + ], + reimbursementRequest.accountCode.accountCodeId, + reimbursementRequest.totalCost, + org, + new Date('2022-11-22T00:00:01') + ); + + const dateToSetAsDelivered = addDaysToDate(new Date(), -5); + + const updatedRR = await ReimbursementRequestService.markReimbursementRequestAsDelivered( + createdUser, + oldReimbursementRequest.reimbursementRequestId, + org, + dateToSetAsDelivered + ); + + expect(updatedRR.dateDelivered).toEqual(dateToSetAsDelivered); + }); + }); +}); diff --git a/src/backend/tests/unit/team-type.test.ts b/src/backend/tests/unit/team-type.test.ts new file mode 100644 index 0000000000..e422bf701e --- /dev/null +++ b/src/backend/tests/unit/team-type.test.ts @@ -0,0 +1,106 @@ +import { Organization } from '@prisma/client'; +import TeamsService from '../../src/services/teams.services'; +import { AccessDeniedAdminOnlyException, HttpException, NotFoundException } from '../../src/utils/errors.utils'; +import { batmanAppAdmin, supermanAdmin, wonderwomanGuest } from '../test-data/users.test-data'; +import { createTestOrganization, createTestUser, resetUsers } from '../test-utils'; + +describe('Team Type Tests', () => { + let orgId: string; + let organization: Organization; + beforeEach(async () => { + organization = await createTestOrganization(); + orgId = organization.organizationId; + }); + + afterEach(async () => { + await resetUsers(); + }); + + describe('Create Team Type', () => { + it('Create team type fails if user is not an admin', async () => { + await expect( + async () => + await TeamsService.createTeamType( + await createTestUser(wonderwomanGuest, orgId), + 'Team 2', + 'Warning icon', + organization + ) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('create a team type')); + }); + + it('Create team type fails if there is already another team type with the same name', async () => { + await TeamsService.createTeamType( + await createTestUser(supermanAdmin, orgId), + 'teamType1', + 'YouTubeIcon', + organization + ); + await expect( + async () => + await TeamsService.createTeamType( + await createTestUser(batmanAppAdmin, orgId), + 'teamType1', + 'Warning icon', + organization + ) + ).rejects.toThrow(new HttpException(400, 'Cannot create a teamType with a name that already exists')); + }); + + it('Create team type works', async () => { + const result = await TeamsService.createTeamType( + await createTestUser(supermanAdmin, orgId), + 'teamType3', + 'YouTubeIcon', + organization + ); + + expect(result).toEqual({ + name: 'teamType3', + iconName: 'YouTubeIcon', + organizationId: orgId, + teamTypeId: result.teamTypeId, + calendarId: null + }); + }); + }); + + describe('Get all team types works', () => { + it('Get all team types works', async () => { + const teamType1 = await TeamsService.createTeamType( + await createTestUser(supermanAdmin, orgId), + 'teamType1', + 'YouTubeIcon', + organization + ); + const teamType2 = await TeamsService.createTeamType( + await createTestUser(batmanAppAdmin, orgId), + 'teamType2', + 'WarningIcon', + organization + ); + const result = await TeamsService.getAllTeamTypes(organization); + expect(result).toStrictEqual([teamType1, teamType2]); + }); + }); + + describe('Get a single team type', () => { + it('Get a single team type works', async () => { + const teamType1 = await TeamsService.createTeamType( + await createTestUser(supermanAdmin, orgId), + 'teamType1', + 'YouTubeIcon', + organization + ); + const result = await TeamsService.getSingleTeamType(teamType1.teamTypeId, organization); + expect(result).toStrictEqual(teamType1); + }); + + it('Get a single team type fails', async () => { + const nonExistingTeamTypeId = 'nonExistingId'; + await expect(async () => TeamsService.getSingleTeamType(nonExistingTeamTypeId, organization)).rejects.toThrow( + new NotFoundException('Team Type', nonExistingTeamTypeId) + ); + }); + }); +}); diff --git a/src/backend/tests/unit/users.test.ts b/src/backend/tests/unit/users.test.ts new file mode 100644 index 0000000000..c13a0c857f --- /dev/null +++ b/src/backend/tests/unit/users.test.ts @@ -0,0 +1,51 @@ +import { Organization } from '@prisma/client'; +import { createTestOrganization, createTestTask, createTestUser, resetUsers } from '../test-utils'; +import { batmanAppAdmin } from '../test-data/users.test-data'; +import UsersService from '../../src/services/users.services'; +import { NotFoundException } from '../../src/utils/errors.utils'; + +describe('User Tests', () => { + let orgId: string; + let organization: Organization; + beforeEach(async () => { + organization = await createTestOrganization(); + orgId = organization.organizationId; + }); + + afterEach(async () => { + await resetUsers(); + }); + + describe('Get Users Tasks', () => { + it('fails on invalid user id', async () => { + await expect(async () => await UsersService.getUserTasks('1', organization)).rejects.toThrow( + new NotFoundException('User', '1') + ); + }); + + it("Succeeds and gets user's assigned tasks", async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + + const { task } = await createTestTask(testBatman, organization); + const userTasks = await UsersService.getUserTasks(testBatman.userId, organization); + + expect(userTasks).toStrictEqual([task]); + }); + }); + + describe('Get Many Users Tasks', () => { + it('fails on invalid user id', async () => { + await expect(async () => await UsersService.getManyUserTasks(['1'], organization)).rejects.toThrow( + new NotFoundException('User', '1') + ); + }); + + it("Succeeds and gets all user' tasks in the list", async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + const { task: batmanTask } = await createTestTask(testBatman, organization); + const userTasks = await UsersService.getManyUserTasks([testBatman.userId, testBatman.userId], organization); + + expect(userTasks).toStrictEqual([batmanTask, batmanTask]); + }); + }); +}); diff --git a/src/backend/tests/unit/work-package-template.test.ts b/src/backend/tests/unit/work-package-template.test.ts new file mode 100644 index 0000000000..cb842a6165 --- /dev/null +++ b/src/backend/tests/unit/work-package-template.test.ts @@ -0,0 +1,167 @@ +import { + AccessDeniedGuestException, + AccessDeniedAdminOnlyException, + DeletedException, + HttpException +} from '../../src/utils/errors.utils'; +import { createTestOrganization, createTestUser, createTestWorkPackageTemplate, resetUsers } from '../test-utils'; +import { batmanAppAdmin, supermanAdmin, theVisitorGuest } from '../test-data/users.test-data'; +import { workPackageTemplateTransformer } from '../../src/transformers/work-package-template.transformer'; +import prisma from '../../src/prisma/prisma'; +import WorkPackageTemplatesService from '../../src/services/work-package-template.services'; +import { Organization } from '@prisma/client'; + +describe('Work Package Template Tests', () => { + let orgId: string; + let organization: Organization; + beforeEach(async () => { + organization = await createTestOrganization(); + orgId = organization.organizationId; + }); + + afterEach(async () => { + await resetUsers(); + }); + + describe('Get single work package template', () => { + it('fails if user is a guest', async () => { + await expect( + async () => + await WorkPackageTemplatesService.getSingleWorkPackageTemplate( + await createTestUser(theVisitorGuest, orgId), + 'id', + organization + ) + ).rejects.toThrow(new AccessDeniedGuestException('get a work package template')); + }); + + it('fails is the work package template ID is not found', async () => { + await expect( + async () => + await WorkPackageTemplatesService.getSingleWorkPackageTemplate( + await createTestUser(batmanAppAdmin, orgId), + 'id1', + organization + ) + ).rejects.toThrow(new HttpException(400, `Work package template with id id1 not found`)); + }); + + it('get single work package template succeeds', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + const createdWorkPackageTemplate = await createTestWorkPackageTemplate(testBatman, orgId); + + const recievedWorkPackageTemplate = await WorkPackageTemplatesService.getSingleWorkPackageTemplate( + await createTestUser(supermanAdmin, orgId), + createdWorkPackageTemplate.workPackageTemplateId, + organization + ); + + expect(recievedWorkPackageTemplate).toStrictEqual(workPackageTemplateTransformer(createdWorkPackageTemplate)); + }); + }); + + describe('Delete single work package template', () => { + it('fails if user is a guest', async () => { + await expect( + async () => + await WorkPackageTemplatesService.deleteWorkPackageTemplate( + await createTestUser(theVisitorGuest, orgId), + 'id', + organization + ) + ).rejects.toThrow(new AccessDeniedAdminOnlyException('delete work package template')); + }); + + it('fails is the work package template ID is not found', async () => { + await expect( + async () => + await WorkPackageTemplatesService.deleteWorkPackageTemplate( + await createTestUser(supermanAdmin, orgId), + 'id1', + organization + ) + ).rejects.toThrow(new HttpException(400, `Work Package Template with id: id1 not found!`)); + }); + + it('fails is the work package template has already been deleted', async () => { + const testSuperman = await createTestUser(supermanAdmin, orgId); + const testWorkPackageTemplate = await createTestWorkPackageTemplate(testSuperman, orgId); + await WorkPackageTemplatesService.deleteWorkPackageTemplate( + testSuperman, + testWorkPackageTemplate.workPackageTemplateId, + organization + ); + + await expect( + async () => + await WorkPackageTemplatesService.deleteWorkPackageTemplate( + testSuperman, + testWorkPackageTemplate.workPackageTemplateId, + organization + ) + ).rejects.toThrow(new DeletedException('Work Package Template', testWorkPackageTemplate.workPackageTemplateId)); + }); + + it('succeeds and deletes all blocking templates', async () => { + const testSuperman = await createTestUser(supermanAdmin, orgId); + const [testWorkPackageTemplate1, testWorkPackageTemplate2, testWorkPackageTemplate3] = await Promise.all([ + createTestWorkPackageTemplate(testSuperman, orgId), + createTestWorkPackageTemplate(testSuperman, orgId), + createTestWorkPackageTemplate(testSuperman, orgId) + ]); + + await prisma.work_Package_Template.update({ + where: { + workPackageTemplateId: testWorkPackageTemplate3.workPackageTemplateId + }, + data: { + blockedBy: { + connect: { + workPackageTemplateId: testWorkPackageTemplate2.workPackageTemplateId + } + } + } + }); + + await prisma.work_Package_Template.update({ + where: { + workPackageTemplateId: testWorkPackageTemplate2.workPackageTemplateId + }, + data: { + blockedBy: { + connect: { + workPackageTemplateId: testWorkPackageTemplate1.workPackageTemplateId + } + } + } + }); + + await WorkPackageTemplatesService.deleteWorkPackageTemplate( + testSuperman, + testWorkPackageTemplate1.workPackageTemplateId, + organization + ); + + const updatedTestWorkPackageTemplate1 = await WorkPackageTemplatesService.getSingleWorkPackageTemplate( + testSuperman, + testWorkPackageTemplate1.workPackageTemplateId, + organization + ); + + const updatedTestWorkPackageTemplate2 = await WorkPackageTemplatesService.getSingleWorkPackageTemplate( + testSuperman, + testWorkPackageTemplate2.workPackageTemplateId, + organization + ); + const updatedTestWorkPackageTemplate3 = await WorkPackageTemplatesService.getSingleWorkPackageTemplate( + testSuperman, + testWorkPackageTemplate3.workPackageTemplateId, + organization + ); + + expect(updatedTestWorkPackageTemplate1.dateDeleted).not.toBe(null); + expect(updatedTestWorkPackageTemplate2.dateDeleted).not.toBe(null); + expect(updatedTestWorkPackageTemplate3.dateDeleted).not.toBe(null); + }); + }); +}); diff --git a/src/backend/tests/unmocked/announcements.test.ts b/src/backend/tests/unmocked/announcements.test.ts new file mode 100644 index 0000000000..3981d1feb9 --- /dev/null +++ b/src/backend/tests/unmocked/announcements.test.ts @@ -0,0 +1,91 @@ +import { Organization } from '@prisma/client'; +import { batmanAppAdmin } from '../test-data/users.test-data'; +import { createTestOrganization, createTestUser, resetUsers } from '../test-utils'; +import AnnouncementService from '../../src/services/announcement.service'; + +describe('Announcemnts Tests', () => { + let orgId: string; + let organization: Organization; + beforeEach(async () => { + organization = await createTestOrganization(); + orgId = organization.organizationId; + }); + + afterEach(async () => { + await resetUsers(); + }); + describe('Get Announcements', () => { + it('Succeeds and gets user announcements', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + await AnnouncementService.createAnnouncement( + 'test1', + [testBatman.userId], + new Date(), + 'Thomas Emrax', + '1', + 'software', + organization.organizationId + ); + await AnnouncementService.createAnnouncement( + 'test2', + [testBatman.userId], + new Date(), + 'Superman', + '50', + 'mechanical', + organization.organizationId + ); + + const announcements = await AnnouncementService.getUserUnreadAnnouncements( + testBatman.userId, + organization.organizationId + ); + + expect(announcements).toHaveLength(2); + expect(announcements[0].text).toBe('test1'); + expect(announcements[1].text).toBe('test2'); + }); + }); + + describe('Remove Announcement', () => { + it('Succeeds and removes user announcement', async () => { + const testBatman = await createTestUser(batmanAppAdmin, orgId); + await AnnouncementService.createAnnouncement( + 'test1', + [testBatman.userId], + new Date(), + 'Thomas Emrax', + '1', + 'software', + organization.organizationId + ); + await AnnouncementService.createAnnouncement( + 'test2', + [testBatman.userId], + new Date(), + 'Superman', + '50', + 'mechanical', + organization.organizationId + ); + + const announcements = await AnnouncementService.getUserUnreadAnnouncements( + testBatman.userId, + organization.organizationId + ); + + expect(announcements).toHaveLength(2); + expect(announcements[0].text).toBe('test1'); + expect(announcements[1].text).toBe('test2'); + + const updatedAnnouncements = await AnnouncementService.removeUserAnnouncement( + testBatman.userId, + announcements[0].announcementId, + organization.organizationId + ); + + expect(updatedAnnouncements).toHaveLength(1); + expect(updatedAnnouncements[0].text).toBe('test2'); + }); + }); +}); diff --git a/src/frontend/Dockerfile b/src/frontend/Dockerfile index 9d4c17efbc..fdbb52942d 100644 --- a/src/frontend/Dockerfile +++ b/src/frontend/Dockerfile @@ -1,5 +1,5 @@ # TO BE RUN FROM DOCKER COMPOSE. DO NOT RUN MANUALLY AS CONTEXT IS NOT SET CORRECTLY -FROM node:18 AS builder +FROM node:20 AS builder WORKDIR /base diff --git a/src/frontend/src/apis/announcements.api.ts b/src/frontend/src/apis/announcements.api.ts new file mode 100644 index 0000000000..6bac7d1c8e --- /dev/null +++ b/src/frontend/src/apis/announcements.api.ts @@ -0,0 +1,26 @@ +import { Announcement } from 'shared'; +import axios from '../utils/axios'; +import { apiUrls } from '../utils/urls'; +import { announcementsTransformer } from './transformers/announcements.transformer'; + +/* + * Gets all unread announcement of the user with the given id + */ +export const getAnnouncements = () => { + return axios.get(apiUrls.announcementsCurrentUser(), { + transformResponse: (data) => JSON.parse(data).map(announcementsTransformer) + }); +}; + +/* + * Removes a notification from the user with the given id + */ +export const removeAnnouncement = (announcementId: string) => { + return axios.post( + apiUrls.announcementsRemove(announcementId), + {}, + { + transformResponse: (data) => JSON.parse(data).map(announcementsTransformer) + } + ); +}; diff --git a/src/frontend/src/apis/finance.api.ts b/src/frontend/src/apis/finance.api.ts index 666ad7ebf8..058ca42a3a 100644 --- a/src/frontend/src/apis/finance.api.ts +++ b/src/frontend/src/apis/finance.api.ts @@ -7,7 +7,8 @@ import { EditReimbursementRequestPayload, EditVendorPayload, AccountCodePayload, - RefundPayload + RefundPayload, + MarkDeliveredRequestPayload } from '../hooks/finance.hooks'; import axios from '../utils/axios'; import { apiUrls } from '../utils/urls'; @@ -53,8 +54,8 @@ export const createReimbursementRequest = (formData: CreateReimbursementRequestP * @param id id of the reimbursement request being marked as delivered * @returns the updated reimbursement request */ -export const markReimbursementRequestAsDelivered = (id: string) => { - return axios.post(apiUrls.financeMarkAsDelivered(id)); +export const markReimbursementRequestAsDelivered = (id: string, formData: MarkDeliveredRequestPayload) => { + return axios.post(apiUrls.financeMarkAsDelivered(id), formData); }; /** diff --git a/src/frontend/src/apis/onboarding.api.ts b/src/frontend/src/apis/onboarding.api.ts new file mode 100644 index 0000000000..7912e80516 --- /dev/null +++ b/src/frontend/src/apis/onboarding.api.ts @@ -0,0 +1,16 @@ +import axios from 'axios'; +import { apiUrls } from '../utils/urls'; + +/** + * API Call to download a google image + * @param fileId file id to be downloaded + * @returns an image blob + */ +export const downloadGoogleImage = async (fileId: string): Promise => { + const response = await axios.get(apiUrls.imageById(fileId), { + responseType: 'arraybuffer' // Set the response type to 'arraybuffer' to receive the image as a Buffer + }); + const imageBuffer = new Uint8Array(response.data); + const imageBlob = new Blob([imageBuffer], { type: response.headers['content-type'] }); + return imageBlob; +}; diff --git a/src/frontend/src/apis/organizations.api.ts b/src/frontend/src/apis/organizations.api.ts new file mode 100644 index 0000000000..6821c74543 --- /dev/null +++ b/src/frontend/src/apis/organizations.api.ts @@ -0,0 +1,64 @@ +import axios from '../utils/axios'; +import { Organization, Project } from 'shared'; +import { apiUrls } from '../utils/urls'; + +/** + * Create a design review + * @param payload all info needed to create a design review + */ +export const getCurrentOrganization = async () => { + return axios.get(apiUrls.currentOrganization(), { + transformResponse: (data) => JSON.parse(data) + }); +}; + +export const getFeaturedProjects = async () => { + return axios.get(apiUrls.organizationsFeaturedProjects(), { + transformResponse: (data) => JSON.parse(data) + }); +}; + +export const setOrganizationDescription = async (description: string) => { + return axios.post(apiUrls.organizationsSetDescription(), { + description + }); +}; + +export const getOrganizationLogo = async () => { + return axios.get(apiUrls.organizationsLogoImage(), { + transformResponse: (data) => JSON.parse(data) + }); +}; + +export const setOrganizationLogo = async (file: File) => { + const formData = new FormData(); + formData.append('logo', file); + return axios.post(apiUrls.organizationsSetLogoImage(), formData); +}; + +export const setOrganizationFeaturedProjects = async (featuredProjectIds: string[]) => { + return axios.post(apiUrls.organizationsSetFeaturedProjects(), { + projectIds: featuredProjectIds + }); +}; + +export const setOrganizationWorkspaceId = async (workspaceId: string) => { + return axios.post(apiUrls.organizationsSetWorkspaceId(), { + workspaceId + }); +}; + +/** + * Downloads a given fileId from google drive into a blob + * + * @param fileId the google id of the file to download + * @returns the downloaded file as a Blob + */ +export const downloadGoogleImage = async (fileId: string): Promise => { + const response = await axios.get(apiUrls.imageById(fileId), { + responseType: 'arraybuffer' // Set the response type to 'arraybuffer' to receive the image as a Buffer + }); + const imageBuffer = new Uint8Array(response.data); + const imageBlob = new Blob([imageBuffer], { type: response.headers['content-type'] }); + return imageBlob; +}; diff --git a/src/frontend/src/apis/pop-ups.api.ts b/src/frontend/src/apis/pop-ups.api.ts new file mode 100644 index 0000000000..a0674b9527 --- /dev/null +++ b/src/frontend/src/apis/pop-ups.api.ts @@ -0,0 +1,19 @@ +import axios from '../utils/axios'; +import { apiUrls } from '../utils/urls'; +import { PopUp } from 'shared'; + +/* + * Gets all unread notifications of the user with the given id + */ +export const getPopUps = () => { + return axios.get(apiUrls.popUpsCurrentUser(), { + transformResponse: (data) => JSON.parse(data) + }); +}; + +/* + * Removes a notification from the user with the given id + */ +export const removePopUps = (notificationId: string) => { + return axios.post(apiUrls.popUpsRemove(notificationId)); +}; diff --git a/src/frontend/src/apis/recruitment.api.ts b/src/frontend/src/apis/recruitment.api.ts index 0a55fe5ced..a40f46b57d 100644 --- a/src/frontend/src/apis/recruitment.api.ts +++ b/src/frontend/src/apis/recruitment.api.ts @@ -22,6 +22,10 @@ export const editMilestone = (payload: MilestonePayload, id: string) => { }); }; +export const deleteMilestone = (milestoneId: string) => { + return axios.delete<{ message: string }>(apiUrls.milestoneDelete(milestoneId)); +}; + export const getAllFaqs = () => { return axios.get(apiUrls.allFaqs(), { transformResponse: (data) => JSON.parse(data) @@ -39,3 +43,7 @@ export const editFaq = (payload: FaqPayload, id: string) => { ...payload }); }; + +export const deleteFaq = (faqId: string) => { + return axios.delete<{ message: string }>(apiUrls.faqDelete(faqId)); +}; diff --git a/src/frontend/src/apis/transformers/announcements.transformer.ts b/src/frontend/src/apis/transformers/announcements.transformer.ts new file mode 100644 index 0000000000..821b8d6043 --- /dev/null +++ b/src/frontend/src/apis/transformers/announcements.transformer.ts @@ -0,0 +1,9 @@ +import { Announcement } from 'shared'; + +export const announcementsTransformer = (announcement: Announcement): Announcement => { + return { + ...announcement, + dateMessageSent: new Date(announcement.dateMessageSent), + dateDeleted: announcement.dateDeleted ? new Date(announcement.dateDeleted) : undefined + }; +}; diff --git a/src/frontend/src/apis/users.api.ts b/src/frontend/src/apis/users.api.ts index 44d7a40d70..afa5ea00f6 100644 --- a/src/frontend/src/apis/users.api.ts +++ b/src/frontend/src/apis/users.api.ts @@ -7,6 +7,7 @@ import axios from '../utils/axios'; import { Project, SetUserScheduleSettingsPayload, + Task, User, UserScheduleSettings, UserSecureSettings, @@ -21,6 +22,7 @@ import { } from './transformers/users.transformers'; import { AuthenticatedUser, UserSettings } from 'shared'; import { projectTransformer } from './transformers/projects.transformers'; +import { taskTransformer } from './transformers/tasks.transformers'; /** * Fetches all users. @@ -141,3 +143,19 @@ export const updateUserScheduleSettings = (settings: SetUserScheduleSettingsPayl export const updateUserRole = (id: string, role: string) => { return axios.post<{ message: string }>(apiUrls.userRoleByUserId(id), { role }); }; + +export const getUserTasks = (id: string) => { + return axios.get(apiUrls.userTasks(id), { + transformResponse: (data) => JSON.parse(data).map(taskTransformer) + }); +}; + +export const getManyUserTasks = (userIds: string[]) => { + return axios.post( + apiUrls.manyUserTasks(), + { userIds }, + { + transformResponse: (data) => JSON.parse(data).map(taskTransformer) + } + ); +}; diff --git a/src/frontend/src/app/AppAuthenticated.tsx b/src/frontend/src/app/AppAuthenticated.tsx index b16565bd79..2d5af43022 100644 --- a/src/frontend/src/app/AppAuthenticated.tsx +++ b/src/frontend/src/app/AppAuthenticated.tsx @@ -122,6 +122,7 @@ const AppAuthenticated: React.FC = ({ userId, userRole }) + diff --git a/src/frontend/src/app/AppOrganizationContext.tsx b/src/frontend/src/app/AppOrganizationContext.tsx index f469aa01e7..08860b1355 100644 --- a/src/frontend/src/app/AppOrganizationContext.tsx +++ b/src/frontend/src/app/AppOrganizationContext.tsx @@ -1,5 +1,5 @@ import { createContext } from 'react'; -import { useProvideOrganization } from '../hooks/organization.hooks'; +import { useProvideOrganization } from '../hooks/organizations.hooks'; export interface Organization { organizationId: string; diff --git a/src/frontend/src/app/AppPublic.tsx b/src/frontend/src/app/AppPublic.tsx index e0627cb160..8e5764a64c 100644 --- a/src/frontend/src/app/AppPublic.tsx +++ b/src/frontend/src/app/AppPublic.tsx @@ -10,7 +10,7 @@ import Login from '../pages/LoginPage/Login'; import AppAuthenticated from './AppAuthenticated'; import { useProvideThemeToggle } from '../hooks/theme.hooks'; import LoadingIndicator from '../components/LoadingIndicator'; -import { useOrganization } from '../hooks/organization.hooks'; +import { useOrganization } from '../hooks/organizations.hooks'; import Organizations from '../pages/OrganizationPage/Organizations'; const AppPublic: React.FC = () => { diff --git a/src/frontend/src/components/ChangeRequestDetailCard.tsx b/src/frontend/src/components/ChangeRequestDetailCard.tsx index 852f6d0007..c94beaffdc 100644 --- a/src/frontend/src/components/ChangeRequestDetailCard.tsx +++ b/src/frontend/src/components/ChangeRequestDetailCard.tsx @@ -68,8 +68,19 @@ interface ChangeRequestDetailCardProps { } const ChangeRequestDetailCard: React.FC = ({ changeRequest }) => { + const theme = useTheme(); return ( - + diff --git a/src/frontend/src/components/NERDeleteModal.tsx b/src/frontend/src/components/NERDeleteModal.tsx new file mode 100644 index 0000000000..a2f0f243f9 --- /dev/null +++ b/src/frontend/src/components/NERDeleteModal.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { FieldValues, useForm } from 'react-hook-form'; +import { Typography } from '@mui/material'; +import NERFormModal from './NERFormModal'; +import { NERModalProps } from './NERModal'; + +interface NERDeleteModalProps extends Omit { + onFormSubmit: (data: T) => void; + dataType: string; +} + +const NERDeleteModal = ({ open, onHide, dataType, onFormSubmit }: NERDeleteModalProps) => { + const { handleSubmit, reset } = useForm({ + mode: 'onChange' + }); + + return ( + + Are you sure you want to delete this {dataType}? + This action cannot be undone! + + ); +}; + +export default NERDeleteModal; diff --git a/src/frontend/src/components/PageLayout.tsx b/src/frontend/src/components/PageLayout.tsx index 861e363e5e..c4fb24d7db 100644 --- a/src/frontend/src/components/PageLayout.tsx +++ b/src/frontend/src/components/PageLayout.tsx @@ -20,6 +20,8 @@ interface PageLayoutProps { stickyHeader?: boolean; } +export const PAGE_GRID_HEIGHT = 85; + const PageLayout: React.FC = ({ children, title, diff --git a/src/frontend/src/components/PopUpAlert.tsx b/src/frontend/src/components/PopUpAlert.tsx new file mode 100644 index 0000000000..0a0b271b66 --- /dev/null +++ b/src/frontend/src/components/PopUpAlert.tsx @@ -0,0 +1,49 @@ +import { Box } from '@mui/material'; +import React, { useEffect, useState } from 'react'; +import { PopUp } from 'shared'; +import PopUpCard from './PopUpCard'; +import { useHistory } from 'react-router-dom'; +import { useCurrentUserPopUps, useRemoveUserPopUp } from '../hooks/pop-ups.hooks'; + +const PopUpAlert: React.FC = () => { + const { data: popUps, isLoading: popUpsIsLoading } = useCurrentUserPopUps(); + const { mutateAsync: removePopUp, isLoading: removeIsLoading } = useRemoveUserPopUp(); + const [currentPopUp, setCurrentPopUp] = useState(); + const history = useHistory(); + + useEffect(() => { + if (popUps && popUps.length > 0) { + setCurrentPopUp(popUps[0]); + } + }, [popUps]); + + const removePopUpWrapper = async (popUp: PopUp) => { + setCurrentPopUp(undefined); + await removePopUp(popUp); + }; + + const onClick = async (popUp: PopUp) => { + if (!!popUp.eventLink) { + await removePopUpWrapper(popUp); + history.push(popUp.eventLink); + } + }; + + return ( + + {!removeIsLoading && !popUpsIsLoading && currentPopUp && ( + + )} + + ); +}; + +export default PopUpAlert; diff --git a/src/frontend/src/components/PopUpCard.tsx b/src/frontend/src/components/PopUpCard.tsx new file mode 100644 index 0000000000..e905ca2ad6 --- /dev/null +++ b/src/frontend/src/components/PopUpCard.tsx @@ -0,0 +1,74 @@ +import { Box, Card, Icon, IconButton, Typography, useTheme } from '@mui/material'; +import React from 'react'; +import { PopUp } from 'shared'; +import CloseIcon from '@mui/icons-material/Close'; + +interface PopUpCardProps { + popUp: PopUp; + removePopUp: (popUp: PopUp) => Promise; + onClick: (popUp: PopUp) => Promise; +} + +const PopUpCard: React.FC = ({ popUp, removePopUp, onClick }) => { + const theme = useTheme(); + return ( + + + await onClick(popUp)} + sx={{ + display: 'flex', + alignItems: 'center', + gap: 1, + cursor: !!popUp.eventLink ? 'pointer' : 'default' + }} + > + + + {popUp.iconName} + + + {popUp.text} + + removePopUp(popUp)}> + + + + + ); +}; + +export default PopUpCard; diff --git a/src/frontend/src/hooks/announcements.hooks.ts b/src/frontend/src/hooks/announcements.hooks.ts new file mode 100644 index 0000000000..50cceea661 --- /dev/null +++ b/src/frontend/src/hooks/announcements.hooks.ts @@ -0,0 +1,36 @@ +import { useMutation, useQuery, useQueryClient } from 'react-query'; +import { Announcement } from 'shared'; +import { getAnnouncements, removeAnnouncement } from '../apis/announcements.api'; + +/** + * Curstom react hook to get all unread announcements from a user + * @param userId id of user to get unread announcements from + * @returns + */ +export const useUserAnnouncements = () => { + return useQuery(['announcements', 'current-user'], async () => { + const { data } = await getAnnouncements(); + return data; + }); +}; + +/** + * Curstom react hook to remove a announcement from a user's unread announcements + * @param userId id of user to get unread announcements from + * @returns + */ +export const useRemoveUserAnnouncement = () => { + const queryClient = useQueryClient(); + return useMutation( + ['announcements', 'current-user', 'remove'], + async (announcement: Announcement) => { + const { data } = await removeAnnouncement(announcement.announcementId); + return data; + }, + { + onSuccess: () => { + queryClient.invalidateQueries(['announcements', 'current-user']); + } + } + ); +}; diff --git a/src/frontend/src/hooks/finance.hooks.ts b/src/frontend/src/hooks/finance.hooks.ts index c3ecbe93e4..e92c016a31 100644 --- a/src/frontend/src/hooks/finance.hooks.ts +++ b/src/frontend/src/hooks/finance.hooks.ts @@ -85,6 +85,10 @@ export interface RefundPayload { dateReceived: string; } +export interface MarkDeliveredRequestPayload { + dateDelivered: Date; +} + /** * Custom React Hook to upload a new picture. */ @@ -232,10 +236,10 @@ export const useAllReimbursements = () => { */ export const useMarkReimbursementRequestAsDelivered = (id: string) => { const queryClient = useQueryClient(); - return useMutation( + return useMutation( ['reimbursement-requests', 'edit'], - async () => { - const { data } = await markReimbursementRequestAsDelivered(id); + async (markDeliveredData: MarkDeliveredRequestPayload) => { + const { data } = await markReimbursementRequestAsDelivered(id, markDeliveredData); return data; }, { @@ -394,13 +398,13 @@ export const useDownloadCSVFileOfReimbursementRequests = () => { const { data } = await getAllReimbursementRequests(); const csvContent = 'data:text/csv;charset=utf-8,' + - 'SABO ID,Recipient,Total Cost,Status,Account,Date Created,Date Delivered,Date Submitted,Vendor\n' + + 'SABO ID,FinishLine ID,Recipient,Total Cost,Status,Account,Account Code,Date Created,Date Delivered,Date Submitted,Vendor\n' + data .map( (rr) => - `${rr.saboId},${fullNamePipe(rr.recipient)},${rr.totalCost},${ + `${rr.saboId},${rr.identifier},${fullNamePipe(rr.recipient)},${rr.totalCost},${ rr.reimbursementStatuses[rr.reimbursementStatuses.length - 1].type - },${rr.account},${rr.dateCreated},${rr.dateDelivered ?? ''},${ + },${rr.account},${rr.accountCode.code},${rr.dateCreated},${rr.dateDelivered ?? ''},${ rr.reimbursementStatuses.find((rs) => rs.type === ReimbursementStatusType.SABO_SUBMITTED)?.dateCreated ?? '' },${rr.vendor.name}` ) diff --git a/src/frontend/src/hooks/organizations.hooks.ts b/src/frontend/src/hooks/organizations.hooks.ts new file mode 100644 index 0000000000..c317f040b8 --- /dev/null +++ b/src/frontend/src/hooks/organizations.hooks.ts @@ -0,0 +1,125 @@ +import { useContext, useState } from 'react'; +import { OrganizationContext } from '../app/AppOrganizationContext'; +import { useMutation, useQuery, useQueryClient } from 'react-query'; +import { Organization, Project } from 'shared'; +import { + getFeaturedProjects, + getCurrentOrganization, + setOrganizationDescription, + setOrganizationFeaturedProjects, + setOrganizationWorkspaceId, + setOrganizationLogo, + getOrganizationLogo +} from '../apis/organizations.api'; +import { downloadGoogleImage } from '../apis/organizations.api'; + +interface OrganizationProvider { + organizationId: string; + selectOrganization: (organizationId: string) => void; +} + +export const useProvideOrganization = (): OrganizationProvider => { + const [organizationId, setOrganizationId] = useState(''); + + const selectOrganization = (organizationId: string) => { + setOrganizationId(organizationId); + localStorage.setItem('organizationId', organizationId); + }; + + return { + organizationId, + selectOrganization + }; +}; + +export const useCurrentOrganization = () => { + return useQuery(['organizations'], async () => { + const { data } = await getCurrentOrganization(); + return data; + }); +}; + +export const useFeaturedProjects = () => { + return useQuery(['organizations', 'featured-projects'], async () => { + const { data } = await getFeaturedProjects(); + return data; + }); +}; + +// Hook for child components to get the auth object +export const useOrganization = () => { + const context = useContext(OrganizationContext); + if (context === undefined) throw Error('Organization must be used inside of an organizational context.'); + return context; +}; + +/** + * Custom React Hook to set the description of an organization + * @returns the updated organization + */ +export const useSetOrganizationDescription = () => { + const queryClient = useQueryClient(); + return useMutation( + ['organizations', 'description'], + async (description: string) => { + const { data } = await setOrganizationDescription(description); + return data; + }, + { + onSuccess: () => { + queryClient.invalidateQueries(['organizations']); + } + } + ); +}; + +export const useSetFeaturedProjects = () => { + const queryClient = useQueryClient(); + return useMutation( + ['organizations', 'featured-projects'], + async (featuredProjects: Project[]) => { + const { data } = await setOrganizationFeaturedProjects(featuredProjects.map((project) => project.id)); + return data; + }, + { + onSuccess: () => { + queryClient.invalidateQueries(['organizations']); + } + } + ); +}; + +export const useSetWorkspaceId = () => { + const queryClient = useQueryClient(); + return useMutation( + ['organizations', 'featured-projects'], + async (workspaceId: string) => { + const { data } = await setOrganizationWorkspaceId(workspaceId); + return data; + }, + { + onSuccess: () => { + queryClient.invalidateQueries(['organizations']); + } + } + ); +}; + +export const useSetOrganizationLogo = () => { + const queryClient = useQueryClient(); + return useMutation(['reimbursement-requsts', 'edit'], async (file: File) => { + const { data } = await setOrganizationLogo(file); + queryClient.invalidateQueries(['organizations']); + return data; + }); +}; + +export const useOrganizationLogo = () => { + return useQuery(['organizations', 'logo'], async () => { + const { data: fileId } = await getOrganizationLogo(); + if (!fileId) { + return; + } + return await downloadGoogleImage(fileId); + }); +}; diff --git a/src/frontend/src/hooks/pop-ups.hooks.ts b/src/frontend/src/hooks/pop-ups.hooks.ts new file mode 100644 index 0000000000..7816102dd6 --- /dev/null +++ b/src/frontend/src/hooks/pop-ups.hooks.ts @@ -0,0 +1,36 @@ +import { useMutation, useQuery, useQueryClient } from 'react-query'; +import { PopUp } from 'shared'; +import { getPopUps, removePopUps } from '../apis/pop-ups.api'; + +/** + * Curstom react hook to get all unread notifications from a user + * @param userId id of user to get unread notifications from + * @returns + */ +export const useCurrentUserPopUps = () => { + return useQuery(['pop-ups', 'current-user'], async () => { + const { data } = await getPopUps(); + return data; + }); +}; + +/** + * Curstom react hook to remove a notification from a user's unread notifications + * @param userId id of user to get unread notifications from + * @returns + */ +export const useRemoveUserPopUp = () => { + const queryClient = useQueryClient(); + return useMutation( + ['pop-ups', 'current-user', 'remove'], + async (popUp: PopUp) => { + const { data } = await removePopUps(popUp.popUpId); + return data; + }, + { + onSuccess: () => { + queryClient.invalidateQueries(['pop-ups', 'current-user']); + } + } + ); +}; diff --git a/src/frontend/src/hooks/recruitment.hooks.ts b/src/frontend/src/hooks/recruitment.hooks.ts index a96a6c1a34..ecd18bfa00 100644 --- a/src/frontend/src/hooks/recruitment.hooks.ts +++ b/src/frontend/src/hooks/recruitment.hooks.ts @@ -1,6 +1,15 @@ import { useMutation, useQuery, useQueryClient } from 'react-query'; import { Milestone } from 'shared/src/types/milestone-types'; -import { createFaq, createMilestone, editFaq, editMilestone, getAllFaqs, getAllMilestones } from '../apis/recruitment.api'; +import { + createFaq, + createMilestone, + deleteFaq, + deleteMilestone, + editFaq, + editMilestone, + getAllFaqs, + getAllMilestones +} from '../apis/recruitment.api'; import { FrequentlyAskedQuestion } from 'shared/src/types/frequently-asked-questions-types'; export interface MilestonePayload { @@ -53,6 +62,22 @@ export const useEditMilestone = (id: string) => { ); }; +export const useDeleteMilestone = () => { + const queryClient = useQueryClient(); + return useMutation<{ message: string }, Error, any>( + ['milestones', 'delete'], + async (milestoneId: string) => { + const { data } = await deleteMilestone(milestoneId); + return data; + }, + { + onSuccess: () => { + queryClient.invalidateQueries(['milestones']); + } + } + ); +}; + export const useAllFaqs = () => { return useQuery(['faqs'], async () => { const { data } = await getAllFaqs(); @@ -91,3 +116,19 @@ export const useEditFaq = (id: string) => { } ); }; + +export const useDeleteFAQ = () => { + const queryClient = useQueryClient(); + return useMutation<{ message: string }, Error, any>( + ['faqs', 'delete'], + async (faqId: string) => { + const { data } = await deleteFaq(faqId); + return data; + }, + { + onSuccess: () => { + queryClient.invalidateQueries(['faqs']); + } + } + ); +}; diff --git a/src/frontend/src/hooks/users.hooks.ts b/src/frontend/src/hooks/users.hooks.ts index b0c76b09b9..96b659c1f1 100644 --- a/src/frontend/src/hooks/users.hooks.ts +++ b/src/frontend/src/hooks/users.hooks.ts @@ -17,7 +17,9 @@ import { getCurrentUserSecureSettings, getUserSecureSettings, getUserScheduleSettings, - updateUserScheduleSettings + updateUserScheduleSettings, + getUserTasks, + getManyUserTasks } from '../apis/users.api'; import { User, @@ -28,7 +30,8 @@ import { UserSecureSettings, UserScheduleSettings, UserWithScheduleSettings, - SetUserScheduleSettingsPayload + SetUserScheduleSettingsPayload, + Task } from 'shared'; import { useAuth } from './auth.hooks'; import { useContext } from 'react'; @@ -233,3 +236,27 @@ export const useUpdateUserRole = () => { } ); }; + +/** + * Custom React Hook to get the user's assigned tasks + * @param userId user to get assigned tasks of + * @returns user's assigned task + */ +export const useUserTasks = (userId: string) => { + return useQuery(['users', userId, 'tasks'], async () => { + const { data } = await getUserTasks(userId); + return data; + }); +}; + +/** + * Custom react hook to get the assigned tasks of all users in the list + * @param userIds ids of users to get assigned tasks from + * @returns tasks assigned to all users in list + */ +export const useManyUserTasks = (userIds: string[]) => { + return useQuery(['users', userIds, 'tasks'], async () => { + const { data } = await getManyUserTasks(userIds); + return data; + }); +}; diff --git a/src/frontend/src/pages/AdminToolsPage/AdminToolsPage.tsx b/src/frontend/src/pages/AdminToolsPage/AdminToolsPage.tsx index 9cdf7d1ad1..f99d21f08e 100644 --- a/src/frontend/src/pages/AdminToolsPage/AdminToolsPage.tsx +++ b/src/frontend/src/pages/AdminToolsPage/AdminToolsPage.tsx @@ -18,6 +18,8 @@ import NERTabs from '../../components/Tabs'; import { routes } from '../../utils/routes'; import { Box } from '@mui/system'; import AdminToolsRecruitmentConfig from './RecruitmentConfig/AdminToolsRecruitmentConfig'; +import GuestViewConfig from './EditGuestView/GuestViewConfig'; +import AdminToolsWorkspaceId from './AdminToolsSlackWorkspaceId'; const AdminToolsPage: React.FC = () => { const currentUser = useCurrentUser(); @@ -40,6 +42,7 @@ const AdminToolsPage: React.FC = () => { } if (isUserAdmin) { tabs.push({ tabUrlValue: 'recruitment', tabName: 'Recruitment' }); + tabs.push({ tabUrlValue: 'guest-view', tabName: 'Guest View' }); tabs.push({ tabUrlValue: 'miscellaneous', tabName: 'Miscellaneous' }); } @@ -91,11 +94,14 @@ const AdminToolsPage: React.FC = () => { ) : tabIndex === 3 ? ( + ) : tabIndex === 4 ? ( + ) : ( + )} diff --git a/src/frontend/src/pages/AdminToolsPage/AdminToolsSlackWorkspaceId.tsx b/src/frontend/src/pages/AdminToolsPage/AdminToolsSlackWorkspaceId.tsx new file mode 100644 index 0000000000..57404352d9 --- /dev/null +++ b/src/frontend/src/pages/AdminToolsPage/AdminToolsSlackWorkspaceId.tsx @@ -0,0 +1,72 @@ +/* + * This file is part of NER's FinishLine and licensed under GNU AGPLv3. + * See the LICENSE file in the repository root folder for details. + */ + +import { NERButton } from '../../components/NERButton'; +import { Box, Link, TextField, Typography } from '@mui/material'; +import { useState } from 'react'; +import { useToast } from '../../hooks/toasts.hooks'; +import { useCurrentOrganization, useSetWorkspaceId } from '../../hooks/organizations.hooks'; +import LoadingIndicator from '../../components/LoadingIndicator'; +import ErrorPage from '../ErrorPage'; +import { Organization } from 'shared'; +import HelpIcon from '@mui/icons-material/Help'; + +interface AdminToolsWorkspaceIdViewProps { + organization: Organization; +} + +const AdminToolsWorkspaceId: React.FC = () => { + const { data: organization, isLoading, isError, error } = useCurrentOrganization(); + if (!organization || isLoading) return ; + if (isError) return ; + + return ; +}; + +const AdminToolsWorkspaceIdView: React.FC = ({ organization }) => { + const toast = useToast(); + const { mutateAsync, isLoading } = useSetWorkspaceId(); + const [workspaceId, setWorkspaceId] = useState(organization.slackWorkspaceId ?? ''); + + if (isLoading) return ; + + const slackWorkspaceId = async () => { + try { + await mutateAsync(workspaceId); + toast.success('Successfully updated the slack workspace id'); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + } + } + }; + + return ( + + + {organization.name} Slack Workspace Id + + + + + + setWorkspaceId(e.target.value)} /> + + + Update + + + + + ); +}; + +export default AdminToolsWorkspaceId; diff --git a/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditDescription.tsx b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditDescription.tsx new file mode 100644 index 0000000000..e00599f669 --- /dev/null +++ b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditDescription.tsx @@ -0,0 +1,83 @@ +import { Box, Card, TextField, Typography, useTheme } from '@mui/material'; +import React, { useState } from 'react'; +import { useCurrentOrganization, useSetOrganizationDescription } from '../../../hooks/organizations.hooks'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ErrorPage from '../../ErrorPage'; +import { NERButton } from '../../../components/NERButton'; +import EditDescriptionForm, { EditDescriptionInput } from './EditDescriptionForm'; +import { useToast } from '../../../hooks/toasts.hooks'; + +const EditDescription: React.FC = () => { + const [isEditMode, setIsEditMode] = useState(false); + const theme = useTheme(); + const { data: organization, isLoading, isError, error } = useCurrentOrganization(); + const { mutateAsync: setOrganizationDescription, isLoading: mutateIsLoading } = useSetOrganizationDescription(); + const toast = useToast(); + + const handleClose = () => { + setIsEditMode(false); + }; + + const onSubmit = async (formInput: EditDescriptionInput) => { + try { + await setOrganizationDescription(formInput.description); + toast.success('Description updated successfully!'); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + } + } + handleClose(); + }; + + if (isLoading || mutateIsLoading || !organization) return ; + if (isError) return ; + + return ( + + + {organization.name} Description + + {isEditMode ? ( + + ) : ( + + + + setIsEditMode(true)}> + Update + + + + )} + + ); +}; + +export default EditDescription; diff --git a/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditDescriptionForm.tsx b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditDescriptionForm.tsx new file mode 100644 index 0000000000..048a24180d --- /dev/null +++ b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditDescriptionForm.tsx @@ -0,0 +1,101 @@ +import React from 'react'; +import * as yup from 'yup'; +import { Controller, useForm } from 'react-hook-form'; +import { yupResolver } from '@hookform/resolvers/yup'; +import { Box, FormControl, TextField } from '@mui/material'; +import { countWords, isUnderWordCount, Organization } from 'shared'; +import NERFailButton from '../../../components/NERFailButton'; +import NERSuccessButton from '../../../components/NERSuccessButton'; + +const schema = yup.object().shape({ + description: yup.string() +}); + +export interface EditDescriptionInput { + description: string; +} + +interface EditDescriptionFormProps { + organization: Organization; + onSubmit: (formInput: EditDescriptionInput) => Promise; + onHide: () => void; + isEditMode: boolean; +} + +const EditDescriptionForm: React.FC = ({ organization, onSubmit, onHide, isEditMode }) => { + const { handleSubmit, control, reset } = useForm({ + resolver: yupResolver(schema), + defaultValues: { + description: organization.description ?? '' + } + }); + + const onSubmitWrapper = async (data: EditDescriptionInput) => { + await onSubmit(data); + reset(); + }; + + const onHideWrapper = () => { + onHide(); + reset(); + }; + + return ( +
{ + e.preventDefault(); + e.stopPropagation(); + handleSubmit(onSubmit)(e); + reset(); + }} + onKeyPress={(e) => { + e.key === 'Enter' && e.preventDefault(); + }} + > + + ( + + )} + /> + + {isEditMode && ( + + + Cancel + + + Save + + + )} +
+ ); +}; + +export default EditDescriptionForm; diff --git a/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjects.tsx b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjects.tsx new file mode 100644 index 0000000000..2a798dd67f --- /dev/null +++ b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjects.tsx @@ -0,0 +1,99 @@ +import React, { useState } from 'react'; +import EditFeaturedProjectsForm, { EditFeaturedProjectsFormInput } from './EditFeaturedProjectsForm'; +import { useFeaturedProjects, useSetFeaturedProjects } from '../../../hooks/organizations.hooks'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ErrorPage from '../../ErrorPage'; +import { Box, Card, Chip, Typography, useTheme } from '@mui/material'; +import { NERButton } from '../../../components/NERButton'; +import { useToast } from '../../../hooks/toasts.hooks'; +import { projectWbsNamePipe } from '../../../utils/pipes'; + +const EditFeaturedProjects = () => { + const { data: featuredProjects, isLoading, isError, error } = useFeaturedProjects(); + const { mutateAsync: setFeaturedProjects, isLoading: setFeaturedProjectsIsLoading } = useSetFeaturedProjects(); + const [isEditMode, setIsEditMode] = useState(false); + const theme = useTheme(); + const toast = useToast(); + + if (isLoading || !featuredProjects || setFeaturedProjectsIsLoading || !setFeaturedProjects) return ; + if (isError) return ; + + const handleClose = () => { + setIsEditMode(false); + }; + + const onSubmit = async (formInput: EditFeaturedProjectsFormInput) => { + try { + await setFeaturedProjects(formInput.featuredProjects); + toast.success('Featured Projects updated successfully!'); + } catch (error: unknown) { + if (error instanceof Error) { + toast.error(error.message); + } + } + handleClose(); + }; + + return ( + + + Featured Projects + + {isEditMode ? ( + + ) : ( + + + {featuredProjects.map((project) => ( + + ))} + + + setIsEditMode(true)}> + Update + + + + )} + + ); +}; + +export default EditFeaturedProjects; diff --git a/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjectsDropdown.tsx b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjectsDropdown.tsx new file mode 100644 index 0000000000..254e776e29 --- /dev/null +++ b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjectsDropdown.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { Autocomplete, Chip, TextField } from '@mui/material'; +import { Project } from 'shared'; +import { projectWbsNamePipe } from '../../../utils/pipes'; +import { useAllProjects } from '../../../hooks/projects.hooks'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ErrorPage from '../../ErrorPage'; + +interface EditFeatureProjectsDropdownProps { + onChange: (value: Project[] | null) => void; + value: Project[] | undefined; +} + +const EditFeaturedProjectsDropdown: React.FC = ({ onChange, value }) => { + const { data: allProjects, isLoading, isError, error } = useAllProjects(); + + if (isLoading || !allProjects) return ; + if (isError) return ; + + return ( + `${projectWbsNamePipe(option)}`} + isOptionEqualToValue={(option, value) => option.id === value.id} + value={value} + onChange={(_, newValue) => onChange(newValue)} + renderInput={(params) => } + renderTags={(tagValue, getTagProps) => + tagValue.map((option, index) => ( + + )) + } + placeholder={'Add a Project to Feature'} + /> + ); +}; + +export default EditFeaturedProjectsDropdown; diff --git a/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjectsForm.tsx b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjectsForm.tsx new file mode 100644 index 0000000000..8d89a2da07 --- /dev/null +++ b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditFeaturedProjectsForm.tsx @@ -0,0 +1,95 @@ +import { yupResolver } from '@hookform/resolvers/yup'; +import * as yup from 'yup'; +import React from 'react'; +import { Controller, useForm } from 'react-hook-form'; +import EditFeaturedProjectsDropdown from './EditFeaturedProjectsDropdown'; +import { Box, FormControl } from '@mui/material'; +import { Project } from 'shared'; +import NERFailButton from '../../../components/NERFailButton'; +import NERSuccessButton from '../../../components/NERSuccessButton'; + +const schema = yup.object().shape({ + description: yup.array().of(yup.string()) +}); + +export interface EditFeaturedProjectsFormInput { + featuredProjects: Project[]; +} + +interface EditFeaturedProjectsFormProps { + featuredProjects: Project[]; + onSubmit: (formInput: EditFeaturedProjectsFormInput) => Promise; + onHide: () => void; + isEditMode: boolean; +} + +const EditFeaturedProjectsForm: React.FC = ({ + featuredProjects, + onSubmit, + onHide, + isEditMode +}) => { + const { handleSubmit, control, reset } = useForm({ + resolver: yupResolver(schema), + defaultValues: { + featuredProjects: featuredProjects ?? [] + } + }); + + const onSubmitWrapper = async (data: EditFeaturedProjectsFormInput) => { + await onSubmit(data); + reset(); + }; + + const onHideWrapper = () => { + onHide(); + reset(); + }; + + return ( + + ); +}; + +export default EditFeaturedProjectsForm; diff --git a/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditLogo.tsx b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditLogo.tsx new file mode 100644 index 0000000000..d4c10f0e76 --- /dev/null +++ b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditLogo.tsx @@ -0,0 +1,93 @@ +import React, { useState } from 'react'; +import { useCurrentOrganization, useOrganizationLogo, useSetOrganizationLogo } from '../../../hooks/organizations.hooks'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import EditLogoForm, { EditLogoInput } from './EditLogoForm'; +import { useToast } from '../../../hooks/toasts.hooks'; +import { Box, Card, Typography, useTheme } from '@mui/material'; +import LogoDisplay from '../../HomePage/components/LogoDisplay'; +import { NERButton } from '../../../components/NERButton'; +import ErrorPage from '../../ErrorPage'; + +const EditLogo = () => { + const { + data: organization, + isLoading: organizationIsLoading, + isError: organizationIsError, + error: organizationError + } = useCurrentOrganization(); + const { data: imageData, isLoading: imageDataIsLoading, isError: imageIsError, error: imageError } = useOrganizationLogo(); + const { mutateAsync, isLoading } = useSetOrganizationLogo(); + const toast = useToast(); + const [isEditMode, setIsEditMode] = useState(false); + const theme = useTheme(); + + if (isLoading || !mutateAsync || organizationIsLoading || !organization || imageDataIsLoading) return ; + if (organizationIsError) return ; + if (imageIsError) return ; + + const handleClose = () => { + setIsEditMode(false); + }; + + const onSubmit = async (logoInput: EditLogoInput) => { + try { + if (!logoInput.logoImage) { + toast.error('No logo image submitted.'); + handleClose(); + return; + } + await mutateAsync(logoInput.logoImage); + toast.success('Logo updated successfully!'); + } catch (e) { + if (e instanceof Error) { + toast.error(e.message); + } + } + handleClose(); + }; + + return ( + + + {organization.name} Logo + + {isEditMode ? ( + + ) : ( + <> + + + + setIsEditMode(true)}> + Update + + + + + )} + + ); +}; + +export default EditLogo; diff --git a/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditLogoForm.tsx b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditLogoForm.tsx new file mode 100644 index 0000000000..72be9d618e --- /dev/null +++ b/src/frontend/src/pages/AdminToolsPage/EditGuestView/EditLogoForm.tsx @@ -0,0 +1,111 @@ +import React from 'react'; +import { Box, Button, FormControl, Stack, Typography } from '@mui/material'; +import FileUploadIcon from '@mui/icons-material/FileUpload'; +import { Controller, useForm } from 'react-hook-form'; +import NERFailButton from '../../../components/NERFailButton'; +import NERSuccessButton from '../../../components/NERSuccessButton'; +import ImageIcon from '@mui/icons-material/Image'; + +export interface EditLogoInput { + logoImage?: File; +} + +interface EditLogoFormProps { + onSubmit: (logoImage: EditLogoInput) => Promise; + onHide: () => void; + orgLogo?: File; +} + +const EditLogoForm: React.FC = ({ onSubmit, orgLogo, onHide }) => { + const { handleSubmit, control, reset } = useForm({ + defaultValues: { + logoImage: orgLogo + } + }); + + const onHideWrapper = () => { + onHide(); + reset(); + }; + + return ( + + ); +}; + +export default EditLogoForm; diff --git a/src/frontend/src/pages/AdminToolsPage/EditGuestView/GuestViewConfig.tsx b/src/frontend/src/pages/AdminToolsPage/EditGuestView/GuestViewConfig.tsx new file mode 100644 index 0000000000..419bb2548c --- /dev/null +++ b/src/frontend/src/pages/AdminToolsPage/EditGuestView/GuestViewConfig.tsx @@ -0,0 +1,22 @@ +import { Stack, Grid } from '@mui/material'; +import EditDescription from './EditDescription'; +import EditFeaturedProjects from './EditFeaturedProjects'; +import EditLogo from './EditLogo'; + +const GuestViewConfig: React.FC = () => { + return ( + + + + + + + + + + + + ); +}; + +export default GuestViewConfig; diff --git a/src/frontend/src/pages/AdminToolsPage/RecruitmentConfig/FAQTable.tsx b/src/frontend/src/pages/AdminToolsPage/RecruitmentConfig/FAQTable.tsx index e8c09e688b..1ba2cf1bdf 100644 --- a/src/frontend/src/pages/AdminToolsPage/RecruitmentConfig/FAQTable.tsx +++ b/src/frontend/src/pages/AdminToolsPage/RecruitmentConfig/FAQTable.tsx @@ -1,25 +1,43 @@ +import React, { useState } from 'react'; import { TableRow, TableCell, Box, Table as MuiTable, TableHead, TableBody, Typography, Button } from '@mui/material'; import EditIcon from '@mui/icons-material/Edit'; import DeleteIcon from '@mui/icons-material/Delete'; import { FrequentlyAskedQuestion } from 'shared/src/types/frequently-asked-questions-types'; import { NERButton } from '../../../components/NERButton'; -import { useAllFaqs } from '../../../hooks/recruitment.hooks'; +import { useAllFaqs, useDeleteFAQ } from '../../../hooks/recruitment.hooks'; import LoadingIndicator from '../../../components/LoadingIndicator'; import { useHistoryState } from '../../../hooks/misc.hooks'; import ErrorPage from '../../ErrorPage'; import CreateFaqFormModal from './CreateFaqFormModal'; import EditFaqFormModal from './EditFaqFormModal'; +import NERDeleteModal from '../../../components/NERDeleteModal'; +import { useToast } from '../../../hooks/toasts.hooks'; const FAQsTable = () => { const [createModalShow, setCreateModalShow] = useHistoryState('', false); const [faqEditing, setFaqEditing] = useHistoryState('', undefined); + const [faqToDelete, setFaqToDelete] = useState(undefined); + const { mutateAsync: deleteFaq } = useDeleteFAQ(); + const toast = useToast(); + const { isLoading: faqsIsLoading, isError: faqsIsError, error: faqsError, data: faqs } = useAllFaqs(); + const handleDelete = (id: string) => { + setFaqToDelete(undefined); + try { + deleteFaq(id); + toast.success('Faq deleted successfully'); + } catch (e: unknown) { + if (e instanceof Error) { + toast.error(e.message, 3000); + } + } + }; if (!faqs || faqsIsLoading) return ; if (faqsIsError) return ; const FAQsRows = faqs.map((faq: FrequentlyAskedQuestion, index: number) => ( - + { - @@ -96,6 +119,17 @@ const FAQsTable = () => { Add FAQ + setFaqToDelete(undefined)} + formId="delete-item-form" + dataType="FAQ" + onFormSubmit={() => { + if (faqToDelete) { + handleDelete(faqToDelete.faqId); + } + }} + /> ); }; diff --git a/src/frontend/src/pages/AdminToolsPage/RecruitmentConfig/MilestoneTable.tsx b/src/frontend/src/pages/AdminToolsPage/RecruitmentConfig/MilestoneTable.tsx index 57197ca32a..b4dc73df52 100644 --- a/src/frontend/src/pages/AdminToolsPage/RecruitmentConfig/MilestoneTable.tsx +++ b/src/frontend/src/pages/AdminToolsPage/RecruitmentConfig/MilestoneTable.tsx @@ -6,9 +6,12 @@ import CreateMilestoneFormModal from './CreateMilestoneFormModal'; import EditMilestoneFormModal from './EditMilestoneFormModal'; import LoadingIndicator from '../../../components/LoadingIndicator'; import { useHistoryState } from '../../../hooks/misc.hooks'; -import { useAllMilestones } from '../../../hooks/recruitment.hooks'; +import { useAllMilestones, useDeleteMilestone } from '../../../hooks/recruitment.hooks'; import ErrorPage from '../../ErrorPage'; import { NERButton } from '../../../components/NERButton'; +import NERDeleteModal from '../../../components/NERDeleteModal'; +import { useState } from 'react'; +import { useToast } from '../../../hooks/toasts.hooks'; const MilestoneTable = () => { const [createModalShow, setCreateModalShow] = useHistoryState('', false); @@ -20,6 +23,22 @@ const MilestoneTable = () => { data: milestones } = useAllMilestones(); + const handleDelete = (id: string) => { + setMilestoneToDelete(undefined); + try { + deleteMilestone(id); + toast.success('Milestone deleted successfully'); + } catch (e: unknown) { + if (e instanceof Error) { + toast.error(e.message, 3000); + } + } + }; + + const [milestoneToDelete, setMilestoneToDelete] = useState(undefined); + const { mutateAsync: deleteMilestone } = useDeleteMilestone(); + const toast = useToast(); + if (!milestones || milestonesIsLoading) return ; if (milestonesIsError) return ; @@ -57,7 +76,12 @@ const MilestoneTable = () => { - @@ -117,6 +141,17 @@ const MilestoneTable = () => { Add Milestone + setMilestoneToDelete(undefined)} + formId="delete-item-form" + dataType="Milestone" + onFormSubmit={() => { + if (milestoneToDelete) { + handleDelete(milestoneToDelete.milestoneId); + } + }} + /> ); }; diff --git a/src/frontend/src/pages/CalendarPage/DesignReviewSummaryModal.tsx b/src/frontend/src/pages/CalendarPage/DesignReviewSummaryModal.tsx index f1bb332285..9b3b1abdaa 100644 --- a/src/frontend/src/pages/CalendarPage/DesignReviewSummaryModal.tsx +++ b/src/frontend/src/pages/CalendarPage/DesignReviewSummaryModal.tsx @@ -1,6 +1,6 @@ -import { DesignReview, DesignReviewStatus, TeamType, isAdmin } from 'shared'; +import { DesignReview, DesignReviewStatus, TeamType, isAdmin, wbsPipe } from 'shared'; import NERModal from '../../components/NERModal'; -import { Box, Chip, IconButton, Typography } from '@mui/material'; +import { Box, Chip, IconButton, Link, Typography } from '@mui/material'; import EditIcon from '@mui/icons-material/Edit'; import { useState } from 'react'; import DesignReviewSummaryModalDetails from './SummaryComponents/DesignReviewSummaryModalDetails'; @@ -112,9 +112,15 @@ const DRCSummaryModal: React.FC = ({ - - {`${designReview.wbsName}`} - + + + {`${designReview.wbsName}`} + + { const user = useCurrentUser(); @@ -29,53 +29,9 @@ const ChangeRequestsOverview: React.FC = () => { if (projectIsError) return ; if (wpIsError) return ; - // projects whose change requests the user would have to review - const myProjects = projects.filter((project: Project) => { - const projectMemberIds = project.teams.flatMap((team) => makeTeamList(team)).map((user) => user.userId); - return ( - projectMemberIds.includes(user.userId) || - (project.lead && project.lead.userId === user.userId) || - (project.manager && project.manager.userId === user.userId) - ); - }); - - // work packages whose change requests the user would have to review - const myWorkPackages = workPackages.filter( - (wp: WorkPackage) => - (wp.lead ? wp.lead.userId === user.userId : false) || (wp.manager ? wp.manager.userId === user.userId : false) - ); - - // all of the wbs numbers (in x.x.x string format) corresponding to projects and work packages - // whose change requests the user would have to review - const myWbsNumbers = myProjects - .map((project: Project) => project.wbsNum) - .concat(myWorkPackages.map((wp: WorkPackage) => wp.wbsNum)); - - const currentDate = new Date(); - - const crToReview = changeRequests - .filter( - (cr) => - !cr.dateReviewed && - cr.submitter.userId !== user.userId && - (myWbsNumbers.some((wbsNum) => equalsWbsNumber(wbsNum, cr.wbsNum)) || - cr.requestedReviewers.map((user) => user.userId).includes(user.userId)) - ) - .sort((a, b) => b.dateSubmitted.getTime() - a.dateSubmitted.getTime()); - - const crUnreviewed = changeRequests - .filter((cr: ChangeRequest) => !cr.dateReviewed && cr.submitter.userId === user.userId) - .sort((a, b) => b.dateSubmitted.getTime() - a.dateSubmitted.getTime()); - - const crApproved = changeRequests - .filter( - (cr: ChangeRequest) => - cr.dateReviewed && - cr.accepted && - cr.submitter.userId === user.userId && - currentDate.getTime() - cr.dateReviewed.getTime() <= 1000 * 60 * 60 * 24 * 5 - ) - .sort((a, b) => (a.dateReviewed && b.dateReviewed ? b.dateReviewed.getTime() - a.dateReviewed.getTime() : 0)); + const crToReview = getCRsToReview(projects, workPackages, user, changeRequests); + const crUnreviewed = getCRsUnreviewed(user, changeRequests); + const crApproved = getCRsApproved(user, changeRequests); return ( <> diff --git a/src/frontend/src/pages/CreditsPage/CreditsPage.tsx b/src/frontend/src/pages/CreditsPage/CreditsPage.tsx index 0e4b52c7b1..830d4c148e 100644 --- a/src/frontend/src/pages/CreditsPage/CreditsPage.tsx +++ b/src/frontend/src/pages/CreditsPage/CreditsPage.tsx @@ -211,6 +211,7 @@ const CreditsPage: React.FC = () => { { name: 'Meggan Shvartsberg', color: '#00DBFF' }, { name: 'Visisht Kamalapuram', color: '#3083AA' }, { name: 'Jay Jung', color: '##344739' }, + { name: 'Elton Yu', color: '#f202a2' }, { name: 'Will Anderson', color: '#ebb145' }, { name: 'Alex Park', color: '#CCCCFF' }, { @@ -242,7 +243,23 @@ const CreditsPage: React.FC = () => { { name: 'Alex Dong', color: '#5d42f5' }, { name: 'Chris Li', color: '#5d42f5' }, { name: 'Kenneth Aldridge', color: '#E70D0D' }, - { name: 'Nishanth Chinnadurai', color: '#8E6B9F' } + { name: 'Nishanth Chinnadurai', color: '#8E6B9F' }, + { name: 'Nicholas Yokaitis', color: '#475380' }, + { name: 'Eric Yao', color: '#a5ff38' }, + { name: 'Haylie Pedersen', color: '#368048' }, + { name: 'Kinsey Bellerose', color: '#3281a8' }, + { name: 'Tyler Morrill', color: '#4a881b' }, + { name: 'Kyan Barker', color: '#5d42f5' }, + { name: 'Haiden Busick-Warner', color: '#FF33FD' }, + { name: 'Jason Kuo', color: '#a200ff' }, + { name: 'Wilson Wei', color: '#008000' }, + { name: 'Thanin Kongkiatsophon', color: '#15B392' }, + { name: 'Aryan Gupta', color: '#5a4094' }, + { name: 'Lisa Wan', color: '#CCCCFF' }, + { name: 'Aidan Wong', color: '#4284f5' }, + { name: 'Sarah Taylor', color: '#278f4b' }, + { name: 'Shrey Agarwal', color: '#800080' }, + { name: 'Amber Friar', color: '#F5A9B8' } ]; const snark = ['Add your name!', "Shouldn't you do it yourself?", 'Seriously', 'go', 'do', 'it']; diff --git a/src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/MarkDeliveredModal.tsx b/src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/MarkDeliveredModal.tsx new file mode 100644 index 0000000000..5e7942c1b9 --- /dev/null +++ b/src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/MarkDeliveredModal.tsx @@ -0,0 +1,125 @@ +import { Controller, useForm } from 'react-hook-form'; +import NERFormModal from '../../../components/NERFormModal'; +import { useMarkReimbursementRequestAsDelivered } from '../../../hooks/finance.hooks'; +import { useToast } from '../../../hooks/toasts.hooks'; +import * as yup from 'yup'; +import { yupResolver } from '@hookform/resolvers/yup'; +import { FormControl, FormControlLabel, FormLabel, Radio, RadioGroup } from '@mui/material'; +import { DatePicker } from '@mui/x-date-pickers'; +import { ReimbursementRequest, startOfDay } from 'shared'; + +const schema = yup.object().shape({ + dateDelivered: yup.date().required('Must provide delivery date.'), + confirmDelivered: yup + .boolean() + .required('Please confirm items delivered.') + .test('is-true', 'Please confirm', (value) => value === true) +}); + +interface MarkDeliveredModalProps { + modalShow: boolean; + onHide: () => void; + reimbursementRequest: ReimbursementRequest; +} + +const MarkDeliveredModal = ({ modalShow, onHide, reimbursementRequest }: MarkDeliveredModalProps) => { + const toast = useToast(); + const { mutateAsync: markDelivered } = useMarkReimbursementRequestAsDelivered(reimbursementRequest.reimbursementRequestId); + + // is the given date before the date the expense happened (not when it was reported to FinishLine)? + const dateIsBeforeExpense = (date: Date): boolean => { + if (!reimbursementRequest.dateOfExpense) return false; + return date < startOfDay(reimbursementRequest.dateOfExpense); + }; + + const dateIsInTheFuture = (date: Date) => { + const now = startOfDay(new Date()); + return date > now; + }; + + const { + handleSubmit, + control, + formState: { errors }, + reset + } = useForm({ + resolver: yupResolver(schema), + defaultValues: { + dateDelivered: new Date(), + confirmDelivered: false + }, + mode: 'onChange' + }); + + const handleMarkDelivered = async (data: { dateDelivered: Date; confirmDelivered: boolean }) => { + if (!data.confirmDelivered) { + toast.error('Delivery not confirmed!'); + } + try { + await markDelivered({ dateDelivered: startOfDay(data.dateDelivered) }); + toast.success('Marked as delivered!'); + onHide(); + } catch (e: unknown) { + if (e instanceof Error) { + toast.error(e.message, 3000); + } + } + }; + + return ( + + + Date Final Item Delivered (MM-DD-YYYY) + ( + onChange(date ?? new Date())} + className={'padding: 10'} + value={value} + shouldDisableDate={(date) => dateIsBeforeExpense(date) || dateIsInTheFuture(date)} + slotProps={{ textField: { autoComplete: 'off' } }} + /> + )} + /> + + + + Are you sure the items in this reimbursement request have all been delivered? + + ( + + } label="Yes" /> + } label="No" /> + {errors.confirmDelivered ? ( +

Please confirm all items delivered before proceeding.

+ ) : null} +
+ )} + /> +
+
+ ); +}; + +export default MarkDeliveredModal; diff --git a/src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/ReimbursementRequestDetailsView.tsx b/src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/ReimbursementRequestDetailsView.tsx index 4c6875bb32..86f4ad1dae 100644 --- a/src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/ReimbursementRequestDetailsView.tsx +++ b/src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/ReimbursementRequestDetailsView.tsx @@ -15,7 +15,7 @@ import { Grid, Typography, useTheme, Link, IconButton } from '@mui/material'; import { Box } from '@mui/system'; import { useState } from 'react'; import { useHistory } from 'react-router-dom'; -import { ReimbursementRequest, isHead } from 'shared'; +import { ReimbursementRequest, isAdmin, isHead } from 'shared'; import ActionsMenu, { ButtonInfo } from '../../../components/ActionsMenu'; import NERModal from '../../../components/NERModal'; import PageLayout from '../../../components/PageLayout'; @@ -25,7 +25,6 @@ import { useDenyReimbursementRequest, useLeadershipApproveReimbursementRequest, useMarkPendingFinance, - useMarkReimbursementRequestAsDelivered, useMarkReimbursementRequestAsReimbursed, useRequestReimbursementRequestChanges } from '../../../hooks/finance.hooks'; @@ -56,6 +55,7 @@ import SubmitToSaboModal from './SubmitToSaboModal'; import DownloadIcon from '@mui/icons-material/Download'; import ReimbursementRequestStatusPill from '../../../components/ReimbursementRequestStatusPill'; import CheckList from '../../../components/CheckList'; +import MarkDeliveredModal from './MarkDeliveredModal'; interface ReimbursementRequestDetailsViewProps { reimbursementRequest: ReimbursementRequest; @@ -80,7 +80,6 @@ const ReimbursementRequestDetailsView: React.FC { - try { - await markDelivered(); - setShowMarkDelivered(false); - } catch (e: unknown) { - if (e instanceof Error) { - toast.error(e.message, 3000); - } - } - }; - const handleMarkReimbursed = async () => { try { await markReimbursed(); @@ -225,19 +213,6 @@ const ReimbursementRequestDetailsView: React.FC ( - setShowMarkDelivered(false)} - title="Warning!" - cancelText="No" - submitText="Yes" - onSubmit={handleMarkDelivered} - > - Are you sure the items in this reimbursement request have all been delivered? - - ); - const MarkReimbursedModal = () => ( setShowMarkPendingFinanceModal(true), icon: , - disabled: user.userId !== reimbursementRequest.recipient.userId || isPendingFinance || !isLeadershipApproved + disabled: + isPendingFinance || + !isLeadershipApproved || + (!isAdmin(user.role) && user.userId !== reimbursementRequest.recipient.userId) }, { title: 'Request Changes', @@ -511,7 +489,11 @@ const ReimbursementRequestDetailsView: React.FC - + setShowMarkDelivered(false)} + reimbursementRequest={reimbursementRequest} + /> diff --git a/src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/SubmitToSaboModal.tsx b/src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/SubmitToSaboModal.tsx index f48c1c3e0c..87f9831c9c 100644 --- a/src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/SubmitToSaboModal.tsx +++ b/src/frontend/src/pages/FinancePage/ReimbursementRequestDetailPage/SubmitToSaboModal.tsx @@ -54,6 +54,12 @@ const SubmitToSaboModal = ({ open, setOpen, reimbursementRequest }: SubmitToSabo setOpen(false); }; + const treasurerName = 'Alex Leblang'; + const treasurerEmail = 'leblang.a@northeastern.edu'; + + const advisorName = 'Andrew Gouldstone'; + const advisorEmail = 'a.gouldstone@northeastern.edu'; + return ( - Alex Leblang - + {treasurerName} + - leblang.a@northeastern.edu - + {treasurerEmail} +
@@ -145,12 +151,12 @@ const SubmitToSaboModal = ({ open, setOpen, reimbursementRequest }: SubmitToSabo - Andrew Gouldstone - + {advisorName} + - a.gouldstone@northeastern.edu - + {advisorEmail} + diff --git a/src/frontend/src/pages/FinancePage/ReimbursementRequestsSection.tsx b/src/frontend/src/pages/FinancePage/ReimbursementRequestsSection.tsx index 3a7f43b6b7..a73f28a6c1 100644 --- a/src/frontend/src/pages/FinancePage/ReimbursementRequestsSection.tsx +++ b/src/frontend/src/pages/FinancePage/ReimbursementRequestsSection.tsx @@ -1,7 +1,7 @@ import { Box, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, useTheme } from '@mui/material'; import { Link as RouterLink } from 'react-router-dom'; import { useState } from 'react'; -import { ReimbursementRequest, isAdmin } from 'shared'; +import { ReimbursementRequest, isHead } from 'shared'; import { useCurrentUser } from '../../hooks/users.hooks'; import { centsToDollar, @@ -45,7 +45,7 @@ const ReimbursementRequestTable = ({ const theme = useTheme(); const [tabValue, setTabValue] = useState(0); const user = useCurrentUser(); - const canViewAllReimbursementRequests = user.isFinance || isAdmin(user.role); + const canViewAllReimbursementRequests = user.isFinance || isHead(user.role); const displayedReimbursementRequests = tabValue === 1 && allReimbursementRequests ? allReimbursementRequests : userReimbursementRequests; diff --git a/src/frontend/src/pages/HomePage/AdminHomePage.tsx b/src/frontend/src/pages/HomePage/AdminHomePage.tsx new file mode 100644 index 0000000000..79c1a7678c --- /dev/null +++ b/src/frontend/src/pages/HomePage/AdminHomePage.tsx @@ -0,0 +1,60 @@ +/* + * This file is part of NER's FinishLine and licensed under GNU AGPLv3. + * See the LICENSE file in the repository root folder for details. + */ + +import { Typography, Grid, Box } from '@mui/material'; +import { useSingleUserSettings } from '../../hooks/users.hooks'; +import LoadingIndicator from '../../components/LoadingIndicator'; +import ErrorPage from '../ErrorPage'; +import PageLayout, { PAGE_GRID_HEIGHT } from '../../components/PageLayout'; +import { AuthenticatedUser } from 'shared'; +import WorkPackagesSelectionView from './components/WorkPackagesSelectionView'; +import ChangeRequestsToReview from './components/ChangeRequestsToReview'; +import GeneralAnnouncements from './components/GeneralAnnouncements'; +import UpcomingDesignReviews from './components/UpcomingDesignReviews'; + +interface AdminHomePageProps { + user: AuthenticatedUser; +} + +const AdminHomePage = ({ user }: AdminHomePageProps) => { + const { isLoading, isError, error, data: userSettingsData } = useSingleUserSettings(user.userId); + + if (isLoading || !userSettingsData) return ; + if (isError) return ; + + return ( + + + Welcome, {user.firstName}! + + + + + + + + + + + + + + + + + + + ); +}; + +export default AdminHomePage; diff --git a/src/frontend/src/pages/HomePage/GuestHomePage.tsx b/src/frontend/src/pages/HomePage/GuestHomePage.tsx index 9297a2a008..297559c47a 100644 --- a/src/frontend/src/pages/HomePage/GuestHomePage.tsx +++ b/src/frontend/src/pages/HomePage/GuestHomePage.tsx @@ -1,42 +1,64 @@ -import { Typography, Box } from '@mui/material'; -import PageLayout from '../../components/PageLayout'; +/* + * This file is part of NER's FinishLine and licensed under GNU AGPLv3. + * See the LICENSE file in the repository root folder for details. + */ + +import { Box, Grid, Stack, Typography } from '@mui/material'; +import { useSingleUserSettings } from '../../hooks/users.hooks'; +import LoadingIndicator from '../../components/LoadingIndicator'; +import ErrorPage from '../ErrorPage'; +import PageLayout, { PAGE_GRID_HEIGHT } from '../../components/PageLayout'; import { AuthenticatedUser } from 'shared'; -import ImageWithButton from './components/ImageWithButton'; -import emitter from '../../app/EventBus'; +import MemberEncouragement from './components/MemberEncouragement'; +import GuestOrganizationInfo from './components/GuestOrganizationInfo'; +import FeaturedProjects from './components/FeaturedProjects'; +import OrganizationLogo from './components/OrganizationLogo'; interface GuestHomePageProps { user: AuthenticatedUser; - setOnMemberHomePage: (e: boolean) => void; } -const GuestHomePage = ({ user, setOnMemberHomePage }: GuestHomePageProps) => { - const handleClick = () => { - emitter.emit('memberHomePage', true); - setOnMemberHomePage(true); - }; +const GuestHomePage = ({ user }: GuestHomePageProps) => { + const { isLoading, isError, error, data: userSettingsData } = useSingleUserSettings(user.userId); + + if (isLoading || !userSettingsData) return ; + if (isError) return ; return ( - - {user ? `Welcome, ${user.firstName}!` : 'Welcome, Guest!'} + + Welcome, {user.firstName}! - - - {}} - /> - + + + + + + + + + + + + + + + + + + ); }; + export default GuestHomePage; diff --git a/src/frontend/src/pages/HomePage/Home.tsx b/src/frontend/src/pages/HomePage/Home.tsx index 25da7a5979..1ce8f7c7f6 100644 --- a/src/frontend/src/pages/HomePage/Home.tsx +++ b/src/frontend/src/pages/HomePage/Home.tsx @@ -4,18 +4,33 @@ */ import { useCurrentUser } from '../../hooks/users.hooks'; -import { isGuest } from 'shared'; +import { isAdmin, isGuest, isLead, isMember } from 'shared'; +import IntroGuestHomePage from './IntroGuestHomePage'; import GuestHomePage from './GuestHomePage'; -import MemberHomePage from './MemberHomePage'; import { useState } from 'react'; +import MemberHomePage from './MemberHomePage'; +import LeadHomePage from './LeadHomePage'; +import AdminHomePage from './AdminHomePage'; +import PopUpAlert from '../../components/PopUpAlert'; const Home = () => { const user = useCurrentUser(); const [onMemberHomePage, setOnMemberHomePage] = useState(false); - return isGuest(user.role) && !onMemberHomePage ? ( - - ) : ( - + return ( + <> + {!onMemberHomePage && } + {isGuest(user.role) && !onMemberHomePage ? ( + + ) : isMember(user.role) ? ( + + ) : isLead(user.role) ? ( + + ) : isAdmin(user.role) ? ( + + ) : ( + + )} + ); }; diff --git a/src/frontend/src/pages/HomePage/IntroGuestHomePage.tsx b/src/frontend/src/pages/HomePage/IntroGuestHomePage.tsx new file mode 100644 index 0000000000..deed2d767b --- /dev/null +++ b/src/frontend/src/pages/HomePage/IntroGuestHomePage.tsx @@ -0,0 +1,42 @@ +import { Typography, Box } from '@mui/material'; +import PageLayout from '../../components/PageLayout'; +import { AuthenticatedUser } from 'shared'; +import ImageWithButton from './components/ImageWithButton'; +import emitter from '../../app/EventBus'; + +interface IntroGuestHomePageProps { + user: AuthenticatedUser; + setOnMemberHomePage: (e: boolean) => void; +} + +const IntroGuestHomePage = ({ user, setOnMemberHomePage }: IntroGuestHomePageProps) => { + const handleClick = () => { + emitter.emit('memberHomePage', true); + setOnMemberHomePage(true); + }; + + return ( + + + {user ? `Welcome, ${user.firstName}!` : 'Welcome, Guest!'} + + + + {}} + /> + + + + + ); +}; +export default IntroGuestHomePage; diff --git a/src/frontend/src/pages/HomePage/LeadHomePage.tsx b/src/frontend/src/pages/HomePage/LeadHomePage.tsx new file mode 100644 index 0000000000..8e1c2b9f6d --- /dev/null +++ b/src/frontend/src/pages/HomePage/LeadHomePage.tsx @@ -0,0 +1,60 @@ +/* + * This file is part of NER's FinishLine and licensed under GNU AGPLv3. + * See the LICENSE file in the repository root folder for details. + */ + +import { Box, Grid, Typography } from '@mui/material'; +import { useSingleUserSettings } from '../../hooks/users.hooks'; +import LoadingIndicator from '../../components/LoadingIndicator'; +import ErrorPage from '../ErrorPage'; +import PageLayout, { PAGE_GRID_HEIGHT } from '../../components/PageLayout'; +import { AuthenticatedUser } from 'shared'; +import ChangeRequestsToReview from './components/ChangeRequestsToReview'; +import MyTeamsOverdueTasks from './components/MyTeamsOverdueTasks'; +import UpcomingDesignReviews from './components/UpcomingDesignReviews'; +import GeneralAnnouncements from './components/GeneralAnnouncements'; + +interface LeadHomePageProps { + user: AuthenticatedUser; +} + +const LeadHomePage = ({ user }: LeadHomePageProps) => { + const { isLoading, isError, error, data: userSettingsData } = useSingleUserSettings(user.userId); + + if (isLoading || !userSettingsData) return ; + if (isError) return ; + + return ( + + + Welcome, {user.firstName}! + + + + + + + + + + + + + + + + + + + ); +}; + +export default LeadHomePage; diff --git a/src/frontend/src/pages/HomePage/MemberHomePage.tsx b/src/frontend/src/pages/HomePage/MemberHomePage.tsx index 00f96da519..209b6c09a4 100644 --- a/src/frontend/src/pages/HomePage/MemberHomePage.tsx +++ b/src/frontend/src/pages/HomePage/MemberHomePage.tsx @@ -3,16 +3,15 @@ * See the LICENSE file in the repository root folder for details. */ -import { Typography } from '@mui/material'; -import OverdueWorkPackageAlerts from './components/OverdueWorkPackageAlerts'; -import UsefulLinks from './components/UsefulLinks'; -import WorkPackagesByTimelineStatus from './components/WorkPackagesByTimelineStatus'; -import UpcomingDeadlines from './components/UpcomingDeadlines'; +import { Box, Grid, Typography } from '@mui/material'; import { useSingleUserSettings } from '../../hooks/users.hooks'; import LoadingIndicator from '../../components/LoadingIndicator'; import ErrorPage from '../ErrorPage'; -import PageLayout from '../../components/PageLayout'; +import PageLayout, { PAGE_GRID_HEIGHT } from '../../components/PageLayout'; import { AuthenticatedUser } from 'shared'; +import MyTasks from './components/MyTasks'; +import TeamWorkPackageDisplay from './components/TeamWorkPackageDisplay'; +import GeneralAnnouncements from './components/GeneralAnnouncements'; interface MemberHomePageProps { user: AuthenticatedUser; @@ -29,10 +28,28 @@ const MemberHomePage = ({ user }: MemberHomePageProps) => { Welcome, {user.firstName}! - - - - + + + + + + + + + + + + + + + ); }; diff --git a/src/frontend/src/pages/HomePage/components/ChangeRequestsToReview.tsx b/src/frontend/src/pages/HomePage/components/ChangeRequestsToReview.tsx new file mode 100644 index 0000000000..148ed6c822 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/ChangeRequestsToReview.tsx @@ -0,0 +1,51 @@ +import { useAllWorkPackages } from '../../../hooks/work-packages.hooks'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ErrorPage from '../../ErrorPage'; +import { useAllChangeRequests } from '../../../hooks/change-requests.hooks'; +import { useAllProjects } from '../../../hooks/projects.hooks'; +import { getCRsToReview } from '../../../utils/change-request.utils'; +import ScrollablePageBlock from './ScrollablePageBlock'; +import { AuthenticatedUser, ChangeRequest } from 'shared'; +import ChangeRequestDetailCard from '../../../components/ChangeRequestDetailCard'; +import EmptyPageBlockDisplay from './EmptyPageBlockDisplay'; +import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; + +interface ChangeRequestsToReviewProps { + user: AuthenticatedUser; +} + +const NoChangeRequestsToReview: React.FC = () => { + return ( + } + heading={`You're all caught up!`} + message={'You have no unreviewed change requests!'} + /> + ); +}; + +const ChangeRequestsToReview: React.FC = ({ user }) => { + const { data: changeRequests, isError: crIsError, isLoading: crIsLoading, error: crError } = useAllChangeRequests(); + const { data: projects, isError: projectIsError, isLoading: projectLoading, error: projectError } = useAllProjects(); + const { data: workPackages, isError: wpIsError, isLoading: wpLoading, error: wpError } = useAllWorkPackages(); + + if (crIsLoading || projectLoading || wpLoading || !changeRequests || !projects || !workPackages) + return ; + if (crIsError) return ; + if (projectIsError) return ; + if (wpIsError) return ; + + const crsToReview = getCRsToReview(projects, workPackages, user, changeRequests); + + return ( + + {crsToReview.length === 0 ? ( + + ) : ( + crsToReview.map((cr: ChangeRequest) => ) + )} + + ); +}; + +export default ChangeRequestsToReview; diff --git a/src/frontend/src/pages/HomePage/components/DesignReviewCard.tsx b/src/frontend/src/pages/HomePage/components/DesignReviewCard.tsx new file mode 100644 index 0000000000..fdc80c595f --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/DesignReviewCard.tsx @@ -0,0 +1,117 @@ +import { Box, Card, CardContent, Link, Stack, Typography, useTheme } from '@mui/material'; +import { DesignReview, User } from 'shared'; +import { datePipe, projectWbsPipe } from '../../../utils/pipes'; +import { routes } from '../../../utils/routes'; +import { Link as RouterLink } from 'react-router-dom'; +import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; +import { LocationOnOutlined, Computer } from '@mui/icons-material'; +import { useHistory } from 'react-router-dom'; +import { NERButton } from '../../../components/NERButton'; +import { meetingStartTimePipe } from '../../../../../backend/src/utils/design-reviews.utils'; +import { timezoneOffset } from '../../../utils/datetime.utils'; + +interface DesignReviewProps { + designReview: DesignReview; + user: User; +} + +const DesignReviewInfo = ({ icon, text, link }: { icon: React.ReactNode; text: string; link?: boolean }) => { + return ( + + {icon} + {link ? ( + + + {text} + + + ) : ( + + {text} + + )} + + ); +}; + +const DisplayStatus: React.FC = ({ designReview, user }) => { + const history = useHistory(); + const confirmedMemberIds = designReview.confirmedMembers.map((user) => user.userId); + + return ( + <> + {!confirmedMemberIds.includes(user.userId) ? ( + { + history.push(`${routes.SETTINGS_PREFERENCES}?drId=${designReview.designReviewId}`); + }} + component={RouterLink} + > + Confirm Availibility + + ) : ( + {designReview.status} + )} + + ); +}; + +const getWeekday = (date: Date): string => { + const weekdays: string[] = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; + return weekdays[date.getDay()]; +}; + +const removeYear = (str: string): string => { + return str.substring(0, str.length - 5); +}; + +const UpcomingDesignReviewsCard: React.FC = ({ designReview, user }) => { + const theme = useTheme(); + const timezoneAdjustedDate = timezoneOffset(designReview.dateScheduled); + return ( + + + + + + + {designReview.wbsName} + + + + {} + + {getWeekday(timezoneAdjustedDate) + + ', ' + + removeYear(datePipe(timezoneAdjustedDate)) + + ' @ ' + + meetingStartTimePipe(designReview.meetingTimes)} + + + {designReview.isInPerson && !!designReview.location && ( + } text={designReview.location} /> + )} + {designReview.isOnline && !!designReview.zoomLink && ( + } text={designReview.zoomLink} link /> + )} + + + + + + ); +}; + +export default UpcomingDesignReviewsCard; diff --git a/src/frontend/src/pages/HomePage/components/EmptyPageBlockDisplay.tsx b/src/frontend/src/pages/HomePage/components/EmptyPageBlockDisplay.tsx new file mode 100644 index 0000000000..1cb8301b13 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/EmptyPageBlockDisplay.tsx @@ -0,0 +1,30 @@ +import { Box, Typography } from '@mui/material'; +import React from 'react'; + +interface EmptyPageBlockDisplayProps { + icon: React.ReactNode; + heading: String; + message: String; +} + +const EmptyPageBlockDisplay: React.FC = ({ icon, heading, message }) => { + return ( + + {icon} + {heading} + {message} + + ); +}; + +export default EmptyPageBlockDisplay; diff --git a/src/frontend/src/pages/HomePage/components/FeaturedProjects.tsx b/src/frontend/src/pages/HomePage/components/FeaturedProjects.tsx new file mode 100644 index 0000000000..958e3f05f8 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/FeaturedProjects.tsx @@ -0,0 +1,56 @@ +/* + * This file is part of NER's FinishLine and licensed under GNU AGPLv3. + * See the LICENSE file in the repository root folder for details. + */ + +import FeaturedProjectsCard from './FeaturedProjectsCard'; +import { useFeaturedProjects } from '../../../hooks/organizations.hooks'; +import ErrorPage from '../../ErrorPage'; +import { wbsPipe } from 'shared'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ScrollablePageBlock from './ScrollablePageBlock'; +import EmptyPageBlockDisplay from './EmptyPageBlockDisplay'; +import { Box } from '@mui/material'; +import { Error } from '@mui/icons-material'; + +const NoFeaturedProjectsDisplay: React.FC = () => { + return ( + + } + heading={'No Featured Projects'} + message={'There are no Featured Projects to Display'} + /> + + ); +}; + +const FeaturedProjects: React.FC = () => { + const { data: featuredProjects, isLoading, isError, error } = useFeaturedProjects(); + + if (isLoading || !featuredProjects) return ; + if (isError) return ; + + const fullDisplay = ( + + {featuredProjects.length === 0 ? ( + + ) : ( + featuredProjects.map((p) => ) + )} + + ); + + return fullDisplay; +}; + +export default FeaturedProjects; diff --git a/src/frontend/src/pages/HomePage/components/FeaturedProjectsCard.tsx b/src/frontend/src/pages/HomePage/components/FeaturedProjectsCard.tsx new file mode 100644 index 0000000000..ddc6bc25eb --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/FeaturedProjectsCard.tsx @@ -0,0 +1,60 @@ +import { Construction, Work } from '@mui/icons-material'; +import { Box, Card, CardContent, Chip, Link, Stack, Typography, useTheme } from '@mui/material'; +import { wbsPipe, Project } from 'shared'; +import { datePipe, fullNamePipe, projectWbsPipe } from '../../../utils/pipes'; +import { routes } from '../../../utils/routes'; +import { Link as RouterLink } from 'react-router-dom'; + +interface ProjectCardProps { + project: Project; +} + +const FeaturedProjectsCard: React.FC = ({ project }) => { + const theme = useTheme(); + return ( + + + + + + + {projectWbsPipe(project.wbsNum)} - {project.teams.map((project) => project.teamName)} + + + + + {wbsPipe(project.wbsNum)} - {project.name} + + + + {datePipe(project.startDate) + ' ⟝ ' + project.duration + ' wks ⟞ ' + datePipe(project.endDate)} + + + + + } + label={fullNamePipe(project.lead)} + size="medium" + /> + } label={fullNamePipe(project.manager)} size="medium" /> + + + + ); +}; + +export default FeaturedProjectsCard; diff --git a/src/frontend/src/pages/HomePage/components/GeneralAnnouncementCard.tsx b/src/frontend/src/pages/HomePage/components/GeneralAnnouncementCard.tsx new file mode 100644 index 0000000000..b7e09741f1 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/GeneralAnnouncementCard.tsx @@ -0,0 +1,52 @@ +import { Card, CardContent, Typography, IconButton, Box } from '@mui/material'; +import { useTheme } from '@mui/system'; +import React from 'react'; +import { Announcement } from 'shared'; +import { datePipe } from '../../../utils/pipes'; +import CloseIcon from '@mui/icons-material/Close'; + +interface GeneralAnnouncementCardProps { + announcement: Announcement; + removeAnnouncement: (announcement: Announcement) => Promise; +} + +const GeneralAnnouncementCard: React.FC = ({ announcement, removeAnnouncement }) => { + const theme = useTheme(); + return ( + + + + removeAnnouncement(announcement)}> + + + + + {announcement.senderName} ({datePipe(announcement.dateMessageSent)}) + + #{announcement.slackChannelName} + {announcement.text} + + + ); +}; + +export default GeneralAnnouncementCard; diff --git a/src/frontend/src/pages/HomePage/components/GeneralAnnouncements.tsx b/src/frontend/src/pages/HomePage/components/GeneralAnnouncements.tsx new file mode 100644 index 0000000000..17e5334199 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/GeneralAnnouncements.tsx @@ -0,0 +1,44 @@ +import ScrollablePageBlock from './ScrollablePageBlock'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import EmptyPageBlockDisplay from './EmptyPageBlockDisplay'; +import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; +import GeneralAnnouncementCard from './GeneralAnnouncementCard'; +import { useRemoveUserAnnouncement, useUserAnnouncements } from '../../../hooks/announcements.hooks'; +import ErrorPage from '../../ErrorPage'; + +const NoGeneralAnnouncementsDisplay = () => { + return ( + } + heading={"You're all caught up!"} + message={'You have read all current general announcements!'} + /> + ); +}; + +const GeneralAnnouncements: React.FC = () => { + const { + data: unreadAnnouncements, + isLoading, + isError: announcementsIsError, + error: announcementsError + } = useUserAnnouncements(); + const { mutateAsync: removeAnnouncement, isLoading: removeAnnouncementIsLoading } = useRemoveUserAnnouncement(); + + if (announcementsIsError) return ; + if (isLoading || removeAnnouncementIsLoading || !unreadAnnouncements) return ; + + return ( + + {unreadAnnouncements.length === 0 ? ( + + ) : ( + unreadAnnouncements.map((announcement) => ( + + )) + )} + + ); +}; + +export default GeneralAnnouncements; diff --git a/src/frontend/src/pages/HomePage/components/GuestOrganizationInfo.tsx b/src/frontend/src/pages/HomePage/components/GuestOrganizationInfo.tsx new file mode 100644 index 0000000000..2cd6779fbe --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/GuestOrganizationInfo.tsx @@ -0,0 +1,79 @@ +import { Box, Card, Icon, Typography, useTheme } from '@mui/material'; +import { Grid } from '@mui/material'; +import { useCurrentOrganization } from '../../../hooks/organizations.hooks'; +import React from 'react'; +import { NERButton } from '../../../components/NERButton'; +import { useAllLinkTypes, useAllUsefulLinks } from '../../../hooks/projects.hooks'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ErrorPage from '../../ErrorPage'; + +interface GuestOrganizationInfoButtonProps { + href?: string; + buttonText: string; + iconName: string; +} + +const NERGuestButton: React.FC = ({ href, buttonText, iconName }) => { + return ( + + + {iconName} + + {buttonText} + + + + ); +}; + +const GuestOrganizationInfo = () => { + const theme = useTheme(); + const { data: organization, isLoading, isError, error } = useCurrentOrganization(); + const { + data: usefulLinks, + isLoading: usefulLinksIsLoading, + isError: usefulLinksIsError, + error: usefulLinksError + } = useAllUsefulLinks(); + const { data: linkTypes, isLoading: linkTypesIsLoading } = useAllLinkTypes(); + + if (isLoading || !organization) return ; + if (isError) return ; + + if (!usefulLinks || usefulLinksIsLoading || !linkTypes || linkTypesIsLoading) return ; + if (usefulLinksIsError) return ; + + return ( + + + + {organization.name} + + {organization.description} + + + {usefulLinks.map((link) => ( + + ))} + + + ); +}; + +export default GuestOrganizationInfo; diff --git a/src/frontend/src/pages/HomePage/components/LogoDisplay.tsx b/src/frontend/src/pages/HomePage/components/LogoDisplay.tsx new file mode 100644 index 0000000000..0ebeb68db5 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/LogoDisplay.tsx @@ -0,0 +1,35 @@ +import { Box, useTheme, Card } from '@mui/material'; +import React from 'react'; + +interface LogoDisplayProps { + imageUrl?: string; +} + +const LogoDisplay: React.FC = ({ imageUrl }) => { + const theme = useTheme(); + return ( + + {imageUrl && ( + + )} + + ); +}; + +export default LogoDisplay; diff --git a/src/frontend/src/pages/HomePage/components/MemberEncouragement.tsx b/src/frontend/src/pages/HomePage/components/MemberEncouragement.tsx new file mode 100644 index 0000000000..dc117e16d3 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/MemberEncouragement.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { Box, Alert, Typography, Grid } from '@mui/material'; +import { routes } from '../../../utils/routes'; +import { NERButton } from '../../../components/NERButton'; +import { useHistory } from 'react-router-dom'; + +const MemberEncouragement: React.FC = () => { + const history = useHistory(); + return ( + + + + + + Already a member? + + + Talk to the head of your team to become a member and get added to the team on FinishLine! + + + + { + history.push(routes.TEAMS); + }} + > + See Teams > + + + + + + ); +}; + +export default MemberEncouragement; diff --git a/src/frontend/src/pages/HomePage/components/MyTasks.tsx b/src/frontend/src/pages/HomePage/components/MyTasks.tsx new file mode 100644 index 0000000000..9b12b233d3 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/MyTasks.tsx @@ -0,0 +1,45 @@ +import LoadingIndicator from '../../../components/LoadingIndicator'; +import { useCurrentUser, useUserTasks } from '../../../hooks/users.hooks'; +import TaskDetailCard from './TaskDetailCard'; +import ErrorPage from '../../ErrorPage'; +import EmptyPageBlockDisplay from './EmptyPageBlockDisplay'; +import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; +import ScrollablePageBlock from './ScrollablePageBlock'; + +const NoTasksDisplay: React.FC = () => { + return ( + } + heading={"You're all caught up!"} + message={"You've completed all of your assigned tasks!"} + /> + ); +}; + +const MyTasks: React.FC = () => { + const currentUser = useCurrentUser(); + + const { + data: userTasks, + isLoading: userTasksIsLoading, + error: userTasksError, + isError: userTasksIsError + } = useUserTasks(currentUser.userId); + + if (userTasksIsLoading || !userTasks) return ; + if (userTasksIsError) return ; + + return ( + + {userTasks.length === 0 ? ( + + ) : ( + userTasks.map((task, index) => { + return ; + }) + )} + + ); +}; + +export default MyTasks; diff --git a/src/frontend/src/pages/HomePage/components/MyTeamsOverdueTasks.tsx b/src/frontend/src/pages/HomePage/components/MyTeamsOverdueTasks.tsx new file mode 100644 index 0000000000..95eab5b66b --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/MyTeamsOverdueTasks.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import ScrollablePageBlock from './ScrollablePageBlock'; +import { AuthenticatedUser } from 'shared'; +import { useManyUserTasks } from '../../../hooks/users.hooks'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ErrorPage from '../../ErrorPage'; +import TeamTaskCard from './TeamTaskCard'; +import EmptyPageBlockDisplay from './EmptyPageBlockDisplay'; +import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; +import { getOverdueTasks } from '../../../utils/task.utils'; + +interface MyTeamsOverdueTasksProps { + user: AuthenticatedUser; +} + +const NoOverdueTeamTaskDisplay = () => { + return ( + } + heading={"You're team is all caught up!"} + message={"You're team has no overdue tasks!"} + /> + ); +}; + +const MyTeamsOverdueTasks: React.FC = ({ user }) => { + const teamsAsHead = user.teamsAsHead ?? []; + const teamsAsLead = user.teamsAsLead ?? []; + const teamsAsLeadership = [...teamsAsHead, ...teamsAsLead]; + // converting to set for no duplicate members + const allMembers = new Set(teamsAsLeadership.map((team) => team.members).flat()); + const { data: tasks, isLoading, isError, error } = useManyUserTasks([...allMembers].map((member) => member.userId)); + + if (isLoading || !tasks) return ; + if (isError) return ; + + const overdueTasks = getOverdueTasks(tasks); + + return ( + + {overdueTasks.length === 0 ? ( + + ) : ( + overdueTasks.map((task, index) => ) + )} + + ); +}; + +export default MyTeamsOverdueTasks; diff --git a/src/frontend/src/pages/HomePage/components/OrganizationLogo.tsx b/src/frontend/src/pages/HomePage/components/OrganizationLogo.tsx new file mode 100644 index 0000000000..c16a273c31 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/OrganizationLogo.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import LogoDisplay from './LogoDisplay'; +import { useOrganizationLogo } from '../../../hooks/organizations.hooks'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ErrorPage from '../../ErrorPage'; + +const OrganizationLogo = () => { + const { data: imageData, isLoading, isError, error } = useOrganizationLogo(); + if (isLoading) return ; + if (isError) return ; + + return ; +}; + +export default OrganizationLogo; diff --git a/src/frontend/src/pages/HomePage/components/OverdueWorkPackageCard.tsx b/src/frontend/src/pages/HomePage/components/OverdueWorkPackageCard.tsx new file mode 100644 index 0000000000..deb86badb5 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/OverdueWorkPackageCard.tsx @@ -0,0 +1,145 @@ +import { Construction, Work, CalendarMonth } from '@mui/icons-material'; +import { + Box, + Card, + CardContent, + Chip, + CircularProgress, + CircularProgressProps, + Link, + Stack, + Typography, + useTheme +} from '@mui/material'; +import { wbsPipe, WorkPackage } from 'shared'; +import { datePipe, fullNamePipe, projectWbsPipe } from '../../../utils/pipes'; +import { routes } from '../../../utils/routes'; +import { Link as RouterLink } from 'react-router-dom'; +import { useGetManyWorkPackages } from '../../../hooks/work-packages.hooks'; +import { daysOverdue } from '../../../utils/datetime.utils'; +import LoadingIndicator from '../../../components/LoadingIndicator'; + +export const CircularProgressWithLabel = (props: CircularProgressProps & { value: number }) => { + return ( + + +
+ {`${Math.round(props.value)}%`} +
+
+ ); +}; + +const OverdueWorkPackageCard = ({ wp }: { wp: WorkPackage }) => { + const theme = useTheme(); + const { data: blockedByWps, isLoading } = useGetManyWorkPackages(wp.blockedBy); + const numDaysOverdue = daysOverdue(new Date(wp.endDate)); + if (isLoading || !blockedByWps) return ; + return ( + + + + + + + {projectWbsPipe(wp.wbsNum)} - {wp.projectName} + + + + + {wbsPipe(wp.wbsNum)} - {wp.name} + + + + Blocked By: + +
    + {blockedByWps.length === 0 ? ( +
  • + + No Blockers + +
  • + ) : ( + blockedByWps.map((wp) => ( +
  • + + + {projectWbsPipe(wp.wbsNum)} - {wp.projectName} + + +
  • + )) + )} +
+
+ + + } label={fullNamePipe(wp.lead)} size={'small'} /> + } label={fullNamePipe(wp.manager)} size={'small'} /> + } label={datePipe(new Date(wp.endDate))} size={'small'} /> + + + + + {numDaysOverdue} + + + + Days + + + Overdue + + + + +
+
+
+ ); +}; + +export default OverdueWorkPackageCard; diff --git a/src/frontend/src/pages/HomePage/components/OverdueWorkPackageView.tsx b/src/frontend/src/pages/HomePage/components/OverdueWorkPackageView.tsx new file mode 100644 index 0000000000..d0d42294b1 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/OverdueWorkPackageView.tsx @@ -0,0 +1,96 @@ +import { Box, Card, CardContent, Typography, useTheme } from '@mui/material'; +import { WorkPackage } from 'shared'; +import EmptyPageBlockDisplay from './EmptyPageBlockDisplay'; +import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; +import OverdueWorkPackageCard from './OverdueWorkPackageCard'; + +interface OverdueWorkPackagesViewProps { + workPackages: WorkPackage[]; +} + +const NoOverdueWPsDisplay: React.FC = () => { + return ( + } + heading={'Great Job Team!'} + message={'Your team has no overdue work packages!'} + /> + ); +}; + +const OverdueWorkPackagesView: React.FC = ({ workPackages }) => { + const theme = useTheme(); + const isEmpty = workPackages.length === 0; + return ( + + + + All Overdue Work Packages + + + + + + {isEmpty ? : workPackages.map((wp) => )} + + + + + ); +}; + +export default OverdueWorkPackagesView; diff --git a/src/frontend/src/pages/HomePage/components/OverdueWorkPackages.tsx b/src/frontend/src/pages/HomePage/components/OverdueWorkPackages.tsx new file mode 100644 index 0000000000..7e90c4e10a --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/OverdueWorkPackages.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { AuthenticatedUser, isAdmin, Team } from 'shared'; +import { useAllWorkPackages, useGetManyWorkPackages } from '../../../hooks/work-packages.hooks'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ErrorPage from '../../ErrorPage'; +import { daysOverdue } from '../../../utils/datetime.utils'; +import OverdueWorkPackagesView from './OverdueWorkPackageView'; + +interface OverdueWorkPackagesProps { + user: AuthenticatedUser; +} + +const getAllWbsNumFromTeams = (teams: Team[]) => { + const projects = teams.map((team) => team.projects).flat(); + const workPackages = projects.map((project) => project.workPackages).flat(); + return workPackages.map((wp) => wp.wbsNum); +}; + +const OverdueWorkPackages: React.FC = ({ user }) => { + const teamsAsHead = user.teamsAsHead ?? []; + const teamsAsLead = user.teamsAsLead ?? []; + const teamsAsLeadership = [...teamsAsHead, ...teamsAsLead]; + const { data: allWps, isLoading: isLoadingAllWps, isError: isErrorAllWps, error: errorAllWps } = useAllWorkPackages(); + const { + data: teamWps, + isLoading: isLoadingTeamWps, + isError: isErrorTeamWps, + error: errorTeamWps + } = useGetManyWorkPackages(getAllWbsNumFromTeams(teamsAsLeadership)); + + if (isLoadingAllWps || isLoadingTeamWps || !allWps || !teamWps) return ; + if (isErrorAllWps) return ; + if (isErrorTeamWps) return ; + + const displayedWps = isAdmin(user.role) ? allWps : teamWps; + const overdueWps = displayedWps.filter((wp) => daysOverdue(wp.endDate) > 0); + + return ; +}; + +export default OverdueWorkPackages; diff --git a/src/frontend/src/pages/HomePage/components/ScrollablePageBlock.tsx b/src/frontend/src/pages/HomePage/components/ScrollablePageBlock.tsx new file mode 100644 index 0000000000..54b11ce434 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/ScrollablePageBlock.tsx @@ -0,0 +1,65 @@ +import { Box, Card, CardContent, Typography, useTheme } from '@mui/material'; +import React from 'react'; + +interface ScrollablePageBlockProps { + children: React.ReactNode; + title?: String; + horizontal?: boolean; +} + +const ScrollablePageBlock: React.FC = ({ children, title, horizontal }) => { + const theme = useTheme(); + return ( + + + {title && ( + + {title} + + )} + + {children} + + + + ); +}; +export default ScrollablePageBlock; diff --git a/src/frontend/src/pages/HomePage/components/TaskDetailCard.tsx b/src/frontend/src/pages/HomePage/components/TaskDetailCard.tsx new file mode 100644 index 0000000000..1e4045ea07 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/TaskDetailCard.tsx @@ -0,0 +1,123 @@ +import { Card, CardContent, useTheme, Stack, Link, Typography, Box, Chip } from '@mui/material'; +import Tooltip, { TooltipProps, tooltipClasses } from '@mui/material/Tooltip'; +import { Task, wbsPipe } from 'shared'; +import { Link as RouterLink } from 'react-router-dom'; +import { routes } from '../../../utils/routes'; +import { taskPriorityColor } from '../../../utils/task.utils'; +import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; +import { useState } from 'react'; +import WarningAmberIcon from '@mui/icons-material/WarningAmber'; +import { styled } from '@mui/material/styles'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ErrorPage from '../../ErrorPage'; +import { useSingleProject } from '../../../hooks/projects.hooks'; +import { daysOverdue, formatDate } from '../../../utils/datetime.utils'; + +interface TaskDetailCardProps { + task: Task; + taskNumber: number; +} + +const NERToolTip = styled(({ className, ...props }: TooltipProps) => ( + +))(({ theme }) => ({ + [`& .${tooltipClasses.arrow}`]: { + color: theme.palette.error.dark + }, + [`& .${tooltipClasses.tooltip}`]: { + backgroundColor: theme.palette.error.dark + } +})); + +const TaskDetailCard: React.FC = ({ task, taskNumber }) => { + const theme = useTheme(); + const taskDaysOverdue = daysOverdue(new Date(task.deadline)); + const taskOverdue = taskDaysOverdue > 0; + const [hover, setHover] = useState(false); + const { data: project, isLoading, isError, error } = useSingleProject(task.wbsNum); + + if (isLoading || !project) return ; + if (isError) return ; + + return ( + + + + Task #{taskNumber} is {taskDaysOverdue} Days Overdue! + + + } + open={taskOverdue && hover} + placement="right" + arrow + > + setHover(true)} + onMouseLeave={() => setHover(false)} + sx={{ + width: '100%', + height: 'fit-content', + mr: 3, + background: theme.palette.background.default, + border: taskOverdue && hover ? '1px solid red' : undefined + }} + > + + + + + + + Task #{taskNumber} - {task.title} + + {taskOverdue && ( + + )} + + + + {wbsPipe(task.wbsNum)} - {project.name} + + + + + + + } label={formatDate(new Date(task.deadline))} size="small" /> + + + + + Notes:
{task.notes} +
+
+
+
+
+ ); +}; + +export default TaskDetailCard; diff --git a/src/frontend/src/pages/HomePage/components/TeamTaskCard.tsx b/src/frontend/src/pages/HomePage/components/TeamTaskCard.tsx new file mode 100644 index 0000000000..d9277350d7 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/TeamTaskCard.tsx @@ -0,0 +1,75 @@ +import { Box, Card, CardContent, Chip, Link, Stack, Typography } from '@mui/material'; +import { Link as RouterLink } from 'react-router-dom'; +import { useTheme } from '@mui/system'; +import React from 'react'; +import { Task, wbsPipe } from 'shared'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ErrorPage from '../../ErrorPage'; +import { useSingleProject } from '../../../hooks/projects.hooks'; +import { routes } from '../../../utils/routes'; +import { fullNamePipe } from '../../../utils/pipes'; +import PeopleAltIcon from '@mui/icons-material/PeopleAlt'; +import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; +import { taskPriorityColor } from '../../../utils/task.utils'; +import { formatDate } from '../../../utils/datetime.utils'; + +interface TeamTaskCardProps { + task: Task; + taskNumber: number; +} + +const TeamTaskCard: React.FC = ({ task, taskNumber }) => { + const theme = useTheme(); + const { data: project, isLoading, isError, error } = useSingleProject(task.wbsNum); + if (isLoading || !project) return ; + if (isError) return ; + + return ( + + + + + + Task #{taskNumber} - {task.title} + + + + {wbsPipe(task.wbsNum)} - {project.name} + + + + + {task.assignees.map(fullNamePipe).join(', ')} + + + + + } label={formatDate(new Date(task.deadline))} size="medium" /> + + + + + ); +}; + +export default TeamTaskCard; diff --git a/src/frontend/src/pages/HomePage/components/TeamWorkPackageDisplay.tsx b/src/frontend/src/pages/HomePage/components/TeamWorkPackageDisplay.tsx new file mode 100644 index 0000000000..202bb32504 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/TeamWorkPackageDisplay.tsx @@ -0,0 +1,57 @@ +import WorkPackageCard from './WorkPackageCard'; +import ScrollablePageBlock from './ScrollablePageBlock'; +import EmptyPageBlockDisplay from './EmptyPageBlockDisplay'; +import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; +import { AuthenticatedUser, WbsElementStatus, WorkPackage } from 'shared'; +import { useAllTeams } from '../../../hooks/teams.hooks'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ErrorPage from '../../ErrorPage'; +import { isUserOnTeam } from '../../../utils/teams.utils'; + +interface TeamWorkPackageDisplayProps { + user: AuthenticatedUser; +} + +const NoTeamWorkPackagesDisplay: React.FC = () => { + return ( + } + heading={'No Active Work Packages'} + message={'There are no active work packages assigned to your team!'} + /> + ); +}; + +const TeamWorkPackageDisplay: React.FC = ({ user }) => { + const { isLoading, isError, data: teams, error } = useAllTeams(); + + if (isLoading || !teams) return ; + if (isError) return ; + + const myTeams = teams.filter((team) => isUserOnTeam(team, user)); + + const workPackages = myTeams + //convert list of teams into list of work packages in projects in those teams + .map((team) => { + return team.projects.map((project) => { + return project.workPackages.filter((wp) => wp.status === WbsElementStatus.Active); + }); + }) + //flatten into 1 dimensional list of work packages + .flat(2) + //remove duplicate work packages + .reduce((acc: WorkPackage[], wp: WorkPackage) => { + if (acc.filter((addedWp) => addedWp.id === wp.id).length === 0) { + acc.push(wp); + } + return acc; + }, []); + + return ( + + {workPackages.length === 0 ? : workPackages.map((wp) => )} + + ); +}; + +export default TeamWorkPackageDisplay; diff --git a/src/frontend/src/pages/HomePage/components/UpcomingDesignReviews.tsx b/src/frontend/src/pages/HomePage/components/UpcomingDesignReviews.tsx new file mode 100644 index 0000000000..7d0d4c0565 --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/UpcomingDesignReviews.tsx @@ -0,0 +1,67 @@ +/* + * This file is part of NER's FinishLine and licensed under GNU AGPLv3. + * See the LICENSE file in the repository root folder for details. + */ + +import DesignReviewCard from './DesignReviewCard'; +import { useAllDesignReviews } from '../../../hooks/design-reviews.hooks'; +import ErrorPage from '../../ErrorPage'; +import { AuthenticatedUser, DesignReviewStatus, wbsPipe } from 'shared'; +import LoadingIndicator from '../../../components/LoadingIndicator'; +import ScrollablePageBlock from './ScrollablePageBlock'; +import EmptyPageBlockDisplay from './EmptyPageBlockDisplay'; +import { Error } from '@mui/icons-material'; + +interface UpcomingDesignReviewProps { + user: AuthenticatedUser; +} + +const NoUpcomingDesignReviewsDisplay: React.FC = () => { + return ( + } + heading={'No Upcoming Design Reviews'} + message={'There are no Upcoming Design Reviews to Display'} + /> + ); +}; + +const UpcomingDesignReviews: React.FC = ({ user }) => { + const { data: designReviews, isLoading, isError, error } = useAllDesignReviews(); + + if (isLoading || !designReviews) return ; + if (isError) return ; + + const filteredDesignReviews = designReviews.filter((review) => { + const scheduledDate = review.dateScheduled; + const currentDate = new Date(); + const inTwoWeeks = new Date(); + inTwoWeeks.setDate(currentDate.getDate() + 14); + const memberUserIds = [ + ...review.requiredMembers.map((user) => user.userId), + ...review.optionalMembers.map((user) => user.userId) + ]; + // added in case the person who created the design review forgets to add their name onto the required members + memberUserIds.concat(review.userCreated.userId); + return ( + scheduledDate >= currentDate && + scheduledDate <= inTwoWeeks && + review.status !== DesignReviewStatus.DONE && + memberUserIds.includes(user.userId) + ); + }); + + const fullDisplay = ( + + {filteredDesignReviews.length === 0 ? ( + + ) : ( + filteredDesignReviews.map((d) => ) + )} + + ); + + return fullDisplay; +}; + +export default UpcomingDesignReviews; diff --git a/src/frontend/src/pages/HomePage/components/WorkPackageCard.tsx b/src/frontend/src/pages/HomePage/components/WorkPackageCard.tsx index 57814b4f3f..e6ddd11d14 100644 --- a/src/frontend/src/pages/HomePage/components/WorkPackageCard.tsx +++ b/src/frontend/src/pages/HomePage/components/WorkPackageCard.tsx @@ -40,7 +40,8 @@ const WorkPackageCard = ({ wp }: { wp: WorkPackage }) => { void; + selected?: number; +} + +const WorkPackageSelect: React.FC = ({ options, onSelect, selected = 0 }) => { + const theme = useTheme(); + const [isOpen, setIsOpen] = useState(false); + const dropdownRef = useRef(null); + + const handleSelect = (option: string) => { + setIsOpen(false); + onSelect(options.indexOf(option)); + }; + + const handleClickOutside = (event: MouseEvent) => { + if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { + setIsOpen(false); + } + }; + + useEffect(() => { + if (isOpen) { + document.addEventListener('mousedown', handleClickOutside); + } else { + document.removeEventListener('mousedown', handleClickOutside); + } + }, [isOpen]); + + return ( + + setIsOpen(!isOpen)} + variant="h5" + sx={{ paddingX: 2, paddingY: 1, display: 'inline-block', cursor: 'pointer' }} + > + + {options[selected]} + + {isOpen && ( + setIsOpen(!isOpen)} sx={{ position: 'absolute', top: '-40%', cursor: 'pointer' }}> + + + {options[selected]} + + {options + .filter((option) => option !== options.at(selected)) + .map((option) => ( + { + handleSelect(option); + }} + sx={{ + cursor: 'pointer', + paddingX: 2, + paddingY: 1, + backgroundColor: theme.palette.background.paper, + position: 'relative', + '&:hover': { + backgroundColor: theme.palette.action.hover + } + }} + variant="h5" + > + {option} + + ))} + + + )} + + ); +}; + +export default WorkPackageSelect; diff --git a/src/frontend/src/pages/HomePage/components/WorkPackagesSelectionView.tsx b/src/frontend/src/pages/HomePage/components/WorkPackagesSelectionView.tsx new file mode 100644 index 0000000000..2b05907c4d --- /dev/null +++ b/src/frontend/src/pages/HomePage/components/WorkPackagesSelectionView.tsx @@ -0,0 +1,129 @@ +import { WorkPackage } from 'shared'; +import { Box, Card, CardContent, useTheme } from '@mui/material'; +import { + getInProgressWorkPackages, + getOverdueWorkPackages, + getUpcomingWorkPackages +} from '../../../utils/work-package.utils'; +import { useCurrentUser } from '../../../hooks/users.hooks'; +import WorkPackageCard from './WorkPackageCard'; +import WorkPackageSelect from './WorkPackageSelect'; +import React, { useState } from 'react'; +import EmptyPageBlockDisplay from './EmptyPageBlockDisplay'; +import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'; + +const NoWorkPackages: React.FC = () => { + return ( + } + heading={`You're all set!`} + message={'You have no pending work packages of this type!'} + /> + ); +}; + +const WorkPackagesSelectionView: React.FC = () => { + const user = useCurrentUser(); + const theme = useTheme(); + + const teamsAsHead = user.teamsAsHead ?? []; + const teamsAsLead = user.teamsAsLead ?? []; + const teamsAsLeadership = [...teamsAsHead, ...teamsAsLead]; + + const relevantWPs = teamsAsLeadership.map((team) => team.projects.map((project) => project.workPackages)).flat(2); + + const upcomingWPs: WorkPackage[] = getUpcomingWorkPackages(relevantWPs); + const inProgressWPs: WorkPackage[] = getInProgressWorkPackages(relevantWPs); + const overdueWPs: WorkPackage[] = getOverdueWorkPackages(relevantWPs); + + // options for selection + const workPackageOptions: [string, WorkPackage[]][] = [ + [`Upcoming Work Packages (${upcomingWPs.length})`, upcomingWPs], + [`In Progress Work Packages (${inProgressWPs.length})`, inProgressWPs], + [`Overdue Work Packages (${overdueWPs.length})`, overdueWPs] + ]; + + let defaultFirstDisplay = 2; + if (workPackageOptions[2][1].length === 0) { + defaultFirstDisplay = 1; + if (workPackageOptions[1][1].length === 0) { + defaultFirstDisplay = 0; + } + } + + const [currentDisplayedWPs, setCurrentDisplayedWPs] = useState(defaultFirstDisplay); + + // destructuring tuple to get wps of selected option + const [, currentWps] = workPackageOptions[currentDisplayedWPs]; + + const WorkPackagesDisplay = (workPackages: WorkPackage[]) => ( + + {workPackages.map((wp) => ( + + ))} + + ); + + return ( + + + wp[0])} + onSelect={setCurrentDisplayedWPs} + selected={currentDisplayedWPs} + /> + + {currentWps.length === 0 ? : WorkPackagesDisplay(currentWps)} + + + + ); +}; + +export default WorkPackagesSelectionView; diff --git a/src/frontend/src/pages/LoginPage/Login.tsx b/src/frontend/src/pages/LoginPage/Login.tsx index f41cde2d78..f95913249a 100644 --- a/src/frontend/src/pages/LoginPage/Login.tsx +++ b/src/frontend/src/pages/LoginPage/Login.tsx @@ -12,7 +12,7 @@ import LoginPage from './LoginPage'; import LoadingIndicator from '../../components/LoadingIndicator'; import { useQuery } from '../../hooks/utils.hooks'; import { GoogleLoginResponse, GoogleLoginResponseOffline } from 'react-google-login'; -import { useOrganization } from '../../hooks/organization.hooks'; +import { useOrganization } from '../../hooks/organizations.hooks'; /** * Page for unauthenticated users to do login. diff --git a/src/frontend/src/pages/ProjectDetailPage/ProjectViewContainer/BOM/BOMTableWrapper.tsx b/src/frontend/src/pages/ProjectDetailPage/ProjectViewContainer/BOM/BOMTableWrapper.tsx index cb2ab136ba..66f7ecfe99 100644 --- a/src/frontend/src/pages/ProjectDetailPage/ProjectViewContainer/BOM/BOMTableWrapper.tsx +++ b/src/frontend/src/pages/ProjectDetailPage/ProjectViewContainer/BOM/BOMTableWrapper.tsx @@ -46,13 +46,18 @@ const BOMTableWrapper: React.FC = ({ project, hideColumn, const user = useCurrentUser(); const toast = useToast(); - const storedHideColumn = JSON.parse(localStorage.getItem('hideColumn') || 'false'); - if (storedHideColumn === 'false') { - setHideColumn(new Array(12).fill(false)); - } else { - setHideColumn(storedHideColumn); - } + useEffect(() => { + const storedHideColumn = JSON.parse(localStorage.getItem('hideColumn') || 'false'); + if (storedHideColumn === 'false') { + setHideColumn((prev) => { + const newHideColumn = new Array(12).fill(false); + return prev !== newHideColumn ? newHideColumn : prev; + }); + } else { + setHideColumn((prev) => (prev !== storedHideColumn ? storedHideColumn : prev)); + } + }, [setHideColumn]); if (isLoading) return ; diff --git a/src/frontend/src/pages/SettingsPage/UserScheduleSettings/UserScheduleSettingsEdit.tsx b/src/frontend/src/pages/SettingsPage/UserScheduleSettings/UserScheduleSettingsEdit.tsx index 70c81e3478..d0bb566451 100644 --- a/src/frontend/src/pages/SettingsPage/UserScheduleSettings/UserScheduleSettingsEdit.tsx +++ b/src/frontend/src/pages/SettingsPage/UserScheduleSettings/UserScheduleSettingsEdit.tsx @@ -38,9 +38,14 @@ const UserScheduleSettingsEdit: React.FC = ({ const toast = useToast(); const onFormSubmit = (data: ScheduleSettingsFormInput) => { - if (data.personalZoomLink !== '' && !data.personalZoomLink.startsWith('https://zoom.us/j/')) { - toast.error('Invalid Zoom Link Format. Must start with "https://zoom.us/j/"'); - return; + if (data.personalZoomLink !== '') { + if (!data.personalZoomLink.startsWith('https://')) { + toast.error('Invalid Zoom Link Format. Link must start with "https://".'); + return; + } else if (!data.personalZoomLink.includes('zoom.us/j/')) { + toast.error('Invalid Zoom Link Format. Link must contain "zoom.us/j/".'); + return; + } } onSubmit({ availability: Array.from(availabilities.values()), ...data }); }; diff --git a/src/frontend/src/pages/WorkPackageForm/WorkPackageFormDetails.tsx b/src/frontend/src/pages/WorkPackageForm/WorkPackageFormDetails.tsx index a7f38b178c..31a6a516e9 100644 --- a/src/frontend/src/pages/WorkPackageForm/WorkPackageFormDetails.tsx +++ b/src/frontend/src/pages/WorkPackageForm/WorkPackageFormDetails.tsx @@ -93,7 +93,7 @@ const WorkPackageFormDetails: React.FC = ({
- Start Date (YYYY-MM-DD) + Start Date (MM-DD-YYYY) = ({ - Calculated End Date (YYYY-MM-DD) + Calculated End Date (MM-DD-YYYY) diff --git a/src/frontend/src/utils/change-request.utils.ts b/src/frontend/src/utils/change-request.utils.ts index cef541fe04..3f498f5575 100644 --- a/src/frontend/src/utils/change-request.utils.ts +++ b/src/frontend/src/utils/change-request.utils.ts @@ -3,8 +3,70 @@ * See the LICENSE file in the repository root folder for details. */ -import { StandardChangeRequest } from 'shared'; +import { ChangeRequest, equalsWbsNumber, Project, StandardChangeRequest, User, WorkPackage } from 'shared'; +import { makeTeamList } from './teams.utils'; export const hasProposedChanges = (cr: StandardChangeRequest) => { return cr.workPackageProposedChanges || cr.projectProposedChanges; }; + +export const getCRsToReview = ( + projects: Project[], + workPackages: WorkPackage[], + user: User, + changeRequests: ChangeRequest[] +): ChangeRequest[] => { + // projects whose change requests the user would have to review + const myProjects = projects.filter((project: Project) => { + const projectMemberIds = project.teams.flatMap((team) => makeTeamList(team)).map((user) => user.userId); + return ( + projectMemberIds.includes(user.userId) || + (project.lead && project.lead.userId === user.userId) || + (project.manager && project.manager.userId === user.userId) + ); + }); + + // work packages whose change requests the user would have to review + const myWorkPackages = workPackages.filter( + (wp: WorkPackage) => + (wp.lead ? wp.lead.userId === user.userId : false) || (wp.manager ? wp.manager.userId === user.userId : false) + ); + + // all of the wbs numbers (in x.x.x string format) corresponding to projects and work packages + // whose change requests the user would have to review + const myWbsNumbers = myProjects + .map((project: Project) => project.wbsNum) + .concat(myWorkPackages.map((wp: WorkPackage) => wp.wbsNum)); + const crToReview = changeRequests + .filter( + (cr) => + !cr.dateReviewed && + cr.submitter.userId !== user.userId && + (myWbsNumbers.some((wbsNum) => equalsWbsNumber(wbsNum, cr.wbsNum)) || + cr.requestedReviewers.map((user) => user.userId).includes(user.userId)) + ) + .sort((a, b) => b.dateSubmitted.getTime() - a.dateSubmitted.getTime()); + return crToReview; +}; + +export const getCRsUnreviewed = (user: User, changeRequests: ChangeRequest[]) => { + const crUnreviewed = changeRequests + .filter((cr: ChangeRequest) => !cr.dateReviewed && cr.submitter.userId === user.userId) + .sort((a, b) => b.dateSubmitted.getTime() - a.dateSubmitted.getTime()); + return crUnreviewed; +}; + +export const getCRsApproved = (user: User, changeRequests: ChangeRequest[]) => { + const currentDate = new Date(); + const crApproved = changeRequests + .filter( + (cr: ChangeRequest) => + cr.dateReviewed && + cr.accepted && + cr.submitter.userId === user.userId && + currentDate.getTime() - cr.dateReviewed.getTime() <= 1000 * 60 * 60 * 24 * 5 + ) + .sort((a, b) => (a.dateReviewed && b.dateReviewed ? b.dateReviewed.getTime() - a.dateReviewed.getTime() : 0)); + + return crApproved; +}; diff --git a/src/frontend/src/utils/datetime.utils.ts b/src/frontend/src/utils/datetime.utils.ts index de14dfd9df..1b23c43118 100644 --- a/src/frontend/src/utils/datetime.utils.ts +++ b/src/frontend/src/utils/datetime.utils.ts @@ -24,3 +24,18 @@ export const transformDate = (date: Date) => { const day = date.getDate() < 10 ? `0${date.getDate()}` : date.getDate().toString(); return `${date.getFullYear().toString()}/${month}/${day}`; }; + +export const formatDate = (date: Date) => { + const month = date.getMonth() + 1 < 10 ? `0${date.getMonth() + 1}` : (date.getMonth() + 1).toString(); + const day = date.getDate() + 1 < 10 ? `0${date.getDate() + 1}` : (date.getDate() + 1).toString(); + return `${month}/${day}/${date.getFullYear().toString()}`; +}; + +export const daysOverdue = (deadline: Date) => { + return Math.round((new Date().getTime() - deadline.getTime()) / (1000 * 60 * 60 * 24)); +}; + +export const timezoneOffset = (date: Date) => { + const timestamp = new Date(date).getTime() - new Date(date).getTimezoneOffset() * -60000; + return new Date(timestamp); +}; diff --git a/src/frontend/src/utils/reimbursement-request.utils.ts b/src/frontend/src/utils/reimbursement-request.utils.ts index 19fa967789..1542897bda 100644 --- a/src/frontend/src/utils/reimbursement-request.utils.ts +++ b/src/frontend/src/utils/reimbursement-request.utils.ts @@ -109,23 +109,20 @@ export const getAllWbsElements = (projects: Project[]): { wbsNum: WbsNumber; wbs export const cleanReimbursementRequestStatus = (status: ReimbursementStatusType) => { switch (status) { - case ReimbursementStatusType.ADVISOR_APPROVED: { + case ReimbursementStatusType.ADVISOR_APPROVED: return 'Advisor Approved'; - } - case ReimbursementStatusType.PENDING_FINANCE: { + case ReimbursementStatusType.PENDING_FINANCE: return 'Pending Finance Team'; - } - case ReimbursementStatusType.REIMBURSED: { + case ReimbursementStatusType.REIMBURSED: return 'Reimbursed'; - } - case ReimbursementStatusType.SABO_SUBMITTED: { + case ReimbursementStatusType.SABO_SUBMITTED: return 'Submitted to SABO'; - } - case ReimbursementStatusType.DENIED: { + case ReimbursementStatusType.DENIED: return 'Denied'; - } - default: + case ReimbursementStatusType.PENDING_LEADERSHIP_APPROVAL: return 'Pending Leadership Approval'; + case ReimbursementStatusType.LEADERSHIP_APPROVED: + return 'Leadership Approved'; } }; diff --git a/src/frontend/src/utils/routes.ts b/src/frontend/src/utils/routes.ts index c0e518ebeb..7540271b41 100644 --- a/src/frontend/src/utils/routes.ts +++ b/src/frontend/src/utils/routes.ts @@ -4,6 +4,7 @@ */ /**************** General Section ****************/ +const BASE = `/`; const HOME = `/home`; const LOGIN = `/login`; const INFO = `/info`; @@ -56,6 +57,7 @@ const DESIGN_REVIEW_BY_ID = CALENDAR + `/:id`; const ORGANIZATIONS = `/organizations`; export const routes = { + BASE, HOME, LOGIN, INFO, diff --git a/src/frontend/src/utils/task.utils.ts b/src/frontend/src/utils/task.utils.ts index ab597b785f..b3a57067b2 100644 --- a/src/frontend/src/utils/task.utils.ts +++ b/src/frontend/src/utils/task.utils.ts @@ -8,6 +8,7 @@ import { Project, Task, TaskPriority, TaskStatus, TeamPreview, User, UserPreview import { EditTaskFormInput } from '../pages/ProjectDetailPage/ProjectViewContainer/TaskList/TaskFormModal'; import { fullNamePipe } from './pipes'; import { makeTeamList } from './teams.utils'; +import { daysOverdue } from './datetime.utils'; //this is needed to fix some weird bug with getActions() //see comment by michaldudak commented on Dec 5, 2022 @@ -68,3 +69,18 @@ export const taskUserToAutocompleteOption = (user: User): { label: string; id: s export const getTaskAssigneeOptions = (teams: TeamPreview[]): User[] => { return teams.map((team) => makeTeamList(team)).flat(); }; + +export const taskPriorityColor = (task: Task) => { + return task.priority === TaskPriority.Low + ? '#1CAC19' + : task.priority === TaskPriority.Medium + ? '#ffc700' + : task.priority === TaskPriority.High + ? '#EF4345' + : ''; +}; + +export const getOverdueTasks = (tasks: Task[]) => { + const overdueTasks = new Set(tasks.filter((task) => daysOverdue(new Date(task.deadline)) > 0)); + return [...overdueTasks]; +}; diff --git a/src/frontend/src/utils/urls.ts b/src/frontend/src/utils/urls.ts index 7448b1837b..63fe0c9957 100644 --- a/src/frontend/src/utils/urls.ts +++ b/src/frontend/src/utils/urls.ts @@ -24,6 +24,8 @@ const userFavoriteProjects = (id: string) => `${usersById(id)}/favorite-projects const userSecureSettings = (id: string) => `${usersById(id)}/secure-settings`; const userScheduleSettings = (id: string) => `${usersById(id)}/schedule-settings`; const userScheduleSettingsSet = () => `${users()}/schedule-settings/set`; +const userTasks = (id: string) => `${usersById(id)}/tasks`; +const manyUserTasks = () => `${users()}/tasks/get-many`; /**************** Projects Endpoints ****************/ const projects = () => `${API_URL}/projects`; @@ -170,8 +172,15 @@ const workPackageTemplateDelete = (workPackageTemplateId: string) => /******************* Organizations Endpoints ********************/ const organizations = () => `${API_URL}/organizations`; +const currentOrganization = () => `${organizations()}/current`; const organizationsUsefulLinks = () => `${organizations()}/useful-links`; const organizationsSetUsefulLinks = () => `${organizationsUsefulLinks()}/set`; +const organizationsSetDescription = () => `${organizations()}/description/set`; +const organizationsFeaturedProjects = () => `${organizations()}/featured-projects`; +const organizationsLogoImage = () => `${organizations()}/logo`; +const organizationsSetLogoImage = () => `${organizations()}/logo/update`; +const organizationsSetFeaturedProjects = () => `${organizationsFeaturedProjects()}/set`; +const organizationsSetWorkspaceId = () => `${organizations()}/workspaceId/set`; /******************* Car Endpoints ********************/ const cars = () => `${API_URL}/cars`; @@ -182,9 +191,25 @@ const recruitment = () => `${API_URL}/recruitment`; const allMilestones = () => `${recruitment()}/milestones`; const milestoneCreate = () => `${recruitment()}/milestone/create`; const milestoneEdit = (id: string) => `${recruitment()}/milestone/${id}/edit`; +const milestoneDelete = (id: string) => `${recruitment()}/milestone/${id}/delete`; const allFaqs = () => `${recruitment()}/faqs`; const faqCreate = () => `${recruitment()}/faq/create`; const faqEdit = (id: string) => `${recruitment()}/faq/${id}/edit`; +const faqDelete = (id: string) => `${recruitment()}/faq/${id}/delete`; + +/************** Pop Up Endpoints ***************/ +const popUps = () => `${API_URL}/pop-ups`; +const popUpsCurrentUser = () => `${popUps()}/current-user`; +const popUpsRemove = (id: string) => `${popUps()}/${id}/remove`; + +/************** Announcement Endpoints ***************/ +const announcements = () => `${API_URL}/announcements`; +const announcementsCurrentUser = () => `${announcements()}/current-user`; +const announcementsRemove = (id: string) => `${announcements()}/${id}/remove`; + +/************** Onboarding Endpoints ***************/ +const onboarding = () => `${API_URL}/onboarding`; +const imageById = (imageId: string) => `${onboarding()}/image/${imageId}`; /**************** Other Endpoints ****************/ const version = () => `https://api.github.com/repos/Northeastern-Electric-Racing/FinishLine/releases/latest`; @@ -202,6 +227,8 @@ export const apiUrls = { userSecureSettings, userScheduleSettings, userScheduleSettingsSet, + userTasks, + manyUserTasks, projects, allProjects, @@ -322,8 +349,15 @@ export const apiUrls = { workPackageTemplatesCreate, workPackageTemplateDelete, + currentOrganization, organizationsUsefulLinks, organizationsSetUsefulLinks, + organizationsFeaturedProjects, + organizationsSetDescription, + organizationsLogoImage, + organizationsSetLogoImage, + organizationsSetFeaturedProjects, + organizationsSetWorkspaceId, cars, carsCreate, @@ -331,9 +365,20 @@ export const apiUrls = { allMilestones, milestoneCreate, milestoneEdit, + milestoneDelete, allFaqs, faqCreate, faqEdit, + faqDelete, + imageById, + + popUps, + popUpsCurrentUser, + popUpsRemove, + + announcements, + announcementsCurrentUser, + announcementsRemove, version }; diff --git a/src/frontend/src/utils/work-package.utils.ts b/src/frontend/src/utils/work-package.utils.ts index 31ebcb98fa..5e39ad6b7d 100644 --- a/src/frontend/src/utils/work-package.utils.ts +++ b/src/frontend/src/utils/work-package.utils.ts @@ -1,4 +1,4 @@ -import { WbsElement, wbsPipe } from 'shared'; +import { addWeeksToDate, WbsElement, WbsElementStatus, wbsPipe, WorkPackage } from 'shared'; import { WPFormType } from './form'; export const getTitleFromFormType = (formType: WPFormType, wbsElement: WbsElement): string => { @@ -11,3 +11,38 @@ export const getTitleFromFormType = (formType: WPFormType, wbsElement: WbsElemen return `${wbsPipe(wbsElement.wbsNum)} - ${wbsElement.name}`; } }; + +/** + * Given a list of work packages, return the work packages that are overdue. + * @param wpList a list of work packages. + * @returns a sub-list of work packages that are not complete, and have end dates before the current date. + */ +export const getOverdueWorkPackages = (wpList: WorkPackage[]): WorkPackage[] => { + return wpList.filter((wp) => wp.status !== WbsElementStatus.Complete && new Date(wp.endDate) <= new Date()); +}; + +/** + * Given a list of work packages, return the work packages that are upcoming. + * @param wpList a list of work packages. + * @returns a sub-list of work packages that are active and have a start date within the next 2 weeks. + */ +export const getUpcomingWorkPackages = (wpList: WorkPackage[]): WorkPackage[] => { + return wpList.filter( + (wp) => + wp.status !== WbsElementStatus.Complete && + new Date(wp.startDate) <= addWeeksToDate(new Date(), 2) && + new Date(wp.startDate) >= new Date() + ); +}; + +/** + * Given a list of work packages, return the work packages that are in progress. + * @param wpList a list of work packages. + * @returns a sub-list of work packages that are active, have a start date in the past, and an end date in the future. + */ +export const getInProgressWorkPackages = (wpList: WorkPackage[]): WorkPackage[] => { + return wpList.filter( + (wp) => + wp.status === WbsElementStatus.Active && new Date(wp.endDate) >= new Date() && new Date(wp.startDate) <= new Date() + ); +}; diff --git a/src/shared/index.ts b/src/shared/index.ts index 1d3f6c399f..93e9c8899b 100644 --- a/src/shared/index.ts +++ b/src/shared/index.ts @@ -11,7 +11,8 @@ export * from './src/types/team-types'; export * from './src/types/task-types'; export * from './src/types/reimbursement-requests-types'; export * from './src/types/design-review-types'; - +export * from './src/types/pop-up-types'; +export * from './src/types/announcements.types'; export * from './src/validate-wbs'; export * from './src/date-utils'; diff --git a/src/shared/src/date-utils.ts b/src/shared/src/date-utils.ts index 4cf3f11469..a7980552c3 100644 --- a/src/shared/src/date-utils.ts +++ b/src/shared/src/date-utils.ts @@ -35,6 +35,16 @@ const getDay = (date: Date): number => { return Math.round(date.getTime() / (1000 * 60 * 60 * 24)); }; +/** + * Gets the beginning of the day + * @returns the beginning of the day (at 12am local) + */ +export const startOfDay = (date: Date): Date => { + const ret = new Date(date); + ret.setHours(0, 0, 0, 0); + return ret; +}; + /** * Calculate the days between two dates */ diff --git a/src/shared/src/permission-utils.ts b/src/shared/src/permission-utils.ts index b297f1b558..9eace8a590 100644 --- a/src/shared/src/permission-utils.ts +++ b/src/shared/src/permission-utils.ts @@ -48,4 +48,14 @@ export const isGuest: PermissionCheck = (role?: Role) => { return role === RoleEnum.GUEST; }; +export const isMember: PermissionCheck = (role?: Role) => { + if (!role) return true; + return role === RoleEnum.MEMBER; +}; + +export const isLead: PermissionCheck = (role?: Role) => { + if (!role) return true; + return role === RoleEnum.HEAD || role === RoleEnum.LEADERSHIP; +}; + export type PermissionCheck = (role: Role | undefined) => boolean; diff --git a/src/shared/src/types/announcements.types.ts b/src/shared/src/types/announcements.types.ts new file mode 100644 index 0000000000..ac31f72062 --- /dev/null +++ b/src/shared/src/types/announcements.types.ts @@ -0,0 +1,12 @@ +import { User } from './user-types'; + +export interface Announcement { + announcementId: string; + text: string; + usersReceived: User[]; + senderName: string; + dateMessageSent: Date; + slackEventId: string; + slackChannelName: string; + dateDeleted?: Date; +} diff --git a/src/shared/src/types/pop-up-types.ts b/src/shared/src/types/pop-up-types.ts new file mode 100644 index 0000000000..2b517a3900 --- /dev/null +++ b/src/shared/src/types/pop-up-types.ts @@ -0,0 +1,6 @@ +export interface PopUp { + popUpId: string; + text: string; + iconName: string; + eventLink?: string; +} diff --git a/src/shared/src/types/user-types.ts b/src/shared/src/types/user-types.ts index 1a95a46542..f4432cc60a 100644 --- a/src/shared/src/types/user-types.ts +++ b/src/shared/src/types/user-types.ts @@ -4,6 +4,7 @@ */ import { AvailabilityCreateArgs } from './design-review-types'; +import { Team } from './team-types'; export interface User { userId: string; @@ -43,6 +44,7 @@ export interface Organization { treasurer?: UserPreview; advisor?: UserPreview; description: string; + slackWorkspaceId?: string; } /** @@ -64,6 +66,8 @@ export interface AuthenticatedUser { isAtLeastFinanceLead?: boolean; organizations: string[]; currentOrganization?: OrganizationPreview; + teamsAsHead?: Team[]; + teamsAsLead?: Team[]; } export interface UserSettings { diff --git a/yarn.lock b/yarn.lock index 6586f5c64b..3ae1a42802 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6,9 +6,9 @@ __metadata: cacheKey: 8 "@adobe/css-tools@npm:^4.0.1": - version: 4.4.0 - resolution: "@adobe/css-tools@npm:4.4.0" - checksum: 1f08fb49bf17fc7f2d1a86d3e739f29ca80063d28168307f1b0a962ef37501c5667271f6771966578897f2e94e43c4770fd802728a6e6495b812da54112d506a + version: 4.4.1 + resolution: "@adobe/css-tools@npm:4.4.1" + checksum: bbded8a03c314afee0fb0b42922f664f437e0e2f0b86eeeb06dee9d02cd8fc958cf87aa3314952b00074e0b22fc5b8da23f45b61b6f8291c8aaa7cffc56a76e9 languageName: node linkType: hard @@ -40,20 +40,21 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.24.7, @babel/code-frame@npm:^7.5.5": - version: 7.24.7 - resolution: "@babel/code-frame@npm:7.24.7" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.5.5": + version: 7.26.2 + resolution: "@babel/code-frame@npm:7.26.2" dependencies: - "@babel/highlight": ^7.24.7 + "@babel/helper-validator-identifier": ^7.25.9 + js-tokens: ^4.0.0 picocolors: ^1.0.0 - checksum: 830e62cd38775fdf84d612544251ce773d544a8e63df667728cc9e0126eeef14c6ebda79be0f0bc307e8318316b7f58c27ce86702e0a1f5c321d842eb38ffda4 + checksum: db13f5c42d54b76c1480916485e6900748bbcb0014a8aca87f50a091f70ff4e0d0a6db63cade75eb41fcc3d2b6ba0a7f89e343def4f96f00269b41b8ab8dd7b8 languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/compat-data@npm:7.24.7" - checksum: 1fc276825dd434fe044877367dfac84171328e75a8483a6976aa28bf833b32367e90ee6df25bdd97c287d1aa8019757adcccac9153de70b1932c0d243a978ae9 +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.25.9, @babel/compat-data@npm:^7.26.0": + version: 7.26.2 + resolution: "@babel/compat-data@npm:7.26.2" + checksum: d52fae9b0dc59b409d6005ae6b172e89329f46d68136130065ebe923a156fc633e0f1c8600b3e319b9e0f99fd948f64991a5419e2e9431d00d9d235d5f7a7618 languageName: node linkType: hard @@ -81,32 +82,32 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.1.0, @babel/core@npm:^7.12.3, @babel/core@npm:^7.16.0, @babel/core@npm:^7.20.5, @babel/core@npm:^7.24.5, @babel/core@npm:^7.7.5, @babel/core@npm:^7.8.4": - version: 7.24.7 - resolution: "@babel/core@npm:7.24.7" +"@babel/core@npm:^7.1.0, @babel/core@npm:^7.12.3, @babel/core@npm:^7.16.0, @babel/core@npm:^7.20.5, @babel/core@npm:^7.26.0, @babel/core@npm:^7.7.5, @babel/core@npm:^7.8.4": + version: 7.26.0 + resolution: "@babel/core@npm:7.26.0" dependencies: "@ampproject/remapping": ^2.2.0 - "@babel/code-frame": ^7.24.7 - "@babel/generator": ^7.24.7 - "@babel/helper-compilation-targets": ^7.24.7 - "@babel/helper-module-transforms": ^7.24.7 - "@babel/helpers": ^7.24.7 - "@babel/parser": ^7.24.7 - "@babel/template": ^7.24.7 - "@babel/traverse": ^7.24.7 - "@babel/types": ^7.24.7 + "@babel/code-frame": ^7.26.0 + "@babel/generator": ^7.26.0 + "@babel/helper-compilation-targets": ^7.25.9 + "@babel/helper-module-transforms": ^7.26.0 + "@babel/helpers": ^7.26.0 + "@babel/parser": ^7.26.0 + "@babel/template": ^7.25.9 + "@babel/traverse": ^7.25.9 + "@babel/types": ^7.26.0 convert-source-map: ^2.0.0 debug: ^4.1.0 gensync: ^1.0.0-beta.2 json5: ^2.2.3 semver: ^6.3.1 - checksum: 017497e2a1b4683a885219eef7d2aee83c1c0cf353506b2e180b73540ec28841d8ef1ea1837fa69f8c561574b24ddd72f04764b27b87afedfe0a07299ccef24d + checksum: b296084cfd818bed8079526af93b5dfa0ba70282532d2132caf71d4060ab190ba26d3184832a45accd82c3c54016985a4109ab9118674347a7e5e9bc464894e6 languageName: node linkType: hard "@babel/eslint-parser@npm:^7.16.3": - version: 7.24.7 - resolution: "@babel/eslint-parser@npm:7.24.7" + version: 7.25.9 + resolution: "@babel/eslint-parser@npm:7.25.9" dependencies: "@nicolo-ribaudo/eslint-scope-5-internals": 5.1.1-v1 eslint-visitor-keys: ^2.1.0 @@ -114,89 +115,88 @@ __metadata: peerDependencies: "@babel/core": ^7.11.0 eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - checksum: 0e08ccecfe48cf9dacd96fb46747014b9c3683882ae6886a17a666533f0d5e99b61e31e3992ffee0efc67d805ae8be9b2a6342ce5d66a36de8d99d88c9a244a0 + checksum: dd2afa122b62a5b07c1e71d1c23b2cd4d655d96609eb2ba1b1ae3ec6f415f4365b77d6669ff859aa7b75952fb63a1d29c5db6e5811fc4012841491cb2dee36e4 languageName: node linkType: hard -"@babel/generator@npm:^7.12.1, @babel/generator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/generator@npm:7.24.7" +"@babel/generator@npm:^7.12.1, @babel/generator@npm:^7.25.9, @babel/generator@npm:^7.26.0": + version: 7.26.2 + resolution: "@babel/generator@npm:7.26.2" dependencies: - "@babel/types": ^7.24.7 + "@babel/parser": ^7.26.2 + "@babel/types": ^7.26.0 "@jridgewell/gen-mapping": ^0.3.5 "@jridgewell/trace-mapping": ^0.3.25 - jsesc: ^2.5.1 - checksum: 0ff31a73b15429f1287e4d57b439bba4a266f8c673bb445fe313b82f6d110f586776997eb723a777cd7adad9d340edd162aea4973a90112c5d0cfcaf6686844b + jsesc: ^3.0.2 + checksum: 6ff850b7d6082619f8c2f518d993cf7254cfbaa20b026282cbef5c9b2197686d076a432b18e36c4d1a42721c016df4f77a8f62c67600775d9683621d534b91b4 languageName: node linkType: hard -"@babel/helper-annotate-as-pure@npm:^7.18.6, @babel/helper-annotate-as-pure@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-annotate-as-pure@npm:7.24.7" +"@babel/helper-annotate-as-pure@npm:^7.18.6, @babel/helper-annotate-as-pure@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-annotate-as-pure@npm:7.25.9" dependencies: - "@babel/types": ^7.24.7 - checksum: 6178566099a6a0657db7a7fa601a54fb4731ca0b8614fbdccfd8e523c210c13963649bc8fdfd53ce7dd14d05e3dda2fb22dea5b30113c488b9eb1a906d60212e + "@babel/types": ^7.25.9 + checksum: 41edda10df1ae106a9b4fe617bf7c6df77db992992afd46192534f5cff29f9e49a303231733782dd65c5f9409714a529f215325569f14282046e9d3b7a1ffb6c languageName: node linkType: hard -"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.24.7" +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.25.9" dependencies: - "@babel/traverse": ^7.24.7 - "@babel/types": ^7.24.7 - checksum: 71a6158a9fdebffb82fdc400d5555ba8f2e370cea81a0d578155877bdc4db7d5252b75c43b2fdf3f72b3f68348891f99bd35ae315542daad1b7ace8322b1abcb + "@babel/traverse": ^7.25.9 + "@babel/types": ^7.25.9 + checksum: e1bb465b3b0155702d82cfef09e3813e87a6d777cdd2c513796861eac14953340491eafea1d4109278bf4ceb48b54074c45758f042c0544d00c498090bee5a6f languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-compilation-targets@npm:7.24.7" +"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-compilation-targets@npm:7.25.9" dependencies: - "@babel/compat-data": ^7.24.7 - "@babel/helper-validator-option": ^7.24.7 - browserslist: ^4.22.2 + "@babel/compat-data": ^7.25.9 + "@babel/helper-validator-option": ^7.25.9 + browserslist: ^4.24.0 lru-cache: ^5.1.1 semver: ^6.3.1 - checksum: dfc88bc35e223ade796c7267901728217c665adc5bc2e158f7b0ae850de14f1b7941bec4fe5950ae46236023cfbdeddd9c747c276acf9b39ca31f8dd97dc6cc6 + checksum: 3af536e2db358b38f968abdf7d512d425d1018fef2f485d6f131a57a7bcaed32c606b4e148bb230e1508fa42b5b2ac281855a68eb78270f54698c48a83201b9b languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.21.0, @babel/helper-create-class-features-plugin@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-create-class-features-plugin@npm:7.24.7" +"@babel/helper-create-class-features-plugin@npm:^7.18.6, @babel/helper-create-class-features-plugin@npm:^7.21.0, @babel/helper-create-class-features-plugin@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-create-class-features-plugin@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": ^7.24.7 - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-function-name": ^7.24.7 - "@babel/helper-member-expression-to-functions": ^7.24.7 - "@babel/helper-optimise-call-expression": ^7.24.7 - "@babel/helper-replace-supers": ^7.24.7 - "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 - "@babel/helper-split-export-declaration": ^7.24.7 + "@babel/helper-annotate-as-pure": ^7.25.9 + "@babel/helper-member-expression-to-functions": ^7.25.9 + "@babel/helper-optimise-call-expression": ^7.25.9 + "@babel/helper-replace-supers": ^7.25.9 + "@babel/helper-skip-transparent-expression-wrappers": ^7.25.9 + "@babel/traverse": ^7.25.9 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0 - checksum: 371a181a1717a9b0cebc97727c8ea9ca6afa34029476a684b6030f9d1ad94dcdafd7de175da10b63ae3ba79e4e82404db8ed968ebf264b768f097e5d64faab71 + checksum: 91dd5f203ed04568c70b052e2f26dfaac7c146447196c00b8ecbb6d3d2f3b517abadb985d3321a19d143adaed6fe17f7f79f8f50e0c20e9d8ad83e1027b42424 languageName: node linkType: hard -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.24.7" +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": ^7.24.7 - regexpu-core: ^5.3.1 + "@babel/helper-annotate-as-pure": ^7.25.9 + regexpu-core: ^6.1.1 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0 - checksum: 17c59fa222af50f643946eca940ce1d474ff2da1f4afed2312687ab9d708ebbb8c9372754ddbdf44b6e21ead88b8fc144644f3a7b63ccb886de002458cef3974 + checksum: 563ed361ceed3d7a9d64dd58616bf6f0befcc23620ab22d31dd6d8b751d3f99d6d210487b1a5a1e209ab4594df67bacfab7445cbfa092bfe2b719cd42ae1ba6f languageName: node linkType: hard -"@babel/helper-define-polyfill-provider@npm:^0.6.1, @babel/helper-define-polyfill-provider@npm:^0.6.2": - version: 0.6.2 - resolution: "@babel/helper-define-polyfill-provider@npm:0.6.2" +"@babel/helper-define-polyfill-provider@npm:^0.6.2, @babel/helper-define-polyfill-provider@npm:^0.6.3": + version: 0.6.3 + resolution: "@babel/helper-define-polyfill-provider@npm:0.6.3" dependencies: "@babel/helper-compilation-targets": ^7.22.6 "@babel/helper-plugin-utils": ^7.22.5 @@ -205,253 +205,226 @@ __metadata: resolve: ^1.14.2 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 2bba965ea9a4887ddf9c11d51d740ab473bd7597b787d042c325f6a45912dfe908c2d6bb1d837bf82f7e9fa51e6ad5150563c58131d2bb85515e63d971414a9c + checksum: 710e6d8a5391736b9f53f09d0494575c2e03de199ad8d1349bc8e514cb85251ea1f1842c2ff44830849d482052ddb42ae931101002a87a263b12f649c2e57c01 languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-environment-visitor@npm:7.24.7" +"@babel/helper-member-expression-to-functions@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-member-expression-to-functions@npm:7.25.9" dependencies: - "@babel/types": ^7.24.7 - checksum: 079d86e65701b29ebc10baf6ed548d17c19b808a07aa6885cc141b690a78581b180ee92b580d755361dc3b16adf975b2d2058b8ce6c86675fcaf43cf22f2f7c6 + "@babel/traverse": ^7.25.9 + "@babel/types": ^7.25.9 + checksum: 8e2f1979b6d596ac2a8cbf17f2cf709180fefc274ac3331408b48203fe19134ed87800774ef18838d0275c3965130bae22980d90caed756b7493631d4b2cf961 languageName: node linkType: hard -"@babel/helper-function-name@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-function-name@npm:7.24.7" +"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-module-imports@npm:7.25.9" dependencies: - "@babel/template": ^7.24.7 - "@babel/types": ^7.24.7 - checksum: 142ee08922074dfdc0ff358e09ef9f07adf3671ab6eef4fca74dcf7a551f1a43717e7efa358c9e28d7eea84c28d7f177b7a58c70452fc312ae3b1893c5dab2a4 + "@babel/traverse": ^7.25.9 + "@babel/types": ^7.25.9 + checksum: 1b411ce4ca825422ef7065dffae7d8acef52023e51ad096351e3e2c05837e9bf9fca2af9ca7f28dc26d596a588863d0fedd40711a88e350b736c619a80e704e6 languageName: node linkType: hard -"@babel/helper-hoist-variables@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-hoist-variables@npm:7.24.7" +"@babel/helper-module-transforms@npm:^7.12.1, @babel/helper-module-transforms@npm:^7.25.9, @babel/helper-module-transforms@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/helper-module-transforms@npm:7.26.0" dependencies: - "@babel/types": ^7.24.7 - checksum: 6cfdcf2289cd12185dcdbdf2435fa8d3447b797ac75851166de9fc8503e2fd0021db6baf8dfbecad3753e582c08e6a3f805c8d00cbed756060a877d705bd8d8d - languageName: node - linkType: hard - -"@babel/helper-member-expression-to-functions@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-member-expression-to-functions@npm:7.24.7" - dependencies: - "@babel/traverse": ^7.24.7 - "@babel/types": ^7.24.7 - checksum: 9fecf412f85fa23b7cf55d19eb69de39f8240426a028b141c9df2aed8cfedf20b3ec3318d40312eb7a3dec9eea792828ce0d590e0ff62da3da532482f537192c - languageName: node - linkType: hard - -"@babel/helper-module-imports@npm:^7.0.0, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-module-imports@npm:7.24.7" - dependencies: - "@babel/traverse": ^7.24.7 - "@babel/types": ^7.24.7 - checksum: 8ac15d96d262b8940bc469052a048e06430bba1296369be695fabdf6799f201dd0b00151762b56012a218464e706bc033f27c07f6cec20c6f8f5fd6543c67054 - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.12.1, @babel/helper-module-transforms@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-module-transforms@npm:7.24.7" - dependencies: - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-module-imports": ^7.24.7 - "@babel/helper-simple-access": ^7.24.7 - "@babel/helper-split-export-declaration": ^7.24.7 - "@babel/helper-validator-identifier": ^7.24.7 + "@babel/helper-module-imports": ^7.25.9 + "@babel/helper-validator-identifier": ^7.25.9 + "@babel/traverse": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0 - checksum: ddff3b41c2667876b4e4e73d961168f48a5ec9560c95c8c2d109e6221f9ca36c6f90c6317eb7a47f2a3c99419c356e529a86b79174cad0d4f7a61960866b88ca + checksum: 942eee3adf2b387443c247a2c190c17c4fd45ba92a23087abab4c804f40541790d51ad5277e4b5b1ed8d5ba5b62de73857446b7742f835c18ebd350384e63917 languageName: node linkType: hard -"@babel/helper-optimise-call-expression@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-optimise-call-expression@npm:7.24.7" +"@babel/helper-optimise-call-expression@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-optimise-call-expression@npm:7.25.9" dependencies: - "@babel/types": ^7.24.7 - checksum: 280654eaf90e92bf383d7eed49019573fb35a98c9e992668f701ad099957246721044be2068cf6840cb2299e0ad393705a1981c88c23a1048096a8d59e5f79a3 + "@babel/types": ^7.25.9 + checksum: f09d0ad60c0715b9a60c31841b3246b47d67650c512ce85bbe24a3124f1a4d66377df793af393273bc6e1015b0a9c799626c48e53747581c1582b99167cc65dc languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": - version: 7.24.7 - resolution: "@babel/helper-plugin-utils@npm:7.24.7" - checksum: 81f2a15751d892e4a8fce25390f973363a5b27596167861d2d6eab0f61856eb2ba389b031a9f19f669c0bd4dd601185828d3cebafd25431be7a1696f2ce3ef68 +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.25.9, @babel/helper-plugin-utils@npm:^7.8.0": + version: 7.25.9 + resolution: "@babel/helper-plugin-utils@npm:7.25.9" + checksum: e19ec8acf0b696756e6d84531f532c5fe508dce57aa68c75572a77798bd04587a844a9a6c8ea7d62d673e21fdc174d091c9097fb29aea1c1b49f9c6eaa80f022 languageName: node linkType: hard -"@babel/helper-remap-async-to-generator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-remap-async-to-generator@npm:7.24.7" +"@babel/helper-remap-async-to-generator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-remap-async-to-generator@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": ^7.24.7 - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-wrap-function": ^7.24.7 + "@babel/helper-annotate-as-pure": ^7.25.9 + "@babel/helper-wrap-function": ^7.25.9 + "@babel/traverse": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0 - checksum: bab7be178f875350f22a2cb9248f67fe3a8a8128db77a25607096ca7599fd972bc7049fb11ed9e95b45a3f1dd1fac3846a3279f9cbac16f337ecb0e6ca76e1fc + checksum: ea37ad9f8f7bcc27c109963b8ebb9d22bac7a5db2a51de199cb560e251d5593fe721e46aab2ca7d3e7a24b0aa4aff0eaf9c7307af9c2fd3a1d84268579073052 languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-replace-supers@npm:7.24.7" +"@babel/helper-replace-supers@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-replace-supers@npm:7.25.9" dependencies: - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-member-expression-to-functions": ^7.24.7 - "@babel/helper-optimise-call-expression": ^7.24.7 + "@babel/helper-member-expression-to-functions": ^7.25.9 + "@babel/helper-optimise-call-expression": ^7.25.9 + "@babel/traverse": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0 - checksum: 2bf0d113355c60d86a04e930812d36f5691f26c82d4ec1739e5ec0a4c982c9113dad3167f7c74f888a96328bd5e696372232406d8200e5979e6e0dc2af5e7c76 - languageName: node - linkType: hard - -"@babel/helper-simple-access@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-simple-access@npm:7.24.7" - dependencies: - "@babel/traverse": ^7.24.7 - "@babel/types": ^7.24.7 - checksum: ddbf55f9dea1900213f2a1a8500fabfd21c5a20f44dcfa957e4b0d8638c730f88751c77f678644f754f1a1dc73f4eb8b766c300deb45a9daad000e4247957819 + checksum: 84f40e12520b7023e52d289bf9d569a06284879fe23bbbacad86bec5d978b2669769f11b073fcfeb1567d8c547168323005fda88607a4681ecaeb4a5cdd48bb9 languageName: node linkType: hard -"@babel/helper-skip-transparent-expression-wrappers@npm:^7.20.0, @babel/helper-skip-transparent-expression-wrappers@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.24.7" +"@babel/helper-simple-access@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-simple-access@npm:7.25.9" dependencies: - "@babel/traverse": ^7.24.7 - "@babel/types": ^7.24.7 - checksum: 11b28fe534ce2b1a67c4d8e51a7b5711a2a0a0cae802f74614eee54cca58c744d9a62f6f60103c41759e81c537d270bfd665bf368a6bea214c6052f2094f8407 + "@babel/traverse": ^7.25.9 + "@babel/types": ^7.25.9 + checksum: 6d96c94b88e8288d15e5352c1221486bd4f62de8c7dc7c7b9f5b107ce2c79f67fec5ed71a0476e146f1fefbbbf1d69abe35dc821d80ce01fc7f472286c342421 languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-split-export-declaration@npm:7.24.7" +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.20.0, @babel/helper-skip-transparent-expression-wrappers@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.25.9" dependencies: - "@babel/types": ^7.24.7 - checksum: e3ddc91273e5da67c6953f4aa34154d005a00791dc7afa6f41894e768748540f6ebcac5d16e72541aea0c89bee4b89b4da6a3d65972a0ea8bfd2352eda5b7e22 + "@babel/traverse": ^7.25.9 + "@babel/types": ^7.25.9 + checksum: fdbb5248932198bc26daa6abf0d2ac42cab9c2dbb75b7e9f40d425c8f28f09620b886d40e7f9e4e08ffc7aaa2cefe6fc2c44be7c20e81f7526634702fb615bdc languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-string-parser@npm:7.24.7" - checksum: 09568193044a578743dd44bf7397940c27ea693f9812d24acb700890636b376847a611cdd0393a928544e79d7ad5b8b916bd8e6e772bc8a10c48a647a96e7b1a +"@babel/helper-string-parser@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-string-parser@npm:7.25.9" + checksum: 6435ee0849e101681c1849868278b5aee82686ba2c1e27280e5e8aca6233af6810d39f8e4e693d2f2a44a3728a6ccfd66f72d71826a94105b86b731697cdfa99 languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-validator-identifier@npm:7.24.7" - checksum: 6799ab117cefc0ecd35cd0b40ead320c621a298ecac88686a14cffceaac89d80cdb3c178f969861bf5fa5e4f766648f9161ea0752ecfe080d8e89e3147270257 +"@babel/helper-validator-identifier@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-identifier@npm:7.25.9" + checksum: 5b85918cb1a92a7f3f508ea02699e8d2422fe17ea8e82acd445006c0ef7520fbf48e3dbcdaf7b0a1d571fc3a2715a29719e5226636cb6042e15fe6ed2a590944 languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-validator-option@npm:7.24.7" - checksum: 9689166bf3f777dd424c026841c8cd651e41b21242dbfd4569a53086179a3e744c8eddd56e9d10b54142270141c91581b53af0d7c00c82d552d2540e2a919f7e +"@babel/helper-validator-option@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-validator-option@npm:7.25.9" + checksum: 9491b2755948ebbdd68f87da907283698e663b5af2d2b1b02a2765761974b1120d5d8d49e9175b167f16f72748ffceec8c9cf62acfbee73f4904507b246e2b3d languageName: node linkType: hard -"@babel/helper-wrap-function@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helper-wrap-function@npm:7.24.7" +"@babel/helper-wrap-function@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/helper-wrap-function@npm:7.25.9" dependencies: - "@babel/helper-function-name": ^7.24.7 - "@babel/template": ^7.24.7 - "@babel/traverse": ^7.24.7 - "@babel/types": ^7.24.7 - checksum: 085bf130ed08670336e3976f5841ae44e3e10001131632e22ef234659341978d2fd37e65785f59b6cb1745481347fc3bce84b33a685cacb0a297afbe1d2b03af + "@babel/template": ^7.25.9 + "@babel/traverse": ^7.25.9 + "@babel/types": ^7.25.9 + checksum: 8ec1701e60ae004415800c4a7a188f5564c73b4e4f3fdf58dd3f34a3feaa9753173f39bbd6d02e7ecc974f48155efc7940e62584435b3092c07728ee46a604ea languageName: node linkType: hard -"@babel/helpers@npm:^7.12.1, @babel/helpers@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/helpers@npm:7.24.7" +"@babel/helpers@npm:^7.12.1, @babel/helpers@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/helpers@npm:7.26.0" dependencies: - "@babel/template": ^7.24.7 - "@babel/types": ^7.24.7 - checksum: 934da58098a3670ca7f9f42425b9c44d0ca4f8fad815c0f51d89fc7b64c5e0b4c7d5fec038599de691229ada737edeaf72fad3eba8e16dd5842e8ea447f76b66 + "@babel/template": ^7.25.9 + "@babel/types": ^7.26.0 + checksum: d77fe8d45033d6007eadfa440355c1355eed57902d5a302f450827ad3d530343430a21210584d32eef2f216ae463d4591184c6fc60cf205bbf3a884561469200 languageName: node linkType: hard -"@babel/highlight@npm:^7.10.4, @babel/highlight@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/highlight@npm:7.24.7" +"@babel/highlight@npm:^7.10.4": + version: 7.25.9 + resolution: "@babel/highlight@npm:7.25.9" dependencies: - "@babel/helper-validator-identifier": ^7.24.7 + "@babel/helper-validator-identifier": ^7.25.9 chalk: ^2.4.2 js-tokens: ^4.0.0 picocolors: ^1.0.0 - checksum: 5cd3a89f143671c4ac129960024ba678b669e6fc673ce078030f5175002d1d3d52bc10b22c5b916a6faf644b5028e9a4bd2bb264d053d9b05b6a98690f1d46f1 + checksum: a6e0ac0a1c4bef7401915ca3442ab2b7ae4adf360262ca96b91396bfb9578abb28c316abf5e34460b780696db833b550238d9256bdaca60fade4ba7a67645064 languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.12.3, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.24.7, @babel/parser@npm:^7.7.0": - version: 7.24.7 - resolution: "@babel/parser@npm:7.24.7" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.12.3, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.2, @babel/parser@npm:^7.7.0": + version: 7.26.2 + resolution: "@babel/parser@npm:7.26.2" + dependencies: + "@babel/types": ^7.26.0 bin: parser: ./bin/babel-parser.js - checksum: fc9d2c4c8712f89672edc55c0dc5cf640dcec715b56480f111f85c2bc1d507e251596e4110d65796690a96ac37a4b60432af90b3e97bb47e69d4ef83872dbbd6 + checksum: c88b5ea0adf357ef909cdc2c31e284a154943edc59f63f6e8a4c20bf773a1b2f3d8c2205e59c09ca7cdad91e7466300114548876529277a80651b6436a48d5d9 languageName: node linkType: hard -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.24.7" +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.25.9" dependencies: - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/traverse": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0 - checksum: 68d315642b53af143aa17a71eb976cf431b51339aee584e29514a462b81c998636dd54219c2713b5f13e1df89eaf130dfab59683f9116825608708c81696b96c + checksum: b33d37dacf98a9c74f53959999adc37a258057668b62dba557e6865689433c53764673109eaba9102bf73b2ac4db162f0d9b89a6cca6f1b71d12f5908ec11da9 languageName: node linkType: hard -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.24.7" +"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0 - checksum: 7eb4e7ce5e3d6db4b0fdbdfaaa301c2e58f38a7ee39d5a4259a1fda61a612e83d3e4bc90fc36fb0345baf57e1e1a071e0caffeb80218623ad163f2fdc2e53a54 + checksum: d3e14ab1cb9cb50246d20cab9539f2fbd1e7ef1ded73980c8ad7c0561b4d5e0b144d362225f0976d47898e04cbd40f2000e208b0913bd788346cf7791b96af91 languageName: node linkType: hard -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.24.7" +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 - "@babel/plugin-transform-optional-chaining": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: a9d1ee3fd100d3eb6799a2f2bbd785296f356c531d75c9369f71541811fa324270258a374db103ce159156d006da2f33370330558d0133e6f7584152c34997ca + languageName: node + linkType: hard + +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.25.9" + dependencies: + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-skip-transparent-expression-wrappers": ^7.25.9 + "@babel/plugin-transform-optional-chaining": ^7.25.9 peerDependencies: "@babel/core": ^7.13.0 - checksum: 07b92878ac58a98ea1fdf6a8b4ec3413ba4fa66924e28b694d63ec5b84463123fbf4d7153b56cf3cedfef4a3482c082fe3243c04f8fb2c041b32b0e29b4a9e21 + checksum: 5b298b28e156f64de51cdb03a2c5b80c7f978815ef1026f3ae8b9fc48d28bf0a83817d8fbecb61ef8fb94a7201f62cca5103cc6e7b9e8f28e38f766d7905b378 languageName: node linkType: hard -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.24.7" +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.25.9" dependencies: - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/traverse": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0 - checksum: 8324d458db57060590942c7c2e9603880d07718ccb6450ec935105b8bd3c4393c4b8ada88e178c232258d91f33ffdcf2b1043d54e07a86989e50667ee100a32e + checksum: c684593952ab1b40dfa4e64e98a07e7227c6db175c21bd0e6d71d2ad5d240fef4e4a984d56f05a494876542a022244fe1c1098f4116109fd90d06615e8a269b1 languageName: node linkType: hard @@ -468,15 +441,15 @@ __metadata: linkType: hard "@babel/plugin-proposal-decorators@npm:^7.16.4": - version: 7.24.7 - resolution: "@babel/plugin-proposal-decorators@npm:7.24.7" + version: 7.25.9 + resolution: "@babel/plugin-proposal-decorators@npm:7.25.9" dependencies: - "@babel/helper-create-class-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-decorators": ^7.24.7 + "@babel/helper-create-class-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/plugin-syntax-decorators": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 75aa5ff5537d5ff77f0e52eb161a2f67c7d2bfd8f2000be710dedb1dd238b43ce53d2f734f84bda95b3f013b69de126403f84167f4eddb1d35e8f26257ee07c8 + checksum: ff598127818ac8e704009f1a9a207766ada5f84f6ca74e9de662cb6ce32bcb846c28fd52d6c5df9c55b4eac9a2a3492aa71fbd5cef0569a14b6f12003df22af2 languageName: node linkType: hard @@ -574,7 +547,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-class-properties@npm:^7.12.13, @babel/plugin-syntax-class-properties@npm:^7.8.3": +"@babel/plugin-syntax-class-properties@npm:^7.12.13": version: 7.12.13 resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" dependencies: @@ -596,73 +569,51 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-decorators@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-decorators@npm:7.24.7" - dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: dc303bcc1f5df61638f1eddc69dd55e65574bd43d8a4a098d3589f5a742e93a4ca3a173967b34eb95e4eaa994799b4c72bfed8688036e43c634be7f24db01ac5 - languageName: node - linkType: hard - -"@babel/plugin-syntax-dynamic-import@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-dynamic-import@npm:7.8.3" - dependencies: - "@babel/helper-plugin-utils": ^7.8.0 - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: ce307af83cf433d4ec42932329fad25fa73138ab39c7436882ea28742e1c0066626d224e0ad2988724c82644e41601cef607b36194f695cb78a1fcdc959637bd - languageName: node - linkType: hard - -"@babel/plugin-syntax-export-namespace-from@npm:^7.8.3": - version: 7.8.3 - resolution: "@babel/plugin-syntax-export-namespace-from@npm:7.8.3" +"@babel/plugin-syntax-decorators@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-syntax-decorators@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.8.3 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 85740478be5b0de185228e7814451d74ab8ce0a26fcca7613955262a26e99e8e15e9da58f60c754b84515d4c679b590dbd3f2148f0f58025f4ae706f1c5a5d4a + checksum: aaf58b17e6aa08f41f93897daa93c601a486233a0375b4231799fc5c4e7c98480aaad3c1c44cf391a62e428c5f6546f76488a1023a4036bb87cd61fa79f1173b languageName: node linkType: hard -"@babel/plugin-syntax-flow@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-flow@npm:7.24.7" +"@babel/plugin-syntax-flow@npm:^7.25.9": + version: 7.26.0 + resolution: "@babel/plugin-syntax-flow@npm:7.26.0" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 43b78b5fcdedb2a6d80c3d02a1a564fbfde86b73b442d616a8f318f673caa6ce0151513af5a00fcae42a512f144e70ef259d368b9537ee35d40336a6c895a7d4 + checksum: fdc0d0a7b512e00d933e12cf93c785ea4645a193f4b539230b7601cfaa8c704410199318ce9ea14e5fca7d13e9027822f7d81a7871d3e854df26b6af04cc3c6c languageName: node linkType: hard -"@babel/plugin-syntax-import-assertions@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-import-assertions@npm:7.24.7" +"@babel/plugin-syntax-import-assertions@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.26.0" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c4d67be4eb1d4637e361477dbe01f5b392b037d17c1f861cfa0faa120030e137aab90a9237931b8040fd31d1e5d159e11866fa1165f78beef7a3be876a391a17 + checksum: b58f2306df4a690ca90b763d832ec05202c50af787158ff8b50cdf3354359710bce2e1eb2b5135fcabf284756ac8eadf09ca74764aa7e76d12a5cac5f6b21e67 languageName: node linkType: hard -"@babel/plugin-syntax-import-attributes@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.24.7" +"@babel/plugin-syntax-import-attributes@npm:^7.24.7, @babel/plugin-syntax-import-attributes@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.26.0" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 590dbb5d1a15264f74670b427b8d18527672c3d6c91d7bae7e65f80fd810edbc83d90e68065088644cbad3f2457ed265a54a9956fb789fcb9a5b521822b3a275 + checksum: c122aa577166c80ee67f75aebebeef4150a132c4d3109d25d7fc058bf802946f883e330f20b78c1d3e3a5ada631c8780c263d2d01b5dbaecc69efefeedd42916 languageName: node linkType: hard -"@babel/plugin-syntax-import-meta@npm:^7.10.4, @babel/plugin-syntax-import-meta@npm:^7.8.3": +"@babel/plugin-syntax-import-meta@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-import-meta@npm:7.10.4" dependencies: @@ -684,18 +635,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-jsx@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-jsx@npm:7.24.7" +"@babel/plugin-syntax-jsx@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-syntax-jsx@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7a5ca629d8ca1e1ee78705a78e58c12920d07ed8006d7e7232b31296a384ff5e41d7b649bde5561196041037bbb9f9715be1d1c20975df87ca204f34ad15b965 + checksum: bb609d1ffb50b58f0c1bac8810d0e46a4f6c922aa171c458f3a19d66ee545d36e782d3bffbbc1fed0dc65a558bdce1caf5279316583c0fff5a2c1658982a8563 languageName: node linkType: hard -"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4, @babel/plugin-syntax-logical-assignment-operators@npm:^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-logical-assignment-operators@npm:7.10.4" dependencies: @@ -717,7 +668,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-numeric-separator@npm:^7.10.4, @babel/plugin-syntax-numeric-separator@npm:^7.8.3": +"@babel/plugin-syntax-numeric-separator@npm:^7.10.4": version: 7.10.4 resolution: "@babel/plugin-syntax-numeric-separator@npm:7.10.4" dependencies: @@ -772,7 +723,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-top-level-await@npm:^7.14.5, @babel/plugin-syntax-top-level-await@npm:^7.8.3": +"@babel/plugin-syntax-top-level-await@npm:^7.14.5": version: 7.14.5 resolution: "@babel/plugin-syntax-top-level-await@npm:7.14.5" dependencies: @@ -783,14 +734,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-typescript@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-syntax-typescript@npm:7.24.7" +"@babel/plugin-syntax-typescript@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-syntax-typescript@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 56fe84f3044ecbf038977281648db6b63bd1301f2fff6595820dc10ee276c1d1586919d48d52a8d497ecae32c958be38f42c1c8d174dc58aad856c516dc5b35a + checksum: 0e9821e8ba7d660c36c919654e4144a70546942ae184e85b8102f2322451eae102cbfadbcadd52ce077a2b44b400ee52394c616feab7b5b9f791b910e933fd33 languageName: node linkType: hard @@ -806,808 +757,807 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-arrow-functions@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-arrow-functions@npm:7.24.7" +"@babel/plugin-transform-arrow-functions@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 707c209b5331c7dc79bd326128c6a6640dbd62a78da1653c844db20c4f36bf7b68454f1bc4d2d051b3fde9136fa291f276ec03a071bb00ee653069ff82f91010 + checksum: c29f081224859483accf55fb4d091db2aac0dcd0d7954bac5ca889030cc498d3f771aa20eb2e9cd8310084ec394d85fa084b97faf09298b6bc9541182b3eb5bb languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.24.7" +"@babel/plugin-transform-async-generator-functions@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.25.9" dependencies: - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-remap-async-to-generator": ^7.24.7 - "@babel/plugin-syntax-async-generators": ^7.8.4 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-remap-async-to-generator": ^7.25.9 + "@babel/traverse": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 112e3b18f9c496ebc01209fc27f0b41a3669c479c7bc44f7249383172b432ebaae1e523caa7c6ecbd2d0d7adcb7e5769fe2798f8cb01c08cd57232d1bb6d8ad4 + checksum: 41e02c18c2a57de9f274fa2c5a1bf81a20ab5f321db29cc3051512b9c5bdf3f1a8c42f1fc282cb62343c6d50849f992eede954d5f7fb5e7df48ae0c59ea7e054 languageName: node linkType: hard -"@babel/plugin-transform-async-to-generator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-async-to-generator@npm:7.24.7" +"@babel/plugin-transform-async-to-generator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.25.9" dependencies: - "@babel/helper-module-imports": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-remap-async-to-generator": ^7.24.7 + "@babel/helper-module-imports": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-remap-async-to-generator": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 13704fb3b83effc868db2b71bfb2c77b895c56cb891954fc362e95e200afd523313b0e7cf04ce02f45b05e76017c5b5fa8070c92613727a35131bb542c253a36 + checksum: b3ad50fb93c171644d501864620ed23952a46648c4df10dc9c62cc9ad08031b66bd272cfdd708faeee07c23b6251b16f29ce0350473e4c79f0c32178d38ce3a6 languageName: node linkType: hard -"@babel/plugin-transform-block-scoped-functions@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.24.7" +"@babel/plugin-transform-block-scoped-functions@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 249cdcbff4e778b177245f9652b014ea4f3cd245d83297f10a7bf6d97790074089aa62bcde8c08eb299c5e68f2faed346b587d3ebac44d625ba9a83a4ee27028 + checksum: bf31896556b33a80f017af3d445ceb532ec0f5ca9d69bc211a963ac92514d172d5c24c5ac319f384d9dfa7f1a4d8dc23032c2fe3e74f98a59467ecd86f7033ae languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-block-scoping@npm:7.24.7" +"@babel/plugin-transform-block-scoping@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-block-scoping@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 039206155533600f079f3a455f85888dd7d4970ff7ffa85ef44760f4f5acb9f19c9d848cc1fec1b9bdbc0dfec9e8a080b90d0ab66ad2bdc7138b5ca4ba96e61c + checksum: e869500cfb1995e06e64c9608543b56468639809febfcdd6fcf683bc0bf1be2431cacf2981a168a1a14f4766393e37bc9f7c96d25bc5b5f39a64a8a8ad0bf8e0 languageName: node linkType: hard -"@babel/plugin-transform-class-properties@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-class-properties@npm:7.24.7" +"@babel/plugin-transform-class-properties@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-class-properties@npm:7.25.9" dependencies: - "@babel/helper-create-class-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-create-class-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 1348d7ce74da38ba52ea85b3b4289a6a86913748569ef92ef0cff30702a9eb849e5eaf59f1c6f3517059aa68115fb3067e389735dccacca39add4e2b0c67e291 + checksum: a8d69e2c285486b63f49193cbcf7a15e1d3a5f632c1c07d7a97f65306df7f554b30270b7378dde143f8b557d1f8f6336c643377943dec8ec405e4cd11e90b9ea languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-class-static-block@npm:7.24.7" +"@babel/plugin-transform-class-static-block@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/plugin-transform-class-static-block@npm:7.26.0" dependencies: - "@babel/helper-create-class-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-class-static-block": ^7.14.5 + "@babel/helper-create-class-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.12.0 - checksum: 324049263504f18416f1c3e24033baebfafd05480fdd885c8ebe6f2b415b0fc8e0b98d719360f9e30743cc78ac387fabc0b3c6606d2b54135756ffb92963b382 + checksum: d779d4d3a6f8d363f67fcbd928c15baa72be8d3b86c6d05e0300b50e66e2c4be9e99398b803d13064bc79d90ae36e37a505e3dc8af11904459804dec07660246 languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-classes@npm:7.24.7" +"@babel/plugin-transform-classes@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-classes@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": ^7.24.7 - "@babel/helper-compilation-targets": ^7.24.7 - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-function-name": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-replace-supers": ^7.24.7 - "@babel/helper-split-export-declaration": ^7.24.7 + "@babel/helper-annotate-as-pure": ^7.25.9 + "@babel/helper-compilation-targets": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-replace-supers": ^7.25.9 + "@babel/traverse": ^7.25.9 globals: ^11.1.0 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: f01cb31143730d425681e9816020cbb519c7ddb3b6ca308dfaf2821eda5699a746637fc6bf19811e2fb42cfdf8b00a21b31c754da83771a5c280077925677354 + checksum: d12584f72125314cc0fa8c77586ece2888d677788ac75f7393f5da574dfe4e45a556f7e3488fab29c8777ab3e5856d7a2d79f6df02834083aaa9d766440e3c68 languageName: node linkType: hard -"@babel/plugin-transform-computed-properties@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-computed-properties@npm:7.24.7" +"@babel/plugin-transform-computed-properties@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-computed-properties@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/template": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/template": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 0cf8c1b1e4ea57dec8d4612460d84fd4cdbf71a7499bb61ee34632cf89018a59eee818ffca88a8d99ee7057c20a4257044d7d463fda6daef9bf1db9fa81563cb + checksum: f77fa4bc0c1e0031068172df28852388db6b0f91c268d037905f459607cf1e8ebab00015f9f179f4ad96e11c5f381b635cd5dc4e147a48c7ac79d195ae7542de languageName: node linkType: hard -"@babel/plugin-transform-destructuring@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-destructuring@npm:7.24.7" +"@babel/plugin-transform-destructuring@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-destructuring@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: b9637b27faf9d24a8119bc5a1f98a2f47c69e6441bd8fc71163500be316253a72173308a93122bcf27d8d314ace43344c976f7291cf6376767f408350c8149d4 + checksum: 965f63077a904828f4adee91393f83644098533442b8217d5a135c23a759a4c252c714074c965676a60d2c33f610f579a4eeb59ffd783724393af61c0ca45fef languageName: node linkType: hard -"@babel/plugin-transform-dotall-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-dotall-regex@npm:7.24.7" +"@babel/plugin-transform-dotall-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.25.9" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-create-regexp-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 67b10fc6abb1f61f0e765288eb4c6d63d1d0f9fc0660e69f6f2170c56fa16bc74e49857afc644beda112b41771cd90cf52df0940d11e97e52617c77c7dcff171 + checksum: 8bdf1bb9e6e3a2cc8154ae88a3872faa6dc346d6901994505fb43ac85f858728781f1219f40b67f7bb0687c507450236cb7838ac68d457e65637f98500aa161b languageName: node linkType: hard -"@babel/plugin-transform-duplicate-keys@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-duplicate-keys@npm:7.24.7" +"@babel/plugin-transform-duplicate-keys@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d1da2ff85ecb56a63f4ccfd9dc9ae69400d85f0dadf44ecddd9e71c6e5c7a9178e74e3a9637555f415a2bb14551e563f09f98534ab54f53d25e8439fdde6ba2d + checksum: b553eebc328797ead6be5ba5bdaf2f1222cea8a5bd33fb4ed625975d4f9b510bfb0d688d97e314cd4b4a48b279bea7b3634ad68c1b41ee143c3082db0ae74037 languageName: node linkType: hard -"@babel/plugin-transform-dynamic-import@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-dynamic-import@npm:7.24.7" +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-dynamic-import": ^7.8.3 + "@babel/helper-create-regexp-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: f7233cf596be8c6843d31951afaf2464a62a610cb89c72c818c044765827fab78403ab8a7d3a6386f838c8df574668e2a48f6c206b1d7da965aff9c6886cb8e6 + languageName: node + linkType: hard + +"@babel/plugin-transform-dynamic-import@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.25.9" + dependencies: + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 776509ff62ab40c12be814a342fc56a5cc09b91fb63032b2633414b635875fd7da03734657be0f6db2891fe6e3033b75d5ddb6f2baabd1a02e4443754a785002 + checksum: aaca1ccda819be9b2b85af47ba08ddd2210ff2dbea222f26e4cd33f97ab020884bf81a66197e50872721e9daf36ceb5659502c82199884ea74d5d75ecda5c58b languageName: node linkType: hard -"@babel/plugin-transform-exponentiation-operator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.24.7" +"@babel/plugin-transform-exponentiation-operator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.25.9" dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-builder-binary-assignment-operator-visitor": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 23c84a23eb56589fdd35a3540f9a1190615be069110a2270865223c03aee3ba4e0fc68fe14850800cf36f0712b26e4964d3026235261f58f0405a29fe8dac9b1 + checksum: 57e1bb4135dd16782fe84b49dd360cce8f9bf5f62eb10424dcdaf221e54a8bacdf50f2541c5ac01dea9f833a6c628613d71be915290938a93454389cba4de06b languageName: node linkType: hard -"@babel/plugin-transform-export-namespace-from@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-export-namespace-from@npm:7.24.7" +"@babel/plugin-transform-export-namespace-from@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-export-namespace-from": ^7.8.3 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3bd3a10038f10ae0dea1ee42137f3edcf7036b5e9e570a0d1cbd0865f03658990c6c2d84fa2475f87a754e7dc5b46766c16f7ce5c9b32c3040150b6a21233a80 + checksum: 4dfe8df86c5b1d085d591290874bb2d78a9063090d71567ed657a418010ad333c3f48af2c974b865f53bbb718987a065f89828d43279a7751db1a56c9229078d languageName: node linkType: hard "@babel/plugin-transform-flow-strip-types@npm:^7.16.0": - version: 7.24.7 - resolution: "@babel/plugin-transform-flow-strip-types@npm:7.24.7" + version: 7.25.9 + resolution: "@babel/plugin-transform-flow-strip-types@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-flow": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/plugin-syntax-flow": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 260bd95b1a90ff4af11bf8e21e6dd35b1b7863daffb12a5b2018e2806fec033a7883114dc5f0b67d594ca93fe6f2c9894944c865dd2c51affb7da0f9a6473872 + checksum: 7f51cd5cc0c3a5ce2fe31c689458706ed40284a1c59b017167c3cbef953550a843450c5cfe6896b154fb645f141a930a4fd925f46b2215d0fcc66e7758202c38 languageName: node linkType: hard -"@babel/plugin-transform-for-of@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-for-of@npm:7.24.7" +"@babel/plugin-transform-for-of@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-for-of@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-skip-transparent-expression-wrappers": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a53b42dc93ab4b7d1ebd3c695b52be22b3d592f6a3dbdb3dc2fea2c8e0a7e1508fe919864c455cde552aec44ce7518625fccbb70c7063373ca228d884f4f49ea + checksum: 41b56e70256a29fc26ed7fb95ece062d7ec2f3b6ea8f0686349ffd004cd4816132085ee21165b89c502ee7161cb7cfb12510961638851357945dc7bc546475b7 languageName: node linkType: hard -"@babel/plugin-transform-function-name@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-function-name@npm:7.24.7" +"@babel/plugin-transform-function-name@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-function-name@npm:7.25.9" dependencies: - "@babel/helper-compilation-targets": ^7.24.7 - "@babel/helper-function-name": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-compilation-targets": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/traverse": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 8eb1a67894a124910b5a67630bed4307757504381f39f0fb5cf82afc7ae8647dbc03b256d13865b73a749b9071b68e9fb8a28cef2369917b4299ebb93fd66146 + checksum: a8d7c8d019a6eb57eab5ca1be3e3236f175557d55b1f3b11f8ad7999e3fbb1cf37905fd8cb3a349bffb4163a558e9f33b63f631597fdc97c858757deac1b2fd7 languageName: node linkType: hard -"@babel/plugin-transform-json-strings@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-json-strings@npm:7.24.7" +"@babel/plugin-transform-json-strings@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-json-strings@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-json-strings": ^7.8.3 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 88874d0b7a1ddea66c097fc0abb68801ffae194468aa44b828dde9a0e20ac5d8647943793de86092eabaa2911c96f67a6b373793d4bb9c932ef81b2711c06c2e + checksum: e2498d84761cfd05aaea53799933d55af309c9d6204e66b38778792d171e4d1311ad34f334259a3aa3407dd0446f6bd3e390a1fcb8ce2e42fe5aabed0e41bee1 languageName: node linkType: hard -"@babel/plugin-transform-literals@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-literals@npm:7.24.7" +"@babel/plugin-transform-literals@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-literals@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3c075cc093a3dd9e294b8b7d6656e65f889e7ca2179ca27978dcd65b4dc4885ebbfb327408d7d8f483c55547deed00ba840956196f3ac8a3c3d2308a330a8c23 + checksum: 3cca75823a38aab599bc151b0fa4d816b5e1b62d6e49c156aa90436deb6e13649f5505973151a10418b64f3f9d1c3da53e38a186402e0ed7ad98e482e70c0c14 languageName: node linkType: hard -"@babel/plugin-transform-logical-assignment-operators@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.24.7" +"@babel/plugin-transform-logical-assignment-operators@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3367ce0be243704dc6fce23e86a592c4380f01998ee5dd9f94c54b1ef7b971ac6f8a002901eb51599ac6cbdc0d067af8d1a720224fca1c40fde8bb8aab804aac + checksum: 8c6febb4ac53852314d28b5e2c23d5dbbff7bf1e57d61f9672e0d97531ef7778b3f0ad698dcf1179f5486e626c77127508916a65eb846a89e98a92f70ed3537b languageName: node linkType: hard -"@babel/plugin-transform-member-expression-literals@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-member-expression-literals@npm:7.24.7" +"@babel/plugin-transform-member-expression-literals@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 2720c57aa3bf70576146ba7d6ea03227f4611852122d76d237924f7b008dafc952e6ae61a19e5024f26c665f44384bbd378466f01b6bd1305b3564a3b7fb1a5d + checksum: db92041ae87b8f59f98b50359e0bb172480f6ba22e5e76b13bdfe07122cbf0daa9cd8ad2e78dcb47939938fed88ad57ab5989346f64b3a16953fc73dea3a9b1f languageName: node linkType: hard -"@babel/plugin-transform-modules-amd@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-modules-amd@npm:7.24.7" +"@babel/plugin-transform-modules-amd@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-modules-amd@npm:7.25.9" dependencies: - "@babel/helper-module-transforms": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-module-transforms": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: f1dd0fb2f46c0f8f21076b8c7ccd5b33a85ce6dcb31518ea4c648d9a5bb2474cd4bd87c9b1b752e68591e24b022e334ba0d07631fef2b6b4d8a4b85cf3d581f5 + checksum: baad1f6fd0e0d38e9a9c1086a06abdc014c4c653fd452337cadfe23fb5bd8bf4368d1bc433a5ac8e6421bc0732ebb7c044cf3fb39c1b7ebe967d66e26c4e5cec languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.7" +"@babel/plugin-transform-modules-commonjs@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.25.9" dependencies: - "@babel/helper-module-transforms": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-simple-access": ^7.24.7 + "@babel/helper-module-transforms": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-simple-access": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: bfda2a0297197ed342e2a02e5f9847a489a3ae40a4a7d7f00f4aeb8544a85e9006e0c5271c8f61f39bc97975ef2717b5594cf9486694377a53433162909d64c1 + checksum: 4f101f0ea4a57d1d27a7976d668c63a7d0bbb0d9c1909d8ac43c785fd1496c31e6552ffd9673730c088873df1bc64f1cc4aad7c3c90413ac5e80b33e336d80e4 languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.24.7" +"@babel/plugin-transform-modules-systemjs@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.25.9" dependencies: - "@babel/helper-hoist-variables": ^7.24.7 - "@babel/helper-module-transforms": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-validator-identifier": ^7.24.7 + "@babel/helper-module-transforms": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-validator-identifier": ^7.25.9 + "@babel/traverse": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 8af7a9db2929991d82cfdf41fb175dee344274d39b39122f8c35f24b5d682f98368e3d8f5130401298bd21412df21d416a7d8b33b59c334fae3d3c762118b1d8 + checksum: bf446202f372ba92dc0db32b24b56225b6e3ad3b227e31074de8b86fdec01c273ae2536873e38dbe3ceb1cd0894209343adeaa37df208e3fa88c0c7dffec7924 languageName: node linkType: hard -"@babel/plugin-transform-modules-umd@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-modules-umd@npm:7.24.7" +"@babel/plugin-transform-modules-umd@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-modules-umd@npm:7.25.9" dependencies: - "@babel/helper-module-transforms": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-module-transforms": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9ff1c464892efe042952ba778468bda6131b196a2729615bdcc3f24cdc94014f016a4616ee5643c5845bade6ba698f386833e61056d7201314b13a7fd69fac88 + checksum: 946db66be5f04ab9ee56c424b00257276ec094aa2f148508927e6085239f76b00304fa1e33026d29eccdbe312efea15ca3d92e74a12689d7f0cdd9a7ba1a6c54 languageName: node linkType: hard -"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.24.7" +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.25.9" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-create-regexp-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0 - checksum: f1c6c7b5d60a86b6d7e4dd098798e1d393d55e993a0b57a73b53640c7a94985b601a96bdacee063f809a9a700bcea3a2ff18e98fa561554484ac56b761d774bd + checksum: 434346ba05cf74e3f4704b3bdd439287b95cd2a8676afcdc607810b8c38b6f4798cd69c1419726b2e4c7204e62e4a04d31b0360e91ca57a930521c9211e07789 languageName: node linkType: hard -"@babel/plugin-transform-new-target@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-new-target@npm:7.24.7" +"@babel/plugin-transform-new-target@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-new-target@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3cb94cd1076b270f768f91fdcf9dd2f6d487f8dbfff3df7ca8d07b915900b86d02769a35ba1407d16fe49499012c8f055e1741299e2c880798b953d942a8fa1b + checksum: f8113539919aafce52f07b2bd182c771a476fe1d5d96d813460b33a16f173f038929369c595572cadc1f7bd8cb816ce89439d056e007770ddd7b7a0878e7895f languageName: node linkType: hard -"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.24.7" +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 4a9221356401d87762afbc37a9e8e764afc2daf09c421117537820f8cfbed6876888372ad3a7bcfae2d45c95f026651f050ab4020b777be31d3ffb00908dbdd3 + checksum: 26e03b1c2c0408cc300e46d8f8cb639653ff3a7b03456d0d8afbb53c44f33a89323f51d99991dade3a5676921119bbdf869728bb7911799b5ef99ffafa2cdd24 languageName: node linkType: hard -"@babel/plugin-transform-numeric-separator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-numeric-separator@npm:7.24.7" +"@babel/plugin-transform-numeric-separator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-numeric-separator": ^7.10.4 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 561b5f1d08b2c3f92ce849f092751558b5e6cfeb7eb55c79e7375c34dd9c3066dce5e630bb439affef6adcf202b6cbcaaa23870070276fa5bb429c8f5b8c7514 + checksum: 0528ef041ed88e8c3f51624ee87b8182a7f246fe4013f0572788e0727d20795b558f2b82e3989b5dd416cbd339500f0d88857de41b6d3b6fdacb1d5344bcc5b1 languageName: node linkType: hard "@babel/plugin-transform-object-assign@npm:^7.18.6": - version: 7.24.7 - resolution: "@babel/plugin-transform-object-assign@npm:7.24.7" + version: 7.25.9 + resolution: "@babel/plugin-transform-object-assign@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: e208760295511ba086131dd828903b2f1b12724a8bdbb6708b62534c17b3796d8ba4d38820d1b75a8861b3dbd8cccda7d17324c6796d42e2a4f33ae12dc68838 + checksum: d2664884b1e0ec7245adfb5b511f994304271cc3f0fa41a2e2f0e8a096151227c67595c65351ae7f2561928de5c3b9fe13b53ac2267597833ef32e3cb0e0f327 languageName: node linkType: hard -"@babel/plugin-transform-object-rest-spread@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.24.7" +"@babel/plugin-transform-object-rest-spread@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.25.9" dependencies: - "@babel/helper-compilation-targets": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-object-rest-spread": ^7.8.3 - "@babel/plugin-transform-parameters": ^7.24.7 + "@babel/helper-compilation-targets": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/plugin-transform-parameters": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 169d257b9800c13e1feb4c37fb05dae84f702e58b342bb76e19e82e6692b7b5337c9923ee89e3916a97c0dd04a3375bdeca14f5e126f110bbacbeb46d1886ca2 + checksum: a8ff73e1c46a03056b3a2236bafd6b3a4b83da93afe7ee24a50d0a8088150bf85bc5e5977daa04e66ff5fb7613d02d63ad49b91ebb64cf3f3022598d722e3a7a languageName: node linkType: hard -"@babel/plugin-transform-object-super@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-object-super@npm:7.24.7" +"@babel/plugin-transform-object-super@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-object-super@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-replace-supers": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-replace-supers": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: f71e607a830ee50a22fa1a2686524d3339440cf9dea63032f6efbd865cfe4e35000e1e3f3492459e5c986f7c0c07dc36938bf3ce61fc9ba5f8ab732d0b64ab37 + checksum: 1817b5d8b80e451ae1ad9080cca884f4f16df75880a158947df76a2ed8ab404d567a7dce71dd8051ef95f90fbe3513154086a32aba55cc76027f6cbabfbd7f98 languageName: node linkType: hard -"@babel/plugin-transform-optional-catch-binding@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.24.7" +"@babel/plugin-transform-optional-catch-binding@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7229f3a5a4facaab40f4fdfc7faabc157dc38a67d66bed7936599f4bc509e0bff636f847ac2aa45294881fce9cf8a0a460b85d2a465b7b977de9739fce9b18f6 + checksum: b46a8d1e91829f3db5c252583eb00d05a779b4660abeea5500fda0f8ffa3584fd18299443c22f7fddf0ed9dfdb73c782c43b445dc468d4f89803f2356963b406 languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.7" +"@babel/plugin-transform-optional-chaining@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 - "@babel/plugin-syntax-optional-chaining": ^7.8.3 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-skip-transparent-expression-wrappers": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 877e7ce9097d475132c7f4d1244de50bb2fd37993dc4580c735f18f8cbc49282f6e77752821bcad5ca9d3528412d2c8a7ee0aa7ca71bb680ff82648e7a5fed25 + checksum: f1642a7094456067e82b176e1e9fd426fda7ed9df54cb6d10109fc512b622bf4b3c83acc5875125732b8622565107fdbe2d60fe3ec8685e1d1c22c38c1b57782 languageName: node linkType: hard -"@babel/plugin-transform-parameters@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-parameters@npm:7.24.7" +"@babel/plugin-transform-parameters@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-parameters@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ab534b03ac2eff94bc79342b8f39a4584666f5305a6c63c1964afda0b1b004e6b861e49d1683548030defe248e3590d3ff6338ee0552cb90c064f7e1479968c3 + checksum: d7ba2a7d05edbc85aed741289b0ff3d6289a1c25d82ac4be32c565f88a66391f46631aad59ceeed40824037f7eeaa7a0de1998db491f50e65a565cd964f78786 languageName: node linkType: hard -"@babel/plugin-transform-private-methods@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-private-methods@npm:7.24.7" +"@babel/plugin-transform-private-methods@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-private-methods@npm:7.25.9" dependencies: - "@babel/helper-create-class-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-create-class-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c151548e34909be2adcceb224d8fdd70bafa393bc1559a600906f3f647317575bf40db670470934a360e90ee8084ef36dffa34ec25d387d414afd841e74cf3fe + checksum: 6e3671b352c267847c53a170a1937210fa8151764d70d25005e711ef9b21969aaf422acc14f9f7fb86bc0e4ec43e7aefcc0ad9196ae02d262ec10f509f126a58 languageName: node linkType: hard -"@babel/plugin-transform-private-property-in-object@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-private-property-in-object@npm:7.24.7" +"@babel/plugin-transform-private-property-in-object@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": ^7.24.7 - "@babel/helper-create-class-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + "@babel/helper-annotate-as-pure": ^7.25.9 + "@babel/helper-create-class-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 8cee9473095305cc787bb653fd681719b49363281feabf677db8a552e8e41c94441408055d7e5fd5c7d41b315e634fa70b145ad0c7c54456216049df4ed57350 + checksum: 9ce3e983fea9b9ba677c192aa065c0b42ebdc7774be4c02135df09029ad92a55c35b004650c75952cb64d650872ed18f13ab64422c6fc891d06333762caa8a0a languageName: node linkType: hard -"@babel/plugin-transform-property-literals@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-property-literals@npm:7.24.7" +"@babel/plugin-transform-property-literals@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-property-literals@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 9aeefc3aab6c6bf9d1fae1cf3a2d38c7d886fd3c6c81b7c608c477f5758aee2e7abf52f32724310fe861da61af934ee2508b78a5b5f234b9740c9134e1c14437 + checksum: 436046ab07d54a9b44a384eeffec701d4e959a37a7547dda72e069e751ca7ff753d1782a8339e354b97c78a868b49ea97bf41bf5a44c6d7a3c0a05ad40eeb49c languageName: node linkType: hard "@babel/plugin-transform-react-constant-elements@npm:^7.12.1": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-constant-elements@npm:7.24.7" + version: 7.25.9 + resolution: "@babel/plugin-transform-react-constant-elements@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 15a50645d5bd5139a65a57cc1ca8d731921bf4b3d453ed14150760a16891bdd8c0d6e870a85e3a580a00686415732fd74ff2c669a823e641a6124ac9489d8ed4 + checksum: ed59464c96cd4014f636852b4de398d2ffc22ffe3177a6c2a6058447a72839bb66a346a1db525ab60dcc5dd48ec59113a8325f785593689900358a15136e05c3 languageName: node linkType: hard -"@babel/plugin-transform-react-display-name@npm:^7.16.0, @babel/plugin-transform-react-display-name@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-display-name@npm:7.24.7" +"@babel/plugin-transform-react-display-name@npm:^7.16.0, @babel/plugin-transform-react-display-name@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-display-name@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: a05bf83bf5e7b31f7a3b56da1bf8e2eeec76ef52ae44435ceff66363a1717fcda45b7b4b931a2c115982175f481fc3f2d0fab23f0a43c44e6d983afc396858f0 + checksum: cd7020494e6f31c287834e8929e6a718d5b0ace21232fa30feb48622c2312045504c34b347dcff9e88145c349882b296a7d6b6cc3d3447d8c85502f16471747c languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-development@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-jsx-development@npm:7.24.7" +"@babel/plugin-transform-react-jsx-development@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx-development@npm:7.25.9" dependencies: - "@babel/plugin-transform-react-jsx": ^7.24.7 + "@babel/plugin-transform-react-jsx": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 653d32ea5accb12d016e324ec5a584b60a8f39e60c6a5101194b73553fdefbfa3c3f06ec2410216ec2033fddae181a2f146a1d6ed59f075c488fc4570cad2e7b + checksum: 537d38369537f1eb56041c4b770bc0733fde1801a7f5ffef40a1217ea448f33ee2fa8e6098a58a82fd00e432c1b9426a66849496da419020c9eca3b1b1a23779 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-self@npm:^7.24.5": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-jsx-self@npm:7.24.7" +"@babel/plugin-transform-react-jsx-self@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx-self@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 2d72c33664e614031b8a03fc2d4cfd185e99efb1d681cbde4b0b4ab379864b31d83ee923509892f6d94b2c5893c309f0217d33bcda3e470ed42297f958138381 + checksum: 41c833cd7f91b1432710f91b1325706e57979b2e8da44e83d86312c78bbe96cd9ef778b4e79e4e17ab25fa32c72b909f2be7f28e876779ede28e27506c41f4ae languageName: node linkType: hard -"@babel/plugin-transform-react-jsx-source@npm:^7.24.1": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-jsx-source@npm:7.24.7" +"@babel/plugin-transform-react-jsx-source@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx-source@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: c9afcb2259dd124a2de76f8a578589c18bd2f24dbcf78fe02b53c5cbc20c493c4618369604720e4e699b52be10ba0751b97140e1ef8bc8f0de0a935280e9d5b7 + checksum: a3e0e5672e344e9d01fb20b504fe29a84918eaa70cec512c4d4b1b035f72803261257343d8e93673365b72c371f35cf34bb0d129720bf178a4c87812c8b9c662 languageName: node linkType: hard -"@babel/plugin-transform-react-jsx@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-jsx@npm:7.24.7" +"@babel/plugin-transform-react-jsx@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-jsx@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": ^7.24.7 - "@babel/helper-module-imports": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-jsx": ^7.24.7 - "@babel/types": ^7.24.7 + "@babel/helper-annotate-as-pure": ^7.25.9 + "@babel/helper-module-imports": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/plugin-syntax-jsx": ^7.25.9 + "@babel/types": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ddfe494eb4b6ad567ebf0c029246df55d006512b1eb4beead73427b83af2e7e91b6d6e6954e275a92c81a5111d1e6e1fb4a62fdfc6f77c847cc7581650a7c452 + checksum: 5c6523c3963e3c6cf4c3cc2768a3766318af05b8f6c17aff52a4010e2c170e87b2fcdc94e9c9223ae12158664df4852ce81b9c8d042c15ea8fd83d6375f9f30f languageName: node linkType: hard -"@babel/plugin-transform-react-pure-annotations@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.24.7" +"@babel/plugin-transform-react-pure-annotations@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-annotate-as-pure": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: d859ada3cbeb829fa3d9978a29b2d36657fcc9dcc1e4c3c3af84ec5a044a8f8db26ada406baa309e5d4d512aca53d07c520d991b891ff943bec7d8f01aae0419 + checksum: 9995c0fc7c25d3aaaa0ce84233de02eab2564ea111d0813ec5baa538eb21520402879cc787ad1ad4c2061b99cebc3beb09910e64c9592e8ccb42ae62d9e4fd9a languageName: node linkType: hard -"@babel/plugin-transform-regenerator@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-regenerator@npm:7.24.7" +"@babel/plugin-transform-regenerator@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-regenerator@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 regenerator-transform: ^0.15.2 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 20c6c3fb6fc9f407829087316653388d311e8c1816b007609bb09aeef254092a7157adace8b3aaa8f34be752503717cb85c88a5fe482180a9b11bcbd676063be + checksum: 1c09e8087b476c5967282c9790fb8710e065eda77c60f6cb5da541edd59ded9d003d96f8ef640928faab4a0b35bf997673499a194973da4f0c97f0935807a482 + languageName: node + linkType: hard + +"@babel/plugin-transform-regexp-modifiers@npm:^7.26.0": + version: 7.26.0 + resolution: "@babel/plugin-transform-regexp-modifiers@npm:7.26.0" + dependencies: + "@babel/helper-create-regexp-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 726deca486bbd4b176f8a966eb0f4aabc19d9def3b8dabb8b3a656778eca0df1fda3f3c92b213aa5a184232fdafd5b7bd73b4e24ca4345c498ef6baff2bda4e1 languageName: node linkType: hard -"@babel/plugin-transform-reserved-words@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-reserved-words@npm:7.24.7" +"@babel/plugin-transform-reserved-words@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-reserved-words@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 3d5876954d5914d7270819479504f30c4bf5452a65c677f44e2dab2db50b3c9d4b47793c45dfad7abf4f377035dd79e4b3f554ae350df9f422201d370ce9f8dd + checksum: 8beda04481b25767acbd1f6b9ef7b3a9c12fbd9dcb24df45a6ad120e1dc4b247c073db60ac742f9093657d6d8c050501fc0606af042f81a3bb6a3ff862cddc47 languageName: node linkType: hard "@babel/plugin-transform-runtime@npm:^7.16.4": - version: 7.24.7 - resolution: "@babel/plugin-transform-runtime@npm:7.24.7" + version: 7.25.9 + resolution: "@babel/plugin-transform-runtime@npm:7.25.9" dependencies: - "@babel/helper-module-imports": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-module-imports": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 babel-plugin-polyfill-corejs2: ^0.4.10 - babel-plugin-polyfill-corejs3: ^0.10.1 + babel-plugin-polyfill-corejs3: ^0.10.6 babel-plugin-polyfill-regenerator: ^0.6.1 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 98bcbbdc833d5c451189a6325f88820fe92973e119c59ce74bf28681cf4687c8280decb55b6c47f22e98c3973ae3a13521c4f51855a2b8577b230ecb1b4ca5b4 + checksum: db7f20a7a7324dbfe3b43a09f0095c69dadcf8b08567fa7c7fa6e245d97c66cdcdc330e97733b7589261c0e1046bc5cc36741b932ac5dd7757374495b57e7b02 languageName: node linkType: hard -"@babel/plugin-transform-shorthand-properties@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-shorthand-properties@npm:7.24.7" +"@babel/plugin-transform-shorthand-properties@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 7b524245814607188212b8eb86d8c850e5974203328455a30881b4a92c364b93353fae14bc2af5b614ef16300b75b8c1d3b8f3a08355985b4794a7feb240adc3 + checksum: f774995d58d4e3a992b732cf3a9b8823552d471040e280264dd15e0735433d51b468fef04d75853d061309389c66bda10ce1b298297ce83999220eb0ad62741d languageName: node linkType: hard -"@babel/plugin-transform-spread@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-spread@npm:7.24.7" +"@babel/plugin-transform-spread@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-spread@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-skip-transparent-expression-wrappers": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-skip-transparent-expression-wrappers": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 4c4254c8b9cceb1a8f975fa9b92257ddb08380a35c0a3721b8f4b9e13a3d82e403af2e0fba577b9f2452dd8f06bc3dea71cc53b1e2c6af595af5db52a13429d6 + checksum: 2403a5d49171b7714d5e5ecb1f598c61575a4dbe5e33e5a5f08c0ea990b75e693ca1ea983b6a96b2e3e5e7da48c8238333f525e47498c53b577c5d094d964c06 languageName: node linkType: hard -"@babel/plugin-transform-sticky-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-sticky-regex@npm:7.24.7" +"@babel/plugin-transform-sticky-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 118fc7a7ebf7c20411b670c8a030535fdfe4a88bc5643bb625a584dbc4c8a468da46430a20e6bf78914246962b0f18f1b9d6a62561a7762c4f34a038a5a77179 + checksum: 7454b00844dbe924030dd15e2b3615b36e196500c4c47e98dabc6b37a054c5b1038ecd437e910aabf0e43bf56b973cb148d3437d50f6e2332d8309568e3e979b languageName: node linkType: hard -"@babel/plugin-transform-template-literals@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-template-literals@npm:7.24.7" +"@babel/plugin-transform-template-literals@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-template-literals@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: ad44e5826f5a98c1575832dbdbd033adfe683cdff195e178528ead62507564bf02f479b282976cfd3caebad8b06d5fd7349c1cdb880dec3c56daea4f1f179619 + checksum: 92eb1d6e2d95bd24abbb74fa7640d02b66ff6214e0bb616d7fda298a7821ce15132a4265d576a3502a347a3c9e94b6c69ed265bb0784664592fa076785a3d16a languageName: node linkType: hard -"@babel/plugin-transform-typeof-symbol@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-typeof-symbol@npm:7.24.7" +"@babel/plugin-transform-typeof-symbol@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 6bd16b9347614d44187d8f8ee23ebd7be30dabf3632eed5ff0415f35a482e827de220527089eae9cdfb75e85aa72db0e141ebc2247c4b1187c1abcdacdc34895 + checksum: 3f9458840d96f61502f0e9dfaae3efe8325fa0b2151e24ea0d41307f28cdd166905419f5a43447ce0f1ae4bfd001f3906b658839a60269c254168164090b4c73 languageName: node linkType: hard -"@babel/plugin-transform-typescript@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-typescript@npm:7.24.7" +"@babel/plugin-transform-typescript@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-typescript@npm:7.25.9" dependencies: - "@babel/helper-annotate-as-pure": ^7.24.7 - "@babel/helper-create-class-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/plugin-syntax-typescript": ^7.24.7 + "@babel/helper-annotate-as-pure": ^7.25.9 + "@babel/helper-create-class-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-skip-transparent-expression-wrappers": ^7.25.9 + "@babel/plugin-syntax-typescript": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 6b367d1e3d6bdbe438878a76436fc6903e2b4fd7c31fa036d43865570d282679ec3f7c0306399851f2866a9b36686a0ea8c343df3750f70d427f1fe20ca54310 + checksum: 6dd1303f1b9f314e22c6c54568a8b9709a081ce97be757d4004f960e3e73d6b819e6b49cee6cf1fc8455511e41127a8b580fa34602de62d17ab8a0b2d0ccf183 languageName: node linkType: hard -"@babel/plugin-transform-unicode-escapes@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-unicode-escapes@npm:7.24.7" +"@babel/plugin-transform-unicode-escapes@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.25.9" dependencies: - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 4af0a193e1ddea6ff82b2b15cc2501b872728050bd625740b813c8062fec917d32d530ff6b41de56c15e7296becdf3336a58db81f5ca8e7c445c1306c52f3e01 + checksum: be067e07488d804e3e82d7771f23666539d2ae5af03bf6eb8480406adf3dabd776e60c1fd5c6078dc5714b73cd80bbaca70e71d4f5d154c5c57200581602ca2f languageName: node linkType: hard -"@babel/plugin-transform-unicode-property-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.24.7" +"@babel/plugin-transform-unicode-property-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.25.9" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-create-regexp-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: aae13350c50973f5802ca7906d022a6a0cc0e3aebac9122d0450bbd51e78252d4c2032ad69385e2759fcbdd3aac5d571bd7e26258907f51f8e1a51b53be626c2 + checksum: 201f6f46c1beb399e79aa208b94c5d54412047511795ce1e790edcd189cef73752e6a099fdfc01b3ad12205f139ae344143b62f21f44bbe02338a95e8506a911 languageName: node linkType: hard -"@babel/plugin-transform-unicode-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-unicode-regex@npm:7.24.7" +"@babel/plugin-transform-unicode-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.25.9" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-create-regexp-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 1cb4e70678906e431da0a05ac3f8350025fee290304ad7482d9cfaa1ca67b2e898654de537c9268efbdad5b80d3ebadf42b4a88ea84609bd8a4cce7b11b48afd + checksum: e8baae867526e179467c6ef5280d70390fa7388f8763a19a27c21302dd59b121032568be080749514b097097ceb9af716bf4b90638f1b3cf689aa837ba20150f languageName: node linkType: hard -"@babel/plugin-transform-unicode-sets-regex@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.24.7" +"@babel/plugin-transform-unicode-sets-regex@npm:^7.25.9": + version: 7.25.9 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.25.9" dependencies: - "@babel/helper-create-regexp-features-plugin": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 + "@babel/helper-create-regexp-features-plugin": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0 - checksum: 08a2844914f33dacd2ce1ab021ce8c1cc35dc6568521a746d8bf29c21571ee5be78787b454231c4bb3526cbbe280f1893223c82726cec5df2be5dae0a3b51837 + checksum: 4445ef20de687cb4dcc95169742a8d9013d680aa5eee9186d8e25875bbfa7ee5e2de26a91177ccf70b1db518e36886abcd44750d28db5d7a9539f0efa6839f4b languageName: node linkType: hard "@babel/preset-env@npm:^7.12.1, @babel/preset-env@npm:^7.16.4, @babel/preset-env@npm:^7.8.4": - version: 7.24.7 - resolution: "@babel/preset-env@npm:7.24.7" - dependencies: - "@babel/compat-data": ^7.24.7 - "@babel/helper-compilation-targets": ^7.24.7 - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-validator-option": ^7.24.7 - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ^7.24.7 - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.24.7 - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.24.7 - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.24.7 + version: 7.26.0 + resolution: "@babel/preset-env@npm:7.26.0" + dependencies: + "@babel/compat-data": ^7.26.0 + "@babel/helper-compilation-targets": ^7.25.9 + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-validator-option": ^7.25.9 + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ^7.25.9 + "@babel/plugin-bugfix-safari-class-field-initializer-scope": ^7.25.9 + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ^7.25.9 + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ^7.25.9 + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ^7.25.9 "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2 - "@babel/plugin-syntax-async-generators": ^7.8.4 - "@babel/plugin-syntax-class-properties": ^7.12.13 - "@babel/plugin-syntax-class-static-block": ^7.14.5 - "@babel/plugin-syntax-dynamic-import": ^7.8.3 - "@babel/plugin-syntax-export-namespace-from": ^7.8.3 - "@babel/plugin-syntax-import-assertions": ^7.24.7 - "@babel/plugin-syntax-import-attributes": ^7.24.7 - "@babel/plugin-syntax-import-meta": ^7.10.4 - "@babel/plugin-syntax-json-strings": ^7.8.3 - "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 - "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 - "@babel/plugin-syntax-numeric-separator": ^7.10.4 - "@babel/plugin-syntax-object-rest-spread": ^7.8.3 - "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 - "@babel/plugin-syntax-optional-chaining": ^7.8.3 - "@babel/plugin-syntax-private-property-in-object": ^7.14.5 - "@babel/plugin-syntax-top-level-await": ^7.14.5 + "@babel/plugin-syntax-import-assertions": ^7.26.0 + "@babel/plugin-syntax-import-attributes": ^7.26.0 "@babel/plugin-syntax-unicode-sets-regex": ^7.18.6 - "@babel/plugin-transform-arrow-functions": ^7.24.7 - "@babel/plugin-transform-async-generator-functions": ^7.24.7 - "@babel/plugin-transform-async-to-generator": ^7.24.7 - "@babel/plugin-transform-block-scoped-functions": ^7.24.7 - "@babel/plugin-transform-block-scoping": ^7.24.7 - "@babel/plugin-transform-class-properties": ^7.24.7 - "@babel/plugin-transform-class-static-block": ^7.24.7 - "@babel/plugin-transform-classes": ^7.24.7 - "@babel/plugin-transform-computed-properties": ^7.24.7 - "@babel/plugin-transform-destructuring": ^7.24.7 - "@babel/plugin-transform-dotall-regex": ^7.24.7 - "@babel/plugin-transform-duplicate-keys": ^7.24.7 - "@babel/plugin-transform-dynamic-import": ^7.24.7 - "@babel/plugin-transform-exponentiation-operator": ^7.24.7 - "@babel/plugin-transform-export-namespace-from": ^7.24.7 - "@babel/plugin-transform-for-of": ^7.24.7 - "@babel/plugin-transform-function-name": ^7.24.7 - "@babel/plugin-transform-json-strings": ^7.24.7 - "@babel/plugin-transform-literals": ^7.24.7 - "@babel/plugin-transform-logical-assignment-operators": ^7.24.7 - "@babel/plugin-transform-member-expression-literals": ^7.24.7 - "@babel/plugin-transform-modules-amd": ^7.24.7 - "@babel/plugin-transform-modules-commonjs": ^7.24.7 - "@babel/plugin-transform-modules-systemjs": ^7.24.7 - "@babel/plugin-transform-modules-umd": ^7.24.7 - "@babel/plugin-transform-named-capturing-groups-regex": ^7.24.7 - "@babel/plugin-transform-new-target": ^7.24.7 - "@babel/plugin-transform-nullish-coalescing-operator": ^7.24.7 - "@babel/plugin-transform-numeric-separator": ^7.24.7 - "@babel/plugin-transform-object-rest-spread": ^7.24.7 - "@babel/plugin-transform-object-super": ^7.24.7 - "@babel/plugin-transform-optional-catch-binding": ^7.24.7 - "@babel/plugin-transform-optional-chaining": ^7.24.7 - "@babel/plugin-transform-parameters": ^7.24.7 - "@babel/plugin-transform-private-methods": ^7.24.7 - "@babel/plugin-transform-private-property-in-object": ^7.24.7 - "@babel/plugin-transform-property-literals": ^7.24.7 - "@babel/plugin-transform-regenerator": ^7.24.7 - "@babel/plugin-transform-reserved-words": ^7.24.7 - "@babel/plugin-transform-shorthand-properties": ^7.24.7 - "@babel/plugin-transform-spread": ^7.24.7 - "@babel/plugin-transform-sticky-regex": ^7.24.7 - "@babel/plugin-transform-template-literals": ^7.24.7 - "@babel/plugin-transform-typeof-symbol": ^7.24.7 - "@babel/plugin-transform-unicode-escapes": ^7.24.7 - "@babel/plugin-transform-unicode-property-regex": ^7.24.7 - "@babel/plugin-transform-unicode-regex": ^7.24.7 - "@babel/plugin-transform-unicode-sets-regex": ^7.24.7 + "@babel/plugin-transform-arrow-functions": ^7.25.9 + "@babel/plugin-transform-async-generator-functions": ^7.25.9 + "@babel/plugin-transform-async-to-generator": ^7.25.9 + "@babel/plugin-transform-block-scoped-functions": ^7.25.9 + "@babel/plugin-transform-block-scoping": ^7.25.9 + "@babel/plugin-transform-class-properties": ^7.25.9 + "@babel/plugin-transform-class-static-block": ^7.26.0 + "@babel/plugin-transform-classes": ^7.25.9 + "@babel/plugin-transform-computed-properties": ^7.25.9 + "@babel/plugin-transform-destructuring": ^7.25.9 + "@babel/plugin-transform-dotall-regex": ^7.25.9 + "@babel/plugin-transform-duplicate-keys": ^7.25.9 + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": ^7.25.9 + "@babel/plugin-transform-dynamic-import": ^7.25.9 + "@babel/plugin-transform-exponentiation-operator": ^7.25.9 + "@babel/plugin-transform-export-namespace-from": ^7.25.9 + "@babel/plugin-transform-for-of": ^7.25.9 + "@babel/plugin-transform-function-name": ^7.25.9 + "@babel/plugin-transform-json-strings": ^7.25.9 + "@babel/plugin-transform-literals": ^7.25.9 + "@babel/plugin-transform-logical-assignment-operators": ^7.25.9 + "@babel/plugin-transform-member-expression-literals": ^7.25.9 + "@babel/plugin-transform-modules-amd": ^7.25.9 + "@babel/plugin-transform-modules-commonjs": ^7.25.9 + "@babel/plugin-transform-modules-systemjs": ^7.25.9 + "@babel/plugin-transform-modules-umd": ^7.25.9 + "@babel/plugin-transform-named-capturing-groups-regex": ^7.25.9 + "@babel/plugin-transform-new-target": ^7.25.9 + "@babel/plugin-transform-nullish-coalescing-operator": ^7.25.9 + "@babel/plugin-transform-numeric-separator": ^7.25.9 + "@babel/plugin-transform-object-rest-spread": ^7.25.9 + "@babel/plugin-transform-object-super": ^7.25.9 + "@babel/plugin-transform-optional-catch-binding": ^7.25.9 + "@babel/plugin-transform-optional-chaining": ^7.25.9 + "@babel/plugin-transform-parameters": ^7.25.9 + "@babel/plugin-transform-private-methods": ^7.25.9 + "@babel/plugin-transform-private-property-in-object": ^7.25.9 + "@babel/plugin-transform-property-literals": ^7.25.9 + "@babel/plugin-transform-regenerator": ^7.25.9 + "@babel/plugin-transform-regexp-modifiers": ^7.26.0 + "@babel/plugin-transform-reserved-words": ^7.25.9 + "@babel/plugin-transform-shorthand-properties": ^7.25.9 + "@babel/plugin-transform-spread": ^7.25.9 + "@babel/plugin-transform-sticky-regex": ^7.25.9 + "@babel/plugin-transform-template-literals": ^7.25.9 + "@babel/plugin-transform-typeof-symbol": ^7.25.9 + "@babel/plugin-transform-unicode-escapes": ^7.25.9 + "@babel/plugin-transform-unicode-property-regex": ^7.25.9 + "@babel/plugin-transform-unicode-regex": ^7.25.9 + "@babel/plugin-transform-unicode-sets-regex": ^7.25.9 "@babel/preset-modules": 0.1.6-no-external-plugins babel-plugin-polyfill-corejs2: ^0.4.10 - babel-plugin-polyfill-corejs3: ^0.10.4 + babel-plugin-polyfill-corejs3: ^0.10.6 babel-plugin-polyfill-regenerator: ^0.6.1 - core-js-compat: ^3.31.0 + core-js-compat: ^3.38.1 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 1a82c883c7404359b19b7436d0aab05f8dd4e89e8b1f7de127cc65d0ff6a9b1c345211d9c038f5b6e8f93d26f091fa9c73812d82851026ab4ec93f5ed0f0d675 + checksum: 0c3e2b3758cc0347dcf5551b5209db702764183dce66ff20bffceff6486c090bef9175f5f7d1e68cfe5584f0d817b2aab25ab5992058a7998f061f244c8caf5f languageName: node linkType: hard @@ -1625,99 +1575,88 @@ __metadata: linkType: hard "@babel/preset-react@npm:^7.12.5, @babel/preset-react@npm:^7.16.0, @babel/preset-react@npm:^7.18.6": - version: 7.24.7 - resolution: "@babel/preset-react@npm:7.24.7" - dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-validator-option": ^7.24.7 - "@babel/plugin-transform-react-display-name": ^7.24.7 - "@babel/plugin-transform-react-jsx": ^7.24.7 - "@babel/plugin-transform-react-jsx-development": ^7.24.7 - "@babel/plugin-transform-react-pure-annotations": ^7.24.7 + version: 7.25.9 + resolution: "@babel/preset-react@npm:7.25.9" + dependencies: + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-validator-option": ^7.25.9 + "@babel/plugin-transform-react-display-name": ^7.25.9 + "@babel/plugin-transform-react-jsx": ^7.25.9 + "@babel/plugin-transform-react-jsx-development": ^7.25.9 + "@babel/plugin-transform-react-pure-annotations": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 76d0365b6bca808be65c4ccb3f3384c0792084add15eb537f16b3e44184216b82fa37f945339b732ceee6f06e09ba1f39f75c45e69b9811ddcc479f05555ea9c + checksum: b5650c07a744ab4024c04fae002c9043235b4ad8687de8bf759135b9c6186553f4f53fde0a4583ce4c019560b79c176f39c745cdf77645af07071d26d8ba84ce languageName: node linkType: hard "@babel/preset-typescript@npm:^7.16.0, @babel/preset-typescript@npm:^7.18.6": - version: 7.24.7 - resolution: "@babel/preset-typescript@npm:7.24.7" - dependencies: - "@babel/helper-plugin-utils": ^7.24.7 - "@babel/helper-validator-option": ^7.24.7 - "@babel/plugin-syntax-jsx": ^7.24.7 - "@babel/plugin-transform-modules-commonjs": ^7.24.7 - "@babel/plugin-transform-typescript": ^7.24.7 + version: 7.26.0 + resolution: "@babel/preset-typescript@npm:7.26.0" + dependencies: + "@babel/helper-plugin-utils": ^7.25.9 + "@babel/helper-validator-option": ^7.25.9 + "@babel/plugin-syntax-jsx": ^7.25.9 + "@babel/plugin-transform-modules-commonjs": ^7.25.9 + "@babel/plugin-transform-typescript": ^7.25.9 peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 12929b24757f3bd6548103475f86478eda4c872bc7cefd920b29591eee8f4a4f350561d888e133d632d0c9402b8615fdcec9138e5127a6567dcb22f804ff207f - languageName: node - linkType: hard - -"@babel/regjsgen@npm:^0.8.0": - version: 0.8.0 - resolution: "@babel/regjsgen@npm:0.8.0" - checksum: 89c338fee774770e5a487382170711014d49a68eb281e74f2b5eac88f38300a4ad545516a7786a8dd5702e9cf009c94c2f582d200f077ac5decd74c56b973730 + checksum: 6d8641fa6efd0e10eec5e8f92cd164b916a06d57131cfa5216c281404289c87d2b4995140a1c1d9c3bad171ff6ef2226be5f0585e09577ffff349706e991ec71 languageName: node linkType: hard "@babel/runtime-corejs3@npm:^7.10.2": - version: 7.24.7 - resolution: "@babel/runtime-corejs3@npm:7.24.7" + version: 7.26.0 + resolution: "@babel/runtime-corejs3@npm:7.26.0" dependencies: core-js-pure: ^3.30.2 regenerator-runtime: ^0.14.0 - checksum: fb5cae960a2d4cbcb2144059dfa9dbe5530d027fa210a5bc37c67c3014226c32390f221320066124872f3d6c4830af17a19da09c10ab114da9b6fa8ab4377cea + checksum: c6c5adac03e33aa4b5bb636a677aa2a6e400b91d91aac5674448d20af4100b80a8bedfb742338e4236e22c092d3edeb27210efdf48bd13ec353bd899f097ff41 languageName: node linkType: hard -"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.9, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.8, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.1, @babel/runtime@npm:^7.24.6, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.24.7 - resolution: "@babel/runtime@npm:7.24.7" +"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.15.4, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.9, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.8, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.1, @babel/runtime@npm:^7.24.6, @babel/runtime@npm:^7.26.0, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": + version: 7.26.0 + resolution: "@babel/runtime@npm:7.26.0" dependencies: regenerator-runtime: ^0.14.0 - checksum: d17f29eed6f848ac15cdf4202a910b741facfb0419a9d79e5c7fa37df6362fc3227f1cc2e248cc6db5e53ddffb4caa6686c488e6e80ce3d29c36a4e74c8734ea + checksum: c8e2c0504ab271b3467a261a8f119bf2603eb857a0d71e37791f4e3fae00f681365073cc79f141ddaa90c6077c60ba56448004ad5429d07ac73532be9f7cf28a languageName: node linkType: hard -"@babel/template@npm:^7.10.4, @babel/template@npm:^7.24.7, @babel/template@npm:^7.3.3": - version: 7.24.7 - resolution: "@babel/template@npm:7.24.7" +"@babel/template@npm:^7.10.4, @babel/template@npm:^7.25.9, @babel/template@npm:^7.3.3": + version: 7.25.9 + resolution: "@babel/template@npm:7.25.9" dependencies: - "@babel/code-frame": ^7.24.7 - "@babel/parser": ^7.24.7 - "@babel/types": ^7.24.7 - checksum: ea90792fae708ddf1632e54c25fe1a86643d8c0132311f81265d2bdbdd42f9f4fac65457056c1b6ca87f7aa0d6a795b549566774bba064bdcea2034ab3960ee9 + "@babel/code-frame": ^7.25.9 + "@babel/parser": ^7.25.9 + "@babel/types": ^7.25.9 + checksum: 103641fea19c7f4e82dc913aa6b6ac157112a96d7c724d513288f538b84bae04fb87b1f1e495ac1736367b1bc30e10f058b30208fb25f66038e1f1eb4e426472 languageName: node linkType: hard -"@babel/traverse@npm:^7.1.0, @babel/traverse@npm:^7.12.1, @babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.7.0": - version: 7.24.7 - resolution: "@babel/traverse@npm:7.24.7" +"@babel/traverse@npm:^7.1.0, @babel/traverse@npm:^7.12.1, @babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.7.0": + version: 7.25.9 + resolution: "@babel/traverse@npm:7.25.9" dependencies: - "@babel/code-frame": ^7.24.7 - "@babel/generator": ^7.24.7 - "@babel/helper-environment-visitor": ^7.24.7 - "@babel/helper-function-name": ^7.24.7 - "@babel/helper-hoist-variables": ^7.24.7 - "@babel/helper-split-export-declaration": ^7.24.7 - "@babel/parser": ^7.24.7 - "@babel/types": ^7.24.7 + "@babel/code-frame": ^7.25.9 + "@babel/generator": ^7.25.9 + "@babel/parser": ^7.25.9 + "@babel/template": ^7.25.9 + "@babel/types": ^7.25.9 debug: ^4.3.1 globals: ^11.1.0 - checksum: 7cd366afe9e7ee77e493779fdf24f67bf5595247289364f4689e29688572505eaeb886d7a8f20ebb9c29fc2de7d0895e4ff9e203e78e39ac67239724d45aa83b + checksum: 901d325662ff1dd9bc51de00862e01055fa6bc374f5297d7e3731f2f0e268bbb1d2141f53fa82860aa308ee44afdcf186a948f16c83153927925804b95a9594d languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.12.1, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.7.0, @babel/types@npm:^7.8.3": - version: 7.24.7 - resolution: "@babel/types@npm:7.24.7" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.12.1, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.7.0": + version: 7.26.0 + resolution: "@babel/types@npm:7.26.0" dependencies: - "@babel/helper-string-parser": ^7.24.7 - "@babel/helper-validator-identifier": ^7.24.7 - to-fast-properties: ^2.0.0 - checksum: 3e4437fced97e02982972ce5bebd318c47d42c9be2152c0fd28c6f786cc74086cc0a8fb83b602b846e41df37f22c36254338eada1a47ef9d8a1ec92332ca3ea8 + "@babel/helper-string-parser": ^7.25.9 + "@babel/helper-validator-identifier": ^7.25.9 + checksum: a3dd37dabac693018872da96edb8c1843a605c1bfacde6c3f504fba79b972426a6f24df70aa646356c0c1b19bdd2c722c623c684a996c002381071680602280d languageName: node linkType: hard @@ -1763,149 +1702,149 @@ __metadata: languageName: node linkType: hard -"@emotion/babel-plugin@npm:^11.11.0": - version: 11.11.0 - resolution: "@emotion/babel-plugin@npm:11.11.0" +"@emotion/babel-plugin@npm:^11.13.5": + version: 11.13.5 + resolution: "@emotion/babel-plugin@npm:11.13.5" dependencies: "@babel/helper-module-imports": ^7.16.7 "@babel/runtime": ^7.18.3 - "@emotion/hash": ^0.9.1 - "@emotion/memoize": ^0.8.1 - "@emotion/serialize": ^1.1.2 + "@emotion/hash": ^0.9.2 + "@emotion/memoize": ^0.9.0 + "@emotion/serialize": ^1.3.3 babel-plugin-macros: ^3.1.0 convert-source-map: ^1.5.0 escape-string-regexp: ^4.0.0 find-root: ^1.1.0 source-map: ^0.5.7 stylis: 4.2.0 - checksum: 6b363edccc10290f7a23242c06f88e451b5feb2ab94152b18bb8883033db5934fb0e421e2d67d09907c13837c21218a3ac28c51707778a54d6cd3706c0c2f3f9 + checksum: c41df7e6c19520e76d1939f884be878bf88b5ba00bd3de9d05c5b6c5baa5051686ab124d7317a0645de1b017b574d8139ae1d6390ec267fbe8e85a5252afb542 languageName: node linkType: hard -"@emotion/cache@npm:^11.11.0": - version: 11.11.0 - resolution: "@emotion/cache@npm:11.11.0" +"@emotion/cache@npm:^11.11.0, @emotion/cache@npm:^11.13.5": + version: 11.13.5 + resolution: "@emotion/cache@npm:11.13.5" dependencies: - "@emotion/memoize": ^0.8.1 - "@emotion/sheet": ^1.2.2 - "@emotion/utils": ^1.2.1 - "@emotion/weak-memoize": ^0.3.1 + "@emotion/memoize": ^0.9.0 + "@emotion/sheet": ^1.4.0 + "@emotion/utils": ^1.4.2 + "@emotion/weak-memoize": ^0.4.0 stylis: 4.2.0 - checksum: 8eb1dc22beaa20c21a2e04c284d5a2630a018a9d51fb190e52de348c8d27f4e8ca4bbab003d68b4f6cd9cc1c569ca747a997797e0f76d6c734a660dc29decf08 + checksum: d4429bcac07730dd65707b8203f855be3d1958183e05d265eeefbeab19822e70c87250fad9abaeaea575d844256d1b8fee348211ef905f7715234df0ee088188 languageName: node linkType: hard -"@emotion/hash@npm:^0.9.1": - version: 0.9.1 - resolution: "@emotion/hash@npm:0.9.1" - checksum: 716e17e48bf9047bf9383982c071de49f2615310fb4e986738931776f5a823bc1f29c84501abe0d3df91a3803c80122d24e28b57351bca9e01356ebb33d89876 +"@emotion/hash@npm:^0.9.2": + version: 0.9.2 + resolution: "@emotion/hash@npm:0.9.2" + checksum: 379bde2830ccb0328c2617ec009642321c0e009a46aa383dfbe75b679c6aea977ca698c832d225a893901f29d7b3eef0e38cf341f560f6b2b56f1ff23c172387 languageName: node linkType: hard -"@emotion/is-prop-valid@npm:^1.2.2": - version: 1.2.2 - resolution: "@emotion/is-prop-valid@npm:1.2.2" +"@emotion/is-prop-valid@npm:^1.3.0": + version: 1.3.1 + resolution: "@emotion/is-prop-valid@npm:1.3.1" dependencies: - "@emotion/memoize": ^0.8.1 - checksum: 61f6b128ea62b9f76b47955057d5d86fcbe2a6989d2cd1e583daac592901a950475a37d049b9f7a7c6aa8758a33b408735db759fdedfd1f629df0f85ab60ea25 + "@emotion/memoize": ^0.9.0 + checksum: fe6549d54f389e1a17cb02d832af7ee85fb6ea126fc18d02ca47216e8ff19332c1983f4a0ba68602cfcd3b325ffd4ebf0b2d0c6270f1e7e6fe3fca4ba7741e1a languageName: node linkType: hard -"@emotion/memoize@npm:^0.8.1": - version: 0.8.1 - resolution: "@emotion/memoize@npm:0.8.1" - checksum: a19cc01a29fcc97514948eaab4dc34d8272e934466ed87c07f157887406bc318000c69ae6f813a9001c6a225364df04249842a50e692ef7a9873335fbcc141b0 +"@emotion/memoize@npm:^0.9.0": + version: 0.9.0 + resolution: "@emotion/memoize@npm:0.9.0" + checksum: 038132359397348e378c593a773b1148cd0cf0a2285ffd067a0f63447b945f5278860d9de718f906a74c7c940ba1783ac2ca18f1c06a307b01cc0e3944e783b1 languageName: node linkType: hard "@emotion/react@npm:^11.10.4": - version: 11.11.4 - resolution: "@emotion/react@npm:11.11.4" + version: 11.13.5 + resolution: "@emotion/react@npm:11.13.5" dependencies: "@babel/runtime": ^7.18.3 - "@emotion/babel-plugin": ^11.11.0 - "@emotion/cache": ^11.11.0 - "@emotion/serialize": ^1.1.3 - "@emotion/use-insertion-effect-with-fallbacks": ^1.0.1 - "@emotion/utils": ^1.2.1 - "@emotion/weak-memoize": ^0.3.1 + "@emotion/babel-plugin": ^11.13.5 + "@emotion/cache": ^11.13.5 + "@emotion/serialize": ^1.3.3 + "@emotion/use-insertion-effect-with-fallbacks": ^1.1.0 + "@emotion/utils": ^1.4.2 + "@emotion/weak-memoize": ^0.4.0 hoist-non-react-statics: ^3.3.1 peerDependencies: react: ">=16.8.0" peerDependenciesMeta: "@types/react": optional: true - checksum: 6abaa7a05c5e1db31bffca7ac79169f5456990022cbb3794e6903221536609a60420f2b4888dd3f84e9634a304e394130cb88dc32c243a1dedc263e50da329f8 + checksum: 25c6572bdb1472d622a41817881628eb311deafe507bbb1be95c6a4c2c23a19bdd011c368d5794c5a17a1fdf2b5db327480a4c0b85d9322078d531289c163225 languageName: node linkType: hard -"@emotion/serialize@npm:^1.1.2, @emotion/serialize@npm:^1.1.3, @emotion/serialize@npm:^1.1.4": - version: 1.1.4 - resolution: "@emotion/serialize@npm:1.1.4" +"@emotion/serialize@npm:^1.3.3": + version: 1.3.3 + resolution: "@emotion/serialize@npm:1.3.3" dependencies: - "@emotion/hash": ^0.9.1 - "@emotion/memoize": ^0.8.1 - "@emotion/unitless": ^0.8.1 - "@emotion/utils": ^1.2.1 + "@emotion/hash": ^0.9.2 + "@emotion/memoize": ^0.9.0 + "@emotion/unitless": ^0.10.0 + "@emotion/utils": ^1.4.2 csstype: ^3.0.2 - checksum: 71b99f816a9c1d61a87c62cf4928da3894bb62213f3aff38b1ea9790b3368f084af98a3e5453b5055c2f36a7d70318d2fa9955b7b5676c2065b868062375df39 + checksum: 510331233767ae4e09e925287ca2c7269b320fa1d737ea86db5b3c861a734483ea832394c0c1fe5b21468fe335624a75e72818831d303ba38125f54f44ba02e7 languageName: node linkType: hard -"@emotion/sheet@npm:^1.2.2": - version: 1.2.2 - resolution: "@emotion/sheet@npm:1.2.2" - checksum: d973273c9c15f1c291ca2269728bf044bd3e92a67bca87943fa9ec6c3cd2b034f9a6bfe95ef1b5d983351d128c75b547b43ff196a00a3875f7e1d269793cecfe +"@emotion/sheet@npm:^1.4.0": + version: 1.4.0 + resolution: "@emotion/sheet@npm:1.4.0" + checksum: eeb1212e3289db8e083e72e7e401cd6d1a84deece87e9ce184f7b96b9b5dbd6f070a89057255a6ff14d9865c3ce31f27c39248a053e4cdd875540359042586b4 languageName: node linkType: hard "@emotion/styled@npm:^11.10.4": - version: 11.11.5 - resolution: "@emotion/styled@npm:11.11.5" + version: 11.13.5 + resolution: "@emotion/styled@npm:11.13.5" dependencies: "@babel/runtime": ^7.18.3 - "@emotion/babel-plugin": ^11.11.0 - "@emotion/is-prop-valid": ^1.2.2 - "@emotion/serialize": ^1.1.4 - "@emotion/use-insertion-effect-with-fallbacks": ^1.0.1 - "@emotion/utils": ^1.2.1 + "@emotion/babel-plugin": ^11.13.5 + "@emotion/is-prop-valid": ^1.3.0 + "@emotion/serialize": ^1.3.3 + "@emotion/use-insertion-effect-with-fallbacks": ^1.1.0 + "@emotion/utils": ^1.4.2 peerDependencies: "@emotion/react": ^11.0.0-rc.0 react: ">=16.8.0" peerDependenciesMeta: "@types/react": optional: true - checksum: ad5fc42d00e8aa9597f6d9665986036d5ebe0e8f8155af6d95831c5e8fb2319fb837724e6c5cd59e5346f14c3263711b7ce7271d34688e974d1f32ffeecb37ba + checksum: 316b3e9f98fc9d3faa54a990ad7f3805611c76a4ebffac9a6c28b6e7e9dd6e9343e9b80c79617af7f64524081a606f3789a89373abf67362fa138028f91b62af languageName: node linkType: hard -"@emotion/unitless@npm:^0.8.1": - version: 0.8.1 - resolution: "@emotion/unitless@npm:0.8.1" - checksum: 385e21d184d27853bb350999471f00e1429fa4e83182f46cd2c164985999d9b46d558dc8b9cc89975cb337831ce50c31ac2f33b15502e85c299892e67e7b4a88 +"@emotion/unitless@npm:^0.10.0": + version: 0.10.0 + resolution: "@emotion/unitless@npm:0.10.0" + checksum: d79346df31a933e6d33518e92636afeb603ce043f3857d0a39a2ac78a09ef0be8bedff40130930cb25df1beeee12d96ee38613963886fa377c681a89970b787c languageName: node linkType: hard -"@emotion/use-insertion-effect-with-fallbacks@npm:^1.0.1": - version: 1.0.1 - resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.0.1" +"@emotion/use-insertion-effect-with-fallbacks@npm:^1.1.0": + version: 1.1.0 + resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.1.0" peerDependencies: react: ">=16.8.0" - checksum: 700b6e5bbb37a9231f203bb3af11295eed01d73b2293abece0bc2a2237015e944d7b5114d4887ad9a79776504aa51ed2a8b0ddbc117c54495dd01a6b22f93786 + checksum: 63665191773b27de66807c53b90091ef0d10d5161381f62726cfceecfe1d8c944f18594b8021805fc81575b64246fd5ab9c75d60efabec92f940c1c410530949 languageName: node linkType: hard -"@emotion/utils@npm:^1.2.1": - version: 1.2.1 - resolution: "@emotion/utils@npm:1.2.1" - checksum: e0b44be0705b56b079c55faff93952150be69e79b660ae70ddd5b6e09fc40eb1319654315a9f34bb479d7f4ec94be6068c061abbb9e18b9778ae180ad5d97c73 +"@emotion/utils@npm:^1.4.2": + version: 1.4.2 + resolution: "@emotion/utils@npm:1.4.2" + checksum: 04cf76849c6401205c058b82689fd0ec5bf501aed6974880fe9681a1d61543efb97e848f4c38664ac4a9068c7ad2d1cb84f73bde6cf95f1208aa3c28e0190321 languageName: node linkType: hard -"@emotion/weak-memoize@npm:^0.3.1": - version: 0.3.1 - resolution: "@emotion/weak-memoize@npm:0.3.1" - checksum: b2be47caa24a8122622ea18cd2d650dbb4f8ad37b636dc41ed420c2e082f7f1e564ecdea68122b546df7f305b159bf5ab9ffee872abd0f052e687428459af594 +"@emotion/weak-memoize@npm:^0.4.0": + version: 0.4.0 + resolution: "@emotion/weak-memoize@npm:0.4.0" + checksum: db5da0e89bd752c78b6bd65a1e56231f0abebe2f71c0bd8fc47dff96408f7065b02e214080f99924f6a3bfe7ee15afc48dad999d76df86b39b16e513f7a94f52 languageName: node linkType: hard @@ -2071,20 +2010,20 @@ __metadata: linkType: hard "@eslint-community/eslint-utils@npm:^4.2.0": - version: 4.4.0 - resolution: "@eslint-community/eslint-utils@npm:4.4.0" + version: 4.4.1 + resolution: "@eslint-community/eslint-utils@npm:4.4.1" dependencies: - eslint-visitor-keys: ^3.3.0 + eslint-visitor-keys: ^3.4.3 peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: cdfe3ae42b4f572cbfb46d20edafe6f36fc5fb52bf2d90875c58aefe226892b9677fef60820e2832caf864a326fe4fc225714c46e8389ccca04d5f9288aabd22 + checksum: a7ffc838eb6a9ef594cda348458ccf38f34439ac77dc090fa1c120024bcd4eb911dfd74d5ef44d42063e7949fa7c5123ce714a015c4abb917d4124be1bd32bfe languageName: node linkType: hard "@eslint-community/regexpp@npm:^4.4.0": - version: 4.10.1 - resolution: "@eslint-community/regexpp@npm:4.10.1" - checksum: 1e04bc366fb8152c9266258cd25e3fded102f1d212a9476928e3cb98c48be645df6d676728d1c596053992fb9134879fe0de23c9460035b342cceb22d3af1776 + version: 4.12.1 + resolution: "@eslint-community/regexpp@npm:4.12.1" + checksum: 0d628680e204bc316d545b4993d3658427ca404ae646ce541fcc65306b8c712c340e5e573e30fb9f85f4855c0c5f6dca9868931f2fcced06417fbe1a0c6cd2d6 languageName: node linkType: hard @@ -2105,41 +2044,41 @@ __metadata: languageName: node linkType: hard -"@floating-ui/core@npm:^1.0.0": - version: 1.6.2 - resolution: "@floating-ui/core@npm:1.6.2" +"@floating-ui/core@npm:^1.6.0": + version: 1.6.8 + resolution: "@floating-ui/core@npm:1.6.8" dependencies: - "@floating-ui/utils": ^0.2.0 - checksum: a161b2c8e14b6e185960ec19398f4b893ef3cd6620d535c348c1dc877fb4ffc9f701eb7156f6a30a89b7826093ba28ea223fc2fd1996c0b2464741208725ac8f + "@floating-ui/utils": ^0.2.8 + checksum: 82faa6ea9d57e466779324e51308d6d49c098fb9d184a08d9bb7f4fad83f08cc070fc491f8d56f0cad44a16215fb43f9f829524288413e6c33afcb17303698de languageName: node linkType: hard "@floating-ui/dom@npm:^1.0.0": - version: 1.6.5 - resolution: "@floating-ui/dom@npm:1.6.5" + version: 1.6.12 + resolution: "@floating-ui/dom@npm:1.6.12" dependencies: - "@floating-ui/core": ^1.0.0 - "@floating-ui/utils": ^0.2.0 - checksum: 767295173cfc9024b2187b65d3c1a0c8d8596a1f827d57c86288e52edf91b41508b3679643e24e0ef9f522d86aab59ef97354b456b39be4f6f5159d819cc807d + "@floating-ui/core": ^1.6.0 + "@floating-ui/utils": ^0.2.8 + checksum: 956514ed100c0c853e73ace9e3c877b7e535444d7c31326f687a7690d49cb1e59ef457e9c93b76141aea0d280e83ed5a983bb852718b62eea581f755454660f6 languageName: node linkType: hard "@floating-ui/react-dom@npm:^2.0.8": - version: 2.1.0 - resolution: "@floating-ui/react-dom@npm:2.1.0" + version: 2.1.2 + resolution: "@floating-ui/react-dom@npm:2.1.2" dependencies: "@floating-ui/dom": ^1.0.0 peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 371ab3b14627026c637f4a2b8ca3dbfb7f67f1d51e74af5448b8e5bc76b8ccf30fed5e66d855f1ac1a6de28d79acc6dffcbcca4744a327a5e8d47f3515b0b52a + checksum: 25bb031686e23062ed4222a8946e76b3f9021d40a48437bd747233c4964a766204b8a55f34fa8b259839af96e60db7c6e3714d81f1de06914294f90e86ffbc48 languageName: node linkType: hard -"@floating-ui/utils@npm:^0.2.0": - version: 0.2.2 - resolution: "@floating-ui/utils@npm:0.2.2" - checksum: 3d8d46fd1b071c98e10d374e2dcf54d1eb9de0aa75ed2b994c9132ebf6f783f896f979053be71450bdb6d60021120cfc24d25a5c84ebb3db0994080e13d9762f +"@floating-ui/utils@npm:^0.2.8": + version: 0.2.8 + resolution: "@floating-ui/utils@npm:0.2.8" + checksum: deb98bba017c4e073c7ad5740d4dec33a4d3e0942d412e677ac0504f3dade15a68fc6fd164d43c93c0bb0bcc5dc5015c1f4080dfb1a6161140fe660624f7c875 languageName: node linkType: hard @@ -2565,10 +2504,10 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15": - version: 1.4.15 - resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" - checksum: b881c7e503db3fc7f3c1f35a1dd2655a188cc51a3612d76efc8a6eb74728bef5606e6758ee77423e564092b4a518aba569bbb21c9bac5ab7a35b0c6ae7e344c8 +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.5.0": + version: 1.5.0 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" + checksum: 05df4f2538b3b0f998ea4c1cd34574d0feba216fa5d4ccaef0187d12abf82eafe6021cec8b49f9bb4d90f2ba4582ccc581e72986a5fcf4176ae0cfeb04cf52ec languageName: node linkType: hard @@ -2618,28 +2557,6 @@ __metadata: languageName: node linkType: hard -"@mui/base@npm:5.0.0-beta.40": - version: 5.0.0-beta.40 - resolution: "@mui/base@npm:5.0.0-beta.40" - dependencies: - "@babel/runtime": ^7.23.9 - "@floating-ui/react-dom": ^2.0.8 - "@mui/types": ^7.2.14 - "@mui/utils": ^5.15.14 - "@popperjs/core": ^2.11.8 - clsx: ^2.1.0 - prop-types: ^15.8.1 - peerDependencies: - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 9c084ee67de372411a71af5eca9a5367db9f5bce57bb43973629c522760fe64fa2a43d2934dccd24d6dcbcd0ed399c5fc5c461226c86104f5767de1c9b8deba2 - languageName: node - linkType: hard - "@mui/base@npm:^5.0.0-beta.22": version: 5.0.0-dev.20240529-082515-213b5e33ab resolution: "@mui/base@npm:5.0.0-dev.20240529-082515-213b5e33ab" @@ -2662,51 +2579,51 @@ __metadata: languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.15.19": - version: 5.15.19 - resolution: "@mui/core-downloads-tracker@npm:5.15.19" - checksum: 32dd442d72a4cf4abea0e5c0a325707c3f8aba16b7b40ed674da2c068ed10d686f1941240e527407d685e00ed12931c331d99265e1ed570630c856ffbe291c23 +"@mui/core-downloads-tracker@npm:^5.16.8": + version: 5.16.8 + resolution: "@mui/core-downloads-tracker@npm:5.16.8" + checksum: 1d099442aabf0a17ae0045d370565fca9c8654a654f88a08595542e6566d159aa632cc7d73aefa247f2ae3ab853709ea2e37118a080891bfbd200c58212202ca languageName: node linkType: hard "@mui/icons-material@npm:^5.10.3": - version: 5.15.19 - resolution: "@mui/icons-material@npm:5.15.19" + version: 5.16.8 + resolution: "@mui/icons-material@npm:5.16.8" dependencies: "@babel/runtime": ^7.23.9 peerDependencies: "@mui/material": ^5.0.0 - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 + "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 365d9e93bef6cd19b7c8862ee926e2afd96c815df0c777670cca6e9c348f1fc0178ad0e060684c34f6953bb8a1a5f87648ff0a129ec23a9664964dbe0a8d2026 + checksum: 072c7221ede6adb7c8c9024421906185b23a0d3acf48409e0bcfe7bcef9c439d1449fb73d0fbc605a85056e296d9efdb7bddb95846f105a8511ed9ddbfad1280 languageName: node linkType: hard "@mui/material@npm:^5.10.3": - version: 5.15.19 - resolution: "@mui/material@npm:5.15.19" + version: 5.16.8 + resolution: "@mui/material@npm:5.16.8" dependencies: "@babel/runtime": ^7.23.9 - "@mui/base": 5.0.0-beta.40 - "@mui/core-downloads-tracker": ^5.15.19 - "@mui/system": ^5.15.15 - "@mui/types": ^7.2.14 - "@mui/utils": ^5.15.14 + "@mui/core-downloads-tracker": ^5.16.8 + "@mui/system": ^5.16.8 + "@mui/types": ^7.2.15 + "@mui/utils": ^5.16.8 + "@popperjs/core": ^2.11.8 "@types/react-transition-group": ^4.4.10 clsx: ^2.1.0 csstype: ^3.1.3 prop-types: ^15.8.1 - react-is: ^18.2.0 + react-is: ^18.3.1 react-transition-group: ^4.4.5 peerDependencies: "@emotion/react": ^11.5.0 "@emotion/styled": ^11.3.0 - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 + "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@emotion/react": optional: true @@ -2714,30 +2631,30 @@ __metadata: optional: true "@types/react": optional: true - checksum: 001095973c5d8581c97b05bca888d9aae51876684c9bcf7e1841635287c225ac9af94ca13a8baaa410f60b16b1ebb3003efa85a008d7338e23c12272cbf29ecb + checksum: 37aa0bba0d64feb46b6c7ef71ed44010c0799c5ebb57b345cf364e43be748a5229abfe3f4b573de225369b9cac13b35f6d32ad9e3015ad152645296f52096584 languageName: node linkType: hard -"@mui/private-theming@npm:^5.15.14": - version: 5.15.14 - resolution: "@mui/private-theming@npm:5.15.14" +"@mui/private-theming@npm:^5.16.8": + version: 5.16.8 + resolution: "@mui/private-theming@npm:5.16.8" dependencies: "@babel/runtime": ^7.23.9 - "@mui/utils": ^5.15.14 + "@mui/utils": ^5.16.8 prop-types: ^15.8.1 peerDependencies: - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 + "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 1b1ef54e8281c9b13fcc58f4c39682efc610946a68402283c19fcfbce8a7d7a231d61b536d6df9bf7a59a1426591bd403a453a59eb8efb9689437fb58554dc8c + checksum: 576cf19188c236482a8a698978d3061c7e8d76ba9d891d323ce96d92d6b80d88e1aa2a67fe4698d76b8a43221ef0f8ed21be74971fc684ce1279dc73fd34316b languageName: node linkType: hard -"@mui/styled-engine@npm:^5.15.14": - version: 5.15.14 - resolution: "@mui/styled-engine@npm:5.15.14" +"@mui/styled-engine@npm:^5.16.8": + version: 5.16.8 + resolution: "@mui/styled-engine@npm:5.16.8" dependencies: "@babel/runtime": ^7.23.9 "@emotion/cache": ^11.11.0 @@ -2746,33 +2663,33 @@ __metadata: peerDependencies: "@emotion/react": ^11.4.1 "@emotion/styled": ^11.3.0 - react: ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@emotion/react": optional: true "@emotion/styled": optional: true - checksum: 23b45c859a4f0d2b10933d06a6082c0ff093f7b6d8d32a2bfe3a6e515fe46d7a38ca9e7150d45c025a2e98d963bae9a5991d131cf4748b62670075ef0fa321ed + checksum: 8eab246e985bbe2707af4620a3193166bacefb029df65ac846cfc0ac5d7996fcb72c50327241f60913538f58a2ad9aa6de3ef12b72eb7750c71f8d3c284a420b languageName: node linkType: hard -"@mui/system@npm:^5.10.16, @mui/system@npm:^5.15.15": - version: 5.15.15 - resolution: "@mui/system@npm:5.15.15" +"@mui/system@npm:^5.10.16, @mui/system@npm:^5.16.8": + version: 5.16.8 + resolution: "@mui/system@npm:5.16.8" dependencies: "@babel/runtime": ^7.23.9 - "@mui/private-theming": ^5.15.14 - "@mui/styled-engine": ^5.15.14 - "@mui/types": ^7.2.14 - "@mui/utils": ^5.15.14 + "@mui/private-theming": ^5.16.8 + "@mui/styled-engine": ^5.16.8 + "@mui/types": ^7.2.15 + "@mui/utils": ^5.16.8 clsx: ^2.1.0 csstype: ^3.1.3 prop-types: ^15.8.1 peerDependencies: "@emotion/react": ^11.5.0 "@emotion/styled": ^11.3.0 - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 + "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@emotion/react": optional: true @@ -2780,55 +2697,59 @@ __metadata: optional: true "@types/react": optional: true - checksum: 9ca96d5f66b2a9d6471909cc98c671eea5ec0a6d58a7ec071073b9e5200b95c3f017f0ca5cc946abc7f83074bd11830ca18f5e30bc98e25cd6ca217bd1b3a26f + checksum: 8082b176009fa907cdb0391db59db6cd3589659ad92497caec998c01e1683978ab2eda4ece4d12e523d233b062aa5946d4a438d9a22bf172f0568be1db773e9c languageName: node linkType: hard -"@mui/types@npm:^7.2.14, @mui/types@npm:^7.2.14-dev.20240529-082515-213b5e33ab": - version: 7.2.14 - resolution: "@mui/types@npm:7.2.14" +"@mui/types@npm:^7.2.14-dev.20240529-082515-213b5e33ab, @mui/types@npm:^7.2.15, @mui/types@npm:^7.2.19": + version: 7.2.19 + resolution: "@mui/types@npm:7.2.19" peerDependencies: - "@types/react": ^17.0.0 || ^18.0.0 + "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 615c9f9110933157f5d3c4fee69d6e70b98fc0d9ebc3b63079b6a1e23e6b389748687a25ab4ac15b56166fc228885da87c3929503b41fa322cfdee0f6d411206 + checksum: c3b5723e6f0861d47df834c57878f19347aefecdaf948cf9a25a64b73fbc75791430693d0f540b2bdc01bdfc605dc32bf4ba738113ec415aa9eaf002ce38f064 languageName: node linkType: hard -"@mui/utils@npm:^5.10.3, @mui/utils@npm:^5.14.16, @mui/utils@npm:^5.15.14": - version: 5.15.14 - resolution: "@mui/utils@npm:5.15.14" +"@mui/utils@npm:^5.10.3, @mui/utils@npm:^5.14.16, @mui/utils@npm:^5.16.8": + version: 5.16.8 + resolution: "@mui/utils@npm:5.16.8" dependencies: "@babel/runtime": ^7.23.9 - "@types/prop-types": ^15.7.11 + "@mui/types": ^7.2.15 + "@types/prop-types": ^15.7.12 + clsx: ^2.1.1 prop-types: ^15.8.1 - react-is: ^18.2.0 + react-is: ^18.3.1 peerDependencies: - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 + "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 36543ba7e3b65fb3219ed27e8f1455aff15b47a74c9b642c63e60774e22baa6492a196079e72bcfa5a570421dab32160398f892110bd444428bcf8b266b11893 + checksum: ed714c6aa583bdf17af9f523c9b9ba3789a47677aa6408bc2afd842fa9eaa6d111361c1309435d481ea03b8c695e22ead98c43dc13239c63a3da481c95e5ad72 languageName: node linkType: hard "@mui/utils@npm:^6.0.0-dev.20240529-082515-213b5e33ab": - version: 6.0.0-dev.20240529-082515-213b5e33ab - resolution: "@mui/utils@npm:6.0.0-dev.20240529-082515-213b5e33ab" + version: 6.1.9 + resolution: "@mui/utils@npm:6.1.9" dependencies: - "@babel/runtime": ^7.24.6 - "@types/prop-types": ^15.7.12 + "@babel/runtime": ^7.26.0 + "@mui/types": ^7.2.19 + "@types/prop-types": ^15.7.13 + clsx: ^2.1.1 prop-types: ^15.8.1 - react-is: ^18.2.0 + react-is: ^18.3.1 peerDependencies: - "@types/react": ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 + "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 6869a031b5f725933e3f028c6efc7890a42601ec7b8498edc396fd9a93d8eeff8726b696ceaada1b89aa55a00a00d6371ebb5d144a3926e5429356edc806c8e0 + checksum: a2c61c0537b312ab0faeb3f13e7f3b0736e11f29e7907ccd77b0643afc0dca3a0dceb3817371666f35ca8df723ddeac9b2bbb6b759206bde99e03514cfd4ebb9 languageName: node linkType: hard @@ -2851,8 +2772,8 @@ __metadata: linkType: hard "@mui/x-date-pickers@npm:^6.19.4": - version: 6.20.1 - resolution: "@mui/x-date-pickers@npm:6.20.1" + version: 6.20.2 + resolution: "@mui/x-date-pickers@npm:6.20.2" dependencies: "@babel/runtime": ^7.23.2 "@mui/base": ^5.0.0-beta.22 @@ -2894,7 +2815,7 @@ __metadata: optional: true moment-jalaali: optional: true - checksum: bffd715cd2e5d6449627aa25fa58563deb632abce771f137b2bfa66a3806e82c0da63acfea8986bbf22112d0600dcd5268c99dcbf002960c21bad3c276fd5b2b + checksum: 0447b911ea0d78d4ee2080827bc075d8c1ed4764bd289d6bf65ee2ff870ac8ef72daef8a1858ccf27aad6c296cfece5455f6834a2d18a2c8e719518cd5464a0b languageName: node linkType: hard @@ -2983,6 +2904,150 @@ __metadata: languageName: node linkType: hard +"@parcel/watcher-android-arm64@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-android-arm64@npm:2.5.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@parcel/watcher-darwin-arm64@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-darwin-arm64@npm:2.5.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@parcel/watcher-darwin-x64@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-darwin-x64@npm:2.5.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@parcel/watcher-freebsd-x64@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-freebsd-x64@npm:2.5.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@parcel/watcher-linux-arm-glibc@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-linux-arm-glibc@npm:2.5.0" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@parcel/watcher-linux-arm-musl@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-linux-arm-musl@npm:2.5.0" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + +"@parcel/watcher-linux-arm64-glibc@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-linux-arm64-glibc@npm:2.5.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@parcel/watcher-linux-arm64-musl@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-linux-arm64-musl@npm:2.5.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@parcel/watcher-linux-x64-glibc@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-linux-x64-glibc@npm:2.5.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@parcel/watcher-linux-x64-musl@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-linux-x64-musl@npm:2.5.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@parcel/watcher-win32-arm64@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-win32-arm64@npm:2.5.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@parcel/watcher-win32-ia32@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-win32-ia32@npm:2.5.0" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@parcel/watcher-win32-x64@npm:2.5.0": + version: 2.5.0 + resolution: "@parcel/watcher-win32-x64@npm:2.5.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@parcel/watcher@npm:^2.4.1": + version: 2.5.0 + resolution: "@parcel/watcher@npm:2.5.0" + dependencies: + "@parcel/watcher-android-arm64": 2.5.0 + "@parcel/watcher-darwin-arm64": 2.5.0 + "@parcel/watcher-darwin-x64": 2.5.0 + "@parcel/watcher-freebsd-x64": 2.5.0 + "@parcel/watcher-linux-arm-glibc": 2.5.0 + "@parcel/watcher-linux-arm-musl": 2.5.0 + "@parcel/watcher-linux-arm64-glibc": 2.5.0 + "@parcel/watcher-linux-arm64-musl": 2.5.0 + "@parcel/watcher-linux-x64-glibc": 2.5.0 + "@parcel/watcher-linux-x64-musl": 2.5.0 + "@parcel/watcher-win32-arm64": 2.5.0 + "@parcel/watcher-win32-ia32": 2.5.0 + "@parcel/watcher-win32-x64": 2.5.0 + detect-libc: ^1.0.3 + is-glob: ^4.0.3 + micromatch: ^4.0.5 + node-addon-api: ^7.0.0 + node-gyp: latest + dependenciesMeta: + "@parcel/watcher-android-arm64": + optional: true + "@parcel/watcher-darwin-arm64": + optional: true + "@parcel/watcher-darwin-x64": + optional: true + "@parcel/watcher-freebsd-x64": + optional: true + "@parcel/watcher-linux-arm-glibc": + optional: true + "@parcel/watcher-linux-arm-musl": + optional: true + "@parcel/watcher-linux-arm64-glibc": + optional: true + "@parcel/watcher-linux-arm64-musl": + optional: true + "@parcel/watcher-linux-x64-glibc": + optional: true + "@parcel/watcher-linux-x64-musl": + optional: true + "@parcel/watcher-win32-arm64": + optional: true + "@parcel/watcher-win32-ia32": + optional: true + "@parcel/watcher-win32-x64": + optional: true + checksum: 253f93c5f443dfbb638df58712df077fe46ff7e01e7c78df0c4ceb001e8f5b31db01eb7ddac3ae4159722c4d1525894cd4ce5be49f5e6c14a3a52cbbf9f41cbf + languageName: node + linkType: hard + "@pdf-lib/standard-fonts@npm:^1.0.0": version: 1.0.0 resolution: "@pdf-lib/standard-fonts@npm:1.0.0" @@ -3052,60 +3117,60 @@ __metadata: linkType: hard "@prisma/client@npm:^5.7.1": - version: 5.15.0 - resolution: "@prisma/client@npm:5.15.0" + version: 5.22.0 + resolution: "@prisma/client@npm:5.22.0" peerDependencies: prisma: "*" peerDependenciesMeta: prisma: optional: true - checksum: 1ecb1e6a0db6e38b5d510f4764cd3531c85302c7a7e514d4d78a60504b24d08434b3bb3831045d64f4b1fc220ce8618822a2222e4a332b489619cd6d17c13e8c + checksum: 2a4db1e631528644ad8e726f26fbbcd692fbf3483a872185797cc34ba2531d17288841d7fa753439da29937706d7cd515fa1fc06f01b9e375c2232e2943c169e languageName: node linkType: hard -"@prisma/debug@npm:5.15.0": - version: 5.15.0 - resolution: "@prisma/debug@npm:5.15.0" - checksum: 3189f558c7f3550451d20aa5f347ff015e4e85e4edffd0adc7c9688c73d7433cf1bf5e0401d4dbaef79a0c66e9b18fcc0ecb50712d83a7b4722605ddaef44d12 +"@prisma/debug@npm:5.22.0": + version: 5.22.0 + resolution: "@prisma/debug@npm:5.22.0" + checksum: ee263d933c3ab92e93aee78771e5040a510316d96ce69c64cfd65d21e59646b9c5a047446ce7965651563d001150ef763485474bd43ca8a6544ab7ce604d2ffa languageName: node linkType: hard -"@prisma/engines-version@npm:5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022": - version: 5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022 - resolution: "@prisma/engines-version@npm:5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022" - checksum: c669a0087da307228783739c7aa394c9077a7b171d36627b8599bc4cefbbd2733681b32ea42f88fc9b3dab64ad91ee2004ea693a3dcb91e7d82955d8ef4445ad +"@prisma/engines-version@npm:5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2": + version: 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 + resolution: "@prisma/engines-version@npm:5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2" + checksum: 9ea0689474db5da01d14ec6b24b348c282ce7fc6874a15c7dc7910398a52ef44f67a10b24dee8e41386b4611bdbbc10679145cba5b092f7989cf0543bbf5b078 languageName: node linkType: hard -"@prisma/engines@npm:5.15.0": - version: 5.15.0 - resolution: "@prisma/engines@npm:5.15.0" +"@prisma/engines@npm:5.22.0": + version: 5.22.0 + resolution: "@prisma/engines@npm:5.22.0" dependencies: - "@prisma/debug": 5.15.0 - "@prisma/engines-version": 5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022 - "@prisma/fetch-engine": 5.15.0 - "@prisma/get-platform": 5.15.0 - checksum: b386b4a34ce5dc6c6d9b556b02dc1a8e079a706ce1faf4445860a1abf7f934d84aa3c7c6de40495b89a7382594767bc3b1b3af5a6baede354a7493732655af60 + "@prisma/debug": 5.22.0 + "@prisma/engines-version": 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 + "@prisma/fetch-engine": 5.22.0 + "@prisma/get-platform": 5.22.0 + checksum: b66d08f4291af401a1dc75f096bbd980383bf4334221e5dd6be67882a0a91661d994d4b80f94a683b13bbf9062412eb194263df2f7925d53d1e20bfc6c4ede73 languageName: node linkType: hard -"@prisma/fetch-engine@npm:5.15.0": - version: 5.15.0 - resolution: "@prisma/fetch-engine@npm:5.15.0" +"@prisma/fetch-engine@npm:5.22.0": + version: 5.22.0 + resolution: "@prisma/fetch-engine@npm:5.22.0" dependencies: - "@prisma/debug": 5.15.0 - "@prisma/engines-version": 5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022 - "@prisma/get-platform": 5.15.0 - checksum: 133c9578ec52b723d8664e0aef1de1340a5712ca4d9f65cb99b3393c795b8e858db0d16f02b9e7a3f798d9b81b73de443e9bff7d4509fe66cc9145ac972665b2 + "@prisma/debug": 5.22.0 + "@prisma/engines-version": 5.22.0-44.605197351a3c8bdd595af2d2a9bc3025bca48ea2 + "@prisma/get-platform": 5.22.0 + checksum: d65def9fe4a86ef05041738d12cb730cc8b948379e11ac3e3fa2db08d5640a70467b623b4bb0d6d3f4da86c135f6c6da61867c1658eab430dd0e3939382d3a41 languageName: node linkType: hard -"@prisma/get-platform@npm:5.15.0": - version: 5.15.0 - resolution: "@prisma/get-platform@npm:5.15.0" +"@prisma/get-platform@npm:5.22.0": + version: 5.22.0 + resolution: "@prisma/get-platform@npm:5.22.0" dependencies: - "@prisma/debug": 5.15.0 - checksum: 18358b490e1fdbb44a9b4e8b77eec1b5e428c0d71460042663e6de1809c95afdfddfac4a80d6c6a1efecb4f086d7e32a881fe02e38aa8c7ca3590fbe9240dde5 + "@prisma/debug": 5.22.0 + checksum: 6d1f47dc586560c3518dadcf1cccaa8d624d1268e5d74a12277cc6ecf7cb2f530ec34b8019faa2c22eb29243efe3733d3c9005ec36dc84cd766d2794fa7b0025 languageName: node linkType: hard @@ -3149,10 +3214,17 @@ __metadata: languageName: node linkType: hard +"@rtsao/scc@npm:^1.1.0": + version: 1.1.0 + resolution: "@rtsao/scc@npm:1.1.0" + checksum: 17d04adf404e04c1e61391ed97bca5117d4c2767a76ae3e879390d6dec7b317fcae68afbf9e98badee075d0b64fa60f287729c4942021b4d19cd01db77385c01 + languageName: node + linkType: hard + "@rushstack/eslint-patch@npm:^1.1.0": - version: 1.10.3 - resolution: "@rushstack/eslint-patch@npm:1.10.3" - checksum: 1042779367ee102576a3c132f052d718d7111fee9f815758a72b21e8145620f7d3403c14fcde3b4cfa1cbc14b08b8519151ff77d0f353bf647f0a0a16eafdef5 + version: 1.10.4 + resolution: "@rushstack/eslint-patch@npm:1.10.4" + checksum: ec17ac954ed01e9c714e29ae00da29099234a71615d6f61f2da5c7beeef283f5619132114faf9481cb1ca7b4417aed74c05a54d416e4d8facc189bb216d49066 languageName: node linkType: hard @@ -3188,6 +3260,30 @@ __metadata: languageName: node linkType: hard +"@slack/events-api@npm:^3.0.1": + version: 3.0.1 + resolution: "@slack/events-api@npm:3.0.1" + dependencies: + "@types/debug": ^4.1.4 + "@types/express": ^4.17.0 + "@types/lodash.isstring": ^4.0.6 + "@types/node": ">=12.13.0 < 13" + "@types/yargs": ^15.0.4 + debug: ^2.6.1 + express: ^4.0.0 + lodash.isstring: ^4.0.1 + raw-body: ^2.3.3 + tsscmp: ^1.0.6 + yargs: ^15.3.1 + dependenciesMeta: + express: + optional: true + bin: + slack-verify: dist/verify.js + checksum: ce62dc2ee9dd93b88820e18f88f543228740243dc390caf49b3a7e1ad351b298e3961898bd78f5eb43e9f6acac067458257cd34c9661089f684bb5cf4af468c3 + languageName: node + linkType: hard + "@slack/logger@npm:^3.0.0": version: 3.0.0 resolution: "@slack/logger@npm:3.0.0" @@ -3198,28 +3294,28 @@ __metadata: linkType: hard "@slack/types@npm:^2.11.0": - version: 2.12.0 - resolution: "@slack/types@npm:2.12.0" - checksum: 490e92f93163aac46bb0e1df8d94e577c61b47efe72e6e4981b34145acbff84cd83fdab067dd72377944e46f07410407bb460f8525ee0990d5743b40704720bc + version: 2.14.0 + resolution: "@slack/types@npm:2.14.0" + checksum: fbef74d50d0de8f16125f7178bd2e664a69eeefd827b09c6f78153957278fc4400049685c756076e7dbcabd04c22730ac783bcc5d36fd588c7749d35f02c2afd languageName: node linkType: hard "@slack/web-api@npm:^6.7.2": - version: 6.12.0 - resolution: "@slack/web-api@npm:6.12.0" + version: 6.13.0 + resolution: "@slack/web-api@npm:6.13.0" dependencies: "@slack/logger": ^3.0.0 "@slack/types": ^2.11.0 "@types/is-stream": ^1.1.0 "@types/node": ">=12.0.0" - axios: ^1.6.5 + axios: ^1.7.4 eventemitter3: ^3.1.0 form-data: ^2.5.0 is-electron: 2.2.2 is-stream: ^1.1.0 p-queue: ^6.6.1 p-retry: ^4.0.0 - checksum: d0cc16a2981167f3780a07542b4c88d31fc836a743de04e52e9f8fe8a82281781103f8821b3db5aa9de55471b6e550f044e767dbf482045865bd713b90fddd65 + checksum: 77f0d506bbb011ae43d322e5152e8b1ec2b88aa01256da6b3c9ff8ce106d2284f887cad2d9f044e0fe34dc865d60f2bce1c6bb5c4117150ff71a7ef341f5dfeb languageName: node linkType: hard @@ -3568,10 +3664,19 @@ __metadata: languageName: node linkType: hard -"@types/chai@npm:*, @types/chai@npm:^4.3.5": - version: 4.3.16 - resolution: "@types/chai@npm:4.3.16" - checksum: bb5f52d1b70534ed8b4bf74bd248add003ffe1156303802ea367331607c06b494da885ffbc2b674a66b4f90c9ee88759790a5f243879f6759f124f22328f5e95 +"@types/chai@npm:*": + version: 5.0.1 + resolution: "@types/chai@npm:5.0.1" + dependencies: + "@types/deep-eql": "*" + checksum: 53d813cbca3755c025381ad4ac8b51b17897df90316350247f9527bdba3adb48b3b1315308fbd717d9013d8e60375c0ab4bd004dc72330133486ff5db4cb0b2c + languageName: node + linkType: hard + +"@types/chai@npm:^4.3.5": + version: 4.3.20 + resolution: "@types/chai@npm:4.3.20" + checksum: 7c5b0c9148f1a844a8d16cb1e16c64f2e7749cab2b8284155b9e494a6b34054846e22fb2b38df6b290f9bf57e6beebb2e121940c5896bc086ad7bab7ed429f06 languageName: node linkType: hard @@ -3594,11 +3699,11 @@ __metadata: linkType: hard "@types/cookie-parser@npm:^1.4.3": - version: 1.4.7 - resolution: "@types/cookie-parser@npm:1.4.7" - dependencies: + version: 1.4.8 + resolution: "@types/cookie-parser@npm:1.4.8" + peerDependencies: "@types/express": "*" - checksum: 7b87c59420598e686a57e240be6e0db53967c3c8814be9326bf86609ee2fc39c4b3b9f2263e1deba43526090121d1df88684b64c19f7b494a80a4437caf3d40b + checksum: b26ace5560adce1a746c059a75f18227ee3e3614a49c70dd29b8af204696079ced22eaa9d6cb084e3433ec433bff845cb47ffb890ae9af96a4aab2ff85e40da7 languageName: node linkType: hard @@ -3625,7 +3730,7 @@ __metadata: languageName: node linkType: hard -"@types/debug@npm:^4.1.7": +"@types/debug@npm:^4.1.4, @types/debug@npm:^4.1.7": version: 4.1.12 resolution: "@types/debug@npm:4.1.12" dependencies: @@ -3634,6 +3739,13 @@ __metadata: languageName: node linkType: hard +"@types/deep-eql@npm:*": + version: 4.0.2 + resolution: "@types/deep-eql@npm:4.0.2" + checksum: 249a27b0bb22f6aa28461db56afa21ec044fa0e303221a62dff81831b20c8530502175f1a49060f7099e7be06181078548ac47c668de79ff9880241968d43d0c + languageName: node + linkType: hard + "@types/eslint@npm:^7.29.0": version: 7.29.0 resolution: "@types/eslint@npm:7.29.0" @@ -3645,9 +3757,9 @@ __metadata: linkType: hard "@types/estree@npm:*": - version: 1.0.5 - resolution: "@types/estree@npm:1.0.5" - checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a + version: 1.0.6 + resolution: "@types/estree@npm:1.0.6" + checksum: 8825d6e729e16445d9a1dd2fb1db2edc5ed400799064cd4d028150701031af012ba30d6d03fe9df40f4d7a437d0de6d2b256020152b7b09bde9f2e420afdffd9 languageName: node linkType: hard @@ -3669,14 +3781,26 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:^4.17.33": - version: 4.19.3 - resolution: "@types/express-serve-static-core@npm:4.19.3" + version: 4.19.6 + resolution: "@types/express-serve-static-core@npm:4.19.6" + dependencies: + "@types/node": "*" + "@types/qs": "*" + "@types/range-parser": "*" + "@types/send": "*" + checksum: b0576eddc2d25ccdf10e68ba09598b87a4d7b2ad04a81dc847cb39fe56beb0b6a5cc017b1e00aa0060cb3b38e700384ce96d291a116a0f1e54895564a104aae9 + languageName: node + linkType: hard + +"@types/express-serve-static-core@npm:^5.0.0": + version: 5.0.2 + resolution: "@types/express-serve-static-core@npm:5.0.2" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" "@types/send": "*" - checksum: fff38a7f43baeb6a62380682d39846c9d92047e0dce1737d76ebd944528619abc18addc4f0548bf43dbf4514090a1bd5140ba36695024656f941a87424b8ed7d + checksum: 841229b63801b334729e56ec04b5023e084e2962d61dddc95b3508e2fc821e8550bd69c074b6cb0a1c57147eb324c4dc543103d0827e34077f7eb6d230d08a8f languageName: node linkType: hard @@ -3689,7 +3813,19 @@ __metadata: languageName: node linkType: hard -"@types/express@npm:*, @types/express@npm:^4.17.6": +"@types/express@npm:*, @types/express@npm:^5.0.0": + version: 5.0.0 + resolution: "@types/express@npm:5.0.0" + dependencies: + "@types/body-parser": "*" + "@types/express-serve-static-core": ^5.0.0 + "@types/qs": "*" + "@types/serve-static": "*" + checksum: ef68d8e2b7593c930093b1e79bf4df15413773508c9acd6a1a933ed7017f2a4892a8d128b2222d7eab9a3fa43181067a378c2600d9258bd7ae917f170e962df4 + languageName: node + linkType: hard + +"@types/express@npm:^4.17.0": version: 4.17.21 resolution: "@types/express@npm:4.17.21" dependencies: @@ -3802,12 +3938,12 @@ __metadata: linkType: hard "@types/jest@npm:*": - version: 29.5.12 - resolution: "@types/jest@npm:29.5.12" + version: 29.5.14 + resolution: "@types/jest@npm:29.5.14" dependencies: expect: ^29.0.0 pretty-format: ^29.0.0 - checksum: 19b1efdeed9d9a60a81edc8226cdeae5af7479e493eaed273e01243891c9651f7b8b4c08fc633a7d0d1d379b091c4179bbaa0807af62542325fd72f2dd17ce1c + checksum: 18dba4623f26661641d757c63da2db45e9524c9be96a29ef713c703a9a53792df9ecee9f7365a0858ddbd6440d98fe6b65ca67895ca5884b73cbc7ffc11f3838 languageName: node linkType: hard @@ -3851,10 +3987,19 @@ __metadata: languageName: node linkType: hard -"@types/lodash@npm:^4.14.175": - version: 4.17.4 - resolution: "@types/lodash@npm:4.17.4" - checksum: 268e652fd52d49189f155bc89b49bd4535aa44f0b6b0ed9ce7e50318307bda58147c49539d2047f39ca37cf5b5ea38dfb801d0dbcdbc8b019c95c1afc346b05a +"@types/lodash.isstring@npm:^4.0.6": + version: 4.0.9 + resolution: "@types/lodash.isstring@npm:4.0.9" + dependencies: + "@types/lodash": "*" + checksum: ef381be69b459caa42d7c5dc4ff5b3653e6b3c9b2393f6e92848efeafe7690438e058b26f036b11b4e535fc7645ff12d1203847b9a82e9ae0593bdd3b25a971b + languageName: node + linkType: hard + +"@types/lodash@npm:*, @types/lodash@npm:^4.14.175": + version: 4.17.13 + resolution: "@types/lodash@npm:4.17.13" + checksum: d0bf8fbd950be71946e0076b30fd40d492293baea75f05931b6b5b906fd62583708c6229abdb95b30205ad24ce1ed2f48bc9d419364f682320edd03405cc0c7e languageName: node linkType: hard @@ -3896,20 +4041,20 @@ __metadata: linkType: hard "@types/multer@npm:^1.4.7": - version: 1.4.11 - resolution: "@types/multer@npm:1.4.11" + version: 1.4.12 + resolution: "@types/multer@npm:1.4.12" dependencies: "@types/express": "*" - checksum: 3d80b2acdfbc9f3e9027d4467e948925810b67e5622a3017f42f58a3598d34b25376890801e55d0c03973ccc34573abf5218af334e8292ec455832f4ade3e5f5 + checksum: 719cacf88ec83ed77e250e45bee830fd7a505323825efa2a2c1144f5f3d7d36e67408ec988e571bcbaa571e0c214b5ede42d57ebb0f9b453a5eb8faba8ff12d0 languageName: node linkType: hard "@types/node@npm:*, @types/node@npm:>=12.0.0": - version: 20.14.2 - resolution: "@types/node@npm:20.14.2" + version: 22.10.1 + resolution: "@types/node@npm:22.10.1" dependencies: - undici-types: ~5.26.4 - checksum: 265362479b8f3b50fcd1e3f9e9af6121feb01a478dff0335ae67cccc3babfe45d0f12209d3d350595eebd7e67471762697b877c380513f8e5d27a238fa50c805 + undici-types: ~6.20.0 + checksum: 5a9b81500f288a8fb757b61bd939f99f72b6cb59347a5bae52dd1c2c87100ebbaa9da4256ef3cb9add2090e8704cda1d9a1ffc14ccd5db47a6466c8bae10ebcb languageName: node linkType: hard @@ -3920,12 +4065,19 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:>=12.13.0 < 13": + version: 12.20.55 + resolution: "@types/node@npm:12.20.55" + checksum: e4f86785f4092706e0d3b0edff8dca5a13b45627e4b36700acd8dfe6ad53db71928c8dee914d4276c7fd3b6ccd829aa919811c9eb708a2c8e4c6eb3701178c37 + languageName: node + linkType: hard + "@types/nodemailer@npm:^6.4.0": - version: 6.4.15 - resolution: "@types/nodemailer@npm:6.4.15" + version: 6.4.17 + resolution: "@types/nodemailer@npm:6.4.17" dependencies: "@types/node": "*" - checksum: f6f9a2f8a669703ecc3ca6359c12345b16f6b2e5691b93c406b9af7de639c02092ec00133526e6fecd8c60d884890a7cd0f967d8e64bedab46d5c3d8be0882d7 + checksum: 498b702575111494a42cf9cdd3d399f0308c3b3b0244e7f53008924327955a16b39ba0bf99a5ccf17af9fd2bc50a61a76ae7e8a75498a426ea2f828a05202eab languageName: node linkType: hard @@ -3950,10 +4102,10 @@ __metadata: languageName: node linkType: hard -"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.11, @types/prop-types@npm:^15.7.12": - version: 15.7.12 - resolution: "@types/prop-types@npm:15.7.12" - checksum: ac16cc3d0a84431ffa5cfdf89579ad1e2269549f32ce0c769321fdd078f84db4fbe1b461ed5a1a496caf09e637c0e367d600c541435716a55b1d9713f5035dfe +"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.12, @types/prop-types@npm:^15.7.13": + version: 15.7.13 + resolution: "@types/prop-types@npm:15.7.13" + checksum: 8935cad87c683c665d09a055919d617fe951cb3b2d5c00544e3a913f861a2bd8d2145b51c9aa6d2457d19f3107ab40784c40205e757232f6a80cc8b1c815513c languageName: node linkType: hard @@ -3965,9 +4117,9 @@ __metadata: linkType: hard "@types/qs@npm:*": - version: 6.9.15 - resolution: "@types/qs@npm:6.9.15" - checksum: 97d8208c2b82013b618e7a9fc14df6bd40a73e1385ac479b6896bafc7949a46201c15f42afd06e86a05e914f146f495f606b6fb65610cc60cf2e0ff743ec38a2 + version: 6.9.17 + resolution: "@types/qs@npm:6.9.17" + checksum: fc3beda0be70e820ddabaa361e8dfec5e09b482b8f6cf1515615479a027dd06cd5ba0ffbd612b654c2605523f45f484c8905a475623d6cd0c4cadcf5d0c517f5 languageName: node linkType: hard @@ -4027,11 +4179,11 @@ __metadata: linkType: hard "@types/react-transition-group@npm:^4.4.10, @types/react-transition-group@npm:^4.4.8": - version: 4.4.10 - resolution: "@types/react-transition-group@npm:4.4.10" + version: 4.4.11 + resolution: "@types/react-transition-group@npm:4.4.11" dependencies: "@types/react": "*" - checksum: fe2ea11f70251e9f79f368e198c18fd469b1d4f1e1d44e4365845b44e15974b0ec925100036f449b023b0ca3480a82725c5f0a73040e282ad32ec7b0def9b57c + checksum: a6e3b2e4363cb019e256ae4f19dadf9d7eb199da1a5e4109bbbf6a132821884044d332e9c74b520b1e5321a7f545502443fd1ce0b18649c8b510fa4220b0e5c2 languageName: node linkType: hard @@ -4090,11 +4242,11 @@ __metadata: linkType: hard "@types/set-cookie-parser@npm:^2.4.0": - version: 2.4.7 - resolution: "@types/set-cookie-parser@npm:2.4.7" + version: 2.4.10 + resolution: "@types/set-cookie-parser@npm:2.4.10" dependencies: "@types/node": "*" - checksum: 01ef803e24b8cd33e49fe7463f32a562da45ce3f960381b90cccf67ea71b1830d2273df044255b040069c0a92ea25b4bf21c39ac2f85b50c01818ded5e918554 + checksum: 105cc90c7d7deeb344858f720b58bd137356586545ac00d1a448e050bfcc0f385553ff26bc9c674bd8c2e953a458149eadb1945ee3d1eee81e6c0656236ebc0a languageName: node linkType: hard @@ -4113,13 +4265,14 @@ __metadata: linkType: hard "@types/superagent@npm:*": - version: 8.1.7 - resolution: "@types/superagent@npm:8.1.7" + version: 8.1.9 + resolution: "@types/superagent@npm:8.1.9" dependencies: "@types/cookiejar": ^2.1.5 "@types/methods": ^1.1.4 "@types/node": "*" - checksum: 8f80c72bd1cc9a9295a2e1e8a7a8de9bef09348db63f33cc4f61e457917662064ab86ce013f28249c34d7239d9a4415c1a597dc70d4391b2ad83b338a63a3b73 + form-data: ^4.0.0 + checksum: 530d8c2e87706315c82c8c9696500c40621de3353bc54ea9b104947f3530243abf54d0a49a6ae219d4947606a102ceb94bedfc43b9cc49f74069a18cbb3be8e2 languageName: node linkType: hard @@ -4158,9 +4311,9 @@ __metadata: linkType: hard "@types/unist@npm:^2, @types/unist@npm:^2.0.0, @types/unist@npm:^2.0.2, @types/unist@npm:^2.0.3": - version: 2.0.10 - resolution: "@types/unist@npm:2.0.10" - checksum: e2924e18dedf45f68a5c6ccd6015cd62f1643b1b43baac1854efa21ae9e70505db94290434a23da1137d9e31eb58e54ca175982005698ac37300a1c889f6c4aa + version: 2.0.11 + resolution: "@types/unist@npm:2.0.11" + checksum: 6d436e832bc35c6dde9f056ac515ebf2b3384a1d7f63679d12358766f9b313368077402e9c1126a14d827f10370a5485e628bf61aa91117cf4fc882423191a4e languageName: node linkType: hard @@ -4183,8 +4336,8 @@ __metadata: linkType: hard "@types/webpack@npm:^4.41.8": - version: 4.41.38 - resolution: "@types/webpack@npm:4.41.38" + version: 4.41.40 + resolution: "@types/webpack@npm:4.41.40" dependencies: "@types/node": "*" "@types/tapable": ^1 @@ -4192,7 +4345,7 @@ __metadata: "@types/webpack-sources": "*" anymatch: ^3.0.0 source-map: ^0.6.0 - checksum: d3de65993ef3a7621f75548c2f6f509e8f87f586032238e999743d6067030655c67e38ec5f8b32e04fa5276c83bdfb7a761773bce0e6f28605da87e3fc388e3e + checksum: 3866c3177e1ca0810d9e3cb88fb35183f093b4bcf6cc29f6161425a2a5ea7b4faf5d429c6cf3ed58b780e36dc471a0f511cedb1dcd43f519e1df7d24185f5d4a languageName: node linkType: hard @@ -4203,7 +4356,7 @@ __metadata: languageName: node linkType: hard -"@types/yargs@npm:^15.0.0": +"@types/yargs@npm:^15.0.0, @types/yargs@npm:^15.0.4": version: 15.0.19 resolution: "@types/yargs@npm:15.0.19" dependencies: @@ -4213,11 +4366,11 @@ __metadata: linkType: hard "@types/yargs@npm:^17.0.8": - version: 17.0.32 - resolution: "@types/yargs@npm:17.0.32" + version: 17.0.33 + resolution: "@types/yargs@npm:17.0.33" dependencies: "@types/yargs-parser": "*" - checksum: 4505bdebe8716ff383640c6e928f855b5d337cb3c68c81f7249fc6b983d0aa48de3eee26062b84f37e0d75a5797bc745e0c6e76f42f81771252a758c638f36ba + checksum: ee013f257472ab643cb0584cf3e1ff9b0c44bca1c9ba662395300a7f1a6c55fa9d41bd40ddff42d99f5d95febb3907c9ff600fbcb92dadbec22c6a76de7e1236 languageName: node linkType: hard @@ -4604,17 +4757,17 @@ __metadata: linkType: hard "@vitejs/plugin-react@npm:^4.0.0": - version: 4.3.0 - resolution: "@vitejs/plugin-react@npm:4.3.0" + version: 4.3.4 + resolution: "@vitejs/plugin-react@npm:4.3.4" dependencies: - "@babel/core": ^7.24.5 - "@babel/plugin-transform-react-jsx-self": ^7.24.5 - "@babel/plugin-transform-react-jsx-source": ^7.24.1 + "@babel/core": ^7.26.0 + "@babel/plugin-transform-react-jsx-self": ^7.25.9 + "@babel/plugin-transform-react-jsx-source": ^7.25.9 "@types/babel__core": ^7.20.5 react-refresh: ^0.14.2 peerDependencies: - vite: ^4.2.0 || ^5.0.0 - checksum: e4642c081e74e701fc07f03f505b44eb428d7105461b8026e7364ecd30dcf7785126bf272767a3bc36899b6abe85479af444612ef6d09509d9bc7d6025cac925 + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + checksum: d417f40d9259a1d5193152f7d9fee081d5bf41cbeef9662ae1123ccc1e26aa4b6b04bc82ebb8c4fbfde9516a746fb3af7da19fdd449819c30f0631daaa10a44b languageName: node linkType: hard @@ -4894,7 +5047,17 @@ __metadata: languageName: node linkType: hard -"accepts@npm:~1.3.4, accepts@npm:~1.3.5, accepts@npm:~1.3.8": +"accepts@npm:^2.0.0": + version: 2.0.0 + resolution: "accepts@npm:2.0.0" + dependencies: + mime-types: ^3.0.0 + negotiator: ^1.0.0 + checksum: 49fe6c050cb6f6ff4e771b4d88324fca4d3127865f2473872e818dca127d809ba3aa8fdfc7acb51dd3c5bade7311ca6b8cfff7015ea6db2f7eb9c8444d223a4f + languageName: node + linkType: hard + +"accepts@npm:~1.3.4, accepts@npm:~1.3.8": version: 1.3.8 resolution: "accepts@npm:1.3.8" dependencies: @@ -4931,9 +5094,11 @@ __metadata: linkType: hard "acorn-walk@npm:^8.1.1, acorn-walk@npm:^8.2.0": - version: 8.3.2 - resolution: "acorn-walk@npm:8.3.2" - checksum: 3626b9d26a37b1b427796feaa5261faf712307a8920392c8dce9a5739fb31077667f4ad2ec71c7ac6aaf9f61f04a9d3d67ff56f459587206fc04aa31c27ef392 + version: 8.3.4 + resolution: "acorn-walk@npm:8.3.4" + dependencies: + acorn: ^8.11.0 + checksum: 4ff03f42323e7cf90f1683e08606b0f460e1e6ac263d2730e3df91c7665b6f64e696db6ea27ee4bed18c2599569be61f28a8399fa170c611161a348c402ca19c languageName: node linkType: hard @@ -4955,12 +5120,12 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.10.0, acorn@npm:^8.11.3, acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.5.0, acorn@npm:^8.8.2, acorn@npm:^8.9.0": - version: 8.11.3 - resolution: "acorn@npm:8.11.3" +"acorn@npm:^8.10.0, acorn@npm:^8.11.0, acorn@npm:^8.14.0, acorn@npm:^8.2.4, acorn@npm:^8.4.1, acorn@npm:^8.5.0, acorn@npm:^8.8.2, acorn@npm:^8.9.0": + version: 8.14.0 + resolution: "acorn@npm:8.14.0" bin: acorn: bin/acorn - checksum: 76d8e7d559512566b43ab4aadc374f11f563f0a9e21626dd59cb2888444e9445923ae9f3699972767f18af61df89cd89f5eaaf772d1327b055b45cb829b4a88c + checksum: 8755074ba55fff94e84e81c72f1013c2d9c78e973c31231c8ae505a5f966859baf654bddd75046bffd73ce816b149298977fff5077a3033dedba0ae2aad152d4 languageName: node linkType: hard @@ -5047,14 +5212,14 @@ __metadata: linkType: hard "ajv@npm:^8.0.1": - version: 8.16.0 - resolution: "ajv@npm:8.16.0" + version: 8.17.1 + resolution: "ajv@npm:8.17.1" dependencies: fast-deep-equal: ^3.1.3 + fast-uri: ^3.0.1 json-schema-traverse: ^1.0.0 require-from-string: ^2.0.2 - uri-js: ^4.4.1 - checksum: bdf3d4c9f1d11e220850051ef4cd89346e951cfb933d6d41be36d45053c1092af1523ee6c62525cce567355caf0a4f4c19a08a93851649c1fa32b4a39b7c4858 + checksum: 1797bf242cfffbaf3b870d13565bd1716b73f214bb7ada9a497063aada210200da36e3ed40237285f3255acc4feeae91b1fb183625331bad27da95973f7253d9 languageName: node linkType: hard @@ -5119,9 +5284,9 @@ __metadata: linkType: hard "ansi-regex@npm:^6.0.1": - version: 6.0.1 - resolution: "ansi-regex@npm:6.0.1" - checksum: 1ff8b7667cded1de4fa2c9ae283e979fc87036864317da86a2e546725f96406746411d0d85e87a2d12fa5abd715d90006de7fa4fa0477c92321ad3b4c7d4e169 + version: 6.1.0 + resolution: "ansi-regex@npm:6.1.0" + checksum: 495834a53b0856c02acd40446f7130cb0f8284f4a39afdab20d5dc42b2e198b1196119fe887beed8f9055c4ff2055e3b2f6d4641d0be018cdfb64fedf6fc1aac languageName: node linkType: hard @@ -5233,12 +5398,10 @@ __metadata: languageName: node linkType: hard -"aria-query@npm:^5.0.0, aria-query@npm:^5.3.0": - version: 5.3.0 - resolution: "aria-query@npm:5.3.0" - dependencies: - dequal: ^2.0.3 - checksum: 305bd73c76756117b59aba121d08f413c7ff5e80fa1b98e217a3443fcddb9a232ee790e24e432b59ae7625aebcf4c47cb01c2cac872994f0b426f5bdfcd96ba9 +"aria-query@npm:^5.0.0, aria-query@npm:^5.3.2": + version: 5.3.2 + resolution: "aria-query@npm:5.3.2" + checksum: d971175c85c10df0f6d14adfe6f1292409196114ab3c62f238e208b53103686f46cc70695a4f775b73bc65f6a09b6a092fd963c4f3a5a7d690c8fc5094925717 languageName: node linkType: hard @@ -5287,6 +5450,13 @@ __metadata: languageName: node linkType: hard +"array-flatten@npm:3.0.0": + version: 3.0.0 + resolution: "array-flatten@npm:3.0.0" + checksum: ad00c51ca70cf837501fb6da823ba39bc6a86b43d0b76d840daa02fe0f8e68e94ad5bc2d0d038053118b879aaca8ea6168c32c7387a2fa5b118ad28db4f1f863 + languageName: node + linkType: hard + "array-flatten@npm:^2.1.0": version: 2.1.2 resolution: "array-flatten@npm:2.1.2" @@ -5294,7 +5464,7 @@ __metadata: languageName: node linkType: hard -"array-includes@npm:^3.1.6, array-includes@npm:^3.1.7, array-includes@npm:^3.1.8": +"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8": version: 3.1.8 resolution: "array-includes@npm:3.1.8" dependencies: @@ -5352,7 +5522,7 @@ __metadata: languageName: node linkType: hard -"array.prototype.findlastindex@npm:^1.2.3": +"array.prototype.findlastindex@npm:^1.2.5": version: 1.2.5 resolution: "array.prototype.findlastindex@npm:1.2.5" dependencies: @@ -5405,19 +5575,7 @@ __metadata: languageName: node linkType: hard -"array.prototype.toreversed@npm:^1.1.2": - version: 1.1.2 - resolution: "array.prototype.toreversed@npm:1.1.2" - dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-shim-unscopables: ^1.0.0 - checksum: 58598193426282155297bedf950dc8d464624a0d81659822fb73124286688644cb7e0e4927a07f3ab2daaeb6617b647736cc3a5e6ca7ade5bb8e573b284e6240 - languageName: node - linkType: hard - -"array.prototype.tosorted@npm:^1.1.3": +"array.prototype.tosorted@npm:^1.1.4": version: 1.1.4 resolution: "array.prototype.tosorted@npm:1.1.4" dependencies: @@ -5581,10 +5739,10 @@ __metadata: languageName: node linkType: hard -"axe-core@npm:=4.7.0": - version: 4.7.0 - resolution: "axe-core@npm:4.7.0" - checksum: f086bcab42be1761ba2b0b127dec350087f4c3a853bba8dd58f69d898cefaac31a1561da23146f6f3c07954c76171d1f2ce460e555e052d2b02cd79af628fa4a +"axe-core@npm:^4.10.0": + version: 4.10.2 + resolution: "axe-core@npm:4.10.2" + checksum: 2b9b1c93ea73ea9f206604e4e17bd771d2d835f077bde54517d73028b8865c69b209460e73d5b109968cbdb39ab3d28943efa5695189bd79e16421ce1706719e languageName: node linkType: hard @@ -5598,23 +5756,21 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.6.5": - version: 1.7.2 - resolution: "axios@npm:1.7.2" +"axios@npm:^1.7.4": + version: 1.7.8 + resolution: "axios@npm:1.7.8" dependencies: follow-redirects: ^1.15.6 form-data: ^4.0.0 proxy-from-env: ^1.1.0 - checksum: e457e2b0ab748504621f6fa6609074ac08c824bf0881592209dfa15098ece7e88495300e02cd22ba50b3468fd712fe687e629dcb03d6a3f6a51989727405aedf + checksum: 3d21652faf8e29fb36c47517d2872bb5e2285127a24f5c53ce23082c4eac7f5a88de84dd49d4a1a83068e5301dcfd9067b41e5fbd00b0d20ab7b0a843559273d languageName: node linkType: hard -"axobject-query@npm:^3.2.1": - version: 3.2.1 - resolution: "axobject-query@npm:3.2.1" - dependencies: - dequal: ^2.0.3 - checksum: a94047e702b57c91680e6a952ec4a1aaa2cfd0d80ead76bc8c954202980d8c51968a6ea18b4d8010e8e2cf95676533d8022a8ebba9abc1dfe25686721df26fd2 +"axobject-query@npm:^4.1.0": + version: 4.1.0 + resolution: "axobject-query@npm:4.1.0" + checksum: 7d1e87bf0aa7ae7a76cd39ab627b7c48fda3dc40181303d9adce4ba1d5b5ce73b5e5403ee6626ec8e91090448c887294d6144e24b6741a976f5be9347e3ae1df languageName: node linkType: hard @@ -5723,38 +5879,38 @@ __metadata: linkType: hard "babel-plugin-polyfill-corejs2@npm:^0.4.10": - version: 0.4.11 - resolution: "babel-plugin-polyfill-corejs2@npm:0.4.11" + version: 0.4.12 + resolution: "babel-plugin-polyfill-corejs2@npm:0.4.12" dependencies: "@babel/compat-data": ^7.22.6 - "@babel/helper-define-polyfill-provider": ^0.6.2 + "@babel/helper-define-polyfill-provider": ^0.6.3 semver: ^6.3.1 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: f098353ce7c7dde1a1d2710858e01b471e85689110c9e37813e009072347eb8c55d5f84d20d3bf1cab31755f20078ba90f8855fdc4686a9daa826a95ff280bd7 + checksum: 6e6e6a8b85fec80a310ded2f5c151385e4ac59118909dd6a952e1025e4a478eb79dda45a5a6322cc2e598fd696eb07d4e2fa52418b4101f3dc370bdf8c8939ba languageName: node linkType: hard -"babel-plugin-polyfill-corejs3@npm:^0.10.1, babel-plugin-polyfill-corejs3@npm:^0.10.4": - version: 0.10.4 - resolution: "babel-plugin-polyfill-corejs3@npm:0.10.4" +"babel-plugin-polyfill-corejs3@npm:^0.10.6": + version: 0.10.6 + resolution: "babel-plugin-polyfill-corejs3@npm:0.10.6" dependencies: - "@babel/helper-define-polyfill-provider": ^0.6.1 - core-js-compat: ^3.36.1 + "@babel/helper-define-polyfill-provider": ^0.6.2 + core-js-compat: ^3.38.0 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: b96a54495f7cc8b3797251c8c15f5ed015edddc3110fc122f6b32c94bec33af1e8bc56fa99091808f500bde0cccaaa266889cdc5935d9e6e9cf09898214f02dd + checksum: f762f29f7acca576897c63149c850f0a72babd3fb9ea436a2e36f0c339161c4b912a77828541d8188ce8a91e50965c6687120cf36071eabb1b7aa92f279e2164 languageName: node linkType: hard "babel-plugin-polyfill-regenerator@npm:^0.6.1": - version: 0.6.2 - resolution: "babel-plugin-polyfill-regenerator@npm:0.6.2" + version: 0.6.3 + resolution: "babel-plugin-polyfill-regenerator@npm:0.6.3" dependencies: - "@babel/helper-define-polyfill-provider": ^0.6.2 + "@babel/helper-define-polyfill-provider": ^0.6.3 peerDependencies: "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 150233571072b6b3dfe946242da39cba8587b7f908d1c006f7545fc88b0e3c3018d445739beb61e7a75835f0c2751dbe884a94ff9b245ec42369d9267e0e1b3f + checksum: d12696e6b3f280eb78fac551619ca4389262db62c7352cd54bf679d830df8b35596eef2de77cf00db6648eada1c99d49c4f40636dbc9c335a1e5420cfef96750 languageName: node linkType: hard @@ -5783,24 +5939,27 @@ __metadata: linkType: hard "babel-preset-current-node-syntax@npm:^1.0.0": - version: 1.0.1 - resolution: "babel-preset-current-node-syntax@npm:1.0.1" + version: 1.1.0 + resolution: "babel-preset-current-node-syntax@npm:1.1.0" dependencies: "@babel/plugin-syntax-async-generators": ^7.8.4 "@babel/plugin-syntax-bigint": ^7.8.3 - "@babel/plugin-syntax-class-properties": ^7.8.3 - "@babel/plugin-syntax-import-meta": ^7.8.3 + "@babel/plugin-syntax-class-properties": ^7.12.13 + "@babel/plugin-syntax-class-static-block": ^7.14.5 + "@babel/plugin-syntax-import-attributes": ^7.24.7 + "@babel/plugin-syntax-import-meta": ^7.10.4 "@babel/plugin-syntax-json-strings": ^7.8.3 - "@babel/plugin-syntax-logical-assignment-operators": ^7.8.3 + "@babel/plugin-syntax-logical-assignment-operators": ^7.10.4 "@babel/plugin-syntax-nullish-coalescing-operator": ^7.8.3 - "@babel/plugin-syntax-numeric-separator": ^7.8.3 + "@babel/plugin-syntax-numeric-separator": ^7.10.4 "@babel/plugin-syntax-object-rest-spread": ^7.8.3 "@babel/plugin-syntax-optional-catch-binding": ^7.8.3 "@babel/plugin-syntax-optional-chaining": ^7.8.3 - "@babel/plugin-syntax-top-level-await": ^7.8.3 + "@babel/plugin-syntax-private-property-in-object": ^7.14.5 + "@babel/plugin-syntax-top-level-await": ^7.14.5 peerDependencies: "@babel/core": ^7.0.0 - checksum: d118c2742498c5492c095bc8541f4076b253e705b5f1ad9a2e7d302d81a84866f0070346662355c8e25fc02caa28dc2da8d69bcd67794a0d60c4d6fab6913cc8 + checksum: 9f93fac975eaba296c436feeca1031ca0539143c4066eaf5d1ba23525a31850f03b651a1049caea7287df837a409588c8252c15627ad3903f17864c8e25ed64b languageName: node linkType: hard @@ -5868,7 +6027,7 @@ __metadata: "@types/concat-stream": ^2.0.0 "@types/cookie-parser": ^1.4.3 "@types/cors": ^2.8.12 - "@types/express": ^4.17.6 + "@types/express": ^5.0.0 "@types/express-jwt": ^6.0.4 "@types/jsonwebtoken": ^8.5.9 "@types/multer": ^1.4.7 @@ -5881,7 +6040,7 @@ __metadata: cors: ^2.8.5 decimal.js: ^10.4.3 dotenv: ^16.0.1 - express: ^4.17.1 + express: ^5.0.0 express-jwt: ^7.7.5 express-validator: ^6.14.2 google-auth-library: ^8.1.1 @@ -6019,22 +6178,22 @@ __metadata: linkType: hard "bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.9": - version: 4.12.0 - resolution: "bn.js@npm:4.12.0" - checksum: 39afb4f15f4ea537b55eaf1446c896af28ac948fdcf47171961475724d1bb65118cca49fa6e3d67706e4790955ec0e74de584e45c8f1ef89f46c812bee5b5a12 + version: 4.12.1 + resolution: "bn.js@npm:4.12.1" + checksum: f7f84a909bd07bdcc6777cccbf280b629540792e6965fb1dd1aeafba96e944f197ca10cbec2692f51e0a906ff31da1eb4317f3d1cd659d6f68b8bcd211f7ecbc languageName: node linkType: hard -"bn.js@npm:^5.0.0, bn.js@npm:^5.2.1": +"bn.js@npm:^5.2.1": version: 5.2.1 resolution: "bn.js@npm:5.2.1" checksum: 3dd8c8d38055fedfa95c1d5fc3c99f8dd547b36287b37768db0abab3c239711f88ff58d18d155dd8ad902b0b0cee973747b7ae20ea12a09473272b0201c9edd3 languageName: node linkType: hard -"body-parser@npm:1.20.2, body-parser@npm:^1.19.0": - version: 1.20.2 - resolution: "body-parser@npm:1.20.2" +"body-parser@npm:1.20.3, body-parser@npm:^1.19.0": + version: 1.20.3 + resolution: "body-parser@npm:1.20.3" dependencies: bytes: 3.1.2 content-type: ~1.0.5 @@ -6044,11 +6203,29 @@ __metadata: http-errors: 2.0.0 iconv-lite: 0.4.24 on-finished: 2.4.1 - qs: 6.11.0 + qs: 6.13.0 raw-body: 2.5.2 type-is: ~1.6.18 unpipe: 1.0.0 - checksum: 14d37ec638ab5c93f6099ecaed7f28f890d222c650c69306872e00b9efa081ff6c596cd9afb9930656aae4d6c4e1c17537bea12bb73c87a217cb3cfea8896737 + checksum: 1a35c59a6be8d852b00946330141c4f142c6af0f970faa87f10ad74f1ee7118078056706a05ae3093c54dabca9cd3770fa62a170a85801da1a4324f04381167d + languageName: node + linkType: hard + +"body-parser@npm:^2.0.1": + version: 2.0.2 + resolution: "body-parser@npm:2.0.2" + dependencies: + bytes: 3.1.2 + content-type: ~1.0.5 + debug: 3.1.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.5.2 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: ^3.0.0 + type-is: ~1.6.18 + checksum: 24514663b0569f6d918e6111c6938950a91021d7816de41cd77775d3904a2ea32fffd35004eb3d7f0e1c10e73b7f683203420c4216b076ecf747be44be805175 languageName: node linkType: hard @@ -6173,7 +6350,7 @@ __metadata: languageName: node linkType: hard -"browserify-cipher@npm:^1.0.0": +"browserify-cipher@npm:^1.0.1": version: 1.0.1 resolution: "browserify-cipher@npm:1.0.1" dependencies: @@ -6197,16 +6374,17 @@ __metadata: linkType: hard "browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.1.0": - version: 4.1.0 - resolution: "browserify-rsa@npm:4.1.0" + version: 4.1.1 + resolution: "browserify-rsa@npm:4.1.1" dependencies: - bn.js: ^5.0.0 - randombytes: ^2.0.1 - checksum: 155f0c135873efc85620571a33d884aa8810e40176125ad424ec9d85016ff105a07f6231650914a760cca66f29af0494087947b7be34880dd4599a0cd3c38e54 + bn.js: ^5.2.1 + randombytes: ^2.1.0 + safe-buffer: ^5.2.1 + checksum: 2628508646331791c29312bbf274c076a237437a17178ea9bdc75c577fb4164a0da0b137deaadf6ade623701332377c5c2ceb0ff6f991c744a576e790ec95852 languageName: node linkType: hard -"browserify-sign@npm:^4.0.0": +"browserify-sign@npm:^4.2.3": version: 4.2.3 resolution: "browserify-sign@npm:4.2.3" dependencies: @@ -6247,17 +6425,17 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.12.0, browserslist@npm:^4.22.2, browserslist@npm:^4.23.0, browserslist@npm:^4.6.2, browserslist@npm:^4.6.4": - version: 4.23.0 - resolution: "browserslist@npm:4.23.0" +"browserslist@npm:^4.0.0, browserslist@npm:^4.12.0, browserslist@npm:^4.24.0, browserslist@npm:^4.24.2, browserslist@npm:^4.6.2, browserslist@npm:^4.6.4": + version: 4.24.2 + resolution: "browserslist@npm:4.24.2" dependencies: - caniuse-lite: ^1.0.30001587 - electron-to-chromium: ^1.4.668 - node-releases: ^2.0.14 - update-browserslist-db: ^1.0.13 + caniuse-lite: ^1.0.30001669 + electron-to-chromium: ^1.5.41 + node-releases: ^2.0.18 + update-browserslist-db: ^1.1.1 bin: browserslist: cli.js - checksum: 436f49e796782ca751ebab7edc010cfc9c29f68536f387666cd70ea22f7105563f04dd62c6ff89cb24cc3254d17cba385f979eeeb3484d43e012412ff7e75def + checksum: cf64085f12132d38638f38937a255edb82c7551b164a98577b055dd79719187a816112f7b97b9739e400c4954cd66479c0d7a843cb816e346f4795dc24fd5d97 languageName: node linkType: hard @@ -6362,13 +6540,6 @@ __metadata: languageName: node linkType: hard -"bytes@npm:3.0.0": - version: 3.0.0 - resolution: "bytes@npm:3.0.0" - checksum: a2b386dd8188849a5325f58eef69c3b73c51801c08ffc6963eddc9be244089ba32d19347caf6d145c86f315ae1b1fc7061a32b0c1aa6379e6a719090287ed101 - languageName: node - linkType: hard - "bytes@npm:3.1.2": version: 3.1.2 resolution: "bytes@npm:3.1.2" @@ -6433,8 +6604,8 @@ __metadata: linkType: hard "cacache@npm:^18.0.0": - version: 18.0.3 - resolution: "cacache@npm:18.0.3" + version: 18.0.4 + resolution: "cacache@npm:18.0.4" dependencies: "@npmcli/fs": ^3.1.0 fs-minipass: ^3.0.0 @@ -6448,7 +6619,7 @@ __metadata: ssri: ^10.0.0 tar: ^6.1.11 unique-filename: ^3.0.0 - checksum: b717fd9b36e9c3279bfde4545c3a8f6d5a539b084ee26a9504d48f83694beb724057d26e090b97540f9cc62bea18b9f6cf671c50e18fb7dac60eda9db691714f + checksum: b7422c113b4ec750f33beeca0f426a0024c28e3172f332218f48f963e5b970647fa1ac05679fe5bb448832c51efea9fda4456b9a95c3a1af1105fe6c1833cde2 languageName: node linkType: hard @@ -6550,10 +6721,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30000981, caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001125, caniuse-lite@npm:^1.0.30001587": - version: 1.0.30001629 - resolution: "caniuse-lite@npm:1.0.30001629" - checksum: c5e646e1b309b2a70b01499e0f0fca3a54bc111212f121b32614fe925b8f24ff6c1832a4306ddadf35678fbb11a6a97f953be07ccdc96bce5b530a4f84f40c45 +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30000981, caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001125, caniuse-lite@npm:^1.0.30001669": + version: 1.0.30001685 + resolution: "caniuse-lite@npm:1.0.30001685" + checksum: 5926f672d985b43b62825e971a12881c33ca1989d1b26fe3c0daf5a834b63c2470f7dd78b883fbd334b4b69c6a56e9893e14b58b86028a3de7a452a1ea6a58e4 languageName: node linkType: hard @@ -6585,8 +6756,8 @@ __metadata: linkType: hard "chai@npm:^4.3.7": - version: 4.4.1 - resolution: "chai@npm:4.4.1" + version: 4.5.0 + resolution: "chai@npm:4.5.0" dependencies: assertion-error: ^1.1.0 check-error: ^1.0.3 @@ -6594,8 +6765,8 @@ __metadata: get-func-name: ^2.0.2 loupe: ^2.3.6 pathval: ^1.1.1 - type-detect: ^4.0.8 - checksum: 9ab84f36eb8e0b280c56c6c21ca4da5933132cd8a0c89c384f1497f77953640db0bc151edd47f81748240a9fab57b78f7d925edfeedc8e8fc98016d71f40c36e + type-detect: ^4.1.0 + checksum: 70e5a8418a39e577e66a441cc0ce4f71fd551a650a71de30dd4e3e31e75ed1f5aa7119cf4baf4a2cb5e85c0c6befdb4d8a05811fad8738c1a6f3aa6a23803821 languageName: node linkType: hard @@ -6724,25 +6895,6 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:>=3.0.0 <4.0.0, chokidar@npm:^3.4.1, chokidar@npm:^3.4.2, chokidar@npm:^3.5.2, chokidar@npm:^3.5.3": - version: 3.6.0 - resolution: "chokidar@npm:3.6.0" - dependencies: - anymatch: ~3.1.2 - braces: ~3.0.2 - fsevents: ~2.3.2 - glob-parent: ~5.1.2 - is-binary-path: ~2.1.0 - is-glob: ~4.0.1 - normalize-path: ~3.0.0 - readdirp: ~3.6.0 - dependenciesMeta: - fsevents: - optional: true - checksum: d2f29f499705dcd4f6f3bbed79a9ce2388cf530460122eed3b9c48efeab7a4e28739c6551fd15bec9245c6b9eeca7a32baa64694d64d9b6faeb74ddb8c4a413d - languageName: node - linkType: hard - "chokidar@npm:^2.1.8": version: 2.1.8 resolution: "chokidar@npm:2.1.8" @@ -6762,7 +6914,35 @@ __metadata: dependenciesMeta: fsevents: optional: true - checksum: 0c43e89cbf0268ef1e1f41ce8ec5233c7ba022c6f3282c2ef6530e351d42396d389a1148c5a040f291cf1f4083a4c6b2f51dad3f31c726442ea9a337de316bcf + checksum: 0c43e89cbf0268ef1e1f41ce8ec5233c7ba022c6f3282c2ef6530e351d42396d389a1148c5a040f291cf1f4083a4c6b2f51dad3f31c726442ea9a337de316bcf + languageName: node + linkType: hard + +"chokidar@npm:^3.4.1, chokidar@npm:^3.4.2, chokidar@npm:^3.5.2, chokidar@npm:^3.5.3": + version: 3.6.0 + resolution: "chokidar@npm:3.6.0" + dependencies: + anymatch: ~3.1.2 + braces: ~3.0.2 + fsevents: ~2.3.2 + glob-parent: ~5.1.2 + is-binary-path: ~2.1.0 + is-glob: ~4.0.1 + normalize-path: ~3.0.0 + readdirp: ~3.6.0 + dependenciesMeta: + fsevents: + optional: true + checksum: d2f29f499705dcd4f6f3bbed79a9ce2388cf530460122eed3b9c48efeab7a4e28739c6551fd15bec9245c6b9eeca7a32baa64694d64d9b6faeb74ddb8c4a413d + languageName: node + linkType: hard + +"chokidar@npm:^4.0.0": + version: 4.0.1 + resolution: "chokidar@npm:4.0.1" + dependencies: + readdirp: ^4.0.1 + checksum: 193da9786b0422a895d59c7552195d15c6c636e6a2293ae43d09e34e243e24ccd02d693f007c767846a65abbeae5fea6bfacb8fc2ddec4ea4d397620d552010d languageName: node linkType: hard @@ -6802,12 +6982,12 @@ __metadata: linkType: hard "cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": - version: 1.0.4 - resolution: "cipher-base@npm:1.0.4" + version: 1.0.6 + resolution: "cipher-base@npm:1.0.6" dependencies: - inherits: ^2.0.1 - safe-buffer: ^5.0.1 - checksum: 47d3568dbc17431a339bad1fe7dff83ac0891be8206911ace3d3b818fc695f376df809bea406e759cdea07fff4b454fa25f1013e648851bec790c1d75763032e + inherits: ^2.0.4 + safe-buffer: ^5.2.1 + checksum: 64a1738a8583163cf096bc85321a69ef3075bb0873f34cf89dc705e62b9eee058dd6b2e5c672f774ede0b6bdbe56fe7b710e0d38c4f08a2f355d8ab828f05c6f languageName: node linkType: hard @@ -7077,7 +7257,7 @@ __metadata: languageName: node linkType: hard -"compressible@npm:~2.0.16": +"compressible@npm:~2.0.18": version: 2.0.18 resolution: "compressible@npm:2.0.18" dependencies: @@ -7087,17 +7267,17 @@ __metadata: linkType: hard "compression@npm:^1.7.4": - version: 1.7.4 - resolution: "compression@npm:1.7.4" + version: 1.7.5 + resolution: "compression@npm:1.7.5" dependencies: - accepts: ~1.3.5 - bytes: 3.0.0 - compressible: ~2.0.16 + bytes: 3.1.2 + compressible: ~2.0.18 debug: 2.6.9 + negotiator: ~0.6.4 on-headers: ~1.0.2 - safe-buffer: 5.1.2 + safe-buffer: 5.2.1 vary: ~1.1.2 - checksum: 35c0f2eb1f28418978615dc1bc02075b34b1568f7f56c62d60f4214d4b7cc00d0f6d282b5f8a954f59872396bd770b6b15ffd8aa94c67d4bce9b8887b906999b + checksum: d624b5562492518eee82c4f1381ea36f69f1f10b4283bfc2dcafd7d4d7eeed17c3f0e8f2951798594b7064db7ac5a6198df34816bde2d56bb7c75ce1570880e9 languageName: node linkType: hard @@ -7151,10 +7331,10 @@ __metadata: languageName: node linkType: hard -"confbox@npm:^0.1.7": - version: 0.1.7 - resolution: "confbox@npm:0.1.7" - checksum: bde836c26f5154a348b0c0a757f8a0138929e5737e0553be3c4f07a056abca618b861aa63ac3b22d344789b56be99a1382928933e08cd500df00213bf4d8fb43 +"confbox@npm:^0.1.8": + version: 0.1.8 + resolution: "confbox@npm:0.1.8" + checksum: 5c7718ab22cf9e35a31c21ef124156076ae8c9dc65e6463d54961caf5a1d529284485a0fdf83fd23b27329f3b75b0c8c07d2e36c699f5151a2efe903343f976a languageName: node linkType: hard @@ -7206,7 +7386,16 @@ __metadata: languageName: node linkType: hard -"content-type@npm:~1.0.4, content-type@npm:~1.0.5": +"content-disposition@npm:^1.0.0": + version: 1.0.0 + resolution: "content-disposition@npm:1.0.0" + dependencies: + safe-buffer: 5.2.1 + checksum: b27e2579fefe0ecf78238bb652fbc750671efce8344f0c6f05235b12433e6a965adb40906df1ac1fdde23e8f9f0e58385e44640e633165420f3f47d830ae0398 + languageName: node + linkType: hard + +"content-type@npm:^1.0.5, content-type@npm:~1.0.4, content-type@npm:~1.0.5": version: 1.0.5 resolution: "content-type@npm:1.0.5" checksum: 566271e0a251642254cde0f845f9dd4f9856e52d988f4eb0d0dcffbb7a1f8ec98de7a5215fc628f3bce30fe2fb6fd2bc064b562d721658c59b544e2d34ea2766 @@ -7244,12 +7433,12 @@ __metadata: linkType: hard "cookie-parser@npm:^1.4.5": - version: 1.4.6 - resolution: "cookie-parser@npm:1.4.6" + version: 1.4.7 + resolution: "cookie-parser@npm:1.4.7" dependencies: - cookie: 0.4.1 + cookie: 0.7.2 cookie-signature: 1.0.6 - checksum: 1e5a63aa82e8eb4e02d2977c6902983dee87b02e87ec5ec43ac3cb1e72da354003716570cd5190c0ad9e8a454c9d3237f4ad6e2f16d0902205a96a1c72b77ba5 + checksum: 243fa13f217e793d20a57675e6552beea08c5989fcc68495d543997a31646875335e0e82d687b42dcfd466df57891d22bae7f5ba6ab33b7705ed2dd6eb989105 languageName: node linkType: hard @@ -7260,17 +7449,24 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.4.1": - version: 0.4.1 - resolution: "cookie@npm:0.4.1" - checksum: bd7c47f5d94ab70ccdfe8210cde7d725880d2fcda06d8e375afbdd82de0c8d3b73541996e9ce57d35f67f672c4ee6d60208adec06b3c5fc94cebb85196084cf8 +"cookie-signature@npm:^1.2.1": + version: 1.2.2 + resolution: "cookie-signature@npm:1.2.2" + checksum: 1ad4f9b3907c9f3673a0f0a07c0a23da7909ac6c9204c5d80a0ec102fe50ccc45f27fdf496361840d6c132c5bb0037122c0a381f856d070183d1ebe3e5e041ff languageName: node linkType: hard -"cookie@npm:0.6.0": - version: 0.6.0 - resolution: "cookie@npm:0.6.0" - checksum: f56a7d32a07db5458e79c726b77e3c2eff655c36792f2b6c58d351fb5f61531e5b1ab7f46987150136e366c65213cbe31729e02a3eaed630c3bf7334635fb410 +"cookie@npm:0.7.1": + version: 0.7.1 + resolution: "cookie@npm:0.7.1" + checksum: cec5e425549b3650eb5c3498a9ba3cde0b9cd419e3b36e4b92739d30b4d89e0b678b98c1ddc209ce7cf958cd3215671fd6ac47aec21f10c2a0cc68abd399d8a7 + languageName: node + linkType: hard + +"cookie@npm:0.7.2": + version: 0.7.2 + resolution: "cookie@npm:0.7.2" + checksum: 9bf8555e33530affd571ea37b615ccad9b9a34febbf2c950c86787088eb00a8973690833b0f8ebd6b69b753c62669ea60cec89178c1fb007bf0749abed74f93e languageName: node linkType: hard @@ -7309,19 +7505,19 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.36.1": - version: 3.37.1 - resolution: "core-js-compat@npm:3.37.1" +"core-js-compat@npm:^3.38.0, core-js-compat@npm:^3.38.1": + version: 3.39.0 + resolution: "core-js-compat@npm:3.39.0" dependencies: - browserslist: ^4.23.0 - checksum: 5e7430329358bced08c30950512d2081aea0a5652b4c5892cbb3c4a6db05b0d3893a191a955162a07fdb5f4fe74e61b6429fdb503f54e062336d76e43c9555d9 + browserslist: ^4.24.2 + checksum: 2d7d087c3271d711d03a55203d4756f6288317a1ce35cdc8bafaf1833ef21fd67a92a50cff8dcf7df1325ac63720906ab3cf514c85b238c95f65fca1040f6ad6 languageName: node linkType: hard "core-js-pure@npm:^3.30.2": - version: 3.37.1 - resolution: "core-js-pure@npm:3.37.1" - checksum: a13a40e3951975cffef12a0933d3dbf1ecedbf9821e1ec8024884b587744951ad30e3762a86bcb8e2a18fdd4b8d7c8971b2391605329799fc04e1fc1e1397dc1 + version: 3.39.0 + resolution: "core-js-pure@npm:3.39.0" + checksum: cdcb1eec4eb9308fcf5cfe18a95322c388b05c11e66b5b0ac296a08f8f2106b458ecfe8aca0155d62ed2c5e150485b68073937e7b0a563fbc287563c4475a7c1 languageName: node linkType: hard @@ -7333,9 +7529,9 @@ __metadata: linkType: hard "core-js@npm:^3.6.5": - version: 3.37.1 - resolution: "core-js@npm:3.37.1" - checksum: 2d58a5c599f05c3e04abc8bc5e64b88eb17d914c0f552f670fb800afa74ec54b4fcc7f231ad6bd45badaf62c0fb0ce30e6fe89cedb6bb6d54e6f19115c3c17ff + version: 3.39.0 + resolution: "core-js@npm:3.39.0" + checksum: 7a3670e9a2a89e0a049daa288d742d09f6e16d27a8945c5e2ef6fc45dc57e5c4bc5db589da05947486f54ae978d14cf27bd3fb1db0b9907000a611e8af37355b languageName: node linkType: hard @@ -7381,7 +7577,7 @@ __metadata: languageName: node linkType: hard -"create-ecdh@npm:^4.0.0": +"create-ecdh@npm:^4.0.4": version: 4.0.4 resolution: "create-ecdh@npm:4.0.4" dependencies: @@ -7404,7 +7600,7 @@ __metadata: languageName: node linkType: hard -"create-hmac@npm:^1.1.0, create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": +"create-hmac@npm:^1.1.4, create-hmac@npm:^1.1.7": version: 1.1.7 resolution: "create-hmac@npm:1.1.7" dependencies: @@ -7425,7 +7621,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:7.0.3, cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2": +"cross-spawn@npm:7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" dependencies: @@ -7437,34 +7633,46 @@ __metadata: linkType: hard "cross-spawn@npm:^6.0.0": - version: 6.0.5 - resolution: "cross-spawn@npm:6.0.5" + version: 6.0.6 + resolution: "cross-spawn@npm:6.0.6" dependencies: nice-try: ^1.0.4 path-key: ^2.0.1 semver: ^5.5.0 shebang-command: ^1.2.0 which: ^1.2.9 - checksum: f893bb0d96cd3d5751d04e67145bdddf25f99449531a72e82dcbbd42796bbc8268c1076c6b3ea51d4d455839902804b94bc45dfb37ecbb32ea8e54a6741c3ab9 + checksum: a6e2e5b04a0e0f806c1df45f92cd079b65f95fbe5a7650ee1ab60318c33a6c156a8a2f8b6898f57764f7363ec599a0625e9855dfa78d52d2d73dbd32eb11c25e + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2": + version: 7.0.6 + resolution: "cross-spawn@npm:7.0.6" + dependencies: + path-key: ^3.1.0 + shebang-command: ^2.0.0 + which: ^2.0.1 + checksum: 8d306efacaf6f3f60e0224c287664093fa9185680b2d195852ba9a863f85d02dcc737094c6e512175f8ee0161f9b87c73c6826034c2422e39de7d6569cf4503b languageName: node linkType: hard "crypto-browserify@npm:^3.11.0": - version: 3.12.0 - resolution: "crypto-browserify@npm:3.12.0" + version: 3.12.1 + resolution: "crypto-browserify@npm:3.12.1" dependencies: - browserify-cipher: ^1.0.0 - browserify-sign: ^4.0.0 - create-ecdh: ^4.0.0 - create-hash: ^1.1.0 - create-hmac: ^1.1.0 - diffie-hellman: ^5.0.0 - inherits: ^2.0.1 - pbkdf2: ^3.0.3 - public-encrypt: ^4.0.0 - randombytes: ^2.0.0 - randomfill: ^1.0.3 - checksum: c1609af82605474262f3eaa07daa0b2140026bd264ab316d4bf1170272570dbe02f0c49e29407fe0d3634f96c507c27a19a6765fb856fed854a625f9d15618e2 + browserify-cipher: ^1.0.1 + browserify-sign: ^4.2.3 + create-ecdh: ^4.0.4 + create-hash: ^1.2.0 + create-hmac: ^1.1.7 + diffie-hellman: ^5.0.3 + hash-base: ~3.0.4 + inherits: ^2.0.4 + pbkdf2: ^3.1.2 + public-encrypt: ^4.0.3 + randombytes: ^2.1.0 + randomfill: ^1.0.4 + checksum: 4e643dd5acfff80fbe2cc567feb75a22d726cc4df34772c988f326976c3c1ee1f8a611a33498dab11568cff3e134f0bd44a0e1f4c216585e5877ab5327cdb6fc languageName: node linkType: hard @@ -7897,9 +8105,9 @@ __metadata: linkType: hard "dayjs@npm:^1.11.10": - version: 1.11.11 - resolution: "dayjs@npm:1.11.11" - checksum: 84788275aad8a87fee4f1ce4be08861df29687aae6b7b43dd65350118a37dda56772a3902f802cb2dc651dfed447a5a8df62d88f0fb900dba8333e411190a5d5 + version: 1.11.13 + resolution: "dayjs@npm:1.11.13" + checksum: f388db88a6aa93956c1f6121644e783391c7b738b73dbc54485578736565c8931bdfba4bb94e9b1535c6e509c97d5deb918bbe1ae6b34358d994de735055cca9 languageName: node linkType: hard @@ -7910,7 +8118,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:2.6.9, debug@npm:^2.2.0, debug@npm:^2.3.3, debug@npm:^2.6.0": +"debug@npm:2.6.9, debug@npm:^2.2.0, debug@npm:^2.3.3, debug@npm:^2.6.0, debug@npm:^2.6.1": version: 2.6.9 resolution: "debug@npm:2.6.9" dependencies: @@ -7919,15 +8127,36 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.0.1, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.3, debug@npm:^4.3.4": - version: 4.3.5 - resolution: "debug@npm:4.3.5" +"debug@npm:3.1.0": + version: 3.1.0 + resolution: "debug@npm:3.1.0" + dependencies: + ms: 2.0.0 + checksum: 0b52718ab957254a5b3ca07fc34543bc778f358620c206a08452251eb7fc193c3ea3505072acbf4350219c14e2d71ceb7bdaa0d3370aa630b50da790458d08b3 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.0.1, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:^4.3.5": + version: 4.3.7 + resolution: "debug@npm:4.3.7" + dependencies: + ms: ^2.1.3 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 822d74e209cd910ef0802d261b150314bbcf36c582ccdbb3e70f0894823c17e49a50d3e66d96b633524263975ca16b6a833f3e3b7e030c157169a5fabac63160 + languageName: node + linkType: hard + +"debug@npm:4.3.6": + version: 4.3.6 + resolution: "debug@npm:4.3.6" dependencies: ms: 2.1.2 peerDependenciesMeta: supports-color: optional: true - checksum: 7c002b51e256257f936dda09eb37167df952758c57badf6bf44bdc40b89a4bcb8e5a0a2e4c7b53f97c69e2970dd5272d33a757378a12c8f8e64ea7bf99e8e86e + checksum: 1630b748dea3c581295e02137a9f5cbe2c1d85fea35c1e6597a65ca2b16a6fce68cec61b299d480787ef310ba927dc8c92d3061faba0ad06c6a724672f66be7f languageName: node linkType: hard @@ -8136,13 +8365,6 @@ __metadata: languageName: node linkType: hard -"dequal@npm:^2.0.3": - version: 2.0.3 - resolution: "dequal@npm:2.0.3" - checksum: 8679b850e1a3d0ebbc46ee780d5df7b478c23f335887464023a631d1b9af051ad4a6595a44220f9ff8ff95a8ddccf019b5ad778a976fd7bbf77383d36f412f90 - languageName: node - linkType: hard - "des.js@npm:^1.0.0": version: 1.1.0 resolution: "des.js@npm:1.1.0" @@ -8153,13 +8375,22 @@ __metadata: languageName: node linkType: hard -"destroy@npm:1.2.0": +"destroy@npm:1.2.0, destroy@npm:^1.2.0": version: 1.2.0 resolution: "destroy@npm:1.2.0" checksum: 0acb300b7478a08b92d810ab229d5afe0d2f4399272045ab22affa0d99dbaf12637659411530a6fcd597a9bdac718fc94373a61a95b4651bbc7b83684a565e38 languageName: node linkType: hard +"detect-libc@npm:^1.0.3": + version: 1.0.3 + resolution: "detect-libc@npm:1.0.3" + bin: + detect-libc: ./bin/detect-libc.js + checksum: daaaed925ffa7889bd91d56e9624e6c8033911bb60f3a50a74a87500680652969dbaab9526d1e200a4c94acf80fc862a22131841145a0a8482d60a99c24f4a3e + languageName: node + linkType: hard + "detect-newline@npm:^3.0.0": version: 3.1.0 resolution: "detect-newline@npm:3.1.0" @@ -8225,7 +8456,7 @@ __metadata: languageName: node linkType: hard -"diffie-hellman@npm:^5.0.0": +"diffie-hellman@npm:^5.0.3": version: 5.0.3 resolution: "diffie-hellman@npm:5.0.3" dependencies: @@ -8485,16 +8716,16 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.3.564, electron-to-chromium@npm:^1.4.668": - version: 1.4.796 - resolution: "electron-to-chromium@npm:1.4.796" - checksum: 29829ba285b2bb765e3abb82023b006f1d214333d045ab434b2c6be964c5ce0a761e992bd9eab09f51ac2b31712a5b003ed34cf891a627bf80f37e79ccddd6ac +"electron-to-chromium@npm:^1.3.564, electron-to-chromium@npm:^1.5.41": + version: 1.5.67 + resolution: "electron-to-chromium@npm:1.5.67" + checksum: 553a1cde45ea11bab5cbfbdb2be041f1512d3edcb15f73694b340b43a001322c371655bae61ba1141a5bc282ac8dd3bacb7e49b2d320d326c0931321a623cac7 languageName: node linkType: hard "elliptic@npm:^6.5.3, elliptic@npm:^6.5.5": - version: 6.5.5 - resolution: "elliptic@npm:6.5.5" + version: 6.6.1 + resolution: "elliptic@npm:6.6.1" dependencies: bn.js: ^4.11.9 brorand: ^1.1.0 @@ -8503,7 +8734,7 @@ __metadata: inherits: ^2.0.4 minimalistic-assert: ^1.0.1 minimalistic-crypto-utils: ^1.0.1 - checksum: ec9105e4469eb3b32b0ee2579756c888ddf3f99d259aa0d65fccb906ee877768aaf8880caae73e3e669c9a4adeb3eb1945703aa974ec5000d2d33a239f4567eb + checksum: 27b14a52f68bbbc0720da259f712cb73e953f6d2047958cd02fb0d0ade2e83849dc39fb4af630889c67df8817e24237428cf59c4f4c07700f755b401149a7375 languageName: node linkType: hard @@ -8542,6 +8773,13 @@ __metadata: languageName: node linkType: hard +"encodeurl@npm:^2.0.0, encodeurl@npm:~2.0.0": + version: 2.0.0 + resolution: "encodeurl@npm:2.0.0" + checksum: abf5cd51b78082cf8af7be6785813c33b6df2068ce5191a40ca8b1afe6a86f9230af9a9ce694a5ce4665955e5c1120871826df9c128a642e09c58d592e2807fe + languageName: node + linkType: hard + "encodeurl@npm:~1.0.2": version: 1.0.2 resolution: "encodeurl@npm:1.0.2" @@ -8638,9 +8876,9 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.17.2, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.1, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3": - version: 1.23.3 - resolution: "es-abstract@npm:1.23.3" +"es-abstract@npm:^1.17.2, es-abstract@npm:^1.17.5, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5": + version: 1.23.5 + resolution: "es-abstract@npm:1.23.5" dependencies: array-buffer-byte-length: ^1.0.1 arraybuffer.prototype.slice: ^1.0.3 @@ -8657,7 +8895,7 @@ __metadata: function.prototype.name: ^1.1.6 get-intrinsic: ^1.2.4 get-symbol-description: ^1.0.2 - globalthis: ^1.0.3 + globalthis: ^1.0.4 gopd: ^1.0.1 has-property-descriptors: ^1.0.2 has-proto: ^1.0.3 @@ -8673,10 +8911,10 @@ __metadata: is-string: ^1.0.7 is-typed-array: ^1.1.13 is-weakref: ^1.0.2 - object-inspect: ^1.13.1 + object-inspect: ^1.13.3 object-keys: ^1.1.1 object.assign: ^4.1.5 - regexp.prototype.flags: ^1.5.2 + regexp.prototype.flags: ^1.5.3 safe-array-concat: ^1.1.2 safe-regex-test: ^1.0.3 string.prototype.trim: ^1.2.9 @@ -8688,7 +8926,7 @@ __metadata: typed-array-length: ^1.0.6 unbox-primitive: ^1.0.2 which-typed-array: ^1.1.15 - checksum: f840cf161224252512f9527306b57117192696571e07920f777cb893454e32999206198b4f075516112af6459daca282826d1735c450528470356d09eff3a9ae + checksum: 17c81f8a42f0322fd11e0025d3c2229ecfd7923560c710906b8e68660e19c42322750dcedf8ba5cf28bae50d5befd8174d3903ac50dbabb336d3efc3aabed2ee languageName: node linkType: hard @@ -8732,9 +8970,9 @@ __metadata: languageName: node linkType: hard -"es-iterator-helpers@npm:^1.0.15, es-iterator-helpers@npm:^1.0.19": - version: 1.0.19 - resolution: "es-iterator-helpers@npm:1.0.19" +"es-iterator-helpers@npm:^1.1.0": + version: 1.2.0 + resolution: "es-iterator-helpers@npm:1.2.0" dependencies: call-bind: ^1.0.7 define-properties: ^1.2.1 @@ -8743,14 +8981,15 @@ __metadata: es-set-tostringtag: ^2.0.3 function-bind: ^1.1.2 get-intrinsic: ^1.2.4 - globalthis: ^1.0.3 + globalthis: ^1.0.4 + gopd: ^1.0.1 has-property-descriptors: ^1.0.2 has-proto: ^1.0.3 has-symbols: ^1.0.3 internal-slot: ^1.0.7 - iterator.prototype: ^1.1.2 + iterator.prototype: ^1.1.3 safe-array-concat: ^1.1.2 - checksum: 7ae112b88359fbaf4b9d7d1d1358ae57c5138768c57ba3a8fb930393662653b0512bfd7917c15890d1471577fb012fee8b73b4465e59b331739e6ee94f961683 + checksum: c5f5ff10d57f956539581aca7a2d8726c5a8a3e49e6285700d74dcd8b64c7a337b9ab5e81b459b079dac745d2fe02e4f6b80a842e3df45d9cfe3f12325fda8c0 languageName: node linkType: hard @@ -8784,13 +9023,13 @@ __metadata: linkType: hard "es-to-primitive@npm:^1.2.1": - version: 1.2.1 - resolution: "es-to-primitive@npm:1.2.1" + version: 1.3.0 + resolution: "es-to-primitive@npm:1.3.0" dependencies: - is-callable: ^1.1.4 - is-date-object: ^1.0.1 - is-symbol: ^1.0.2 - checksum: 4ead6671a2c1402619bdd77f3503991232ca15e17e46222b0a41a5d81aebc8740a77822f5b3c965008e631153e9ef0580540007744521e72de8e33599fca2eed + is-callable: ^1.2.7 + is-date-object: ^1.0.5 + is-symbol: ^1.0.4 + checksum: 966965880356486cd4d1fe9a523deda2084c81b3702d951212c098f5f2ee93605d1b7c1840062efb48a07d892641c7ed1bc194db563645c0dd2b919cb6d65b93 languageName: node linkType: hard @@ -9118,14 +9357,14 @@ __metadata: languageName: node linkType: hard -"escalade@npm:^3.0.2, escalade@npm:^3.1.1, escalade@npm:^3.1.2": - version: 3.1.2 - resolution: "escalade@npm:3.1.2" - checksum: 1ec0977aa2772075493002bdbd549d595ff6e9393b1cb0d7d6fcaf78c750da0c158f180938365486f75cb69fba20294351caddfce1b46552a7b6c3cde52eaa02 +"escalade@npm:^3.0.2, escalade@npm:^3.1.1, escalade@npm:^3.2.0": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 47b029c83de01b0d17ad99ed766347b974b0d628e848de404018f3abee728e987da0d2d370ad4574aa3d5b5bfc368754fd085d69a30f8e75903486ec4b5b709e languageName: node linkType: hard -"escape-html@npm:~1.0.3": +"escape-html@npm:^1.0.3, escape-html@npm:~1.0.3": version: 1.0.3 resolution: "escape-html@npm:1.0.3" checksum: 6213ca9ae00d0ab8bccb6d8d4e0a98e76237b2410302cf7df70aaa6591d509a2a37ce8998008cbecae8fc8ffaadf3fb0229535e6a145f3ce0b211d060decbb24 @@ -9262,15 +9501,15 @@ __metadata: languageName: node linkType: hard -"eslint-module-utils@npm:^2.8.0": - version: 2.8.1 - resolution: "eslint-module-utils@npm:2.8.1" +"eslint-module-utils@npm:^2.12.0": + version: 2.12.0 + resolution: "eslint-module-utils@npm:2.12.0" dependencies: debug: ^3.2.7 peerDependenciesMeta: eslint: optional: true - checksum: 3cecd99b6baf45ffc269167da0f95dcb75e5aa67b93d73a3bab63e2a7eedd9cdd6f188eed048e2f57c1b77db82c9cbf2adac20b512fa70e597d863dd3720170d + checksum: be3ac52e0971c6f46daeb1a7e760e45c7c45f820c8cc211799f85f10f04ccbf7afc17039165d56cb2da7f7ca9cec2b3a777013cddf0b976784b37eb9efa24180 languageName: node linkType: hard @@ -9312,29 +9551,31 @@ __metadata: linkType: hard "eslint-plugin-import@npm:^2.22.1, eslint-plugin-import@npm:^2.25.3": - version: 2.29.1 - resolution: "eslint-plugin-import@npm:2.29.1" + version: 2.31.0 + resolution: "eslint-plugin-import@npm:2.31.0" dependencies: - array-includes: ^3.1.7 - array.prototype.findlastindex: ^1.2.3 + "@rtsao/scc": ^1.1.0 + array-includes: ^3.1.8 + array.prototype.findlastindex: ^1.2.5 array.prototype.flat: ^1.3.2 array.prototype.flatmap: ^1.3.2 debug: ^3.2.7 doctrine: ^2.1.0 eslint-import-resolver-node: ^0.3.9 - eslint-module-utils: ^2.8.0 - hasown: ^2.0.0 - is-core-module: ^2.13.1 + eslint-module-utils: ^2.12.0 + hasown: ^2.0.2 + is-core-module: ^2.15.1 is-glob: ^4.0.3 minimatch: ^3.1.2 - object.fromentries: ^2.0.7 - object.groupby: ^1.0.1 - object.values: ^1.1.7 + object.fromentries: ^2.0.8 + object.groupby: ^1.0.3 + object.values: ^1.2.0 semver: ^6.3.1 + string.prototype.trimend: ^1.0.8 tsconfig-paths: ^3.15.0 peerDependencies: - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: e65159aef808136d26d029b71c8c6e4cb5c628e65e5de77f1eb4c13a379315ae55c9c3afa847f43f4ff9df7e54515c77ffc6489c6a6f81f7dd7359267577468c + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + checksum: b1d2ac268b3582ff1af2a72a2c476eae4d250c100f2e335b6e102036e4a35efa530b80ec578dfc36761fabb34a635b9bf5ab071abe9d4404a4bb054fdf22d415 languageName: node linkType: hard @@ -9371,28 +9612,27 @@ __metadata: linkType: hard "eslint-plugin-jsx-a11y@npm:^6.3.1, eslint-plugin-jsx-a11y@npm:^6.5.1": - version: 6.8.0 - resolution: "eslint-plugin-jsx-a11y@npm:6.8.0" + version: 6.10.2 + resolution: "eslint-plugin-jsx-a11y@npm:6.10.2" dependencies: - "@babel/runtime": ^7.23.2 - aria-query: ^5.3.0 - array-includes: ^3.1.7 + aria-query: ^5.3.2 + array-includes: ^3.1.8 array.prototype.flatmap: ^1.3.2 ast-types-flow: ^0.0.8 - axe-core: =4.7.0 - axobject-query: ^3.2.1 + axe-core: ^4.10.0 + axobject-query: ^4.1.0 damerau-levenshtein: ^1.0.8 emoji-regex: ^9.2.2 - es-iterator-helpers: ^1.0.15 - hasown: ^2.0.0 + hasown: ^2.0.2 jsx-ast-utils: ^3.3.5 language-tags: ^1.0.9 minimatch: ^3.1.2 - object.entries: ^1.1.7 - object.fromentries: ^2.0.7 + object.fromentries: ^2.0.8 + safe-regex-test: ^1.0.3 + string.prototype.includes: ^2.0.1 peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: 3dec00e2a3089c4c61ac062e4196a70985fb7eda1fd67fe035363d92578debde92fdb8ed2e472321fc0d71e75f4a1e8888c6a3218c14dd93c8e8d19eb6f51554 + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + checksum: 0cc861398fa26ada61ed5703eef5b335495fcb96253263dcd5e399488ff019a2636372021baacc040e3560d1a34bfcd5d5ad9f1754f44cd0509c956f7df94050 languageName: node linkType: hard @@ -9421,30 +9661,30 @@ __metadata: linkType: hard "eslint-plugin-react@npm:^7.21.5, eslint-plugin-react@npm:^7.27.1": - version: 7.34.2 - resolution: "eslint-plugin-react@npm:7.34.2" + version: 7.37.2 + resolution: "eslint-plugin-react@npm:7.37.2" dependencies: array-includes: ^3.1.8 array.prototype.findlast: ^1.2.5 array.prototype.flatmap: ^1.3.2 - array.prototype.toreversed: ^1.1.2 - array.prototype.tosorted: ^1.1.3 + array.prototype.tosorted: ^1.1.4 doctrine: ^2.1.0 - es-iterator-helpers: ^1.0.19 + es-iterator-helpers: ^1.1.0 estraverse: ^5.3.0 + hasown: ^2.0.2 jsx-ast-utils: ^2.4.1 || ^3.0.0 minimatch: ^3.1.2 object.entries: ^1.1.8 object.fromentries: ^2.0.8 - object.hasown: ^1.1.4 object.values: ^1.2.0 prop-types: ^15.8.1 resolve: ^2.0.0-next.5 semver: ^6.3.1 string.prototype.matchall: ^4.0.11 + string.prototype.repeat: ^1.0.0 peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - checksum: aed331239f3a64fcd884380534ece4b8716f1eca4899c8636d04306879e6b4e7339e28e427bdd571d372b78b713025e0767e5f5b5486a8d19bff82616ebe8959 + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + checksum: 7f5203afee7fbe3702b27fdd2b9a3c0ccbbb47d0672f58311b9d8a08dea819c9da4a87c15e8bd508f2562f327a9d29ee8bd9cd189bf758d8dc903de5648b0bfa languageName: node linkType: hard @@ -9524,7 +9764,7 @@ __metadata: languageName: node linkType: hard -"eslint-visitor-keys@npm:^3.3.0": +"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.3": version: 3.4.3 resolution: "eslint-visitor-keys@npm:3.4.3" checksum: 36e9ef87fca698b6fd7ca5ca35d7b2b6eeaaf106572e2f7fd31c12d3bfdaccdb587bba6d3621067e5aece31c8c3a348b93922ab8f7b2cbc6aaab5e1d89040c60 @@ -9642,11 +9882,11 @@ __metadata: linkType: hard "esquery@npm:^1.4.0": - version: 1.5.0 - resolution: "esquery@npm:1.5.0" + version: 1.6.0 + resolution: "esquery@npm:1.6.0" dependencies: estraverse: ^5.1.0 - checksum: aefb0d2596c230118656cd4ec7532d447333a410a48834d80ea648b1e7b5c9bc9ed8b5e33a89cb04e487b60d622f44cf5713bf4abed7c97343edefdc84a35900 + checksum: 08ec4fe446d9ab27186da274d979558557fbdbbd10968fa9758552482720c54152a5640e08b9009e5a30706b66aba510692054d4129d32d0e12e05bbc0b96fb2 languageName: node linkType: hard @@ -9694,7 +9934,7 @@ __metadata: languageName: node linkType: hard -"etag@npm:~1.8.1": +"etag@npm:^1.8.1, etag@npm:~1.8.1": version: 1.8.1 resolution: "etag@npm:1.8.1" checksum: 571aeb3dbe0f2bbd4e4fadbdb44f325fc75335cd5f6f6b6a091e6a06a9f25ed5392f0863c5442acb0646787446e816f13cbfc6edce5b07658541dff573cab1ff @@ -9859,13 +10099,13 @@ __metadata: linkType: hard "express-jwt@npm:^7.7.5": - version: 7.7.7 - resolution: "express-jwt@npm:7.7.7" + version: 7.7.8 + resolution: "express-jwt@npm:7.7.8" dependencies: "@types/jsonwebtoken": ^8.5.8 express-unless: ^2.1.3 - jsonwebtoken: ^8.5.1 - checksum: b3aec510ce490cd8d449604c82ce1debf9b8c215fb0220f78d07e86c555fb06ca93b4199da135c00e62bb98c67a47fac8c1fdcc6ea74f2047f4e2defbc4578fe + jsonwebtoken: ^9.0.2 + checksum: 88ea57e7c033bafd5918cdbddd67f469a3e70f9ae3c5c973b370ef0b9f86e3499ea132fb15d9ecdddcc97d8305dec1f759a1fdf4dfc8a1a9e6642e166188e28b languageName: node linkType: hard @@ -9886,42 +10126,121 @@ __metadata: languageName: node linkType: hard +"express@npm:^4.0.0": + version: 4.21.2 + resolution: "express@npm:4.21.2" + dependencies: + accepts: ~1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: ~1.0.4 + cookie: 0.7.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: ~2.0.0 + escape-html: ~1.0.3 + etag: ~1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: ~1.1.2 + on-finished: 2.4.1 + parseurl: ~1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: ~2.0.7 + qs: 6.13.0 + range-parser: ~1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: ~1.6.18 + utils-merge: 1.0.1 + vary: ~1.1.2 + checksum: 3aef1d355622732e20b8f3a7c112d4391d44e2131f4f449e1f273a309752a41abfad714e881f177645517cbe29b3ccdc10b35e7e25c13506114244a5b72f549d + languageName: node + linkType: hard + "express@npm:^4.17.1": - version: 4.19.2 - resolution: "express@npm:4.19.2" + version: 4.21.1 + resolution: "express@npm:4.21.1" dependencies: accepts: ~1.3.8 array-flatten: 1.1.1 - body-parser: 1.20.2 + body-parser: 1.20.3 content-disposition: 0.5.4 content-type: ~1.0.4 - cookie: 0.6.0 + cookie: 0.7.1 cookie-signature: 1.0.6 debug: 2.6.9 depd: 2.0.0 - encodeurl: ~1.0.2 + encodeurl: ~2.0.0 escape-html: ~1.0.3 etag: ~1.8.1 - finalhandler: 1.2.0 + finalhandler: 1.3.1 fresh: 0.5.2 http-errors: 2.0.0 - merge-descriptors: 1.0.1 + merge-descriptors: 1.0.3 methods: ~1.1.2 on-finished: 2.4.1 parseurl: ~1.3.3 - path-to-regexp: 0.1.7 + path-to-regexp: 0.1.10 proxy-addr: ~2.0.7 - qs: 6.11.0 + qs: 6.13.0 range-parser: ~1.2.1 safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 + send: 0.19.0 + serve-static: 1.16.2 setprototypeof: 1.2.0 statuses: 2.0.1 type-is: ~1.6.18 utils-merge: 1.0.1 vary: ~1.1.2 - checksum: 212dbd6c2c222a96a61bc927639c95970a53b06257080bb9e2838adb3bffdb966856551fdad1ab5dd654a217c35db94f987d0aa88d48fb04d306340f5f34dca5 + checksum: 5ac2b26d8aeddda5564fc0907227d29c100f90c0ead2ead9d474dc5108e8fb306c2de2083c4e3ba326e0906466f2b73417dbac16961f4075ff9f03785fd940fe + languageName: node + linkType: hard + +"express@npm:^5.0.0": + version: 5.0.1 + resolution: "express@npm:5.0.1" + dependencies: + accepts: ^2.0.0 + body-parser: ^2.0.1 + content-disposition: ^1.0.0 + content-type: ~1.0.4 + cookie: 0.7.1 + cookie-signature: ^1.2.1 + debug: 4.3.6 + depd: 2.0.0 + encodeurl: ~2.0.0 + escape-html: ~1.0.3 + etag: ~1.8.1 + finalhandler: ^2.0.0 + fresh: 2.0.0 + http-errors: 2.0.0 + merge-descriptors: ^2.0.0 + methods: ~1.1.2 + mime-types: ^3.0.0 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: ~1.3.3 + proxy-addr: ~2.0.7 + qs: 6.13.0 + range-parser: ~1.2.1 + router: ^2.0.0 + safe-buffer: 5.2.1 + send: ^1.1.0 + serve-static: ^2.1.0 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: ^2.0.0 + utils-merge: 1.0.1 + vary: ~1.1.2 + checksum: d1a3e934a2e3c5d7491049dabbedf6290e942b081a76e88598f3b0870ae53d4177c116ab5056bdbb32fc3cf556d3388362b689d06b73aaba7de67c2af29fd25b languageName: node linkType: hard @@ -10042,6 +10361,13 @@ __metadata: languageName: node linkType: hard +"fast-uri@npm:^3.0.1": + version: 3.0.3 + resolution: "fast-uri@npm:3.0.3" + checksum: c52e6c86465f5c240e84a4485fb001088cc743d261a4b54b0050ce4758b1648bdbe53da1328ef9620149dca1435e3de64184f226d7c0a3656cb5837b3491e149 + languageName: node + linkType: hard + "fastparse@npm:^1.1.2": version: 1.1.2 resolution: "fastparse@npm:1.1.2" @@ -10155,9 +10481,24 @@ __metadata: languageName: node linkType: hard -"finalhandler@npm:1.2.0": - version: 1.2.0 - resolution: "finalhandler@npm:1.2.0" +"finalhandler@npm:1.3.1": + version: 1.3.1 + resolution: "finalhandler@npm:1.3.1" + dependencies: + debug: 2.6.9 + encodeurl: ~2.0.0 + escape-html: ~1.0.3 + on-finished: 2.4.1 + parseurl: ~1.3.3 + statuses: 2.0.1 + unpipe: ~1.0.0 + checksum: a8c58cd97c9cd47679a870f6833a7b417043f5a288cd6af6d0f49b476c874a506100303a128b6d3b654c3d74fa4ff2ffed68a48a27e8630cda5c918f2977dcf4 + languageName: node + linkType: hard + +"finalhandler@npm:^2.0.0": + version: 2.0.0 + resolution: "finalhandler@npm:2.0.0" dependencies: debug: 2.6.9 encodeurl: ~1.0.2 @@ -10166,7 +10507,7 @@ __metadata: parseurl: ~1.3.3 statuses: 2.0.1 unpipe: ~1.0.0 - checksum: 92effbfd32e22a7dff2994acedbd9bcc3aa646a3e919ea6a53238090e87097f8ef07cced90aa2cc421abdf993aefbdd5b00104d55c7c5479a8d00ed105b45716 + checksum: 51403fd0b8f156aabb91040875d01e4f9f4fae8e356427dbf19d29956fc3a28c3fccfcb8bd50ea7318b390e67b8906a821a7ec9526f44de2f116fa409fed80de languageName: node linkType: hard @@ -10226,6 +10567,7 @@ __metadata: "@babel/plugin-transform-object-assign": ^7.18.6 "@babel/preset-react": ^7.18.6 "@babel/preset-typescript": ^7.18.6 + "@slack/events-api": ^3.0.1 "@types/jest": ^28.1.6 "@types/node": 18.17.1 "@typescript-eslint/eslint-plugin": 4.18.0 @@ -10257,9 +10599,9 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.3.1 - resolution: "flatted@npm:3.3.1" - checksum: 85ae7181650bb728c221e7644cbc9f4bf28bc556f2fc89bb21266962bdf0ce1029cc7acc44bb646cd469d9baac7c317f64e841c4c4c00516afa97320cdac7f94 + version: 3.3.2 + resolution: "flatted@npm:3.3.2" + checksum: ac3c159742e01d0e860a861164bcfd35bb567ccbebb8a0dd041e61cf3c64a435b917dd1e7ed1c380c2ebca85735fb16644485ec33665bc6aafc3b316aa1eed44 languageName: node linkType: hard @@ -10281,12 +10623,12 @@ __metadata: linkType: hard "follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.6": - version: 1.15.6 - resolution: "follow-redirects@npm:1.15.6" + version: 1.15.9 + resolution: "follow-redirects@npm:1.15.9" peerDependenciesMeta: debug: optional: true - checksum: a62c378dfc8c00f60b9c80cab158ba54e99ba0239a5dd7c81245e5a5b39d10f0c35e249c3379eae719ff0285fff88c365dd446fab19dee771f1d76252df1bbf5 + checksum: 859e2bacc7a54506f2bf9aacb10d165df78c8c1b0ceb8023f966621b233717dab56e8d08baadc3ad3b9db58af290413d585c999694b7c146aaf2616340c3d2a6 languageName: node linkType: hard @@ -10307,12 +10649,12 @@ __metadata: linkType: hard "foreground-child@npm:^3.1.0": - version: 3.1.1 - resolution: "foreground-child@npm:3.1.1" + version: 3.3.0 + resolution: "foreground-child@npm:3.3.0" dependencies: cross-spawn: ^7.0.0 signal-exit: ^4.0.1 - checksum: 139d270bc82dc9e6f8bc045fe2aae4001dc2472157044fdfad376d0a3457f77857fa883c1c8b21b491c6caade9a926a4bed3d3d2e8d3c9202b151a4cbbd0bcd5 + checksum: 1989698488f725b05b26bc9afc8a08f08ec41807cd7b92ad85d96004ddf8243fd3e79486b8348c64a3011ae5cc2c9f0936af989e1f28339805d8bc178a75b451 languageName: node linkType: hard @@ -10332,35 +10674,36 @@ __metadata: linkType: hard "form-data@npm:^2.5.0": - version: 2.5.1 - resolution: "form-data@npm:2.5.1" + version: 2.5.2 + resolution: "form-data@npm:2.5.2" dependencies: asynckit: ^0.4.0 combined-stream: ^1.0.6 mime-types: ^2.1.12 - checksum: 5134ada56cc246b293a1ac7678dba6830000603a3979cf83ff7b2f21f2e3725202237cfb89e32bcb38a1d35727efbd3c3a22e65b42321e8ade8eec01ce755d08 + safe-buffer: ^5.2.1 + checksum: 89ed3d96238d6fa874d75435e20f1aad28a1c22a88ab4e726ac4f6b0d29bef33d7e5aca51248c1070eccbbf4df94020a53842e800b2f1fb63073881a268113b4 languageName: node linkType: hard "form-data@npm:^3.0.0": - version: 3.0.1 - resolution: "form-data@npm:3.0.1" + version: 3.0.2 + resolution: "form-data@npm:3.0.2" dependencies: asynckit: ^0.4.0 combined-stream: ^1.0.8 mime-types: ^2.1.12 - checksum: b019e8d35c8afc14a2bd8a7a92fa4f525a4726b6d5a9740e8d2623c30e308fbb58dc8469f90415a856698933c8479b01646a9dff33c87cc4e76d72aedbbf860d + checksum: 25ffdeed693c8fc59b56082d15ad63f11688fabac2d14918fb339170020f66295e520a6659f3a698217f15c7924fbc593117ecd61d8391a146ea06d686793622 languageName: node linkType: hard "form-data@npm:^4.0.0": - version: 4.0.0 - resolution: "form-data@npm:4.0.0" + version: 4.0.1 + resolution: "form-data@npm:4.0.1" dependencies: asynckit: ^0.4.0 combined-stream: ^1.0.8 mime-types: ^2.1.12 - checksum: 01135bf8675f9d5c61ff18e2e2932f719ca4de964e3be90ef4c36aacfc7b9cb2fceb5eca0b7e0190e3383fe51c5b37f4cb80b62ca06a99aaabfcfd6ac7c9328c + checksum: ccee458cd5baf234d6b57f349fe9cc5f9a2ea8fd1af5ecda501a18fd1572a6dd3bf08a49f00568afd995b6a65af34cb8dec083cf9d582c4e621836499498dd84 languageName: node linkType: hard @@ -10392,13 +10735,20 @@ __metadata: languageName: node linkType: hard -"fresh@npm:0.5.2": +"fresh@npm:0.5.2, fresh@npm:^0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" checksum: 13ea8b08f91e669a64e3ba3a20eb79d7ca5379a81f1ff7f4310d54e2320645503cc0c78daedc93dfb6191287295f6479544a649c64d8e41a1c0fb0c221552346 languageName: node linkType: hard +"fresh@npm:2.0.0": + version: 2.0.0 + resolution: "fresh@npm:2.0.0" + checksum: 38b9828352c6271e2a0dd8bdd985d0100dbbc4eb8b6a03286071dd6f7d96cfaacd06d7735701ad9a95870eb3f4555e67c08db1dcfe24c2e7bb87383c72fae1d2 + languageName: node + linkType: hard + "from2@npm:^2.1.0": version: 2.3.0 resolution: "from2@npm:2.3.0" @@ -10540,6 +10890,16 @@ __metadata: languageName: node linkType: hard +"fsevents@npm:2.3.3, fsevents@npm:^2.1.2, fsevents@npm:^2.1.3, fsevents@npm:~2.3.2": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: latest + checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 + conditions: os=darwin + languageName: node + linkType: hard + "fsevents@npm:^1.2.7": version: 1.2.13 resolution: "fsevents@npm:1.2.13" @@ -10551,12 +10911,11 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:^2.1.2, fsevents@npm:^2.1.3, fsevents@npm:~2.3.2": +"fsevents@patch:fsevents@2.3.3#~builtin, fsevents@patch:fsevents@^2.1.2#~builtin, fsevents@patch:fsevents@^2.1.3#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin": version: 2.3.3 - resolution: "fsevents@npm:2.3.3" + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=18f3a7" dependencies: node-gyp: latest - checksum: 11e6ea6fea15e42461fc55b4b0e4a0a3c654faa567f1877dbd353f39156f69def97a69936d1746619d656c4b93de2238bf731f6085a03a50cabf287c9d024317 conditions: os=darwin languageName: node linkType: hard @@ -10571,15 +10930,6 @@ __metadata: languageName: node linkType: hard -"fsevents@patch:fsevents@^2.1.2#~builtin, fsevents@patch:fsevents@^2.1.3#~builtin, fsevents@patch:fsevents@~2.3.2#~builtin": - version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#~builtin::version=2.3.3&hash=18f3a7" - dependencies: - node-gyp: latest - conditions: os=darwin - languageName: node - linkType: hard - "function-bind@npm:^1.1.2": version: 1.1.2 resolution: "function-bind@npm:1.1.2" @@ -10587,7 +10937,7 @@ __metadata: languageName: node linkType: hard -"function.prototype.name@npm:^1.1.5, function.prototype.name@npm:^1.1.6": +"function.prototype.name@npm:^1.1.6": version: 1.1.6 resolution: "function.prototype.name@npm:1.1.6" dependencies: @@ -10739,17 +11089,18 @@ __metadata: linkType: hard "glob@npm:^10.2.2, glob@npm:^10.3.10": - version: 10.4.1 - resolution: "glob@npm:10.4.1" + version: 10.4.5 + resolution: "glob@npm:10.4.5" dependencies: foreground-child: ^3.1.0 jackspeak: ^3.1.2 minimatch: ^9.0.4 minipass: ^7.1.2 + package-json-from-dist: ^1.0.0 path-scurry: ^1.11.1 bin: glob: dist/esm/bin.mjs - checksum: 5d33c686c80bf6877f4284adf99a8c3cbb2a6eccbc92342943fe5d4b42c01d78c1881f2223d950c92a938d0f857e12e37b86a8e5483ab2141822e053b67d0dde + checksum: 0bc725de5e4862f9f387fd0f2b274baf16850dcd2714502ccf471ee401803997983e2c05590cb65f9675a3c6f2a58e7a53f9e365704108c6ad3cbf1d60934c4a languageName: node linkType: hard @@ -10803,7 +11154,7 @@ __metadata: languageName: node linkType: hard -"globalthis@npm:^1.0.3": +"globalthis@npm:^1.0.4": version: 1.0.4 resolution: "globalthis@npm:1.0.4" dependencies: @@ -10906,12 +11257,12 @@ __metadata: languageName: node linkType: hard -"gopd@npm:^1.0.1": - version: 1.0.1 - resolution: "gopd@npm:1.0.1" +"gopd@npm:^1.0.1, gopd@npm:^1.1.0": + version: 1.1.0 + resolution: "gopd@npm:1.1.0" dependencies: - get-intrinsic: ^1.1.3 - checksum: a5ccfb8806e0917a94e0b3de2af2ea4979c1da920bc381667c260e00e7cafdbe844e2cb9c5bcfef4e5412e8bf73bab837285bc35c7ba73aaaf0134d4583393a6 + get-intrinsic: ^1.2.4 + checksum: ed09ffe54ef841e9de35a56f9d249495c1149dc611f05a242c476cc538f13b2228ac1ee3970f9bfca2cadd6f9785efe854419eeef6050e7de3f02fbee9292ad4 languageName: node linkType: hard @@ -10930,9 +11281,9 @@ __metadata: linkType: hard "graphql@npm:^16.3.0": - version: 16.8.1 - resolution: "graphql@npm:16.8.1" - checksum: 8d304b7b6f708c8c5cc164b06e92467dfe36aff6d4f2cf31dd19c4c2905a0e7b89edac4b7e225871131fd24e21460836b369de0c06532644d15b461d55b1ccc0 + version: 16.9.0 + resolution: "graphql@npm:16.9.0" + checksum: 8cb3d54100e9227310383ce7f791ca48d12f15ed9f2021f23f8735f1121aafe4e5e611a853081dd935ce221724ea1ae4638faef5d2921fb1ad7c26b5f46611e9 languageName: node linkType: hard @@ -11025,9 +11376,11 @@ __metadata: linkType: hard "has-proto@npm:^1.0.1, has-proto@npm:^1.0.3": - version: 1.0.3 - resolution: "has-proto@npm:1.0.3" - checksum: fe7c3d50b33f50f3933a04413ed1f69441d21d2d2944f81036276d30635cad9279f6b43bc8f32036c31ebdfcf6e731150f46c1907ad90c669ffe9b066c3ba5c4 + version: 1.1.0 + resolution: "has-proto@npm:1.1.0" + dependencies: + call-bind: ^1.0.7 + checksum: 0335b8acd01a0de9bb6f7f89c4ef4f1512b48cec25f1c23e847a68d65afb8c579f168907e79969b01dc7025d707b48c71d481bca140579a40d735b071b2cc1bc languageName: node linkType: hard @@ -11104,13 +11457,13 @@ __metadata: languageName: node linkType: hard -"hash-base@npm:~3.0": - version: 3.0.4 - resolution: "hash-base@npm:3.0.4" +"hash-base@npm:~3.0, hash-base@npm:~3.0.4": + version: 3.0.5 + resolution: "hash-base@npm:3.0.5" dependencies: - inherits: ^2.0.1 - safe-buffer: ^5.0.1 - checksum: 878465a0dfcc33cce195c2804135352c590d6d10980adc91a9005fd377e77f2011256c2b7cfce472e3f2e92d561d1bf3228d2da06348a9017ce9a258b3b49764 + inherits: ^2.0.4 + safe-buffer: ^5.2.1 + checksum: 6a82675a5de2ea9347501bbe655a2334950c7ec972fd9810ae9529e06aeab8f7e8ef68fc2112e5e6f0745561a7e05326efca42ad59bb5fd116537f5f8b0a216d languageName: node linkType: hard @@ -11339,7 +11692,7 @@ __metadata: languageName: node linkType: hard -"http-errors@npm:2.0.0": +"http-errors@npm:2.0.0, http-errors@npm:^2.0.0": version: 2.0.0 resolution: "http-errors@npm:2.0.0" dependencies: @@ -11433,12 +11786,12 @@ __metadata: linkType: hard "https-proxy-agent@npm:^7.0.1": - version: 7.0.4 - resolution: "https-proxy-agent@npm:7.0.4" + version: 7.0.5 + resolution: "https-proxy-agent@npm:7.0.5" dependencies: agent-base: ^7.0.2 debug: 4 - checksum: daaab857a967a2519ddc724f91edbbd388d766ff141b9025b629f92b9408fc83cee8a27e11a907aede392938e9c398e240d643e178408a59e4073539cde8cfe9 + checksum: 2e1a28960f13b041a50702ee74f240add8e75146a5c37fc98f1960f0496710f6918b3a9fe1e5aba41e50f58e6df48d107edd9c405c5f0d73ac260dabf2210857 languageName: node linkType: hard @@ -11458,7 +11811,16 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.6.2": +"iconv-lite@npm:0.5.2": + version: 0.5.2 + resolution: "iconv-lite@npm:0.5.2" + dependencies: + safer-buffer: ">= 2.1.2 < 3" + checksum: aa184914b74db7a23feb98cad3e4ed22058f2aa27c5613a127327423b3230a0b934665c2aecf5dc657a58a59891c92fd1e721ed160d1b2f3c682bc26e3fe3f14 + languageName: node + linkType: hard + +"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" dependencies: @@ -11521,9 +11883,9 @@ __metadata: linkType: hard "ignore@npm:^5.1.4, ignore@npm:^5.1.8, ignore@npm:^5.2.0": - version: 5.3.1 - resolution: "ignore@npm:5.3.1" - checksum: 71d7bb4c1dbe020f915fd881108cbe85a0db3d636a0ea3ba911393c53946711d13a9b1143c7e70db06d571a5822c0a324a6bcde5c9904e7ca5047f01f1bf8cd3 + version: 5.3.2 + resolution: "ignore@npm:5.3.2" + checksum: 2acfd32a573260ea522ea0bfeff880af426d68f6831f973129e2ba7363f422923cf53aab62f8369cbf4667c7b25b6f8a3761b34ecdb284ea18e87a5262a865be languageName: node linkType: hard @@ -11534,10 +11896,10 @@ __metadata: languageName: node linkType: hard -"immutable@npm:^4.0.0": - version: 4.3.6 - resolution: "immutable@npm:4.3.6" - checksum: 3afd020be988ec9ba42c1e585b88858970beba91332ac04ac11446722c7e5da03d5956f5049806573d29dfee25f69262297cb7f3bd6b16fc83a175a0176c6c2a +"immutable@npm:^5.0.2": + version: 5.0.3 + resolution: "immutable@npm:5.0.3" + checksum: b2fcfc75aff29634babfcf6afb102111d7bc3858bfc55c17c5ad5eedf11085fe8b72d59fac883c6cfe9b2ec6e72cc184dec88782d5375ab17dc4eb25e3a665ed languageName: node linkType: hard @@ -11592,14 +11954,14 @@ __metadata: linkType: hard "import-local@npm:^3.0.2": - version: 3.1.0 - resolution: "import-local@npm:3.1.0" + version: 3.2.0 + resolution: "import-local@npm:3.2.0" dependencies: pkg-dir: ^4.2.0 resolve-cwd: ^3.0.0 bin: import-local-fixture: fixtures/cli.js - checksum: bfcdb63b5e3c0e245e347f3107564035b128a414c4da1172a20dc67db2504e05ede4ac2eee1252359f78b0bfd7b19ef180aec427c2fce6493ae782d73a04cddd + checksum: 0b0b0b412b2521739fbb85eeed834a3c34de9bc67e670b3d0b86248fc460d990a7b116ad056c084b87a693ef73d1f17268d6a5be626bb43c998a8b1c8a230004 languageName: node linkType: hard @@ -11855,12 +12217,12 @@ __metadata: linkType: hard "is-boolean-object@npm:^1.1.0": - version: 1.1.2 - resolution: "is-boolean-object@npm:1.1.2" + version: 1.2.0 + resolution: "is-boolean-object@npm:1.2.0" dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: c03b23dbaacadc18940defb12c1c0e3aaece7553ef58b162a0f6bba0c2a7e1551b59f365b91e00d2dbac0522392d576ef322628cb1d036a0fe51eb466db67222 + call-bind: ^1.0.7 + has-tostringtag: ^1.0.2 + checksum: cebc780cc3881dfb0c6c933e308f6a8eccf07ef92a7ea533fb2ee4fb7d704473b476f0b345fea4f2f45fe70937ef568a2f450eb6000d08b99350d87280927ff8 languageName: node linkType: hard @@ -11878,7 +12240,7 @@ __metadata: languageName: node linkType: hard -"is-callable@npm:^1.1.3, is-callable@npm:^1.1.4, is-callable@npm:^1.2.7": +"is-callable@npm:^1.1.3, is-callable@npm:^1.2.7": version: 1.2.7 resolution: "is-callable@npm:1.2.7" checksum: 61fd57d03b0d984e2ed3720fb1c7a897827ea174bd44402878e059542ea8c4aeedee0ea0985998aa5cc2736b2fa6e271c08587addb5b3959ac52cf665173d1ac @@ -11910,12 +12272,12 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.0.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1": - version: 2.13.1 - resolution: "is-core-module@npm:2.13.1" +"is-core-module@npm:^2.0.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1": + version: 2.15.1 + resolution: "is-core-module@npm:2.15.1" dependencies: - hasown: ^2.0.0 - checksum: 256559ee8a9488af90e4bad16f5583c6d59e92f0742e9e8bb4331e758521ee86b810b93bae44f390766ffbc518a0488b18d9dab7da9a5ff997d499efc9403f7c + hasown: ^2.0.2 + checksum: df134c168115690724b62018c37b2f5bba0d5745fa16960b329c5a00883a8bea6a5632fdb1e3efcce237c201826ba09f93197b7cd95577ea56b0df335be23633 languageName: node linkType: hard @@ -11937,7 +12299,7 @@ __metadata: languageName: node linkType: hard -"is-date-object@npm:^1.0.1, is-date-object@npm:^1.0.5": +"is-date-object@npm:^1.0.5": version: 1.0.5 resolution: "is-date-object@npm:1.0.5" dependencies: @@ -12019,12 +12381,12 @@ __metadata: languageName: node linkType: hard -"is-finalizationregistry@npm:^1.0.2": - version: 1.0.2 - resolution: "is-finalizationregistry@npm:1.0.2" +"is-finalizationregistry@npm:^1.1.0": + version: 1.1.0 + resolution: "is-finalizationregistry@npm:1.1.0" dependencies: - call-bind: ^1.0.2 - checksum: 4f243a8e06228cd45bdab8608d2cb7abfc20f6f0189c8ac21ea8d603f1f196eabd531ce0bb8e08cbab047e9845ef2c191a3761c9a17ad5cabf8b35499c4ad35d + call-bind: ^1.0.7 + checksum: 480818ab86e112a00444410a2fd551a5363bca0c39c7bc66e29df665b1e47c803ba107227c1db86d67264a3f020779fab257061463ce02b01b6abbe5966e33b8 languageName: node linkType: hard @@ -12126,11 +12488,12 @@ __metadata: linkType: hard "is-number-object@npm:^1.0.4": - version: 1.0.7 - resolution: "is-number-object@npm:1.0.7" + version: 1.1.0 + resolution: "is-number-object@npm:1.1.0" dependencies: - has-tostringtag: ^1.0.0 - checksum: d1e8d01bb0a7134c74649c4e62da0c6118a0bfc6771ea3c560914d52a627873e6920dd0fd0ebc0e12ad2ff4687eac4c308f7e80320b973b2c8a2c8f97a7524f7 + call-bind: ^1.0.7 + has-tostringtag: ^1.0.2 + checksum: 965f91493e5c02a44bb9c5d8dd4ae40da20bd9bd1cff9cd92e2f2e66a486935a0a01f8a4744eab033c450888f01a4ec3226e1c75bbcff973ce12d06ed79eb17b languageName: node linkType: hard @@ -12219,13 +12582,22 @@ __metadata: languageName: node linkType: hard +"is-promise@npm:4.0.0": + version: 4.0.0 + resolution: "is-promise@npm:4.0.0" + checksum: 0b46517ad47b00b6358fd6553c83ec1f6ba9acd7ffb3d30a0bf519c5c69e7147c132430452351b8a9fc198f8dd6c4f76f8e6f5a7f100f8c77d57d9e0f4261a8a + languageName: node + linkType: hard + "is-regex@npm:^1.1.4": - version: 1.1.4 - resolution: "is-regex@npm:1.1.4" - dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: 362399b33535bc8f386d96c45c9feb04cf7f8b41c182f54174c1a45c9abbbe5e31290bbad09a458583ff6bf3b2048672cdb1881b13289569a7c548370856a652 + version: 1.2.0 + resolution: "is-regex@npm:1.2.0" + dependencies: + call-bind: ^1.0.7 + gopd: ^1.1.0 + has-tostringtag: ^1.0.2 + hasown: ^2.0.2 + checksum: dd2693d71866850d1276815204a2629d28dc1d24bd56b734e57a39f56b777cd87030d57552e7093d91a2ac331d99af9dba49a0a641fa4e4435d40e944d4dde12 languageName: node linkType: hard @@ -12281,15 +12653,16 @@ __metadata: linkType: hard "is-string@npm:^1.0.5, is-string@npm:^1.0.7": - version: 1.0.7 - resolution: "is-string@npm:1.0.7" + version: 1.1.0 + resolution: "is-string@npm:1.1.0" dependencies: - has-tostringtag: ^1.0.0 - checksum: 323b3d04622f78d45077cf89aab783b2f49d24dc641aa89b5ad1a72114cfeff2585efc8c12ef42466dff32bde93d839ad321b26884cf75e5a7892a938b089989 + call-bind: ^1.0.7 + has-tostringtag: ^1.0.2 + checksum: 1e330e9fe0984cdf37371f704f9babf9b56d50b1e9d2e6c19b8b78443be3e9771c33309b4aadde9ba2a8870769374538681e01f54113a335dd393c80a72e7d11 languageName: node linkType: hard -"is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": +"is-symbol@npm:^1.0.3, is-symbol@npm:^1.0.4": version: 1.0.4 resolution: "is-symbol@npm:1.0.4" dependencies: @@ -12485,29 +12858,29 @@ __metadata: languageName: node linkType: hard -"iterator.prototype@npm:^1.1.2": - version: 1.1.2 - resolution: "iterator.prototype@npm:1.1.2" +"iterator.prototype@npm:^1.1.3": + version: 1.1.3 + resolution: "iterator.prototype@npm:1.1.3" dependencies: define-properties: ^1.2.1 get-intrinsic: ^1.2.1 has-symbols: ^1.0.3 reflect.getprototypeof: ^1.0.4 set-function-name: ^2.0.1 - checksum: d8a507e2ccdc2ce762e8a1d3f4438c5669160ac72b88b648e59a688eec6bc4e64b22338e74000518418d9e693faf2a092d2af21b9ec7dbf7763b037a54701168 + checksum: 7d2a1f8bcbba7b76f72e956faaf7b25405f4de54430c9d099992e6fb9d571717c3044604e8cdfb8e624cb881337d648030ee8b1541d544af8b338835e3f47ebe languageName: node linkType: hard "jackspeak@npm:^3.1.2": - version: 3.4.0 - resolution: "jackspeak@npm:3.4.0" + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" dependencies: "@isaacs/cliui": ^8.0.2 "@pkgjs/parseargs": ^0.11.0 dependenciesMeta: "@pkgjs/parseargs": optional: true - checksum: 350f6f311018bb175ffbe736b19c26ac0b134bb5a17a638169e89594eb0c24ab1c658ab3a2fda24ff63b3b19292e1a5ec19d2255bc526df704e8168d392bef85 + checksum: be31027fc72e7cc726206b9f560395604b82e0fddb46c4cbf9f97d049bcef607491a5afc0699612eaa4213ca5be8fd3e1e7cd187b3040988b65c9489838a7c00 languageName: node linkType: hard @@ -12693,9 +13066,9 @@ __metadata: linkType: hard "jest-fail-on-console@npm:^3.0.2": - version: 3.3.0 - resolution: "jest-fail-on-console@npm:3.3.0" - checksum: 891cbe9bac5d7656beee75850c880427401880debc6dc110b845d17313cf375dc5f6f1d27eaf411553839287fe150fd46738f3c5facba5cb22244546ee66e111 + version: 3.3.1 + resolution: "jest-fail-on-console@npm:3.3.1" + checksum: ca83aaf623e3772ec612e639fefca54472d38a7f4ea8119de8f12dcdb5e425e9f09d803ffd3b7db7b78fdc4edcffea3340f1ea7d160007da32f03d6ec569686b languageName: node linkType: hard @@ -13259,21 +13632,12 @@ __metadata: languageName: node linkType: hard -"jsesc@npm:^2.5.1": - version: 2.5.2 - resolution: "jsesc@npm:2.5.2" - bin: - jsesc: bin/jsesc - checksum: 4dc190771129e12023f729ce20e1e0bfceac84d73a85bc3119f7f938843fe25a4aeccb54b6494dce26fcf263d815f5f31acdefac7cc9329efb8422a4f4d9fa9d - languageName: node - linkType: hard - -"jsesc@npm:~0.5.0": - version: 0.5.0 - resolution: "jsesc@npm:0.5.0" +"jsesc@npm:^3.0.2, jsesc@npm:~3.0.2": + version: 3.0.2 + resolution: "jsesc@npm:3.0.2" bin: jsesc: bin/jsesc - checksum: b8b44cbfc92f198ad972fba706ee6a1dfa7485321ee8c0b25f5cedd538dcb20cde3197de16a7265430fce8277a12db066219369e3d51055038946039f6e20e17 + checksum: a36d3ca40574a974d9c2063bf68c2b6141c20da8f2a36bd3279fc802563f35f0527a6c828801295bdfb2803952cf2cf387786c2c90ed564f88d5782475abfe3c languageName: node linkType: hard @@ -13402,6 +13766,24 @@ __metadata: languageName: node linkType: hard +"jsonwebtoken@npm:^9.0.2": + version: 9.0.2 + resolution: "jsonwebtoken@npm:9.0.2" + dependencies: + jws: ^3.2.2 + lodash.includes: ^4.3.0 + lodash.isboolean: ^3.0.3 + lodash.isinteger: ^4.0.4 + lodash.isnumber: ^3.0.3 + lodash.isplainobject: ^4.0.6 + lodash.isstring: ^4.0.1 + lodash.once: ^4.0.0 + ms: ^2.1.1 + semver: ^7.5.4 + checksum: fc739a6a8b33f1974f9772dca7f8493ca8df4cc31c5a09dcfdb7cff77447dcf22f4236fb2774ef3fe50df0abeb8e1c6f4c41eba82f500a804ab101e2fbc9d61a + languageName: node + linkType: hard + "jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.5": version: 3.3.5 resolution: "jsx-ast-utils@npm:3.3.5" @@ -13786,9 +14168,9 @@ __metadata: linkType: hard "loglevel@npm:^1.6.8": - version: 1.9.1 - resolution: "loglevel@npm:1.9.1" - checksum: e1c8586108c4d566122e91f8a79c8df728920e3a714875affa5120566761a24077ec8ec9e5fc388b022e39fc411ec6e090cde1b5775871241b045139771eeb06 + version: 1.9.2 + resolution: "loglevel@npm:1.9.2" + checksum: 896c67b90a507bfcfc1e9a4daa7bf789a441dd70d95cd13b998d6dd46233a3bfadfb8fadb07250432bbfb53bf61e95f2520f9b11f9d3175cc460e5c251eca0af languageName: node linkType: hard @@ -13822,9 +14204,9 @@ __metadata: linkType: hard "lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.2.2 - resolution: "lru-cache@npm:10.2.2" - checksum: 98e8fc93691c546f719a76103ef2bee5a3ac823955c755a47641ec41f8c7fafa1baeaba466937cc1cbfa9cfd47e03536d10e2db3158a64ad91ff3a58a32c893e + version: 10.4.3 + resolution: "lru-cache@npm:10.4.3" + checksum: 6476138d2125387a6d20f100608c2583d415a4f64a0fecf30c9e2dda976614f09cad4baa0842447bd37dd459a7bd27f57d9d8f8ce558805abd487c583f3d774a languageName: node linkType: hard @@ -13865,11 +14247,11 @@ __metadata: linkType: hard "magic-string@npm:^0.30.0": - version: 0.30.10 - resolution: "magic-string@npm:0.30.10" + version: 0.30.14 + resolution: "magic-string@npm:0.30.14" dependencies: - "@jridgewell/sourcemap-codec": ^1.4.15 - checksum: 456fd47c39b296c47dff967e1965121ace35417eab7f45a99e681e725b8661b48e1573c366ee67a27715025b3740773c46b088f115421c7365ea4ea6fa10d399 + "@jridgewell/sourcemap-codec": ^1.5.0 + checksum: 67b3b2d817a7c4e94cb63e2dcaffbeee3b76ff0798eeaee8159a6ff4faee30db824375b2cadbf43807b56c6802fe6373b40d02567d489593017012d74ec0b719 languageName: node linkType: hard @@ -14047,6 +14429,13 @@ __metadata: languageName: node linkType: hard +"media-typer@npm:^1.1.0": + version: 1.1.0 + resolution: "media-typer@npm:1.1.0" + checksum: a58dd60804df73c672942a7253ccc06815612326dc1c0827984b1a21704466d7cde351394f47649e56cf7415e6ee2e26e000e81b51b3eebb5a93540e8bf93cbd + languageName: node + linkType: hard + "memoize-one@npm:^6.0.0": version: 6.0.0 resolution: "memoize-one@npm:6.0.0" @@ -14074,10 +14463,17 @@ __metadata: languageName: node linkType: hard -"merge-descriptors@npm:1.0.1": - version: 1.0.1 - resolution: "merge-descriptors@npm:1.0.1" - checksum: 5abc259d2ae25bb06d19ce2b94a21632583c74e2a9109ee1ba7fd147aa7362b380d971e0251069f8b3eb7d48c21ac839e21fa177b335e82c76ec172e30c31a26 +"merge-descriptors@npm:1.0.3": + version: 1.0.3 + resolution: "merge-descriptors@npm:1.0.3" + checksum: 52117adbe0313d5defa771c9993fe081e2d2df9b840597e966aadafde04ae8d0e3da46bac7ca4efc37d4d2b839436582659cd49c6a43eacb3fe3050896a105d1 + languageName: node + linkType: hard + +"merge-descriptors@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-descriptors@npm:2.0.0" + checksum: e383332e700a94682d0125a36c8be761142a1320fc9feeb18e6e36647c9edf064271645f5669b2c21cf352116e561914fd8aa831b651f34db15ef4038c86696a languageName: node linkType: hard @@ -14141,12 +14537,12 @@ __metadata: linkType: hard "micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": - version: 4.0.7 - resolution: "micromatch@npm:4.0.7" + version: 4.0.8 + resolution: "micromatch@npm:4.0.8" dependencies: braces: ^3.0.3 picomatch: ^2.3.1 - checksum: 3cde047d70ad80cf60c787b77198d680db3b8c25b23feb01de5e2652205d9c19f43bd81882f69a0fd1f0cde6a7a122d774998aad3271ddb1b8accf8a0f480cf7 + checksum: 79920eb634e6f400b464a954fcfa589c4e7c7143209488e44baf627f9affc8b1e306f41f4f0deedde97e69cb725920879462d3e750ab3bd3c1aed675bb3a8966 languageName: node linkType: hard @@ -14169,14 +14565,21 @@ __metadata: languageName: node linkType: hard -"mime-db@npm:1.52.0, mime-db@npm:>= 1.43.0 < 2": +"mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" checksum: 0d99a03585f8b39d68182803b12ac601d9c01abfa28ec56204fa330bc9f3d1c5e14beb049bafadb3dbdf646dfb94b87e24d4ec7b31b7279ef906a8ea9b6a513f languageName: node linkType: hard -"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:~2.1.17, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": +"mime-db@npm:>= 1.43.0 < 2, mime-db@npm:^1.53.0": + version: 1.53.0 + resolution: "mime-db@npm:1.53.0" + checksum: 3fd9380bdc0b085d0b56b580e4f89ca4fc3b823722310d795c248f0806b9a80afd5d8f4347f015ad943b9ecfa7cc0b71dffa0db96fa776d01a13474821a2c7fb + languageName: node + linkType: hard + +"mime-types@npm:^2.1.12, mime-types@npm:^2.1.27, mime-types@npm:^2.1.35, mime-types@npm:~2.1.17, mime-types@npm:~2.1.24, mime-types@npm:~2.1.34": version: 2.1.35 resolution: "mime-types@npm:2.1.35" dependencies: @@ -14185,6 +14588,15 @@ __metadata: languageName: node linkType: hard +"mime-types@npm:^3.0.0": + version: 3.0.0 + resolution: "mime-types@npm:3.0.0" + dependencies: + mime-db: ^1.53.0 + checksum: 2d87c94ff682c61b9a5727c37ba66e199aba2d6a85465b41722ca7281629c32848601b540339d12a97d1b6ab39f94f9e63a72530dd7c22ee57ff25e1038af039 + languageName: node + linkType: hard + "mime@npm:1.6.0": version: 1.6.0 resolution: "mime@npm:1.6.0" @@ -14264,11 +14676,11 @@ __metadata: linkType: hard "minimatch@npm:^9.0.4": - version: 9.0.4 - resolution: "minimatch@npm:9.0.4" + version: 9.0.5 + resolution: "minimatch@npm:9.0.5" dependencies: brace-expansion: ^2.0.1 - checksum: cf717f597ec3eed7dabc33153482a2e8d49f4fd3c26e58fd9c71a94c5029a0838728841b93f46bf1263b65a8010e2ee800d0dc9b004ab8ba8b6d1ec07cc115b5 + checksum: 2c035575eda1e50623c731ec6c14f65a85296268f749b9337005210bb2b34e2705f8ef1a358b188f69892286ab99dc42c8fb98a57bde55c8d81b3023c19cea28 languageName: node linkType: hard @@ -14427,15 +14839,15 @@ __metadata: languageName: node linkType: hard -"mlly@npm:^1.4.0, mlly@npm:^1.7.0": - version: 1.7.1 - resolution: "mlly@npm:1.7.1" +"mlly@npm:^1.4.0, mlly@npm:^1.7.2": + version: 1.7.3 + resolution: "mlly@npm:1.7.3" dependencies: - acorn: ^8.11.3 + acorn: ^8.14.0 pathe: ^1.1.2 - pkg-types: ^1.1.1 - ufo: ^1.5.3 - checksum: 956a6d54119eef782f302580f63a9800654e588cd70015b4218a00069c6ef11b87984e8ffe140a4668b0100ad4022b11d1f9b11ac2c6dbafa4d8bc33ae3a08a8 + pkg-types: ^1.2.1 + ufo: ^1.5.4 + checksum: 60d309c7ce2ac162224a087fcd683a891260511f57011b2f436b54dfef146b8aae7473013958a58d5b6039f2a8692c32a2599c8390c5b307d1119ad0d917b414 languageName: node linkType: hard @@ -14467,7 +14879,7 @@ __metadata: languageName: node linkType: hard -"ms@npm:2.1.3, ms@npm:^2.1.1": +"ms@npm:2.1.3, ms@npm:^2.1.1, ms@npm:^2.1.3": version: 2.1.3 resolution: "ms@npm:2.1.3" checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d @@ -14551,11 +14963,11 @@ __metadata: linkType: hard "nan@npm:^2.12.1": - version: 2.19.0 - resolution: "nan@npm:2.19.0" + version: 2.22.0 + resolution: "nan@npm:2.22.0" dependencies: node-gyp: latest - checksum: 29a894a003c1954c250d690768c30e69cd91017e2e5eb21b294380f7cace425559508f5ffe3e329a751307140b0bd02f83af040740fa4def1a3869be6af39600 + checksum: 222e3a090e326c72f6782d948f44ee9b81cfb2161d5fe53216f04426a273fd094deee9dcc6813096dd2397689a2b10c1a92d3885d2e73fd2488a51547beb2929 languageName: node linkType: hard @@ -14576,11 +14988,11 @@ __metadata: linkType: hard "nanoid@npm:^3.3.7": - version: 3.3.7 - resolution: "nanoid@npm:3.3.7" + version: 3.3.8 + resolution: "nanoid@npm:3.3.8" bin: nanoid: bin/nanoid.cjs - checksum: d36c427e530713e4ac6567d488b489a36582ef89da1d6d4e3b87eded11eb10d7042a877958c6f104929809b2ab0bafa17652b076cdf84324aa75b30b722204f2 + checksum: dfe0adbc0c77e9655b550c333075f51bb28cfc7568afbf3237249904f9c86c9aaaed1f113f0fddddba75673ee31c758c30c43d4414f014a52a7a626efc5958c9 languageName: node linkType: hard @@ -14626,13 +15038,27 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:0.6.3, negotiator@npm:^0.6.3": +"negotiator@npm:0.6.3": version: 0.6.3 resolution: "negotiator@npm:0.6.3" checksum: b8ffeb1e262eff7968fc90a2b6767b04cfd9842582a9d0ece0af7049537266e7b2506dfb1d107a32f06dd849ab2aea834d5830f7f4d0e5cb7d36e1ae55d021d9 languageName: node linkType: hard +"negotiator@npm:^0.6.3, negotiator@npm:~0.6.4": + version: 0.6.4 + resolution: "negotiator@npm:0.6.4" + checksum: 7ded10aa02a0707d1d12a9973fdb5954f98547ca7beb60e31cb3a403cc6e8f11138db7a3b0128425cf836fc85d145ec4ce983b2bdf83dca436af879c2d683510 + languageName: node + linkType: hard + +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 20ebfe79b2d2e7cf9cbc8239a72662b584f71164096e6e8896c8325055497c96f6b80cd22c258e8a2f2aa382a787795ec3ee8b37b422a302c7d4381b0d5ecfbb + languageName: node + linkType: hard + "neo-async@npm:^2.5.0, neo-async@npm:^2.6.1, neo-async@npm:^2.6.2": version: 2.6.2 resolution: "neo-async@npm:2.6.2" @@ -14664,6 +15090,15 @@ __metadata: languageName: node linkType: hard +"node-addon-api@npm:^7.0.0": + version: 7.1.1 + resolution: "node-addon-api@npm:7.1.1" + dependencies: + node-gyp: latest + checksum: 46051999e3289f205799dfaf6bcb017055d7569090f0004811110312e2db94cb4f8654602c7eb77a60a1a05142cc2b96e1b5c56ca4622c41a5c6370787faaf30 + languageName: node + linkType: hard + "node-fetch@npm:^2.6.7, node-fetch@npm:^2.6.9": version: 2.7.0 resolution: "node-fetch@npm:2.7.0" @@ -14693,8 +15128,8 @@ __metadata: linkType: hard "node-gyp@npm:latest": - version: 10.1.0 - resolution: "node-gyp@npm:10.1.0" + version: 10.2.0 + resolution: "node-gyp@npm:10.2.0" dependencies: env-paths: ^2.2.0 exponential-backoff: ^3.1.1 @@ -14702,13 +15137,13 @@ __metadata: graceful-fs: ^4.2.6 make-fetch-happen: ^13.0.0 nopt: ^7.0.0 - proc-log: ^3.0.0 + proc-log: ^4.1.0 semver: ^7.3.5 - tar: ^6.1.2 + tar: ^6.2.1 which: ^4.0.0 bin: node-gyp: bin/node-gyp.js - checksum: 72e2ab4b23fc32007a763da94018f58069fc0694bf36115d49a2b195c8831e12cf5dd1e7a3718fa85c06969aedf8fc126722d3b672ec1cb27e06ed33caee3c60 + checksum: 0233759d8c19765f7fdc259a35eb046ad86c3d09e22f7384613ae2b89647dd27fcf833fdf5293d9335041e91f9b1c539494225959cdb312a5c8080b7534b926f languageName: node linkType: hard @@ -14771,17 +15206,17 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.14": - version: 2.0.14 - resolution: "node-releases@npm:2.0.14" - checksum: 59443a2f77acac854c42d321bf1b43dea0aef55cd544c6a686e9816a697300458d4e82239e2d794ea05f7bbbc8a94500332e2d3ac3f11f52e4b16cbe638b3c41 +"node-releases@npm:^2.0.18": + version: 2.0.18 + resolution: "node-releases@npm:2.0.18" + checksum: ef55a3d853e1269a6d6279b7692cd6ff3e40bc74947945101138745bfdc9a5edabfe72cb19a31a8e45752e1910c4c65c77d931866af6357f242b172b7283f5b3 languageName: node linkType: hard "nodemailer@npm:^6.9.1": - version: 6.9.13 - resolution: "nodemailer@npm:6.9.13" - checksum: 1b591ef480be2ff69480127cbff819e6593b1ef263b6f920e1a4e83e40280582daf7a14a809ef92f9828e2a70bdb3ce22b11924e209f2afe4975f9ff37e08e9d + version: 6.9.16 + resolution: "nodemailer@npm:6.9.16" + checksum: a031d243914ab5a3bb48c75e1fab02d25fb45c2b5b9bc15569cce45ec851235bc970087de99477ca6e7ee88fab2cb6a590a714af310f58532dbcc31396f68b1c languageName: node linkType: hard @@ -14914,9 +15349,9 @@ __metadata: linkType: hard "nwsapi@npm:^2.2.0": - version: 2.2.10 - resolution: "nwsapi@npm:2.2.10" - checksum: 5f1d361b38c47ab49727d5ea8bbfeb5867ae6de0e538eec9a8b77c88005ddde36d8b930e0730b50ee5e5dda949112c0f9ffed1bf15e7e1b3cd9cfa319f5a9b6f + version: 2.2.16 + resolution: "nwsapi@npm:2.2.16" + checksum: 467b36a74b7b8647d53fd61d05ca7d6c73a4a5d1b94ea84f770c03150b00ef46d38076cf8e708936246ae450c42a1f21e28e153023719784dc4d1a19b1737d47 languageName: node linkType: hard @@ -14938,10 +15373,10 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.1": - version: 1.13.1 - resolution: "object-inspect@npm:1.13.1" - checksum: 7d9fa9221de3311dcb5c7c307ee5dc011cdd31dc43624b7c184b3840514e118e05ef0002be5388304c416c0eb592feb46e983db12577fc47e47d5752fbbfb61f +"object-inspect@npm:^1.13.1, object-inspect@npm:^1.13.3": + version: 1.13.3 + resolution: "object-inspect@npm:1.13.3" + checksum: 8c962102117241e18ea403b84d2521f78291b774b03a29ee80a9863621d88265ffd11d0d7e435c4c2cea0dc2a2fbf8bbc92255737a05536590f2df2e8756f297 languageName: node linkType: hard @@ -14983,7 +15418,7 @@ __metadata: languageName: node linkType: hard -"object.entries@npm:^1.1.0, object.entries@npm:^1.1.7, object.entries@npm:^1.1.8": +"object.entries@npm:^1.1.0, object.entries@npm:^1.1.8": version: 1.1.8 resolution: "object.entries@npm:1.1.8" dependencies: @@ -14994,7 +15429,7 @@ __metadata: languageName: node linkType: hard -"object.fromentries@npm:^2.0.7, object.fromentries@npm:^2.0.8": +"object.fromentries@npm:^2.0.8": version: 2.0.8 resolution: "object.fromentries@npm:2.0.8" dependencies: @@ -15021,7 +15456,7 @@ __metadata: languageName: node linkType: hard -"object.groupby@npm:^1.0.1": +"object.groupby@npm:^1.0.3": version: 1.0.3 resolution: "object.groupby@npm:1.0.3" dependencies: @@ -15032,17 +15467,6 @@ __metadata: languageName: node linkType: hard -"object.hasown@npm:^1.1.4": - version: 1.1.4 - resolution: "object.hasown@npm:1.1.4" - dependencies: - define-properties: ^1.2.1 - es-abstract: ^1.23.2 - es-object-atoms: ^1.0.0 - checksum: bc46eb5ca22106fcd07aab1411508c2c68b7565fe8fb272f166fb9bf203972e8b5c86a5a4b2c86204beead0626a7a4119d32cefbaf7c5dd57b400bf9e6363cb6 - languageName: node - linkType: hard - "object.pick@npm:^1.3.0": version: 1.3.0 resolution: "object.pick@npm:1.3.0" @@ -15052,7 +15476,7 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.0, object.values@npm:^1.1.6, object.values@npm:^1.1.7, object.values@npm:^1.2.0": +"object.values@npm:^1.1.0, object.values@npm:^1.1.6, object.values@npm:^1.2.0": version: 1.2.0 resolution: "object.values@npm:1.2.0" dependencies: @@ -15077,7 +15501,7 @@ __metadata: languageName: node linkType: hard -"on-finished@npm:2.4.1": +"on-finished@npm:2.4.1, on-finished@npm:^2.4.1": version: 2.4.1 resolution: "on-finished@npm:2.4.1" dependencies: @@ -15093,7 +15517,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": +"once@npm:1.4.0, once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -15202,9 +15626,9 @@ __metadata: linkType: hard "outvariant@npm:^1.2.1, outvariant@npm:^1.3.0": - version: 1.4.2 - resolution: "outvariant@npm:1.4.2" - checksum: 5d9e2b3edb1cc8be9cbfc1c8c97e8b05137c4384bbfc56e0a465de26c5d2f023e65732ddcda9d46599b06d667fbc0de32c30d2ecd11f6f3f43bcf8ce0d320918 + version: 1.4.3 + resolution: "outvariant@npm:1.4.3" + checksum: 4a3551fb2b45309e585eebf88bad094dbe56ac6d3a28d59dd2e4050b431aa2beb6097a0763fce3cd82ca0f077026f380a9b60fffc306aaf430141421e7a7b6ed languageName: node linkType: hard @@ -15328,6 +15752,13 @@ __metadata: languageName: node linkType: hard +"package-json-from-dist@npm:^1.0.0": + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 58ee9538f2f762988433da00e26acc788036914d57c71c246bf0be1b60cdbd77dd60b6a3e1a30465f0b248aeb80079e0b34cb6050b1dfa18c06953bb1cbc7602 + languageName: node + linkType: hard + "pako@npm:^1.0.10, pako@npm:^1.0.11, pako@npm:^1.0.6, pako@npm:~1.0.5": version: 1.0.11 resolution: "pako@npm:1.0.11" @@ -15422,7 +15853,7 @@ __metadata: languageName: node linkType: hard -"parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": +"parseurl@npm:^1.3.3, parseurl@npm:~1.3.2, parseurl@npm:~1.3.3": version: 1.3.3 resolution: "parseurl@npm:1.3.3" checksum: 407cee8e0a3a4c5cd472559bca8b6a45b82c124e9a4703302326e9ab60fc1081442ada4e02628efef1eb16197ddc7f8822f5a91fd7d7c86b51f530aedb17dfa2 @@ -15529,26 +15960,40 @@ __metadata: languageName: node linkType: hard -"path-to-regexp@npm:0.1.7": - version: 0.1.7 - resolution: "path-to-regexp@npm:0.1.7" - checksum: 69a14ea24db543e8b0f4353305c5eac6907917031340e5a8b37df688e52accd09e3cebfe1660b70d76b6bd89152f52183f28c74813dbf454ba1a01c82a38abce +"path-to-regexp@npm:0.1.10": + version: 0.1.10 + resolution: "path-to-regexp@npm:0.1.10" + checksum: ab7a3b7a0b914476d44030340b0a65d69851af2a0f33427df1476100ccb87d409c39e2182837a96b98fb38c4ef2ba6b87bdad62bb70a2c153876b8061760583c + languageName: node + linkType: hard + +"path-to-regexp@npm:0.1.12": + version: 0.1.12 + resolution: "path-to-regexp@npm:0.1.12" + checksum: ab237858bee7b25ecd885189f175ab5b5161e7b712b360d44f5c4516b8d271da3e4bf7bf0a7b9153ecb04c7d90ce8ff5158614e1208819cf62bac2b08452722e languageName: node linkType: hard "path-to-regexp@npm:^1.7.0": - version: 1.8.0 - resolution: "path-to-regexp@npm:1.8.0" + version: 1.9.0 + resolution: "path-to-regexp@npm:1.9.0" dependencies: isarray: 0.0.1 - checksum: 709f6f083c0552514ef4780cb2e7e4cf49b0cc89a97439f2b7cc69a608982b7690fb5d1720a7473a59806508fc2dae0be751ba49f495ecf89fd8fbc62abccbcd + checksum: 5b2ac9cab2a9f82effd30a35164b20998b18d99d96608281dd2cab6e66c0e4536187970369b185ab21d3815da1ecb7dcb2d5f97a4bf0ee6e31a9612299fca147 languageName: node linkType: hard "path-to-regexp@npm:^6.2.0": - version: 6.2.2 - resolution: "path-to-regexp@npm:6.2.2" - checksum: b7b0005c36f5099f9ed1fb20a820d2e4ed1297ffe683ea1d678f5e976eb9544f01debb281369dabdc26da82e6453901bf71acf2c7ed14b9243536c2a45286c33 + version: 6.3.0 + resolution: "path-to-regexp@npm:6.3.0" + checksum: eca78602e6434a1b6799d511d375ec044e8d7e28f5a48aa5c28d57d8152fb52f3fc62fb1cfc5dfa2198e1f041c2a82ed14043d75740a2fe60e91b5089a153250 + languageName: node + linkType: hard + +"path-to-regexp@npm:^8.0.0": + version: 8.2.0 + resolution: "path-to-regexp@npm:8.2.0" + checksum: 56e13e45962e776e9e7cd72e87a441cfe41f33fd539d097237ceb16adc922281136ca12f5a742962e33d8dda9569f630ba594de56d8b7b6e49adf31803c5e771 languageName: node linkType: hard @@ -15573,7 +16018,7 @@ __metadata: languageName: node linkType: hard -"pbkdf2@npm:^3.0.3, pbkdf2@npm:^3.1.2": +"pbkdf2@npm:^3.1.2": version: 3.1.2 resolution: "pbkdf2@npm:3.1.2" dependencies: @@ -15612,10 +16057,10 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1": - version: 1.0.1 - resolution: "picocolors@npm:1.0.1" - checksum: fa68166d1f56009fc02a34cdfd112b0dd3cf1ef57667ac57281f714065558c01828cdf4f18600ad6851cbe0093952ed0660b1e0156bddf2184b6aaf5817553a5 +"picocolors@npm:^1.0.0, picocolors@npm:^1.1.0, picocolors@npm:^1.1.1": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 languageName: node linkType: hard @@ -15688,14 +16133,14 @@ __metadata: languageName: node linkType: hard -"pkg-types@npm:^1.1.1": - version: 1.1.1 - resolution: "pkg-types@npm:1.1.1" +"pkg-types@npm:^1.2.1": + version: 1.2.1 + resolution: "pkg-types@npm:1.2.1" dependencies: - confbox: ^0.1.7 - mlly: ^1.7.0 + confbox: ^0.1.8 + mlly: ^1.7.2 pathe: ^1.1.2 - checksum: 78ee49eea8c03802ffbdc79dfb6a741f905a4053453280cd2f1149850523fdaf46d39ecb88c2c2f757cceb9883f234bb0e56371084b5895632bdb00ef0f7298f + checksum: d2e3ad7aef36cc92b17403e61c04db521bf0beb175ccb4d432c284239f00ec32ff37feb072a260613e9ff727911cff1127a083fd52f91b9bec6b62970f385702 languageName: node linkType: hard @@ -16513,12 +16958,12 @@ __metadata: linkType: hard "postcss-selector-parser@npm:^6.0.0, postcss-selector-parser@npm:^6.0.2": - version: 6.1.0 - resolution: "postcss-selector-parser@npm:6.1.0" + version: 6.1.2 + resolution: "postcss-selector-parser@npm:6.1.2" dependencies: cssesc: ^3.0.0 util-deprecate: ^1.0.2 - checksum: 449f614e6706421be307d8638183c61ba45bc3b460fe3815df8971dbb4d59c4087181940d879daee4a7a2daf3d86e915db1cce0c006dd68ca75b4087079273bd + checksum: ce9440fc42a5419d103f4c7c1847cb75488f3ac9cbe81093b408ee9701193a509f664b4d10a2b4d82c694ee7495e022f8f482d254f92b7ffd9ed9dea696c6f84 languageName: node linkType: hard @@ -16613,13 +17058,13 @@ __metadata: linkType: hard "postcss@npm:^8.1.0, postcss@npm:^8.4.26, postcss@npm:^8.4.27": - version: 8.4.38 - resolution: "postcss@npm:8.4.38" + version: 8.4.49 + resolution: "postcss@npm:8.4.49" dependencies: nanoid: ^3.3.7 - picocolors: ^1.0.0 - source-map-js: ^1.2.0 - checksum: 649f9e60a763ca4b5a7bbec446a069edf07f057f6d780a5a0070576b841538d1ecf7dd888f2fbfd1f76200e26c969e405aeeae66332e6927dbdc8bdcb90b9451 + picocolors: ^1.1.1 + source-map-js: ^1.2.1 + checksum: eb5d6cbdca24f50399aafa5d2bea489e4caee4c563ea1edd5a2485bc5f84e9ceef3febf170272bc83a99c31d23a316ad179213e853f34c2a7a8ffa534559d63a languageName: node linkType: hard @@ -16726,24 +17171,21 @@ __metadata: linkType: hard "prisma@npm:^5.7.1": - version: 5.15.0 - resolution: "prisma@npm:5.15.0" + version: 5.22.0 + resolution: "prisma@npm:5.22.0" dependencies: - "@prisma/engines": 5.15.0 + "@prisma/engines": 5.22.0 + fsevents: 2.3.3 + dependenciesMeta: + fsevents: + optional: true bin: prisma: build/index.js - checksum: e780334771f0d64a4f9187013b137676ba9f767a162127f53b11f2955bc457f6250da22e0b31f7a2bf171a911cbd194d28c5a96a688d4ef07fe5bbbf014c807f + checksum: 75a098b80f656f339ec5c89fe0c88e21b410c31eba77b84ad812cfc40cd78c1c26adcab757931427af26c10367d78773b97376747fd37feb99ee401115c85458 languageName: node linkType: hard -"proc-log@npm:^3.0.0": - version: 3.0.0 - resolution: "proc-log@npm:3.0.0" - checksum: 02b64e1b3919e63df06f836b98d3af002b5cd92655cab18b5746e37374bfb73e03b84fe305454614b34c25b485cc687a9eebdccf0242cda8fda2475dd2c97e02 - languageName: node - linkType: hard - -"proc-log@npm:^4.2.0": +"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": version: 4.2.0 resolution: "proc-log@npm:4.2.0" checksum: 98f6cd012d54b5334144c5255ecb941ee171744f45fca8b43b58ae5a0c1af07352475f481cadd9848e7f0250376ee584f6aa0951a856ff8f021bdfbff4eb33fc @@ -16869,9 +17311,11 @@ __metadata: linkType: hard "psl@npm:^1.1.33": - version: 1.9.0 - resolution: "psl@npm:1.9.0" - checksum: 20c4277f640c93d393130673f392618e9a8044c6c7bf61c53917a0fddb4952790f5f362c6c730a9c32b124813e173733f9895add8d26f566ed0ea0654b2e711d + version: 1.15.0 + resolution: "psl@npm:1.15.0" + dependencies: + punycode: ^2.3.1 + checksum: 6f777d82eecfe1c2406dadbc15e77467b186fec13202ec887a45d0209a2c6fca530af94a462a477c3c4a767ad892ec9ede7c482d98f61f653dd838b50e89dc15 languageName: node linkType: hard @@ -16882,7 +17326,7 @@ __metadata: languageName: node linkType: hard -"public-encrypt@npm:^4.0.0": +"public-encrypt@npm:^4.0.3": version: 4.0.3 resolution: "public-encrypt@npm:4.0.3" dependencies: @@ -16907,12 +17351,12 @@ __metadata: linkType: hard "pump@npm:^3.0.0": - version: 3.0.0 - resolution: "pump@npm:3.0.0" + version: 3.0.2 + resolution: "pump@npm:3.0.2" dependencies: end-of-stream: ^1.1.0 once: ^1.3.1 - checksum: e42e9229fba14732593a718b04cb5e1cfef8254544870997e0ecd9732b189a48e1256e4e5478148ecb47c8511dca2b09eae56b4d0aad8009e6fac8072923cfc9 + checksum: e0c4216874b96bd25ddf31a0b61a5613e26cc7afa32379217cf39d3915b0509def3565f5f6968fafdad2894c8bbdbd67d340e84f3634b2a29b950cffb6442d9f languageName: node linkType: hard @@ -16934,7 +17378,7 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^2.1.0, punycode@npm:^2.1.1": +"punycode@npm:^2.1.0, punycode@npm:^2.1.1, punycode@npm:^2.3.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2 @@ -16948,21 +17392,21 @@ __metadata: languageName: node linkType: hard -"qs@npm:6.11.0": - version: 6.11.0 - resolution: "qs@npm:6.11.0" +"qs@npm:6.13.0": + version: 6.13.0 + resolution: "qs@npm:6.13.0" dependencies: - side-channel: ^1.0.4 - checksum: 6e1f29dd5385f7488ec74ac7b6c92f4d09a90408882d0c208414a34dd33badc1a621019d4c799a3df15ab9b1d0292f97c1dd71dc7c045e69f81a8064e5af7297 + side-channel: ^1.0.6 + checksum: e9404dc0fc2849245107108ce9ec2766cde3be1b271de0bf1021d049dc5b98d1a2901e67b431ac5509f865420a7ed80b7acb3980099fe1c118a1c5d2e1432ad8 languageName: node linkType: hard -"qs@npm:^6.11.0, qs@npm:^6.11.2, qs@npm:^6.7.0": - version: 6.12.1 - resolution: "qs@npm:6.12.1" +"qs@npm:^6.11.0, qs@npm:^6.12.3, qs@npm:^6.7.0": + version: 6.13.1 + resolution: "qs@npm:6.13.1" dependencies: side-channel: ^1.0.6 - checksum: aa761d99e65b6936ba2dd2187f2d9976afbcda38deb3ff1b3fe331d09b0c578ed79ca2abdde1271164b5be619c521ec7db9b34c23f49a074e5921372d16242d5 + checksum: 86c5059146955fab76624e95771031541328c171b1d63d48a7ac3b1fdffe262faf8bc5fcadc1684e6f3da3ec87a8dedc8c0009792aceb20c5e94dc34cf468bb9 languageName: node linkType: hard @@ -17029,7 +17473,7 @@ __metadata: languageName: node linkType: hard -"randomfill@npm:^1.0.3": +"randomfill@npm:^1.0.4": version: 1.0.4 resolution: "randomfill@npm:1.0.4" dependencies: @@ -17046,7 +17490,7 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.2": +"raw-body@npm:2.5.2, raw-body@npm:^2.3.3": version: 2.5.2 resolution: "raw-body@npm:2.5.2" dependencies: @@ -17058,6 +17502,18 @@ __metadata: languageName: node linkType: hard +"raw-body@npm:^3.0.0": + version: 3.0.0 + resolution: "raw-body@npm:3.0.0" + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + unpipe: 1.0.0 + checksum: 25b7cf7964183db322e819050d758a5abd0f22c51e9f37884ea44a9ed6855a1fb61f8caa8ec5b61d07e69f54db43dbbc08ad98ef84556696d6aa806be247af0e + languageName: node + linkType: hard + "react-app-polyfill@npm:^2.0.0": version: 2.0.0 resolution: "react-app-polyfill@npm:2.0.0" @@ -17176,12 +17632,12 @@ __metadata: linkType: hard "react-google-charts@npm:^4.0.0": - version: 4.0.1 - resolution: "react-google-charts@npm:4.0.1" + version: 4.0.7 + resolution: "react-google-charts@npm:4.0.7" peerDependencies: react: ">=16.3.0" react-dom: ">=16.3.0" - checksum: 874a552b07cc67d6b830718dd5e71055c46fbd0c7a12bca14078c0744111d8fead833e36a16bd0b0ea5c26f6cff0eb84b4b6de62845c945b3c47c6cc75233f9d + checksum: 73b7765aad8adee94a93d3e01f2a81ccc096d95ae555946307cd7be826b8b8bc056757d4602b4ff27c9e5ce3196dbb8136f5f30a49719783eba9bd7710c9d482 languageName: node linkType: hard @@ -17223,11 +17679,11 @@ __metadata: linkType: hard "react-hook-form@npm:^7.34.0": - version: 7.51.5 - resolution: "react-hook-form@npm:7.51.5" + version: 7.53.2 + resolution: "react-hook-form@npm:7.53.2" peerDependencies: - react: ^16.8.0 || ^17 || ^18 - checksum: 6b6a56b6520ddb68d491e2f07791538aa611c13fcd76052a499ba10bdaf7f77f4a5f7191e6ca9d9ab0af739bf07171c6e8d97f6c4da06f576aa74caed71828f1 + react: ^16.8.0 || ^17 || ^18 || ^19 + checksum: 37e2dd0e79cd8d3376a7a2cb72ad7b59f0594be499daa898d2c6bec896fc30c2f86e62e8b41bc9d325f77220bd8d76cb31e917f77f1c92ad5740adb1a4cc69e2 languageName: node linkType: hard @@ -17245,7 +17701,7 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.0.0, react-is@npm:^18.2.0": +"react-is@npm:^18.0.0, react-is@npm:^18.3.1": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: e20fe84c86ff172fc8d898251b7cc2c43645d108bf96d0b8edf39b98f9a2cae97b40520ee7ed8ee0085ccc94736c4886294456033304151c3f94978cec03df21 @@ -17588,6 +18044,13 @@ __metadata: languageName: node linkType: hard +"readdirp@npm:^4.0.1": + version: 4.0.2 + resolution: "readdirp@npm:4.0.2" + checksum: 309376e717f94fb7eb61bec21e2603243a9e2420cd2e9bf94ddf026aefea0d7377ed1a62f016d33265682e44908049a55c3cfc2307450a1421654ea008489b39 + languageName: node + linkType: hard + "readdirp@npm:~3.6.0": version: 3.6.0 resolution: "readdirp@npm:3.6.0" @@ -17625,27 +18088,27 @@ __metadata: languageName: node linkType: hard -"reflect.getprototypeof@npm:^1.0.4": - version: 1.0.6 - resolution: "reflect.getprototypeof@npm:1.0.6" +"reflect.getprototypeof@npm:^1.0.4, reflect.getprototypeof@npm:^1.0.6": + version: 1.0.7 + resolution: "reflect.getprototypeof@npm:1.0.7" dependencies: call-bind: ^1.0.7 define-properties: ^1.2.1 - es-abstract: ^1.23.1 + es-abstract: ^1.23.5 es-errors: ^1.3.0 get-intrinsic: ^1.2.4 - globalthis: ^1.0.3 - which-builtin-type: ^1.1.3 - checksum: 88e9e65a7eaa0bf8e9a8bbf8ac07571363bc333ba8b6769ed5e013e0042ed7c385e97fae9049510b3b5fe4b42472d8f32de9ce8ce84902bc4297d4bbe3777dba + gopd: ^1.0.1 + which-builtin-type: ^1.1.4 + checksum: e023846d4d9631b46476a2315f5cdebb1f98782e145e807d985b47df8314776220b0d82244c9f3e51718acb09da79149f406afa9872e4fb4ca473dcc4e980598 languageName: node linkType: hard -"regenerate-unicode-properties@npm:^10.1.0": - version: 10.1.1 - resolution: "regenerate-unicode-properties@npm:10.1.1" +"regenerate-unicode-properties@npm:^10.2.0": + version: 10.2.0 + resolution: "regenerate-unicode-properties@npm:10.2.0" dependencies: regenerate: ^1.4.2 - checksum: b80958ef40f125275824c2c47d5081dfaefebd80bff26c76761e9236767c748a4a95a69c053fe29d2df881177f2ca85df4a71fe70a82360388b31159ef19adcf + checksum: d5c5fc13f8b8d7e16e791637a4bfef741f8d70e267d51845ee7d5404a32fa14c75b181c4efba33e4bff8b0000a2f13e9773593713dfe5b66597df4259275ce63 languageName: node linkType: hard @@ -17703,15 +18166,15 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2": - version: 1.5.2 - resolution: "regexp.prototype.flags@npm:1.5.2" +"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2, regexp.prototype.flags@npm:^1.5.3": + version: 1.5.3 + resolution: "regexp.prototype.flags@npm:1.5.3" dependencies: - call-bind: ^1.0.6 + call-bind: ^1.0.7 define-properties: ^1.2.1 es-errors: ^1.3.0 - set-function-name: ^2.0.1 - checksum: d7f333667d5c564e2d7a97c56c3075d64c722c9bb51b2b4df6822b2e8096d623a5e63088fb4c83df919b6951ef8113841de8b47de7224872fa6838bc5d8a7d64 + set-function-name: ^2.0.2 + checksum: 83ff0705b837f7cb6d664010a11642250f36d3f642263dd0f3bdfe8f150261aa7b26b50ee97f21c1da30ef82a580bb5afedbef5f45639d69edaafbeac9bbb0ed languageName: node linkType: hard @@ -17722,28 +18185,35 @@ __metadata: languageName: node linkType: hard -"regexpu-core@npm:^5.3.1": - version: 5.3.2 - resolution: "regexpu-core@npm:5.3.2" +"regexpu-core@npm:^6.1.1": + version: 6.2.0 + resolution: "regexpu-core@npm:6.2.0" dependencies: - "@babel/regjsgen": ^0.8.0 regenerate: ^1.4.2 - regenerate-unicode-properties: ^10.1.0 - regjsparser: ^0.9.1 + regenerate-unicode-properties: ^10.2.0 + regjsgen: ^0.8.0 + regjsparser: ^0.12.0 unicode-match-property-ecmascript: ^2.0.0 unicode-match-property-value-ecmascript: ^2.1.0 - checksum: 95bb97088419f5396e07769b7de96f995f58137ad75fac5811fb5fe53737766dfff35d66a0ee66babb1eb55386ef981feaef392f9df6d671f3c124812ba24da2 + checksum: 67d3c4a3f6c99bc80b5d690074a27e6f675be1c1739f8a9acf028fbc36f1a468472574ea65e331e217995198ba4404d7878f3cb3739a73552dd3c70d3fb7f8e6 languageName: node linkType: hard -"regjsparser@npm:^0.9.1": - version: 0.9.1 - resolution: "regjsparser@npm:0.9.1" +"regjsgen@npm:^0.8.0": + version: 0.8.0 + resolution: "regjsgen@npm:0.8.0" + checksum: a1d925ff14a4b2be774e45775ee6b33b256f89c42d480e6d85152d2133f18bd3d6af662161b226fa57466f7efec367eaf7ccd2a58c0ec2a1306667ba2ad07b0d + languageName: node + linkType: hard + +"regjsparser@npm:^0.12.0": + version: 0.12.0 + resolution: "regjsparser@npm:0.12.0" dependencies: - jsesc: ~0.5.0 + jsesc: ~3.0.2 bin: regjsparser: bin/parser - checksum: 5e1b76afe8f1d03c3beaf9e0d935dd467589c3625f6d65fb8ffa14f224d783a0fed4bf49c2c1b8211043ef92b6117313419edf055a098ed8342e340586741afc + checksum: 094b55b0ab3e1fd58f8ce5132a1d44dab08d91f7b0eea4132b0157b303ebb8ded20a9cbd893d25402d2aeddb23fac1f428ab4947b295d6fa51dd1c334a9e76f0 languageName: node linkType: hard @@ -18157,8 +18627,8 @@ __metadata: linkType: hard "rollup@npm:^3.25.2, rollup@npm:^3.27.1": - version: 3.29.4 - resolution: "rollup@npm:3.29.4" + version: 3.29.5 + resolution: "rollup@npm:3.29.5" dependencies: fsevents: ~2.3.2 dependenciesMeta: @@ -18166,7 +18636,22 @@ __metadata: optional: true bin: rollup: dist/bin/rollup - checksum: 8bb20a39c8d91130825159c3823eccf4dc2295c9a0a5c4ed851a5bf2167dbf24d9a29f23461a54c955e5506395e6cc188eafc8ab0e20399d7489fb33793b184e + checksum: 6f8304e58ac8170a715e61e46c4aa674b2ae2587ed2a712dab58f72e5e54803ae40b485fbe6b3e6a694f4c8f7a59ab936ccf9f6b686c7cfd1f1970fa9ecadf1a + languageName: node + linkType: hard + +"router@npm:^2.0.0": + version: 2.0.0 + resolution: "router@npm:2.0.0" + dependencies: + array-flatten: 3.0.0 + is-promise: 4.0.0 + methods: ~1.1.2 + parseurl: ~1.3.3 + path-to-regexp: ^8.0.0 + setprototypeof: 1.2.0 + utils-merge: 1.0.1 + checksum: 810ed3a4287ae90abe91908c49cc0b1faa0eb04b161bf266e29e789c7d9718f74ca1931445d9c8fe53c08ca30614d5856c167a4b4b3bb217276a96452b02b8ab languageName: node linkType: hard @@ -18232,13 +18717,6 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:5.1.2, safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": - version: 5.1.2 - resolution: "safe-buffer@npm:5.1.2" - checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c - languageName: node - linkType: hard - "safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.0, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": version: 5.2.1 resolution: "safe-buffer@npm:5.2.1" @@ -18246,6 +18724,13 @@ __metadata: languageName: node linkType: hard +"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": + version: 5.1.2 + resolution: "safe-buffer@npm:5.1.2" + checksum: f2f1f7943ca44a594893a852894055cf619c1fbcb611237fc39e461ae751187e7baf4dc391a72125e0ac4fb2d8c5c0b3c71529622e6a58f46b960211e704903c + languageName: node + linkType: hard + "safe-regex-test@npm:^1.0.3": version: 1.0.3 resolution: "safe-regex-test@npm:1.0.3" @@ -18325,15 +18810,19 @@ __metadata: linkType: hard "sass@npm:^1.54.0": - version: 1.77.4 - resolution: "sass@npm:1.77.4" + version: 1.81.0 + resolution: "sass@npm:1.81.0" dependencies: - chokidar: ">=3.0.0 <4.0.0" - immutable: ^4.0.0 + "@parcel/watcher": ^2.4.1 + chokidar: ^4.0.0 + immutable: ^5.0.2 source-map-js: ">=0.6.2 <2.0.0" + dependenciesMeta: + "@parcel/watcher": + optional: true bin: sass: sass.js - checksum: 415d76960e35d78310ffc33bc61fdb2b35a54bb2823dfc4eff50eee960096dacc210d7ef7ae6695120e1a4f005f269719c34d58c77c54ff7787516bda6a89e55 + checksum: 93db5b342c3b0449af2b08123ed4c0793643bd3a30f78e4e0686a1aa991ad640e0d9bc8da09aa5d7ff313bbd317b3be9c827cca60fb33b07d9f4b14b001eccfe languageName: node linkType: hard @@ -18429,12 +18918,12 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.x, semver@npm:^7.2.1, semver@npm:^7.3.2, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3": - version: 7.6.2 - resolution: "semver@npm:7.6.2" +"semver@npm:7.x, semver@npm:^7.2.1, semver@npm:^7.3.2, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8, semver@npm:^7.5.3, semver@npm:^7.5.4": + version: 7.6.3 + resolution: "semver@npm:7.6.3" bin: semver: bin/semver.js - checksum: 40f6a95101e8d854357a644da1b8dd9d93ce786d5c6a77227bc69dbb17bea83d0d1d1d7c4cd5920a6df909f48e8bd8a5909869535007f90278289f2451d0292d + checksum: 4110ec5d015c9438f322257b1c51fe30276e5f766a3f64c09edd1d7ea7118ecbc3f379f3b69032bacf13116dc7abc4ad8ce0d7e2bd642e26b0d271b56b61a7d8 languageName: node linkType: hard @@ -18456,9 +18945,9 @@ __metadata: languageName: node linkType: hard -"send@npm:0.18.0": - version: 0.18.0 - resolution: "send@npm:0.18.0" +"send@npm:0.19.0": + version: 0.19.0 + resolution: "send@npm:0.19.0" dependencies: debug: 2.6.9 depd: 2.0.0 @@ -18473,7 +18962,27 @@ __metadata: on-finished: 2.4.1 range-parser: ~1.2.1 statuses: 2.0.1 - checksum: 74fc07ebb58566b87b078ec63e5a3e41ecd987e4272ba67b7467e86c6ad51bc6b0b0154133b6d8b08a2ddda360464f71382f7ef864700f34844a76c8027817a8 + checksum: 5ae11bd900c1c2575525e2aa622e856804e2f96a09281ec1e39610d089f53aa69e13fd8db84b52f001d0318cf4bb0b3b904ad532fc4c0014eb90d32db0cff55f + languageName: node + linkType: hard + +"send@npm:^1.0.0, send@npm:^1.1.0": + version: 1.1.0 + resolution: "send@npm:1.1.0" + dependencies: + debug: ^4.3.5 + destroy: ^1.2.0 + encodeurl: ^2.0.0 + escape-html: ^1.0.3 + etag: ^1.8.1 + fresh: ^0.5.2 + http-errors: ^2.0.0 + mime-types: ^2.1.35 + ms: ^2.1.3 + on-finished: ^2.4.1 + range-parser: ^1.2.1 + statuses: ^2.0.1 + checksum: cb82bec244cb0e54ffaadf657dc79f55f350428c0d1f58511b9aae74ba87b07078907e462b8fefe13380f592baebd4b9e184204f3b74bd4558e7561669204b0f languageName: node linkType: hard @@ -18521,15 +19030,27 @@ __metadata: languageName: node linkType: hard -"serve-static@npm:1.15.0": - version: 1.15.0 - resolution: "serve-static@npm:1.15.0" +"serve-static@npm:1.16.2": + version: 1.16.2 + resolution: "serve-static@npm:1.16.2" dependencies: - encodeurl: ~1.0.2 + encodeurl: ~2.0.0 escape-html: ~1.0.3 parseurl: ~1.3.3 - send: 0.18.0 - checksum: af57fc13be40d90a12562e98c0b7855cf6e8bd4c107fe9a45c212bf023058d54a1871b1c89511c3958f70626fff47faeb795f5d83f8cf88514dbaeb2b724464d + send: 0.19.0 + checksum: dffc52feb4cc5c68e66d0c7f3c1824d4e989f71050aefc9bd5f822a42c54c9b814f595fc5f2b717f4c7cc05396145f3e90422af31186a93f76cf15f707019759 + languageName: node + linkType: hard + +"serve-static@npm:^2.1.0": + version: 2.1.0 + resolution: "serve-static@npm:2.1.0" + dependencies: + encodeurl: ^2.0.0 + escape-html: ^1.0.3 + parseurl: ^1.3.3 + send: ^1.0.0 + checksum: 569f5af7f2a3073a97e3217263e7f4173fafe0861d73049c13ba99f0a9bc3708db747e6657f8f736cdbcec39c3271c795f7f4ffeab0b8933201b53c7728d3ed2 languageName: node linkType: hard @@ -18541,9 +19062,9 @@ __metadata: linkType: hard "set-cookie-parser@npm:^2.4.6": - version: 2.6.0 - resolution: "set-cookie-parser@npm:2.6.0" - checksum: bf11ebc594c53d84588f1b4c04f1b8ce14e0498b1c011b3d76b5c6d5aac481bbc3f7c5260ec4ce99bdc1d9aed19f9fc315e73166a36ca74d0f12349a73f6bdc9 + version: 2.7.1 + resolution: "set-cookie-parser@npm:2.7.1" + checksum: 2ef8b351094712f8f7df6d63ed4b10350b24a5b515772690e7dec227df85fcef5bc451c7765f484fd9f36694ece5438d1456407d017f237d0d3351d7dbbd3587 languageName: node linkType: hard @@ -18828,17 +19349,17 @@ __metadata: linkType: hard "socks-proxy-agent@npm:^8.0.3": - version: 8.0.3 - resolution: "socks-proxy-agent@npm:8.0.3" + version: 8.0.4 + resolution: "socks-proxy-agent@npm:8.0.4" dependencies: agent-base: ^7.1.1 debug: ^4.3.4 - socks: ^2.7.1 - checksum: 8fab38821c327c190c28f1658087bc520eb065d55bc07b4a0fdf8d1e0e7ad5d115abbb22a95f94f944723ea969dd771ad6416b1e3cde9060c4c71f705c8b85c5 + socks: ^2.8.3 + checksum: b2ec5051d85fe49072f9a250c427e0e9571fd09d5db133819192d078fd291276e1f0f50f6dbc04329b207738b1071314cee8bdbb4b12e27de42dbcf1d4233c67 languageName: node linkType: hard -"socks@npm:^2.7.1": +"socks@npm:^2.8.3": version: 2.8.3 resolution: "socks@npm:2.8.3" dependencies: @@ -18864,10 +19385,10 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.2.0": - version: 1.2.0 - resolution: "source-map-js@npm:1.2.0" - checksum: 791a43306d9223792e84293b00458bf102a8946e7188f3db0e4e22d8d530b5f80a4ce468eb5ec0bf585443ad55ebbd630bf379c98db0b1f317fd902500217f97 +"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 4eb0cd997cdf228bc253bcaff9340afeb706176e64868ecd20efbe6efea931465f43955612346d6b7318789e5265bdc419bc7669c1cebe3db0eb255f57efa76b languageName: node linkType: hard @@ -18971,9 +19492,9 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.18 - resolution: "spdx-license-ids@npm:3.0.18" - checksum: 457825df5dd1fc0135b0bb848c896143f70945cc2da148afc71c73ed0837d1d651f809006e406d82109c9dd71a8cb39785a3604815fe46bc0548e9d3976f6b69 + version: 3.0.20 + resolution: "spdx-license-ids@npm:3.0.20" + checksum: 0c57750bedbcff48f3d0e266fbbdaf0aab54217e182f669542ffe0b5a902dce69e8cdfa126a131e1ddd39a9bef4662e357b2b41315d7240b4a28c0a7e782bb40 languageName: node linkType: hard @@ -19103,7 +19624,7 @@ __metadata: languageName: node linkType: hard -"statuses@npm:2.0.1, statuses@npm:^2.0.0": +"statuses@npm:2.0.1, statuses@npm:^2.0.0, statuses@npm:^2.0.1": version: 2.0.1 resolution: "statuses@npm:2.0.1" checksum: 18c7623fdb8f646fb213ca4051be4df7efb3484d4ab662937ca6fbef7ced9b9e12842709872eb3020cc3504b93bde88935c9f6417489627a7786f24f8031cbcb @@ -19118,9 +19639,9 @@ __metadata: linkType: hard "std-env@npm:^3.3.3": - version: 3.7.0 - resolution: "std-env@npm:3.7.0" - checksum: 4f489d13ff2ab838c9acd4ed6b786b51aa52ecacdfeaefe9275fcb220ff2ac80c6e95674723508fd29850a694569563a8caaaea738eb82ca16429b3a0b50e510 + version: 3.8.0 + resolution: "std-env@npm:3.8.0" + checksum: ad4554485c2d09138a1d0f03944245e169510e6f5200b7d30fcdd4536e27a2a9a2fd934caff7ef58ebbe21993fa0e2b9e5b1979f431743c925305863b7ff36d5 languageName: node linkType: hard @@ -19246,6 +19767,17 @@ __metadata: languageName: node linkType: hard +"string.prototype.includes@npm:^2.0.1": + version: 2.0.1 + resolution: "string.prototype.includes@npm:2.0.1" + dependencies: + call-bind: ^1.0.7 + define-properties: ^1.2.1 + es-abstract: ^1.23.3 + checksum: ed4b7058b092f30d41c4df1e3e805eeea92479d2c7a886aa30f42ae32fde8924a10cc99cccc99c29b8e18c48216608a0fe6bf887f8b4aadf9559096a758f313a + languageName: node + linkType: hard + "string.prototype.matchall@npm:^4.0.11": version: 4.0.11 resolution: "string.prototype.matchall@npm:4.0.11" @@ -19266,6 +19798,16 @@ __metadata: languageName: node linkType: hard +"string.prototype.repeat@npm:^1.0.0": + version: 1.0.0 + resolution: "string.prototype.repeat@npm:1.0.0" + dependencies: + define-properties: ^1.1.3 + es-abstract: ^1.17.5 + checksum: 95dfc514ed7f328d80a066dabbfbbb1615c3e51490351085409db2eb7cbfed7ea29fdadaf277647fbf9f4a1e10e6dd9e95e78c0fd2c4e6bb6723ea6e59401004 + languageName: node + linkType: hard + "string.prototype.trim@npm:^1.2.9": version: 1.2.9 resolution: "string.prototype.trim@npm:1.2.9" @@ -19630,7 +20172,7 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.0.2, tar@npm:^6.1.11, tar@npm:^6.1.2": +"tar@npm:^6.0.2, tar@npm:^6.1.11, tar@npm:^6.2.1": version: 6.2.1 resolution: "tar@npm:6.2.1" dependencies: @@ -19692,8 +20234,8 @@ __metadata: linkType: hard "terser-webpack-plugin@npm:^1.4.3": - version: 1.4.5 - resolution: "terser-webpack-plugin@npm:1.4.5" + version: 1.4.6 + resolution: "terser-webpack-plugin@npm:1.4.6" dependencies: cacache: ^12.0.2 find-cache-dir: ^2.1.0 @@ -19706,7 +20248,7 @@ __metadata: worker-farm: ^1.7.0 peerDependencies: webpack: ^4.0.0 - checksum: 02aada80927d3c8105d69cb00384d307b73aed67d180db5d20023a8d649149f3803ad50f9cd2ef9eb2622005de87e677198ecc5088f51422bfac5d4d57472d0e + checksum: 8b6c84df929383032edb25c949781dc55dc31ff85dda9ede25af49357077f615f0065101fcc567cd9c801c8cb1f158ce441fb193c18c6127d04a809a1e7d0d2b languageName: node linkType: hard @@ -19724,8 +20266,8 @@ __metadata: linkType: hard "terser@npm:^5.3.4": - version: 5.31.1 - resolution: "terser@npm:5.31.1" + version: 5.36.0 + resolution: "terser@npm:5.36.0" dependencies: "@jridgewell/source-map": ^0.3.3 acorn: ^8.8.2 @@ -19733,7 +20275,7 @@ __metadata: source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: 6ab57e62e9cd690dc99b3d0ee2e07289cd3408109a950c7118bf39e32851a5bf08b67fe19e0ac43a5a98813792ac78101bf25e5aa524f05ae8bb4e0131d0feef + checksum: 489afd31901a2b170f7766948a3aa0e25da0acb41e9e35bd9f9b4751dfa2fc846e485f6fb9d34f0839a96af77f675b5fbf0a20c9aa54e0b8d7c219cf0b55e508 languageName: node linkType: hard @@ -19817,9 +20359,9 @@ __metadata: linkType: hard "tinybench@npm:^2.5.0": - version: 2.8.0 - resolution: "tinybench@npm:2.8.0" - checksum: 024a307c6a71f6e2903e110952457ee3dfa606093b45d7f49efcfd01d452650e099474080677ff650b0fd76b49074425ac68ff2a70561699a78515a278bf0862 + version: 2.9.0 + resolution: "tinybench@npm:2.9.0" + checksum: 1ab00d7dfe0d1f127cbf00822bacd9024f7a50a3ecd1f354a8168e0b7d2b53a639a24414e707c27879d1adc0f5153141d51d76ebd7b4d37fe245e742e5d91fe8 languageName: node linkType: hard @@ -19860,13 +20402,6 @@ __metadata: languageName: node linkType: hard -"to-fast-properties@npm:^2.0.0": - version: 2.0.0 - resolution: "to-fast-properties@npm:2.0.0" - checksum: be2de62fe58ead94e3e592680052683b1ec986c72d589e7b21e5697f8744cdbf48c266fa72f6c15932894c10187b5f54573a3bcf7da0bfd964d5caf23d436168 - languageName: node - linkType: hard - "to-object-path@npm:^0.3.0": version: 0.3.0 resolution: "to-object-path@npm:0.3.0" @@ -20092,9 +20627,16 @@ __metadata: linkType: hard "tslib@npm:^2.0.3, tslib@npm:^2.1.0": - version: 2.6.3 - resolution: "tslib@npm:2.6.3" - checksum: 74fce0e100f1ebd95b8995fbbd0e6c91bdd8f4c35c00d4da62e285a3363aaa534de40a80db30ecfd388ed7c313c42d930ee0eaf108e8114214b180eec3dbe6f5 + version: 2.8.1 + resolution: "tslib@npm:2.8.1" + checksum: e4aba30e632b8c8902b47587fd13345e2827fa639e7c3121074d5ee0880723282411a8838f830b55100cbe4517672f84a2472667d355b81e8af165a55dc6203a + languageName: node + linkType: hard + +"tsscmp@npm:^1.0.6": + version: 1.0.6 + resolution: "tsscmp@npm:1.0.6" + checksum: 1512384def36bccc9125cabbd4c3b0e68608d7ee08127ceaa0b84a71797263f1a01c7f82fa69be8a3bd3c1396e2965d2f7b52d581d3a5eeaf3967fbc52e3b3bf languageName: node linkType: hard @@ -20134,13 +20676,20 @@ __metadata: languageName: node linkType: hard -"type-detect@npm:4.0.8, type-detect@npm:^4.0.0, type-detect@npm:^4.0.8": +"type-detect@npm:4.0.8": version: 4.0.8 resolution: "type-detect@npm:4.0.8" checksum: 62b5628bff67c0eb0b66afa371bd73e230399a8d2ad30d852716efcc4656a7516904570cd8631a49a3ce57c10225adf5d0cbdcb47f6b0255fe6557c453925a15 languageName: node linkType: hard +"type-detect@npm:^4.0.0, type-detect@npm:^4.1.0": + version: 4.1.0 + resolution: "type-detect@npm:4.1.0" + checksum: 3b32f873cd02bc7001b00a61502b7ddc4b49278aabe68d652f732e1b5d768c072de0bc734b427abf59d0520a5f19a2e07309ab921ef02018fa1cb4af155cdb37 + languageName: node + linkType: hard + "type-fest@npm:^0.20.2": version: 0.20.2 resolution: "type-fest@npm:0.20.2" @@ -20193,6 +20742,17 @@ __metadata: languageName: node linkType: hard +"type-is@npm:^2.0.0": + version: 2.0.0 + resolution: "type-is@npm:2.0.0" + dependencies: + content-type: ^1.0.5 + media-typer: ^1.1.0 + mime-types: ^3.0.0 + checksum: 571c7daca550d5e0d9d8a71c33bde1a0c12ddee3bc77aa2f7c62c39a4f1f52ee7770d1c2eeba21c306ac3627b2cf3a1b8417bbb1af5d65829e092dcf3356038c + languageName: node + linkType: hard + "type@npm:^2.7.2": version: 2.7.3 resolution: "type@npm:2.7.3" @@ -20225,8 +20785,8 @@ __metadata: linkType: hard "typed-array-byte-offset@npm:^1.0.2": - version: 1.0.2 - resolution: "typed-array-byte-offset@npm:1.0.2" + version: 1.0.3 + resolution: "typed-array-byte-offset@npm:1.0.3" dependencies: available-typed-arrays: ^1.0.7 call-bind: ^1.0.7 @@ -20234,21 +20794,22 @@ __metadata: gopd: ^1.0.1 has-proto: ^1.0.3 is-typed-array: ^1.1.13 - checksum: c8645c8794a621a0adcc142e0e2c57b1823bbfa4d590ad2c76b266aa3823895cf7afb9a893bf6685e18454ab1b0241e1a8d885a2d1340948efa4b56add4b5f67 + reflect.getprototypeof: ^1.0.6 + checksum: 36728daa80d49a9fa51cd3f0f2b037613f4574666fd4473bd37ac123d7f6f81ea68ff45424c1e2673257964e10bedeb3ebfce73532672913ebbe446999912303 languageName: node linkType: hard "typed-array-length@npm:^1.0.6": - version: 1.0.6 - resolution: "typed-array-length@npm:1.0.6" + version: 1.0.7 + resolution: "typed-array-length@npm:1.0.7" dependencies: call-bind: ^1.0.7 for-each: ^0.3.3 gopd: ^1.0.1 - has-proto: ^1.0.3 is-typed-array: ^1.1.13 possible-typed-array-names: ^1.0.0 - checksum: f0315e5b8f0168c29d390ff410ad13e4d511c78e6006df4a104576844812ee447fcc32daab1f3a76c9ef4f64eff808e134528b5b2439de335586b392e9750e5c + reflect.getprototypeof: ^1.0.6 + checksum: deb1a4ffdb27cd930b02c7030cb3e8e0993084c643208e52696e18ea6dd3953dfc37b939df06ff78170423d353dc8b10d5bae5796f3711c1b3abe52872b3774c languageName: node linkType: hard @@ -20337,10 +20898,10 @@ __metadata: languageName: node linkType: hard -"ufo@npm:^1.5.3": - version: 1.5.3 - resolution: "ufo@npm:1.5.3" - checksum: 2f54fa543b2e689cc4ab341fe2194937afe37c5ee43cd782e6ecc184e36859e84d4197a43ae4cd6e9a56f793ca7c5b950dfff3f16fadaeef9b6b88b05c88c8ef +"ufo@npm:^1.5.4": + version: 1.5.4 + resolution: "ufo@npm:1.5.4" + checksum: f244703b7d4f9f0df4f9af23921241ab73410b591f4e5b39c23e3147f3159b139a4b1fb5903189c306129f7a16b55995dac0008e0fbae88a37c3e58cbc34d833 languageName: node linkType: hard @@ -20370,17 +20931,17 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~5.26.4": - version: 5.26.5 - resolution: "undici-types@npm:5.26.5" - checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487 +"undici-types@npm:~6.20.0": + version: 6.20.0 + resolution: "undici-types@npm:6.20.0" + checksum: b7bc50f012dc6afbcce56c9fd62d7e86b20a62ff21f12b7b5cbf1973b9578d90f22a9c7fe50e638e96905d33893bf2f9f16d98929c4673c2480de05c6c96ea8b languageName: node linkType: hard "unicode-canonical-property-names-ecmascript@npm:^2.0.0": - version: 2.0.0 - resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0" - checksum: 39be078afd014c14dcd957a7a46a60061bc37c4508ba146517f85f60361acf4c7539552645ece25de840e17e293baa5556268d091ca6762747fdd0c705001a45 + version: 2.0.1 + resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.1" + checksum: 3c3dabdb1d22aef4904399f9e810d0b71c0b12b3815169d96fac97e56d5642840c6071cf709adcace2252bc6bb80242396c2ec74b37224eb015c5f7aca40bad7 languageName: node linkType: hard @@ -20395,9 +20956,9 @@ __metadata: linkType: hard "unicode-match-property-value-ecmascript@npm:^2.1.0": - version: 2.1.0 - resolution: "unicode-match-property-value-ecmascript@npm:2.1.0" - checksum: 8d6f5f586b9ce1ed0e84a37df6b42fdba1317a05b5df0c249962bd5da89528771e2d149837cad11aa26bcb84c35355cb9f58a10c3d41fa3b899181ece6c85220 + version: 2.2.0 + resolution: "unicode-match-property-value-ecmascript@npm:2.2.0" + checksum: 9e3151e1d0bc6be35c4cef105e317c04090364173e8462005b5cde08a1e7c858b6586486cfebac39dc2c6c8c9ee24afb245de6d527604866edfa454fe2a35fae languageName: node linkType: hard @@ -20613,17 +21174,17 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.0.13": - version: 1.0.16 - resolution: "update-browserslist-db@npm:1.0.16" +"update-browserslist-db@npm:^1.1.1": + version: 1.1.1 + resolution: "update-browserslist-db@npm:1.1.1" dependencies: - escalade: ^3.1.2 - picocolors: ^1.0.1 + escalade: ^3.2.0 + picocolors: ^1.1.0 peerDependencies: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 51b1f7189c9ea5925c80154b0a6fd3ec36106d07858d8f69826427d8edb4735d1801512c69eade38ba0814d7407d11f400d74440bbf3da0309f3d788017f35b2 + checksum: 2ea11bd2562122162c3e438d83a1f9125238c0844b6d16d366e3276d0c0acac6036822dc7df65fc5a89c699cdf9f174acf439c39bedf3f9a2f3983976e4b4c3e languageName: node linkType: hard @@ -20645,7 +21206,7 @@ __metadata: languageName: node linkType: hard -"uri-js@npm:^4.2.2, uri-js@npm:^4.4.1": +"uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" dependencies: @@ -20696,12 +21257,12 @@ __metadata: linkType: hard "url@npm:^0.11.0": - version: 0.11.3 - resolution: "url@npm:0.11.3" + version: 0.11.4 + resolution: "url@npm:0.11.4" dependencies: punycode: ^1.4.1 - qs: ^6.11.2 - checksum: f9e7886f46a16f96d2e42fbcc5d682c231c55ef5442c1ff66150c0f6556f6e3a97d094a84f51be15ec2432711d212eb60426659ce418f5fcadeaa3f601532c4e + qs: ^6.12.3 + checksum: c25e587723d343d5d4248892393bfa5039ded9c2c07095a9d005bc64b7cb8956d623c0d8da8d1a28f71986a7a8d80fc2e9f9cf84235e48fa435a5cb4451062c6 languageName: node linkType: hard @@ -20973,8 +21534,8 @@ __metadata: linkType: hard "vite@npm:^3.0.0 || ^4.0.0": - version: 4.5.3 - resolution: "vite@npm:4.5.3" + version: 4.5.5 + resolution: "vite@npm:4.5.5" dependencies: esbuild: ^0.18.10 fsevents: ~2.3.2 @@ -21008,7 +21569,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: fd3f512ce48ca2a1fe60ad0376283b832de9272725fdbc65064ae9248f792de87b0f27a89573115e23e26784800daca329f8a9234d298ba6f60e808a9c63883c + checksum: 300c5f39c83b22413dfdc84f72e9ba979bf4004e4d939409eea1470b116626294495b09e2bd73fae387a254b79988c8d54ceb281f9515120a0eda179c33b216e languageName: node linkType: hard @@ -21401,27 +21962,28 @@ __metadata: languageName: node linkType: hard -"which-builtin-type@npm:^1.1.3": - version: 1.1.3 - resolution: "which-builtin-type@npm:1.1.3" +"which-builtin-type@npm:^1.1.4": + version: 1.2.0 + resolution: "which-builtin-type@npm:1.2.0" dependencies: - function.prototype.name: ^1.1.5 - has-tostringtag: ^1.0.0 + call-bind: ^1.0.7 + function.prototype.name: ^1.1.6 + has-tostringtag: ^1.0.2 is-async-function: ^2.0.0 is-date-object: ^1.0.5 - is-finalizationregistry: ^1.0.2 + is-finalizationregistry: ^1.1.0 is-generator-function: ^1.0.10 is-regex: ^1.1.4 is-weakref: ^1.0.2 isarray: ^2.0.5 which-boxed-primitive: ^1.0.2 - which-collection: ^1.0.1 - which-typed-array: ^1.1.9 - checksum: 43730f7d8660ff9e33d1d3f9f9451c4784265ee7bf222babc35e61674a11a08e1c2925019d6c03154fcaaca4541df43abe35d2720843b9b4cbcebdcc31408f36 + which-collection: ^1.0.2 + which-typed-array: ^1.1.15 + checksum: 6d40ecdf33a28c3fdeab13e7e3b4289fb51f7ebd0983e628d50fa42e113d8be1bc7dd0e6eb23c6b6a0c2c0c7667763eca3a2af1f6d768e48efba8073870eb568 languageName: node linkType: hard -"which-collection@npm:^1.0.1": +"which-collection@npm:^1.0.1, which-collection@npm:^1.0.2": version: 1.0.2 resolution: "which-collection@npm:1.0.2" dependencies: @@ -21440,16 +22002,16 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9": - version: 1.1.15 - resolution: "which-typed-array@npm:1.1.15" +"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.2": + version: 1.1.16 + resolution: "which-typed-array@npm:1.1.16" dependencies: available-typed-arrays: ^1.0.7 call-bind: ^1.0.7 for-each: ^0.3.3 gopd: ^1.0.1 has-tostringtag: ^1.0.2 - checksum: 65227dcbfadf5677aacc43ec84356d17b5500cb8b8753059bb4397de5cd0c2de681d24e1a7bd575633f976a95f88233abfd6549c2105ef4ebd58af8aa1807c75 + checksum: 903d398ec234d608011e1df09af6c004e66965bb24d5e1a82856cba0495fa6389ae393d1c9d5411498a9cba8e61b2e39a8e8be7b3005cbeadd317f772b1bdaef languageName: node linkType: hard @@ -21487,14 +22049,14 @@ __metadata: linkType: hard "why-is-node-running@npm:^2.2.2": - version: 2.2.2 - resolution: "why-is-node-running@npm:2.2.2" + version: 2.3.0 + resolution: "why-is-node-running@npm:2.3.0" dependencies: siginfo: ^2.0.0 stackback: 0.0.2 bin: why-is-node-running: cli.js - checksum: 50820428f6a82dfc3cbce661570bcae9b658723217359b6037b67e495255409b4c8bc7931745f5c175df71210450464517cab32b2f7458ac9c40b4925065200a + checksum: 58ebbf406e243ace97083027f0df7ff4c2108baf2595bb29317718ef207cc7a8104e41b711ff65d6fa354f25daa8756b67f2f04931a4fd6ba9d13ae8197496fb languageName: node linkType: hard @@ -21774,17 +22336,17 @@ __metadata: linkType: hard "ws@npm:^6.2.1": - version: 6.2.2 - resolution: "ws@npm:6.2.2" + version: 6.2.3 + resolution: "ws@npm:6.2.3" dependencies: async-limiter: ~1.0.0 - checksum: aec3154ec51477c094ac2cb5946a156e17561a581fa27005cbf22c53ac57f8d4e5f791dd4bbba6a488602cb28778c8ab7df06251d590507c3c550fd8ebeee949 + checksum: bbc96ff5628832d80669a88fd117487bf070492dfaa50df77fa442a2b119792e772f4365521e0a8e025c0d51173c54fa91adab165c11b8e0674685fdd36844a5 languageName: node linkType: hard "ws@npm:^7.4.6": - version: 7.5.9 - resolution: "ws@npm:7.5.9" + version: 7.5.10 + resolution: "ws@npm:7.5.10" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ^5.0.2 @@ -21793,7 +22355,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: c3c100a181b731f40b7f2fddf004aa023f79d64f489706a28bc23ff88e87f6a64b3c6651fbec3a84a53960b75159574d7a7385709847a62ddb7ad6af76f49138 + checksum: f9bb062abf54cc8f02d94ca86dcd349c3945d63851f5d07a3a61c2fcb755b15a88e943a63cf580cbdb5b74436d67ef6b67f745b8f7c0814e411379138e1863cb languageName: node linkType: hard @@ -21905,7 +22467,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^15.4.1": +"yargs@npm:^15.3.1, yargs@npm:^15.4.1": version: 15.4.1 resolution: "yargs@npm:15.4.1" dependencies: @@ -21954,9 +22516,9 @@ __metadata: linkType: hard "yocto-queue@npm:^1.0.0": - version: 1.0.0 - resolution: "yocto-queue@npm:1.0.0" - checksum: 2cac84540f65c64ccc1683c267edce396b26b1e931aa429660aefac8fbe0188167b7aee815a3c22fa59a28a58d898d1a2b1825048f834d8d629f4c2a5d443801 + version: 1.1.1 + resolution: "yocto-queue@npm:1.1.1" + checksum: f2e05b767ed3141e6372a80af9caa4715d60969227f38b1a4370d60bffe153c9c5b33a862905609afc9b375ec57cd40999810d20e5e10229a204e8bde7ef255c languageName: node linkType: hard From 44fc84ca3f7d34c7167aca2fef5127bec9e9e8a8 Mon Sep 17 00:00:00 2001 From: Peyton-McKee Date: Tue, 7 Jan 2025 14:03:29 -0500 Subject: [PATCH 03/11] Merge Conflicts --- .../migration.sql | 79 - .../migration.sql | 81 + .../src/routes/organizations.routes.ts | 2 +- .../src/services/organizations.services.ts | 22 +- src/backend/tests/test-utils.ts | 38 + src/backend/tests/unit/team-type.test.ts | 13 +- src/backend/tests/unit/users.test.ts | 6 +- src/frontend/src/hooks/organizations.hooks.ts | 38 - src/frontend/src/utils/work-package.utils.ts | 2 +- yarn.lock | 1617 ++++++++--------- 10 files changed, 904 insertions(+), 994 deletions(-) delete mode 100644 src/backend/src/prisma/migrations/20241230221615_homepage_redesign/migration.sql rename src/backend/src/prisma/migrations/{20241227031743_stats_page => 20250107183556_stats_page_home_page}/migration.sql (60%) diff --git a/src/backend/src/prisma/migrations/20241230221615_homepage_redesign/migration.sql b/src/backend/src/prisma/migrations/20241230221615_homepage_redesign/migration.sql deleted file mode 100644 index c62b11a4bb..0000000000 --- a/src/backend/src/prisma/migrations/20241230221615_homepage_redesign/migration.sql +++ /dev/null @@ -1,79 +0,0 @@ --- AlterTable -ALTER TABLE "Organization" ADD COLUMN "logoImageId" TEXT, -ADD COLUMN "slackWorkspaceId" TEXT; - --- AlterTable -ALTER TABLE "Project" ADD COLUMN "organizationId" TEXT; - --- CreateTable -CREATE TABLE "Announcement" ( - "announcementId" TEXT NOT NULL, - "text" TEXT NOT NULL, - "dateMessageSent" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "dateDeleted" TIMESTAMP(3), - "senderName" TEXT NOT NULL, - "slackEventId" TEXT NOT NULL, - "slackChannelName" TEXT NOT NULL, - "organizationId" TEXT NOT NULL, - - CONSTRAINT "Announcement_pkey" PRIMARY KEY ("announcementId") -); - --- CreateTable -CREATE TABLE "PopUp" ( - "popUpId" TEXT NOT NULL, - "text" TEXT NOT NULL, - "iconName" TEXT NOT NULL, - "eventLink" TEXT, - "organizationId" TEXT NOT NULL, - - CONSTRAINT "PopUp_pkey" PRIMARY KEY ("popUpId") -); - --- CreateTable -CREATE TABLE "_receivedAnnouncements" ( - "A" TEXT NOT NULL, - "B" TEXT NOT NULL -); - --- CreateTable -CREATE TABLE "_userPopUps" ( - "A" TEXT NOT NULL, - "B" TEXT NOT NULL -); - --- CreateIndex -CREATE UNIQUE INDEX "Announcement_slackEventId_key" ON "Announcement"("slackEventId"); - --- CreateIndex -CREATE UNIQUE INDEX "_receivedAnnouncements_AB_unique" ON "_receivedAnnouncements"("A", "B"); - --- CreateIndex -CREATE INDEX "_receivedAnnouncements_B_index" ON "_receivedAnnouncements"("B"); - --- CreateIndex -CREATE UNIQUE INDEX "_userPopUps_AB_unique" ON "_userPopUps"("A", "B"); - --- CreateIndex -CREATE INDEX "_userPopUps_B_index" ON "_userPopUps"("B"); - --- AddForeignKey -ALTER TABLE "Project" ADD CONSTRAINT "Project_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "Announcement" ADD CONSTRAINT "Announcement_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "PopUp" ADD CONSTRAINT "PopUp_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_receivedAnnouncements" ADD CONSTRAINT "_receivedAnnouncements_A_fkey" FOREIGN KEY ("A") REFERENCES "Announcement"("announcementId") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_receivedAnnouncements" ADD CONSTRAINT "_receivedAnnouncements_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_userPopUps" ADD CONSTRAINT "_userPopUps_A_fkey" FOREIGN KEY ("A") REFERENCES "PopUp"("popUpId") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "_userPopUps" ADD CONSTRAINT "_userPopUps_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/src/backend/src/prisma/migrations/20241227031743_stats_page/migration.sql b/src/backend/src/prisma/migrations/20250107183556_stats_page_home_page/migration.sql similarity index 60% rename from src/backend/src/prisma/migrations/20241227031743_stats_page/migration.sql rename to src/backend/src/prisma/migrations/20250107183556_stats_page_home_page/migration.sql index 0d12c002e3..5ff6ef192b 100644 --- a/src/backend/src/prisma/migrations/20241227031743_stats_page/migration.sql +++ b/src/backend/src/prisma/migrations/20250107183556_stats_page_home_page/migration.sql @@ -1,3 +1,9 @@ +/* + Warnings: + + - You are about to drop the column `logoImage` on the `Organization` table. All the data in the column will be lost. + +*/ -- CreateEnum CREATE TYPE "Graph_Type" AS ENUM ('PROJECT_BUDGET_BY_PROJECT', 'PROJECT_BUDGET_BY_TEAM', 'PROJECT_BUDGET_BY_DIVISION', 'CHANGE_REQUESTS_BY_PROJECT', 'CHANGE_REQUESTS_BY_TEAM', 'CHANGE_REQUESTS_BY_DIVISION', 'REIMBURSEMENT_TOTAL_BY_PROJECT', 'REIMBURSEMENT_TOTAL_BY_TEAM', 'REIMBURSEMENT_TOTAL_BY_DIVISION'); @@ -16,6 +22,11 @@ CREATE TYPE "Graph_Collection_Permission" AS ENUM ('EDIT_GRAPH_COLLECTION', 'CRE -- CreateEnum CREATE TYPE "Special_Permission" AS ENUM ('FINANCE_ONLY'); +-- AlterTable +ALTER TABLE "Organization" DROP COLUMN "logoImage", +ADD COLUMN "logoImageId" TEXT, +ADD COLUMN "slackWorkspaceId" TEXT; + -- AlterTable ALTER TABLE "Team_Type" ADD COLUMN "dateDeleted" TIMESTAMP(3), ADD COLUMN "deletedById" TEXT; @@ -57,18 +68,70 @@ CREATE TABLE "Graph_Collection" ( CONSTRAINT "Graph_Collection_pkey" PRIMARY KEY ("id") ); +-- CreateTable +CREATE TABLE "Announcement" ( + "announcementId" TEXT NOT NULL, + "text" TEXT NOT NULL, + "dateMessageSent" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "dateDeleted" TIMESTAMP(3), + "senderName" TEXT NOT NULL, + "slackEventId" TEXT NOT NULL, + "slackChannelName" TEXT NOT NULL, + "organizationId" TEXT NOT NULL, + + CONSTRAINT "Announcement_pkey" PRIMARY KEY ("announcementId") +); + +-- CreateTable +CREATE TABLE "PopUp" ( + "popUpId" TEXT NOT NULL, + "text" TEXT NOT NULL, + "iconName" TEXT NOT NULL, + "eventLink" TEXT, + "organizationId" TEXT NOT NULL, + + CONSTRAINT "PopUp_pkey" PRIMARY KEY ("popUpId") +); + -- CreateTable CREATE TABLE "_graphCars" ( "A" TEXT NOT NULL, "B" TEXT NOT NULL ); +-- CreateTable +CREATE TABLE "_receivedAnnouncements" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "_userPopUps" ( + "A" TEXT NOT NULL, + "B" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "Announcement_slackEventId_key" ON "Announcement"("slackEventId"); + -- CreateIndex CREATE UNIQUE INDEX "_graphCars_AB_unique" ON "_graphCars"("A", "B"); -- CreateIndex CREATE INDEX "_graphCars_B_index" ON "_graphCars"("B"); +-- CreateIndex +CREATE UNIQUE INDEX "_receivedAnnouncements_AB_unique" ON "_receivedAnnouncements"("A", "B"); + +-- CreateIndex +CREATE INDEX "_receivedAnnouncements_B_index" ON "_receivedAnnouncements"("B"); + +-- CreateIndex +CREATE UNIQUE INDEX "_userPopUps_AB_unique" ON "_userPopUps"("A", "B"); + +-- CreateIndex +CREATE INDEX "_userPopUps_B_index" ON "_userPopUps"("B"); + -- AddForeignKey ALTER TABLE "Team_Type" ADD CONSTRAINT "Team_Type_deletedById_fkey" FOREIGN KEY ("deletedById") REFERENCES "User"("userId") ON DELETE SET NULL ON UPDATE CASCADE; @@ -93,8 +156,26 @@ ALTER TABLE "Graph_Collection" ADD CONSTRAINT "Graph_Collection_userDeletedId_fk -- AddForeignKey ALTER TABLE "Graph_Collection" ADD CONSTRAINT "Graph_Collection_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE RESTRICT ON UPDATE CASCADE; +-- AddForeignKey +ALTER TABLE "Announcement" ADD CONSTRAINT "Announcement_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "PopUp" ADD CONSTRAINT "PopUp_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE RESTRICT ON UPDATE CASCADE; + -- AddForeignKey ALTER TABLE "_graphCars" ADD CONSTRAINT "_graphCars_A_fkey" FOREIGN KEY ("A") REFERENCES "Car"("carId") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "_graphCars" ADD CONSTRAINT "_graphCars_B_fkey" FOREIGN KEY ("B") REFERENCES "Graph"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_receivedAnnouncements" ADD CONSTRAINT "_receivedAnnouncements_A_fkey" FOREIGN KEY ("A") REFERENCES "Announcement"("announcementId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_receivedAnnouncements" ADD CONSTRAINT "_receivedAnnouncements_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_userPopUps" ADD CONSTRAINT "_userPopUps_A_fkey" FOREIGN KEY ("A") REFERENCES "PopUp"("popUpId") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "_userPopUps" ADD CONSTRAINT "_userPopUps_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("userId") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/src/backend/src/routes/organizations.routes.ts b/src/backend/src/routes/organizations.routes.ts index 799044be7b..991eb8f95f 100644 --- a/src/backend/src/routes/organizations.routes.ts +++ b/src/backend/src/routes/organizations.routes.ts @@ -1,6 +1,6 @@ import express from 'express'; import { linkValidators, nonEmptyString, validateInputs } from '../utils/validation.utils'; -import OrganizationsController from '../controllers/organizations.controllerss'; +import OrganizationsController from '../controllers/organizations.controllers'; import multer, { memoryStorage } from 'multer'; import { body } from 'express-validator'; diff --git a/src/backend/src/services/organizations.services.ts b/src/backend/src/services/organizations.services.ts index e22507bffd..31a26eadfb 100644 --- a/src/backend/src/services/organizations.services.ts +++ b/src/backend/src/services/organizations.services.ts @@ -1,7 +1,7 @@ import { Organization, User } from '@prisma/client'; import { LinkCreateArgs, isAdmin } from 'shared'; import prisma from '../prisma/prisma'; -import { AccessDeniedAdminOnlyException, DeletedException, HttpException, DeletedException, NotFoundException } from '../utils/errors.utils'; +import { AccessDeniedAdminOnlyException, DeletedException, HttpException, NotFoundException } from '../utils/errors.utils'; import { userHasPermission } from '../utils/users.utils'; import { createUsefulLinks } from '../utils/organizations.utils'; import { linkTransformer } from '../transformers/links.transformer'; @@ -12,26 +12,6 @@ import { getProjectQueryArgs } from '../prisma-query-args/projects.query-args'; import projectTransformer from '../transformers/projects.transformer'; export default class OrganizationsService { - /** - * Gets the current organization - * @param organizationId the organizationId to be fetched - */ - static async getCurrentOrganization(organizationId: string) { - const organization = await prisma.organization.findUnique({ - where: { organizationId } - }); - - if (!organization) { - throw new NotFoundException('Organization', organizationId); - } - - if (organization.dateDeleted) { - throw new DeletedException('Organization', organizationId); - } - - return organization; - } - /** * Retrieve all the organizations * @returns an array of every organization diff --git a/src/backend/tests/test-utils.ts b/src/backend/tests/test-utils.ts index 549f358794..43a5fba7bb 100644 --- a/src/backend/tests/test-utils.ts +++ b/src/backend/tests/test-utils.ts @@ -570,6 +570,44 @@ export const createTestTask = async ( return task; }; +export const createTestTaskWithOrganization = async (user: User, organization?: Organization) => { + if (!organization) organization = await createTestOrganization(); + const orgId = organization.organizationId; + const team = await TeamsService.createTeam(user, 'Test team', user.userId, 'Test', '', false, organization); + if (!team) throw new Error('Failed to create team'); + const project = await createTestProject(user, organization.organizationId); + if (!project) throw new Error('Failed to create project'); + await ProjectsService.setProjectTeam( + user, + { + carNumber: 0, + projectNumber: 1, + workPackageNumber: 0 + }, + team.teamId, + organization + ); + + const task = await TasksService.createTask( + user, + { + carNumber: 0, + projectNumber: 1, + workPackageNumber: 0 + }, + 'Test task', + 'Test', + TaskPriority.High, + TaskStatus.IN_PROGRESS, + [user.userId], + organization, + new Date() + ); + + if (!task) throw new Error('Failed to create task'); + return { task, organization, orgId }; +}; + export const createSlackMessageEvent = ( channel: string, event_ts: string, diff --git a/src/backend/tests/unit/team-type.test.ts b/src/backend/tests/unit/team-type.test.ts index e422bf701e..82318ad00b 100644 --- a/src/backend/tests/unit/team-type.test.ts +++ b/src/backend/tests/unit/team-type.test.ts @@ -24,6 +24,7 @@ describe('Team Type Tests', () => { await createTestUser(wonderwomanGuest, orgId), 'Team 2', 'Warning icon', + 'team2 Description', organization ) ).rejects.toThrow(new AccessDeniedAdminOnlyException('create a team type')); @@ -34,6 +35,7 @@ describe('Team Type Tests', () => { await createTestUser(supermanAdmin, orgId), 'teamType1', 'YouTubeIcon', + 'teamType1 Description', organization ); await expect( @@ -42,6 +44,7 @@ describe('Team Type Tests', () => { await createTestUser(batmanAppAdmin, orgId), 'teamType1', 'Warning icon', + 'teamType1 Description', organization ) ).rejects.toThrow(new HttpException(400, 'Cannot create a teamType with a name that already exists')); @@ -52,6 +55,7 @@ describe('Team Type Tests', () => { await createTestUser(supermanAdmin, orgId), 'teamType3', 'YouTubeIcon', + 'teamType3 Description', organization ); @@ -60,7 +64,11 @@ describe('Team Type Tests', () => { iconName: 'YouTubeIcon', organizationId: orgId, teamTypeId: result.teamTypeId, - calendarId: null + calendarId: null, + dateDeleted: undefined, + deletedById: undefined, + description: 'teamType3 Description', + imageFileId: null }); }); }); @@ -71,12 +79,14 @@ describe('Team Type Tests', () => { await createTestUser(supermanAdmin, orgId), 'teamType1', 'YouTubeIcon', + 'teamType1 Description', organization ); const teamType2 = await TeamsService.createTeamType( await createTestUser(batmanAppAdmin, orgId), 'teamType2', 'WarningIcon', + 'teamType1 Description', organization ); const result = await TeamsService.getAllTeamTypes(organization); @@ -90,6 +100,7 @@ describe('Team Type Tests', () => { await createTestUser(supermanAdmin, orgId), 'teamType1', 'YouTubeIcon', + 'teamType1 Description', organization ); const result = await TeamsService.getSingleTeamType(teamType1.teamTypeId, organization); diff --git a/src/backend/tests/unit/users.test.ts b/src/backend/tests/unit/users.test.ts index c13a0c857f..bb5de4d78a 100644 --- a/src/backend/tests/unit/users.test.ts +++ b/src/backend/tests/unit/users.test.ts @@ -1,5 +1,5 @@ import { Organization } from '@prisma/client'; -import { createTestOrganization, createTestTask, createTestUser, resetUsers } from '../test-utils'; +import { createTestOrganization, createTestTaskWithOrganization, createTestUser, resetUsers } from '../test-utils'; import { batmanAppAdmin } from '../test-data/users.test-data'; import UsersService from '../../src/services/users.services'; import { NotFoundException } from '../../src/utils/errors.utils'; @@ -26,7 +26,7 @@ describe('User Tests', () => { it("Succeeds and gets user's assigned tasks", async () => { const testBatman = await createTestUser(batmanAppAdmin, orgId); - const { task } = await createTestTask(testBatman, organization); + const { task } = await createTestTaskWithOrganization(testBatman, organization); const userTasks = await UsersService.getUserTasks(testBatman.userId, organization); expect(userTasks).toStrictEqual([task]); @@ -42,7 +42,7 @@ describe('User Tests', () => { it("Succeeds and gets all user' tasks in the list", async () => { const testBatman = await createTestUser(batmanAppAdmin, orgId); - const { task: batmanTask } = await createTestTask(testBatman, organization); + const { task: batmanTask } = await createTestTaskWithOrganization(testBatman, organization); const userTasks = await UsersService.getManyUserTasks([testBatman.userId, testBatman.userId], organization); expect(userTasks).toStrictEqual([batmanTask, batmanTask]); diff --git a/src/frontend/src/hooks/organizations.hooks.ts b/src/frontend/src/hooks/organizations.hooks.ts index a2cb2a087a..c317f040b8 100644 --- a/src/frontend/src/hooks/organizations.hooks.ts +++ b/src/frontend/src/hooks/organizations.hooks.ts @@ -1,43 +1,5 @@ import { useContext, useState } from 'react'; import { OrganizationContext } from '../app/AppOrganizationContext'; -import { useQuery } from 'react-query'; -import { Organization } from 'shared'; -import { getCurrentOrganization } from '../apis/organizations.api'; - -interface OrganizationProvider { - organizationId: string; - selectOrganization: (organizationId: string) => void; -} - -export const useProvideOrganization = (): OrganizationProvider => { - const [organizationId, setOrganizationId] = useState(''); - - const selectOrganization = (organizationId: string) => { - setOrganizationId(organizationId); - localStorage.setItem('organizationId', organizationId); - }; - - return { - organizationId, - selectOrganization - }; -}; - -export const useCurrentOrganization = () => { - return useQuery(['organizations'], async () => { - const { data } = await getCurrentOrganization(); - return data; - }); -}; - -// Hook for child components to get the auth object -export const useOrganization = () => { - const context = useContext(OrganizationContext); - if (context === undefined) throw Error('Organization must be used inside of an organizational context.'); - return context; -}; -import { useContext, useState } from 'react'; -import { OrganizationContext } from '../app/AppOrganizationContext'; import { useMutation, useQuery, useQueryClient } from 'react-query'; import { Organization, Project } from 'shared'; import { diff --git a/src/frontend/src/utils/work-package.utils.ts b/src/frontend/src/utils/work-package.utils.ts index 9625ffde05..5e39ad6b7d 100644 --- a/src/frontend/src/utils/work-package.utils.ts +++ b/src/frontend/src/utils/work-package.utils.ts @@ -1,4 +1,4 @@ -import { addWeeksToDate, WbsElement, WbsElementStatus, WbsElementStatus, wbsPipe, WorkPackage, WorkPackage } from 'shared'; +import { addWeeksToDate, WbsElement, WbsElementStatus, wbsPipe, WorkPackage } from 'shared'; import { WPFormType } from './form'; export const getTitleFromFormType = (formType: WPFormType, wbsElement: WbsElement): string => { diff --git a/yarn.lock b/yarn.lock index fd3a5f15a5..b6dd97e564 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1,3 +1,6 @@ +# This file is generated by running "yarn install" inside your project. +# Manual changes might be lost - proceed with caution! + __metadata: version: 6 cacheKey: 8 @@ -48,17 +51,6 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.10.4, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.5.5": - version: 7.26.2 - resolution: "@babel/code-frame@npm:7.26.2" - dependencies: - "@babel/helper-validator-identifier": ^7.25.9 - js-tokens: ^4.0.0 - picocolors: ^1.0.0 - checksum: db13f5c42d54b76c1480916485e6900748bbcb0014a8aca87f50a091f70ff4e0d0a6db63cade75eb41fcc3d2b6ba0a7f89e343def4f96f00269b41b8ab8dd7b8 - languageName: node - linkType: hard - "@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.25.9, @babel/compat-data@npm:^7.26.0": version: 7.26.3 resolution: "@babel/compat-data@npm:7.26.3" @@ -127,19 +119,6 @@ __metadata: languageName: node linkType: hard -"@babel/generator@npm:^7.12.1, @babel/generator@npm:^7.25.9, @babel/generator@npm:^7.26.0": - version: 7.26.2 - resolution: "@babel/generator@npm:7.26.2" - dependencies: - "@babel/parser": ^7.26.2 - "@babel/types": ^7.26.0 - "@jridgewell/gen-mapping": ^0.3.5 - "@jridgewell/trace-mapping": ^0.3.25 - jsesc: ^3.0.2 - checksum: 6ff850b7d6082619f8c2f518d993cf7254cfbaa20b026282cbef5c9b2197686d076a432b18e36c4d1a42721c016df4f77a8f62c67600775d9683621d534b91b4 - languageName: node - linkType: hard - "@babel/generator@npm:^7.12.1, @babel/generator@npm:^7.26.0, @babel/generator@npm:^7.26.3": version: 7.26.3 resolution: "@babel/generator@npm:7.26.3" @@ -162,16 +141,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.25.9" - dependencies: - "@babel/traverse": ^7.25.9 - "@babel/types": ^7.25.9 - checksum: e1bb465b3b0155702d82cfef09e3813e87a6d777cdd2c513796861eac14953340491eafea1d4109278bf4ceb48b54074c45758f042c0544d00c498090bee5a6f - languageName: node - linkType: hard - "@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-compilation-targets@npm:7.25.9" @@ -305,16 +274,6 @@ __metadata: languageName: node linkType: hard -"@babel/helper-simple-access@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-simple-access@npm:7.25.9" - dependencies: - "@babel/traverse": ^7.25.9 - "@babel/types": ^7.25.9 - checksum: 6d96c94b88e8288d15e5352c1221486bd4f62de8c7dc7c7b9f5b107ce2c79f67fec5ed71a0476e146f1fefbbbf1d69abe35dc821d80ce01fc7f472286c342421 - languageName: node - linkType: hard - "@babel/helper-skip-transparent-expression-wrappers@npm:^7.20.0, @babel/helper-skip-transparent-expression-wrappers@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.25.9" @@ -379,17 +338,6 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.12.3, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.2, @babel/parser@npm:^7.7.0": - version: 7.26.2 - resolution: "@babel/parser@npm:7.26.2" - dependencies: - "@babel/types": ^7.26.0 - bin: - parser: ./bin/babel-parser.js - checksum: c88b5ea0adf357ef909cdc2c31e284a154943edc59f63f6e8a4c20bf773a1b2f3d8c2205e59c09ca7cdad91e7466300114548876529277a80651b6436a48d5d9 - languageName: node - linkType: hard - "@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.12.3, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.3, @babel/parser@npm:^7.7.0": version: 7.26.3 resolution: "@babel/parser@npm:7.26.3" @@ -1666,8 +1614,8 @@ __metadata: linkType: hard "@babel/traverse@npm:^7.1.0, @babel/traverse@npm:^7.12.1, @babel/traverse@npm:^7.25.9, @babel/traverse@npm:^7.7.0": - version: 7.26.3 - resolution: "@babel/traverse@npm:7.26.3" + version: 7.26.4 + resolution: "@babel/traverse@npm:7.26.4" dependencies: "@babel/code-frame": ^7.26.2 "@babel/generator": ^7.26.3 @@ -1676,7 +1624,7 @@ __metadata: "@babel/types": ^7.26.3 debug: ^4.3.1 globals: ^11.1.0 - checksum: 417287d1197b9878af950c0c89bacd67e3749960bdf325eeca646142dbc7e2d959f713ab69c715c2ad48c8a3cd9210ff8a1d2f86968f75aba4f93d5d70cbdfae + checksum: dcdf51b27ab640291f968e4477933465c2910bfdcbcff8f5315d1f29b8ff861864f363e84a71fb489f5e9708e8b36b7540608ce019aa5e57ef7a4ba537e62700 languageName: node linkType: hard @@ -1690,16 +1638,6 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.12.1, @babel/types@npm:^7.12.6, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.4.4, @babel/types@npm:^7.7.0": - version: 7.26.0 - resolution: "@babel/types@npm:7.26.0" - dependencies: - "@babel/helper-string-parser": ^7.25.9 - "@babel/helper-validator-identifier": ^7.25.9 - checksum: a3dd37dabac693018872da96edb8c1843a605c1bfacde6c3f504fba79b972426a6f24df70aa646356c0c1b19bdd2c722c623c684a996c002381071680602280d - languageName: node - linkType: hard - "@bcoe/v8-coverage@npm:^0.2.3": version: 0.2.3 resolution: "@bcoe/v8-coverage@npm:0.2.3" @@ -1761,16 +1699,16 @@ __metadata: languageName: node linkType: hard -"@emotion/cache@npm:^11.11.0, @emotion/cache@npm:^11.13.5": - version: 11.13.5 - resolution: "@emotion/cache@npm:11.13.5" +"@emotion/cache@npm:^11.13.5, @emotion/cache@npm:^11.14.0": + version: 11.14.0 + resolution: "@emotion/cache@npm:11.14.0" dependencies: "@emotion/memoize": ^0.9.0 "@emotion/sheet": ^1.4.0 "@emotion/utils": ^1.4.2 "@emotion/weak-memoize": ^0.4.0 stylis: 4.2.0 - checksum: d4429bcac07730dd65707b8203f855be3d1958183e05d265eeefbeab19822e70c87250fad9abaeaea575d844256d1b8fee348211ef905f7715234df0ee088188 + checksum: 0a81591541ea43bc7851742e6444b7800d72e98006f94e775ae6ea0806662d14e0a86ff940f5f19d33b4bb2c427c882aa65d417e7322a6e0d5f20fe65ed920c9 languageName: node linkType: hard @@ -1798,14 +1736,14 @@ __metadata: linkType: hard "@emotion/react@npm:^11.10.4": - version: 11.13.5 - resolution: "@emotion/react@npm:11.13.5" + version: 11.14.0 + resolution: "@emotion/react@npm:11.14.0" dependencies: "@babel/runtime": ^7.18.3 "@emotion/babel-plugin": ^11.13.5 - "@emotion/cache": ^11.13.5 + "@emotion/cache": ^11.14.0 "@emotion/serialize": ^1.3.3 - "@emotion/use-insertion-effect-with-fallbacks": ^1.1.0 + "@emotion/use-insertion-effect-with-fallbacks": ^1.2.0 "@emotion/utils": ^1.4.2 "@emotion/weak-memoize": ^0.4.0 hoist-non-react-statics: ^3.3.1 @@ -1814,7 +1752,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 25c6572bdb1472d622a41817881628eb311deafe507bbb1be95c6a4c2c23a19bdd011c368d5794c5a17a1fdf2b5db327480a4c0b85d9322078d531289c163225 + checksum: 3cf023b11d132b56168713764d6fced8e5a1f0687dfe0caa2782dfd428c8f9e30f9826a919965a311d87b523cd196722aaf75919cd0f6bd0fd57f8a6a0281500 languageName: node linkType: hard @@ -1839,14 +1777,14 @@ __metadata: linkType: hard "@emotion/styled@npm:^11.10.4": - version: 11.13.5 - resolution: "@emotion/styled@npm:11.13.5" + version: 11.14.0 + resolution: "@emotion/styled@npm:11.14.0" dependencies: "@babel/runtime": ^7.18.3 "@emotion/babel-plugin": ^11.13.5 "@emotion/is-prop-valid": ^1.3.0 "@emotion/serialize": ^1.3.3 - "@emotion/use-insertion-effect-with-fallbacks": ^1.1.0 + "@emotion/use-insertion-effect-with-fallbacks": ^1.2.0 "@emotion/utils": ^1.4.2 peerDependencies: "@emotion/react": ^11.0.0-rc.0 @@ -1854,7 +1792,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 316b3e9f98fc9d3faa54a990ad7f3805611c76a4ebffac9a6c28b6e7e9dd6e9343e9b80c79617af7f64524081a606f3789a89373abf67362fa138028f91b62af + checksum: 9c1b842e942e69fb6037d1ab161046d2bcfeff95fd2ccfdab30acaaf6b89dc07b14bb00f8cc8ec14df11e6746c8e4e1d781bc54d10bd739aab44966ded64d4fb languageName: node linkType: hard @@ -1865,12 +1803,12 @@ __metadata: languageName: node linkType: hard -"@emotion/use-insertion-effect-with-fallbacks@npm:^1.1.0": - version: 1.1.0 - resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.1.0" +"@emotion/use-insertion-effect-with-fallbacks@npm:^1.2.0": + version: 1.2.0 + resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.2.0" peerDependencies: react: ">=16.8.0" - checksum: 63665191773b27de66807c53b90091ef0d10d5161381f62726cfceecfe1d8c944f18594b8021805fc81575b64246fd5ab9c75d60efabec92f940c1c410530949 + checksum: 8ff6aec7f2924526ff8c8f8f93d4b8236376e2e12c435314a18c9a373016e24dfdf984e82bbc83712b8e90ff4783cd765eb39fc7050d1a43245e5728740ddd71 languageName: node linkType: hard @@ -2085,21 +2023,21 @@ __metadata: linkType: hard "@floating-ui/core@npm:^1.6.0": - version: 1.6.8 - resolution: "@floating-ui/core@npm:1.6.8" + version: 1.6.9 + resolution: "@floating-ui/core@npm:1.6.9" dependencies: - "@floating-ui/utils": ^0.2.8 - checksum: 82faa6ea9d57e466779324e51308d6d49c098fb9d184a08d9bb7f4fad83f08cc070fc491f8d56f0cad44a16215fb43f9f829524288413e6c33afcb17303698de + "@floating-ui/utils": ^0.2.9 + checksum: 21cbcac72a40172399570dedf0eb96e4f24b0d829980160e8d14edf08c2955ac6feffb7b94e1530c78fb7944635e52669c9257ad08570e0295efead3b5a9af91 languageName: node linkType: hard "@floating-ui/dom@npm:^1.0.0": - version: 1.6.12 - resolution: "@floating-ui/dom@npm:1.6.12" + version: 1.6.13 + resolution: "@floating-ui/dom@npm:1.6.13" dependencies: "@floating-ui/core": ^1.6.0 - "@floating-ui/utils": ^0.2.8 - checksum: 956514ed100c0c853e73ace9e3c877b7e535444d7c31326f687a7690d49cb1e59ef457e9c93b76141aea0d280e83ed5a983bb852718b62eea581f755454660f6 + "@floating-ui/utils": ^0.2.9 + checksum: eabab9d860d3b5beab1c2d6936287efc4d9ab352de99062380589ef62870d59e8730397489c34a96657e128498001b5672330c4a9da0159fe8b2401ac59fe314 languageName: node linkType: hard @@ -2115,10 +2053,10 @@ __metadata: languageName: node linkType: hard -"@floating-ui/utils@npm:^0.2.8": - version: 0.2.8 - resolution: "@floating-ui/utils@npm:0.2.8" - checksum: deb98bba017c4e073c7ad5740d4dec33a4d3e0942d412e677ac0504f3dade15a68fc6fd164d43c93c0bb0bcc5dc5015c1f4080dfb1a6161140fe660624f7c875 +"@floating-ui/utils@npm:^0.2.9": + version: 0.2.9 + resolution: "@floating-ui/utils@npm:0.2.9" + checksum: d518b80cec5a323e54a069a1dd99a20f8221a4853ed98ac16c75275a0cc22f75de4f8ac5b121b4f8990bd45da7ad1fb015b9a1e4bac27bb1cd62444af84e9784 languageName: node linkType: hard @@ -2519,13 +2457,13 @@ __metadata: linkType: hard "@jridgewell/gen-mapping@npm:^0.3.5": - version: 0.3.5 - resolution: "@jridgewell/gen-mapping@npm:0.3.5" + version: 0.3.8 + resolution: "@jridgewell/gen-mapping@npm:0.3.8" dependencies: "@jridgewell/set-array": ^1.2.1 "@jridgewell/sourcemap-codec": ^1.4.10 "@jridgewell/trace-mapping": ^0.3.24 - checksum: ff7a1764ebd76a5e129c8890aa3e2f46045109dabde62b0b6c6a250152227647178ff2069ea234753a690d8f3c4ac8b5e7b267bbee272bffb7f3b0a370ab6e52 + checksum: c0687b5227461717aa537fe71a42e356bcd1c43293b3353796a148bf3b0d6f59109def46c22f05b60e29a46f19b2e4676d027959a7c53a6c92b9d5b0d87d0420 languageName: node linkType: hard @@ -2635,23 +2573,16 @@ __metadata: languageName: node linkType: hard -"@mui/core-downloads-tracker@npm:^5.16.8": - version: 5.16.8 - resolution: "@mui/core-downloads-tracker@npm:5.16.8" - checksum: 1d099442aabf0a17ae0045d370565fca9c8654a654f88a08595542e6566d159aa632cc7d73aefa247f2ae3ab853709ea2e37118a080891bfbd200c58212202ca - languageName: node - linkType: hard - -"@mui/core-downloads-tracker@npm:^5.16.9": - version: 5.16.9 - resolution: "@mui/core-downloads-tracker@npm:5.16.9" - checksum: 25e7cf746627e12671e2bae4ea8f81967fbb7e05188c268052104d05f249eea1baa3f3d97f66d1242112afa944a7b025a331527392797d620acbcc1dde23a3df +"@mui/core-downloads-tracker@npm:^5.16.14": + version: 5.16.14 + resolution: "@mui/core-downloads-tracker@npm:5.16.14" + checksum: a25658362a69a89f35cdc12ded01b998b7f02df43648029f2523813fc7f259cc85f62bd1877059359d462e7c163e82308bd4cc74fa2d35651d302c5d8bbbc7f4 languageName: node linkType: hard "@mui/icons-material@npm:^5.10.3": - version: 5.16.9 - resolution: "@mui/icons-material@npm:5.16.9" + version: 5.16.14 + resolution: "@mui/icons-material@npm:5.16.14" dependencies: "@babel/runtime": ^7.23.9 peerDependencies: @@ -2661,25 +2592,25 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 84e6884de333afbc819f2871d4449a00960a8c080bfdcb5e9c621a7727179ce2ce97097dc1e4dbcda7d6b234a09aa7593ab6cd172a323429f562625d70511545 + checksum: 14c01298e47972099ce71a8f142e2bb93dfc61a3ac0239030c55b3e5c6719f692e9c2fac131247c52f4922e74b08291ecb1f3398117222cc7baa82ec6f38e073 languageName: node linkType: hard "@mui/material@npm:^5.10.3": - version: 5.16.9 - resolution: "@mui/material@npm:5.16.9" + version: 5.16.14 + resolution: "@mui/material@npm:5.16.14" dependencies: "@babel/runtime": ^7.23.9 - "@mui/core-downloads-tracker": ^5.16.9 - "@mui/system": ^5.16.8 + "@mui/core-downloads-tracker": ^5.16.14 + "@mui/system": ^5.16.14 "@mui/types": ^7.2.15 - "@mui/utils": ^5.16.8 + "@mui/utils": ^5.16.14 "@popperjs/core": ^2.11.8 "@types/react-transition-group": ^4.4.10 clsx: ^2.1.0 csstype: ^3.1.3 prop-types: ^15.8.1 - react-is: ^18.3.1 + react-is: ^19.0.0 react-transition-group: ^4.4.5 peerDependencies: "@emotion/react": ^11.5.0 @@ -2694,16 +2625,16 @@ __metadata: optional: true "@types/react": optional: true - checksum: e3692ba08add0a4b959d7e5f754cf5bf934d30798a9256d1eb5bbf37021f81cf6cc0b86a3cb065815af7f2112c6a359e463a6641618d07559f93516e1374669e + checksum: 0c09353099580ca4f4e214ef1251a5fb1328a5ec19b5195ec4dd628c0ae0b3fae47a8fcae39a807aac1ac8a26bf0109da07eb7eca183975f8cae583d7306de0f languageName: node linkType: hard -"@mui/private-theming@npm:^5.16.8": - version: 5.16.8 - resolution: "@mui/private-theming@npm:5.16.8" +"@mui/private-theming@npm:^5.16.14": + version: 5.16.14 + resolution: "@mui/private-theming@npm:5.16.14" dependencies: "@babel/runtime": ^7.23.9 - "@mui/utils": ^5.16.8 + "@mui/utils": ^5.16.14 prop-types: ^15.8.1 peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -2711,16 +2642,16 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 576cf19188c236482a8a698978d3061c7e8d76ba9d891d323ce96d92d6b80d88e1aa2a67fe4698d76b8a43221ef0f8ed21be74971fc684ce1279dc73fd34316b + checksum: da762a6ccf5d12e2bfad4de29cdfbcfaf7d8229706e1063ecf41a0e724e0cd0317a847a83b0edc553f07e63566dbbb4e6aa15f6b295993224977f969769318be languageName: node linkType: hard -"@mui/styled-engine@npm:^5.16.8": - version: 5.16.8 - resolution: "@mui/styled-engine@npm:5.16.8" +"@mui/styled-engine@npm:^5.16.14": + version: 5.16.14 + resolution: "@mui/styled-engine@npm:5.16.14" dependencies: "@babel/runtime": ^7.23.9 - "@emotion/cache": ^11.11.0 + "@emotion/cache": ^11.13.5 csstype: ^3.1.3 prop-types: ^15.8.1 peerDependencies: @@ -2732,19 +2663,19 @@ __metadata: optional: true "@emotion/styled": optional: true - checksum: 8eab246e985bbe2707af4620a3193166bacefb029df65ac846cfc0ac5d7996fcb72c50327241f60913538f58a2ad9aa6de3ef12b72eb7750c71f8d3c284a420b + checksum: 5868683e6dd4004b34a0ce9de8842c180f7b7618c0b8cff904771659ef2da3aae574ea10b0c5ad6ffe59db396f699773ebb99f3f9d831d8b5adc398ecc618195 languageName: node linkType: hard -"@mui/system@npm:^5.10.16, @mui/system@npm:^5.16.8": - version: 5.16.8 - resolution: "@mui/system@npm:5.16.8" +"@mui/system@npm:^5.10.16, @mui/system@npm:^5.16.14": + version: 5.16.14 + resolution: "@mui/system@npm:5.16.14" dependencies: "@babel/runtime": ^7.23.9 - "@mui/private-theming": ^5.16.8 - "@mui/styled-engine": ^5.16.8 + "@mui/private-theming": ^5.16.14 + "@mui/styled-engine": ^5.16.14 "@mui/types": ^7.2.15 - "@mui/utils": ^5.16.8 + "@mui/utils": ^5.16.14 clsx: ^2.1.0 csstype: ^3.1.3 prop-types: ^15.8.1 @@ -2760,59 +2691,59 @@ __metadata: optional: true "@types/react": optional: true - checksum: 8082b176009fa907cdb0391db59db6cd3589659ad92497caec998c01e1683978ab2eda4ece4d12e523d233b062aa5946d4a438d9a22bf172f0568be1db773e9c + checksum: 20b5d7c1cd1f163c6e28fb267ffb9705e61faf24b62bae5dde08904f2b42a2173ee714d72ae1b5f84a7d50356ad5fa7525a625f9e360d9a886c52b1a1bf6698e languageName: node linkType: hard -"@mui/types@npm:^7.2.14-dev.20240529-082515-213b5e33ab, @mui/types@npm:^7.2.15, @mui/types@npm:^7.2.19": - version: 7.2.19 - resolution: "@mui/types@npm:7.2.19" +"@mui/types@npm:^7.2.14-dev.20240529-082515-213b5e33ab, @mui/types@npm:^7.2.15, @mui/types@npm:^7.2.21": + version: 7.2.21 + resolution: "@mui/types@npm:7.2.21" peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: c3b5723e6f0861d47df834c57878f19347aefecdaf948cf9a25a64b73fbc75791430693d0f540b2bdc01bdfc605dc32bf4ba738113ec415aa9eaf002ce38f064 + checksum: d3c005358777204debb75c684a25ec324df8a0e108440a4b8bd7c658716d6712d993253294fc790c4c9f431156502f1cafd63819643c7a7b9651ac3216ebf9f2 languageName: node linkType: hard -"@mui/utils@npm:^5.10.3, @mui/utils@npm:^5.14.16, @mui/utils@npm:^5.16.8": - version: 5.16.8 - resolution: "@mui/utils@npm:5.16.8" +"@mui/utils@npm:^5.10.3, @mui/utils@npm:^5.14.16, @mui/utils@npm:^5.16.14": + version: 5.16.14 + resolution: "@mui/utils@npm:5.16.14" dependencies: "@babel/runtime": ^7.23.9 "@mui/types": ^7.2.15 "@types/prop-types": ^15.7.12 clsx: ^2.1.1 prop-types: ^15.8.1 - react-is: ^18.3.1 + react-is: ^19.0.0 peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: ed714c6aa583bdf17af9f523c9b9ba3789a47677aa6408bc2afd842fa9eaa6d111361c1309435d481ea03b8c695e22ead98c43dc13239c63a3da481c95e5ad72 + checksum: 311ca0c2c2aa315cdcb351805fc5be2c474492afb0b07ae88d99e7ad7d5ab5bbc477cc3d5f6cbde32e16b65588d52dcc53fbe70c026534134a5e3b942dcc444c languageName: node linkType: hard "@mui/utils@npm:^6.0.0-dev.20240529-082515-213b5e33ab": - version: 6.1.10 - resolution: "@mui/utils@npm:6.1.10" + version: 6.3.1 + resolution: "@mui/utils@npm:6.3.1" dependencies: "@babel/runtime": ^7.26.0 - "@mui/types": ^7.2.19 - "@types/prop-types": ^15.7.13 + "@mui/types": ^7.2.21 + "@types/prop-types": ^15.7.14 clsx: ^2.1.1 prop-types: ^15.8.1 - react-is: ^18.3.1 + react-is: ^19.0.0 peerDependencies: "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0 react: ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 92d3e30ca38cb77e7a9de555cc6b3521d1a50aafedfc769d6b6f55d9fd41e8f71ea3b4e716bedb55e52b88d495a25168d9e2dbd5ed23db496edee6a10f28ec6d + checksum: 49740d9b1b465c06d0cdb56bed32f95e5006af998197357681b313c1c4c618ac200b701169be35a1cfc8beb2026e212d2bacb0069b9284acd13885ab872b1aea languageName: node linkType: hard @@ -3285,9 +3216,9 @@ __metadata: linkType: hard "@rushstack/eslint-patch@npm:^1.1.0": - version: 1.10.4 - resolution: "@rushstack/eslint-patch@npm:1.10.4" - checksum: ec17ac954ed01e9c714e29ae00da29099234a71615d6f61f2da5c7beeef283f5619132114faf9481cb1ca7b4417aed74c05a54d416e4d8facc189bb216d49066 + version: 1.10.5 + resolution: "@rushstack/eslint-patch@npm:1.10.5" + checksum: c7df90efeb77e4311f70549c1b0c41455e3a4f0c0cf2696e560d9a535f129d63ab84c98d0a3de95ed2d369d5281b541af819f99002bfd38e185e59c355b58d69 languageName: node linkType: hard @@ -3856,14 +3787,14 @@ __metadata: linkType: hard "@types/express-serve-static-core@npm:^5.0.0": - version: 5.0.2 - resolution: "@types/express-serve-static-core@npm:5.0.2" + version: 5.0.3 + resolution: "@types/express-serve-static-core@npm:5.0.3" dependencies: "@types/node": "*" "@types/qs": "*" "@types/range-parser": "*" "@types/send": "*" - checksum: 841229b63801b334729e56ec04b5023e084e2962d61dddc95b3508e2fc821e8550bd69c074b6cb0a1c57147eb324c4dc543103d0827e34077f7eb6d230d08a8f + checksum: aacfef3c31d20598a12a3d9f98e924c94b10acd9fc4dca155c91b5cef5861851952821e8c449fa409eb4287b35203d3c470bf2ffa2e69090f8dfa742f1499335 languageName: node linkType: hard @@ -3893,10 +3824,10 @@ __metadata: resolution: "@types/express@npm:4.17.21" dependencies: "@types/body-parser": "*" - "@types/express-serve-static-core": ^5.0.0 + "@types/express-serve-static-core": ^4.17.33 "@types/qs": "*" "@types/serve-static": "*" - checksum: ef68d8e2b7593c930093b1e79bf4df15413773508c9acd6a1a933ed7017f2a4892a8d128b2222d7eab9a3fa43181067a378c2600d9258bd7ae917f170e962df4 + checksum: fb238298630370a7392c7abdc80f495ae6c716723e114705d7e3fb67e3850b3859bbfd29391463a3fb8c0b32051847935933d99e719c0478710f8098ee7091c5 languageName: node linkType: hard @@ -3943,12 +3874,12 @@ __metadata: linkType: hard "@types/hoist-non-react-statics@npm:^3.3.1": - version: 3.3.5 - resolution: "@types/hoist-non-react-statics@npm:3.3.5" + version: 3.3.6 + resolution: "@types/hoist-non-react-statics@npm:3.3.6" dependencies: "@types/react": "*" hoist-non-react-statics: ^3.3.0 - checksum: b645b062a20cce6ab1245ada8274051d8e2e0b2ee5c6bd58215281d0ec6dae2f26631af4e2e7c8abe238cdcee73fcaededc429eef569e70908f82d0cc0ea31d7 + checksum: f03e43bd081876c49584ffa0eb690d69991f258203efca44dcc30efdda49a50653ff06402917d1edc9cb7e2adebbe9e2d1d0e739bc99c1b5372103b1cc534e47 languageName: node linkType: hard @@ -4060,16 +3991,9 @@ __metadata: linkType: hard "@types/lodash@npm:*, @types/lodash@npm:^4.14.175": - version: 4.17.13 - resolution: "@types/lodash@npm:4.17.13" - checksum: d0bf8fbd950be71946e0076b30fd40d492293baea75f05931b6b5b906fd62583708c6229abdb95b30205ad24ce1ed2f48bc9d419364f682320edd03405cc0c7e - languageName: node - linkType: hard - -"@types/lodash@npm:^4.14.175": - version: 4.17.13 - resolution: "@types/lodash@npm:4.17.13" - checksum: d0bf8fbd950be71946e0076b30fd40d492293baea75f05931b6b5b906fd62583708c6229abdb95b30205ad24ce1ed2f48bc9d419364f682320edd03405cc0c7e + version: 4.17.14 + resolution: "@types/lodash@npm:4.17.14" + checksum: 2dbeaff92b31cb523f6bc4bb99a3d8c88fbb001d54f2367a888add85784fb213744a9b1600e1e98b6790ab191fdb6ec839eb0e3d63fcf6fb6cf1ebe4c3d21149 languageName: node linkType: hard @@ -4120,11 +4044,11 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:>=12.0.0": - version: 22.10.1 - resolution: "@types/node@npm:22.10.1" + version: 22.10.5 + resolution: "@types/node@npm:22.10.5" dependencies: undici-types: ~6.20.0 - checksum: 5a9b81500f288a8fb757b61bd939f99f72b6cb59347a5bae52dd1c2c87100ebbaa9da4256ef3cb9add2090e8704cda1d9a1ffc14ccd5db47a6466c8bae10ebcb + checksum: 3b0e966df4e130edac3ad034f1cddbe134e70f11556062468c9fbd749a3b07a44445a3a75a7eec68a104930bf05d4899f1a418c4ae48493d2c8c1544d8594bcc languageName: node linkType: hard @@ -4172,10 +4096,10 @@ __metadata: languageName: node linkType: hard -"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.12, @types/prop-types@npm:^15.7.13": - version: 15.7.13 - resolution: "@types/prop-types@npm:15.7.13" - checksum: 8935cad87c683c665d09a055919d617fe951cb3b2d5c00544e3a913f861a2bd8d2145b51c9aa6d2457d19f3107ab40784c40205e757232f6a80cc8b1c815513c +"@types/prop-types@npm:*, @types/prop-types@npm:^15.7.12, @types/prop-types@npm:^15.7.14": + version: 15.7.14 + resolution: "@types/prop-types@npm:15.7.14" + checksum: d0c5407b9ccc3dd5fae0ccf9b1007e7622ba5e6f1c18399b4f24dff33619d469da4b9fa918a374f19dc0d9fe6a013362aab0b844b606cfc10676efba3f5f736d languageName: node linkType: hard @@ -4249,11 +4173,11 @@ __metadata: linkType: hard "@types/react-transition-group@npm:^4.4.10, @types/react-transition-group@npm:^4.4.8": - version: 4.4.11 - resolution: "@types/react-transition-group@npm:4.4.11" - dependencies: + version: 4.4.12 + resolution: "@types/react-transition-group@npm:4.4.12" + peerDependencies: "@types/react": "*" - checksum: a6e3b2e4363cb019e256ae4f19dadf9d7eb199da1a5e4109bbbf6a132821884044d332e9c74b520b1e5321a7f545502443fd1ce0b18649c8b510fa4220b0e5c2 + checksum: 13d36396cae4d3c316b03d4a0ba299f0d039c59368ba65e04b0c3dc06fd0a16f59d2c669c3e32d6d525a95423f156b84e550d26bff0bdd8df285f305f8f3a0ed languageName: node linkType: hard @@ -5232,12 +5156,10 @@ __metadata: languageName: node linkType: hard -"agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.1": - version: 7.1.1 - resolution: "agent-base@npm:7.1.1" - dependencies: - debug: ^4.3.4 - checksum: 51c158769c5c051482f9ca2e6e1ec085ac72b5a418a9b31b4e82fe6c0a6699adb94c1c42d246699a587b3335215037091c79e0de512c516f73b6ea844202f037 +"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": + version: 7.1.3 + resolution: "agent-base@npm:7.1.3" + checksum: 87bb7ee54f5ecf0ccbfcba0b07473885c43ecd76cb29a8db17d6137a19d9f9cd443a2a7c5fd8a3f24d58ad8145f9eb49116344a66b107e1aeab82cf2383f4753 languageName: node linkType: hard @@ -5503,13 +5425,13 @@ __metadata: languageName: node linkType: hard -"array-buffer-byte-length@npm:^1.0.0, array-buffer-byte-length@npm:^1.0.1": - version: 1.0.1 - resolution: "array-buffer-byte-length@npm:1.0.1" +"array-buffer-byte-length@npm:^1.0.0, array-buffer-byte-length@npm:^1.0.1, array-buffer-byte-length@npm:^1.0.2": + version: 1.0.2 + resolution: "array-buffer-byte-length@npm:1.0.2" dependencies: - call-bind: ^1.0.5 - is-array-buffer: ^3.0.4 - checksum: 53524e08f40867f6a9f35318fafe467c32e45e9c682ba67b11943e167344d2febc0f6977a17e699b05699e805c3e8f073d876f8bbf1b559ed494ad2cd0fae09e + call-bound: ^1.0.3 + is-array-buffer: ^3.0.5 + checksum: 0ae3786195c3211b423e5be8dd93357870e6fb66357d81da968c2c39ef43583ef6eece1f9cb1caccdae4806739c65dea832b44b8593414313cd76a89795fca63 languageName: node linkType: hard @@ -5607,26 +5529,26 @@ __metadata: linkType: hard "array.prototype.flat@npm:^1.3.1, array.prototype.flat@npm:^1.3.2": - version: 1.3.2 - resolution: "array.prototype.flat@npm:1.3.2" + version: 1.3.3 + resolution: "array.prototype.flat@npm:1.3.3" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-shim-unscopables: ^1.0.0 - checksum: 5d6b4bf102065fb3f43764bfff6feb3295d372ce89591e6005df3d0ce388527a9f03c909af6f2a973969a4d178ab232ffc9236654149173e0e187ec3a1a6b87b + call-bind: ^1.0.8 + define-properties: ^1.2.1 + es-abstract: ^1.23.5 + es-shim-unscopables: ^1.0.2 + checksum: 5d5a7829ab2bb271a8d30a1c91e6271cef0ec534593c0fe6d2fb9ebf8bb62c1e5326e2fddcbbcbbe5872ca04f5e6b54a1ecf092e0af704fb538da9b2bfd95b40 languageName: node linkType: hard -"array.prototype.flatmap@npm:^1.3.2": - version: 1.3.2 - resolution: "array.prototype.flatmap@npm:1.3.2" +"array.prototype.flatmap@npm:^1.3.2, array.prototype.flatmap@npm:^1.3.3": + version: 1.3.3 + resolution: "array.prototype.flatmap@npm:1.3.3" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 - es-shim-unscopables: ^1.0.0 - checksum: ce09fe21dc0bcd4f30271f8144083aa8c13d4639074d6c8dc82054b847c7fc9a0c97f857491f4da19d4003e507172a78f4bcd12903098adac8b9cd374f734be3 + call-bind: ^1.0.8 + define-properties: ^1.2.1 + es-abstract: ^1.23.5 + es-shim-unscopables: ^1.0.2 + checksum: 11b4de09b1cf008be6031bb507d997ad6f1892e57dc9153583de6ebca0f74ea403fffe0f203461d359de05048d609f3f480d9b46fed4099652d8b62cc972f284 languageName: node linkType: hard @@ -5658,19 +5580,18 @@ __metadata: languageName: node linkType: hard -"arraybuffer.prototype.slice@npm:^1.0.3": - version: 1.0.3 - resolution: "arraybuffer.prototype.slice@npm:1.0.3" +"arraybuffer.prototype.slice@npm:^1.0.4": + version: 1.0.4 + resolution: "arraybuffer.prototype.slice@npm:1.0.4" dependencies: array-buffer-byte-length: ^1.0.1 - call-bind: ^1.0.5 + call-bind: ^1.0.8 define-properties: ^1.2.1 - es-abstract: ^1.22.3 - es-errors: ^1.2.1 - get-intrinsic: ^1.2.3 + es-abstract: ^1.23.5 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.6 is-array-buffer: ^3.0.4 - is-shared-array-buffer: ^1.0.2 - checksum: 352259cba534dcdd969c92ab002efd2ba5025b2e3b9bead3973150edbdf0696c629d7f4b3f061c5931511e8207bdc2306da614703c820b45dabce39e3daf7e3e + checksum: b1d1fd20be4e972a3779b1569226f6740170dca10f07aa4421d42cefeec61391e79c557cda8e771f5baefe47d878178cd4438f60916ce831813c08132bced765 languageName: node linkType: hard @@ -6495,17 +6416,17 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.12.0, browserslist@npm:^4.24.0, browserslist@npm:^4.24.2, browserslist@npm:^4.6.2, browserslist@npm:^4.6.4": - version: 4.24.2 - resolution: "browserslist@npm:4.24.2" +"browserslist@npm:^4.0.0, browserslist@npm:^4.12.0, browserslist@npm:^4.24.0, browserslist@npm:^4.24.3, browserslist@npm:^4.6.2, browserslist@npm:^4.6.4": + version: 4.24.3 + resolution: "browserslist@npm:4.24.3" dependencies: - caniuse-lite: ^1.0.30001669 - electron-to-chromium: ^1.5.41 - node-releases: ^2.0.18 + caniuse-lite: ^1.0.30001688 + electron-to-chromium: ^1.5.73 + node-releases: ^2.0.19 update-browserslist-db: ^1.1.1 bin: browserslist: cli.js - checksum: cf64085f12132d38638f38937a255edb82c7551b164a98577b055dd79719187a816112f7b97b9739e400c4954cd66479c0d7a843cb816e346f4795dc24fd5d97 + checksum: 016efc9953350e3a7212edcfdd72210cb33b339c1a974a77c0715eb67d23d7e5cd0a073ce1c801ab09235d8c213425ca51b92d41bbb829b833872b45f885fe7c languageName: node linkType: hard @@ -6673,26 +6594,6 @@ __metadata: languageName: node linkType: hard -"cacache@npm:^18.0.0": - version: 18.0.4 - resolution: "cacache@npm:18.0.4" - dependencies: - "@npmcli/fs": ^4.0.0 - fs-minipass: ^3.0.0 - glob: ^10.2.2 - lru-cache: ^10.0.1 - minipass: ^7.0.3 - minipass-collect: ^2.0.1 - minipass-flush: ^1.0.5 - minipass-pipeline: ^1.2.4 - p-map: ^4.0.0 - ssri: ^10.0.0 - tar: ^6.1.11 - unique-filename: ^3.0.0 - checksum: b7422c113b4ec750f33beeca0f426a0024c28e3172f332218f48f963e5b970647fa1ac05679fe5bb448832c51efea9fda4456b9a95c3a1af1105fe6c1833cde2 - languageName: node - linkType: hard - "cacache@npm:^19.0.1": version: 19.0.1 resolution: "cacache@npm:19.0.1" @@ -6730,16 +6631,35 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7": - version: 1.0.7 - resolution: "call-bind@npm:1.0.7" +"call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1": + version: 1.0.1 + resolution: "call-bind-apply-helpers@npm:1.0.1" dependencies: - es-define-property: ^1.0.0 es-errors: ^1.3.0 function-bind: ^1.1.2 + checksum: 3c55343261bb387c58a4762d15ad9d42053659a62681ec5eb50690c6b52a4a666302a01d557133ce6533e8bd04530ee3b209f23dd06c9577a1925556f8fcccdf + languageName: node + linkType: hard + +"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": + version: 1.0.8 + resolution: "call-bind@npm:1.0.8" + dependencies: + call-bind-apply-helpers: ^1.0.0 + es-define-property: ^1.0.0 get-intrinsic: ^1.2.4 - set-function-length: ^1.2.1 - checksum: 295c0c62b90dd6522e6db3b0ab1ce26bdf9e7404215bda13cfee25b626b5ff1a7761324d58d38b1ef1607fc65aca2d06e44d2e18d0dfc6c14b465b00d8660029 + set-function-length: ^1.2.2 + checksum: aa2899bce917a5392fd73bd32e71799c37c0b7ab454e0ed13af7f6727549091182aade8bbb7b55f304a5bc436d543241c14090fb8a3137e9875e23f444f4f5a9 + languageName: node + linkType: hard + +"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3": + version: 1.0.3 + resolution: "call-bound@npm:1.0.3" + dependencies: + call-bind-apply-helpers: ^1.0.1 + get-intrinsic: ^1.2.6 + checksum: a93bbe0f2d0a2d6c144a4349ccd0593d5d0d5d9309b69101710644af8964286420062f2cc3114dca120b9bc8cc07507952d4b1b3ea7672e0d7f6f1675efedb32 languageName: node linkType: hard @@ -6811,10 +6731,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30000981, caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001125, caniuse-lite@npm:^1.0.30001669": - version: 1.0.30001686 - resolution: "caniuse-lite@npm:1.0.30001686" - checksum: 9c8a0ce38ec201d5d7039ebd6da548cbda19c67f1449e2a1dd831a9ff6f1f92048e2896899bbc07795b39cfbdc895225393d89e3af97874865f3a0ea9cf680a8 +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30000981, caniuse-lite@npm:^1.0.30001109, caniuse-lite@npm:^1.0.30001125, caniuse-lite@npm:^1.0.30001688": + version: 1.0.30001690 + resolution: "caniuse-lite@npm:1.0.30001690" + checksum: f2c1b595f15d8de4d9ccd155d61ac9f00ac62f1515870505a0186266fd52aef169fcddc90d8a4814e52b77107244806466fadc2c216662f23f1022a430e735ee languageName: node linkType: hard @@ -7037,11 +6957,11 @@ __metadata: linkType: hard "chokidar@npm:^4.0.0": - version: 4.0.1 - resolution: "chokidar@npm:4.0.1" + version: 4.0.3 + resolution: "chokidar@npm:4.0.3" dependencies: readdirp: ^4.0.1 - checksum: 193da9786b0422a895d59c7552195d15c6c636e6a2293ae43d09e34e243e24ccd02d693f007c767846a65abbeae5fea6bfacb8fc2ddec4ea4d397620d552010d + checksum: a8765e452bbafd04f3f2fad79f04222dd65f43161488bb6014a41099e6ca18d166af613d59a90771908c1c823efa3f46ba36b86ac50b701c20c1b9908c5fe36e languageName: node linkType: hard @@ -7612,18 +7532,18 @@ __metadata: linkType: hard "core-js-compat@npm:^3.38.0, core-js-compat@npm:^3.38.1": - version: 3.39.0 - resolution: "core-js-compat@npm:3.39.0" + version: 3.40.0 + resolution: "core-js-compat@npm:3.40.0" dependencies: - browserslist: ^4.24.2 - checksum: 2d7d087c3271d711d03a55203d4756f6288317a1ce35cdc8bafaf1833ef21fd67a92a50cff8dcf7df1325ac63720906ab3cf514c85b238c95f65fca1040f6ad6 + browserslist: ^4.24.3 + checksum: 7ad00607c481ab2ded13d72be9ca5db5bbf42e221a175e905fb425e1ef520864aea28736c7283f57e9552d570eb6204bed87fbc8b9eab0fcfd9a7830dacccd43 languageName: node linkType: hard "core-js-pure@npm:^3.30.2": - version: 3.39.0 - resolution: "core-js-pure@npm:3.39.0" - checksum: cdcb1eec4eb9308fcf5cfe18a95322c388b05c11e66b5b0ac296a08f8f2106b458ecfe8aca0155d62ed2c5e150485b68073937e7b0a563fbc287563c4475a7c1 + version: 3.40.0 + resolution: "core-js-pure@npm:3.40.0" + checksum: 14e7bd3ef1d39bbeb079b820b0f15f699a0f1589c640818c17679e00ae8c2baf1e0fe8e2734e04562d89b648626d4bc52660e5c44b216107160dbf2fe7e36c5a languageName: node linkType: hard @@ -7635,9 +7555,9 @@ __metadata: linkType: hard "core-js@npm:^3.6.5": - version: 3.39.0 - resolution: "core-js@npm:3.39.0" - checksum: 7a3670e9a2a89e0a049daa288d742d09f6e16d27a8945c5e2ef6fc45dc57e5c4bc5db589da05947486f54ae978d14cf27bd3fb1db0b9907000a611e8af37355b + version: 3.40.0 + resolution: "core-js@npm:3.40.0" + checksum: fc962b93470fd4a129555c765b630c1741fc38706bca68779879f0feaef3b6eec11a33904e3111b2b0e8ba206e8cfbc2a70193271227cfa2f2d13a986f78e557 languageName: node linkType: hard @@ -8168,36 +8088,36 @@ __metadata: languageName: node linkType: hard -"data-view-buffer@npm:^1.0.1": - version: 1.0.1 - resolution: "data-view-buffer@npm:1.0.1" +"data-view-buffer@npm:^1.0.2": + version: 1.0.2 + resolution: "data-view-buffer@npm:1.0.2" dependencies: - call-bind: ^1.0.6 + call-bound: ^1.0.3 es-errors: ^1.3.0 - is-data-view: ^1.0.1 - checksum: ce24348f3c6231223b216da92e7e6a57a12b4af81a23f27eff8feabdf06acfb16c00639c8b705ca4d167f761cfc756e27e5f065d0a1f840c10b907fdaf8b988c + is-data-view: ^1.0.2 + checksum: 1e1cd509c3037ac0f8ba320da3d1f8bf1a9f09b0be09394b5e40781b8cc15ff9834967ba7c9f843a425b34f9fe14ce44cf055af6662c44263424c1eb8d65659b languageName: node linkType: hard -"data-view-byte-length@npm:^1.0.1": - version: 1.0.1 - resolution: "data-view-byte-length@npm:1.0.1" +"data-view-byte-length@npm:^1.0.2": + version: 1.0.2 + resolution: "data-view-byte-length@npm:1.0.2" dependencies: - call-bind: ^1.0.7 + call-bound: ^1.0.3 es-errors: ^1.3.0 - is-data-view: ^1.0.1 - checksum: dbb3200edcb7c1ef0d68979834f81d64fd8cab2f7691b3a4c6b97e67f22182f3ec2c8602efd7b76997b55af6ff8bce485829c1feda4fa2165a6b71fb7baa4269 + is-data-view: ^1.0.2 + checksum: 3600c91ced1cfa935f19ef2abae11029e01738de8d229354d3b2a172bf0d7e4ed08ff8f53294b715569fdf72dfeaa96aa7652f479c0f60570878d88e7e8bddf6 languageName: node linkType: hard -"data-view-byte-offset@npm:^1.0.0": - version: 1.0.0 - resolution: "data-view-byte-offset@npm:1.0.0" +"data-view-byte-offset@npm:^1.0.1": + version: 1.0.1 + resolution: "data-view-byte-offset@npm:1.0.1" dependencies: - call-bind: ^1.0.6 + call-bound: ^1.0.2 es-errors: ^1.3.0 is-data-view: ^1.0.1 - checksum: 7f0bf8720b7414ca719eedf1846aeec392f2054d7af707c5dc9a753cc77eb8625f067fa901e0b5127e831f9da9056138d894b9c2be79c27a21f6db5824f009c2 + checksum: 8dd492cd51d19970876626b5b5169fbb67ca31ec1d1d3238ee6a71820ca8b80cafb141c485999db1ee1ef02f2cc3b99424c5eda8d59e852d9ebb79ab290eb5ee languageName: node linkType: hard @@ -8243,14 +8163,14 @@ __metadata: linkType: hard "debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.0.1, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:^4.3.5": - version: 4.3.7 - resolution: "debug@npm:4.3.7" + version: 4.4.0 + resolution: "debug@npm:4.4.0" dependencies: ms: ^2.1.3 peerDependenciesMeta: supports-color: optional: true - checksum: 822d74e209cd910ef0802d261b150314bbcf36c582ccdbb3e70f0894823c17e49a50d3e66d96b633524263975ca16b6a833f3e3b7e030c157169a5fabac63160 + checksum: fb42df878dd0e22816fc56e1fdca9da73caa85212fbe40c868b1295a6878f9101ae684f4eeef516c13acfc700f5ea07f1136954f43d4cd2d477a811144136479 languageName: node linkType: hard @@ -8396,7 +8316,7 @@ __metadata: languageName: node linkType: hard -"define-properties@npm:^1.1.2, define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": +"define-properties@npm:^1.1.2, define-properties@npm:^1.1.3, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -8773,6 +8693,17 @@ __metadata: languageName: node linkType: hard +"dunder-proto@npm:^1.0.0, dunder-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "dunder-proto@npm:1.0.1" + dependencies: + call-bind-apply-helpers: ^1.0.1 + es-errors: ^1.3.0 + gopd: ^1.2.0 + checksum: 149207e36f07bd4941921b0ca929e3a28f1da7bd6b6ff8ff7f4e2f2e460675af4576eeba359c635723dc189b64cdd4787e0255897d5b135ccc5d15cb8685fc90 + languageName: node + linkType: hard + "duplexer@npm:^0.1.1": version: 0.1.2 resolution: "duplexer@npm:0.1.2" @@ -8822,10 +8753,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.3.564, electron-to-chromium@npm:^1.5.41": - version: 1.5.68 - resolution: "electron-to-chromium@npm:1.5.68" - checksum: c2851bdd9aab164de4590d3a114a794b01afebc9ef86e61c1d665b132ede3668399abc11451742bf660cecda70e5516765ad2dfc6d23ba4d396734ab701bf393 +"electron-to-chromium@npm:^1.3.564, electron-to-chromium@npm:^1.5.73": + version: 1.5.78 + resolution: "electron-to-chromium@npm:1.5.78" + checksum: 84034073990470a9bad79bbe9c7b3fcc7a92aea9ccb745ce411415562e2112ad089e924817c7e34ba9e08e581b9fc88f33c3acdc6d6ef2812d559bd5cfb6f801 languageName: node linkType: hard @@ -8982,57 +8913,62 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.17.2, es-abstract@npm:^1.17.5, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.23.0, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5": - version: 1.23.5 - resolution: "es-abstract@npm:1.23.5" +"es-abstract@npm:^1.17.2, es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9": + version: 1.23.9 + resolution: "es-abstract@npm:1.23.9" dependencies: - array-buffer-byte-length: ^1.0.1 - arraybuffer.prototype.slice: ^1.0.3 + array-buffer-byte-length: ^1.0.2 + arraybuffer.prototype.slice: ^1.0.4 available-typed-arrays: ^1.0.7 - call-bind: ^1.0.7 - data-view-buffer: ^1.0.1 - data-view-byte-length: ^1.0.1 - data-view-byte-offset: ^1.0.0 - es-define-property: ^1.0.0 + call-bind: ^1.0.8 + call-bound: ^1.0.3 + data-view-buffer: ^1.0.2 + data-view-byte-length: ^1.0.2 + data-view-byte-offset: ^1.0.1 + es-define-property: ^1.0.1 es-errors: ^1.3.0 es-object-atoms: ^1.0.0 - es-set-tostringtag: ^2.0.3 - es-to-primitive: ^1.2.1 - function.prototype.name: ^1.1.6 - get-intrinsic: ^1.2.4 - get-symbol-description: ^1.0.2 + es-set-tostringtag: ^2.1.0 + es-to-primitive: ^1.3.0 + function.prototype.name: ^1.1.8 + get-intrinsic: ^1.2.7 + get-proto: ^1.0.0 + get-symbol-description: ^1.1.0 globalthis: ^1.0.4 - gopd: ^1.0.1 + gopd: ^1.2.0 has-property-descriptors: ^1.0.2 - has-proto: ^1.0.3 - has-symbols: ^1.0.3 + has-proto: ^1.2.0 + has-symbols: ^1.1.0 hasown: ^2.0.2 - internal-slot: ^1.0.7 - is-array-buffer: ^3.0.4 + internal-slot: ^1.1.0 + is-array-buffer: ^3.0.5 is-callable: ^1.2.7 - is-data-view: ^1.0.1 - is-negative-zero: ^2.0.3 - is-regex: ^1.1.4 - is-shared-array-buffer: ^1.0.3 - is-string: ^1.0.7 - is-typed-array: ^1.1.13 - is-weakref: ^1.0.2 + is-data-view: ^1.0.2 + is-regex: ^1.2.1 + is-shared-array-buffer: ^1.0.4 + is-string: ^1.1.1 + is-typed-array: ^1.1.15 + is-weakref: ^1.1.0 + math-intrinsics: ^1.1.0 object-inspect: ^1.13.3 object-keys: ^1.1.1 - object.assign: ^4.1.5 + object.assign: ^4.1.7 + own-keys: ^1.0.1 regexp.prototype.flags: ^1.5.3 - safe-array-concat: ^1.1.2 - safe-regex-test: ^1.0.3 - string.prototype.trim: ^1.2.9 - string.prototype.trimend: ^1.0.8 + safe-array-concat: ^1.1.3 + safe-push-apply: ^1.0.0 + safe-regex-test: ^1.1.0 + set-proto: ^1.0.0 + string.prototype.trim: ^1.2.10 + string.prototype.trimend: ^1.0.9 string.prototype.trimstart: ^1.0.8 - typed-array-buffer: ^1.0.2 - typed-array-byte-length: ^1.0.1 - typed-array-byte-offset: ^1.0.2 - typed-array-length: ^1.0.6 - unbox-primitive: ^1.0.2 - which-typed-array: ^1.1.15 - checksum: 17c81f8a42f0322fd11e0025d3c2229ecfd7923560c710906b8e68660e19c42322750dcedf8ba5cf28bae50d5befd8174d3903ac50dbabb336d3efc3aabed2ee + typed-array-buffer: ^1.0.3 + typed-array-byte-length: ^1.0.3 + typed-array-byte-offset: ^1.0.4 + typed-array-length: ^1.0.7 + unbox-primitive: ^1.1.0 + which-typed-array: ^1.1.18 + checksum: f3ee2614159ca197f97414ab36e3f406ee748ce2f97ffbf09e420726db5a442ce13f1e574601468bff6e6eb81588e6c9ce1ac6c03868a37c7cd48ac679f8485a languageName: node linkType: hard @@ -9043,16 +8979,14 @@ __metadata: languageName: node linkType: hard -"es-define-property@npm:^1.0.0": - version: 1.0.0 - resolution: "es-define-property@npm:1.0.0" - dependencies: - get-intrinsic: ^1.2.4 - checksum: f66ece0a887b6dca71848fa71f70461357c0e4e7249696f81bad0a1f347eed7b31262af4a29f5d726dc026426f085483b6b90301855e647aa8e21936f07293c6 +"es-define-property@npm:^1.0.0, es-define-property@npm:^1.0.1": + version: 1.0.1 + resolution: "es-define-property@npm:1.0.1" + checksum: 0512f4e5d564021c9e3a644437b0155af2679d10d80f21adaf868e64d30efdfbd321631956f20f42d655fedb2e3a027da479fad3fa6048f768eb453a80a5f80a languageName: node linkType: hard -"es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": +"es-errors@npm:^1.3.0": version: 1.3.0 resolution: "es-errors@npm:1.3.0" checksum: ec1414527a0ccacd7f15f4a3bc66e215f04f595ba23ca75cdae0927af099b5ec865f9f4d33e9d7e86f512f252876ac77d4281a7871531a50678132429b1271b5 @@ -9076,26 +9010,27 @@ __metadata: languageName: node linkType: hard -"es-iterator-helpers@npm:^1.1.0": - version: 1.2.0 - resolution: "es-iterator-helpers@npm:1.2.0" +"es-iterator-helpers@npm:^1.2.1": + version: 1.2.1 + resolution: "es-iterator-helpers@npm:1.2.1" dependencies: - call-bind: ^1.0.7 + call-bind: ^1.0.8 + call-bound: ^1.0.3 define-properties: ^1.2.1 - es-abstract: ^1.23.3 + es-abstract: ^1.23.6 es-errors: ^1.3.0 es-set-tostringtag: ^2.0.3 function-bind: ^1.1.2 - get-intrinsic: ^1.2.4 + get-intrinsic: ^1.2.6 globalthis: ^1.0.4 - gopd: ^1.0.1 + gopd: ^1.2.0 has-property-descriptors: ^1.0.2 - has-proto: ^1.0.3 - has-symbols: ^1.0.3 - internal-slot: ^1.0.7 - iterator.prototype: ^1.1.3 - safe-array-concat: ^1.1.2 - checksum: c5f5ff10d57f956539581aca7a2d8726c5a8a3e49e6285700d74dcd8b64c7a337b9ab5e81b459b079dac745d2fe02e4f6b80a842e3df45d9cfe3f12325fda8c0 + has-proto: ^1.2.0 + has-symbols: ^1.1.0 + internal-slot: ^1.1.0 + iterator.prototype: ^1.1.4 + safe-array-concat: ^1.1.3 + checksum: 952808dd1df3643d67ec7adf20c30b36e5eecadfbf36354e6f39ed3266c8e0acf3446ce9bc465e38723d613cb1d915c1c07c140df65bdce85da012a6e7bda62b languageName: node linkType: hard @@ -9108,18 +9043,19 @@ __metadata: languageName: node linkType: hard -"es-set-tostringtag@npm:^2.0.3": - version: 2.0.3 - resolution: "es-set-tostringtag@npm:2.0.3" +"es-set-tostringtag@npm:^2.0.3, es-set-tostringtag@npm:^2.1.0": + version: 2.1.0 + resolution: "es-set-tostringtag@npm:2.1.0" dependencies: - get-intrinsic: ^1.2.4 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.6 has-tostringtag: ^1.0.2 - hasown: ^2.0.1 - checksum: 7227fa48a41c0ce83e0377b11130d324ac797390688135b8da5c28994c0165be8b252e15cd1de41e1325e5a5412511586960213e88f9ab4a5e7d028895db5129 + hasown: ^2.0.2 + checksum: 789f35de4be3dc8d11fdcb91bc26af4ae3e6d602caa93299a8c45cf05d36cc5081454ae2a6d3afa09cceca214b76c046e4f8151e092e6fc7feeb5efb9e794fc6 languageName: node linkType: hard -"es-shim-unscopables@npm:^1.0.0, es-shim-unscopables@npm:^1.0.2": +"es-shim-unscopables@npm:^1.0.2": version: 1.0.2 resolution: "es-shim-unscopables@npm:1.0.2" dependencies: @@ -9128,7 +9064,7 @@ __metadata: languageName: node linkType: hard -"es-to-primitive@npm:^1.2.1": +"es-to-primitive@npm:^1.3.0": version: 1.3.0 resolution: "es-to-primitive@npm:1.3.0" dependencies: @@ -9767,30 +9703,30 @@ __metadata: linkType: hard "eslint-plugin-react@npm:^7.21.5, eslint-plugin-react@npm:^7.27.1": - version: 7.37.2 - resolution: "eslint-plugin-react@npm:7.37.2" + version: 7.37.3 + resolution: "eslint-plugin-react@npm:7.37.3" dependencies: array-includes: ^3.1.8 array.prototype.findlast: ^1.2.5 - array.prototype.flatmap: ^1.3.2 + array.prototype.flatmap: ^1.3.3 array.prototype.tosorted: ^1.1.4 doctrine: ^2.1.0 - es-iterator-helpers: ^1.1.0 + es-iterator-helpers: ^1.2.1 estraverse: ^5.3.0 hasown: ^2.0.2 jsx-ast-utils: ^2.4.1 || ^3.0.0 minimatch: ^3.1.2 object.entries: ^1.1.8 object.fromentries: ^2.0.8 - object.values: ^1.2.0 + object.values: ^1.2.1 prop-types: ^15.8.1 resolve: ^2.0.0-next.5 semver: ^6.3.1 - string.prototype.matchall: ^4.0.11 + string.prototype.matchall: ^4.0.12 string.prototype.repeat: ^1.0.0 peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - checksum: 7f5203afee7fbe3702b27fdd2b9a3c0ccbbb47d0672f58311b9d8a08dea819c9da4a87c15e8bd508f2562f327a9d29ee8bd9cd189bf758d8dc903de5648b0bfa + checksum: 670dcee215f560a394b8b9966aecfc3c5ee5c15603a690f5333b0e16863275958f9c1853b12355eb0e36ef74dfac8bf645e4f440cb9b985a3bae2ac09d5ed55a languageName: node linkType: hard @@ -10232,7 +10168,7 @@ __metadata: languageName: node linkType: hard -"express@npm:^4.0.0": +"express@npm:^4.0.0, express@npm:^4.17.1": version: 4.21.2 resolution: "express@npm:4.21.2" dependencies: @@ -10271,45 +10207,6 @@ __metadata: languageName: node linkType: hard -"express@npm:^4.17.1": - version: 4.21.1 - resolution: "express@npm:4.21.1" - dependencies: - accepts: ~1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.3 - content-disposition: 0.5.4 - content-type: ~1.0.4 - cookie: 0.7.1 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: ~2.0.0 - escape-html: ~1.0.3 - etag: ~1.8.1 - finalhandler: 1.3.1 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.3 - methods: ~1.1.2 - on-finished: 2.4.1 - parseurl: ~1.3.3 - path-to-regexp: 0.1.10 - proxy-addr: ~2.0.7 - qs: 6.13.0 - range-parser: ~1.2.1 - safe-buffer: 5.2.1 - send: 0.19.0 - serve-static: 1.16.2 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: ~1.6.18 - utils-merge: 1.0.1 - vary: ~1.1.2 - checksum: 5ac2b26d8aeddda5564fc0907227d29c100f90c0ead2ead9d474dc5108e8fb306c2de2083c4e3ba326e0906466f2b73417dbac16961f4075ff9f03785fd940fe - languageName: node - linkType: hard - "express@npm:^5.0.0": version: 5.0.1 resolution: "express@npm:5.0.1" @@ -10427,15 +10324,15 @@ __metadata: linkType: hard "fast-glob@npm:^3.1.1, fast-glob@npm:^3.2.9": - version: 3.3.2 - resolution: "fast-glob@npm:3.3.2" + version: 3.3.3 + resolution: "fast-glob@npm:3.3.3" dependencies: "@nodelib/fs.stat": ^2.0.2 "@nodelib/fs.walk": ^1.2.3 glob-parent: ^5.1.2 merge2: ^1.3.0 - micromatch: ^4.0.4 - checksum: 900e4979f4dbc3313840078419245621259f349950411ca2fa445a2f9a1a6d98c3b5e7e0660c5ccd563aa61abe133a21765c6c0dec8e57da1ba71d8000b05ec1 + micromatch: ^4.0.8 + checksum: 0704d7b85c0305fd2cef37777337dfa26230fdd072dce9fb5c82a4b03156f3ffb8ed3e636033e65d45d2a5805a4e475825369a27404c0307f2db0c8eb3366fbd languageName: node linkType: hard @@ -10468,9 +10365,9 @@ __metadata: linkType: hard "fast-uri@npm:^3.0.1": - version: 3.0.3 - resolution: "fast-uri@npm:3.0.3" - checksum: c52e6c86465f5c240e84a4485fb001088cc743d261a4b54b0050ce4758b1648bdbe53da1328ef9620149dca1435e3de64184f226d7c0a3656cb5837b3491e149 + version: 3.0.5 + resolution: "fast-uri@npm:3.0.5" + checksum: b56cda8e7355bad9adcc3c2eacd94cb592eaa9536497a4779a9527784f4f95a3755f30525c63583bd85807c493b396ac89926c970f19a60905ed875121ca78fd languageName: node linkType: hard @@ -10482,11 +10379,11 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.17.1 - resolution: "fastq@npm:1.17.1" + version: 1.18.0 + resolution: "fastq@npm:1.18.0" dependencies: reusify: ^1.0.4 - checksum: a8c5b26788d5a1763f88bae56a8ddeee579f935a831c5fe7a8268cea5b0a91fbfe705f612209e02d639b881d7b48e461a50da4a10cfaa40da5ca7cc9da098d88 + checksum: fb8d94318c2e5545a1913c1647b35e8b7825caaba888a98ef9887085e57f5a82104aefbb05f26c81d4e220f02b2ea6f2c999132186d8c77e6c681d91870191ba languageName: node linkType: hard @@ -11045,15 +10942,17 @@ __metadata: languageName: node linkType: hard -"function.prototype.name@npm:^1.1.6": - version: 1.1.6 - resolution: "function.prototype.name@npm:1.1.6" +"function.prototype.name@npm:^1.1.6, function.prototype.name@npm:^1.1.8": + version: 1.1.8 + resolution: "function.prototype.name@npm:1.1.8" dependencies: - call-bind: ^1.0.2 - define-properties: ^1.2.0 - es-abstract: ^1.22.1 + call-bind: ^1.0.8 + call-bound: ^1.0.3 + define-properties: ^1.2.1 functions-have-names: ^1.2.3 - checksum: 7a3f9bd98adab09a07f6e1f03da03d3f7c26abbdeaeee15223f6c04a9fb5674792bdf5e689dac19b97ac71de6aad2027ba3048a9b883aa1b3173eed6ab07f479 + hasown: ^2.0.2 + is-callable: ^1.2.7 + checksum: 3a366535dc08b25f40a322efefa83b2da3cd0f6da41db7775f2339679120ef63b6c7e967266182609e655b8f0a8f65596ed21c7fd72ad8bd5621c2340edd4010 languageName: node linkType: hard @@ -11114,16 +11013,21 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": - version: 1.2.4 - resolution: "get-intrinsic@npm:1.2.4" +"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7": + version: 1.2.7 + resolution: "get-intrinsic@npm:1.2.7" dependencies: + call-bind-apply-helpers: ^1.0.1 + es-define-property: ^1.0.1 es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 function-bind: ^1.1.2 - has-proto: ^1.0.1 - has-symbols: ^1.0.3 - hasown: ^2.0.0 - checksum: 414e3cdf2c203d1b9d7d33111df746a4512a1aa622770b361dadddf8ed0b5aeb26c560f49ca077e24bfafb0acb55ca908d1f709216ccba33ffc548ec8a79a951 + get-proto: ^1.0.0 + gopd: ^1.2.0 + has-symbols: ^1.1.0 + hasown: ^2.0.2 + math-intrinsics: ^1.1.0 + checksum: a1597b3b432074f805b6a0ba1182130dd6517c0ea0c4eecc4b8834c803913e1ea62dfc412865be795b3dacb1555a21775b70cf9af7a18b1454ff3414e5442d4a languageName: node linkType: hard @@ -11141,6 +11045,16 @@ __metadata: languageName: node linkType: hard +"get-proto@npm:^1.0.0, get-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "get-proto@npm:1.0.1" + dependencies: + dunder-proto: ^1.0.1 + es-object-atoms: ^1.0.0 + checksum: 4fc96afdb58ced9a67558698b91433e6b037aaa6f1493af77498d7c85b141382cf223c0e5946f334fb328ee85dfe6edd06d218eaf09556f4bc4ec6005d7f5f7b + languageName: node + linkType: hard + "get-stream@npm:^4.0.0": version: 4.1.0 resolution: "get-stream@npm:4.1.0" @@ -11159,14 +11073,14 @@ __metadata: languageName: node linkType: hard -"get-symbol-description@npm:^1.0.2": - version: 1.0.2 - resolution: "get-symbol-description@npm:1.0.2" +"get-symbol-description@npm:^1.1.0": + version: 1.1.0 + resolution: "get-symbol-description@npm:1.1.0" dependencies: - call-bind: ^1.0.5 + call-bound: ^1.0.3 es-errors: ^1.3.0 - get-intrinsic: ^1.2.4 - checksum: e1cb53bc211f9dbe9691a4f97a46837a553c4e7caadd0488dc24ac694db8a390b93edd412b48dcdd0b4bbb4c595de1709effc75fc87c0839deedc6968f5bd973 + get-intrinsic: ^1.2.6 + checksum: 655ed04db48ee65ef2ddbe096540d4405e79ba0a7f54225775fef43a7e2afcb93a77d141c5f05fdef0afce2eb93bcbfb3597142189d562ac167ff183582683cd languageName: node linkType: hard @@ -11196,7 +11110,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10": +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": version: 10.4.5 resolution: "glob@npm:10.4.5" dependencies: @@ -11212,25 +11126,9 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": - version: 10.4.5 - resolution: "glob@npm:10.4.5" - dependencies: - foreground-child: ^3.1.0 - jackspeak: ^3.1.2 - minimatch: ^9.0.4 - minipass: ^7.1.2 - package-json-from-dist: ^1.0.0 - path-scurry: ^1.11.1 - bin: - glob: dist/esm/bin.mjs - checksum: 0bc725de5e4862f9f387fd0f2b274baf16850dcd2714502ccf471ee401803997983e2c05590cb65f9675a3c6f2a58e7a53f9e365704108c6ad3cbf1d60934c4a - languageName: node - linkType: hard - -"glob@npm:^7.0.3, glob@npm:^7.1.1, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.2.0": - version: 7.2.3 - resolution: "glob@npm:7.2.3" +"glob@npm:^7.0.3, glob@npm:^7.1.1, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.4, glob@npm:^7.1.6, glob@npm:^7.2.0": + version: 7.2.3 + resolution: "glob@npm:7.2.3" dependencies: fs.realpath: ^1.0.0 inflight: ^1.0.4 @@ -11279,9 +11177,9 @@ __metadata: linkType: hard "globals@npm:^15.11.0": - version: 15.13.0 - resolution: "globals@npm:15.13.0" - checksum: 3f98514ce25a21150b246fbd63aeaeb271a93b3340cf7f4f6e9934d3b37dbb4b0fddef9c470183097dcfd2e8757bb86bbae701588f0e376667d8d9d6f665db3b + version: 15.14.0 + resolution: "globals@npm:15.14.0" + checksum: fa993433a01bf4a118904fbafbcff34db487fce83f73da75fb4a8653afc6dcd72905e6208c49bab307ff0980928273d0ecd1cfc67e1a4782dabfbd92c234ab68 languageName: node linkType: hard @@ -11388,7 +11286,7 @@ __metadata: languageName: node linkType: hard -"gopd@npm:^1.0.1, gopd@npm:^1.1.0": +"gopd@npm:^1.0.1, gopd@npm:^1.2.0": version: 1.2.0 resolution: "gopd@npm:1.2.0" checksum: cc6d8e655e360955bdccaca51a12a474268f95bb793fc3e1f2bdadb075f28bfd1fd988dab872daf77a61d78cbaf13744bc8727a17cfb1d150d76047d805375f3 @@ -11410,9 +11308,9 @@ __metadata: linkType: hard "graphql@npm:^16.3.0": - version: 16.9.0 - resolution: "graphql@npm:16.9.0" - checksum: 8cb3d54100e9227310383ce7f791ca48d12f15ed9f2021f23f8735f1121aafe4e5e611a853081dd935ce221724ea1ae4638faef5d2921fb1ad7c26b5f46611e9 + version: 16.10.0 + resolution: "graphql@npm:16.10.0" + checksum: 969c2d1061d69ad6fe08a7fe642428212b0b8485a2f9b5d8650203eb6c3221479e81ec6a757708f849d84b85afcb3ebc5a8ff2f71778bb66c5e4850f051c170e languageName: node linkType: hard @@ -11468,9 +11366,9 @@ __metadata: linkType: hard "has-bigints@npm:^1.0.2": - version: 1.0.2 - resolution: "has-bigints@npm:1.0.2" - checksum: 390e31e7be7e5c6fe68b81babb73dfc35d413604d7ee5f56da101417027a4b4ce6a27e46eff97ad040c835b5d228676eae99a9b5c3bc0e23c8e81a49241ff45b + version: 1.1.0 + resolution: "has-bigints@npm:1.1.0" + checksum: 79730518ae02c77e4af6a1d1a0b6a2c3e1509785532771f9baf0241e83e36329542c3d7a0e723df8cbc85f74eff4f177828a2265a01ba576adbdc2d40d86538b languageName: node linkType: hard @@ -11504,23 +11402,23 @@ __metadata: languageName: node linkType: hard -"has-proto@npm:^1.0.1, has-proto@npm:^1.0.3": - version: 1.1.0 - resolution: "has-proto@npm:1.1.0" +"has-proto@npm:^1.2.0": + version: 1.2.0 + resolution: "has-proto@npm:1.2.0" dependencies: - call-bind: ^1.0.7 - checksum: 0335b8acd01a0de9bb6f7f89c4ef4f1512b48cec25f1c23e847a68d65afb8c579f168907e79969b01dc7025d707b48c71d481bca140579a40d735b071b2cc1bc + dunder-proto: ^1.0.0 + checksum: f55010cb94caa56308041d77967c72a02ffd71386b23f9afa8447e58bc92d49d15c19bf75173713468e92fe3fb1680b03b115da39c21c32c74886d1d50d3e7ff languageName: node linkType: hard -"has-symbols@npm:^1.0.1, has-symbols@npm:^1.0.3": +"has-symbols@npm:^1.0.1, has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": version: 1.1.0 resolution: "has-symbols@npm:1.1.0" checksum: b2316c7302a0e8ba3aaba215f834e96c22c86f192e7310bdf689dd0e6999510c89b00fbc5742571507cebf25764d68c988b3a0da217369a73596191ac0ce694b languageName: node linkType: hard -"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.2": +"has-tostringtag@npm:^1.0.2": version: 1.0.2 resolution: "has-tostringtag@npm:1.0.2" dependencies: @@ -11606,7 +11504,7 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0, hasown@npm:^2.0.1, hasown@npm:^2.0.2": +"hasown@npm:^2.0.0, hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" dependencies: @@ -11915,12 +11813,12 @@ __metadata: linkType: hard "https-proxy-agent@npm:^7.0.1": - version: 7.0.5 - resolution: "https-proxy-agent@npm:7.0.5" + version: 7.0.6 + resolution: "https-proxy-agent@npm:7.0.6" dependencies: - agent-base: ^7.0.2 + agent-base: ^7.1.2 debug: 4 - checksum: 2e1a28960f13b041a50702ee74f240add8e75146a5c37fc98f1960f0496710f6918b3a9fe1e5aba41e50f58e6df48d107edd9c405c5f0d73ac260dabf2210857 + checksum: b882377a120aa0544846172e5db021fa8afbf83fea2a897d397bd2ddd8095ab268c24bc462f40a15f2a8c600bf4aa05ce52927f70038d4014e68aefecfa94e8d languageName: node linkType: hard @@ -12193,14 +12091,14 @@ __metadata: languageName: node linkType: hard -"internal-slot@npm:^1.0.4, internal-slot@npm:^1.0.7": - version: 1.0.7 - resolution: "internal-slot@npm:1.0.7" +"internal-slot@npm:^1.1.0": + version: 1.1.0 + resolution: "internal-slot@npm:1.1.0" dependencies: es-errors: ^1.3.0 - hasown: ^2.0.0 - side-channel: ^1.0.4 - checksum: cadc5eea5d7d9bc2342e93aae9f31f04c196afebb11bde97448327049f492cd7081e18623ae71388aac9cd237b692ca3a105be9c68ac39c1dec679d7409e33eb + hasown: ^2.0.2 + side-channel: ^1.1.0 + checksum: 8e0991c2d048cc08dab0a91f573c99f6a4215075887517ea4fa32203ce8aea60fa03f95b177977fa27eb502e5168366d0f3e02c762b799691411d49900611861 languageName: node linkType: hard @@ -12276,22 +12174,23 @@ __metadata: linkType: hard "is-arguments@npm:^1.0.4, is-arguments@npm:^1.1.1": - version: 1.1.1 - resolution: "is-arguments@npm:1.1.1" + version: 1.2.0 + resolution: "is-arguments@npm:1.2.0" dependencies: - call-bind: ^1.0.2 - has-tostringtag: ^1.0.0 - checksum: 7f02700ec2171b691ef3e4d0e3e6c0ba408e8434368504bb593d0d7c891c0dbfda6d19d30808b904a6cb1929bca648c061ba438c39f296c2a8ca083229c49f27 + call-bound: ^1.0.2 + has-tostringtag: ^1.0.2 + checksum: aae9307fedfe2e5be14aebd0f48a9eeedf6b8c8f5a0b66257b965146d1e94abdc3f08e3dce3b1d908e1fa23c70039a88810ee1d753905758b9b6eebbab0bafeb languageName: node linkType: hard -"is-array-buffer@npm:^3.0.2, is-array-buffer@npm:^3.0.4": - version: 3.0.4 - resolution: "is-array-buffer@npm:3.0.4" +"is-array-buffer@npm:^3.0.2, is-array-buffer@npm:^3.0.4, is-array-buffer@npm:^3.0.5": + version: 3.0.5 + resolution: "is-array-buffer@npm:3.0.5" dependencies: - call-bind: ^1.0.2 - get-intrinsic: ^1.2.1 - checksum: e4e3e6ef0ff2239e75371d221f74bc3c26a03564a22efb39f6bb02609b598917ddeecef4e8c877df2a25888f247a98198959842a5e73236bc7f22cabdf6351a7 + call-bind: ^1.0.8 + call-bound: ^1.0.3 + get-intrinsic: ^1.2.6 + checksum: f137a2a6e77af682cdbffef1e633c140cf596f72321baf8bba0f4ef22685eb4339dde23dfe9e9ca430b5f961dee4d46577dcf12b792b68518c8449b134fb9156 languageName: node linkType: hard @@ -12310,11 +12209,14 @@ __metadata: linkType: hard "is-async-function@npm:^2.0.0": - version: 2.0.0 - resolution: "is-async-function@npm:2.0.0" + version: 2.1.0 + resolution: "is-async-function@npm:2.1.0" dependencies: - has-tostringtag: ^1.0.0 - checksum: e3471d95e6c014bf37cad8a93f2f4b6aac962178e0a5041e8903147166964fdc1c5c1d2ef87e86d77322c370ca18f2ea004fa7420581fa747bcaf7c223069dbd + call-bound: ^1.0.3 + get-proto: ^1.0.1 + has-tostringtag: ^1.0.2 + safe-regex-test: ^1.1.0 + checksum: e8dfa81561eb7cd845d626bf49675c735a177013943eb6919185e1f358fe8b16fd11fa477397df8ddddd31ade47092de8243997530931a4ec17cb2b9d15479c9 languageName: node linkType: hard @@ -12345,23 +12247,13 @@ __metadata: languageName: node linkType: hard -"is-boolean-object@npm:^1.1.0": - version: 1.2.0 - resolution: "is-boolean-object@npm:1.2.0" - dependencies: - call-bind: ^1.0.7 - has-tostringtag: ^1.0.2 - checksum: cebc780cc3881dfb0c6c933e308f6a8eccf07ef92a7ea533fb2ee4fb7d704473b476f0b345fea4f2f45fe70937ef568a2f450eb6000d08b99350d87280927ff8 - languageName: node - linkType: hard - -"is-boolean-object@npm:^1.2.0": - version: 1.2.0 - resolution: "is-boolean-object@npm:1.2.0" +"is-boolean-object@npm:^1.2.1": + version: 1.2.1 + resolution: "is-boolean-object@npm:1.2.1" dependencies: - call-bind: ^1.0.7 + call-bound: ^1.0.2 has-tostringtag: ^1.0.2 - checksum: cebc780cc3881dfb0c6c933e308f6a8eccf07ef92a7ea533fb2ee4fb7d704473b476f0b345fea4f2f45fe70937ef568a2f450eb6000d08b99350d87280927ff8 + checksum: 2672609f0f2536172873810a38ec006a415e43ddc6a240f7638a1659cb20dfa91cc75c8a1bed36247bb046aa8f0eab945f20d1203bc69606418bd129c745f861 languageName: node linkType: hard @@ -12411,12 +12303,12 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.0.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1": - version: 2.15.1 - resolution: "is-core-module@npm:2.15.1" +"is-core-module@npm:^2.0.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.15.1, is-core-module@npm:^2.16.0": + version: 2.16.1 + resolution: "is-core-module@npm:2.16.1" dependencies: hasown: ^2.0.2 - checksum: df134c168115690724b62018c37b2f5bba0d5745fa16960b329c5a00883a8bea6a5632fdb1e3efcce237c201826ba09f93197b7cd95577ea56b0df335be23633 + checksum: 6ec5b3c42d9cbf1ac23f164b16b8a140c3cec338bf8f884c076ca89950c7cc04c33e78f02b8cae7ff4751f3247e3174b2330f1fe4de194c7210deb8b1ea316a7 languageName: node linkType: hard @@ -12429,21 +12321,24 @@ __metadata: languageName: node linkType: hard -"is-data-view@npm:^1.0.1": - version: 1.0.1 - resolution: "is-data-view@npm:1.0.1" +"is-data-view@npm:^1.0.1, is-data-view@npm:^1.0.2": + version: 1.0.2 + resolution: "is-data-view@npm:1.0.2" dependencies: + call-bound: ^1.0.2 + get-intrinsic: ^1.2.6 is-typed-array: ^1.1.13 - checksum: 4ba4562ac2b2ec005fefe48269d6bd0152785458cd253c746154ffb8a8ab506a29d0cfb3b74af87513843776a88e4981ae25c89457bf640a33748eab1a7216b5 + checksum: 31600dd19932eae7fd304567e465709ffbfa17fa236427c9c864148e1b54eb2146357fcf3aed9b686dee13c217e1bb5a649cb3b9c479e1004c0648e9febde1b2 languageName: node linkType: hard -"is-date-object@npm:^1.0.5": - version: 1.0.5 - resolution: "is-date-object@npm:1.0.5" +"is-date-object@npm:^1.0.5, is-date-object@npm:^1.1.0": + version: 1.1.0 + resolution: "is-date-object@npm:1.1.0" dependencies: - has-tostringtag: ^1.0.0 - checksum: baa9077cdf15eb7b58c79398604ca57379b2fc4cf9aa7a9b9e295278648f628c9b201400c01c5e0f7afae56507d741185730307cbe7cad3b9f90a77e5ee342fc + call-bound: ^1.0.2 + has-tostringtag: ^1.0.2 + checksum: d6c36ab9d20971d65f3fc64cef940d57a4900a2ac85fb488a46d164c2072a33da1cb51eefcc039e3e5c208acbce343d3480b84ab5ff0983f617512da2742562a languageName: node linkType: hard @@ -12521,11 +12416,11 @@ __metadata: linkType: hard "is-finalizationregistry@npm:^1.1.0": - version: 1.1.0 - resolution: "is-finalizationregistry@npm:1.1.0" + version: 1.1.1 + resolution: "is-finalizationregistry@npm:1.1.1" dependencies: - call-bind: ^1.0.7 - checksum: 480818ab86e112a00444410a2fd551a5363bca0c39c7bc66e29df665b1e47c803ba107227c1db86d67264a3f020779fab257061463ce02b01b6abbe5966e33b8 + call-bound: ^1.0.3 + checksum: 38c646c506e64ead41a36c182d91639833311970b6b6c6268634f109eef0a1a9d2f1f2e499ef4cb43c744a13443c4cdd2f0812d5afdcee5e9b65b72b28c48557 languageName: node linkType: hard @@ -12551,11 +12446,14 @@ __metadata: linkType: hard "is-generator-function@npm:^1.0.10, is-generator-function@npm:^1.0.7": - version: 1.0.10 - resolution: "is-generator-function@npm:1.0.10" + version: 1.1.0 + resolution: "is-generator-function@npm:1.1.0" dependencies: - has-tostringtag: ^1.0.0 - checksum: d54644e7dbaccef15ceb1e5d91d680eb5068c9ee9f9eb0a9e04173eb5542c9b51b5ab52c5537f5703e48d5fddfd376817c1ca07a84a407b7115b769d4bdde72b + call-bound: ^1.0.3 + get-proto: ^1.0.0 + has-tostringtag: ^1.0.2 + safe-regex-test: ^1.1.0 + checksum: f7f7276131bdf7e28169b86ac55a5b080012a597f9d85a0cbef6fe202a7133fa450a3b453e394870e3cb3685c5a764c64a9f12f614684b46969b1e6f297bed6b languageName: node linkType: hard @@ -12605,13 +12503,6 @@ __metadata: languageName: node linkType: hard -"is-negative-zero@npm:^2.0.3": - version: 2.0.3 - resolution: "is-negative-zero@npm:2.0.3" - checksum: c1e6b23d2070c0539d7b36022d5a94407132411d01aba39ec549af824231f3804b1aea90b5e4e58e807a65d23ceb538ed6e355ce76b267bdd86edb757ffcbdcd - languageName: node - linkType: hard - "is-node-process@npm:^1.0.1": version: 1.2.0 resolution: "is-node-process@npm:1.2.0" @@ -12619,23 +12510,13 @@ __metadata: languageName: node linkType: hard -"is-number-object@npm:^1.0.4": - version: 1.1.0 - resolution: "is-number-object@npm:1.1.0" - dependencies: - call-bind: ^1.0.7 - has-tostringtag: ^1.0.2 - checksum: 965f91493e5c02a44bb9c5d8dd4ae40da20bd9bd1cff9cd92e2f2e66a486935a0a01f8a4744eab033c450888f01a4ec3226e1c75bbcff973ce12d06ed79eb17b - languageName: node - linkType: hard - -"is-number-object@npm:^1.1.0": - version: 1.1.0 - resolution: "is-number-object@npm:1.1.0" +"is-number-object@npm:^1.1.1": + version: 1.1.1 + resolution: "is-number-object@npm:1.1.1" dependencies: - call-bind: ^1.0.7 + call-bound: ^1.0.3 has-tostringtag: ^1.0.2 - checksum: 965f91493e5c02a44bb9c5d8dd4ae40da20bd9bd1cff9cd92e2f2e66a486935a0a01f8a4744eab033c450888f01a4ec3226e1c75bbcff973ce12d06ed79eb17b + checksum: 6517f0a0e8c4b197a21afb45cd3053dc711e79d45d8878aa3565de38d0102b130ca8732485122c7b336e98c27dacd5236854e3e6526e0eb30cae64956535662f languageName: node linkType: hard @@ -12731,15 +12612,15 @@ __metadata: languageName: node linkType: hard -"is-regex@npm:^1.1.4": - version: 1.2.0 - resolution: "is-regex@npm:1.2.0" +"is-regex@npm:^1.1.4, is-regex@npm:^1.2.1": + version: 1.2.1 + resolution: "is-regex@npm:1.2.1" dependencies: - call-bind: ^1.0.7 - gopd: ^1.1.0 + call-bound: ^1.0.2 + gopd: ^1.2.0 has-tostringtag: ^1.0.2 hasown: ^2.0.2 - checksum: dd2693d71866850d1276815204a2629d28dc1d24bd56b734e57a39f56b777cd87030d57552e7093d91a2ac331d99af9dba49a0a641fa4e4435d40e944d4dde12 + checksum: 99ee0b6d30ef1bb61fa4b22fae7056c6c9b3c693803c0c284ff7a8570f83075a7d38cda53b06b7996d441215c27895ea5d1af62124562e13d91b3dbec41a5e13 languageName: node linkType: hard @@ -12771,12 +12652,12 @@ __metadata: languageName: node linkType: hard -"is-shared-array-buffer@npm:^1.0.2, is-shared-array-buffer@npm:^1.0.3": - version: 1.0.3 - resolution: "is-shared-array-buffer@npm:1.0.3" +"is-shared-array-buffer@npm:^1.0.2, is-shared-array-buffer@npm:^1.0.4": + version: 1.0.4 + resolution: "is-shared-array-buffer@npm:1.0.4" dependencies: - call-bind: ^1.0.7 - checksum: a4fff602c309e64ccaa83b859255a43bb011145a42d3f56f67d9268b55bc7e6d98a5981a1d834186ad3105d6739d21547083fe7259c76c0468483fc538e716d8 + call-bound: ^1.0.3 + checksum: 1611fedc175796eebb88f4dfc393dd969a4a8e6c69cadaff424ee9d4464f9f026399a5f84a90f7c62d6d7ee04e3626a912149726de102b0bd6c1ee6a9868fa5a languageName: node linkType: hard @@ -12794,54 +12675,33 @@ __metadata: languageName: node linkType: hard -"is-string@npm:^1.0.5, is-string@npm:^1.0.7": - version: 1.1.0 - resolution: "is-string@npm:1.1.0" - dependencies: - call-bind: ^1.0.7 - has-tostringtag: ^1.0.2 - checksum: 1e330e9fe0984cdf37371f704f9babf9b56d50b1e9d2e6c19b8b78443be3e9771c33309b4aadde9ba2a8870769374538681e01f54113a335dd393c80a72e7d11 - languageName: node - linkType: hard - -"is-string@npm:^1.0.7, is-string@npm:^1.1.0": - version: 1.1.0 - resolution: "is-string@npm:1.1.0" +"is-string@npm:^1.0.7, is-string@npm:^1.1.1": + version: 1.1.1 + resolution: "is-string@npm:1.1.1" dependencies: - call-bind: ^1.0.7 + call-bound: ^1.0.3 has-tostringtag: ^1.0.2 - checksum: 1e330e9fe0984cdf37371f704f9babf9b56d50b1e9d2e6c19b8b78443be3e9771c33309b4aadde9ba2a8870769374538681e01f54113a335dd393c80a72e7d11 + checksum: 2eeaaff605250f5e836ea3500d33d1a5d3aa98d008641d9d42fb941e929ffd25972326c2ef912987e54c95b6f10416281aaf1b35cdf81992cfb7524c5de8e193 languageName: node linkType: hard -"is-symbol@npm:^1.0.3, is-symbol@npm:^1.0.4": - version: 1.0.4 - resolution: "is-symbol@npm:1.0.4" - dependencies: - call-bind: ^1.0.7 - has-symbols: ^1.0.3 - safe-regex-test: ^1.0.3 - checksum: 3623c934c8e61ddd6ef0927a17eb3da3cb9a9894f2fb8a96d447887d085d43e5d8bb59a8f97e46b54a919fc3f8845df29686672ad693d028570627bc661bcb6c - languageName: node - linkType: hard - -"is-symbol@npm:^1.0.4, is-symbol@npm:^1.1.0": - version: 1.1.0 - resolution: "is-symbol@npm:1.1.0" +"is-symbol@npm:^1.0.4, is-symbol@npm:^1.1.1": + version: 1.1.1 + resolution: "is-symbol@npm:1.1.1" dependencies: - call-bind: ^1.0.7 - has-symbols: ^1.0.3 - safe-regex-test: ^1.0.3 - checksum: 3623c934c8e61ddd6ef0927a17eb3da3cb9a9894f2fb8a96d447887d085d43e5d8bb59a8f97e46b54a919fc3f8845df29686672ad693d028570627bc661bcb6c + call-bound: ^1.0.2 + has-symbols: ^1.1.0 + safe-regex-test: ^1.1.0 + checksum: bfafacf037af6f3c9d68820b74be4ae8a736a658a3344072df9642a090016e281797ba8edbeb1c83425879aae55d1cb1f30b38bf132d703692b2570367358032 languageName: node linkType: hard -"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.3": - version: 1.1.13 - resolution: "is-typed-array@npm:1.1.13" +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15, is-typed-array@npm:^1.1.3": + version: 1.1.15 + resolution: "is-typed-array@npm:1.1.15" dependencies: - which-typed-array: ^1.1.14 - checksum: 150f9ada183a61554c91e1c4290086d2c100b0dff45f60b028519be72a8db964da403c48760723bf5253979b8dffe7b544246e0e5351dcd05c5fdb1dcc1dc0f0 + which-typed-array: ^1.1.16 + checksum: ea7cfc46c282f805d19a9ab2084fd4542fed99219ee9dbfbc26284728bd713a51eac66daa74eca00ae0a43b61322920ba334793607dc39907465913e921e0892 languageName: node linkType: hard @@ -12866,22 +12726,22 @@ __metadata: languageName: node linkType: hard -"is-weakref@npm:^1.0.2": - version: 1.0.2 - resolution: "is-weakref@npm:1.0.2" +"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.0": + version: 1.1.0 + resolution: "is-weakref@npm:1.1.0" dependencies: - call-bind: ^1.0.2 - checksum: 95bd9a57cdcb58c63b1c401c60a474b0f45b94719c30f548c891860f051bc2231575c290a6b420c6bc6e7ed99459d424c652bd5bf9a1d5259505dc35b4bf83de + call-bound: ^1.0.2 + checksum: 2a2f3a1746ee1baecf9ac6483d903cd3f8ef3cca88e2baa42f2e85ea064bd246d218eed5f6d479fc1c76dae2231e71133b6b86160e821d176932be9fae3da4da languageName: node linkType: hard "is-weakset@npm:^2.0.3": - version: 2.0.3 - resolution: "is-weakset@npm:2.0.3" + version: 2.0.4 + resolution: "is-weakset@npm:2.0.4" dependencies: - call-bind: ^1.0.7 - get-intrinsic: ^1.2.4 - checksum: 8b6a20ee9f844613ff8f10962cfee49d981d584525f2357fee0a04dfbcde9fd607ed60cb6dab626dbcc470018ae6392e1ff74c0c1aced2d487271411ad9d85ae + call-bound: ^1.0.3 + get-intrinsic: ^1.2.6 + checksum: 5c6c8415a06065d78bdd5e3a771483aa1cd928df19138aa73c4c51333226f203f22117b4325df55cc8b3085a6716870a320c2d757efee92d7a7091a039082041 languageName: node linkType: hard @@ -13023,16 +12883,17 @@ __metadata: languageName: node linkType: hard -"iterator.prototype@npm:^1.1.3": - version: 1.1.3 - resolution: "iterator.prototype@npm:1.1.3" +"iterator.prototype@npm:^1.1.4": + version: 1.1.5 + resolution: "iterator.prototype@npm:1.1.5" dependencies: - define-properties: ^1.2.1 - get-intrinsic: ^1.2.1 - has-symbols: ^1.0.3 - reflect.getprototypeof: ^1.0.4 - set-function-name: ^2.0.1 - checksum: 7d2a1f8bcbba7b76f72e956faaf7b25405f4de54430c9d099992e6fb9d571717c3044604e8cdfb8e624cb881337d648030ee8b1541d544af8b338835e3f47ebe + define-data-property: ^1.1.4 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.6 + get-proto: ^1.0.0 + has-symbols: ^1.1.0 + set-function-name: ^2.0.2 + checksum: 7db23c42629ba4790e6e15f78b555f41dbd08818c85af306988364bd19d86716a1187cb333444f3a0036bfc078a0e9cb7ec67fef3a61662736d16410d7f77869 languageName: node linkType: hard @@ -13797,7 +13658,16 @@ __metadata: languageName: node linkType: hard -"jsesc@npm:^3.0.2, jsesc@npm:~3.0.2": +"jsesc@npm:^3.0.2": + version: 3.1.0 + resolution: "jsesc@npm:3.1.0" + bin: + jsesc: bin/jsesc + checksum: 19c94095ea026725540c0d29da33ab03144f6bcf2d4159e4833d534976e99e0c09c38cefa9a575279a51fc36b31166f8d6d05c9fe2645d5f15851d690b41f17f + languageName: node + linkType: hard + +"jsesc@npm:~3.0.2": version: 3.0.2 resolution: "jsesc@npm:3.0.2" bin: @@ -14412,11 +14282,11 @@ __metadata: linkType: hard "magic-string@npm:^0.30.0": - version: 0.30.14 - resolution: "magic-string@npm:0.30.14" + version: 0.30.17 + resolution: "magic-string@npm:0.30.17" dependencies: "@jridgewell/sourcemap-codec": ^1.5.0 - checksum: 67b3b2d817a7c4e94cb63e2dcaffbeee3b76ff0798eeaee8159a6ff4faee30db824375b2cadbf43807b56c6802fe6373b40d02567d489593017012d74ec0b719 + checksum: f4b4ed17c5ada64f77fc98491847302ebad64894a905c417c943840c0384662118c9b37f9f68bb86add159fa4749ff6f118c4627d69a470121b46731f8debc6d languageName: node linkType: hard @@ -14509,6 +14379,13 @@ __metadata: languageName: node linkType: hard +"math-intrinsics@npm:^1.1.0": + version: 1.1.0 + resolution: "math-intrinsics@npm:1.1.0" + checksum: 0e513b29d120f478c85a70f49da0b8b19bc638975eca466f2eeae0071f3ad00454c621bf66e16dd435896c208e719fc91ad79bbfba4e400fe0b372e7c1c9c9a2 + languageName: node + linkType: hard + "md5.js@npm:^1.3.4": version: 1.3.5 resolution: "md5.js@npm:1.3.5" @@ -14700,7 +14577,7 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": +"micromatch@npm:^4.0.2, micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" dependencies: @@ -15022,7 +14899,7 @@ __metadata: languageName: node linkType: hard -"mlly@npm:^1.4.0, mlly@npm:^1.7.2": +"mlly@npm:^1.4.0, mlly@npm:^1.7.3": version: 1.7.3 resolution: "mlly@npm:1.7.3" dependencies: @@ -15228,13 +15105,6 @@ __metadata: languageName: node linkType: hard -"negotiator@npm:^0.6.3, negotiator@npm:~0.6.4": - version: 0.6.4 - resolution: "negotiator@npm:0.6.4" - checksum: 7ded10aa02a0707d1d12a9973fdb5954f98547ca7beb60e31cb3a403cc6e8f11138db7a3b0128425cf836fc85d145ec4ce983b2bdf83dca436af879c2d683510 - languageName: node - linkType: hard - "negotiator@npm:^1.0.0": version: 1.0.0 resolution: "negotiator@npm:1.0.0" @@ -15396,10 +15266,10 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.18": - version: 2.0.18 - resolution: "node-releases@npm:2.0.18" - checksum: ef55a3d853e1269a6d6279b7692cd6ff3e40bc74947945101138745bfdc9a5edabfe72cb19a31a8e45752e1910c4c65c77d931866af6357f242b172b7283f5b3 +"node-releases@npm:^2.0.19": + version: 2.0.19 + resolution: "node-releases@npm:2.0.19" + checksum: 917dbced519f48c6289a44830a0ca6dc944c3ee9243c468ebd8515a41c97c8b2c256edb7f3f750416bc37952cc9608684e6483c7b6c6f39f6bd8d86c52cfe658 languageName: node linkType: hard @@ -15563,7 +15433,7 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.1, object-inspect@npm:^1.13.3": +"object-inspect@npm:^1.13.3": version: 1.13.3 resolution: "object-inspect@npm:1.13.3" checksum: 8c962102117241e18ea403b84d2521f78291b774b03a29ee80a9863621d88265ffd11d0d7e435c4c2cea0dc2a2fbf8bbc92255737a05536590f2df2e8756f297 @@ -15596,15 +15466,17 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.4, object.assign@npm:^4.1.5": - version: 4.1.5 - resolution: "object.assign@npm:4.1.5" +"object.assign@npm:^4.1.4, object.assign@npm:^4.1.7": + version: 4.1.7 + resolution: "object.assign@npm:4.1.7" dependencies: - call-bind: ^1.0.5 + call-bind: ^1.0.8 + call-bound: ^1.0.3 define-properties: ^1.2.1 - has-symbols: ^1.0.3 + es-object-atoms: ^1.0.0 + has-symbols: ^1.1.0 object-keys: ^1.1.1 - checksum: f9aeac0541661370a1fc86e6a8065eb1668d3e771f7dbb33ee54578201336c057b21ee61207a186dd42db0c62201d91aac703d20d12a79fc79c353eed44d4e25 + checksum: 60e07d2651cf4f5528c485f1aa4dbded9b384c47d80e8187cefd11320abb1aebebf78df5483451dfa549059f8281c21f7b4bf7d19e9e5e97d8d617df0df298de languageName: node linkType: hard @@ -15666,14 +15538,15 @@ __metadata: languageName: node linkType: hard -"object.values@npm:^1.1.0, object.values@npm:^1.1.6, object.values@npm:^1.2.0": - version: 1.2.0 - resolution: "object.values@npm:1.2.0" +"object.values@npm:^1.1.0, object.values@npm:^1.1.6, object.values@npm:^1.2.0, object.values@npm:^1.2.1": + version: 1.2.1 + resolution: "object.values@npm:1.2.1" dependencies: - call-bind: ^1.0.7 + call-bind: ^1.0.8 + call-bound: ^1.0.3 define-properties: ^1.2.1 es-object-atoms: ^1.0.0 - checksum: 51fef456c2a544275cb1766897f34ded968b22adfc13ba13b5e4815fdaf4304a90d42a3aee114b1f1ede048a4890381d47a5594d84296f2767c6a0364b9da8fa + checksum: f9b9a2a125ccf8ded29414d7c056ae0d187b833ee74919821fc60d7e216626db220d9cb3cf33f965c84aaaa96133626ca13b80f3c158b673976dc8cfcfcd26bb languageName: node linkType: hard @@ -15822,6 +15695,17 @@ __metadata: languageName: node linkType: hard +"own-keys@npm:^1.0.1": + version: 1.0.1 + resolution: "own-keys@npm:1.0.1" + dependencies: + get-intrinsic: ^1.2.6 + object-keys: ^1.1.1 + safe-push-apply: ^1.0.0 + checksum: cc9dd7d85c4ccfbe8109fce307d581ac7ede7b26de892b537873fbce2dc6a206d89aea0630dbb98e47ce0873517cefeaa7be15fcf94aaf4764a3b34b474a5b61 + languageName: node + linkType: hard + "p-each-series@npm:^2.1.0": version: 2.2.0 resolution: "p-each-series@npm:2.2.0" @@ -15898,9 +15782,9 @@ __metadata: linkType: hard "p-map@npm:^7.0.2": - version: 7.0.2 - resolution: "p-map@npm:7.0.2" - checksum: bc128c2b244ef5d4619392b2247d718a3fe471d5fa4a73834fd96182a237f460ec7e0ad0f95139ef7103a6b50ed164228c62e2f8e41ba2b15360fe1c20d13563 + version: 7.0.3 + resolution: "p-map@npm:7.0.3" + checksum: 8c92d533acf82f0d12f7e196edccff773f384098bbb048acdd55a08778ce4fc8889d8f1bde72969487bd96f9c63212698d79744c20bedfce36c5b00b46d369f8 languageName: node linkType: hard @@ -16157,13 +16041,6 @@ __metadata: languageName: node linkType: hard -"path-to-regexp@npm:0.1.10": - version: 0.1.10 - resolution: "path-to-regexp@npm:0.1.10" - checksum: ab7a3b7a0b914476d44030340b0a65d69851af2a0f33427df1476100ccb87d409c39e2182837a96b98fb38c4ef2ba6b87bdad62bb70a2c153876b8061760583c - languageName: node - linkType: hard - "path-to-regexp@npm:0.1.12": version: 0.1.12 resolution: "path-to-regexp@npm:0.1.12" @@ -16331,13 +16208,13 @@ __metadata: linkType: hard "pkg-types@npm:^1.2.1": - version: 1.2.1 - resolution: "pkg-types@npm:1.2.1" + version: 1.3.0 + resolution: "pkg-types@npm:1.3.0" dependencies: confbox: ^0.1.8 - mlly: ^1.7.2 + mlly: ^1.7.3 pathe: ^1.1.2 - checksum: d2e3ad7aef36cc92b17403e61c04db521bf0beb175ccb4d432c284239f00ec32ff37feb072a260613e9ff727911cff1127a083fd52f91b9bec6b62970f385702 + checksum: 9637de6bbaceb4cf7c99c098b9286de63382cdd916e9e02c243dcd9f8725650aba7025a80cd7ac085176054b71c07656045b558fe452fe4ed2445383b51d6e24 languageName: node linkType: hard @@ -17382,13 +17259,6 @@ __metadata: languageName: node linkType: hard -"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0": - version: 4.2.0 - resolution: "proc-log@npm:4.2.0" - checksum: 98f6cd012d54b5334144c5255ecb941ee171744f45fca8b43b58ae5a0c1af07352475f481cadd9848e7f0250376ee584f6aa0951a856ff8f021bdfbff4eb33fc - languageName: node - linkType: hard - "proc-log@npm:^5.0.0": version: 5.0.0 resolution: "proc-log@npm:5.0.0" @@ -17893,11 +17763,11 @@ __metadata: linkType: hard "react-hook-form@npm:^7.34.0": - version: 7.53.2 - resolution: "react-hook-form@npm:7.53.2" + version: 7.54.2 + resolution: "react-hook-form@npm:7.54.2" peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 - checksum: 37e2dd0e79cd8d3376a7a2cb72ad7b59f0594be499daa898d2c6bec896fc30c2f86e62e8b41bc9d325f77220bd8d76cb31e917f77f1c92ad5740adb1a4cc69e2 + checksum: 49a867ece9894dca82f6552e5eefd012b7db962c56a7543f9275ae0b6ec202d549973c3694e7f97436afc2396549cb8fc8777241dd660b71793547aa9c8e5686 languageName: node linkType: hard @@ -17915,13 +17785,20 @@ __metadata: languageName: node linkType: hard -"react-is@npm:^18.0.0, react-is@npm:^18.3.1": +"react-is@npm:^18.0.0": version: 18.3.1 resolution: "react-is@npm:18.3.1" checksum: e20fe84c86ff172fc8d898251b7cc2c43645d108bf96d0b8edf39b98f9a2cae97b40520ee7ed8ee0085ccc94736c4886294456033304151c3f94978cec03df21 languageName: node linkType: hard +"react-is@npm:^19.0.0": + version: 19.0.0 + resolution: "react-is@npm:19.0.0" + checksum: fbb3060bcb6b3e8e525b17f0872d1cf62a40b73fa7c5de02419069e2edd3e01cf1e8e86c8888f0733cff006175ee76ae927b40b6f0c4332bdda21020505ac90b + languageName: node + linkType: hard + "react-markdown@npm:^6.0.0": version: 6.0.3 resolution: "react-markdown@npm:6.0.3" @@ -18302,18 +18179,19 @@ __metadata: languageName: node linkType: hard -"reflect.getprototypeof@npm:^1.0.4, reflect.getprototypeof@npm:^1.0.6": - version: 1.0.7 - resolution: "reflect.getprototypeof@npm:1.0.7" +"reflect.getprototypeof@npm:^1.0.6, reflect.getprototypeof@npm:^1.0.9": + version: 1.0.10 + resolution: "reflect.getprototypeof@npm:1.0.10" dependencies: - call-bind: ^1.0.7 + call-bind: ^1.0.8 define-properties: ^1.2.1 - es-abstract: ^1.23.5 + es-abstract: ^1.23.9 es-errors: ^1.3.0 - get-intrinsic: ^1.2.4 - gopd: ^1.0.1 - which-builtin-type: ^1.1.4 - checksum: e023846d4d9631b46476a2315f5cdebb1f98782e145e807d985b47df8314776220b0d82244c9f3e51718acb09da79149f406afa9872e4fb4ca473dcc4e980598 + es-object-atoms: ^1.0.0 + get-intrinsic: ^1.2.7 + get-proto: ^1.0.1 + which-builtin-type: ^1.2.1 + checksum: ccc5debeb66125e276ae73909cecb27e47c35d9bb79d9cc8d8d055f008c58010ab8cb401299786e505e4aab733a64cba9daf5f312a58e96a43df66adad221870 languageName: node linkType: hard @@ -18380,15 +18258,17 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2, regexp.prototype.flags@npm:^1.5.3": - version: 1.5.3 - resolution: "regexp.prototype.flags@npm:1.5.3" +"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.3": + version: 1.5.4 + resolution: "regexp.prototype.flags@npm:1.5.4" dependencies: - call-bind: ^1.0.7 + call-bind: ^1.0.8 define-properties: ^1.2.1 es-errors: ^1.3.0 + get-proto: ^1.0.1 + gopd: ^1.2.0 set-function-name: ^2.0.2 - checksum: 83ff0705b837f7cb6d664010a11642250f36d3f642263dd0f3bdfe8f150261aa7b26b50ee97f21c1da30ef82a580bb5afedbef5f45639d69edaafbeac9bbb0ed + checksum: 18cb667e56cb328d2dda569d7f04e3ea78f2683135b866d606538cf7b1d4271f7f749f09608c877527799e6cf350e531368f3c7a20ccd1bb41048a48926bdeeb languageName: node linkType: hard @@ -18399,20 +18279,6 @@ __metadata: languageName: node linkType: hard -"regexpu-core@npm:^6.1.1": - version: 6.2.0 - resolution: "regexpu-core@npm:6.2.0" - dependencies: - regenerate: ^1.4.2 - regenerate-unicode-properties: ^10.2.0 - regjsgen: ^0.8.0 - regjsparser: ^0.12.0 - unicode-match-property-ecmascript: ^2.0.0 - unicode-match-property-value-ecmascript: ^2.1.0 - checksum: 67d3c4a3f6c99bc80b5d690074a27e6f675be1c1739f8a9acf028fbc36f1a468472574ea65e331e217995198ba4404d7878f3cb3739a73552dd3c70d3fb7f8e6 - languageName: node - linkType: hard - "regexpu-core@npm:^6.2.0": version: 6.2.0 resolution: "regexpu-core@npm:6.2.0" @@ -18642,15 +18508,15 @@ __metadata: linkType: hard "resolve@npm:^1.10.0, resolve@npm:^1.12.0, resolve@npm:^1.14.2, resolve@npm:^1.17.0, resolve@npm:^1.18.1, resolve@npm:^1.19.0, resolve@npm:^1.22.4, resolve@npm:^1.3.2": - version: 1.22.8 - resolution: "resolve@npm:1.22.8" + version: 1.22.10 + resolution: "resolve@npm:1.22.10" dependencies: - is-core-module: ^2.13.0 + is-core-module: ^2.16.0 path-parse: ^1.0.7 supports-preserve-symlinks-flag: ^1.0.0 bin: resolve: bin/resolve - checksum: f8a26958aa572c9b064562750b52131a37c29d072478ea32e129063e2da7f83e31f7f11e7087a18225a8561cfe8d2f0df9dbea7c9d331a897571c0a2527dbb4c + checksum: ab7a32ff4046fcd7c6fdd525b24a7527847d03c3650c733b909b01b757f92eb23510afa9cc3e9bf3f26a3e073b48c88c706dfd4c1d2fb4a16a96b73b6328ddcf languageName: node linkType: hard @@ -18678,15 +18544,15 @@ __metadata: linkType: hard "resolve@patch:resolve@^1.10.0#~builtin, resolve@patch:resolve@^1.12.0#~builtin, resolve@patch:resolve@^1.14.2#~builtin, resolve@patch:resolve@^1.17.0#~builtin, resolve@patch:resolve@^1.18.1#~builtin, resolve@patch:resolve@^1.19.0#~builtin, resolve@patch:resolve@^1.22.4#~builtin, resolve@patch:resolve@^1.3.2#~builtin": - version: 1.22.8 - resolution: "resolve@patch:resolve@npm%3A1.22.8#~builtin::version=1.22.8&hash=07638b" + version: 1.22.10 + resolution: "resolve@patch:resolve@npm%3A1.22.10#~builtin::version=1.22.10&hash=07638b" dependencies: - is-core-module: ^2.13.0 + is-core-module: ^2.16.0 path-parse: ^1.0.7 supports-preserve-symlinks-flag: ^1.0.0 bin: resolve: bin/resolve - checksum: 5479b7d431cacd5185f8db64bfcb7286ae5e31eb299f4c4f404ad8aa6098b77599563ac4257cb2c37a42f59dfc06a1bec2bcf283bb448f319e37f0feb9a09847 + checksum: 8aac1e4e4628bd00bf4b94b23de137dd3fe44097a8d528fd66db74484be929936e20c696e1a3edf4488f37e14180b73df6f600992baea3e089e8674291f16c9d languageName: node linkType: hard @@ -18944,15 +18810,16 @@ __metadata: languageName: node linkType: hard -"safe-array-concat@npm:^1.1.2": - version: 1.1.2 - resolution: "safe-array-concat@npm:1.1.2" +"safe-array-concat@npm:^1.1.2, safe-array-concat@npm:^1.1.3": + version: 1.1.3 + resolution: "safe-array-concat@npm:1.1.3" dependencies: - call-bind: ^1.0.7 - get-intrinsic: ^1.2.4 - has-symbols: ^1.0.3 + call-bind: ^1.0.8 + call-bound: ^1.0.2 + get-intrinsic: ^1.2.6 + has-symbols: ^1.1.0 isarray: ^2.0.5 - checksum: a3b259694754ddfb73ae0663829e396977b99ff21cbe8607f35a469655656da8e271753497e59da8a7575baa94d2e684bea3e10ddd74ba046c0c9b4418ffa0c4 + checksum: 00f6a68140e67e813f3ad5e73e6dedcf3e42a9fa01f04d44b0d3f7b1f4b257af876832a9bfc82ac76f307e8a6cc652e3cf95876048a26cbec451847cf6ae3707 languageName: node linkType: hard @@ -18970,14 +18837,24 @@ __metadata: languageName: node linkType: hard -"safe-regex-test@npm:^1.0.3": - version: 1.0.3 - resolution: "safe-regex-test@npm:1.0.3" +"safe-push-apply@npm:^1.0.0": + version: 1.0.0 + resolution: "safe-push-apply@npm:1.0.0" dependencies: - call-bind: ^1.0.6 es-errors: ^1.3.0 - is-regex: ^1.1.4 - checksum: 6c7d392ff1ae7a3ae85273450ed02d1d131f1d2c76e177d6b03eb88e6df8fa062639070e7d311802c1615f351f18dc58f9454501c58e28d5ffd9b8f502ba6489 + isarray: ^2.0.5 + checksum: 8c11cbee6dc8ff5cc0f3d95eef7052e43494591384015902e4292aef4ae9e539908288520ed97179cee17d6ffb450fe5f05a46ce7a1749685f7524fd568ab5db + languageName: node + linkType: hard + +"safe-regex-test@npm:^1.0.3, safe-regex-test@npm:^1.1.0": + version: 1.1.0 + resolution: "safe-regex-test@npm:1.1.0" + dependencies: + call-bound: ^1.0.2 + es-errors: ^1.3.0 + is-regex: ^1.2.1 + checksum: 3c809abeb81977c9ed6c869c83aca6873ea0f3ab0f806b8edbba5582d51713f8a6e9757d24d2b4b088f563801475ea946c8e77e7713e8c65cdd02305b6caedab languageName: node linkType: hard @@ -19049,8 +18926,8 @@ __metadata: linkType: hard "sass@npm:^1.54.0": - version: 1.82.0 - resolution: "sass@npm:1.82.0" + version: 1.83.1 + resolution: "sass@npm:1.83.1" dependencies: "@parcel/watcher": ^2.4.1 chokidar: ^4.0.0 @@ -19061,7 +18938,7 @@ __metadata: optional: true bin: sass: sass.js - checksum: 3fbfed5361147627097261e69715d6e4826864b636df5a70e4100228fe0e3c1bfd264e2401cfd3e291f739fbee2bd2f56dff27f7f5dc0e21d320356bf51630d0 + checksum: 367a9f270c74a9ad2851955e1cf5b2a05e57d27aec4bf054be1da48eb49858076467b65ec180d8c4392b5c55c0f4d4ba644855f985652ffca15d68a20641d5e0 languageName: node linkType: hard @@ -19307,7 +19184,7 @@ __metadata: languageName: node linkType: hard -"set-function-length@npm:^1.2.1": +"set-function-length@npm:^1.2.2": version: 1.2.2 resolution: "set-function-length@npm:1.2.2" dependencies: @@ -19321,7 +19198,7 @@ __metadata: languageName: node linkType: hard -"set-function-name@npm:^2.0.1, set-function-name@npm:^2.0.2": +"set-function-name@npm:^2.0.2": version: 2.0.2 resolution: "set-function-name@npm:2.0.2" dependencies: @@ -19333,6 +19210,17 @@ __metadata: languageName: node linkType: hard +"set-proto@npm:^1.0.0": + version: 1.0.0 + resolution: "set-proto@npm:1.0.0" + dependencies: + dunder-proto: ^1.0.1 + es-errors: ^1.3.0 + es-object-atoms: ^1.0.0 + checksum: ec27cbbe334598547e99024403e96da32aca3e530583e4dba7f5db1c43cbc4affa9adfbd77c7b2c210b9b8b2e7b2e600bad2a6c44fd62e804d8233f96bbb62f4 + languageName: node + linkType: hard + "set-value@npm:^2.0.0, set-value@npm:^2.0.1": version: 2.0.1 resolution: "set-value@npm:2.0.1" @@ -19434,15 +19322,51 @@ __metadata: languageName: node linkType: hard -"side-channel@npm:^1.0.4, side-channel@npm:^1.0.6": - version: 1.0.6 - resolution: "side-channel@npm:1.0.6" +"side-channel-list@npm:^1.0.0": + version: 1.0.0 + resolution: "side-channel-list@npm:1.0.0" dependencies: - call-bind: ^1.0.7 es-errors: ^1.3.0 - get-intrinsic: ^1.2.4 - object-inspect: ^1.13.1 - checksum: bfc1afc1827d712271453e91b7cd3878ac0efd767495fd4e594c4c2afaa7963b7b510e249572bfd54b0527e66e4a12b61b80c061389e129755f34c493aad9b97 + object-inspect: ^1.13.3 + checksum: 603b928997abd21c5a5f02ae6b9cc36b72e3176ad6827fab0417ead74580cc4fb4d5c7d0a8a2ff4ead34d0f9e35701ed7a41853dac8a6d1a664fcce1a044f86f + languageName: node + linkType: hard + +"side-channel-map@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-map@npm:1.0.1" + dependencies: + call-bound: ^1.0.2 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.5 + object-inspect: ^1.13.3 + checksum: 42501371cdf71f4ccbbc9c9e2eb00aaaab80a4c1c429d5e8da713fd4d39ef3b8d4a4b37ed4f275798a65260a551a7131fd87fe67e922dba4ac18586d6aab8b06 + languageName: node + linkType: hard + +"side-channel-weakmap@npm:^1.0.2": + version: 1.0.2 + resolution: "side-channel-weakmap@npm:1.0.2" + dependencies: + call-bound: ^1.0.2 + es-errors: ^1.3.0 + get-intrinsic: ^1.2.5 + object-inspect: ^1.13.3 + side-channel-map: ^1.0.1 + checksum: a815c89bc78c5723c714ea1a77c938377ea710af20d4fb886d362b0d1f8ac73a17816a5f6640f354017d7e292a43da9c5e876c22145bac00b76cfb3468001736 + languageName: node + linkType: hard + +"side-channel@npm:^1.0.4, side-channel@npm:^1.0.6, side-channel@npm:^1.1.0": + version: 1.1.0 + resolution: "side-channel@npm:1.1.0" + dependencies: + es-errors: ^1.3.0 + object-inspect: ^1.13.3 + side-channel-list: ^1.0.0 + side-channel-map: ^1.0.1 + side-channel-weakmap: ^1.0.2 + checksum: bf73d6d6682034603eb8e99c63b50155017ed78a522d27c2acec0388a792c3ede3238b878b953a08157093b85d05797217d270b7666ba1f111345fbe933380ff languageName: node linkType: hard @@ -19588,13 +19512,13 @@ __metadata: linkType: hard "socks-proxy-agent@npm:^8.0.3": - version: 8.0.4 - resolution: "socks-proxy-agent@npm:8.0.4" + version: 8.0.5 + resolution: "socks-proxy-agent@npm:8.0.5" dependencies: - agent-base: ^7.1.1 + agent-base: ^7.1.2 debug: ^4.3.4 socks: ^2.8.3 - checksum: b2ec5051d85fe49072f9a250c427e0e9571fd09d5db133819192d078fd291276e1f0f50f6dbc04329b207738b1071314cee8bdbb4b12e27de42dbcf1d4233c67 + checksum: b4fbcdb7ad2d6eec445926e255a1fb95c975db0020543fbac8dfa6c47aecc6b3b619b7fb9c60a3f82c9b2969912a5e7e174a056ae4d98cb5322f3524d6036e1d languageName: node linkType: hard @@ -19885,11 +19809,12 @@ __metadata: linkType: hard "stop-iteration-iterator@npm:^1.0.0": - version: 1.0.0 - resolution: "stop-iteration-iterator@npm:1.0.0" + version: 1.1.0 + resolution: "stop-iteration-iterator@npm:1.1.0" dependencies: - internal-slot: ^1.0.4 - checksum: d04173690b2efa40e24ab70e5e51a3ff31d56d699550cfad084104ab3381390daccb36652b25755e420245f3b0737de66c1879eaa2a8d4fc0a78f9bf892fcb42 + es-errors: ^1.3.0 + internal-slot: ^1.1.0 + checksum: be944489d8829fb3bdec1a1cc4a2142c6b6eb317305eeace1ece978d286d6997778afa1ae8cb3bd70e2b274b9aa8c69f93febb1e15b94b1359b11058f9d3c3a1 languageName: node linkType: hard @@ -20017,23 +19942,24 @@ __metadata: languageName: node linkType: hard -"string.prototype.matchall@npm:^4.0.11": - version: 4.0.11 - resolution: "string.prototype.matchall@npm:4.0.11" +"string.prototype.matchall@npm:^4.0.12": + version: 4.0.12 + resolution: "string.prototype.matchall@npm:4.0.12" dependencies: - call-bind: ^1.0.7 + call-bind: ^1.0.8 + call-bound: ^1.0.3 define-properties: ^1.2.1 - es-abstract: ^1.23.2 + es-abstract: ^1.23.6 es-errors: ^1.3.0 es-object-atoms: ^1.0.0 - get-intrinsic: ^1.2.4 - gopd: ^1.0.1 - has-symbols: ^1.0.3 - internal-slot: ^1.0.7 - regexp.prototype.flags: ^1.5.2 + get-intrinsic: ^1.2.6 + gopd: ^1.2.0 + has-symbols: ^1.1.0 + internal-slot: ^1.1.0 + regexp.prototype.flags: ^1.5.3 set-function-name: ^2.0.2 - side-channel: ^1.0.6 - checksum: 6ac6566ed065c0c8489c91156078ca077db8ff64d683fda97ae652d00c52dfa5f39aaab0a710d8243031a857fd2c7c511e38b45524796764d25472d10d7075ae + side-channel: ^1.1.0 + checksum: 98a09d6af91bfc6ee25556f3d7cd6646d02f5f08bda55d45528ed273d266d55a71af7291fe3fc76854deffb9168cc1a917d0b07a7d5a178c7e9537c99e6d2b57 languageName: node linkType: hard @@ -20047,26 +19973,30 @@ __metadata: languageName: node linkType: hard -"string.prototype.trim@npm:^1.2.9": - version: 1.2.9 - resolution: "string.prototype.trim@npm:1.2.9" +"string.prototype.trim@npm:^1.2.10": + version: 1.2.10 + resolution: "string.prototype.trim@npm:1.2.10" dependencies: - call-bind: ^1.0.7 + call-bind: ^1.0.8 + call-bound: ^1.0.2 + define-data-property: ^1.1.4 define-properties: ^1.2.1 - es-abstract: ^1.23.0 + es-abstract: ^1.23.5 es-object-atoms: ^1.0.0 - checksum: ea2df6ec1e914c9d4e2dc856fa08228e8b1be59b59e50b17578c94a66a176888f417264bb763d4aac638ad3b3dad56e7a03d9317086a178078d131aa293ba193 + has-property-descriptors: ^1.0.2 + checksum: 87659cd8561237b6c69f5376328fda934693aedde17bb7a2c57008e9d9ff992d0c253a391c7d8d50114e0e49ff7daf86a362f7961cf92f7564cd01342ca2e385 languageName: node linkType: hard -"string.prototype.trimend@npm:^1.0.8": - version: 1.0.8 - resolution: "string.prototype.trimend@npm:1.0.8" +"string.prototype.trimend@npm:^1.0.8, string.prototype.trimend@npm:^1.0.9": + version: 1.0.9 + resolution: "string.prototype.trimend@npm:1.0.9" dependencies: - call-bind: ^1.0.7 + call-bind: ^1.0.8 + call-bound: ^1.0.2 define-properties: ^1.2.1 es-object-atoms: ^1.0.0 - checksum: cc3bd2de08d8968a28787deba9a3cb3f17ca5f9f770c91e7e8fa3e7d47f079bad70fadce16f05dda9f261788be2c6e84a942f618c3bed31e42abc5c1084f8dfd + checksum: cb86f639f41d791a43627784be2175daa9ca3259c7cb83e7a207a729909b74f2ea0ec5d85de5761e6835e5f443e9420c6ff3f63a845378e4a61dd793177bc287 languageName: node linkType: hard @@ -20425,20 +20355,6 @@ __metadata: languageName: node linkType: hard -"tar@npm:^6.0.2, tar@npm:^6.1.11, tar@npm:^6.2.1": - version: 6.2.1 - resolution: "tar@npm:6.2.1" - dependencies: - chownr: ^2.0.0 - fs-minipass: ^2.0.0 - minipass: ^5.0.0 - minizlib: ^2.1.1 - mkdirp: ^1.0.3 - yallist: ^4.0.0 - checksum: f1322768c9741a25356c11373bce918483f40fa9a25c69c59410c8a1247632487edef5fe76c5f12ac51a6356d2f1829e96d2bc34098668a2fc34d76050ac2b6c - languageName: node - linkType: hard - "tar@npm:^7.4.3": version: 7.4.3 resolution: "tar@npm:7.4.3" @@ -20533,8 +20449,8 @@ __metadata: linkType: hard "terser@npm:^5.3.4": - version: 5.36.0 - resolution: "terser@npm:5.36.0" + version: 5.37.0 + resolution: "terser@npm:5.37.0" dependencies: "@jridgewell/source-map": ^0.3.3 acorn: ^8.8.2 @@ -20542,7 +20458,7 @@ __metadata: source-map-support: ~0.5.20 bin: terser: bin/terser - checksum: 489afd31901a2b170f7766948a3aa0e25da0acb41e9e35bd9f9b4751dfa2fc846e485f6fb9d34f0839a96af77f675b5fbf0a20c9aa54e0b8d7c219cf0b55e508 + checksum: 70c06a8ce1288ff4370a7e481beb6fc8b22fc4995371479f49df1552aa9cf8e794ace66e1da6e87057eda1745644311213f5043bda9a06cf55421eff68b3ac06 languageName: node linkType: hard @@ -21027,46 +20943,46 @@ __metadata: languageName: node linkType: hard -"typed-array-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "typed-array-buffer@npm:1.0.2" +"typed-array-buffer@npm:^1.0.3": + version: 1.0.3 + resolution: "typed-array-buffer@npm:1.0.3" dependencies: - call-bind: ^1.0.7 + call-bound: ^1.0.3 es-errors: ^1.3.0 - is-typed-array: ^1.1.13 - checksum: 02ffc185d29c6df07968272b15d5319a1610817916ec8d4cd670ded5d1efe72901541ff2202fcc622730d8a549c76e198a2f74e312eabbfb712ed907d45cbb0b + is-typed-array: ^1.1.14 + checksum: 3fb91f0735fb413b2bbaaca9fabe7b8fc14a3fa5a5a7546bab8a57e755be0e3788d893195ad9c2b842620592de0e68d4c077d4c2c41f04ec25b8b5bb82fa9a80 languageName: node linkType: hard -"typed-array-byte-length@npm:^1.0.1": - version: 1.0.1 - resolution: "typed-array-byte-length@npm:1.0.1" +"typed-array-byte-length@npm:^1.0.3": + version: 1.0.3 + resolution: "typed-array-byte-length@npm:1.0.3" dependencies: - call-bind: ^1.0.7 + call-bind: ^1.0.8 for-each: ^0.3.3 - gopd: ^1.0.1 - has-proto: ^1.0.3 - is-typed-array: ^1.1.13 - checksum: f65e5ecd1cf76b1a2d0d6f631f3ea3cdb5e08da106c6703ffe687d583e49954d570cc80434816d3746e18be889ffe53c58bf3e538081ea4077c26a41055b216d + gopd: ^1.2.0 + has-proto: ^1.2.0 + is-typed-array: ^1.1.14 + checksum: cda9352178ebeab073ad6499b03e938ebc30c4efaea63a26839d89c4b1da9d2640b0d937fc2bd1f049eb0a38def6fbe8a061b601292ae62fe079a410ce56e3a6 languageName: node linkType: hard -"typed-array-byte-offset@npm:^1.0.2": - version: 1.0.3 - resolution: "typed-array-byte-offset@npm:1.0.3" +"typed-array-byte-offset@npm:^1.0.4": + version: 1.0.4 + resolution: "typed-array-byte-offset@npm:1.0.4" dependencies: available-typed-arrays: ^1.0.7 - call-bind: ^1.0.7 + call-bind: ^1.0.8 for-each: ^0.3.3 - gopd: ^1.0.1 - has-proto: ^1.0.3 - is-typed-array: ^1.1.13 - reflect.getprototypeof: ^1.0.6 - checksum: 36728daa80d49a9fa51cd3f0f2b037613f4574666fd4473bd37ac123d7f6f81ea68ff45424c1e2673257964e10bedeb3ebfce73532672913ebbe446999912303 + gopd: ^1.2.0 + has-proto: ^1.2.0 + is-typed-array: ^1.1.15 + reflect.getprototypeof: ^1.0.9 + checksum: 670b7e6bb1d3c2cf6160f27f9f529e60c3f6f9611c67e47ca70ca5cfa24ad95415694c49d1dbfeda016d3372cab7dfc9e38c7b3e1bb8d692cae13a63d3c144d7 languageName: node linkType: hard -"typed-array-length@npm:^1.0.6": +"typed-array-length@npm:^1.0.7": version: 1.0.7 resolution: "typed-array-length@npm:1.0.7" dependencies: @@ -21172,15 +21088,15 @@ __metadata: languageName: node linkType: hard -"unbox-primitive@npm:^1.0.2": - version: 1.0.2 - resolution: "unbox-primitive@npm:1.0.2" +"unbox-primitive@npm:^1.1.0": + version: 1.1.0 + resolution: "unbox-primitive@npm:1.1.0" dependencies: - call-bind: ^1.0.2 + call-bound: ^1.0.3 has-bigints: ^1.0.2 - has-symbols: ^1.0.3 - which-boxed-primitive: ^1.0.2 - checksum: b7a1cf5862b5e4b5deb091672ffa579aa274f648410009c81cca63fed3b62b610c4f3b773f912ce545bb4e31edc3138975b5bc777fc6e4817dca51affb6380e9 + has-symbols: ^1.1.0 + which-boxed-primitive: ^1.1.1 + checksum: 729f13b84a5bfa3fead1d8139cee5c38514e63a8d6a437819a473e241ba87eeb593646568621c7fc7f133db300ef18d65d1a5a60dc9c7beb9000364d93c581df languageName: node linkType: hard @@ -21543,11 +21459,11 @@ __metadata: linkType: hard "use-sync-external-store@npm:^1.0.0": - version: 1.2.2 - resolution: "use-sync-external-store@npm:1.2.2" + version: 1.4.0 + resolution: "use-sync-external-store@npm:1.4.0" peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - checksum: fe07c071c4da3645f112c38c0e57beb479a8838616ff4e92598256ecce527f2888c08febc7f9b2f0ce2f0e18540ba3cde41eb2035e4fafcb4f52955037098a81 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + checksum: dc3843a1b59ac8bd01417bd79498d4c688d5df8bf4801be50008ef4bfaacb349058c0b1605b5b43c828e0a2d62722d7e861573b3f31cea77a7f23e8b0fc2f7e3 languageName: node linkType: hard @@ -22216,37 +22132,37 @@ __metadata: languageName: node linkType: hard -"which-boxed-primitive@npm:^1.0.2": - version: 1.1.0 - resolution: "which-boxed-primitive@npm:1.1.0" +"which-boxed-primitive@npm:^1.0.2, which-boxed-primitive@npm:^1.1.0, which-boxed-primitive@npm:^1.1.1": + version: 1.1.1 + resolution: "which-boxed-primitive@npm:1.1.1" dependencies: is-bigint: ^1.1.0 - is-boolean-object: ^1.2.0 - is-number-object: ^1.1.0 - is-string: ^1.1.0 - is-symbol: ^1.1.0 - checksum: 49ebec9693ed21ee8183b9e353ee7134a03722776c84624019964124885a4a940f469af3d1508ad83022a68cc515aecbef70fb1256ace57a871c43d24d050304 + is-boolean-object: ^1.2.1 + is-number-object: ^1.1.1 + is-string: ^1.1.1 + is-symbol: ^1.1.1 + checksum: ee41d0260e4fd39551ad77700c7047d3d281ec03d356f5e5c8393fe160ba0db53ef446ff547d05f76ffabfd8ad9df7c9a827e12d4cccdbc8fccf9239ff8ac21e languageName: node linkType: hard -"which-builtin-type@npm:^1.1.4": - version: 1.2.0 - resolution: "which-builtin-type@npm:1.2.0" +"which-builtin-type@npm:^1.2.1": + version: 1.2.1 + resolution: "which-builtin-type@npm:1.2.1" dependencies: - call-bind: ^1.0.7 + call-bound: ^1.0.2 function.prototype.name: ^1.1.6 has-tostringtag: ^1.0.2 is-async-function: ^2.0.0 - is-date-object: ^1.0.5 + is-date-object: ^1.1.0 is-finalizationregistry: ^1.1.0 is-generator-function: ^1.0.10 - is-regex: ^1.1.4 + is-regex: ^1.2.1 is-weakref: ^1.0.2 isarray: ^2.0.5 - which-boxed-primitive: ^1.0.2 + which-boxed-primitive: ^1.1.0 which-collection: ^1.0.2 - which-typed-array: ^1.1.15 - checksum: 6d40ecdf33a28c3fdeab13e7e3b4289fb51f7ebd0983e628d50fa42e113d8be1bc7dd0e6eb23c6b6a0c2c0c7667763eca3a2af1f6d768e48efba8073870eb568 + which-typed-array: ^1.1.16 + checksum: 7a3617ba0e7cafb795f74db418df889867d12bce39a477f3ee29c6092aa64d396955bf2a64eae3726d8578440e26777695544057b373c45a8bcf5fbe920bf633 languageName: node linkType: hard @@ -22269,16 +22185,17 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.15, which-typed-array@npm:^1.1.2": - version: 1.1.16 - resolution: "which-typed-array@npm:1.1.16" +"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.18, which-typed-array@npm:^1.1.2": + version: 1.1.18 + resolution: "which-typed-array@npm:1.1.18" dependencies: available-typed-arrays: ^1.0.7 - call-bind: ^1.0.7 + call-bind: ^1.0.8 + call-bound: ^1.0.3 for-each: ^0.3.3 - gopd: ^1.0.1 + gopd: ^1.2.0 has-tostringtag: ^1.0.2 - checksum: 903d398ec234d608011e1df09af6c004e66965bb24d5e1a82856cba0495fa6389ae393d1c9d5411498a9cba8e61b2e39a8e8be7b3005cbeadd317f772b1bdaef + checksum: d2feea7f51af66b3a240397aa41c796585033e1069f18e5b6d4cd3878538a1e7780596fd3ea9bf347c43d9e98e13be09b37d9ea3887cef29b11bc291fd47bb52 languageName: node linkType: hard From b77ed2b4c0ea5d8be37cb3a80baa9106ad5d180d Mon Sep 17 00:00:00 2001 From: Peyton-McKee Date: Tue, 7 Jan 2025 14:11:26 -0500 Subject: [PATCH 04/11] Fix TSC Check --- .../src/pages/HomePage/components/TaskDetailCard.tsx | 8 ++++++-- .../src/pages/HomePage/components/TeamTaskCard.tsx | 6 +++++- src/frontend/src/utils/task.utils.ts | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/frontend/src/pages/HomePage/components/TaskDetailCard.tsx b/src/frontend/src/pages/HomePage/components/TaskDetailCard.tsx index 1e4045ea07..87a9d90910 100644 --- a/src/frontend/src/pages/HomePage/components/TaskDetailCard.tsx +++ b/src/frontend/src/pages/HomePage/components/TaskDetailCard.tsx @@ -31,7 +31,7 @@ const NERToolTip = styled(({ className, ...props }: TooltipProps) => ( const TaskDetailCard: React.FC = ({ task, taskNumber }) => { const theme = useTheme(); - const taskDaysOverdue = daysOverdue(new Date(task.deadline)); + const taskDaysOverdue = task.deadline ? daysOverdue(new Date(task.deadline)) : 0; const taskOverdue = taskDaysOverdue > 0; const [hover, setHover] = useState(false); const { data: project, isLoading, isError, error } = useSingleProject(task.wbsNum); @@ -99,7 +99,11 @@ const TaskDetailCard: React.FC = ({ task, taskNumber }) => label={task.priority} size="small" /> - } label={formatDate(new Date(task.deadline))} size="small" /> + } + label={task.deadline ? formatDate(new Date(task.deadline)) : 'No Deadline'} + size="small" + /> = ({ task, taskNumber }) => { label={task.priority} size="medium" /> - } label={formatDate(new Date(task.deadline))} size="medium" /> + } + label={task.deadline ? formatDate(new Date(task.deadline)) : 'No Deadline'} + size="medium" + />
diff --git a/src/frontend/src/utils/task.utils.ts b/src/frontend/src/utils/task.utils.ts index e79771b896..59046cf887 100644 --- a/src/frontend/src/utils/task.utils.ts +++ b/src/frontend/src/utils/task.utils.ts @@ -81,6 +81,6 @@ export const taskPriorityColor = (task: Task) => { }; export const getOverdueTasks = (tasks: Task[]) => { - const overdueTasks = new Set(tasks.filter((task) => daysOverdue(new Date(task.deadline)) > 0)); + const overdueTasks = new Set(tasks.filter((task) => (task.deadline ? daysOverdue(new Date(task.deadline)) : 0) > 0)); return [...overdueTasks]; }; From 3feeb64e34e87ceb59f76725002b4ad25fe97f3e Mon Sep 17 00:00:00 2001 From: Peyton-McKee Date: Tue, 7 Jan 2025 14:23:46 -0500 Subject: [PATCH 05/11] Fix Wrong Imports --- src/backend/src/services/notifications.services.ts | 3 +-- src/backend/src/utils/design-reviews.utils.ts | 6 ------ src/backend/src/utils/slack.utils.ts | 4 ++-- .../src/pages/HomePage/components/DesignReviewCard.tsx | 3 +-- src/frontend/src/tests/pages/HomePage/Home.test.tsx | 3 --- src/shared/src/utils.ts | 6 ++++++ 6 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/backend/src/services/notifications.services.ts b/src/backend/src/services/notifications.services.ts index 176d4bc73e..8dd4a2d879 100644 --- a/src/backend/src/services/notifications.services.ts +++ b/src/backend/src/services/notifications.services.ts @@ -7,12 +7,11 @@ import { usersToSlackPings } from '../utils/notifications.utils'; import { sendMessage } from '../integrations/slack'; -import { daysBetween, startOfDay, wbsPipe } from 'shared'; +import { daysBetween, meetingStartTimePipe, startOfDay, wbsPipe } from 'shared'; import { buildDueString } from '../utils/slack.utils'; import WorkPackagesService from './work-packages.services'; import { addWeeksToDate } from 'shared'; import { HttpException } from '../utils/errors.utils'; -import { meetingStartTimePipe } from '../utils/design-reviews.utils'; export default class NotificationsService { static async sendDailySlackNotifications() { diff --git a/src/backend/src/utils/design-reviews.utils.ts b/src/backend/src/utils/design-reviews.utils.ts index b7fd9ba65f..8a42700a70 100644 --- a/src/backend/src/utils/design-reviews.utils.ts +++ b/src/backend/src/utils/design-reviews.utils.ts @@ -29,12 +29,6 @@ export const isUserOnDesignReview = (user: User, designReview: DesignReview): bo return requiredMembers.includes(user.userId) || optionalMembers.includes(user.userId); }; -export const meetingStartTimePipe = (times: number[]) => { - const time = (times[0] % 12) + 10; - - return time <= 12 ? time + 'am' : time - 12 + 'pm'; -}; - export const transformStartTime = (times: number[]) => { return (times[0] % 12) + 10; }; diff --git a/src/backend/src/utils/slack.utils.ts b/src/backend/src/utils/slack.utils.ts index 4019c6d6db..73d040f7ab 100644 --- a/src/backend/src/utils/slack.utils.ts +++ b/src/backend/src/utils/slack.utils.ts @@ -1,4 +1,4 @@ -import { ChangeRequest, daysBetween, Task, UserPreview, wbsPipe, calculateEndDate } from 'shared'; +import { ChangeRequest, daysBetween, Task, UserPreview, wbsPipe, calculateEndDate, meetingStartTimePipe } from 'shared'; import { User } from '@prisma/client'; import { editMessage, @@ -15,7 +15,7 @@ import { HttpException } from './errors.utils'; import { Change_Request, Design_Review, Team, WBS_Element } from '@prisma/client'; import { UserWithSettings } from './auth.utils'; import { usersToSlackPings, userToSlackPing } from './notifications.utils'; -import { addHours, meetingStartTimePipe } from './design-reviews.utils'; +import { addHours } from './design-reviews.utils'; import { WorkPackageQueryArgs } from '../prisma-query-args/work-packages.query-args'; import { Prisma } from '@prisma/client'; import { userTransformer } from '../transformers/user.transformer'; diff --git a/src/frontend/src/pages/HomePage/components/DesignReviewCard.tsx b/src/frontend/src/pages/HomePage/components/DesignReviewCard.tsx index fdc80c595f..b2896398e6 100644 --- a/src/frontend/src/pages/HomePage/components/DesignReviewCard.tsx +++ b/src/frontend/src/pages/HomePage/components/DesignReviewCard.tsx @@ -1,5 +1,5 @@ import { Box, Card, CardContent, Link, Stack, Typography, useTheme } from '@mui/material'; -import { DesignReview, User } from 'shared'; +import { DesignReview, meetingStartTimePipe, User } from 'shared'; import { datePipe, projectWbsPipe } from '../../../utils/pipes'; import { routes } from '../../../utils/routes'; import { Link as RouterLink } from 'react-router-dom'; @@ -7,7 +7,6 @@ import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; import { LocationOnOutlined, Computer } from '@mui/icons-material'; import { useHistory } from 'react-router-dom'; import { NERButton } from '../../../components/NERButton'; -import { meetingStartTimePipe } from '../../../../../backend/src/utils/design-reviews.utils'; import { timezoneOffset } from '../../../utils/datetime.utils'; interface DesignReviewProps { diff --git a/src/frontend/src/tests/pages/HomePage/Home.test.tsx b/src/frontend/src/tests/pages/HomePage/Home.test.tsx index 5f1c3c9f03..e76fff2d39 100644 --- a/src/frontend/src/tests/pages/HomePage/Home.test.tsx +++ b/src/frontend/src/tests/pages/HomePage/Home.test.tsx @@ -63,8 +63,5 @@ describe('home component', () => { it('renders welcome', () => { renderComponent(); expect(screen.getByText(`Welcome, ${exampleAdminUser.firstName}!`)).toBeInTheDocument(); - expect(screen.getByText('useful-links')).toBeInTheDocument(); - expect(screen.getByText('upcoming-deadlines')).toBeInTheDocument(); - expect(screen.getByText('work-packages-by-timeline-status')).toBeInTheDocument(); }); }); diff --git a/src/shared/src/utils.ts b/src/shared/src/utils.ts index 2d2500e275..8a63678f3a 100644 --- a/src/shared/src/utils.ts +++ b/src/shared/src/utils.ts @@ -24,3 +24,9 @@ export const wbsNamePipe = (wbsElement: { wbsNum: WbsNumber; name: string }) => export const isSubset = (elements: string[], suppliedArray: string[]): boolean => { return elements.every((element) => suppliedArray.includes(element)); }; + +export const meetingStartTimePipe = (times: number[]) => { + const time = (times[0] % 12) + 10; + + return time <= 12 ? time + 'am' : time - 12 + 'pm'; +}; \ No newline at end of file From a7b1ef6cea85986bc4c0c52d895a6fe807539c6c Mon Sep 17 00:00:00 2001 From: Peyton-McKee Date: Tue, 7 Jan 2025 14:26:06 -0500 Subject: [PATCH 06/11] prettier --- src/shared/src/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/src/utils.ts b/src/shared/src/utils.ts index 8a63678f3a..0c7d782815 100644 --- a/src/shared/src/utils.ts +++ b/src/shared/src/utils.ts @@ -29,4 +29,4 @@ export const meetingStartTimePipe = (times: number[]) => { const time = (times[0] % 12) + 10; return time <= 12 ? time + 'am' : time - 12 + 'pm'; -}; \ No newline at end of file +}; From 8a2fd330387137eeb0da702aa13d14f3dccfbde7 Mon Sep 17 00:00:00 2001 From: Peyton-McKee Date: Thu, 9 Jan 2025 12:56:05 -0500 Subject: [PATCH 07/11] consolidate migrations --- .../migration.sql | 8 -------- .../migration.sql | 2 -- .../migration.sql | 18 ++++++++++-------- 3 files changed, 10 insertions(+), 18 deletions(-) delete mode 100644 src/backend/src/prisma/migrations/20240910005616_add_logo_image_featured_project/migration.sql delete mode 100644 src/backend/src/prisma/migrations/20241113231854_optional_deadline_assignees_task/migration.sql rename src/backend/src/prisma/migrations/{20250107183556_stats_page_home_page => 20250109175241_stats_home_page_optional_task_assignees_deadlines}/migration.sql (94%) diff --git a/src/backend/src/prisma/migrations/20240910005616_add_logo_image_featured_project/migration.sql b/src/backend/src/prisma/migrations/20240910005616_add_logo_image_featured_project/migration.sql deleted file mode 100644 index fe5771a6b1..0000000000 --- a/src/backend/src/prisma/migrations/20240910005616_add_logo_image_featured_project/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ --- AlterTable -ALTER TABLE "Organization" ADD COLUMN "logoImage" TEXT; - --- AlterTable -ALTER TABLE "Project" ADD COLUMN "organizationId" TEXT; - --- AddForeignKey -ALTER TABLE "Project" ADD CONSTRAINT "Project_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/src/backend/src/prisma/migrations/20241113231854_optional_deadline_assignees_task/migration.sql b/src/backend/src/prisma/migrations/20241113231854_optional_deadline_assignees_task/migration.sql deleted file mode 100644 index 28f390d560..0000000000 --- a/src/backend/src/prisma/migrations/20241113231854_optional_deadline_assignees_task/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Task" ALTER COLUMN "deadline" DROP NOT NULL; diff --git a/src/backend/src/prisma/migrations/20250107183556_stats_page_home_page/migration.sql b/src/backend/src/prisma/migrations/20250109175241_stats_home_page_optional_task_assignees_deadlines/migration.sql similarity index 94% rename from src/backend/src/prisma/migrations/20250107183556_stats_page_home_page/migration.sql rename to src/backend/src/prisma/migrations/20250109175241_stats_home_page_optional_task_assignees_deadlines/migration.sql index 5ff6ef192b..21fbd119ee 100644 --- a/src/backend/src/prisma/migrations/20250107183556_stats_page_home_page/migration.sql +++ b/src/backend/src/prisma/migrations/20250109175241_stats_home_page_optional_task_assignees_deadlines/migration.sql @@ -1,9 +1,3 @@ -/* - Warnings: - - - You are about to drop the column `logoImage` on the `Organization` table. All the data in the column will be lost. - -*/ -- CreateEnum CREATE TYPE "Graph_Type" AS ENUM ('PROJECT_BUDGET_BY_PROJECT', 'PROJECT_BUDGET_BY_TEAM', 'PROJECT_BUDGET_BY_DIVISION', 'CHANGE_REQUESTS_BY_PROJECT', 'CHANGE_REQUESTS_BY_TEAM', 'CHANGE_REQUESTS_BY_DIVISION', 'REIMBURSEMENT_TOTAL_BY_PROJECT', 'REIMBURSEMENT_TOTAL_BY_TEAM', 'REIMBURSEMENT_TOTAL_BY_DIVISION'); @@ -23,10 +17,15 @@ CREATE TYPE "Graph_Collection_Permission" AS ENUM ('EDIT_GRAPH_COLLECTION', 'CRE CREATE TYPE "Special_Permission" AS ENUM ('FINANCE_ONLY'); -- AlterTable -ALTER TABLE "Organization" DROP COLUMN "logoImage", -ADD COLUMN "logoImageId" TEXT, +ALTER TABLE "Organization" ADD COLUMN "logoImageId" TEXT, ADD COLUMN "slackWorkspaceId" TEXT; +-- AlterTable +ALTER TABLE "Project" ADD COLUMN "organizationId" TEXT; + +-- AlterTable +ALTER TABLE "Task" ALTER COLUMN "deadline" DROP NOT NULL; + -- AlterTable ALTER TABLE "Team_Type" ADD COLUMN "dateDeleted" TIMESTAMP(3), ADD COLUMN "deletedById" TEXT; @@ -132,6 +131,9 @@ CREATE UNIQUE INDEX "_userPopUps_AB_unique" ON "_userPopUps"("A", "B"); -- CreateIndex CREATE INDEX "_userPopUps_B_index" ON "_userPopUps"("B"); +-- AddForeignKey +ALTER TABLE "Project" ADD CONSTRAINT "Project_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE SET NULL ON UPDATE CASCADE; + -- AddForeignKey ALTER TABLE "Team_Type" ADD CONSTRAINT "Team_Type_deletedById_fkey" FOREIGN KEY ("deletedById") REFERENCES "User"("userId") ON DELETE SET NULL ON UPDATE CASCADE; From add39e64cad6c87500929f02f0711814211cda4c Mon Sep 17 00:00:00 2001 From: Peyton-McKee Date: Thu, 9 Jan 2025 13:21:45 -0500 Subject: [PATCH 08/11] Enforce User Organization Membership on API request --- src/backend/src/utils/auth.utils.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/backend/src/utils/auth.utils.ts b/src/backend/src/utils/auth.utils.ts index 277010b66d..47e514970e 100644 --- a/src/backend/src/utils/auth.utils.ts +++ b/src/backend/src/utils/auth.utils.ts @@ -120,7 +120,7 @@ export type UserWithSecureSettings = UserWithSettings & { userSecureSettings: User_Secure_Settings | null; }; -export const getOrganization = async (headers: IncomingHttpHeaders): Promise => { +export const getOrganization = async (headers: IncomingHttpHeaders, currentUser: User): Promise => { let { organizationid } = headers; const isProd = process.env.NODE_ENV === 'production'; @@ -141,7 +141,8 @@ export const getOrganization = async (headers: IncomingHttpHeaders): Promise user.userId === currentUser.userId)) { + throw new AccessDeniedException('Cannot access this organization'); + } + return organization; }; @@ -181,7 +186,7 @@ export const getUserAndOrganization = async (req: Request, res: Response, next: } try { const user = await getCurrentUser(res); - const organization = await getOrganization(req.headers); + const organization = await getOrganization(req.headers, user); req.currentUser = user; req.organization = organization; return next(); From 96c026f71d2eb9ef78ea0a01d47f462ba1147b02 Mon Sep 17 00:00:00 2001 From: Peyton-McKee Date: Thu, 9 Jan 2025 13:23:58 -0500 Subject: [PATCH 09/11] Check if organization is deleted in middleware --- src/backend/src/utils/auth.utils.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/backend/src/utils/auth.utils.ts b/src/backend/src/utils/auth.utils.ts index 47e514970e..3f6b11d291 100644 --- a/src/backend/src/utils/auth.utils.ts +++ b/src/backend/src/utils/auth.utils.ts @@ -2,7 +2,7 @@ import jwt from 'jsonwebtoken'; import { Request, Response, NextFunction } from 'express'; import { JwtPayload, VerifyErrors } from 'jsonwebtoken'; import prisma from '../prisma/prisma'; -import { AccessDeniedException, HttpException, NotFoundException } from './errors.utils'; +import { AccessDeniedException, DeletedException, HttpException, NotFoundException } from './errors.utils'; import { Organization, User, User_Secure_Settings, User_Settings } from '@prisma/client'; import { IncomingHttpHeaders } from 'http'; @@ -150,6 +150,10 @@ export const getOrganization = async (headers: IncomingHttpHeaders, currentUser: throw new NotFoundException('Organization', organizationid); } + if (organization.dateDeleted) { + throw new DeletedException('Organization', organization.organizationId); + } + if (!organization.users.some((user) => user.userId === currentUser.userId)) { throw new AccessDeniedException('Cannot access this organization'); } From ab9af6307c050180ed64cf8c714c42e49f3e9282 Mon Sep 17 00:00:00 2001 From: caiodasilva2005 Date: Thu, 9 Jan 2025 17:09:35 -0500 Subject: [PATCH 10/11] fixed endpoint checks on homepage --- .../prisma-query-args/pop-up.query-args.ts | 2 +- .../migration.sql | 4 +-- src/backend/src/prisma/schema.prisma | 26 +++++++++---------- .../src/services/announcement.service.ts | 8 ++++-- src/backend/src/services/pop-up.services.ts | 8 +++++- src/backend/src/services/users.services.ts | 4 ++- src/backend/src/utils/errors.utils.ts | 1 + src/backend/src/utils/projects.utils.ts | 2 +- src/backend/tests/test-utils.ts | 1 + 9 files changed, 35 insertions(+), 21 deletions(-) rename src/backend/src/prisma/migrations/{20250109175241_stats_home_page_optional_task_assignees_deadlines => 20250109215552_stats_home_page_optional_task_assignees_deadlines}/migration.sql (96%) diff --git a/src/backend/src/prisma-query-args/pop-up.query-args.ts b/src/backend/src/prisma-query-args/pop-up.query-args.ts index 0862956d22..52f989099f 100644 --- a/src/backend/src/prisma-query-args/pop-up.query-args.ts +++ b/src/backend/src/prisma-query-args/pop-up.query-args.ts @@ -6,6 +6,6 @@ export type PopUpQueryArgs = ReturnType; export const getPopUpQueryArgs = (organizationId: string) => Prisma.validator()({ include: { - users: getUserQueryArgs(organizationId) + usersReceived: getUserQueryArgs(organizationId) } }); diff --git a/src/backend/src/prisma/migrations/20250109175241_stats_home_page_optional_task_assignees_deadlines/migration.sql b/src/backend/src/prisma/migrations/20250109215552_stats_home_page_optional_task_assignees_deadlines/migration.sql similarity index 96% rename from src/backend/src/prisma/migrations/20250109175241_stats_home_page_optional_task_assignees_deadlines/migration.sql rename to src/backend/src/prisma/migrations/20250109215552_stats_home_page_optional_task_assignees_deadlines/migration.sql index 21fbd119ee..90d73bcdaa 100644 --- a/src/backend/src/prisma/migrations/20250109175241_stats_home_page_optional_task_assignees_deadlines/migration.sql +++ b/src/backend/src/prisma/migrations/20250109215552_stats_home_page_optional_task_assignees_deadlines/migration.sql @@ -21,7 +21,7 @@ ALTER TABLE "Organization" ADD COLUMN "logoImageId" TEXT, ADD COLUMN "slackWorkspaceId" TEXT; -- AlterTable -ALTER TABLE "Project" ADD COLUMN "organizationId" TEXT; +ALTER TABLE "Project" ADD COLUMN "featuredByOrganizationId" TEXT; -- AlterTable ALTER TABLE "Task" ALTER COLUMN "deadline" DROP NOT NULL; @@ -132,7 +132,7 @@ CREATE UNIQUE INDEX "_userPopUps_AB_unique" ON "_userPopUps"("A", "B"); CREATE INDEX "_userPopUps_B_index" ON "_userPopUps"("B"); -- AddForeignKey -ALTER TABLE "Project" ADD CONSTRAINT "Project_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("organizationId") ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE "Project" ADD CONSTRAINT "Project_featuredByOrganizationId_fkey" FOREIGN KEY ("featuredByOrganizationId") REFERENCES "Organization"("organizationId") ON DELETE SET NULL ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "Team_Type" ADD CONSTRAINT "Team_Type_deletedById_fkey" FOREIGN KEY ("deletedById") REFERENCES "User"("userId") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/src/backend/src/prisma/schema.prisma b/src/backend/src/prisma/schema.prisma index 3e31e4becc..12416a4a91 100644 --- a/src/backend/src/prisma/schema.prisma +++ b/src/backend/src/prisma/schema.prisma @@ -432,18 +432,18 @@ model WBS_Element { } model Project { - projectId String @id @default(uuid()) - wbsElementId String @unique - wbsElement WBS_Element @relation(fields: [wbsElementId], references: [wbsElementId]) - budget Int @default(0) - summary String - workPackages Work_Package[] - carId String - car Car @relation(fields: [carId], references: [carId]) - teams Team[] @relation(name: "assignedBy") - favoritedBy User[] @relation(name: "favoritedBy") - organizationId String? - organization Organization? @relation(fields: [organizationId], references: [organizationId]) + projectId String @id @default(uuid()) + wbsElementId String @unique + wbsElement WBS_Element @relation(fields: [wbsElementId], references: [wbsElementId]) + budget Int @default(0) + summary String + workPackages Work_Package[] + carId String + car Car @relation(fields: [carId], references: [carId]) + teams Team[] @relation(name: "assignedBy") + favoritedBy User[] @relation(name: "favoritedBy") + featuredByOrganizationId String? + featuredByOrganization Organization? @relation(fields: [featuredByOrganizationId], references: [organizationId]) } model Work_Package { @@ -1047,7 +1047,7 @@ model PopUp { popUpId String @id @default(uuid()) text String iconName String - users User[] @relation("userPopUps") + usersReceived User[] @relation("userPopUps") eventLink String? organizationId String organization Organization @relation(fields: [organizationId], references: [organizationId]) diff --git a/src/backend/src/services/announcement.service.ts b/src/backend/src/services/announcement.service.ts index 6b5c758338..e109cd1984 100644 --- a/src/backend/src/services/announcement.service.ts +++ b/src/backend/src/services/announcement.service.ts @@ -3,6 +3,7 @@ import prisma from '../prisma/prisma'; import { getAnnouncementQueryArgs } from '../prisma-query-args/announcements.query.args'; import announcementTransformer from '../transformers/announcements.transformer'; import { DeletedException, HttpException, NotFoundException } from '../utils/errors.utils'; +import { getUsers } from '../utils/users.utils'; export default class AnnouncementService { /** @@ -26,12 +27,15 @@ export default class AnnouncementService { slackChannelName: string, organizationId: string ): Promise { + // throws if a user id is invalid + const usersToSend = await getUsers(usersReceivedIds); + const announcement = await prisma.announcement.create({ data: { text, usersReceived: { - connect: usersReceivedIds.map((id) => ({ - userId: id + connect: usersToSend.map((user) => ({ + userId: user.userId })) }, dateMessageSent, diff --git a/src/backend/src/services/pop-up.services.ts b/src/backend/src/services/pop-up.services.ts index 61bba89bd0..cf70419bc6 100644 --- a/src/backend/src/services/pop-up.services.ts +++ b/src/backend/src/services/pop-up.services.ts @@ -13,7 +13,7 @@ export class PopUpService { static async getUserUnreadPopUps(userId: string, organizationId: string) { const unreadPopUps = await prisma.popUp.findMany({ where: { - users: { + usersReceived: { some: { userId } }, organizationId @@ -34,6 +34,12 @@ export class PopUpService { * @returns the user's updated unread pop up */ static async removeUserPopUp(userId: string, popUpId: string, organizationId: string) { + const popUp = await prisma.popUp.findUnique({ + where: { popUpId } + }); + + if (!popUp) throw new NotFoundException('Pop Up', popUpId); + const updatedUser = await prisma.user.update({ where: { userId }, data: { diff --git a/src/backend/src/services/users.services.ts b/src/backend/src/services/users.services.ts index d786c04137..4d89cee82d 100644 --- a/src/backend/src/services/users.services.ts +++ b/src/backend/src/services/users.services.ts @@ -545,9 +545,11 @@ export default class UsersService { static async getUserTasks(userId: string, organization: Organization) { const requestedUser = await prisma.user.findUnique({ where: { userId }, - include: { assignedTasks: getTaskQueryArgs(organization.organizationId) } + include: { assignedTasks: getTaskQueryArgs(organization.organizationId), organizations: true } }); if (!requestedUser) throw new NotFoundException('User', userId); + if (!requestedUser.organizations.map((org) => org.organizationId).includes(organization.organizationId)) + throw new HttpException(400, `User ${userId} is not apart of the current organization`); return requestedUser.assignedTasks.map(taskTransformer); } diff --git a/src/backend/src/utils/errors.utils.ts b/src/backend/src/utils/errors.utils.ts index efa4bfb7c8..6c30280c9d 100644 --- a/src/backend/src/utils/errors.utils.ts +++ b/src/backend/src/utils/errors.utils.ts @@ -139,6 +139,7 @@ export type ExceptionObjectNames = | 'Car' | 'Milestone' | 'Faq' + | 'Pop Up' | 'Announcement' | 'Graph' | 'Graph Collection'; diff --git a/src/backend/src/utils/projects.utils.ts b/src/backend/src/utils/projects.utils.ts index 22becc4e89..9f8f5e3238 100644 --- a/src/backend/src/utils/projects.utils.ts +++ b/src/backend/src/utils/projects.utils.ts @@ -225,7 +225,7 @@ export const checkMaterialInputs = async ( */ export const getProjects = async (projectIds: string[], organizationId: string) => { const projects = await prisma.project.findMany({ - where: { projectId: { in: projectIds } }, + where: { projectId: { in: projectIds }, wbsElement: { organizationId, dateDeleted: null } }, ...getProjectQueryArgs(organizationId) }); diff --git a/src/backend/tests/test-utils.ts b/src/backend/tests/test-utils.ts index 43a5fba7bb..c6c5ac4678 100644 --- a/src/backend/tests/test-utils.ts +++ b/src/backend/tests/test-utils.ts @@ -60,6 +60,7 @@ export const createTestUser = async ( } }, additionalPermissions: permissions + organizations: { connect: { organizationId } } } }); From 95edbc61e38fbd6be32a53b978cec8db9b0ef2c8 Mon Sep 17 00:00:00 2001 From: caiodasilva2005 Date: Thu, 9 Jan 2025 17:14:14 -0500 Subject: [PATCH 11/11] small fix --- src/backend/tests/test-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/tests/test-utils.ts b/src/backend/tests/test-utils.ts index c6c5ac4678..0665047826 100644 --- a/src/backend/tests/test-utils.ts +++ b/src/backend/tests/test-utils.ts @@ -59,7 +59,7 @@ export const createTestUser = async ( organizationId } }, - additionalPermissions: permissions + additionalPermissions: permissions, organizations: { connect: { organizationId } } } });