diff --git a/application/backend/batches/sendMailsForRules.ts b/application/backend/batches/sendMailsForRules.ts index 603a77ae..fc00df6b 100644 --- a/application/backend/batches/sendMailsForRules.ts +++ b/application/backend/batches/sendMailsForRules.ts @@ -3,7 +3,7 @@ import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit.js"; import MailRule from "jc-shared/mail/mailRule.js"; import mailstore from "../lib/mailsender/mailstore.js"; import mailtransport from "../lib/mailsender/mailtransport.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../simpleConfigure.js"; import Vermietung from "jc-shared/vermietung/vermietung.js"; import { byDateRangeInAscendingOrder } from "./gigAndRentService.js"; import VeranstaltungFormatter from "jc-shared/veranstaltung/VeranstaltungFormatter.js"; diff --git a/application/backend/batches/sendMailsKasseFehlt.ts b/application/backend/batches/sendMailsKasseFehlt.ts index 6813e9b2..ccc1c7ac 100644 --- a/application/backend/batches/sendMailsKasseFehlt.ts +++ b/application/backend/batches/sendMailsKasseFehlt.ts @@ -2,7 +2,7 @@ import { loggers } from "winston"; import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit.js"; import Konzert from "jc-shared/konzert/konzert.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../simpleConfigure.js"; import store from "../lib/konzerte/konzertestore.js"; import userstore from "../lib/users/userstore.js"; diff --git a/application/backend/batches/sendMailsMasterFehlt.ts b/application/backend/batches/sendMailsMasterFehlt.ts index c608bb11..c117c278 100644 --- a/application/backend/batches/sendMailsMasterFehlt.ts +++ b/application/backend/batches/sendMailsMasterFehlt.ts @@ -2,7 +2,7 @@ import { loggers } from "winston"; import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit.js"; import Konzert from "jc-shared/konzert/konzert.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../simpleConfigure.js"; import store from "../lib/konzerte/konzertestore.js"; import userstore from "../lib/users/userstore.js"; diff --git a/application/backend/batches/sendMailsNightlyBar.ts b/application/backend/batches/sendMailsNightlyBar.ts index 7479aa47..b5289193 100644 --- a/application/backend/batches/sendMailsNightlyBar.ts +++ b/application/backend/batches/sendMailsNightlyBar.ts @@ -1,7 +1,7 @@ import { loggers } from "winston"; import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../simpleConfigure.js"; import mailtransport from "../lib/mailsender/mailtransport.js"; import usersService from "../lib/users/usersService.js"; import { byDateRangeInAscendingOrder } from "./gigAndRentService.js"; diff --git a/application/backend/batches/sendMailsNightlyPhotoAndFluegel.ts b/application/backend/batches/sendMailsNightlyPhotoAndFluegel.ts index db9093f8..6543975b 100644 --- a/application/backend/batches/sendMailsNightlyPhotoAndFluegel.ts +++ b/application/backend/batches/sendMailsNightlyPhotoAndFluegel.ts @@ -1,7 +1,7 @@ import { loggers } from "winston"; import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../simpleConfigure.js"; import mailtransport from "../lib/mailsender/mailtransport.js"; import usersService from "../lib/users/usersService.js"; import Vermietung from "jc-shared/vermietung/vermietung.js"; diff --git a/application/backend/batches/sendMailsPressetextFehlt.ts b/application/backend/batches/sendMailsPressetextFehlt.ts index 1e6fabfe..3271c360 100644 --- a/application/backend/batches/sendMailsPressetextFehlt.ts +++ b/application/backend/batches/sendMailsPressetextFehlt.ts @@ -2,7 +2,7 @@ import { loggers } from "winston"; import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit.js"; import MailRule from "jc-shared/mail/mailRule.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../simpleConfigure.js"; import mailstore from "../lib/mailsender/mailstore.js"; import mailtransport from "../lib/mailsender/mailtransport.js"; import usersService from "../lib/users/usersService.js"; diff --git a/application/backend/batches/sendMailsStaffReminder.ts b/application/backend/batches/sendMailsStaffReminder.ts index 75b2309e..901d09af 100644 --- a/application/backend/batches/sendMailsStaffReminder.ts +++ b/application/backend/batches/sendMailsStaffReminder.ts @@ -1,6 +1,6 @@ import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../simpleConfigure.js"; import userstore from "../lib/users/userstore.js"; import mailtransport from "../lib/mailsender/mailtransport.js"; import mixVeranstaltungenMitUsers, { VerMitUser } from "jc-shared/commons/mixVeranstaltungenMitUsers.js"; diff --git a/application/backend/configure.ts b/application/backend/configure.ts index a07b9d28..6da28b16 100644 --- a/application/backend/configure.ts +++ b/application/backend/configure.ts @@ -1,4 +1,4 @@ -import conf, { SimpleConfigure } from "jc-shared/commons/simpleConfigure.js"; +import conf, { SimpleConfigure } from "./simpleConfigure.js"; import path, { dirname } from "path"; import fs from "fs"; import { fileURLToPath } from "url"; diff --git a/application/backend/configureApp.ts b/application/backend/configureApp.ts index ff4d0e80..06c62ff9 100644 --- a/application/backend/configureApp.ts +++ b/application/backend/configureApp.ts @@ -13,7 +13,7 @@ import ridersrest from "./lib/rider/ridersrest.js"; import passportInitializer from "./lib/middleware/passportInitializer.js"; import passportApiKeyInitializer from "./lib/middleware/passportApiKeyInitializer.js"; import { fileURLToPath } from "url"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "./simpleConfigure.js"; const __dirname = dirname(fileURLToPath(import.meta.url)); diff --git a/application/backend/lib/commons/hashPassword.ts b/application/backend/lib/commons/hashPassword.ts index 120b7825..41106910 100644 --- a/application/backend/lib/commons/hashPassword.ts +++ b/application/backend/lib/commons/hashPassword.ts @@ -1,5 +1,5 @@ import crypto from "crypto"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; export function genSalt(): string { const length = 64; diff --git a/application/backend/lib/konzerte/imageService.ts b/application/backend/lib/konzerte/imageService.ts index 0a5e2376..f4c1ab21 100644 --- a/application/backend/lib/konzerte/imageService.ts +++ b/application/backend/lib/konzerte/imageService.ts @@ -2,7 +2,7 @@ import User from "jc-shared/user/user.js"; import fs from "fs/promises"; import { ImageOverviewRow } from "jc-shared/konzert/konzert.js"; import store from "./konzertestore.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; import map from "lodash/map.js"; import sortBy from "lodash/sortBy.js"; diff --git a/application/backend/lib/konzerte/konzerteService.ts b/application/backend/lib/konzerte/konzerteService.ts index f4912d8a..64a5bfb8 100644 --- a/application/backend/lib/konzerte/konzerteService.ts +++ b/application/backend/lib/konzerte/konzerteService.ts @@ -11,7 +11,7 @@ import User from "jc-shared/user/user.js"; import store from "./konzertestore.js"; import groupBy from "lodash/groupBy.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; import map from "lodash/map.js"; import flatMap from "lodash/flatMap.js"; import forEach from "lodash/forEach.js"; diff --git a/application/backend/lib/konzerte/konzertestore.ts b/application/backend/lib/konzerte/konzertestore.ts index 13ffcdd8..9d7d0f02 100644 --- a/application/backend/lib/konzerte/konzertestore.ts +++ b/application/backend/lib/konzerte/konzertestore.ts @@ -9,6 +9,7 @@ import User from "jc-shared/user/user.js"; const persistence = pers("veranstaltungenstore", ["startDate", "endDate", "url"]); const logger = winston.loggers.get("transactions"); +import conf from "../../simpleConfigure.js"; function byDateRange(rangeFrom: DatumUhrzeit, rangeTo: DatumUhrzeit, sortOrder: "ASC" | "DESC") { const result = persistence.listByField( @@ -26,25 +27,21 @@ function byDateRangeInDescendingOrder(rangeFrom: DatumUhrzeit, rangeTo: DatumUhr return byDateRange(rangeFrom, rangeTo, "DESC"); } +function now() { + return DatumUhrzeit.forISOString(conf.nowForDevelopment); +} + export default { zukuenftigeMitGestern: function zukuenftigeMitGestern() { - const now = new DatumUhrzeit(); - return byDateRangeInAscendingOrder(now.minus({ tage: 1 }), now.plus({ jahre: 10 })); - }, - - zukuenftige: function zukuenftige() { - const now = new DatumUhrzeit(); - return byDateRangeInAscendingOrder(now, now.plus({ jahre: 10 })); + return byDateRangeInAscendingOrder(now().minus({ tage: 1 }), now().plus({ jahre: 10 })); }, vergangene: function vergangene() { - const now = new DatumUhrzeit(); - return byDateRangeInDescendingOrder(now.minus({ monate: 24 }), now); + return byDateRangeInDescendingOrder(now().minus({ monate: 24 }), now()); }, alle: function alle() { - const now = new DatumUhrzeit(); - return byDateRangeInDescendingOrder(now.minus({ jahre: 20 }), now.plus({ jahre: 10 })); + return byDateRangeInDescendingOrder(now().minus({ jahre: 20 }), now().plus({ jahre: 10 })); }, byDateRangeInAscendingOrder, diff --git a/application/backend/lib/mailsender/mailtransport.ts b/application/backend/lib/mailsender/mailtransport.ts index 1cc090e1..ea0053a8 100644 --- a/application/backend/lib/mailsender/mailtransport.ts +++ b/application/backend/lib/mailsender/mailtransport.ts @@ -2,7 +2,7 @@ import * as nodemailer from "nodemailer"; import * as Mail from "nodemailer/lib/mailer"; import * as winston from "winston"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; import MailBodyRenderer from "./mailbodyRenderer.js"; import MailMessage from "jc-shared/mail/mailMessage.js"; diff --git a/application/backend/lib/middleware/passportApiKeyInitializer.ts b/application/backend/lib/middleware/passportApiKeyInitializer.ts index cebb7e88..9a03639e 100644 --- a/application/backend/lib/middleware/passportApiKeyInitializer.ts +++ b/application/backend/lib/middleware/passportApiKeyInitializer.ts @@ -1,7 +1,7 @@ import passport from "passport"; import { Strategy } from "passport-http-bearer"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; import { loggers } from "winston"; const appLogger = loggers.get("application"); diff --git a/application/backend/lib/middleware/passportInitializer.ts b/application/backend/lib/middleware/passportInitializer.ts index 6d7375f6..6f18b49a 100644 --- a/application/backend/lib/middleware/passportInitializer.ts +++ b/application/backend/lib/middleware/passportInitializer.ts @@ -1,7 +1,7 @@ import passport from "passport"; import { ExtractJwt, Strategy, VerifiedCallback } from "passport-jwt"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; import { loggers } from "winston"; import store from "../users/userstore.js"; diff --git a/application/backend/lib/pdf/pdfGeneration.ts b/application/backend/lib/pdf/pdfGeneration.ts index 41bc5f8b..abfe3b4d 100644 --- a/application/backend/lib/pdf/pdfGeneration.ts +++ b/application/backend/lib/pdf/pdfGeneration.ts @@ -3,7 +3,7 @@ import { NextFunction, Response } from "express"; import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit.js"; import Konzert from "jc-shared/konzert/konzert.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; import store from "../konzerte/konzertestore.js"; import vermietungenstore from "../vermietungen/vermietungenstore.js"; import konzerteService from "../konzerte/konzerteService.js"; diff --git a/application/backend/lib/persistence/sqlitePersistence.ts b/application/backend/lib/persistence/sqlitePersistence.ts index 9933f63c..ebc5cb15 100644 --- a/application/backend/lib/persistence/sqlitePersistence.ts +++ b/application/backend/lib/persistence/sqlitePersistence.ts @@ -1,5 +1,5 @@ import Database, { SqliteError } from "better-sqlite3"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; import { loggers } from "winston"; import User from "jc-shared/user/user.js"; import { areDifferentForHistoryEntries } from "jc-shared/commons/comparingAndTransforming.js"; diff --git a/application/backend/lib/site/index.ts b/application/backend/lib/site/index.ts index 49375ede..ffefdae0 100644 --- a/application/backend/lib/site/index.ts +++ b/application/backend/lib/site/index.ts @@ -14,7 +14,7 @@ import store from "../konzerte/konzertestore.js"; import { resToJson } from "../commons/replies.js"; import userstore from "../users/userstore.js"; import { hashPassword } from "../commons/hashPassword.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; import refreshstore from "./refreshstore.js"; import usersService from "../users/usersService.js"; import User, { SUPERUSERS } from "jc-shared/user/user.js"; diff --git a/application/backend/lib/vermietungen/vermietungenstore.ts b/application/backend/lib/vermietungen/vermietungenstore.ts index ac179b79..f1b93d0b 100644 --- a/application/backend/lib/vermietungen/vermietungenstore.ts +++ b/application/backend/lib/vermietungen/vermietungenstore.ts @@ -6,6 +6,7 @@ import pers from "../persistence/sqlitePersistence.js"; import misc from "jc-shared/commons/misc.js"; import Vermietung from "jc-shared/vermietung/vermietung.js"; import User from "jc-shared/user/user.js"; +import conf from "../../simpleConfigure.js"; const persistence = pers("vermietungenstore", ["startDate", "endDate", "url"]); const logger = winston.loggers.get("transactions"); @@ -26,20 +27,17 @@ function byDateRangeInDescendingOrder(rangeFrom: DatumUhrzeit, rangeTo: DatumUhr return byDateRange(rangeFrom, rangeTo, "DESC"); } +function now() { + return DatumUhrzeit.forISOString(conf.nowForDevelopment); +} + export default { zukuenftigeMitGestern: function zukuenftigeMitGestern() { - const now = new DatumUhrzeit(); - return byDateRangeInAscendingOrder(now.minus({ tage: 1 }), now.plus({ jahre: 10 })); - }, - - zukuenftige: function zukuenftige() { - const now = new DatumUhrzeit(); - return byDateRangeInAscendingOrder(now, now.plus({ jahre: 10 })); + return byDateRangeInAscendingOrder(now().minus({ tage: 1 }), now().plus({ jahre: 10 })); }, vergangene: function vergangene() { - const now = new DatumUhrzeit(); - return byDateRangeInDescendingOrder(now.minus({ monate: 12 }), now); + return byDateRangeInDescendingOrder(now().minus({ monate: 12 }), now()); }, alle: function alle() { diff --git a/application/backend/lib/wiki/gitExec.ts b/application/backend/lib/wiki/gitExec.ts index e81a7523..41a7db97 100644 --- a/application/backend/lib/wiki/gitExec.ts +++ b/application/backend/lib/wiki/gitExec.ts @@ -3,7 +3,7 @@ import fs from "fs/promises"; import Fs from "fs/promises"; import childProcess from "child_process"; import util from "util"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; const exec = util.promisify(childProcess.exec); diff --git a/application/backend/lib/wiki/gitmech.ts b/application/backend/lib/wiki/gitmech.ts index 941528ff..88531dad 100644 --- a/application/backend/lib/wiki/gitmech.ts +++ b/application/backend/lib/wiki/gitmech.ts @@ -1,5 +1,5 @@ import gitExec from "./gitExec.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; import filter from "lodash/filter.js"; const workTree = conf.wikipath; diff --git a/application/backend/lib/wiki/wikiService.ts b/application/backend/lib/wiki/wikiService.ts index e5765202..1446a92b 100644 --- a/application/backend/lib/wiki/wikiService.ts +++ b/application/backend/lib/wiki/wikiService.ts @@ -6,7 +6,7 @@ import map from "lodash/map.js"; import { UploadedFile } from "jc-shared/konzert/konzert.js"; import fs from "fs"; import path from "path"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; const wikiUploadDir = conf.wikiUploadDir; diff --git a/application/backend/rest/mail.ts b/application/backend/rest/mail.ts index 22c86223..e6f3eea6 100644 --- a/application/backend/rest/mail.ts +++ b/application/backend/rest/mail.ts @@ -16,6 +16,7 @@ import MailMessage from "jc-shared/mail/mailMessage.js"; import map from "lodash/map.js"; import forEach from "lodash/forEach.js"; import filter from "lodash/filter.js"; +import conf from "../simpleConfigure.js"; const app = express(); @@ -40,6 +41,7 @@ app.post("/rundmail", [checkSuperuser], async (req: Request, res: Response) => { const user = req.user as User; const message = MailMessage.forJsonAndUser(JSON.parse((fields.message ?? [])[0]), user); + message.from = MailMessage.formatEMailAddress(`${user.name} via backoffice.jazzclub.de`, conf.senderAddress); if (files.dateien) { message.attachments = await Promise.all( // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/application/shared/commons/simpleConfigure.ts b/application/backend/simpleConfigure.ts similarity index 98% rename from application/shared/commons/simpleConfigure.ts rename to application/backend/simpleConfigure.ts index c3cf1945..c3a6e151 100644 --- a/application/shared/commons/simpleConfigure.ts +++ b/application/backend/simpleConfigure.ts @@ -1,5 +1,5 @@ import path from "node:path"; -import { MailAddress } from "../mail/mailMessage.js"; +import { MailAddress } from "jc-shared/mail/mailMessage.js"; import assign from "lodash/assign.js"; export class SimpleConfigure { diff --git a/application/backend/start.ts b/application/backend/start.ts index 1cbaef91..6777b408 100644 --- a/application/backend/start.ts +++ b/application/backend/start.ts @@ -5,7 +5,7 @@ import loggers from "./initWinston.js"; import express from "express"; import { createServer } from "http"; import configureApp from "./configureApp.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "./simpleConfigure.js"; const app = express(); configureApp(app); diff --git a/application/backend/test/mailsender/mailRendering.test.ts b/application/backend/test/mailsender/mailRendering.test.ts index 948af12d..6b26caf3 100644 --- a/application/backend/test/mailsender/mailRendering.test.ts +++ b/application/backend/test/mailsender/mailRendering.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; import "jc-backend/configure.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; +import conf from "../../simpleConfigure.js"; import { toTransportObject } from "jc-backend/lib/mailsender/mailtransport.js"; import MailMessage from "jc-shared/mail/mailMessage.js"; import User from "jc-shared/user/user.js"; @@ -41,14 +41,12 @@ Error: "keiner"`); }); it("uses the given sender in Name, but not in Address", () => { - const message = MailMessage.forJsonAndUser( - { subject: "", body: "", bcc: [] }, - new User({ name: "Andreas von Jazzclub", email: "andreas@jazz.club" }), - ); + const user = new User({ name: "Andreas von Jazzclub", email: "andreas@jazz.club" }); + const message = MailMessage.forJsonAndUser({ subject: "", body: "", bcc: [] }, user); const res = toTransportObject(message, false); expect(res.from).to.eql({ address: "sender@jazz.club", - name: "Andreas von Jazzclub via backoffice.jazzclub.de", + name: "Der Sender", }); expect(res.replyTo).to.eql({ address: "andreas@jazz.club", diff --git a/application/shared/commons/DatumUhrzeit.ts b/application/shared/commons/DatumUhrzeit.ts index c635ea0b..94553ec1 100644 --- a/application/shared/commons/DatumUhrzeit.ts +++ b/application/shared/commons/DatumUhrzeit.ts @@ -10,7 +10,6 @@ import weekOfYear from "dayjs/plugin/weekOfYear.js"; import "dayjs/locale/de.js"; import utc from "dayjs/plugin/utc.js"; import timezone from "dayjs/plugin/timezone.js"; -import conf from "./simpleConfigure.js"; dayjs.extend(customParseFormat); dayjs.extend(duration); @@ -37,7 +36,7 @@ export default class DatumUhrzeit { private readonly val: Dayjs; constructor(dateTime?: Dayjs) { - this.val = dateTime && dateTime.isValid() ? dateTime : dayjs(conf.nowForDevelopment); + this.val = dateTime && dateTime.isValid() ? dateTime : dayjs(); } // Konstruktoren diff --git a/application/shared/mail/mailMessage.ts b/application/shared/mail/mailMessage.ts index 3a71aabe..24438bf8 100644 --- a/application/shared/mail/mailMessage.ts +++ b/application/shared/mail/mailMessage.ts @@ -1,5 +1,4 @@ import User from "../user/user.js"; -import conf from "jc-shared/commons/simpleConfigure.js"; import map from "lodash/map.js"; export type MailAddress = { name: string; address: string }; @@ -23,7 +22,6 @@ export default class MailMessage { const message = new MailMessage({ subject }); message.body = body; message.bcc = bcc; - message.from = MailMessage.formatEMailAddress(`${user.name} via backoffice.jazzclub.de`, conf.senderAddress); message.replyTo = MailMessage.formatEMailAddress(user.name, user.email); return message; } diff --git a/application/tsconfig.json b/application/tsconfig.json new file mode 100644 index 00000000..aa0a8c03 --- /dev/null +++ b/application/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "types": ["vitest/globals"] + } +} diff --git a/application/vitest.setup.ts b/application/vitest.setup.ts new file mode 100644 index 00000000..936db5b3 --- /dev/null +++ b/application/vitest.setup.ts @@ -0,0 +1,14 @@ +import { server } from "./vue/test/mockserver/node.js"; + +beforeAll(() => { + console.log("setup server"); + server.listen(); +}); + +afterEach(() => { + server.resetHandlers(); +}); + +afterAll(() => { + server.close(); +}); diff --git a/application/vue/package.json b/application/vue/package.json index f9cf2c86..931edafe 100644 --- a/application/vue/package.json +++ b/application/vue/package.json @@ -21,6 +21,7 @@ "@testing-library/dom": "10.4.0", "@testing-library/jest-dom": "6.6.3", "@testing-library/react": "16.2.0", + "@testing-library/user-event": "14.6.1", "@types/color": "4.2.0", "@types/numeral": "2.0.5", "@types/react": "19.0.10", @@ -37,6 +38,7 @@ "jest-matchmedia-mock": "1.1.0", "jose": "6.0.3", "jsdom": "26.0.0", + "msw": "2.7.3", "numeral": "2.0.6", "react": "19.0.0", "react-bootstrap-icons": "1.11.5", diff --git a/application/vue/src/components/content/InnerContent.tsx b/application/vue/src/components/content/InnerContent.tsx index fe5d2f5e..dd5812da 100644 --- a/application/vue/src/components/content/InnerContent.tsx +++ b/application/vue/src/components/content/InnerContent.tsx @@ -10,7 +10,7 @@ export default function InnerContent() { const ref = useRef(null); useEffect(() => { - ref.current?.scroll({ top: 0 }); + ref.current?.scroll?.({ top: 0 }); }); if (loginState === LoginState.UNKNOWN) { diff --git a/application/vue/src/components/content/menu/Preferences.tsx b/application/vue/src/components/content/menu/Preferences.tsx index 68e2d41a..a75f8072 100644 --- a/application/vue/src/components/content/menu/Preferences.tsx +++ b/application/vue/src/components/content/menu/Preferences.tsx @@ -31,15 +31,15 @@ export default function Preferences({ isOpen, setIsOpen }: { readonly isOpen: bo } return ( - setIsOpen(false)} - onOk={() => setIsOpen(false)} - open={isOpen} - > -
+ + setIsOpen(false)} + onOk={() => setIsOpen(false)} + open={isOpen} + > @@ -88,7 +88,7 @@ export default function Preferences({ isOpen, setIsOpen }: { readonly isOpen: bo }} size="small" /> - -
+
+ ); } diff --git a/application/vue/src/components/konzert/KonzertFormAndPageHeader.tsx b/application/vue/src/components/konzert/KonzertFormAndPageHeader.tsx index 58dd3230..aea7926d 100644 --- a/application/vue/src/components/konzert/KonzertFormAndPageHeader.tsx +++ b/application/vue/src/components/konzert/KonzertFormAndPageHeader.tsx @@ -1,6 +1,6 @@ import * as React from "react"; import { CSSProperties, PropsWithChildren, useContext, useMemo } from "react"; -import { useLocation, useSearchParams } from "react-router"; +import { useSearchParams } from "react-router"; import { HelpWithKasseButton, MoreButton } from "@/components/colored/JazzButtons"; import DatumUhrzeit from "jc-shared/commons/DatumUhrzeit"; import groupBy from "lodash/groupBy"; @@ -29,14 +29,6 @@ export default function KonzertFormAndPageHeader({ const { optionen, currentUser, isDirty } = useJazzContext(); const [search] = useSearchParams(); - const { pathname } = useLocation(); - const isCopy = useMemo(() => { - return pathname.includes("/copy-of-"); - }, [pathname]); - const isNew = useMemo(() => { - return pathname.includes("/new"); - }, [pathname]); - const isKassenseite = useMemo(() => search.get("page") === "kasse", [search]); const startDate = useWatch("startDate", { form, preserve: true }); @@ -46,9 +38,6 @@ export default function KonzertFormAndPageHeader({ const id = useWatch(["id"], { form, preserve: true }); const displayDate = useMemo(() => DatumUhrzeit.forJSDate(startDate).lesbareKurzform, [startDate]); - const title = useMemo(() => { - return `${titel ?? ""}${isNew ? " (Neu)" : ""}${isCopy ? " (Kopie)" : ""}`; - }, [isCopy, isNew, titel]); const titleStyle: CSSProperties = useMemo(() => { const typByName = groupBy(optionen?.typenPlus || [], "name"); @@ -87,7 +76,7 @@ export default function KonzertFormAndPageHeader({ saveForm={saveForm} style={titleStyle} tags={tagsForTitle} - title={title} + title={titel} > {children} diff --git a/application/vue/src/components/konzert/kasse/AusgabenCard.tsx b/application/vue/src/components/konzert/kasse/AusgabenCard.tsx index 0466655a..91064489 100644 --- a/application/vue/src/components/konzert/kasse/AusgabenCard.tsx +++ b/application/vue/src/components/konzert/kasse/AusgabenCard.tsx @@ -13,6 +13,7 @@ import { JazzRow } from "@/widgets/JazzRow.tsx"; import { useWatch } from "antd/es/form/Form"; import KonzertWithRiderBoxes from "jc-shared/konzert/konzertWithRiderBoxes.ts"; import useKassenSaldierer from "@/components/konzert/kasse/useKassenSaldierer.ts"; +import { JazzRowWithRef } from "@/widgets/JazzRowWithRef.tsx"; export default function AusgabenCard() { const form = useFormInstance(); @@ -32,14 +33,14 @@ export default function AusgabenCard() { return ( - + - + diff --git a/application/vue/src/components/konzert/kasse/EinnahmenCard.tsx b/application/vue/src/components/konzert/kasse/EinnahmenCard.tsx index dfc28baf..975874fa 100644 --- a/application/vue/src/components/konzert/kasse/EinnahmenCard.tsx +++ b/application/vue/src/components/konzert/kasse/EinnahmenCard.tsx @@ -12,6 +12,7 @@ import { KassenContext } from "@/components/konzert/kasse/KassenContext.ts"; import { useWatch } from "antd/es/form/Form"; import KonzertWithRiderBoxes from "jc-shared/konzert/konzertWithRiderBoxes.ts"; import useKassenSaldierer from "@/components/konzert/kasse/useKassenSaldierer.ts"; +import { JazzRowWithRef } from "@/widgets/JazzRowWithRef.tsx"; export default function EinnahmenCard() { const form = useFormInstance(); @@ -36,7 +37,7 @@ export default function EinnahmenCard() { return ( - + @@ -45,7 +46,7 @@ export default function EinnahmenCard() { - + diff --git a/application/vue/src/components/team/ExcelMultiExportButton.tsx b/application/vue/src/components/team/ExcelMultiExportButton.tsx index 86ab3480..325affa0 100644 --- a/application/vue/src/components/team/ExcelMultiExportButton.tsx +++ b/application/vue/src/components/team/ExcelMultiExportButton.tsx @@ -84,8 +84,8 @@ function SelectRangeForExcelModal({ }, [bestaetigteFiltered, exportType, optionen, setIsOpen]); return ( - setIsOpen(false)} onOk={okClicked} open={isOpen}> -
+ + setIsOpen(false)} onOk={okClicked} open={isOpen}> @@ -97,8 +97,8 @@ function SelectRangeForExcelModal({ - -
+
+ ); } diff --git a/application/vue/src/components/team/TeamBlock/AdminContent.tsx b/application/vue/src/components/team/TeamBlock/AdminContent.tsx index 9b631fe9..89e1372f 100644 --- a/application/vue/src/components/team/TeamBlock/AdminContent.tsx +++ b/application/vue/src/components/team/TeamBlock/AdminContent.tsx @@ -132,62 +132,62 @@ export default function AdminContent({ veranstaltung: veranVermiet }: { readonly return (
- - - { - setShowMitarbeiter(!showMitarbeiter); - }} - style={{ marginLeft: 8, marginBlockStart: 4, marginBlockEnd: 0 }} - > - - -  ... - - - - - {inView ? ( - - ) : null} - - - {inView ? ( - - { - setDirty(areDifferent(initialValue, form.getFieldsValue(true))); - }} - size="small" - > +
{ + setDirty(areDifferent(initialValue, form.getFieldsValue(true))); + }} + size="small" + > + + + { + setShowMitarbeiter(!showMitarbeiter); + }} + style={{ marginLeft: 8, marginBlockStart: 4, marginBlockEnd: 0 }} + > + + +  ... + + + + + {inView ? ( + + ) : null} + + + {inView ? ( + +
- - ), - }, - ]} - /> - - ) : null} + ), + }, + ]} + /> + + ) : null} + ); } diff --git a/application/vue/src/components/team/TeamFilter/TeamFilter.tsx b/application/vue/src/components/team/TeamFilter/TeamFilter.tsx index 3f3a7e71..86f9cc27 100644 --- a/application/vue/src/components/team/TeamFilter/TeamFilter.tsx +++ b/application/vue/src/components/team/TeamFilter/TeamFilter.tsx @@ -4,7 +4,6 @@ import ButtonWithIcon from "@/widgets/buttonsAndIcons/ButtonWithIcon.tsx"; import { TeamFilterObject } from "./applyTeamFilter.ts"; import { useJazzContext } from "@/components/content/useJazzContext.ts"; import isNil from "lodash/isNil"; -import isEmpty from "lodash/isEmpty"; import { NamePath } from "rc-field-form/es/interface"; import { TeamFilterEdit } from "@/components/team/TeamFilter/TeamFilterEdit.tsx"; import { reset } from "@/components/team/TeamFilter/resetTeamFilter.ts"; @@ -111,7 +110,7 @@ export default function TeamFilter() { return tags.concat(eventTypTags).concat(bookerTags); }, [createBookerTag, eventTypTag, teamFilter]); - const result = [ + return ( setOpen(true)} size="small" text="Filter..." type="default" />
-
, - ]; - if (!isEmpty(taggies)) { - result.push( - { - reset(form); - setTeamFilter(form.getFieldsValue(true)); - }} - size="small" - text="Zurücksetzen" - type="default" - />, - ); - } - result.push(...headerTagsForFilters(taggies)); - return result; + {taggies.length ? ( + { + reset(form); + setTeamFilter(form.getFieldsValue(true)); + }} + size="small" + text="Zurücksetzen" + type="default" + /> + ) : null} + {headerTagsForFilters(taggies)} + + ); } diff --git a/application/vue/src/components/users/UserModals.tsx b/application/vue/src/components/users/UserModals.tsx index bdddc582..3c90bd41 100644 --- a/application/vue/src/components/users/UserModals.tsx +++ b/application/vue/src/components/users/UserModals.tsx @@ -46,15 +46,15 @@ export function ChangePasswordModal({ } return ( - setIsOpen(false)} - onOk={saveForm} - open={isOpen} - title="Passwort ändern" - > -
+ + setIsOpen(false)} + onOk={saveForm} + open={isOpen} + title="Passwort ändern" + > - -
+
+ ); } export function NewUserModal({ isOpen, setIsOpen }: { readonly isOpen: boolean; readonly setIsOpen: (open: boolean) => void }) { @@ -166,28 +166,28 @@ export function EditUserModal({ } return ( - setIsOpen(false)} - onOk={saveForm} - open={isOpen} - title={user.id} +
{ + const current = form.getFieldsValue(true); + logDiffForDirty(initialValue, current, false); + setDirty(areDifferent(initialValue, current)); + }} > - { - const current = form.getFieldsValue(true); - logDiffForDirty(initialValue, current, false); - setDirty(areDifferent(initialValue, current)); - }} + setIsOpen(false)} + onOk={saveForm} + open={isOpen} + title={user.id} > - -
+
+ ); } diff --git a/application/vue/src/components/vermietung/VermietungFormAndPageHeader.tsx b/application/vue/src/components/vermietung/VermietungFormAndPageHeader.tsx index 01eac633..0639f33b 100644 --- a/application/vue/src/components/vermietung/VermietungFormAndPageHeader.tsx +++ b/application/vue/src/components/vermietung/VermietungFormAndPageHeader.tsx @@ -8,7 +8,6 @@ import { useForm, useWatch } from "antd/es/form/Form"; import { useJazzContext } from "@/components/content/useJazzContext.ts"; import JazzFormAndHeaderExtended from "@/components/content/JazzFormAndHeaderExtended.tsx"; import dynamicHeaderTags from "../colored/dynamicHeaderTags.tsx"; -import { useLocation } from "react-router"; export default function VermietungFormAndPageHeader({ data, @@ -23,21 +22,11 @@ export default function VermietungFormAndPageHeader({ document.title = "Vermietung"; const [form] = useForm(); const { isDirty } = useJazzContext(); - const { pathname } = useLocation(); - const isCopy = useMemo(() => { - return pathname.includes("/copy-of-"); - }, [pathname]); - const isNew = useMemo(() => { - return pathname.includes("/new"); - }, [pathname]); const id = useWatch("id", { form, preserve: true }); const startDate = useWatch("startDate", { form, preserve: true }); const titel = useWatch(["kopf", "titel"], { form, preserve: true }); const displayDate = useMemo(() => DatumUhrzeit.forJSDate(startDate).lesbareKurzform, [startDate]); - const title = useMemo(() => { - return `${titel ?? ""}${isNew ? " (Neu)" : ""}${isCopy ? " (Kopie)" : ""}`; - }, [isCopy, isNew, titel]); const tagsForTitle = useMemo( () => @@ -68,7 +57,7 @@ export default function VermietungFormAndPageHeader({ resetChanges={resetChanges} saveForm={saveForm} tags={tagsForTitle} - title={title} + title={titel} > {children} diff --git a/application/vue/src/widgets/JazzPageHeader.css b/application/vue/src/widgets/JazzPageHeader.css new file mode 100644 index 00000000..1b213e11 --- /dev/null +++ b/application/vue/src/widgets/JazzPageHeader.css @@ -0,0 +1,6 @@ +.ant-page-header { + color: var(--ant-color-text); +} +.ant-page-header .ant-page-header-heading-title { + color: var(--ant-color-text); +} diff --git a/application/vue/src/widgets/JazzPageHeader.tsx b/application/vue/src/widgets/JazzPageHeader.tsx index 7b621af9..6218ad43 100644 --- a/application/vue/src/widgets/JazzPageHeader.tsx +++ b/application/vue/src/widgets/JazzPageHeader.tsx @@ -1,8 +1,10 @@ import * as React from "react"; import { PropsWithChildren, ReactNode, useContext, useMemo } from "react"; import { PageHeader } from "@ant-design/pro-layout"; -import { Breadcrumb, type BreadcrumbProps, ConfigProvider, theme } from "antd"; +import { Breadcrumb, type BreadcrumbProps, ConfigProvider, theme, Typography } from "antd"; import { GlobalContext } from "../app/GlobalContext.ts"; +import { useLocation } from "react-router"; +import "./JazzPageHeader.css"; export function JazzPageHeader({ title, @@ -19,17 +21,29 @@ export function JazzPageHeader({ readonly buttons?: ReactNode[]; readonly firstTag?: ReactNode; readonly dateString?: string; - readonly tags?: ReactNode[]; + readonly tags?: ReactNode | ReactNode[]; readonly breadcrumb?: Partial | React.ReactElement; readonly hasErrors?: boolean; readonly style?: React.CSSProperties; } & PropsWithChildren) { const { isDarkMode } = useContext(GlobalContext); - const { token } = theme.useToken(); + const { pathname } = useLocation(); + const isCopy = useMemo(() => { + return pathname.includes("/copy-of-"); + }, [pathname]); + const isNew = useMemo(() => { + return pathname.includes("/new"); + }, [pathname]); - const theHeader = useMemo(() => { - return hasErrors ? Du hast noch Fehler! : {title}; - }, [hasErrors, style, title, token.colorError]); + const subTitle = useMemo( + () => ( + + {`${isNew ? " (Neu)" : ""}${isCopy ? " (Kopie)" : ""}`} + {hasErrors ? Du hast noch Fehler! : null} + + ), + [hasErrors, isCopy, isNew], + ); return ( @@ -46,7 +60,8 @@ export function JazzPageHeader({ tags, ]} style={{ ...style, paddingInline: 4 }} - title={theHeader} + subTitle={subTitle} + title={{title}} > {children} diff --git a/application/vue/src/widgets/JazzRow.tsx b/application/vue/src/widgets/JazzRow.tsx index 7c446254..3616b346 100644 --- a/application/vue/src/widgets/JazzRow.tsx +++ b/application/vue/src/widgets/JazzRow.tsx @@ -1,10 +1,6 @@ -import { forwardRef, PropsWithChildren, Ref } from "react"; +import { PropsWithChildren } from "react"; import { Row } from "antd"; -export const JazzRow = forwardRef(function JazzRowInRef({ children }: PropsWithChildren, ref: Ref | undefined) { - return ( - - {children} - - ); -}); +export function JazzRow({ children }: PropsWithChildren) { + return {children}; +} diff --git a/application/vue/src/widgets/JazzRowWithRef.tsx b/application/vue/src/widgets/JazzRowWithRef.tsx new file mode 100644 index 00000000..ab91c9b5 --- /dev/null +++ b/application/vue/src/widgets/JazzRowWithRef.tsx @@ -0,0 +1,10 @@ +import { forwardRef, PropsWithChildren, Ref } from "react"; +import { Row } from "antd"; + +export const JazzRowWithRef = forwardRef(function JazzRowInRef({ children }: PropsWithChildren, ref: Ref | undefined) { + return ( + + {children} + + ); +}); diff --git a/application/vue/src/widgets/calendar/WrapFullCalendar.tsx b/application/vue/src/widgets/calendar/WrapFullCalendar.tsx index dc745c91..d9915ef6 100644 --- a/application/vue/src/widgets/calendar/WrapFullCalendar.tsx +++ b/application/vue/src/widgets/calendar/WrapFullCalendar.tsx @@ -1,8 +1,6 @@ import "./calendar.css"; import { PropsWithChildren } from "react"; -import { useJazzContext } from "@/components/content/useJazzContext.ts"; export default function WrapFullCalendar({ children }: PropsWithChildren) { - const { isDarkMode } = useJazzContext(); - return
{children}
; + return children; } diff --git a/application/vue/src/widgets/calendar/calendar.css b/application/vue/src/widgets/calendar/calendar.css index 3fd6e675..8ba75285 100644 --- a/application/vue/src/widgets/calendar/calendar.css +++ b/application/vue/src/widgets/calendar/calendar.css @@ -1,64 +1,32 @@ -:root { - --fc-small-font-size: 0.85em; - --fc-neutral-bg-color: rgba(208, 208, 208, 0.3); - --fc-neutral-text-color: #808080; - --fc-border-color: #ddd; +.fc { + --fc-small-font-size: var(--ant-font-size-sm); + --fc-neutral-bg-color: var(--ant-color-fill-content); + --fc-border-color: var(--ant-color-bg-text-active); - --fc-event-bg-color: #6884a3; - --fc-event-border-color: #507088; - --fc-event-selected-overlay-color: rgba(0, 0, 0, 0.25); + --fc-event-bg-color: var(--ant-color-primary); + --fc-event-border-color: var(--ant-color-bg-text-active); - --fc-more-link-bg-color: #d0d0d0; - --fc-more-link-text-color: inherit; + --fc-more-link-bg-color: var(--ant-color-fill-content); + --fc-more-link-text-color: var(--ant-color-text-base); - --fc-event-resizer-thickness: 8px; - --fc-event-resizer-dot-total-width: 8px; - --fc-event-resizer-dot-border-width: 1px; + --fc-today-bg-color: var(--ant-color-warning-border); + --fc-page-bg-color: var(--ant-color-bg-base); - --fc-non-business-color: rgba(215, 215, 215, 0.3); - --fc-bg-event-color: rgb(143, 223, 130); - --fc-bg-event-opacity: 0.3; - --fc-highlight-color: rgba(188, 232, 241, 0.3); - --fc-today-bg-color: rgba(255, 220, 40, 0.15); - --fc-now-indicator-color: red; -} - -.fc-daygrid-event { - white-space: normal; -} - -.dark-calendar { - --fc-page-bg-color: rgb(61, 61, 61); - - --fc-button-text-color: #dcdcdc; - --fc-button-bg-color: rgb(36, 36, 36); - --fc-button-border-color: rgb(82, 82, 82); - --fc-button-hover-bg-color: rgb(82, 82, 82); - --fc-button-hover-border-color: rgb(82, 82, 82); - --fc-button-active-bg-color: rgb(82, 82, 82); - --fc-button-active-border-color: rgb(82, 82, 82); + --fc-button-text-color: var(--ant-color-text-base); + --fc-button-bg-color: var(--ant-color-bg-base); + --fc-button-hover-bg-color: var(--ant-color-border-bg); + --fc-button-border-color: var(--ant-color-icon); + --fc-button-hover-border-color: var(--ant-color-icon-hover); + --fc-button-active-bg-color: var(--ant-color-text-quaternary); + --fc-button-active-border-color: var(--ant-color-icon); - --fc-event-text-color: #dcdcdc; + --fc-event-text-color: #fafafa; a { - color: #dcdcdc; + color: var(--ant-color-text-base); } } -.bright-calendar { - --fc-page-bg-color: #fff; - - --fc-button-text-color: #212529; - --fc-button-bg-color: #fefefe; - --fc-button-border-color: #aaa8a8; - --fc-button-hover-bg-color: #f8f9fa; - --fc-button-hover-border-color: #aaa8a8; - --fc-button-active-bg-color: #dfdede; - --fc-button-active-border-color: #636161; - - --fc-event-text-color: #fff; - - a { - color: #2c4862; - } +.fc-daygrid-event { + white-space: normal; } diff --git a/application/vue/test/PlayAround.test.tsx b/application/vue/test/PlayAround.test.tsx new file mode 100644 index 00000000..d991f48b --- /dev/null +++ b/application/vue/test/PlayAround.test.tsx @@ -0,0 +1,44 @@ +import { render, waitFor } from "@testing-library/react"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, it } from "vitest"; +import { JazzRouter } from "@/router/JazzRouter.tsx"; +import React from "react"; +import JazzclubApp from "@/app/JazzclubApp.tsx"; +import { server } from "./mockserver/node.js"; +import noop from "lodash/noop"; + +describe("Playing Around", () => { + beforeAll(() => { + server.listen(); + }); + beforeEach(() => { + window.scroll = noop; + }); + + afterEach(() => { + server.resetHandlers(); + }); + + afterAll(() => { + server.close(); + }); + + it("should first", async () => { + //const user = userEvent.setup(); + window.history.pushState({}, "Test page", "/vue"); + + const { getByText } = render(, { wrapper: JazzRouter }); + await waitFor(() => { + getByText("Veranstaltungen"); + }); + }); + + it("should second", async () => { + //const user = userEvent.setup(); + window.history.pushState({}, "Test page", "/vue/konzert/new"); + + const { getByText } = render(, { wrapper: JazzRouter }); + await waitFor(() => { + getByText("(Neu)"); + }); + }); +}); diff --git a/application/vue/test/mockserver/handlers.ts b/application/vue/test/mockserver/handlers.ts new file mode 100644 index 00000000..0d04396e --- /dev/null +++ b/application/vue/test/mockserver/handlers.ts @@ -0,0 +1,15 @@ +import { http, HttpResponse } from "msw"; + +export const handlers = [ + http.get("/rest/users/current", () => { + return HttpResponse.json({ + id: "testuser", + name: "Test User", + }); + }), + http.post("/refreshToken", () => { + return HttpResponse.json({ + token: "testuser", + }); + }), +]; diff --git a/application/vue/test/mockserver/node.ts b/application/vue/test/mockserver/node.ts new file mode 100644 index 00000000..172ca7f8 --- /dev/null +++ b/application/vue/test/mockserver/node.ts @@ -0,0 +1,4 @@ +import { setupServer } from "msw/node"; +import { handlers } from "./handlers.js"; + +export const server = setupServer(...handlers); diff --git a/application/vue/test/util/testHelpers.tsx b/application/vue/test/util/testHelpers.tsx index 84968c45..4f54a1d8 100644 --- a/application/vue/test/util/testHelpers.tsx +++ b/application/vue/test/util/testHelpers.tsx @@ -16,7 +16,7 @@ type FormWithProps = { numeral.locale("de"); numeral.localeData("de").delimiters.thousands = "."; -export function FormWith({ tunnel, children }: FormWithProps) { +function FormWith({ tunnel, children }: FormWithProps) { const [form] = Form.useForm(); tunnel.form = form; return
{children}
; diff --git a/application/yarn.lock b/application/yarn.lock index 74878dbf..f3eff6cc 100644 --- a/application/yarn.lock +++ b/application/yarn.lock @@ -1573,6 +1573,34 @@ __metadata: languageName: node linkType: hard +"@bundled-es-modules/cookie@npm:^2.0.1": + version: 2.0.1 + resolution: "@bundled-es-modules/cookie@npm:2.0.1" + dependencies: + cookie: "npm:^0.7.2" + checksum: 10c0/dfac5e36127e827c5557b8577f17a8aa94c057baff6d38555917927b99da0ecf0b1357e7fedadc8853ecdbd4a8a7fa1f5e64111b2a656612f4a36376f5bdbe8d + languageName: node + linkType: hard + +"@bundled-es-modules/statuses@npm:^1.0.1": + version: 1.0.1 + resolution: "@bundled-es-modules/statuses@npm:1.0.1" + dependencies: + statuses: "npm:^2.0.1" + checksum: 10c0/c1a8ede3efa8da61ccda4b98e773582a9733edfbeeee569d4630785f8e018766202edb190a754a3ec7a7f6bd738e857829affc2fdb676b6dab4db1bb44e62785 + languageName: node + linkType: hard + +"@bundled-es-modules/tough-cookie@npm:^0.1.6": + version: 0.1.6 + resolution: "@bundled-es-modules/tough-cookie@npm:0.1.6" + dependencies: + "@types/tough-cookie": "npm:^4.0.5" + tough-cookie: "npm:^4.1.4" + checksum: 10c0/28bcac878bff6b34719ba3aa8341e9924772ee55de5487680ebe784981ec9fccb70ed5d46f563e2404855a04de606f9e56aa4202842d4f5835bc04a4fe820571 + languageName: node + linkType: hard + "@codemirror/autocomplete@npm:^6.0.0, @codemirror/autocomplete@npm:^6.3.2, @codemirror/autocomplete@npm:^6.4.0, @codemirror/autocomplete@npm:^6.7.1": version: 6.18.6 resolution: "@codemirror/autocomplete@npm:6.18.6" @@ -2698,6 +2726,61 @@ __metadata: languageName: node linkType: hard +"@inquirer/confirm@npm:^5.0.0": + version: 5.1.8 + resolution: "@inquirer/confirm@npm:5.1.8" + dependencies: + "@inquirer/core": "npm:^10.1.9" + "@inquirer/type": "npm:^3.0.5" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/e4d3e3ef2c46db3235ead8c149fda442fb7e8ef5049d070803a3d9fbc7bd07a4c67175c66283b545a96944737c4567b4203502482ab3497a0575e35a42f5dcfd + languageName: node + linkType: hard + +"@inquirer/core@npm:^10.1.9": + version: 10.1.9 + resolution: "@inquirer/core@npm:10.1.9" + dependencies: + "@inquirer/figures": "npm:^1.0.11" + "@inquirer/type": "npm:^3.0.5" + ansi-escapes: "npm:^4.3.2" + cli-width: "npm:^4.1.0" + mute-stream: "npm:^2.0.0" + signal-exit: "npm:^4.1.0" + wrap-ansi: "npm:^6.2.0" + yoctocolors-cjs: "npm:^2.1.2" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/36eae788713a9ad67172a86cda9b782481df5663c760dddb0b620292b78374720e6f86b662038e32bcee6fd0ffb4c0ae0c48e84ceb27c7641984a5deff1ade1f + languageName: node + linkType: hard + +"@inquirer/figures@npm:^1.0.11": + version: 1.0.11 + resolution: "@inquirer/figures@npm:1.0.11" + checksum: 10c0/6270e24eebbe42bbc4e7f8e761e906be66b4896787f31ab3e7484ad271c8edc90bce4ec20e232a5da447aee4fc73803397b2dda8cf645f4f7eea83e773b44e1e + languageName: node + linkType: hard + +"@inquirer/type@npm:^3.0.5": + version: 3.0.5 + resolution: "@inquirer/type@npm:3.0.5" + peerDependencies: + "@types/node": ">=18" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 10c0/d6aec3e69bbd5b79ec7e5f4b7b7d2afadd6d6c0566f5fb2b3964a7d72bae89e1736f8d092df15bfdc5cb520678db02f2bde469931c7139e8402ea7ad4d3bdd80 + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -3299,6 +3382,20 @@ __metadata: languageName: node linkType: hard +"@mswjs/interceptors@npm:^0.37.0": + version: 0.37.6 + resolution: "@mswjs/interceptors@npm:0.37.6" + dependencies: + "@open-draft/deferred-promise": "npm:^2.2.0" + "@open-draft/logger": "npm:^0.3.0" + "@open-draft/until": "npm:^2.0.0" + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.4.3" + strict-event-emitter: "npm:^0.5.1" + checksum: 10c0/74f52c09c84fcbba9f1a06e462aa25b1567cf078ed27d396c76a8059c002fa9c361e711dcada0ac2aad4298f247d8e236a4fcc861c08ddf6e2ce0889368596fd + languageName: node + linkType: hard + "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1": version: 5.1.1-v1 resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1" @@ -3357,13 +3454,30 @@ __metadata: languageName: node linkType: hard -"@open-draft/deferred-promise@npm:^2.1.0": +"@open-draft/deferred-promise@npm:^2.1.0, @open-draft/deferred-promise@npm:^2.2.0": version: 2.2.0 resolution: "@open-draft/deferred-promise@npm:2.2.0" checksum: 10c0/eafc1b1d0fc8edb5e1c753c5e0f3293410b40dde2f92688211a54806d4136887051f39b98c1950370be258483deac9dfd17cf8b96557553765198ef2547e4549 languageName: node linkType: hard +"@open-draft/logger@npm:^0.3.0": + version: 0.3.0 + resolution: "@open-draft/logger@npm:0.3.0" + dependencies: + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.4.0" + checksum: 10c0/90010647b22e9693c16258f4f9adb034824d1771d3baa313057b9a37797f571181005bc50415a934eaf7c891d90ff71dcd7a9d5048b0b6bb438f31bef2c7c5c1 + languageName: node + linkType: hard + +"@open-draft/until@npm:^2.0.0, @open-draft/until@npm:^2.1.0": + version: 2.1.0 + resolution: "@open-draft/until@npm:2.1.0" + checksum: 10c0/61d3f99718dd86bb393fee2d7a785f961dcaf12f2055f0c693b27f4d0cd5f7a03d498a6d9289773b117590d794a43cd129366fd8e99222e4832f67b1653d54cf + languageName: node + linkType: hard + "@parcel/watcher-android-arm64@npm:2.5.1": version: 2.5.1 resolution: "@parcel/watcher-android-arm64@npm:2.5.1" @@ -4702,6 +4816,15 @@ __metadata: languageName: node linkType: hard +"@testing-library/user-event@npm:14.6.1": + version: 14.6.1 + resolution: "@testing-library/user-event@npm:14.6.1" + peerDependencies: + "@testing-library/dom": ">=7.21.4" + checksum: 10c0/75fea130a52bf320d35d46ed54f3eec77e71a56911b8b69a3fe29497b0b9947b2dc80d30f04054ad4ce7f577856ae3e5397ea7dff0ef14944d3909784c7a93fe + languageName: node + linkType: hard + "@tootallnate/quickjs-emscripten@npm:^0.23.0": version: 0.23.0 resolution: "@tootallnate/quickjs-emscripten@npm:0.23.0" @@ -5250,6 +5373,13 @@ __metadata: languageName: node linkType: hard +"@types/statuses@npm:^2.0.4": + version: 2.0.5 + resolution: "@types/statuses@npm:2.0.5" + checksum: 10c0/4dacec0b29483a44be902a022a11a22b339de7a6e7b2059daa4f7add10cb6dbcc28d02d2a416fe9687e48d335906bf983065391836d4e7c847e55ddef4de8fad + languageName: node + linkType: hard + "@types/superagent@npm:8.1.9": version: 8.1.9 resolution: "@types/superagent@npm:8.1.9" @@ -5278,6 +5408,13 @@ __metadata: languageName: node linkType: hard +"@types/tough-cookie@npm:^4.0.5": + version: 4.0.5 + resolution: "@types/tough-cookie@npm:4.0.5" + checksum: 10c0/68c6921721a3dcb40451543db2174a145ef915bc8bcbe7ad4e59194a0238e776e782b896c7a59f4b93ac6acefca9161fccb31d1ce3b3445cb6faa467297fb473 + languageName: node + linkType: hard + "@types/triple-beam@npm:^1.3.2": version: 1.3.5 resolution: "@types/triple-beam@npm:1.3.5" @@ -5664,6 +5801,15 @@ __metadata: languageName: node linkType: hard +"ansi-escapes@npm:^4.3.2": + version: 4.3.2 + resolution: "ansi-escapes@npm:4.3.2" + dependencies: + type-fest: "npm:^0.21.3" + checksum: 10c0/da917be01871525a3dfcf925ae2977bc59e8c513d4423368645634bf5d4ceba5401574eb705c1e92b79f7292af5a656f78c5725a4b0e1cec97c4b413705c1d50 + languageName: node + linkType: hard + "ansi-regex@npm:^5.0.1": version: 5.0.1 resolution: "ansi-regex@npm:5.0.1" @@ -6504,6 +6650,13 @@ __metadata: languageName: node linkType: hard +"cli-width@npm:^4.1.0": + version: 4.1.0 + resolution: "cli-width@npm:4.1.0" + checksum: 10c0/1fbd56413578f6117abcaf858903ba1f4ad78370a4032f916745fa2c7e390183a9d9029cf837df320b0fdce8137668e522f60a30a5f3d6529ff3872d265a955f + languageName: node + linkType: hard + "cliui@npm:^8.0.1": version: 8.0.1 resolution: "cliui@npm:8.0.1" @@ -6789,7 +6942,7 @@ __metadata: languageName: node linkType: hard -"cookie@npm:0.7.2": +"cookie@npm:0.7.2, cookie@npm:^0.7.2": version: 0.7.2 resolution: "cookie@npm:0.7.2" checksum: 10c0/9596e8ccdbf1a3a88ae02cf5ee80c1c50959423e1022e4e60b91dd87c622af1da309253d8abdb258fb5e3eacb4f08e579dc58b4897b8087574eee0fd35dfa5d2 @@ -8724,6 +8877,13 @@ __metadata: languageName: node linkType: hard +"graphql@npm:^16.8.1": + version: 16.10.0 + resolution: "graphql@npm:16.10.0" + checksum: 10c0/303730675538c8bd6c76b447dc6f03e61242e2d2596b408c34759666ec4877409e5593a7a0467d590ac5407b8c663b093b599556a77f24f281abea69ddc53de6 + languageName: node + linkType: hard + "has-bigints@npm:^1.0.2": version: 1.1.0 resolution: "has-bigints@npm:1.1.0" @@ -8781,6 +8941,13 @@ __metadata: languageName: node linkType: hard +"headers-polyfill@npm:^4.0.2": + version: 4.0.3 + resolution: "headers-polyfill@npm:4.0.3" + checksum: 10c0/53e85b2c6385f8d411945fb890c5369f1469ce8aa32a6e8d28196df38568148de640c81cf88cbc7c67767103dd9acba48f4f891982da63178fc6e34560022afe + languageName: node + linkType: hard + "hexoid@npm:^2.0.0": version: 2.0.0 resolution: "hexoid@npm:2.0.0" @@ -9196,6 +9363,13 @@ __metadata: languageName: node linkType: hard +"is-node-process@npm:^1.2.0": + version: 1.2.0 + resolution: "is-node-process@npm:1.2.0" + checksum: 10c0/5b24fda6776d00e42431d7bcd86bce81cb0b6cabeb944142fe7b077a54ada2e155066ad06dbe790abdb397884bdc3151e04a9707b8cd185099efbc79780573ed + languageName: node + linkType: hard + "is-number-object@npm:^1.1.1": version: 1.1.1 resolution: "is-number-object@npm:1.1.1" @@ -9515,6 +9689,7 @@ __metadata: "@testing-library/dom": "npm:10.4.0" "@testing-library/jest-dom": "npm:6.6.3" "@testing-library/react": "npm:16.2.0" + "@testing-library/user-event": "npm:14.6.1" "@types/color": "npm:4.2.0" "@types/numeral": "npm:2.0.5" "@types/react": "npm:19.0.10" @@ -9531,6 +9706,7 @@ __metadata: jest-matchmedia-mock: "npm:1.1.0" jose: "npm:6.0.3" jsdom: "npm:26.0.0" + msw: "npm:2.7.3" numeral: "npm:2.0.6" react: "npm:19.0.0" react-bootstrap-icons: "npm:1.11.5" @@ -10968,6 +11144,39 @@ __metadata: languageName: node linkType: hard +"msw@npm:2.7.3": + version: 2.7.3 + resolution: "msw@npm:2.7.3" + dependencies: + "@bundled-es-modules/cookie": "npm:^2.0.1" + "@bundled-es-modules/statuses": "npm:^1.0.1" + "@bundled-es-modules/tough-cookie": "npm:^0.1.6" + "@inquirer/confirm": "npm:^5.0.0" + "@mswjs/interceptors": "npm:^0.37.0" + "@open-draft/deferred-promise": "npm:^2.2.0" + "@open-draft/until": "npm:^2.1.0" + "@types/cookie": "npm:^0.6.0" + "@types/statuses": "npm:^2.0.4" + graphql: "npm:^16.8.1" + headers-polyfill: "npm:^4.0.2" + is-node-process: "npm:^1.2.0" + outvariant: "npm:^1.4.3" + path-to-regexp: "npm:^6.3.0" + picocolors: "npm:^1.1.1" + strict-event-emitter: "npm:^0.5.1" + type-fest: "npm:^4.26.1" + yargs: "npm:^17.7.2" + peerDependencies: + typescript: ">= 4.8.x" + peerDependenciesMeta: + typescript: + optional: true + bin: + msw: cli/index.js + checksum: 10c0/47cad1c4b4615b312477c8977fddfda3e90becd8efc2d81d73be8fb860e45ad0d3f7bca6d4f70ae7ed21894e93975bda66d609aafc3a1c99cb923c5ef67f8686 + languageName: node + linkType: hard + "multiparty@npm:4.2.3": version: 4.2.3 resolution: "multiparty@npm:4.2.3" @@ -10979,6 +11188,13 @@ __metadata: languageName: node linkType: hard +"mute-stream@npm:^2.0.0": + version: 2.0.0 + resolution: "mute-stream@npm:2.0.0" + checksum: 10c0/2cf48a2087175c60c8dcdbc619908b49c07f7adcfc37d29236b0c5c612d6204f789104c98cc44d38acab7b3c96f4a3ec2cfdc4934d0738d876dbefa2a12c69f4 + languageName: node + linkType: hard + "nanoid@npm:^3.3.8": version: 3.3.8 resolution: "nanoid@npm:3.3.8" @@ -11271,7 +11487,7 @@ __metadata: languageName: node linkType: hard -"outvariant@npm:^1.3.0, outvariant@npm:^1.4.0": +"outvariant@npm:^1.3.0, outvariant@npm:^1.4.0, outvariant@npm:^1.4.3": version: 1.4.3 resolution: "outvariant@npm:1.4.3" checksum: 10c0/5976ca7740349cb8c71bd3382e2a762b1aeca6f33dc984d9d896acdf3c61f78c3afcf1bfe9cc633a7b3c4b295ec94d292048f83ea2b2594fae4496656eba992c @@ -11495,6 +11711,13 @@ __metadata: languageName: node linkType: hard +"path-to-regexp@npm:^6.3.0": + version: 6.3.0 + resolution: "path-to-regexp@npm:6.3.0" + checksum: 10c0/73b67f4638b41cde56254e6354e46ae3a2ebc08279583f6af3d96fe4664fc75788f74ed0d18ca44fa4a98491b69434f9eee73b97bb5314bd1b5adb700f5c18d6 + languageName: node + linkType: hard + "pathe@npm:^2.0.3": version: 2.0.3 resolution: "pathe@npm:2.0.3" @@ -11739,6 +11962,15 @@ __metadata: languageName: node linkType: hard +"psl@npm:^1.1.33": + version: 1.15.0 + resolution: "psl@npm:1.15.0" + dependencies: + punycode: "npm:^2.3.1" + checksum: 10c0/d8d45a99e4ca62ca12ac3c373e63d80d2368d38892daa40cfddaa1eb908be98cd549ac059783ef3a56cfd96d57ae8e2fd9ae53d1378d90d42bc661ff924e102a + languageName: node + linkType: hard + "pug-attrs@npm:^3.0.0": version: 3.0.0 resolution: "pug-attrs@npm:3.0.0" @@ -11876,7 +12108,7 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^2.1.0, punycode@npm:^2.3.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: 10c0/14f76a8206bc3464f794fb2e3d3cc665ae416c01893ad7a02b23766eb07159144ee612ad67af5e84fa4479ccfe67678c4feb126b0485651b302babf66f04f9e9 @@ -11931,6 +12163,13 @@ __metadata: languageName: node linkType: hard +"querystringify@npm:^2.1.1": + version: 2.2.0 + resolution: "querystringify@npm:2.2.0" + checksum: 10c0/3258bc3dbdf322ff2663619afe5947c7926a6ef5fb78ad7d384602974c467fadfc8272af44f5eb8cddd0d011aae8fabf3a929a8eee4b86edcc0a21e6bd10f9aa + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -12881,6 +13120,13 @@ __metadata: languageName: node linkType: hard +"requires-port@npm:^1.0.0": + version: 1.0.0 + resolution: "requires-port@npm:1.0.0" + checksum: 10c0/b2bfdd09db16c082c4326e573a82c0771daaf7b53b9ce8ad60ea46aa6e30aaf475fe9b164800b89f93b748d2c234d8abff945d2551ba47bf5698e04cd7713267 + languageName: node + linkType: hard + "resize-observer-polyfill@npm:^1.5.1": version: 1.5.1 resolution: "resize-observer-polyfill@npm:1.5.1" @@ -13514,7 +13760,7 @@ __metadata: languageName: node linkType: hard -"signal-exit@npm:^4.0.1": +"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0": version: 4.1.0 resolution: "signal-exit@npm:4.1.0" checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 @@ -13721,6 +13967,13 @@ __metadata: languageName: node linkType: hard +"strict-event-emitter@npm:^0.5.1": + version: 0.5.1 + resolution: "strict-event-emitter@npm:0.5.1" + checksum: 10c0/f5228a6e6b6393c57f52f62e673cfe3be3294b35d6f7842fc24b172ae0a6e6c209fa83241d0e433fc267c503bc2f4ffdbe41a9990ff8ffd5ac425ec0489417f7 + languageName: node + linkType: hard + "string-convert@npm:^0.2.0": version: 0.2.1 resolution: "string-convert@npm:0.2.1" @@ -14219,6 +14472,18 @@ __metadata: languageName: node linkType: hard +"tough-cookie@npm:^4.1.4": + version: 4.1.4 + resolution: "tough-cookie@npm:4.1.4" + dependencies: + psl: "npm:^1.1.33" + punycode: "npm:^2.1.1" + universalify: "npm:^0.2.0" + url-parse: "npm:^1.5.3" + checksum: 10c0/aca7ff96054f367d53d1e813e62ceb7dd2eda25d7752058a74d64b7266fd07be75908f3753a32ccf866a2f997604b414cfb1916d6e7f69bc64d9d9939b0d6c45 + languageName: node + linkType: hard + "tough-cookie@npm:^5.0.0": version: 5.1.1 resolution: "tough-cookie@npm:5.1.1" @@ -14315,6 +14580,20 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^0.21.3": + version: 0.21.3 + resolution: "type-fest@npm:0.21.3" + checksum: 10c0/902bd57bfa30d51d4779b641c2bc403cdf1371fb9c91d3c058b0133694fcfdb817aef07a47f40faf79039eecbaa39ee9d3c532deff244f3a19ce68cea71a61e8 + languageName: node + linkType: hard + +"type-fest@npm:^4.26.1": + version: 4.38.0 + resolution: "type-fest@npm:4.38.0" + checksum: 10c0/db9990d682a08697cf8ae67ac3cdbca734c742c96615e8888401d7d54e376b390e6a5d3be25fe3b4b439e1bb88a7da461da678a614ece8caccd9c0a07dd2e5f4 + languageName: node + linkType: hard + "type-is@npm:^2.0.0": version: 2.0.0 resolution: "type-is@npm:2.0.0" @@ -14594,6 +14873,13 @@ __metadata: languageName: node linkType: hard +"universalify@npm:^0.2.0": + version: 0.2.0 + resolution: "universalify@npm:0.2.0" + checksum: 10c0/cedbe4d4ca3967edf24c0800cfc161c5a15e240dac28e3ce575c689abc11f2c81ccc6532c8752af3b40f9120fb5e454abecd359e164f4f6aa44c29cd37e194fe + languageName: node + linkType: hard + "universalify@npm:^2.0.0": version: 2.0.1 resolution: "universalify@npm:2.0.1" @@ -14638,6 +14924,16 @@ __metadata: languageName: node linkType: hard +"url-parse@npm:^1.5.3": + version: 1.5.10 + resolution: "url-parse@npm:1.5.10" + dependencies: + querystringify: "npm:^2.1.1" + requires-port: "npm:^1.0.0" + checksum: 10c0/bd5aa9389f896974beb851c112f63b466505a04b4807cea2e5a3b7092f6fbb75316f0491ea84e44f66fed55f1b440df5195d7e3a8203f64fcefa19d182f5be87 + languageName: node + linkType: hard + "urlpattern-polyfill@npm:10.0.0": version: 10.0.0 resolution: "urlpattern-polyfill@npm:10.0.0" @@ -15347,6 +15643,17 @@ __metadata: languageName: node linkType: hard +"wrap-ansi@npm:^6.2.0": + version: 6.2.0 + resolution: "wrap-ansi@npm:6.2.0" + dependencies: + ansi-styles: "npm:^4.0.0" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + checksum: 10c0/baad244e6e33335ea24e86e51868fe6823626e3a3c88d9a6674642afff1d34d9a154c917e74af8d845fd25d170c4ea9cf69a47133c3f3656e1252b3d462d9f6c + languageName: node + linkType: hard + "wrap-ansi@npm:^8.1.0": version: 8.1.0 resolution: "wrap-ansi@npm:8.1.0" @@ -15473,6 +15780,13 @@ __metadata: languageName: node linkType: hard +"yoctocolors-cjs@npm:^2.1.2": + version: 2.1.2 + resolution: "yoctocolors-cjs@npm:2.1.2" + checksum: 10c0/a0e36eb88fea2c7981eab22d1ba45e15d8d268626e6c4143305e2c1628fa17ebfaa40cd306161a8ce04c0a60ee0262058eab12567493d5eb1409780853454c6f + languageName: node + linkType: hard + "zip-stream@npm:^6.0.1": version: 6.0.1 resolution: "zip-stream@npm:6.0.1"