placementt-core 1.400.1014 → 1.400.1015
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/lib/productResolver.d.ts +8 -10
- package/lib/productResolver.js +28 -4
- package/lib/productResolver.js.map +1 -1
- package/package.json +1 -1
- package/src/productResolver.ts +35 -13
- package/src/productResolver.test.ts +0 -156
package/lib/productResolver.d.ts
CHANGED
|
@@ -9,17 +9,12 @@ import { InstituteData } from "./typeDefinitions";
|
|
|
9
9
|
* Three of those are also sub-flags that only apply when `employerEvents` (or the
|
|
10
10
|
* careersHub package) is switched on.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
* the
|
|
14
|
-
*
|
|
15
|
-
* skills on their dashboard that staff could not see on their profile. Wex was
|
|
16
|
-
* opt-in for staff (`workExperience &&`) and opt-out for students (`!== false`).
|
|
17
|
-
*
|
|
18
|
-
* This is the single answer. Nav, home, student surfaces and the backend all read
|
|
19
|
-
* it, so they cannot disagree about what a customer bought. Dependency-free.
|
|
12
|
+
* `parents` has no flag at all — a school has a parent database when there are
|
|
13
|
+
* parents in it — so this is a hook: the count is a query, and the answer arrives
|
|
14
|
+
* a tick after the flags do.
|
|
20
15
|
*/
|
|
21
16
|
/** The product a surface can gate on. */
|
|
22
|
-
export type ProductKey = "wex" | "network" | "events" | "skills" | "activities" | "destinations" | "alumni";
|
|
17
|
+
export type ProductKey = "wex" | "network" | "parents" | "events" | "skills" | "activities" | "destinations" | "alumni";
|
|
23
18
|
export type ResolvedProducts = Record<ProductKey, boolean> & {
|
|
24
19
|
/** Package shape, so callers stop testing `package ===` themselves. */
|
|
25
20
|
isTrust: boolean;
|
|
@@ -41,12 +36,15 @@ export type ProductResolverInput = Partial<Pick<InstituteData, "package" | "work
|
|
|
41
36
|
*
|
|
42
37
|
* @param {ProductResolverInput} [institute] the institute, or a partial of it.
|
|
43
38
|
* @param {object} [options] extra context.
|
|
39
|
+
* @param {string[]} [options.oIds] whose parent database to count. A trust holds
|
|
40
|
+
* none on its own oId, so pass its schools'.
|
|
44
41
|
* @param {ProductResolverInput[]} [options.trustSchools] schools beneath a trust.
|
|
45
42
|
* A trust shows a product when any of its schools has it, matching the nav's
|
|
46
43
|
* existing destinations rule.
|
|
47
44
|
* @return {ResolvedProducts} what this institute has.
|
|
48
45
|
*/
|
|
49
|
-
export declare function
|
|
46
|
+
export declare function useProductResolver(institute?: ProductResolverInput, options?: {
|
|
47
|
+
oIds?: string[];
|
|
50
48
|
trustSchools?: ProductResolverInput[];
|
|
51
49
|
}): ResolvedProducts;
|
|
52
50
|
/** Human labels, for checklists, settings and the trust product strip. */
|
package/lib/productResolver.js
CHANGED
|
@@ -1,21 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.PRODUCT_LABELS = void 0;
|
|
4
|
-
exports.
|
|
5
|
-
const
|
|
7
|
+
exports.useProductResolver = useProductResolver;
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const firestore_1 = require("firebase/firestore");
|
|
10
|
+
const firebaseQuery_1 = __importDefault(require("./firebase/firebaseQuery"));
|
|
11
|
+
const PRODUCT_ORDER = ["wex", "destinations", "events", "skills", "activities", "network", "parents", "alumni"];
|
|
6
12
|
/** Opt-out flag: undefined means on, only an explicit `false` switches it off. */
|
|
7
13
|
const on = (flag) => flag !== false;
|
|
14
|
+
const firebaseQuery = new firebaseQuery_1.default();
|
|
8
15
|
/**
|
|
9
16
|
* Resolve an institute's products.
|
|
10
17
|
*
|
|
11
18
|
* @param {ProductResolverInput} [institute] the institute, or a partial of it.
|
|
12
19
|
* @param {object} [options] extra context.
|
|
20
|
+
* @param {string[]} [options.oIds] whose parent database to count. A trust holds
|
|
21
|
+
* none on its own oId, so pass its schools'.
|
|
13
22
|
* @param {ProductResolverInput[]} [options.trustSchools] schools beneath a trust.
|
|
14
23
|
* A trust shows a product when any of its schools has it, matching the nav's
|
|
15
24
|
* existing destinations rule.
|
|
16
25
|
* @return {ResolvedProducts} what this institute has.
|
|
17
26
|
*/
|
|
18
|
-
function
|
|
27
|
+
function useProductResolver(institute, options) {
|
|
28
|
+
const [parentCount, setParentCount] = (0, react_1.useState)(0);
|
|
29
|
+
const oIds = options?.oIds || [];
|
|
30
|
+
const scope = oIds.join(",");
|
|
31
|
+
(0, react_1.useEffect)(() => {
|
|
32
|
+
if (!oIds.length) {
|
|
33
|
+
setParentCount(0);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
Promise.all(oIds.map((o) => firebaseQuery.getCount(["parents"], [(0, firestore_1.where)("oId", "==", o)])))
|
|
37
|
+
.then((counts) => setParentCount(counts.reduce((t, c) => t + c, 0)))
|
|
38
|
+
.catch(() => setParentCount(0));
|
|
39
|
+
}, [scope]);
|
|
19
40
|
const i = institute || {};
|
|
20
41
|
const pkg = i.package;
|
|
21
42
|
const isTrust = pkg === "institutes-two";
|
|
@@ -39,10 +60,12 @@ function resolveProduct(institute, options) {
|
|
|
39
60
|
// Opt-out and ungated: every institute gets the employer network unless it is
|
|
40
61
|
// explicitly switched off. Matches Institutes.tsx and the staff home today.
|
|
41
62
|
const network = on(i.network);
|
|
63
|
+
// No flag: the database exists if anyone is in it.
|
|
64
|
+
const parents = parentCount > 0;
|
|
42
65
|
const hubIds = Object.entries(i.careersHubLinks || {})
|
|
43
66
|
.filter(([, link]) => link?.status === "approved")
|
|
44
67
|
.map(([oId]) => oId);
|
|
45
|
-
const products = { wex, network, events, skills, activities, destinations, alumni };
|
|
68
|
+
const products = { wex, network, parents, events, skills, activities, destinations, alumni };
|
|
46
69
|
return {
|
|
47
70
|
...products,
|
|
48
71
|
isTrust,
|
|
@@ -61,6 +84,7 @@ exports.PRODUCT_LABELS = {
|
|
|
61
84
|
skills: "Skills",
|
|
62
85
|
activities: "Activities",
|
|
63
86
|
network: "Employer network",
|
|
87
|
+
parents: "Parent database",
|
|
64
88
|
alumni: "Alumni",
|
|
65
89
|
};
|
|
66
90
|
//# sourceMappingURL=productResolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"productResolver.js","sourceRoot":"","sources":["../src/productResolver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"productResolver.js","sourceRoot":"","sources":["../src/productResolver.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/productResolver.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {useEffect, useState} from "react";
|
|
2
|
+
import {where} from "firebase/firestore";
|
|
3
|
+
import FirebaseQuery from "./firebase/firebaseQuery";
|
|
1
4
|
import {InstituteData} from "./typeDefinitions";
|
|
2
5
|
|
|
3
6
|
/**
|
|
@@ -10,19 +13,14 @@ import {InstituteData} from "./typeDefinitions";
|
|
|
10
13
|
* Three of those are also sub-flags that only apply when `employerEvents` (or the
|
|
11
14
|
* careersHub package) is switched on.
|
|
12
15
|
*
|
|
13
|
-
*
|
|
14
|
-
* the
|
|
15
|
-
*
|
|
16
|
-
* skills on their dashboard that staff could not see on their profile. Wex was
|
|
17
|
-
* opt-in for staff (`workExperience &&`) and opt-out for students (`!== false`).
|
|
18
|
-
*
|
|
19
|
-
* This is the single answer. Nav, home, student surfaces and the backend all read
|
|
20
|
-
* it, so they cannot disagree about what a customer bought. Dependency-free.
|
|
16
|
+
* `parents` has no flag at all — a school has a parent database when there are
|
|
17
|
+
* parents in it — so this is a hook: the count is a query, and the answer arrives
|
|
18
|
+
* a tick after the flags do.
|
|
21
19
|
*/
|
|
22
20
|
|
|
23
21
|
/** The product a surface can gate on. */
|
|
24
22
|
export type ProductKey =
|
|
25
|
-
"wex"|"network"|"events"|"skills"|"activities"|"destinations"|"alumni";
|
|
23
|
+
"wex"|"network"|"parents"|"events"|"skills"|"activities"|"destinations"|"alumni";
|
|
26
24
|
|
|
27
25
|
export type ResolvedProducts = Record<ProductKey, boolean> & {
|
|
28
26
|
/** Package shape, so callers stop testing `package ===` themselves. */
|
|
@@ -46,25 +44,45 @@ export type ProductResolverInput = Partial<Pick<InstituteData,
|
|
|
46
44
|
"alumniManagement"|"careersHubLinks">>;
|
|
47
45
|
|
|
48
46
|
const PRODUCT_ORDER: ProductKey[] =
|
|
49
|
-
["wex", "destinations", "events", "skills", "activities", "network", "alumni"];
|
|
47
|
+
["wex", "destinations", "events", "skills", "activities", "network", "parents", "alumni"];
|
|
50
48
|
|
|
51
49
|
/** Opt-out flag: undefined means on, only an explicit `false` switches it off. */
|
|
52
50
|
const on = (flag?: boolean) => flag !== false;
|
|
53
51
|
|
|
52
|
+
const firebaseQuery = new FirebaseQuery();
|
|
53
|
+
|
|
54
54
|
/**
|
|
55
55
|
* Resolve an institute's products.
|
|
56
56
|
*
|
|
57
57
|
* @param {ProductResolverInput} [institute] the institute, or a partial of it.
|
|
58
58
|
* @param {object} [options] extra context.
|
|
59
|
+
* @param {string[]} [options.oIds] whose parent database to count. A trust holds
|
|
60
|
+
* none on its own oId, so pass its schools'.
|
|
59
61
|
* @param {ProductResolverInput[]} [options.trustSchools] schools beneath a trust.
|
|
60
62
|
* A trust shows a product when any of its schools has it, matching the nav's
|
|
61
63
|
* existing destinations rule.
|
|
62
64
|
* @return {ResolvedProducts} what this institute has.
|
|
63
65
|
*/
|
|
64
|
-
export function
|
|
66
|
+
export function useProductResolver(
|
|
65
67
|
institute?: ProductResolverInput,
|
|
66
|
-
options?: {trustSchools?: ProductResolverInput[]},
|
|
68
|
+
options?: {oIds?: string[], trustSchools?: ProductResolverInput[]},
|
|
67
69
|
): ResolvedProducts {
|
|
70
|
+
const [parentCount, setParentCount] = useState(0);
|
|
71
|
+
|
|
72
|
+
const oIds = options?.oIds || [];
|
|
73
|
+
const scope = oIds.join(",");
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (!oIds.length) {
|
|
77
|
+
setParentCount(0);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
Promise.all(oIds.map((o) =>
|
|
81
|
+
firebaseQuery.getCount(["parents"], [where("oId", "==", o)])))
|
|
82
|
+
.then((counts) => setParentCount(counts.reduce((t, c) => t + c, 0)))
|
|
83
|
+
.catch(() => setParentCount(0));
|
|
84
|
+
}, [scope]);
|
|
85
|
+
|
|
68
86
|
const i = institute || {};
|
|
69
87
|
const pkg = i.package;
|
|
70
88
|
|
|
@@ -115,12 +133,15 @@ export function resolveProduct(
|
|
|
115
133
|
// explicitly switched off. Matches Institutes.tsx and the staff home today.
|
|
116
134
|
const network = on(i.network);
|
|
117
135
|
|
|
136
|
+
// No flag: the database exists if anyone is in it.
|
|
137
|
+
const parents = parentCount > 0;
|
|
138
|
+
|
|
118
139
|
const hubIds = Object.entries(i.careersHubLinks || {})
|
|
119
140
|
.filter(([, link]) => link?.status === "approved")
|
|
120
141
|
.map(([oId]) => oId);
|
|
121
142
|
|
|
122
143
|
const products: Record<ProductKey, boolean> =
|
|
123
|
-
{wex, network, events, skills, activities, destinations, alumni};
|
|
144
|
+
{wex, network, parents, events, skills, activities, destinations, alumni};
|
|
124
145
|
|
|
125
146
|
return {
|
|
126
147
|
...products,
|
|
@@ -141,5 +162,6 @@ export const PRODUCT_LABELS: Record<ProductKey, string> = {
|
|
|
141
162
|
skills: "Skills",
|
|
142
163
|
activities: "Activities",
|
|
143
164
|
network: "Employer network",
|
|
165
|
+
parents: "Parent database",
|
|
144
166
|
alumni: "Alumni",
|
|
145
167
|
};
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import {resolveProduct} from "./productResolver";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The defaults are the point of these tests. Four flags are opt-out, so a refactor
|
|
5
|
-
* that "tidies" `!== false` into a truthy check would silently switch four products
|
|
6
|
-
* off for every institute that has never touched the toggle — which is most of them.
|
|
7
|
-
*/
|
|
8
|
-
describe("resolveProduct", () => {
|
|
9
|
-
describe("opt-out defaults", () => {
|
|
10
|
-
it("gives a bare institute the employer network", () => {
|
|
11
|
-
expect(resolveProduct({package: "institutes-one"}).network).toBe(true);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it("switches the network off only on an explicit false", () => {
|
|
15
|
-
expect(resolveProduct({network: false}).network).toBe(false);
|
|
16
|
-
expect(resolveProduct({network: undefined}).network).toBe(true);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it("turns on events, skills and activities when employerEvents is set and the sub-flags are undefined", () => {
|
|
20
|
-
const p = resolveProduct({package: "institutes-one", employerEvents: true});
|
|
21
|
-
expect(p.events).toBe(true);
|
|
22
|
-
expect(p.skills).toBe(true);
|
|
23
|
-
expect(p.activities).toBe(true);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("lets each sub-flag be switched off independently", () => {
|
|
27
|
-
const p = resolveProduct({
|
|
28
|
-
package: "institutes-one",
|
|
29
|
-
employerEvents: true,
|
|
30
|
-
careersEvents: false,
|
|
31
|
-
trackExtracurriculars: false,
|
|
32
|
-
});
|
|
33
|
-
expect(p.events).toBe(false);
|
|
34
|
-
expect(p.activities).toBe(false);
|
|
35
|
-
expect(p.skills).toBe(true);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
describe("sub-flags need their parent", () => {
|
|
40
|
-
it("does not give skills or activities to a school without employerEvents", () => {
|
|
41
|
-
const p = resolveProduct({package: "institutes-one", workExperience: true});
|
|
42
|
-
expect(p.skills).toBe(false);
|
|
43
|
-
expect(p.activities).toBe(false);
|
|
44
|
-
expect(p.events).toBe(false);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("does not resurrect them from an explicit true on the sub-flag alone", () => {
|
|
48
|
-
const p = resolveProduct({
|
|
49
|
-
package: "institutes-one",
|
|
50
|
-
skillsAssessmentsProduct: true,
|
|
51
|
-
trackExtracurriculars: true,
|
|
52
|
-
});
|
|
53
|
-
expect(p.skills).toBe(false);
|
|
54
|
-
expect(p.activities).toBe(false);
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
describe("opt-in products", () => {
|
|
59
|
-
it("leaves wex, destinations and alumni off by default", () => {
|
|
60
|
-
const p = resolveProduct({package: "institutes-one"});
|
|
61
|
-
expect(p.wex).toBe(false);
|
|
62
|
-
expect(p.destinations).toBe(false);
|
|
63
|
-
expect(p.alumni).toBe(false);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("turns them on when explicitly true", () => {
|
|
67
|
-
const p = resolveProduct({
|
|
68
|
-
package: "institutes-one",
|
|
69
|
-
workExperience: true,
|
|
70
|
-
destinationTracking: true,
|
|
71
|
-
alumniManagement: true,
|
|
72
|
-
});
|
|
73
|
-
expect(p.wex).toBe(true);
|
|
74
|
-
expect(p.destinations).toBe(true);
|
|
75
|
-
expect(p.alumni).toBe(true);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
describe("packages", () => {
|
|
80
|
-
it("gives a careersHub events without employerEvents, but no wex or skills", () => {
|
|
81
|
-
const p = resolveProduct({package: "careersHub"});
|
|
82
|
-
expect(p.events).toBe(true);
|
|
83
|
-
expect(p.isHub).toBe(true);
|
|
84
|
-
expect(p.wex).toBe(false);
|
|
85
|
-
expect(p.skills).toBe(false);
|
|
86
|
-
expect(p.activities).toBe(false);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("does not give a careersHub school its own wex even with the flag set", () => {
|
|
90
|
-
const p = resolveProduct({package: "careersSchool", workExperience: true});
|
|
91
|
-
expect(p.wex).toBe(false);
|
|
92
|
-
expect(p.isHubSchool).toBe(true);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("rolls a trust's products up from its schools", () => {
|
|
96
|
-
const p = resolveProduct({package: "institutes-two"}, {
|
|
97
|
-
trustSchools: [
|
|
98
|
-
{destinationTracking: true},
|
|
99
|
-
{employerEvents: true, careersEvents: false},
|
|
100
|
-
],
|
|
101
|
-
});
|
|
102
|
-
expect(p.isTrust).toBe(true);
|
|
103
|
-
expect(p.destinations).toBe(true);
|
|
104
|
-
expect(p.skills).toBe(true); // sub-flag undefined at the school
|
|
105
|
-
expect(p.events).toBe(false); // explicitly off at the only events school
|
|
106
|
-
expect(p.wex).toBe(false);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it("does not roll schools up for a non-trust", () => {
|
|
110
|
-
const p = resolveProduct({package: "institutes-one"}, {
|
|
111
|
-
trustSchools: [{destinationTracking: true}],
|
|
112
|
-
});
|
|
113
|
-
expect(p.destinations).toBe(false);
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
describe("hub links", () => {
|
|
118
|
-
it("counts only approved links", () => {
|
|
119
|
-
const p = resolveProduct({
|
|
120
|
-
careersHubLinks: {
|
|
121
|
-
hubA: {exists: true, invited: "2026-01-01", status: "approved"},
|
|
122
|
-
hubB: {exists: true, invited: "2026-01-01", status: "invited"},
|
|
123
|
-
hubC: {exists: true, invited: "2026-01-01", status: "declined"},
|
|
124
|
-
},
|
|
125
|
-
});
|
|
126
|
-
expect(p.hubLinked).toBe(true);
|
|
127
|
-
expect(p.hubIds).toEqual(["hubA"]);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it("is not hub-linked with no links", () => {
|
|
131
|
-
expect(resolveProduct({}).hubLinked).toBe(false);
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
describe("enabled", () => {
|
|
136
|
-
it("lists products in display order and drives the layout mode", () => {
|
|
137
|
-
const skillsOnly = resolveProduct({
|
|
138
|
-
package: "institutes-one",
|
|
139
|
-
employerEvents: true,
|
|
140
|
-
careersEvents: false,
|
|
141
|
-
network: false,
|
|
142
|
-
});
|
|
143
|
-
expect(skillsOnly.enabled).toEqual(["skills", "activities"]);
|
|
144
|
-
|
|
145
|
-
const fullStack = resolveProduct({
|
|
146
|
-
package: "institutes-one",
|
|
147
|
-
workExperience: true,
|
|
148
|
-
employerEvents: true,
|
|
149
|
-
destinationTracking: true,
|
|
150
|
-
alumniManagement: true,
|
|
151
|
-
});
|
|
152
|
-
expect(fullStack.enabled).toEqual(
|
|
153
|
-
["wex", "destinations", "events", "skills", "activities", "network", "alumni"]);
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
});
|