@churchapps/helpers 1.1.8 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +29 -0
- package/.github/FUNDING.yml +1 -1
- package/.prettierrc +11 -11
- package/.yarnrc.yml +6 -0
- package/CLAUDE.md +97 -89
- package/LICENSE +21 -21
- package/README.md +15 -15
- package/dist/interfaces/Donation.d.ts +6 -0
- package/dist/interfaces/Donation.d.ts.map +1 -1
- package/dist/interfaces/Donation.js.map +1 -1
- package/package.json +55 -54
- package/scripts/build-cjs.js +32 -32
- package/src/ApiHelper.ts +176 -176
- package/src/AppearanceHelper.ts +69 -69
- package/src/ArrayHelper.ts +157 -157
- package/src/CommonEnvironmentHelper.ts +104 -104
- package/src/CurrencyHelper.ts +10 -10
- package/src/DateHelper.ts +153 -153
- package/src/DonationHelper.ts +26 -26
- package/src/ErrorHelper.ts +39 -39
- package/src/EventHelper.ts +49 -49
- package/src/FileHelper.ts +55 -55
- package/src/PersonHelper.ts +82 -82
- package/src/UniqueIdHelper.ts +36 -36
- package/src/UserHelper.ts +59 -59
- package/src/index.ts +15 -15
- package/src/interfaces/Access.ts +138 -138
- package/src/interfaces/Attendance.ts +45 -45
- package/src/interfaces/Content.ts +84 -84
- package/src/interfaces/Doing.ts +93 -93
- package/src/interfaces/Donation.ts +190 -183
- package/src/interfaces/Error.ts +17 -17
- package/src/interfaces/Membership.ts +184 -184
- package/src/interfaces/Messaging.ts +96 -96
- package/src/interfaces/Permissions.ts +92 -92
- package/src/interfaces/Reporting.ts +41 -41
- package/src/interfaces/UserContextInterface.ts +13 -13
- package/src/interfaces/index.ts +13 -13
- package/tsconfig.json +36 -36
- package/eslint.config.js +0 -33
package/src/DateHelper.ts
CHANGED
|
@@ -1,153 +1,153 @@
|
|
|
1
|
-
import dayjs from "dayjs"
|
|
2
|
-
|
|
3
|
-
// Use dynamic import for ES module compatibility with dayjs plugins
|
|
4
|
-
const loadPlugins = async () => {
|
|
5
|
-
const utc = await import("dayjs/plugin/utc");
|
|
6
|
-
const customParseFormat = await import("dayjs/plugin/customParseFormat");
|
|
7
|
-
dayjs.extend((utc as any).default || utc);
|
|
8
|
-
dayjs.extend((customParseFormat as any).default || customParseFormat);
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
// Initialize the plugins
|
|
12
|
-
loadPlugins().catch(() => {
|
|
13
|
-
console.warn("Could not load dayjs plugins");
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
export class DateHelper {
|
|
17
|
-
|
|
18
|
-
//Fixes timezone issues when you just need the date.
|
|
19
|
-
static toDate(input: any) {
|
|
20
|
-
return new Date(Date.parse(input.toString().replace("Z", "")));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
static toDateTime(input: any) {
|
|
24
|
-
return new Date(Date.parse(input.toString()));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
//obsolete. Do not use
|
|
28
|
-
static convertToDate(input: any) {
|
|
29
|
-
return this.toDateTime(input);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
static addDays(date: Date, days: number) {
|
|
33
|
-
const result = new Date(date.getTime());
|
|
34
|
-
result.setDate(result.getDate() + days);
|
|
35
|
-
return result;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
static prettyDate(date: Date) {
|
|
39
|
-
if (date === undefined || date === null) return "";
|
|
40
|
-
return this.formatDateTime(date, "MMM d, yyyy");
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
static prettyDateTime(date: Date) {
|
|
44
|
-
if (date === undefined || date === null) return "";
|
|
45
|
-
return this.formatDateTime(date, "MMM d, yyyy h:mm a");
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
static prettyTime(date: Date) {
|
|
49
|
-
if (date === undefined || date === null) return "";
|
|
50
|
-
return this.formatDateTime(date, "h:mm a");
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
static getLastSunday() {
|
|
54
|
-
let result = new Date();
|
|
55
|
-
while (result.getDay() !== 0) result.setDate(result.getDate() - 1);
|
|
56
|
-
return result;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
static getNextSunday() {
|
|
60
|
-
let result = this.getLastSunday();
|
|
61
|
-
result.setDate(result.getDate() + 7);
|
|
62
|
-
return result;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
static getWeekSunday(year: number, week: number) {
|
|
66
|
-
let result = new Date(year, 0, 1);
|
|
67
|
-
while (result.getDay() !== 0) result.setDate(result.getDate() + 1);
|
|
68
|
-
result.setDate(result.getDate() + ((week - 1) * 7));
|
|
69
|
-
return result;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
static formatHtml5Date(date: Date): string {
|
|
73
|
-
let result = "";
|
|
74
|
-
if (date !== undefined && date !== null) {
|
|
75
|
-
try {
|
|
76
|
-
result = new Date(date).toISOString().split("T")[0];
|
|
77
|
-
} catch { }
|
|
78
|
-
}
|
|
79
|
-
return result;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
static formatHtml5Time(time: Date): string {
|
|
83
|
-
let h = time.getHours();
|
|
84
|
-
let m = time.getMinutes();
|
|
85
|
-
let s = time.getSeconds();
|
|
86
|
-
return `${h < 10 ? ("0" + h) : h}:${m < 10 ? ("0" + m) : m}:${s < 10 ? ("0" + s) : s}`;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
static formatHtml5DateTime(date: Date): string {
|
|
90
|
-
if (date === undefined || date === null) return "";
|
|
91
|
-
else {
|
|
92
|
-
return this.formatDateTime(date, "yyyy-MM-dd") + "T" + this.formatDateTime(date, "HH:mm");
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
static getDisplayDuration(d: Date): string {
|
|
97
|
-
let seconds = Math.round((new Date().getTime() - d.getTime()) / 1000);
|
|
98
|
-
if (seconds > 86400) {
|
|
99
|
-
let days = Math.floor(seconds / 86400);
|
|
100
|
-
return (days === 1) ? "1d" : days.toString() + "d";
|
|
101
|
-
}
|
|
102
|
-
else if (seconds > 3600) {
|
|
103
|
-
let hours = Math.floor(seconds / 3600);
|
|
104
|
-
return (hours === 1) ? "1h" : hours.toString() + "h";
|
|
105
|
-
}
|
|
106
|
-
else if (seconds > 60) {
|
|
107
|
-
let minutes = Math.floor(seconds / 60);
|
|
108
|
-
return (minutes === 1) ? "1m" : minutes.toString() + "m";
|
|
109
|
-
}
|
|
110
|
-
else return (seconds === 1) ? "1s" : Math.floor(seconds).toString() + "s";
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
static getShortDate(d: Date): string {
|
|
114
|
-
return (d.getMonth() + 1).toString() + "/" + (d.getDate()).toString() + "/" + d.getFullYear().toString();
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
static convertDatePickerFormat(d: Date): Date {
|
|
118
|
-
const date = this.formatHtml5Date(d).split("-");
|
|
119
|
-
if (date.length === 3) return new Date(`${date[1]}-${date[2]}-${date[0]}`);
|
|
120
|
-
return new Date();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
private static formatDateTime(date: Date, format: string) {
|
|
124
|
-
try {
|
|
125
|
-
// Convert date-fns format to dayjs format
|
|
126
|
-
const dayjsFormat = format
|
|
127
|
-
.replace(/yyyy/g, 'YYYY')
|
|
128
|
-
.replace(/yy/g, 'YY')
|
|
129
|
-
.replace(/d/g, 'D')
|
|
130
|
-
.replace(/DD/g, 'DD')
|
|
131
|
-
.replace(/a/g, 'A');
|
|
132
|
-
|
|
133
|
-
return dayjs(date).format(dayjsFormat);
|
|
134
|
-
} catch { return ""; }
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
public static toMysqlDate(d: Date) {
|
|
138
|
-
if (d === null || d === undefined) {
|
|
139
|
-
return undefined;
|
|
140
|
-
}
|
|
141
|
-
return dayjs(d).format("YYYY-MM-DD HH:mm:ss")
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
public static subtractHoursFromNow(hour: number) {
|
|
145
|
-
const now = new Date();
|
|
146
|
-
return new Date(now.setHours(now.getHours() - hour));
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
public static toUTCDate(d: Date) {
|
|
150
|
-
return dayjs(d).utc().format("YYYY-MM-DD HH:mm:ss");
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
}
|
|
1
|
+
import dayjs from "dayjs"
|
|
2
|
+
|
|
3
|
+
// Use dynamic import for ES module compatibility with dayjs plugins
|
|
4
|
+
const loadPlugins = async () => {
|
|
5
|
+
const utc = await import("dayjs/plugin/utc");
|
|
6
|
+
const customParseFormat = await import("dayjs/plugin/customParseFormat");
|
|
7
|
+
dayjs.extend((utc as any).default || utc);
|
|
8
|
+
dayjs.extend((customParseFormat as any).default || customParseFormat);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// Initialize the plugins
|
|
12
|
+
loadPlugins().catch(() => {
|
|
13
|
+
console.warn("Could not load dayjs plugins");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export class DateHelper {
|
|
17
|
+
|
|
18
|
+
//Fixes timezone issues when you just need the date.
|
|
19
|
+
static toDate(input: any) {
|
|
20
|
+
return new Date(Date.parse(input.toString().replace("Z", "")));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static toDateTime(input: any) {
|
|
24
|
+
return new Date(Date.parse(input.toString()));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//obsolete. Do not use
|
|
28
|
+
static convertToDate(input: any) {
|
|
29
|
+
return this.toDateTime(input);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static addDays(date: Date, days: number) {
|
|
33
|
+
const result = new Date(date.getTime());
|
|
34
|
+
result.setDate(result.getDate() + days);
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static prettyDate(date: Date) {
|
|
39
|
+
if (date === undefined || date === null) return "";
|
|
40
|
+
return this.formatDateTime(date, "MMM d, yyyy");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static prettyDateTime(date: Date) {
|
|
44
|
+
if (date === undefined || date === null) return "";
|
|
45
|
+
return this.formatDateTime(date, "MMM d, yyyy h:mm a");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static prettyTime(date: Date) {
|
|
49
|
+
if (date === undefined || date === null) return "";
|
|
50
|
+
return this.formatDateTime(date, "h:mm a");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static getLastSunday() {
|
|
54
|
+
let result = new Date();
|
|
55
|
+
while (result.getDay() !== 0) result.setDate(result.getDate() - 1);
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static getNextSunday() {
|
|
60
|
+
let result = this.getLastSunday();
|
|
61
|
+
result.setDate(result.getDate() + 7);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static getWeekSunday(year: number, week: number) {
|
|
66
|
+
let result = new Date(year, 0, 1);
|
|
67
|
+
while (result.getDay() !== 0) result.setDate(result.getDate() + 1);
|
|
68
|
+
result.setDate(result.getDate() + ((week - 1) * 7));
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static formatHtml5Date(date: Date): string {
|
|
73
|
+
let result = "";
|
|
74
|
+
if (date !== undefined && date !== null) {
|
|
75
|
+
try {
|
|
76
|
+
result = new Date(date).toISOString().split("T")[0];
|
|
77
|
+
} catch { }
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static formatHtml5Time(time: Date): string {
|
|
83
|
+
let h = time.getHours();
|
|
84
|
+
let m = time.getMinutes();
|
|
85
|
+
let s = time.getSeconds();
|
|
86
|
+
return `${h < 10 ? ("0" + h) : h}:${m < 10 ? ("0" + m) : m}:${s < 10 ? ("0" + s) : s}`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
static formatHtml5DateTime(date: Date): string {
|
|
90
|
+
if (date === undefined || date === null) return "";
|
|
91
|
+
else {
|
|
92
|
+
return this.formatDateTime(date, "yyyy-MM-dd") + "T" + this.formatDateTime(date, "HH:mm");
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
static getDisplayDuration(d: Date): string {
|
|
97
|
+
let seconds = Math.round((new Date().getTime() - d.getTime()) / 1000);
|
|
98
|
+
if (seconds > 86400) {
|
|
99
|
+
let days = Math.floor(seconds / 86400);
|
|
100
|
+
return (days === 1) ? "1d" : days.toString() + "d";
|
|
101
|
+
}
|
|
102
|
+
else if (seconds > 3600) {
|
|
103
|
+
let hours = Math.floor(seconds / 3600);
|
|
104
|
+
return (hours === 1) ? "1h" : hours.toString() + "h";
|
|
105
|
+
}
|
|
106
|
+
else if (seconds > 60) {
|
|
107
|
+
let minutes = Math.floor(seconds / 60);
|
|
108
|
+
return (minutes === 1) ? "1m" : minutes.toString() + "m";
|
|
109
|
+
}
|
|
110
|
+
else return (seconds === 1) ? "1s" : Math.floor(seconds).toString() + "s";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
static getShortDate(d: Date): string {
|
|
114
|
+
return (d.getMonth() + 1).toString() + "/" + (d.getDate()).toString() + "/" + d.getFullYear().toString();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static convertDatePickerFormat(d: Date): Date {
|
|
118
|
+
const date = this.formatHtml5Date(d).split("-");
|
|
119
|
+
if (date.length === 3) return new Date(`${date[1]}-${date[2]}-${date[0]}`);
|
|
120
|
+
return new Date();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private static formatDateTime(date: Date, format: string) {
|
|
124
|
+
try {
|
|
125
|
+
// Convert date-fns format to dayjs format
|
|
126
|
+
const dayjsFormat = format
|
|
127
|
+
.replace(/yyyy/g, 'YYYY')
|
|
128
|
+
.replace(/yy/g, 'YY')
|
|
129
|
+
.replace(/d/g, 'D')
|
|
130
|
+
.replace(/DD/g, 'DD')
|
|
131
|
+
.replace(/a/g, 'A');
|
|
132
|
+
|
|
133
|
+
return dayjs(date).format(dayjsFormat);
|
|
134
|
+
} catch { return ""; }
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public static toMysqlDate(d: Date) {
|
|
138
|
+
if (d === null || d === undefined) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
return dayjs(d).format("YYYY-MM-DD HH:mm:ss")
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
public static subtractHoursFromNow(hour: number) {
|
|
145
|
+
const now = new Date();
|
|
146
|
+
return new Date(now.setHours(now.getHours() - hour));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public static toUTCDate(d: Date) {
|
|
150
|
+
return dayjs(d).utc().format("YYYY-MM-DD HH:mm:ss");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
}
|
package/src/DonationHelper.ts
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
export class DonationHelper {
|
|
2
|
-
|
|
3
|
-
static getInterval(intervalName:string) {
|
|
4
|
-
let intervalCount = 1;
|
|
5
|
-
let intervalType = "month";
|
|
6
|
-
let parts = intervalName.split("_");
|
|
7
|
-
if (parts.length === 2) {
|
|
8
|
-
switch (parts[0])
|
|
9
|
-
{
|
|
10
|
-
case "two": intervalCount = 2; break;
|
|
11
|
-
case "three": intervalCount = 3; break;
|
|
12
|
-
}
|
|
13
|
-
intervalType = parts[1];
|
|
14
|
-
}
|
|
15
|
-
let result = { interval_count: intervalCount, interval: intervalType };
|
|
16
|
-
return result;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
static getIntervalKeyName(intervalCount: number, intervalType: string) {
|
|
20
|
-
let firstPart = "one";
|
|
21
|
-
if (intervalCount === 2) firstPart = "two";
|
|
22
|
-
else if (intervalCount === 3) firstPart = "three";
|
|
23
|
-
return firstPart + "_" + intervalType;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
}
|
|
1
|
+
export class DonationHelper {
|
|
2
|
+
|
|
3
|
+
static getInterval(intervalName:string) {
|
|
4
|
+
let intervalCount = 1;
|
|
5
|
+
let intervalType = "month";
|
|
6
|
+
let parts = intervalName.split("_");
|
|
7
|
+
if (parts.length === 2) {
|
|
8
|
+
switch (parts[0])
|
|
9
|
+
{
|
|
10
|
+
case "two": intervalCount = 2; break;
|
|
11
|
+
case "three": intervalCount = 3; break;
|
|
12
|
+
}
|
|
13
|
+
intervalType = parts[1];
|
|
14
|
+
}
|
|
15
|
+
let result = { interval_count: intervalCount, interval: intervalType };
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static getIntervalKeyName(intervalCount: number, intervalType: string) {
|
|
20
|
+
let firstPart = "one";
|
|
21
|
+
if (intervalCount === 2) firstPart = "two";
|
|
22
|
+
else if (intervalCount === 3) firstPart = "three";
|
|
23
|
+
return firstPart + "_" + intervalType;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
}
|
package/src/ErrorHelper.ts
CHANGED
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import { ErrorLogInterface, ErrorAppDataInterface } from "./interfaces/Error";
|
|
2
|
-
import { ApiHelper } from "./ApiHelper";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export class ErrorHelper {
|
|
6
|
-
|
|
7
|
-
static getAppData: () => { churchId: string, userId: string, originUrl: string, application: string };
|
|
8
|
-
static customErrorHandler: (errorLog: ErrorLogInterface) => void;
|
|
9
|
-
|
|
10
|
-
static init = (getAppData: () => ErrorAppDataInterface, customErrorHandler: (errorLog: ErrorLogInterface) => void) => {
|
|
11
|
-
ErrorHelper.getAppData = getAppData;
|
|
12
|
-
ErrorHelper.customErrorHandler = customErrorHandler;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
static logError = (errorType: string, message: string, details: string) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (this.getAppData) {
|
|
19
|
-
const data = this.getAppData();
|
|
20
|
-
const log: ErrorLogInterface = {
|
|
21
|
-
application: data.application,
|
|
22
|
-
errorTime: new Date(),
|
|
23
|
-
userId: data.userId,
|
|
24
|
-
churchId: data.churchId,
|
|
25
|
-
originUrl: data.originUrl,
|
|
26
|
-
errorType: errorType,
|
|
27
|
-
message: message,
|
|
28
|
-
details: details
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (log.errorType === "401" && log.message.indexOf("/users/login") > -1) return;
|
|
32
|
-
//temporarily disabled error logging
|
|
33
|
-
//ApiHelper.postAnonymous("/errors", [log], "MembershipApi");
|
|
34
|
-
if (ErrorHelper.customErrorHandler) ErrorHelper.customErrorHandler(log);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
1
|
+
import { ErrorLogInterface, ErrorAppDataInterface } from "./interfaces/Error";
|
|
2
|
+
import { ApiHelper } from "./ApiHelper";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export class ErrorHelper {
|
|
6
|
+
|
|
7
|
+
static getAppData: () => { churchId: string, userId: string, originUrl: string, application: string };
|
|
8
|
+
static customErrorHandler: (errorLog: ErrorLogInterface) => void;
|
|
9
|
+
|
|
10
|
+
static init = (getAppData: () => ErrorAppDataInterface, customErrorHandler: (errorLog: ErrorLogInterface) => void) => {
|
|
11
|
+
ErrorHelper.getAppData = getAppData;
|
|
12
|
+
ErrorHelper.customErrorHandler = customErrorHandler;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static logError = (errorType: string, message: string, details: string) => {
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
if (this.getAppData) {
|
|
19
|
+
const data = this.getAppData();
|
|
20
|
+
const log: ErrorLogInterface = {
|
|
21
|
+
application: data.application,
|
|
22
|
+
errorTime: new Date(),
|
|
23
|
+
userId: data.userId,
|
|
24
|
+
churchId: data.churchId,
|
|
25
|
+
originUrl: data.originUrl,
|
|
26
|
+
errorType: errorType,
|
|
27
|
+
message: message,
|
|
28
|
+
details: details
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (log.errorType === "401" && log.message.indexOf("/users/login") > -1) return;
|
|
32
|
+
//temporarily disabled error logging
|
|
33
|
+
//ApiHelper.postAnonymous("/errors", [log], "MembershipApi");
|
|
34
|
+
if (ErrorHelper.customErrorHandler) ErrorHelper.customErrorHandler(log);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
}
|
package/src/EventHelper.ts
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import { EventInterface } from "./interfaces";
|
|
2
|
-
import { RRule, datetime } from "rrule";
|
|
3
|
-
import { ParsedOptions } from "rrule/dist/esm/types";
|
|
4
|
-
|
|
5
|
-
export class EventHelper {
|
|
6
|
-
|
|
7
|
-
static getRange = (event:EventInterface, startDate:Date, endDate:Date) => {
|
|
8
|
-
const start = new Date(event.start);
|
|
9
|
-
const rrule = EventHelper.getFullRRule(event);
|
|
10
|
-
|
|
11
|
-
const dates = rrule.between(startDate, endDate);
|
|
12
|
-
|
|
13
|
-
dates.forEach(d => {
|
|
14
|
-
d.setHours(start.getHours());
|
|
15
|
-
d.setMinutes(start.getMinutes());
|
|
16
|
-
d.setSeconds(start.getSeconds());
|
|
17
|
-
})
|
|
18
|
-
return dates;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
static getFullRRule = (event:EventInterface) => {
|
|
22
|
-
let rrule = RRule.fromString(event.recurrenceRule);
|
|
23
|
-
rrule.options.dtstart = new Date(event.start);
|
|
24
|
-
return rrule;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
static removeExcludeDates = (events:EventInterface[]) => {
|
|
28
|
-
for (let i=events.length-1; i>=0; i--) {
|
|
29
|
-
if (events[i].exceptionDates?.length>0)
|
|
30
|
-
{
|
|
31
|
-
const parsedDates = events[i].exceptionDates.map(d=>new Date(d).toISOString());
|
|
32
|
-
if (parsedDates.indexOf(events[i].start.toISOString())>-1) events.splice(i,1);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
static getPartialRRuleString = (options:ParsedOptions) => {
|
|
38
|
-
const parts = new RRule(options).toString().split("RRULE:");
|
|
39
|
-
const result = parts.length===2 ? parts[1] : "";
|
|
40
|
-
return result;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
static cleanRule = (options:ParsedOptions) => {
|
|
44
|
-
options.byhour = undefined;
|
|
45
|
-
options.byminute = undefined;
|
|
46
|
-
options.bysecond = undefined;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
}
|
|
1
|
+
import { EventInterface } from "./interfaces";
|
|
2
|
+
import { RRule, datetime } from "rrule";
|
|
3
|
+
import { ParsedOptions } from "rrule/dist/esm/types";
|
|
4
|
+
|
|
5
|
+
export class EventHelper {
|
|
6
|
+
|
|
7
|
+
static getRange = (event:EventInterface, startDate:Date, endDate:Date) => {
|
|
8
|
+
const start = new Date(event.start);
|
|
9
|
+
const rrule = EventHelper.getFullRRule(event);
|
|
10
|
+
|
|
11
|
+
const dates = rrule.between(startDate, endDate);
|
|
12
|
+
|
|
13
|
+
dates.forEach(d => {
|
|
14
|
+
d.setHours(start.getHours());
|
|
15
|
+
d.setMinutes(start.getMinutes());
|
|
16
|
+
d.setSeconds(start.getSeconds());
|
|
17
|
+
})
|
|
18
|
+
return dates;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static getFullRRule = (event:EventInterface) => {
|
|
22
|
+
let rrule = RRule.fromString(event.recurrenceRule);
|
|
23
|
+
rrule.options.dtstart = new Date(event.start);
|
|
24
|
+
return rrule;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static removeExcludeDates = (events:EventInterface[]) => {
|
|
28
|
+
for (let i=events.length-1; i>=0; i--) {
|
|
29
|
+
if (events[i].exceptionDates?.length>0)
|
|
30
|
+
{
|
|
31
|
+
const parsedDates = events[i].exceptionDates.map(d=>new Date(d).toISOString());
|
|
32
|
+
if (parsedDates.indexOf(events[i].start.toISOString())>-1) events.splice(i,1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static getPartialRRuleString = (options:ParsedOptions) => {
|
|
38
|
+
const parts = new RRule(options).toString().split("RRULE:");
|
|
39
|
+
const result = parts.length===2 ? parts[1] : "";
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static cleanRule = (options:ParsedOptions) => {
|
|
44
|
+
options.byhour = undefined;
|
|
45
|
+
options.byminute = undefined;
|
|
46
|
+
options.bysecond = undefined;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
}
|
package/src/FileHelper.ts
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
export class FileHelper {
|
|
2
|
-
|
|
3
|
-
static postPresignedFile = (presigned: any, uploadedFile: File, progressCallback: (percent: number) => void) => {
|
|
4
|
-
const formData = new FormData();
|
|
5
|
-
formData.append("key", presigned.key);
|
|
6
|
-
formData.append("acl", "public-read");
|
|
7
|
-
formData.append("Content-Type", uploadedFile.type);
|
|
8
|
-
for (const property in presigned.fields) formData.append(property, presigned.fields[property]);
|
|
9
|
-
formData.append("file", uploadedFile);
|
|
10
|
-
|
|
11
|
-
// Use XMLHttpRequest for upload progress tracking since fetch doesn't support it natively
|
|
12
|
-
return new Promise((resolve, reject) => {
|
|
13
|
-
const xhr = new XMLHttpRequest();
|
|
14
|
-
|
|
15
|
-
xhr.upload.addEventListener('progress', (event) => {
|
|
16
|
-
if (event.lengthComputable) {
|
|
17
|
-
const percent = Math.round((event.loaded / event.total) * 100);
|
|
18
|
-
progressCallback(percent);
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
xhr.addEventListener('load', () => {
|
|
23
|
-
if (xhr.status >= 200 && xhr.status < 300) {
|
|
24
|
-
resolve({
|
|
25
|
-
status: xhr.status,
|
|
26
|
-
statusText: xhr.statusText,
|
|
27
|
-
data: xhr.responseText
|
|
28
|
-
});
|
|
29
|
-
} else {
|
|
30
|
-
reject(new Error(`HTTP Error: ${xhr.status} ${xhr.statusText}`));
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
xhr.addEventListener('error', () => {
|
|
35
|
-
reject(new Error('Network error occurred'));
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
xhr.open('POST', presigned.url);
|
|
39
|
-
xhr.send(formData);
|
|
40
|
-
});
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
static dataURLtoBlob(dataurl: string) {
|
|
44
|
-
let arr = dataurl.split(",");
|
|
45
|
-
if (arr.length < 2) throw new Error("Invalid data URL format");
|
|
46
|
-
let mimeMatch = arr[0].match(/:(.*?);/);
|
|
47
|
-
if (!mimeMatch) throw new Error("Invalid MIME type in data URL");
|
|
48
|
-
let mime = mimeMatch[1];
|
|
49
|
-
let bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
|
|
50
|
-
while (n--) {
|
|
51
|
-
u8arr[n] = bstr.charCodeAt(n);
|
|
52
|
-
}
|
|
53
|
-
return new Blob([u8arr], { type: mime });
|
|
54
|
-
}
|
|
55
|
-
}
|
|
1
|
+
export class FileHelper {
|
|
2
|
+
|
|
3
|
+
static postPresignedFile = (presigned: any, uploadedFile: File, progressCallback: (percent: number) => void) => {
|
|
4
|
+
const formData = new FormData();
|
|
5
|
+
formData.append("key", presigned.key);
|
|
6
|
+
formData.append("acl", "public-read");
|
|
7
|
+
formData.append("Content-Type", uploadedFile.type);
|
|
8
|
+
for (const property in presigned.fields) formData.append(property, presigned.fields[property]);
|
|
9
|
+
formData.append("file", uploadedFile);
|
|
10
|
+
|
|
11
|
+
// Use XMLHttpRequest for upload progress tracking since fetch doesn't support it natively
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const xhr = new XMLHttpRequest();
|
|
14
|
+
|
|
15
|
+
xhr.upload.addEventListener('progress', (event) => {
|
|
16
|
+
if (event.lengthComputable) {
|
|
17
|
+
const percent = Math.round((event.loaded / event.total) * 100);
|
|
18
|
+
progressCallback(percent);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
xhr.addEventListener('load', () => {
|
|
23
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
24
|
+
resolve({
|
|
25
|
+
status: xhr.status,
|
|
26
|
+
statusText: xhr.statusText,
|
|
27
|
+
data: xhr.responseText
|
|
28
|
+
});
|
|
29
|
+
} else {
|
|
30
|
+
reject(new Error(`HTTP Error: ${xhr.status} ${xhr.statusText}`));
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
xhr.addEventListener('error', () => {
|
|
35
|
+
reject(new Error('Network error occurred'));
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
xhr.open('POST', presigned.url);
|
|
39
|
+
xhr.send(formData);
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
static dataURLtoBlob(dataurl: string) {
|
|
44
|
+
let arr = dataurl.split(",");
|
|
45
|
+
if (arr.length < 2) throw new Error("Invalid data URL format");
|
|
46
|
+
let mimeMatch = arr[0].match(/:(.*?);/);
|
|
47
|
+
if (!mimeMatch) throw new Error("Invalid MIME type in data URL");
|
|
48
|
+
let mime = mimeMatch[1];
|
|
49
|
+
let bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
|
|
50
|
+
while (n--) {
|
|
51
|
+
u8arr[n] = bstr.charCodeAt(n);
|
|
52
|
+
}
|
|
53
|
+
return new Blob([u8arr], { type: mime });
|
|
54
|
+
}
|
|
55
|
+
}
|