@churchapps/helpers 1.2.24 → 1.2.26
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/dist/interfaces/Messaging.d.ts +21 -0
- package/dist/interfaces/Messaging.d.ts.map +1 -1
- package/dist/interfaces/Permissions.d.ts +9 -0
- package/dist/interfaces/Permissions.d.ts.map +1 -1
- package/dist/interfaces/Permissions.js +5 -0
- package/dist/interfaces/Permissions.js.map +1 -1
- package/package.json +10 -5
- package/.github/FUNDING.yml +0 -1
- package/.yarnrc.yml +0 -6
- package/eslint.config.js +0 -48
- package/scripts/build-cjs.js +0 -33
- package/src/ApiHelper.ts +0 -169
- package/src/AppearanceHelper.ts +0 -69
- package/src/ArrayHelper.ts +0 -139
- package/src/CommonEnvironmentHelper.ts +0 -104
- package/src/CurrencyHelper.ts +0 -66
- package/src/DateHelper.ts +0 -180
- package/src/DonationHelper.ts +0 -25
- package/src/ErrorHelper.ts +0 -38
- package/src/EventHelper.ts +0 -83
- package/src/FileHelper.ts +0 -57
- package/src/PersonHelper.ts +0 -80
- package/src/PlanHelper.ts +0 -135
- package/src/UniqueIdHelper.ts +0 -159
- package/src/UserHelper.ts +0 -61
- package/src/contentProviders/ContentProvider.ts +0 -15
- package/src/contentProviders/LessonsContentProvider.ts +0 -278
- package/src/contentProviders/index.ts +0 -2
- package/src/index.ts +0 -16
- package/src/interfaces/Access.ts +0 -138
- package/src/interfaces/Attendance.ts +0 -45
- package/src/interfaces/Content.ts +0 -84
- package/src/interfaces/Doing.ts +0 -142
- package/src/interfaces/Donation.ts +0 -193
- package/src/interfaces/Error.ts +0 -17
- package/src/interfaces/Lessons.ts +0 -61
- package/src/interfaces/Membership.ts +0 -184
- package/src/interfaces/Messaging.ts +0 -96
- package/src/interfaces/Permissions.ts +0 -78
- package/src/interfaces/Reporting.ts +0 -41
- package/src/interfaces/UserContextInterface.ts +0 -13
- package/src/interfaces/index.ts +0 -14
- package/tsconfig.json +0 -36
package/src/PlanHelper.ts
DELETED
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
import type { PlanInterface, PlanItemInterface, PlanItemContentInterface } from "./interfaces/index.js";
|
|
2
|
-
import type { ContentProviderInterface } from "./contentProviders/ContentProvider.js";
|
|
3
|
-
import { LessonsContentProvider } from "./contentProviders/LessonsContentProvider.js";
|
|
4
|
-
|
|
5
|
-
export class PlanHelper {
|
|
6
|
-
private static providers: ContentProviderInterface[] = [new LessonsContentProvider()];
|
|
7
|
-
|
|
8
|
-
// Register additional content providers
|
|
9
|
-
static registerProvider(provider: ContentProviderInterface): void {
|
|
10
|
-
// Avoid duplicates
|
|
11
|
-
if (!this.providers.find(p => p.providerId === provider.providerId)) {
|
|
12
|
-
this.providers.push(provider);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Replace a provider (useful for configuring with different URLs)
|
|
17
|
-
static replaceProvider(provider: ContentProviderInterface): void {
|
|
18
|
-
const index = this.providers.findIndex(p => p.providerId === provider.providerId);
|
|
19
|
-
if (index >= 0) {
|
|
20
|
-
this.providers[index] = provider;
|
|
21
|
-
} else {
|
|
22
|
-
this.providers.push(provider);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Main method: populate planItems with their content
|
|
27
|
-
static async populate(
|
|
28
|
-
plan: PlanInterface,
|
|
29
|
-
planItems: PlanItemInterface[]
|
|
30
|
-
): Promise<PlanItemInterface[]> {
|
|
31
|
-
// Flatten hierarchy to get all items
|
|
32
|
-
const allItems = this.flattenItems(planItems);
|
|
33
|
-
|
|
34
|
-
// Group items by provider
|
|
35
|
-
const itemsByProvider = new Map<ContentProviderInterface, PlanItemInterface[]>();
|
|
36
|
-
|
|
37
|
-
for (const item of allItems) {
|
|
38
|
-
for (const provider of this.providers) {
|
|
39
|
-
if (provider.canHandle(plan, item)) {
|
|
40
|
-
const existing = itemsByProvider.get(provider) || [];
|
|
41
|
-
existing.push(item);
|
|
42
|
-
itemsByProvider.set(provider, existing);
|
|
43
|
-
break; // First matching provider wins
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Fetch content from each provider in parallel
|
|
49
|
-
const fetchPromises: Promise<void>[] = [];
|
|
50
|
-
const contentMap = new Map<string, PlanItemContentInterface>();
|
|
51
|
-
|
|
52
|
-
for (const [provider, items] of itemsByProvider) {
|
|
53
|
-
fetchPromises.push(
|
|
54
|
-
provider.fetchContent(plan, items).then(providerContent => {
|
|
55
|
-
for (const [itemId, content] of providerContent) {
|
|
56
|
-
contentMap.set(itemId, content);
|
|
57
|
-
}
|
|
58
|
-
})
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
await Promise.all(fetchPromises);
|
|
63
|
-
|
|
64
|
-
// Attach content to items (mutates in place for efficiency)
|
|
65
|
-
this.attachContent(planItems, contentMap);
|
|
66
|
-
|
|
67
|
-
return planItems;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Flatten nested planItems for processing
|
|
71
|
-
private static flattenItems(items: PlanItemInterface[]): PlanItemInterface[] {
|
|
72
|
-
const result: PlanItemInterface[] = [];
|
|
73
|
-
|
|
74
|
-
const collect = (itemList: PlanItemInterface[]) => {
|
|
75
|
-
for (const item of itemList) {
|
|
76
|
-
result.push(item);
|
|
77
|
-
if (item.children?.length) {
|
|
78
|
-
collect(item.children);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
collect(items);
|
|
84
|
-
return result;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Attach content to items recursively
|
|
88
|
-
private static attachContent(
|
|
89
|
-
items: PlanItemInterface[],
|
|
90
|
-
contentMap: Map<string, PlanItemContentInterface>
|
|
91
|
-
): void {
|
|
92
|
-
for (const item of items) {
|
|
93
|
-
const content = contentMap.get(item.id);
|
|
94
|
-
if (content) {
|
|
95
|
-
item.content = content;
|
|
96
|
-
}
|
|
97
|
-
if (item.children?.length) {
|
|
98
|
-
this.attachContent(item.children, contentMap);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Convenience: Get the lessons provider for direct lesson operations
|
|
104
|
-
static getLessonsProvider(): LessonsContentProvider {
|
|
105
|
-
return this.providers.find(p => p.providerId === "lessons") as LessonsContentProvider;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// ============================================
|
|
109
|
-
// Time Formatting Utilities
|
|
110
|
-
// ============================================
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Format seconds as MM:SS string
|
|
114
|
-
* @param seconds - Number of seconds to format
|
|
115
|
-
* @returns Formatted time string (e.g., "3:45")
|
|
116
|
-
*/
|
|
117
|
-
static formatTime(seconds: number): string {
|
|
118
|
-
const mins = Math.floor(seconds / 60);
|
|
119
|
-
const secs = seconds % 60;
|
|
120
|
-
return mins + ":" + (secs < 10 ? "0" : "") + secs;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Calculate total duration of a section's children
|
|
125
|
-
* @param section - PlanItem with children
|
|
126
|
-
* @returns Total seconds from all children
|
|
127
|
-
*/
|
|
128
|
-
static getSectionDuration(section: PlanItemInterface): number {
|
|
129
|
-
let totalSeconds = 0;
|
|
130
|
-
section.children?.forEach((child) => {
|
|
131
|
-
totalSeconds += child.seconds || 0;
|
|
132
|
-
});
|
|
133
|
-
return totalSeconds;
|
|
134
|
-
}
|
|
135
|
-
}
|
package/src/UniqueIdHelper.ts
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
export class UniqueIdHelper {
|
|
2
|
-
|
|
3
|
-
static chars = [
|
|
4
|
-
"A",
|
|
5
|
-
"B",
|
|
6
|
-
"C",
|
|
7
|
-
"D",
|
|
8
|
-
"E",
|
|
9
|
-
"F",
|
|
10
|
-
"G",
|
|
11
|
-
"H",
|
|
12
|
-
"I",
|
|
13
|
-
"J",
|
|
14
|
-
"K",
|
|
15
|
-
"L",
|
|
16
|
-
"M",
|
|
17
|
-
"N",
|
|
18
|
-
"O",
|
|
19
|
-
"P",
|
|
20
|
-
"Q",
|
|
21
|
-
"R",
|
|
22
|
-
"S",
|
|
23
|
-
"T",
|
|
24
|
-
"U",
|
|
25
|
-
"V",
|
|
26
|
-
"W",
|
|
27
|
-
"X",
|
|
28
|
-
"Y",
|
|
29
|
-
"Z",
|
|
30
|
-
"a",
|
|
31
|
-
"b",
|
|
32
|
-
"c",
|
|
33
|
-
"d",
|
|
34
|
-
"e",
|
|
35
|
-
"f",
|
|
36
|
-
"g",
|
|
37
|
-
"h",
|
|
38
|
-
"i",
|
|
39
|
-
"j",
|
|
40
|
-
"k",
|
|
41
|
-
"l",
|
|
42
|
-
"m",
|
|
43
|
-
"n",
|
|
44
|
-
"o",
|
|
45
|
-
"p",
|
|
46
|
-
"q",
|
|
47
|
-
"r",
|
|
48
|
-
"s",
|
|
49
|
-
"t",
|
|
50
|
-
"u",
|
|
51
|
-
"v",
|
|
52
|
-
"w",
|
|
53
|
-
"x",
|
|
54
|
-
"y",
|
|
55
|
-
"z",
|
|
56
|
-
"0",
|
|
57
|
-
"1",
|
|
58
|
-
"2",
|
|
59
|
-
"3",
|
|
60
|
-
"4",
|
|
61
|
-
"5",
|
|
62
|
-
"6",
|
|
63
|
-
"7",
|
|
64
|
-
"8",
|
|
65
|
-
"9",
|
|
66
|
-
"-",
|
|
67
|
-
"_"
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
static alphanumericChars = [
|
|
71
|
-
"A",
|
|
72
|
-
"B",
|
|
73
|
-
"C",
|
|
74
|
-
"D",
|
|
75
|
-
"E",
|
|
76
|
-
"F",
|
|
77
|
-
"G",
|
|
78
|
-
"H",
|
|
79
|
-
"I",
|
|
80
|
-
"J",
|
|
81
|
-
"K",
|
|
82
|
-
"L",
|
|
83
|
-
"M",
|
|
84
|
-
"N",
|
|
85
|
-
"O",
|
|
86
|
-
"P",
|
|
87
|
-
"Q",
|
|
88
|
-
"R",
|
|
89
|
-
"S",
|
|
90
|
-
"T",
|
|
91
|
-
"U",
|
|
92
|
-
"V",
|
|
93
|
-
"W",
|
|
94
|
-
"X",
|
|
95
|
-
"Y",
|
|
96
|
-
"Z",
|
|
97
|
-
"a",
|
|
98
|
-
"b",
|
|
99
|
-
"c",
|
|
100
|
-
"d",
|
|
101
|
-
"e",
|
|
102
|
-
"f",
|
|
103
|
-
"g",
|
|
104
|
-
"h",
|
|
105
|
-
"i",
|
|
106
|
-
"j",
|
|
107
|
-
"k",
|
|
108
|
-
"l",
|
|
109
|
-
"m",
|
|
110
|
-
"n",
|
|
111
|
-
"o",
|
|
112
|
-
"p",
|
|
113
|
-
"q",
|
|
114
|
-
"r",
|
|
115
|
-
"s",
|
|
116
|
-
"t",
|
|
117
|
-
"u",
|
|
118
|
-
"v",
|
|
119
|
-
"w",
|
|
120
|
-
"x",
|
|
121
|
-
"y",
|
|
122
|
-
"z",
|
|
123
|
-
"0",
|
|
124
|
-
"1",
|
|
125
|
-
"2",
|
|
126
|
-
"3",
|
|
127
|
-
"4",
|
|
128
|
-
"5",
|
|
129
|
-
"6",
|
|
130
|
-
"7",
|
|
131
|
-
"8",
|
|
132
|
-
"9"
|
|
133
|
-
];
|
|
134
|
-
|
|
135
|
-
public static isMissing(obj: any) {
|
|
136
|
-
if (obj === undefined || obj === null) return true;
|
|
137
|
-
else if (obj.toString() === "") return true;
|
|
138
|
-
else return false;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
public static shortId() {
|
|
142
|
-
return this.generate(UniqueIdHelper.chars, 11);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
public static generateAlphanumeric() {
|
|
146
|
-
return this.generate(UniqueIdHelper.alphanumericChars, 11);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
public static generate(charList: string[], length: number) {
|
|
150
|
-
let result = "";
|
|
151
|
-
for (let i = 0; i < length; i++) {
|
|
152
|
-
const idx = Math.floor(Math.random() * charList.length);
|
|
153
|
-
const c = charList[idx];
|
|
154
|
-
result += c;
|
|
155
|
-
}
|
|
156
|
-
return result;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
}
|
package/src/UserHelper.ts
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { ApiHelper } from "./ApiHelper.js";
|
|
2
|
-
import { UserInterface, UserContextInterface, IApiPermission, PersonInterface, LoginUserChurchInterface } from "./interfaces/index.js";
|
|
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
|
-
if (churchId) {
|
|
15
|
-
UserHelper.userChurches.forEach(uc => {
|
|
16
|
-
if (uc.church.id === churchId) userChurch = uc;
|
|
17
|
-
});
|
|
18
|
-
} else if (keyName) UserHelper.userChurches.forEach(uc => { if (uc.church.subDomain === keyName) userChurch = uc; });
|
|
19
|
-
else userChurch = UserHelper.userChurches[0];
|
|
20
|
-
if (!userChurch) return;
|
|
21
|
-
else {
|
|
22
|
-
UserHelper.currentUserChurch = userChurch;
|
|
23
|
-
UserHelper.setupApiHelper(UserHelper.currentUserChurch);
|
|
24
|
-
// TODO - remove context code from here and perform the logic in the component itself.
|
|
25
|
-
if (context) {
|
|
26
|
-
if (context.userChurch !== null) UserHelper.churchChanged = true;
|
|
27
|
-
context.setUserChurch(UserHelper.currentUserChurch);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
static setupApiHelper(userChurch: LoginUserChurchInterface) {
|
|
33
|
-
ApiHelper.setDefaultPermissions(userChurch.jwt);
|
|
34
|
-
userChurch.apis.forEach(api => { ApiHelper.setPermissions(api.keyName, api.jwt, api.permissions); });
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
static setupApiHelperNoChurch(user: LoginUserChurchInterface) {
|
|
38
|
-
ApiHelper.setDefaultPermissions(user.jwt);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
static checkAccess({ api, contentType, action }: IApiPermission): boolean {
|
|
42
|
-
const config = ApiHelper.getConfig(api);
|
|
43
|
-
if (!config) return false;
|
|
44
|
-
const permissions = config.permissions;
|
|
45
|
-
|
|
46
|
-
let result = false;
|
|
47
|
-
if (permissions !== undefined) {
|
|
48
|
-
permissions.forEach(element => {
|
|
49
|
-
if (element.contentType === contentType && element.action === action) result = true;
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
return result;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
static createAppUrl(appUrl: string, returnUrl: string) {
|
|
56
|
-
const config = ApiHelper.getConfig("MembershipApi");
|
|
57
|
-
const jwt = config?.jwt || "";
|
|
58
|
-
|
|
59
|
-
return `${appUrl}/login/?jwt=${jwt}&returnUrl=${returnUrl}`;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { PlanInterface, PlanItemInterface, PlanItemContentInterface } from "../interfaces/index.js";
|
|
2
|
-
|
|
3
|
-
export interface ContentProviderInterface {
|
|
4
|
-
// Unique identifier for this provider
|
|
5
|
-
readonly providerId: string;
|
|
6
|
-
|
|
7
|
-
// Check if this provider handles the given plan/planItem
|
|
8
|
-
canHandle(plan: PlanInterface, planItem: PlanItemInterface): boolean;
|
|
9
|
-
|
|
10
|
-
// Fetch content for multiple planItems (batch for efficiency)
|
|
11
|
-
fetchContent(
|
|
12
|
-
plan: PlanInterface,
|
|
13
|
-
planItems: PlanItemInterface[]
|
|
14
|
-
): Promise<Map<string, PlanItemContentInterface>>;
|
|
15
|
-
}
|
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
import { ApiHelper } from "../ApiHelper.js";
|
|
2
|
-
import type { PlanInterface, PlanItemInterface, PlanItemContentInterface, ExternalVenueRefInterface } from "../interfaces/index.js";
|
|
3
|
-
import type { VenuePlanItemsResponseInterface, VenueActionResponseInterface, LessonTreeInterface, LessonActionTreeInterface } from "../interfaces/Lessons.js";
|
|
4
|
-
import type { ContentProviderInterface } from "./ContentProvider.js";
|
|
5
|
-
|
|
6
|
-
export class LessonsContentProvider implements ContentProviderInterface {
|
|
7
|
-
readonly providerId = "lessons";
|
|
8
|
-
|
|
9
|
-
private lessonsUrl: string;
|
|
10
|
-
|
|
11
|
-
constructor(lessonsUrl: string = "https://lessons.church") {
|
|
12
|
-
this.lessonsUrl = lessonsUrl;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
canHandle(plan: PlanInterface, planItem: PlanItemInterface): boolean {
|
|
16
|
-
// Handles: lessonAction, lessonAddOn, lessonSection, and items with relatedId when plan has lesson
|
|
17
|
-
const lessonTypes = ["lessonAction", "lessonAddOn", "lessonSection"];
|
|
18
|
-
const hasLessonPlan = plan?.contentType === "venue" || plan?.contentType === "externalVenue";
|
|
19
|
-
|
|
20
|
-
if (lessonTypes.includes(planItem.itemType) && planItem.relatedId) return true;
|
|
21
|
-
if (planItem.itemType === "item" && planItem.relatedId && hasLessonPlan) return true;
|
|
22
|
-
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async fetchContent(
|
|
27
|
-
plan: PlanInterface,
|
|
28
|
-
planItems: PlanItemInterface[]
|
|
29
|
-
): Promise<Map<string, PlanItemContentInterface>> {
|
|
30
|
-
const result = new Map<string, PlanItemContentInterface>();
|
|
31
|
-
|
|
32
|
-
// Group by type for efficient batching
|
|
33
|
-
const actions = planItems.filter(p => p.itemType === "lessonAction" && p.relatedId);
|
|
34
|
-
const addOns = planItems.filter(p => p.itemType === "lessonAddOn" && p.relatedId);
|
|
35
|
-
const sections = planItems.filter(p =>
|
|
36
|
-
(p.itemType === "lessonSection" || p.itemType === "item") && p.relatedId);
|
|
37
|
-
|
|
38
|
-
const externalRef = this.getExternalRef(plan);
|
|
39
|
-
|
|
40
|
-
// Build embed URLs for each item
|
|
41
|
-
for (const item of actions) {
|
|
42
|
-
result.set(item.id, {
|
|
43
|
-
provider: this.providerId,
|
|
44
|
-
embedUrl: externalRef
|
|
45
|
-
? `${this.lessonsUrl}/embed/external/${externalRef.externalProviderId}/action/${item.relatedId}`
|
|
46
|
-
: `${this.lessonsUrl}/embed/action/${item.relatedId}`
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
for (const item of addOns) {
|
|
51
|
-
result.set(item.id, {
|
|
52
|
-
provider: this.providerId,
|
|
53
|
-
embedUrl: externalRef
|
|
54
|
-
? `${this.lessonsUrl}/embed/external/${externalRef.externalProviderId}/addon/${item.relatedId}`
|
|
55
|
-
: `${this.lessonsUrl}/embed/addon/${item.relatedId}`
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
for (const item of sections) {
|
|
60
|
-
result.set(item.id, {
|
|
61
|
-
provider: this.providerId,
|
|
62
|
-
embedUrl: externalRef
|
|
63
|
-
? `${this.lessonsUrl}/embed/external/${externalRef.externalProviderId}/section/${item.relatedId}`
|
|
64
|
-
: `${this.lessonsUrl}/embed/section/${item.relatedId}`
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return result;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// ============================================
|
|
72
|
-
// Plan/Lesson Association Methods
|
|
73
|
-
// ============================================
|
|
74
|
-
|
|
75
|
-
hasAssociatedLesson(plan: PlanInterface): boolean {
|
|
76
|
-
return (plan?.contentType === "venue" || plan?.contentType === "externalVenue") && !!plan?.contentId;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
isExternalVenue(plan: PlanInterface): boolean {
|
|
80
|
-
return plan?.contentType === "externalVenue";
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
getExternalRef(plan: PlanInterface): ExternalVenueRefInterface | null {
|
|
84
|
-
if (!this.isExternalVenue(plan) || !plan?.contentId) return null;
|
|
85
|
-
try {
|
|
86
|
-
return JSON.parse(plan.contentId);
|
|
87
|
-
} catch {
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
getVenueId(plan: PlanInterface): string | null {
|
|
93
|
-
if (!this.hasAssociatedLesson(plan)) return null;
|
|
94
|
-
if (this.isExternalVenue(plan)) {
|
|
95
|
-
return this.getExternalRef(plan)?.venueId || null;
|
|
96
|
-
}
|
|
97
|
-
return plan.contentId || null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// ============================================
|
|
101
|
-
// API Fetch Methods
|
|
102
|
-
// ============================================
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Fetch venue plan items - the basic hierarchical structure
|
|
106
|
-
* Returns: headers with children (sections), but sections don't have their actions
|
|
107
|
-
* Use this for preview mode display
|
|
108
|
-
*/
|
|
109
|
-
async fetchVenuePlanItems(plan: PlanInterface): Promise<VenuePlanItemsResponseInterface> {
|
|
110
|
-
if (!this.hasAssociatedLesson(plan)) return { items: [] };
|
|
111
|
-
const externalRef = this.getExternalRef(plan);
|
|
112
|
-
if (externalRef) {
|
|
113
|
-
return await ApiHelper.getAnonymous(
|
|
114
|
-
`/externalProviders/${externalRef.externalProviderId}/venue/${externalRef.venueId}/planItems`,
|
|
115
|
-
"LessonsApi"
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
return await ApiHelper.getAnonymous(`/venues/public/planItems/${plan.contentId}`, "LessonsApi");
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Fetch venue actions - sections with their full action lists
|
|
123
|
-
* Use this for action selection dialogs and full expansion
|
|
124
|
-
*/
|
|
125
|
-
async fetchVenueActions(plan: PlanInterface): Promise<VenueActionResponseInterface> {
|
|
126
|
-
if (!this.hasAssociatedLesson(plan)) return { sections: [] };
|
|
127
|
-
const externalRef = this.getExternalRef(plan);
|
|
128
|
-
if (externalRef) {
|
|
129
|
-
return await ApiHelper.getAnonymous(
|
|
130
|
-
`/externalProviders/${externalRef.externalProviderId}/venue/${externalRef.venueId}/actions`,
|
|
131
|
-
"LessonsApi"
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
return await ApiHelper.getAnonymous(`/venues/public/actions/${plan.contentId}`, "LessonsApi");
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Fetch the full lesson tree for browsing (programs -> studies -> lessons -> venues)
|
|
139
|
-
*/
|
|
140
|
-
async fetchLessonTree(): Promise<LessonTreeInterface> {
|
|
141
|
-
return await ApiHelper.getAnonymous("/lessons/public/tree", "LessonsApi");
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* Fetch the action tree for action selection (includes actions in each venue section)
|
|
146
|
-
*/
|
|
147
|
-
async fetchActionTree(): Promise<LessonActionTreeInterface> {
|
|
148
|
-
return await ApiHelper.getAnonymous("/lessons/public/actionTree", "LessonsApi");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// ============================================
|
|
152
|
-
// Display List Methods (for preview/display without full actions)
|
|
153
|
-
// ============================================
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Get the display list - hierarchical items suitable for preview
|
|
157
|
-
* Structure: headers -> sections (no actions expanded)
|
|
158
|
-
* This is the lightweight version for showing what a lesson contains
|
|
159
|
-
*/
|
|
160
|
-
async getDisplayList(plan: PlanInterface): Promise<PlanItemInterface[]> {
|
|
161
|
-
const response = await this.fetchVenuePlanItems(plan);
|
|
162
|
-
return response?.items || [];
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Get display list with sections only (strip actions from children)
|
|
167
|
-
* Use this when importing a lesson as editable plan items
|
|
168
|
-
*/
|
|
169
|
-
async getSectionsOnlyList(plan: PlanInterface): Promise<PlanItemInterface[]> {
|
|
170
|
-
const response = await this.fetchVenuePlanItems(plan);
|
|
171
|
-
if (!response?.items) return [];
|
|
172
|
-
|
|
173
|
-
return response.items.map(item => ({
|
|
174
|
-
...item,
|
|
175
|
-
children: item.children?.map(section => ({
|
|
176
|
-
...section,
|
|
177
|
-
children: undefined // Remove actions from sections
|
|
178
|
-
}))
|
|
179
|
-
}));
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// ============================================
|
|
183
|
-
// Expanded List Methods (with full actions)
|
|
184
|
-
// ============================================
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Get the fully expanded list - items with all actions populated in sections
|
|
188
|
-
* Merges fetchVenuePlanItems with fetchVenueActions to get complete data
|
|
189
|
-
*/
|
|
190
|
-
async getExpandedList(plan: PlanInterface): Promise<PlanItemInterface[]> {
|
|
191
|
-
const [planItemsResponse, actionsResponse] = await Promise.all([
|
|
192
|
-
this.fetchVenuePlanItems(plan),
|
|
193
|
-
this.fetchVenueActions(plan)
|
|
194
|
-
]);
|
|
195
|
-
|
|
196
|
-
if (!planItemsResponse?.items) return [];
|
|
197
|
-
|
|
198
|
-
// Create a map of section ID -> actions
|
|
199
|
-
const sectionActionsMap = new Map<string, PlanItemInterface[]>();
|
|
200
|
-
if (actionsResponse?.sections) {
|
|
201
|
-
for (const section of actionsResponse.sections) {
|
|
202
|
-
if (section.id && section.actions) {
|
|
203
|
-
sectionActionsMap.set(section.id, section.actions.map(action => ({
|
|
204
|
-
itemType: "lessonAction",
|
|
205
|
-
relatedId: action.id,
|
|
206
|
-
label: action.name,
|
|
207
|
-
description: action.actionType,
|
|
208
|
-
seconds: action.seconds
|
|
209
|
-
})));
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Recursively expand sections with their actions
|
|
215
|
-
const expandItem = (item: PlanItemInterface): PlanItemInterface => {
|
|
216
|
-
if (!item.children) return item;
|
|
217
|
-
|
|
218
|
-
return {
|
|
219
|
-
...item,
|
|
220
|
-
children: item.children.map(child => {
|
|
221
|
-
// If this is a section (has relatedId), try to get its actions
|
|
222
|
-
if (child.relatedId && sectionActionsMap.has(child.relatedId)) {
|
|
223
|
-
return {
|
|
224
|
-
...child,
|
|
225
|
-
children: sectionActionsMap.get(child.relatedId)
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
// Otherwise recursively process
|
|
229
|
-
return expandItem(child);
|
|
230
|
-
})
|
|
231
|
-
};
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
return planItemsResponse.items.map(expandItem);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// ============================================
|
|
238
|
-
// Embed URL Helpers
|
|
239
|
-
// ============================================
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Get embed URL for an action
|
|
243
|
-
*/
|
|
244
|
-
getActionEmbedUrl(actionId: string, externalProviderId?: string): string {
|
|
245
|
-
if (externalProviderId) {
|
|
246
|
-
return `${this.lessonsUrl}/embed/external/${externalProviderId}/action/${actionId}`;
|
|
247
|
-
}
|
|
248
|
-
return `${this.lessonsUrl}/embed/action/${actionId}`;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Get embed URL for an add-on
|
|
253
|
-
*/
|
|
254
|
-
getAddOnEmbedUrl(addOnId: string, externalProviderId?: string): string {
|
|
255
|
-
if (externalProviderId) {
|
|
256
|
-
return `${this.lessonsUrl}/embed/external/${externalProviderId}/addon/${addOnId}`;
|
|
257
|
-
}
|
|
258
|
-
return `${this.lessonsUrl}/embed/addon/${addOnId}`;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Get embed URL for a section
|
|
263
|
-
*/
|
|
264
|
-
getSectionEmbedUrl(sectionId: string, externalProviderId?: string): string {
|
|
265
|
-
if (externalProviderId) {
|
|
266
|
-
return `${this.lessonsUrl}/embed/external/${externalProviderId}/section/${sectionId}`;
|
|
267
|
-
}
|
|
268
|
-
return `${this.lessonsUrl}/embed/section/${sectionId}`;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Get the external provider ID from a plan (if external)
|
|
273
|
-
*/
|
|
274
|
-
getExternalProviderId(plan: PlanInterface): string | null {
|
|
275
|
-
const externalRef = this.getExternalRef(plan);
|
|
276
|
-
return externalRef?.externalProviderId || null;
|
|
277
|
-
}
|
|
278
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export * from "./interfaces/index.js";
|
|
2
|
-
export { ApiHelper } from "./ApiHelper.js";
|
|
3
|
-
export { AppearanceHelper } from "./AppearanceHelper.js";
|
|
4
|
-
export { ArrayHelper } from "./ArrayHelper.js";
|
|
5
|
-
export { CommonEnvironmentHelper } from "./CommonEnvironmentHelper.js";
|
|
6
|
-
export { CurrencyHelper } from "./CurrencyHelper.js";
|
|
7
|
-
export { DateHelper } from "./DateHelper.js";
|
|
8
|
-
export { DonationHelper } from "./DonationHelper.js";
|
|
9
|
-
export { ErrorHelper } from "./ErrorHelper.js";
|
|
10
|
-
export { EventHelper } from "./EventHelper.js";
|
|
11
|
-
export { FileHelper } from "./FileHelper.js";
|
|
12
|
-
export { PersonHelper } from "./PersonHelper.js";
|
|
13
|
-
export { UserHelper } from "./UserHelper.js";
|
|
14
|
-
export { UniqueIdHelper } from "./UniqueIdHelper.js";
|
|
15
|
-
export { PlanHelper } from "./PlanHelper.js";
|
|
16
|
-
export * from "./contentProviders/index.js";
|