13 Commits

Author SHA1 Message Date
Nicolas
4f22d48e83 Merge pull request #99 from VAR-Virtual-Air-Rescue/staging
Release v2.0.1
2025-07-25 02:25:07 +02:00
Nicolas
e9c1cf0c94 Merge pull request #84 from VAR-Virtual-Air-Rescue/staging
Namenseinstellungen und Markdown Bug Fix
2025-07-23 12:14:33 +02:00
Nicolas
940d62fdd5 Merge pull request #83 from VAR-Virtual-Air-Rescue/staging
make V1 login not case sensitive
2025-07-23 10:33:21 +02:00
PxlLoewe
644fee3e29 Merge pull request #81 from VAR-Virtual-Air-Rescue/staging
fixed condition for discord role assignment
2025-07-22 21:40:07 -07:00
PxlLoewe
d2a865c955 Merge pull request #80 from VAR-Virtual-Air-Rescue/staging
typos
2025-07-22 19:38:40 -07:00
PxlLoewe
33ec5574f2 Merge pull request #79 from VAR-Virtual-Air-Rescue/staging
added more delay to moodle ID lookup
2025-07-22 13:19:17 -07:00
PxlLoewe
8c6057fe6a Merge pull request #78 from VAR-Virtual-Air-Rescue/staging
Bug Fixes
2025-07-22 12:16:10 -07:00
PxlLoewe
25769f551a Merge pull request #77 from VAR-Virtual-Air-Rescue/staging
Final Bugfixes
2025-07-22 11:16:44 -07:00
PxlLoewe
a5998fbe0f Merge pull request #75 from VAR-Virtual-Air-Rescue/staging
Nutzerliste aus V1 übernommen
2025-07-22 09:12:47 -07:00
PxlLoewe
92e550736b Merge pull request #74 from VAR-Virtual-Air-Rescue/staging
release V2.0
2025-07-22 09:05:14 -07:00
PxlLoewe
616d3d3a61 Merge pull request #70 from VAR-Virtual-Air-Rescue/staging
Fix prod-workflow
2025-07-18 13:40:07 -07:00
PxlLoewe
df7f1b8cd1 Merge pull request #69 from VAR-Virtual-Air-Rescue/staging
Datentypen in Prod DB vorbereiten für release
2025-07-18 13:05:13 -07:00
PxlLoewe
eb98971e8a Merge pull request #47 from VAR-Virtual-Air-Rescue/staging
CD Deployment
2025-07-08 23:23:24 -07:00
19 changed files with 176 additions and 212 deletions

View File

@@ -14,7 +14,6 @@ export const sendAlert = async (
connectedAircrafts: ConnectedAircraft[]; connectedAircrafts: ConnectedAircraft[];
mission: Mission; mission: Mission;
}> => { }> => {
try {
const mission = await prisma.mission.findUnique({ const mission = await prisma.mission.findUnique({
where: { id: id }, where: { id: id },
}); });
@@ -124,8 +123,4 @@ export const sendAlert = async (
}); });
} }
return { connectedAircrafts, mission }; return { connectedAircrafts, mission };
} catch (error) {
console.error("Error sending mission alert:", error);
throw new Error("Ein Fehler ist aufgetreten. Bitte melde den Fehler als Bug");
}
}; };

View File

@@ -50,7 +50,10 @@ const getRthCallsigns = (mission: Mission, stations: Station[]) => {
return `🚁 RTH${callsigns.length > 1 ? "s" : ""}: ${callsigns.join(" / ")} `; return `🚁 RTH${callsigns.length > 1 ? "s" : ""}: ${callsigns.join(" / ")} `;
}; };
const getNtfyHeader = (mission: Mission, clientStation: Station): NtfyHeader => ({ const getNtfyHeader = (
mission: Mission,
clientStation: Station,
): NtfyHeader => ({
headers: { headers: {
Title: `${clientStation.bosCallsignShort} / ${mission.missionKeywordAbbreviation} / ${mission.missionKeywordCategory}`, Title: `${clientStation.bosCallsignShort} / ${mission.missionKeywordAbbreviation} / ${mission.missionKeywordCategory}`,
Tags: "pager", Tags: "pager",
@@ -73,13 +76,9 @@ export const sendNtfyMission = async (
clientStation: Station, clientStation: Station,
ntfyRoom: string, ntfyRoom: string,
) => { ) => {
try { axios.post(
await axios.post(
`https://ntfy.sh/${ntfyRoom}`, `https://ntfy.sh/${ntfyRoom}`,
getNtfyData(mission, stations), getNtfyData(mission, stations),
getNtfyHeader(mission, clientStation), getNtfyHeader(mission, clientStation),
); );
} catch (error) {
console.error("Error sending Ntfy mission:", error);
}
}; };

View File

@@ -34,7 +34,7 @@ router.patch("/:id", async (req, res) => {
}, },
}); });
if (discordAccount?.id && !disaptcherUpdate.ghostMode) { if (discordAccount?.id) {
await renameMember( await renameMember(
discordAccount.discordId.toString(), discordAccount.discordId.toString(),
`${getPublicUser(newDispatcher.user).fullName}${newDispatcher.zone}`, `${getPublicUser(newDispatcher.user).fullName}${newDispatcher.zone}`,

View File

@@ -189,11 +189,7 @@ router.post("/:id/send-alert", async (req, res) => {
return; return;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
res res.status(500).json({ error: "Failed to send mission" });
.status(500)
.json({
error: `Ein Fehler ist aufgetreten. Bitte melde den Fehler als Bug (${(error as Error).message})`,
});
return; return;
} }
}); });

View File

@@ -70,7 +70,7 @@ export const handleConnectDispatch =
userId: user.id, userId: user.id,
}, },
}); });
if (discordAccount?.id && !ghostMode) { if (discordAccount?.id) {
await renameMember( await renameMember(
discordAccount.discordId.toString(), discordAccount.discordId.toString(),
`${getPublicUser(user).fullName}${selectedZone}`, `${getPublicUser(user).fullName}${selectedZone}`,

View File

@@ -253,7 +253,7 @@ const MissionMarker = ({
tab: "home", tab: "home",
}, },
], ],
close: [], close: openMissionMarker?.map((m) => m.id) || [],
}); });
} }
}; };

View File

@@ -158,7 +158,7 @@ const PopupContent = ({
</span> </span>
<span> <span>
{aircraft.Station.bosCallsign.length > 15 {aircraft.Station.bosCallsign.length > 15
? aircraft.Station.bosCallsignShort ? aircraft.Station.locationStateShort
: aircraft.Station.bosCallsign} : aircraft.Station.bosCallsign}
</span> </span>
</div> </div>

View File

@@ -177,7 +177,6 @@ export const useAudioStore = create<TalkState>((set, get) => ({
if (dispatchState.status === "connected" && dispatchState.connectedDispatcher?.id) { if (dispatchState.status === "connected" && dispatchState.connectedDispatcher?.id) {
changeDispatcherAPI(dispatchState.connectedDispatcher?.id, { changeDispatcherAPI(dispatchState.connectedDispatcher?.id, {
zone: roomName, zone: roomName,
ghostMode: dispatchState.ghostMode,
}); });
} }

View File

@@ -7,7 +7,6 @@ export const handleParticipantFinished = async (
participant: Participant, participant: Participant,
user: User, user: User,
) => { ) => {
try {
const discordAccount = await prisma.discordAccount.findFirst({ const discordAccount = await prisma.discordAccount.findFirst({
where: { where: {
userId: user.id, userId: user.id,
@@ -57,9 +56,6 @@ export const handleParticipantFinished = async (
}, },
}, },
}); });
} catch (error) {
console.error("Error handling participant finished:", error);
}
}; };
export const handleParticipantEnrolled = async ( export const handleParticipantEnrolled = async (

View File

@@ -34,61 +34,43 @@ const initTransporter = () => {
initTransporter(); initTransporter();
export const sendCourseCompletedEmail = async (to: string, user: User, event: Event) => { export const sendCourseCompletedEmail = async (to: string, user: User, event: Event) => {
try {
const emailHtml = await renderCourseCompleted({ user, event }); const emailHtml = await renderCourseCompleted({ user, event });
if (!transporter) { if (!transporter) {
console.error("Transporter is not initialized"); console.error("Transporter is not initialized");
return; return;
} }
await sendMail(to, `Kurs ${event.name} erfolgreich abgeschlossen`, emailHtml); sendMail(to, `Kurs ${event.name} erfolgreich abgeschlossen`, emailHtml);
} catch (error) {
console.error("Error sending course completed email:", error);
}
}; };
export const sendPasswordChanged = async (to: string, user: User, password: string) => { export const sendPasswordChanged = async (to: string, user: User, password: string) => {
try {
const emailHtml = await renderPasswordChanged({ user, password }); const emailHtml = await renderPasswordChanged({ user, password });
await sendMail(to, `Dein Passwort wurde geändert`, emailHtml); await sendMail(to, `Dein Passwort wurde geändert`, emailHtml);
} catch (error) {}
}; };
export const sendEmailVerification = async (to: string, user: User, code: string) => { export const sendEmailVerification = async (to: string, user: User, code: string) => {
try {
const emailHtml = await renderVerificationCode({ const emailHtml = await renderVerificationCode({
user, user,
code, code,
}); });
await sendMail(to, "Bestätige deine E-Mail-Adresse", emailHtml); await sendMail(to, "Bestätige deine E-Mail-Adresse", emailHtml);
} catch (error) {
console.error("Error sending email verification:", error);
}
}; };
export const sendBannEmail = async (to: string, user: User, staffName: string) => { export const sendBannEmail = async (to: string, user: User, staffName: string) => {
try {
const emailHtml = await renderBannNotice({ const emailHtml = await renderBannNotice({
user, user,
staffName, staffName,
}); });
await sendMail(to, "Deine Sperrung bei Virtual Air Rescue", emailHtml); await sendMail(to, "Deine Sperrung bei Virtual Air Rescue", emailHtml);
} catch (error) {
console.error("Error sending ban email:", error);
}
}; };
export const sendTimebannEmail = async (to: string, user: User, staffName: string) => { export const sendTimebannEmail = async (to: string, user: User, staffName: string) => {
try {
const emailHtml = await renderTimeBanNotice({ const emailHtml = await renderTimeBanNotice({
user, user,
staffName, staffName,
}); });
await sendMail(to, "Deine vorrübergehende Sperrung bei Virtual Air Rescue", emailHtml); await sendMail(to, "Deine vorrübergehende Sperrung bei Virtual Air Rescue", emailHtml);
} catch (error) {
console.error("Error sending time ban email:", error);
}
}; };
export const sendMail = async (to: string, subject: string, html: string) => export const sendMail = async (to: string, subject: string, html: string) =>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 552 KiB

View File

@@ -22,16 +22,13 @@ export const getPublicUser = (
}, },
): PublicUser => { ): PublicUser => {
const lastName = user.lastname const lastName = user.lastname
.trim()
.split(" ") .split(" ")
.map((part) => `${part[0] || ""}.`) .map((part) => `${part[0]}.`)
.join(" "); .join(" ");
return { return {
firstname: user.firstname, firstname: user.firstname,
lastname: user.settingsHideLastname && !options.ignorePrivacy ? "" : lastName.trim(), // Only take the first letter of each section of the last name lastname: user.settingsHideLastname && !options.ignorePrivacy ? "" : lastName, // Only take the first letter of each section of the last name
fullName: fullName: `${user.firstname} ${user.settingsHideLastname && !options.ignorePrivacy ? "" : lastName}`,
`${user.firstname} ${user.settingsHideLastname && !options.ignorePrivacy ? "" : lastName}`.trim(),
publicId: user.publicId, publicId: user.publicId,
badges: user.badges, badges: user.badges,
}; };