Skip to content

Commit 38b6c90

Browse files
committed
Don't require admin access for plans
1 parent 5a48a3a commit 38b6c90

File tree

3 files changed

+27
-21
lines changed

3 files changed

+27
-21
lines changed

src/components/Header.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const Header: React.FC = () => {
1212
const formPermission = UserHelper.checkAccess(Permissions.membershipApi.forms.admin) || UserHelper.checkAccess(Permissions.membershipApi.forms.edit);
1313
const [donationError, setDonationError] = React.useState<boolean>(false);
1414
const [isFormMember, setIsFormMember] = React.useState<boolean>(false);
15+
const [isMinistryMember, setIsMinistryMember] = React.useState<boolean>(false);
1516

1617
useEffect(() => {
1718
if (UserHelper.checkAccess(Permissions.givingApi.donations.viewSummary)) {
@@ -23,6 +24,10 @@ export const Header: React.FC = () => {
2324
if (!formPermission && context?.person?.id) {
2425
ApiHelper.get("/memberpermissions/member/" + context.person?.id, "MembershipApi").then((data) => setIsFormMember(data?.length > 0));
2526
}
27+
28+
if (!UserHelper.checkAccess(Permissions.membershipApi.plans.edit)) {
29+
ApiHelper.get("/groups/my/ministry", "MembershipApi").then((data) => setIsMinistryMember(data?.length > 0));
30+
}
2631
}, [formPermission, context?.person?.id]);
2732

2833
const primaryMenu = useMemo(() => {
@@ -32,7 +37,8 @@ export const Header: React.FC = () => {
3237
if (UserHelper.checkAccess(Permissions.membershipApi.people.view)) menuItems.push({ url: "/people", icon: "person", label: Locale.label("components.wrapper.ppl") });
3338
if (UserHelper.checkAccess(Permissions.givingApi.donations.viewSummary)) menuItems.push({ url: "/donations", label: Locale.label("components.wrapper.don"), icon: donationIcon });
3439

35-
if (UserHelper.checkAccess(Permissions.membershipApi.plans.edit)) menuItems.push({ url: "/serving", label: Locale.label("components.wrapper.serving"), icon: "assignment" });
40+
const canViewPlans = UserHelper.checkAccess(Permissions.membershipApi.plans.edit) || isMinistryMember;
41+
if (canViewPlans) menuItems.push({ url: "/serving", label: Locale.label("components.wrapper.serving"), icon: "assignment" });
3642
else menuItems.push({ url: "/serving/tasks", label: Locale.label("components.wrapper.serving"), icon: "assignment" });
3743

3844
// Temporarily hidden
@@ -44,7 +50,7 @@ export const Header: React.FC = () => {
4450
else if (formPermission || isFormMember) menuItems.push({ url: "/forms", label: Locale.label("components.wrapper.set"), icon: "settings" });
4551
// if (UserHelper.checkAccess(Permissions.membershipApi.server.admin)) tabs.push(<NavItem key="/admin" url="/admin" label={Locale.label("components.wrapper.servAdmin")} icon="admin_panel_settings" selected={selectedTab === "admin"} />);
4652
return menuItems;
47-
}, [donationError, formPermission, isFormMember]);
53+
}, [donationError, formPermission, isFormMember, isMinistryMember]);
4854
/*
4955
const getSecondaryMenu = () => {
5056
const menuItems:{ url: string, label: string }[] = []
@@ -70,7 +76,7 @@ export const Header: React.FC = () => {
7076
return result;
7177
};
7278

73-
const secondaryMenu = SecondaryMenuHelper.getSecondaryMenu(window.location.pathname, { formPermission, search: window.location.search });
79+
const secondaryMenu = SecondaryMenuHelper.getSecondaryMenu(window.location.pathname, { formPermission, search: window.location.search, isMinistryMember });
7480

7581
const handleNavigate = (url: string) => {
7682
navigate(url);

src/helpers/SecondaryMenuHelper.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export class SecondaryMenuHelper {
1313
if (path.startsWith("/people") || path.startsWith("/groups") || path.startsWith("/attendance")) result = this.getPeopleMenu(path, data.search);
1414
else if (path.startsWith("/mobile")) result = this.getMobileMenu(path);
1515
else if (path.startsWith("/settings") || path.startsWith("/admin") || path.startsWith("/forms")) result = this.getSettingsMenu(path, data);
16-
else if (path.startsWith("/serving")) result = this.getServingMenu(path);
16+
else if (path.startsWith("/serving")) result = this.getServingMenu(path, data);
1717
else if (path.startsWith("/donations")) result = this.getDonationsMenu(path);
1818
else if (path.startsWith("/site") || path.startsWith("/calendars") || path.startsWith("/registrations")) result = this.getSiteMenu(path);
1919
else if (path.startsWith("/sermons")) result = this.getSermonsMenu(path);
@@ -26,7 +26,7 @@ export class SecondaryMenuHelper {
2626
const menuItems: MenuItem[] = [];
2727
let label: string = "";
2828
menuItems.push({ url: "/groups", label: Locale.label("components.wrapper.groups"), icon: "groups" });
29-
if (UserHelper.checkAccess(Permissions.membershipApi.plans.edit)) menuItems.push({ url: "/serving", label: Locale.label("components.wrapper.teams"), icon: "people" });
29+
if (UserHelper.checkAccess(Permissions.membershipApi.plans.edit) || data?.isMinistryMember) menuItems.push({ url: "/serving", label: Locale.label("components.wrapper.teams"), icon: "people" });
3030
menuItems.push({ url: "/people", label: Locale.label("components.wrapper.ppl"), icon: "person" });
3131
if (UserHelper.checkAccess(Permissions.attendanceApi.attendance.viewSummary)) menuItems.push({ url: "/attendance", label: Locale.label("components.wrapper.att"), icon: "calendar_month" });
3232

@@ -77,10 +77,11 @@ export class SecondaryMenuHelper {
7777
return { menuItems, label };
7878
};
7979

80-
static getServingMenu = (path: string) => {
80+
static getServingMenu = (path: string, data?: any) => {
8181
const menuItems: MenuItem[] = [];
8282
let label: string = "";
83-
if (UserHelper.checkAccess(Permissions.membershipApi.plans.edit)) {
83+
const canViewPlans = UserHelper.checkAccess(Permissions.membershipApi.plans.edit) || data?.isMinistryMember;
84+
if (canViewPlans) {
8485
menuItems.push({ url: "/serving", label: Locale.label("components.wrapper.plans"), icon: "assignment" });
8586
menuItems.push({ url: "/serving/songs", label: Locale.label("components.wrapper.songs"), icon: "music_note" });
8687
}

src/serving/ServingPage.tsx

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,21 @@ export const ServingPage = () => {
1717
const [selectedMinistryId, setSelectedMinistryId] = React.useState<string | null>(null);
1818
const [showAllMinistries, setShowAllMinistries] = React.useState(false);
1919
const context = React.useContext(UserContext);
20-
20+
const isAdmin = UserHelper.checkAccess(Permissions.membershipApi.roles.edit);
21+
2122
const ministries = useQuery<GroupInterface[]>({
22-
queryKey: ["/groups/tag/ministry", "MembershipApi"],
23+
queryKey: isAdmin ? ["/groups/tag/ministry", "MembershipApi"] : ["/groups/my/ministry", "MembershipApi"],
2324
placeholderData: []
2425
});
2526

2627
const groupIds = React.useMemo(() => {
2728
return ministries.data && ministries.data.length > 0 ? ArrayHelper.getIds(ministries.data, "id") : [];
2829
}, [ministries.data]);
2930

31+
// Only admins need group members (for membership filtering and Show All toggle)
3032
const groupMembers = useQuery<GroupMemberInterface[]>({
3133
queryKey: ["/groupMembers", "MembershipApi", groupIds],
32-
enabled: groupIds.length > 0,
34+
enabled: isAdmin && groupIds.length > 0,
3335
placeholderData: [],
3436
queryFn: async () => {
3537
if (groupIds.length === 0) return [];
@@ -47,17 +49,14 @@ export const ServingPage = () => {
4749

4850
if (ministries.isLoading) return <Loading />;
4951

50-
// Admins: Ministries where they're a member OR ministries with no members (to prevent orphaning)
51-
// Regular users: Ministries where they're a member
52-
// Domain Admins: Can toggle to see all ministries
53-
const isAdmin = UserHelper.checkAccess(Permissions.membershipApi.roles.edit);
54-
const groups = (ministries.data || []).filter((g) => {
55-
if (isAdmin && showAllMinistries) return true;
56-
const members = ArrayHelper.getAll(groupMembers.data || [], "groupId", g.id);
57-
const isMember = ArrayHelper.getOne(members, "personId", context.person?.id) !== null;
58-
if (isAdmin) return isMember || members.length === 0;
59-
return isMember;
60-
});
52+
const groups = isAdmin
53+
? (ministries.data || []).filter((g) => {
54+
if (showAllMinistries) return true;
55+
const members = ArrayHelper.getAll(groupMembers.data || [], "groupId", g.id);
56+
const isMember = ArrayHelper.getOne(members, "personId", context.person?.id) !== null;
57+
return isMember || members.length === 0;
58+
})
59+
: (ministries.data || []);
6160

6261
const selectedMinistry = groups.find((g) => g.id === selectedMinistryId);
6362

0 commit comments

Comments
 (0)