@churchapps/apphelper 0.6.14 → 0.6.16

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.
Files changed (215) hide show
  1. package/dist/components/DisplayBox.d.ts +1 -1
  2. package/dist/components/DisplayBox.d.ts.map +1 -1
  3. package/dist/components/DisplayBox.js +2 -4
  4. package/dist/components/DisplayBox.js.map +1 -1
  5. package/dist/components/ErrorMessages.d.ts.map +1 -1
  6. package/dist/components/ErrorMessages.js +1 -1
  7. package/dist/components/ErrorMessages.js.map +1 -1
  8. package/dist/components/ExportLink.d.ts.map +1 -1
  9. package/dist/components/ExportLink.js +10 -10
  10. package/dist/components/ExportLink.js.map +1 -1
  11. package/dist/components/FloatingSupport.js.map +1 -1
  12. package/dist/components/FormCardPayment.d.ts.map +1 -1
  13. package/dist/components/FormCardPayment.js +20 -5
  14. package/dist/components/FormCardPayment.js.map +1 -1
  15. package/dist/components/FormSubmissionEdit.d.ts.map +1 -1
  16. package/dist/components/FormSubmissionEdit.js +8 -10
  17. package/dist/components/FormSubmissionEdit.js.map +1 -1
  18. package/dist/components/HelpIcon.d.ts.map +1 -1
  19. package/dist/components/HelpIcon.js.map +1 -1
  20. package/dist/components/ImageEditor.d.ts.map +1 -1
  21. package/dist/components/ImageEditor.js +10 -10
  22. package/dist/components/ImageEditor.js.map +1 -1
  23. package/dist/components/InputBox.d.ts +2 -1
  24. package/dist/components/InputBox.d.ts.map +1 -1
  25. package/dist/components/InputBox.js +5 -7
  26. package/dist/components/InputBox.js.map +1 -1
  27. package/dist/components/Loading.d.ts.map +1 -1
  28. package/dist/components/Loading.js.map +1 -1
  29. package/dist/components/PageHeader.js +14 -14
  30. package/dist/components/PersonAvatar.d.ts.map +1 -1
  31. package/dist/components/PersonAvatar.js +9 -16
  32. package/dist/components/PersonAvatar.js.map +1 -1
  33. package/dist/components/QuestionEdit.js +3 -3
  34. package/dist/components/QuestionEdit.js.map +1 -1
  35. package/dist/components/SmallButton.d.ts.map +1 -1
  36. package/dist/components/SmallButton.js +2 -1
  37. package/dist/components/SmallButton.js.map +1 -1
  38. package/dist/components/SupportModal.js.map +1 -1
  39. package/dist/components/gallery/GalleryModal.js +10 -10
  40. package/dist/components/gallery/GalleryModal.js.map +1 -1
  41. package/dist/components/gallery/StockPhotos.js +12 -12
  42. package/dist/components/gallery/StockPhotos.js.map +1 -1
  43. package/dist/components/header/Banner.d.ts.map +1 -1
  44. package/dist/components/header/Banner.js.map +1 -1
  45. package/dist/components/header/PrimaryMenu.js +4 -4
  46. package/dist/components/header/PrimaryMenu.js.map +1 -1
  47. package/dist/components/header/SecondaryMenu.d.ts.map +1 -1
  48. package/dist/components/header/SecondaryMenu.js.map +1 -1
  49. package/dist/components/header/SecondaryMenuAlt.d.ts.map +1 -1
  50. package/dist/components/header/SecondaryMenuAlt.js.map +1 -1
  51. package/dist/components/header/SiteHeader.d.ts.map +1 -1
  52. package/dist/components/header/SiteHeader.js +7 -7
  53. package/dist/components/header/SiteHeader.js.map +1 -1
  54. package/dist/components/header/SupportDrawer.js +1 -1
  55. package/dist/components/header/SupportDrawer.js.map +1 -1
  56. package/dist/components/notes/AddNote.js +14 -14
  57. package/dist/components/notes/Note.d.ts.map +1 -1
  58. package/dist/components/notes/Note.js +7 -7
  59. package/dist/components/notes/Note.js.map +1 -1
  60. package/dist/components/notes/Notes.d.ts.map +1 -1
  61. package/dist/components/notes/Notes.js +4 -4
  62. package/dist/components/notes/Notes.js.map +1 -1
  63. package/dist/components/wrapper/AppList.d.ts.map +1 -1
  64. package/dist/components/wrapper/AppList.js.map +1 -1
  65. package/dist/components/wrapper/ChurchList.js +5 -5
  66. package/dist/components/wrapper/ChurchList.js.map +1 -1
  67. package/dist/components/wrapper/NavItem.js +1 -1
  68. package/dist/components/wrapper/NavItem.js.map +1 -1
  69. package/dist/components/wrapper/NewPrivateMessage.d.ts.map +1 -1
  70. package/dist/components/wrapper/NewPrivateMessage.js +7 -6
  71. package/dist/components/wrapper/NewPrivateMessage.js.map +1 -1
  72. package/dist/components/wrapper/Notifications.d.ts.map +1 -1
  73. package/dist/components/wrapper/Notifications.js +12 -14
  74. package/dist/components/wrapper/Notifications.js.map +1 -1
  75. package/dist/components/wrapper/PrivateMessageDetails.js +10 -10
  76. package/dist/components/wrapper/PrivateMessages.d.ts.map +1 -1
  77. package/dist/components/wrapper/PrivateMessages.js +119 -123
  78. package/dist/components/wrapper/PrivateMessages.js.map +1 -1
  79. package/dist/components/wrapper/UserMenu.d.ts.map +1 -1
  80. package/dist/components/wrapper/UserMenu.js +15 -15
  81. package/dist/components/wrapper/UserMenu.js.map +1 -1
  82. package/dist/helpers/AnalyticsHelper.d.ts.map +1 -1
  83. package/dist/helpers/AnalyticsHelper.js +3 -3
  84. package/dist/helpers/AnalyticsHelper.js.map +1 -1
  85. package/dist/helpers/ArrayHelper.d.ts.map +1 -1
  86. package/dist/helpers/ArrayHelper.js.map +1 -1
  87. package/dist/helpers/CurrencyHelper.d.ts +4 -0
  88. package/dist/helpers/CurrencyHelper.d.ts.map +1 -1
  89. package/dist/helpers/CurrencyHelper.js +65 -0
  90. package/dist/helpers/CurrencyHelper.js.map +1 -1
  91. package/dist/helpers/ErrorHelper.d.ts.map +1 -1
  92. package/dist/helpers/ErrorHelper.js.map +1 -1
  93. package/dist/helpers/EventHelper.d.ts.map +1 -1
  94. package/dist/helpers/EventHelper.js +1 -1
  95. package/dist/helpers/EventHelper.js.map +1 -1
  96. package/dist/helpers/FileHelper.d.ts.map +1 -1
  97. package/dist/helpers/FileHelper.js +3 -1
  98. package/dist/helpers/FileHelper.js.map +1 -1
  99. package/dist/helpers/Locale.d.ts.map +1 -1
  100. package/dist/helpers/Locale.js +10 -16
  101. package/dist/helpers/Locale.js.map +1 -1
  102. package/dist/helpers/NotificationService.js +4 -4
  103. package/dist/helpers/PersonHelper.d.ts.map +1 -1
  104. package/dist/helpers/PersonHelper.js +5 -4
  105. package/dist/helpers/PersonHelper.js.map +1 -1
  106. package/dist/helpers/SlugHelper.d.ts.map +1 -1
  107. package/dist/helpers/SlugHelper.js +5 -3
  108. package/dist/helpers/SlugHelper.js.map +1 -1
  109. package/dist/helpers/SocketHelper.d.ts.map +1 -1
  110. package/dist/helpers/SocketHelper.js +5 -10
  111. package/dist/helpers/SocketHelper.js.map +1 -1
  112. package/dist/helpers/UniqueIdHelper.d.ts.map +1 -1
  113. package/dist/helpers/UniqueIdHelper.js +132 -7
  114. package/dist/helpers/UniqueIdHelper.js.map +1 -1
  115. package/dist/helpers/UserHelper.d.ts.map +1 -1
  116. package/dist/helpers/UserHelper.js +2 -2
  117. package/dist/helpers/UserHelper.js.map +1 -1
  118. package/dist/hooks/useMountedState.d.ts.map +1 -1
  119. package/dist/hooks/useMountedState.js +1 -1
  120. package/dist/hooks/useMountedState.js.map +1 -1
  121. package/dist/hooks/useNotifications.d.ts +2 -2
  122. package/dist/hooks/useNotifications.js +5 -5
  123. package/dist/public/locales/de.json +15 -7
  124. package/dist/public/locales/es.json +193 -190
  125. package/dist/public/locales/fr.json +15 -7
  126. package/dist/public/locales/hi.json +15 -7
  127. package/dist/public/locales/it.json +15 -7
  128. package/dist/public/locales/ko.json +15 -7
  129. package/dist/public/locales/no.json +15 -7
  130. package/dist/public/locales/pt.json +15 -7
  131. package/dist/public/locales/ru.json +15 -7
  132. package/dist/public/locales/tl.json +15 -7
  133. package/dist/public/locales/zh.json +15 -7
  134. package/package.json +106 -73
  135. package/dist/helpers/DateHelper.d.ts +0 -18
  136. package/dist/helpers/DateHelper.d.ts.map +0 -1
  137. package/dist/helpers/DateHelper.js +0 -102
  138. package/dist/helpers/DateHelper.js.map +0 -1
  139. package/public/css/cropper.css +0 -309
  140. package/public/css/styles.css +0 -112
  141. package/public/locales/de.json +0 -273
  142. package/public/locales/en.json +0 -281
  143. package/public/locales/es.json +0 -278
  144. package/public/locales/fr.json +0 -273
  145. package/public/locales/hi.json +0 -273
  146. package/public/locales/it.json +0 -273
  147. package/public/locales/ko.json +0 -273
  148. package/public/locales/no.json +0 -273
  149. package/public/locales/pt.json +0 -273
  150. package/public/locales/ru.json +0 -273
  151. package/public/locales/tl.json +0 -273
  152. package/public/locales/zh.json +0 -273
  153. package/src/components/DisplayBox.tsx +0 -83
  154. package/src/components/ErrorMessages.tsx +0 -28
  155. package/src/components/ExportLink.tsx +0 -81
  156. package/src/components/FloatingSupport.tsx +0 -18
  157. package/src/components/FormCardPayment.tsx +0 -184
  158. package/src/components/FormSubmissionEdit.tsx +0 -168
  159. package/src/components/HelpIcon.tsx +0 -12
  160. package/src/components/ImageEditor.tsx +0 -167
  161. package/src/components/InputBox.tsx +0 -96
  162. package/src/components/Loading.tsx +0 -31
  163. package/src/components/PageHeader.tsx +0 -111
  164. package/src/components/PersonAvatar.tsx +0 -78
  165. package/src/components/QuestionEdit.tsx +0 -99
  166. package/src/components/SmallButton.tsx +0 -42
  167. package/src/components/SupportModal.tsx +0 -32
  168. package/src/components/TabPanel.tsx +0 -28
  169. package/src/components/gallery/GalleryModal.tsx +0 -170
  170. package/src/components/gallery/StockPhotos.tsx +0 -96
  171. package/src/components/gallery/index.ts +0 -2
  172. package/src/components/header/Banner.tsx +0 -11
  173. package/src/components/header/PrimaryMenu.tsx +0 -101
  174. package/src/components/header/SecondaryMenu.tsx +0 -23
  175. package/src/components/header/SecondaryMenuAlt.tsx +0 -40
  176. package/src/components/header/SiteHeader.tsx +0 -205
  177. package/src/components/header/SupportDrawer.tsx +0 -112
  178. package/src/components/header/index.tsx +0 -2
  179. package/src/components/index.tsx +0 -20
  180. package/src/components/notes/AddNote.tsx +0 -185
  181. package/src/components/notes/Note.tsx +0 -84
  182. package/src/components/notes/Notes.tsx +0 -208
  183. package/src/components/notes/index.ts +0 -3
  184. package/src/components/wrapper/AppList.tsx +0 -18
  185. package/src/components/wrapper/ChurchList.tsx +0 -145
  186. package/src/components/wrapper/NavItem.tsx +0 -47
  187. package/src/components/wrapper/NewPrivateMessage.tsx +0 -249
  188. package/src/components/wrapper/Notifications.tsx +0 -220
  189. package/src/components/wrapper/PrivateMessageDetails.tsx +0 -106
  190. package/src/components/wrapper/PrivateMessages.tsx +0 -574
  191. package/src/components/wrapper/UserMenu.tsx +0 -384
  192. package/src/components/wrapper/index.tsx +0 -8
  193. package/src/helpers/AnalyticsHelper.ts +0 -44
  194. package/src/helpers/AppearanceHelper.ts +0 -73
  195. package/src/helpers/ArrayHelper.ts +0 -87
  196. package/src/helpers/CurrencyHelper.ts +0 -10
  197. package/src/helpers/DateHelper.ts +0 -104
  198. package/src/helpers/ErrorHelper.ts +0 -41
  199. package/src/helpers/EventHelper.ts +0 -49
  200. package/src/helpers/FileHelper.ts +0 -31
  201. package/src/helpers/Locale.ts +0 -457
  202. package/src/helpers/NotificationService.ts +0 -233
  203. package/src/helpers/PersonHelper.ts +0 -62
  204. package/src/helpers/SlugHelper.ts +0 -27
  205. package/src/helpers/SocketHelper.ts +0 -183
  206. package/src/helpers/UniqueIdHelper.ts +0 -36
  207. package/src/helpers/UserHelper.ts +0 -103
  208. package/src/helpers/createEmotionCache.ts +0 -17
  209. package/src/helpers/index.ts +0 -58
  210. package/src/hooks/index.ts +0 -3
  211. package/src/hooks/useMountedState.ts +0 -18
  212. package/src/hooks/useNotifications.ts +0 -95
  213. package/src/index.ts +0 -3
  214. package/src/types/interface-extensions.d.ts +0 -12
  215. package/tsconfig.json +0 -32
@@ -1,233 +0,0 @@
1
- import { SocketHelper } from "./SocketHelper";
2
- import { ApiHelper, UserContextInterface } from "@churchapps/helpers";
3
-
4
- export interface NotificationCounts {
5
- notificationCount: number;
6
- pmCount: number;
7
- }
8
-
9
- export class NotificationService {
10
- private static instance: NotificationService;
11
- private counts: NotificationCounts = { notificationCount: 0, pmCount: 0 };
12
- private listeners: Array<(counts: NotificationCounts) => void> = [];
13
- private isInitialized: boolean = false;
14
- private currentPersonId: string | null = null;
15
- private loadTimeout: any | null = null;
16
-
17
- private constructor() {}
18
-
19
- static getInstance(): NotificationService {
20
- if (!NotificationService.instance) {
21
- NotificationService.instance = new NotificationService();
22
- }
23
- return NotificationService.instance;
24
- }
25
-
26
- /**
27
- * Initialize the notification service with user context
28
- */
29
- async initialize(context: UserContextInterface): Promise<void> {
30
- if (this.isInitialized) {
31
- return;
32
- }
33
-
34
- try {
35
- // Store current person ID for conversation counting
36
- this.currentPersonId = context?.person?.id || null;
37
-
38
- // Initialize WebSocket connection
39
- await SocketHelper.init();
40
-
41
- // Set person/church context for websocket
42
- if (context?.person?.id && context?.userChurch?.church?.id) {
43
- SocketHelper.setPersonChurch({
44
- personId: context.person.id,
45
- churchId: context.userChurch.church.id
46
- });
47
- } else {
48
- console.warn('⚠️ NotificationService: Missing person/church IDs, cannot set socket context');
49
- }
50
-
51
- // Register handlers for notification updates
52
- this.registerWebSocketHandlers();
53
-
54
- // Load initial notification counts
55
- await this.loadNotificationCounts();
56
-
57
- this.isInitialized = true;
58
-
59
- } catch (error) {
60
- console.error("❌ Failed to initialize NotificationService:", error);
61
- throw error;
62
- }
63
- }
64
-
65
- /**
66
- * Register websocket handlers for real-time notification updates
67
- */
68
- private registerWebSocketHandlers(): void {
69
- // Handler for new private messages
70
- SocketHelper.addHandler("privateMessage", "NotificationService-PM", (data: any) => {
71
- try {
72
- this.debouncedLoadNotificationCounts();
73
- } catch (error) {
74
- console.error('❌ NotificationService: Error calling debouncedLoadNotificationCounts:', error);
75
- }
76
- });
77
-
78
- // Handler for general notifications
79
- SocketHelper.addHandler("notification", "NotificationService-Notification", (data: any) => {
80
- try {
81
- this.debouncedLoadNotificationCounts();
82
- } catch (error) {
83
- console.error('❌ NotificationService: Error calling debouncedLoadNotificationCounts:', error);
84
- }
85
- });
86
-
87
- // Handler for message updates that could affect notification counts
88
- SocketHelper.addHandler("message", "NotificationService-MessageUpdate", (data: any) => {
89
- // Only update counts if the message update involves the current person
90
- if (data?.message?.personId === this.currentPersonId ||
91
- data?.notifyPersonId === this.currentPersonId) {
92
- try {
93
- this.debouncedLoadNotificationCounts();
94
- } catch (error) {
95
- console.error('❌ NotificationService: Error calling debouncedLoadNotificationCounts:', error);
96
- }
97
- }
98
- });
99
-
100
- // Handler for reconnect events
101
- SocketHelper.addHandler("reconnect", "NotificationService-Reconnect", (data: any) => {
102
- this.loadNotificationCounts(); // Don't debounce reconnect - need immediate update
103
- });
104
- }
105
-
106
- /**
107
- * Load notification counts from the API with debouncing
108
- */
109
- private debouncedLoadNotificationCounts(): void {
110
-
111
- if (this.loadTimeout) {
112
- clearTimeout(this.loadTimeout);
113
- }
114
-
115
- this.loadTimeout = setTimeout(() => {
116
- this.loadNotificationCounts();
117
- }, 300); // 300ms debounce
118
- }
119
-
120
- /**
121
- * Load notification counts from the API
122
- */
123
- async loadNotificationCounts(): Promise<void> {
124
-
125
- try {
126
- // Use the unreadCount endpoint which returns both notification and PM counts
127
- const counts = await ApiHelper.get("/notifications/unreadCount", "MessagingApi");
128
-
129
- const newCounts = {
130
- notificationCount: counts?.notificationCount || 0,
131
- pmCount: counts?.pmCount || 0
132
- };
133
-
134
-
135
- // Update counts and notify listeners
136
- this.updateCounts(newCounts);
137
-
138
- } catch (error) {
139
- console.error("❌ Failed to load notification counts:", error);
140
- console.error("❌ Error details:", {
141
- message: error.message,
142
- status: error.status,
143
- response: error.response
144
- });
145
- // Don't throw - just log the error and keep existing counts
146
- }
147
- }
148
-
149
- /**
150
- * Update counts and notify all listeners
151
- */
152
- private updateCounts(newCounts: NotificationCounts): void {
153
-
154
- const countsChanged =
155
- this.counts.notificationCount !== newCounts.notificationCount ||
156
- this.counts.pmCount !== newCounts.pmCount;
157
-
158
-
159
- if (countsChanged) {
160
- this.counts = { ...newCounts };
161
-
162
- // Notify all listeners
163
- this.listeners.forEach((listener, index) => {
164
- try {
165
- listener(this.counts);
166
- } catch (error) {
167
- console.error(`❌ Error in notification listener ${index}:`, error);
168
- }
169
- });
170
- }
171
- }
172
-
173
- /**
174
- * Subscribe to notification count changes
175
- */
176
- subscribe(listener: (counts: NotificationCounts) => void): () => void {
177
- this.listeners.push(listener);
178
-
179
- // Immediately call with current counts
180
- listener(this.counts);
181
-
182
- // Return unsubscribe function
183
- return () => {
184
- this.listeners = this.listeners.filter(l => l !== listener);
185
- };
186
- }
187
-
188
- /**
189
- * Get current notification counts
190
- */
191
- getCounts(): NotificationCounts {
192
- return { ...this.counts };
193
- }
194
-
195
- /**
196
- * Manually refresh notification counts
197
- */
198
- async refresh(): Promise<void> {
199
- await this.loadNotificationCounts();
200
- }
201
-
202
- /**
203
- * Cleanup the service
204
- */
205
- cleanup(): void {
206
- // Clear any pending timeout
207
- if (this.loadTimeout) {
208
- clearTimeout(this.loadTimeout);
209
- this.loadTimeout = null;
210
- }
211
-
212
- // Remove websocket handlers
213
- SocketHelper.removeHandler("NotificationService-PM");
214
- SocketHelper.removeHandler("NotificationService-Notification");
215
- SocketHelper.removeHandler("NotificationService-MessageUpdate");
216
- SocketHelper.removeHandler("NotificationService-Reconnect");
217
-
218
- // Clear listeners
219
- this.listeners = [];
220
-
221
- // Reset state
222
- this.counts = { notificationCount: 0, pmCount: 0 };
223
- this.currentPersonId = null;
224
- this.isInitialized = false;
225
- }
226
-
227
- /**
228
- * Check if service is initialized
229
- */
230
- isReady(): boolean {
231
- return this.isInitialized && SocketHelper.isConnected();
232
- }
233
- }
@@ -1,62 +0,0 @@
1
- import { PersonInterface, ContactInfoInterface, CommonEnvironmentHelper } from "@churchapps/helpers";
2
- import { Locale } from "./Locale";
3
-
4
- export class PersonHelper {
5
-
6
- static getPhotoUrl(person: PersonInterface) {
7
- if (!person?.photo) return "/images/sample-profile.png"
8
- else return (person?.photo?.startsWith("data:image/png;base64,") || person.photo?.indexOf("://") > -1)
9
- ? person.photo
10
- : CommonEnvironmentHelper.ContentRoot + person.photo;
11
- }
12
-
13
- static getAge(birthdate: Date): string {
14
- if (birthdate !== undefined && birthdate !== null) {
15
- let ageDifMs = Date.now() - new Date(birthdate).getTime();
16
- let ageDate = new Date(ageDifMs);
17
- let years = Math.abs(ageDate.getUTCFullYear() - 1970);
18
- return years + " " + Locale.label("person.years");
19
- }
20
- else return "";
21
- }
22
-
23
- static getDisplayName(firstName: string, lastName: string, nickName: string): string {
24
- if (nickName !== undefined && nickName !== null && nickName.length > 0) return firstName + ' "' + nickName + '" ' + lastName;
25
- else return firstName + " " + lastName;
26
- }
27
-
28
- public static compareAddress(address1: ContactInfoInterface, address2: ContactInfoInterface): boolean {
29
- const displayAddress1: string = this.addressToString(address1).trim();
30
- const displayAddress2: string = this.addressToString(address2).trim();
31
-
32
- if (displayAddress1 !== displayAddress2) {
33
- return true
34
- }
35
- return false
36
- }
37
-
38
- public static addressToString(address: ContactInfoInterface): string {
39
- return `${address.address1 || ""} ${address.address2 || ""} ${address.city || ""}${(address.city && address.state) ? "," : ""} ${address.state || ""} ${address.zip || ""}`
40
- }
41
-
42
- public static changeOnlyAddress(contactInfo1: ContactInfoInterface, contactInfo2: ContactInfoInterface): ContactInfoInterface {
43
- const updatedAddress: ContactInfoInterface = {
44
- ...contactInfo1,
45
- address1: contactInfo2.address1,
46
- address2: contactInfo2.address2,
47
- city: contactInfo2.city,
48
- state: contactInfo2.state,
49
- zip: contactInfo2.zip
50
- }
51
-
52
- return updatedAddress
53
- }
54
-
55
- public static checkAddressAvailabilty(person: PersonInterface): boolean {
56
- const addressString: string = this.addressToString(person.contactInfo).trim();
57
- if (addressString !== "") {
58
- return true;
59
- }
60
- return false;
61
- }
62
- }
@@ -1,27 +0,0 @@
1
- import slug from "slug";
2
-
3
- export class SlugHelper {
4
-
5
- static slugifyString(string: string, type: "urlPath" | "urlSlug", removeCharacters?: string[]) {
6
- const charactersToRemove = removeCharacters ? removeCharacters : ["for", "and", "nor", "but", "or", "yet", "so", "the", "a", "an"];
7
- const characStr = charactersToRemove.join("|");
8
- if (type === "urlPath") {
9
- slug.extend({'/': '/'}); //To keep '/' in the url since it's a special character.
10
- }
11
- const initialSlug = slug(string, { remove: new RegExp('\\b(' + characStr + ')\\b', 'gi') });
12
- const verfiedSlug = this.numerifySlug(initialSlug);
13
- return verfiedSlug;
14
- }
15
-
16
- //remove long sequences of single-digit numbers (e.g., 1-2-3-4 becomes 1), but preserve normal number patterns
17
- static numerifySlug(slug: string) {
18
- let initialString = slug;
19
- // Only match sequences of 3+ single-digit numbers separated by hyphens (e.g., 1-2-3, 1-2-3-4)
20
- // This avoids mangling things like chapter-verse references (6-11) or dates
21
- const regex = /\b(\d)-(\d)-(\d)(?:-\d)*\b/g;
22
- initialString = initialString.replace(regex, "$1");
23
-
24
- return initialString;
25
- }
26
-
27
- }
@@ -1,183 +0,0 @@
1
- import { ConnectionInterface, SocketActionHandlerInterface, SocketPayloadInterface, ApiHelper, ArrayHelper, CommonEnvironmentHelper } from "@churchapps/helpers";
2
-
3
- export class SocketHelper {
4
- static socket: WebSocket;
5
- static socketId: string;
6
- static actionHandlers: SocketActionHandlerInterface[] = [];
7
- private static personIdChurchId: { personId: string, churchId: string } = { personId: "", churchId: "" };
8
- private static isCleanedUp: boolean = false;
9
-
10
- static setPersonChurch = (pc: { personId: string, churchId: string }) => {
11
-
12
- if (pc?.personId && pc.personId && pc.churchId !== this.personIdChurchId.churchId && pc.personId !== this.personIdChurchId.personId) {
13
- this.personIdChurchId = pc;
14
- this.createAlertConnection();
15
- } else {
16
- }
17
- }
18
-
19
- static createAlertConnection = () => {
20
- if (SocketHelper.personIdChurchId.personId && SocketHelper.socketId) {
21
- const connection: ConnectionInterface = {
22
- conversationId: "alerts",
23
- churchId: SocketHelper.personIdChurchId.churchId,
24
- displayName: "Test",
25
- socketId: SocketHelper.socketId,
26
- personId: SocketHelper.personIdChurchId.personId
27
- }
28
-
29
- ApiHelper.postAnonymous("/connections", [connection], "MessagingApi");
30
- }
31
- }
32
-
33
- static init = async () => {
34
- SocketHelper.cleanup();
35
- SocketHelper.isCleanedUp = false;
36
-
37
- if (SocketHelper.socket && SocketHelper.socket.readyState !== SocketHelper.socket.CLOSED) {
38
- try {
39
- SocketHelper.socket.close();
40
- } catch { /* ignore */ }
41
- }
42
-
43
- await new Promise((resolve, reject) => {
44
- try {
45
- SocketHelper.socket = new WebSocket(CommonEnvironmentHelper.MessagingApiSocket);
46
-
47
- SocketHelper.socket.onmessage = (event) => {
48
- if (SocketHelper.isCleanedUp) return;
49
-
50
- try {
51
- const payload = JSON.parse(event.data);
52
- SocketHelper.handleMessage(payload);
53
- } catch { /* ignore parse errors */ }
54
- };
55
-
56
- SocketHelper.socket.onopen = async () => {
57
- SocketHelper.socket.send("getId");
58
-
59
- setTimeout(() => {
60
- resolve(null);
61
- }, 3000);
62
- };
63
-
64
- SocketHelper.socket.onclose = async () => { };
65
-
66
- SocketHelper.socket.onerror = (error) => {
67
- reject(error);
68
- };
69
-
70
- } catch (error) {
71
- reject(error);
72
- }
73
- });
74
- }
75
-
76
- static addHandler = (action: string, id: string, handleMessage: (data: any) => void) => {
77
- const existing = ArrayHelper.getOne(SocketHelper.actionHandlers, "id", id);
78
- if (existing !== null) {
79
- existing.handleMessage = handleMessage;
80
- } else {
81
- SocketHelper.actionHandlers.push({ action, id, handleMessage });
82
- }
83
- }
84
-
85
- static removeHandler = (id: string) => {
86
- SocketHelper.actionHandlers = SocketHelper.actionHandlers.filter(handler => handler.id !== id);
87
- }
88
-
89
- static removeHandlersByAction = (action: string) => {
90
- SocketHelper.actionHandlers = SocketHelper.actionHandlers.filter(handler => handler.action !== action);
91
- }
92
-
93
- static clearAllHandlers = () => {
94
- SocketHelper.actionHandlers = [];
95
- }
96
-
97
- static handleMessage = (payload: SocketPayloadInterface) => {
98
- if (SocketHelper.isCleanedUp) return;
99
-
100
- try {
101
- if (payload.action === "socketId") {
102
- SocketHelper.socketId = payload.data;
103
- SocketHelper.createAlertConnection();
104
- }
105
- else {
106
- const matchingHandlers = ArrayHelper.getAll(SocketHelper.actionHandlers, "action", payload.action);
107
- matchingHandlers.forEach((handler) => {
108
- try {
109
- handler.handleMessage(payload.data);
110
- } catch (error) {
111
- console.error(`Error in handler ${handler.id}:`, error);
112
- }
113
- });
114
- }
115
- } catch (error) {
116
- console.error("Error handling socket message:", error);
117
- }
118
- }
119
-
120
- static cleanup = () => {
121
- SocketHelper.isCleanedUp = true;
122
-
123
- // Close socket connection
124
- if (SocketHelper.socket && SocketHelper.socket.readyState !== SocketHelper.socket.CLOSED) {
125
- try {
126
- SocketHelper.socket.close();
127
- } catch { /* ignore */ }
128
- }
129
-
130
- // Clear references but preserve handlers - they should persist across reconnects
131
- SocketHelper.socket = null;
132
- SocketHelper.socketId = null;
133
- SocketHelper.personIdChurchId = { personId: "", churchId: "" };
134
- }
135
-
136
- static disconnect = () => {
137
- SocketHelper.cleanup();
138
- }
139
-
140
- static isConnected = (): boolean => {
141
- return SocketHelper.socket && SocketHelper.socket.readyState === SocketHelper.socket.OPEN;
142
- }
143
-
144
- static getConnectionState = (): string => {
145
- if (!SocketHelper.socket) return "UNINITIALIZED";
146
-
147
- switch (SocketHelper.socket.readyState) {
148
- case SocketHelper.socket.CONNECTING:
149
- return "CONNECTING";
150
- case SocketHelper.socket.OPEN:
151
- return "OPEN";
152
- case SocketHelper.socket.CLOSING:
153
- return "CLOSING";
154
- case SocketHelper.socket.CLOSED:
155
- return "CLOSED";
156
- default:
157
- return "UNKNOWN";
158
- }
159
- }
160
-
161
- // Global cleanup on window unload
162
- static setupGlobalCleanup = () => {
163
- if (typeof window !== "undefined") {
164
- const cleanup = () => {
165
- SocketHelper.cleanup();
166
- };
167
-
168
- window.addEventListener("beforeunload", cleanup);
169
- window.addEventListener("unload", cleanup);
170
-
171
- // Also cleanup on page visibility change (when tab is closed)
172
- document.addEventListener("visibilitychange", () => {
173
- if (document.visibilityState === "hidden") {
174
- // Optional: cleanup when tab becomes hidden
175
- // SocketHelper.cleanup();
176
- }
177
- });
178
-
179
- return cleanup;
180
- }
181
- }
182
-
183
- }
@@ -1,36 +0,0 @@
1
- export class UniqueIdHelper {
2
-
3
- static chars = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
4
- "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
5
- "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
6
- "-", "_"];
7
-
8
- static alphanumericChars = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
9
- "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
10
- "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];
11
-
12
- public static isMissing(obj: any) {
13
- if (obj === undefined || obj === null) return true;
14
- else if (obj.toString() === "") return true;
15
- else return false;
16
- }
17
-
18
- public static shortId() {
19
- return this.generate(UniqueIdHelper.chars, 11);
20
- }
21
-
22
- public static generateAlphanumeric() {
23
- return this.generate(UniqueIdHelper.alphanumericChars, 11);
24
- }
25
-
26
- public static generate(charList: string[], length: number) {
27
- let result = "";
28
- for (let i = 0; i < length; i++) {
29
- const idx = Math.floor(Math.random() * charList.length);
30
- const c = charList[idx];
31
- result += c;
32
- }
33
- return result;
34
- }
35
-
36
- }
@@ -1,103 +0,0 @@
1
- import { ApiHelper } from "@churchapps/helpers"
2
- import { UserInterface, UserContextInterface, IApiPermission, PersonInterface, LoginUserChurchInterface } from "@churchapps/helpers";
3
-
4
- export class UserHelper {
5
- static currentUserChurch: LoginUserChurchInterface;
6
- static userChurches: LoginUserChurchInterface[];
7
- static user: UserInterface;
8
- static churchChanged: boolean = false;
9
- static person: PersonInterface;
10
-
11
- static selectChurch = async (context?: UserContextInterface, churchId?: string, keyName?: string) => {
12
- let userChurch = null;
13
-
14
- // Ensure userChurches is initialized
15
- if (!UserHelper.userChurches || !Array.isArray(UserHelper.userChurches)) {
16
- console.error('UserHelper.userChurches is not initialized or not an array:', UserHelper.userChurches);
17
- // Try to get userChurches from context if available
18
- if (context?.userChurches && Array.isArray(context.userChurches)) {
19
- UserHelper.userChurches = context.userChurches;
20
- } else {
21
- console.error('Cannot select church: no valid userChurches available');
22
- return;
23
- }
24
- }
25
-
26
- if (churchId) {
27
- UserHelper.userChurches.forEach(uc => {
28
- if (uc.church.id === churchId) userChurch = uc;
29
- });
30
- }
31
- else if (keyName) UserHelper.userChurches.forEach(uc => { if (uc.church.subDomain === keyName) userChurch = uc; });
32
- else userChurch = UserHelper.userChurches[0];
33
- if (!userChurch) return;
34
- else {
35
- UserHelper.currentUserChurch = userChurch;
36
- UserHelper.setupApiHelper(UserHelper.currentUserChurch);
37
- // TODO - remove context code from here and perform the logic in the component itself.
38
- if (context) {
39
- if (context.userChurch !== null) UserHelper.churchChanged = true;
40
- context.setUserChurch(UserHelper.currentUserChurch);
41
-
42
- // Also ensure user is still set in context
43
- if (UserHelper.user && context.setUser) {
44
- context.setUser(UserHelper.user);
45
- }
46
-
47
- // Update person if available
48
- if (UserHelper.person && context.setPerson) {
49
- context.setPerson(UserHelper.person);
50
- }
51
- }
52
- }
53
- }
54
-
55
- static setupApiHelper(userChurch: LoginUserChurchInterface) {
56
- ApiHelper.setDefaultPermissions(userChurch.jwt);
57
- userChurch.apis.forEach(api => { ApiHelper.setPermissions(api.keyName, api.jwt, api.permissions); });
58
- }
59
-
60
- static setupApiHelperNoChurch(user: LoginUserChurchInterface) {
61
- ApiHelper.setDefaultPermissions(user.jwt);
62
- }
63
-
64
- static checkAccess({ api, contentType, action }: IApiPermission): boolean {
65
- const config = ApiHelper.getConfig(api);
66
- if (!config) return false;
67
-
68
- const permissions = config.permissions || [];
69
-
70
- let result = false;
71
- if (permissions !== undefined) {
72
- permissions.forEach((element: any) => {
73
- if (element.contentType === contentType && element.action === action) result = true;
74
- });
75
- }
76
- return result;
77
- }
78
-
79
- static createAppUrl(appUrl: string, returnUrl: string) {
80
- const jwt = ApiHelper.getConfig("MembershipApi")?.jwt;
81
-
82
- if (jwt) {
83
- return `${appUrl}/login/?jwt=${jwt}&returnUrl=${encodeURIComponent(returnUrl)}`;
84
- } else {
85
- return `${appUrl}/login/?returnUrl=${encodeURIComponent(returnUrl)}`;
86
- }
87
- }
88
-
89
- static redirectToLogin(returnUrl?: string, handleRedirect?: (url: string) => void) {
90
- if (typeof window !== "undefined") {
91
- const currentUrl = returnUrl || window.location.pathname + window.location.search;
92
- const encodedReturnUrl = encodeURIComponent(currentUrl);
93
- const loginUrl = `/login?returnUrl=${encodedReturnUrl}`;
94
-
95
- // Use handleRedirect function if available, otherwise fallback to window.location
96
- if (handleRedirect) {
97
- handleRedirect(loginUrl);
98
- } else {
99
- window.location.href = loginUrl;
100
- }
101
- }
102
- }
103
- }
@@ -1,17 +0,0 @@
1
- import createCache from "@emotion/cache";
2
-
3
- const isBrowser = typeof document !== "undefined";
4
-
5
- // On the client side, Create a meta tag at the top of the <head> and set it as insertionPoint.
6
- // This assures that MUI styles are loaded first.
7
- // It allows developers to easily override MUI styles with other styling solutions, like CSS modules.
8
- export function createEmotionCache() {
9
- let insertionPoint;
10
-
11
- if (isBrowser) {
12
- const emotionInsertionPoint = document.querySelector<HTMLMetaElement>('meta[name="emotion-insertion-point"]');
13
- insertionPoint = emotionInsertionPoint ?? undefined;
14
- }
15
-
16
- return createCache({ key: "mui-style", insertionPoint });
17
- }