Skip to content

Commit 03cc3cf

Browse files
committed
fix: server down alert, maintenance
1 parent 78ffb65 commit 03cc3cf

File tree

5 files changed

+99
-24
lines changed

5 files changed

+99
-24
lines changed

backend/src/migrations/1738190126499-EventEntityMap.ts

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,45 @@ export class EventEntityMap1738190126499 implements MigrationInterface {
44
name = "EventEntityMap1738190126499";
55

66
public async up(queryRunner: QueryRunner): Promise<void> {
7-
await queryRunner.query(
8-
`ALTER TABLE "translatable_entity" ADD "location" geography(Point,4326)`,
7+
const hasColumn = await queryRunner.hasColumn(
8+
"translatable_entity",
9+
"location",
910
);
10-
await queryRunner.query(
11-
`CREATE INDEX "IDX_643c345f3e874006834b68ef60" ON "translatable_entity" USING GiST ("location") `,
11+
if (!hasColumn) {
12+
await queryRunner.query(
13+
`ALTER TABLE "translatable_entity" ADD "location" geography(Point,4326)`,
14+
);
15+
}
16+
17+
// Create index if it doesn't exist
18+
const hasIndex = await queryRunner.query(
19+
`SELECT EXISTS (
20+
SELECT FROM pg_indexes
21+
WHERE indexname = 'IDX_643c345f3e874006834b68ef60'
22+
)`,
1223
);
24+
if (!hasIndex[0].exists) {
25+
await queryRunner.query(
26+
`CREATE INDEX "IDX_643c345f3e874006834b68ef60" ON "translatable_entity" USING GiST ("location") `,
27+
);
28+
}
1329
}
1430

1531
public async down(queryRunner: QueryRunner): Promise<void> {
32+
// Drop index if exists
1633
await queryRunner.query(
17-
`DROP INDEX "public"."IDX_643c345f3e874006834b68ef60"`,
34+
`DROP INDEX IF EXISTS "public"."IDX_643c345f3e874006834b68ef60"`,
1835
);
19-
await queryRunner.query(
20-
`ALTER TABLE "translatable_entity" DROP COLUMN "location"`,
36+
37+
// Drop column if exists
38+
const hasColumn = await queryRunner.hasColumn(
39+
"translatable_entity",
40+
"location",
2141
);
42+
if (hasColumn) {
43+
await queryRunner.query(
44+
`ALTER TABLE "translatable_entity" DROP COLUMN "location"`,
45+
);
46+
}
2247
}
2348
}

mobile/localization/de.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { Language } from "./translate.service";
22

33
export const de: Language = {
4+
blog: "Blog lesen",
5+
retry: "Nochmal versuchen",
6+
maintenanceAlertTitle: "Offlinery wird gewartet",
7+
maintenanceAlertDescription:
8+
"Wir führen gerade größere Verbesserungen an unserem System durch. Wir sind gleich wieder zurück.",
49
bgLocationServiceTitle: "Offlinery EIN",
510
bgLocationServiceBody: "Bereit dich zu beeindrucken..",
611
createAccount: "Registrieren",

mobile/localization/en.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
// @dev Other languages have to be typed as Language!
22

33
export const en = {
4+
blog: "Read Blog",
5+
retry: "Retry",
6+
maintenanceAlertTitle: "Offlinery in maintenance",
7+
maintenanceAlertDescription:
8+
"We're making significant improvements on Offlinery right now. We'll be back as soon as possible.",
49
bgLocationServiceTitle: "Offlinery ON",
510
bgLocationServiceBody: "Letting others know about you.",
611
createAccount: "Create Account",

mobile/screens/Welcome.tsx

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,20 @@ import {
1919
saveJWTValues,
2020
} from "@/services/storage.service";
2121
import { API } from "@/utils/api-config";
22+
import { BLOG_URL } from "@/utils/general.constants";
2223
import { writeSupportEmail } from "@/utils/misc.utils";
2324
import { CommonActions, useFocusEffect } from "@react-navigation/native";
2425
import * as Sentry from "@sentry/react-native";
2526
import * as React from "react";
26-
import { useCallback, useState } from "react";
27-
import { Dimensions, Platform, StyleSheet, View } from "react-native";
27+
import { useCallback, useEffect, useState } from "react";
28+
import {
29+
Alert,
30+
Dimensions,
31+
Linking,
32+
Platform,
33+
StyleSheet,
34+
View,
35+
} from "react-native";
2836
import { NativeStackScreenProps } from "react-native-screens/native-stack";
2937
import { ROUTES } from "./routes";
3038

@@ -34,6 +42,7 @@ const Welcome = ({
3442
const { dispatch } = useUserContext();
3543
const [isLoading, setIsLoading] = useState(true);
3644
const [isUserAuthenticated, setIsUserAuthenticated] = useState(false);
45+
const [hasError, setHasError] = useState<boolean>(false);
3746

3847
const checkAuthStatus = async () => {
3948
try {
@@ -66,34 +75,34 @@ const Welcome = ({
6675
resp.refreshToken,
6776
);
6877
} catch (error) {
69-
console.log(
78+
console.error(
7079
`Error checking Auth Status, User might be offline or backend not reachable.`,
7180
);
7281
Sentry.captureException(error, {
7382
tags: {
7483
authStatus: "JWT not checked",
7584
},
7685
});
86+
setHasError(true);
7787
}
7888

7989
return await isAuthenticated();
8090
};
91+
const checkAuthentication = async () => {
92+
try {
93+
if (!(await isOnboardingInProgress())) {
94+
const isAuthSuccessful = await checkAuthStatus();
95+
setIsUserAuthenticated(isAuthSuccessful ?? false);
96+
}
97+
} catch (error) {
98+
console.error("Error checking authentication:", error);
99+
throw error;
100+
} finally {
101+
setIsLoading(false);
102+
}
103+
};
81104
useFocusEffect(
82105
useCallback(() => {
83-
const checkAuthentication = async () => {
84-
try {
85-
if (!(await isOnboardingInProgress())) {
86-
const isAuthSuccessful = await checkAuthStatus();
87-
setIsUserAuthenticated(isAuthSuccessful ?? false);
88-
}
89-
} catch (error) {
90-
console.error("Error checking authentication:", error);
91-
throw error;
92-
} finally {
93-
setIsLoading(false);
94-
}
95-
};
96-
97106
checkAuthentication();
98107
}, [navigation]),
99108
);
@@ -188,6 +197,36 @@ const Welcome = ({
188197
</View>
189198
);
190199

200+
const showAlert = () => {
201+
Alert.alert(
202+
i18n.t(TR.maintenanceAlertTitle),
203+
i18n.t(TR.maintenanceAlertDescription),
204+
[
205+
{
206+
text: i18n.t(TR.retry),
207+
onPress: () => {
208+
setHasError(false);
209+
checkAuthentication();
210+
},
211+
},
212+
{
213+
text: i18n.t(TR.blog),
214+
isPreferred: true,
215+
onPress: () => {
216+
Linking.openURL(BLOG_URL);
217+
showAlert(); // @dev keep open
218+
},
219+
},
220+
],
221+
{ cancelable: false },
222+
);
223+
};
224+
useEffect(() => {
225+
if (hasError) {
226+
showAlert();
227+
}
228+
}, [hasError]);
229+
191230
return (
192231
<OPageColorContainer isLoading={isLoading}>
193232
{!isUserAuthenticated && <AuthScreen />}

mobile/utils/general.constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export const SUPPORT_MAIL = "office@offlinery.io";
22
export const GDPR_URL = "https://www.offlinery.io/gdpr";
3+
export const BLOG_URL = "https://blog.offlinery.io";
34
export const AGB_URL = "https://www.offlinery.io/agb";
45
export const MAIN_WEBSITE = "https://www.offlinery.io";

0 commit comments

Comments
 (0)