placementt-core 1.400.1228 → 1.400.1229
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/engagementPlan.d.ts +101 -0
- package/lib/engagementPlan.js +159 -0
- package/lib/engagementPlan.js.map +1 -0
- package/lib/engagementPlan.test.d.ts +1 -0
- package/lib/engagementPlan.test.js +171 -0
- package/lib/engagementPlan.test.js.map +1 -0
- package/lib/featureMarketing.d.ts +66 -2
- package/lib/featureMarketing.js +103 -4
- package/lib/featureMarketing.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/onboardingPathways.d.ts +62 -4
- package/lib/onboardingPathways.js +203 -31
- package/lib/onboardingPathways.js.map +1 -1
- package/lib/onboardingPathways.test.js +40 -1
- package/lib/onboardingPathways.test.js.map +1 -1
- package/lib/renewals.d.ts +73 -0
- package/lib/renewals.js +90 -0
- package/lib/renewals.js.map +1 -0
- package/lib/renewals.test.d.ts +1 -0
- package/lib/renewals.test.js +53 -0
- package/lib/renewals.test.js.map +1 -0
- package/lib/typeDefinitions.d.ts +58 -3
- package/lib/typeDefinitions.js.map +1 -1
- package/package.json +1 -1
- package/src/engagementPlan.test.ts +209 -0
- package/src/engagementPlan.ts +181 -0
- package/src/featureMarketing.ts +122 -4
- package/src/index.ts +2 -0
- package/src/onboardingPathways.test.ts +48 -1
- package/src/onboardingPathways.ts +235 -32
- package/src/renewals.test.ts +63 -0
- package/src/renewals.ts +138 -0
- package/src/typeDefinitions.ts +47 -3
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { EngagementPlan, InstituteData } from "./typeDefinitions";
|
|
2
|
+
/**
|
|
3
|
+
* The school's plan for the year: which term each feature is set up in.
|
|
4
|
+
*
|
|
5
|
+
* A school drags each feature it has into a term on its homepage board, and
|
|
6
|
+
* the engagement engine sends nothing about a feature before that term starts.
|
|
7
|
+
* Terms rather than months because that is how schools plan, and because we
|
|
8
|
+
* already work out every school's term dates from the holidays
|
|
9
|
+
* (outreachRules.ts). A term starts on the day after the summer, Christmas or
|
|
10
|
+
* Easter holidays; half-terms don't split one.
|
|
11
|
+
*
|
|
12
|
+
* Term ids are absolute ("2026-27:spring") so a saved card means the same
|
|
13
|
+
* thing all year. The board shows them relative: "This term", the rest of
|
|
14
|
+
* this academic year by name, "Next year" and "Not needed". A plan only
|
|
15
|
+
* counts in the academic year it was saved in; in September the board asks
|
|
16
|
+
* again.
|
|
17
|
+
*
|
|
18
|
+
* This file is the term arithmetic. Which features go on the board, and the
|
|
19
|
+
* default term for each, is in featureMarketing.ts, which owns the registry.
|
|
20
|
+
*/
|
|
21
|
+
export type PlanTerm = "autumn" | "spring" | "summer";
|
|
22
|
+
/** A card's term when the feature is not needed this year. */
|
|
23
|
+
export declare const PLAN_NEVER = "never";
|
|
24
|
+
/** A column on the board. `start` is absent on "Not needed". */
|
|
25
|
+
export type PlanColumn = {
|
|
26
|
+
id: string;
|
|
27
|
+
label: string;
|
|
28
|
+
start?: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* @param {number} startYear the year the academic year starts in.
|
|
32
|
+
* @param {PlanTerm} term the term.
|
|
33
|
+
* @return {string} its id, e.g. "2026-27:spring".
|
|
34
|
+
*/
|
|
35
|
+
export declare const planTermId: (startYear: number, term: PlanTerm) => string;
|
|
36
|
+
/**
|
|
37
|
+
* The first school day of a term: the day after the holiday before it.
|
|
38
|
+
*
|
|
39
|
+
* @param {string} id a term id.
|
|
40
|
+
* @return {string|undefined} YYYY-MM-DD, or undefined for "never" or a bad id.
|
|
41
|
+
*/
|
|
42
|
+
export declare const planTermStart: (id: string) => string | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* The term a date belongs to. In term time, the term it is in; in the summer,
|
|
45
|
+
* Christmas or Easter holidays, the term that comes next.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} date YYYY-MM-DD.
|
|
48
|
+
* @return {string} the term id.
|
|
49
|
+
*/
|
|
50
|
+
export declare const planTermOn: (date: string) => string;
|
|
51
|
+
/**
|
|
52
|
+
* @param {Date} now the clock.
|
|
53
|
+
* @return {string} the term it is now, by the rule in planTermOn.
|
|
54
|
+
*/
|
|
55
|
+
export declare const currentPlanTerm: (now: Date) => string;
|
|
56
|
+
/**
|
|
57
|
+
* The academic year a plan saved now belongs to: the current term's. In the
|
|
58
|
+
* summer holidays that is the year about to start.
|
|
59
|
+
*
|
|
60
|
+
* @param {Date} now the clock.
|
|
61
|
+
* @return {string} e.g. "2026-27".
|
|
62
|
+
*/
|
|
63
|
+
export declare const planYearOf: (now: Date) => string;
|
|
64
|
+
/**
|
|
65
|
+
* The board's columns today: this term, the rest of this academic year, next
|
|
66
|
+
* year (its autumn term) and not needed.
|
|
67
|
+
*
|
|
68
|
+
* @param {Date} now the clock.
|
|
69
|
+
* @return {PlanColumn[]} in board order.
|
|
70
|
+
*/
|
|
71
|
+
export declare const planColumns: (now: Date) => PlanColumn[];
|
|
72
|
+
/**
|
|
73
|
+
* Which column a term id sits in today. A term already started is "This
|
|
74
|
+
* term"; one past next autumn is "Next year"; an unknown id is "Not needed".
|
|
75
|
+
*
|
|
76
|
+
* @param {string} term a card's term.
|
|
77
|
+
* @param {Date} now the clock.
|
|
78
|
+
* @return {string} the column id.
|
|
79
|
+
*/
|
|
80
|
+
export declare const planColumnOf: (term: string, now: Date) => string;
|
|
81
|
+
/**
|
|
82
|
+
* Where a feature starts on a fresh board: the term its next season starts
|
|
83
|
+
* in, or this term for one in season now or with no season. Nothing defaults
|
|
84
|
+
* past next autumn.
|
|
85
|
+
*
|
|
86
|
+
* @param {object[]} seasons the feature's "MM-DD" windows, as in featureMarketing.ts.
|
|
87
|
+
* @param {Date} now the clock.
|
|
88
|
+
* @return {string} a term id.
|
|
89
|
+
*/
|
|
90
|
+
export declare const defaultPlanTerm: (seasons: {
|
|
91
|
+
start: string;
|
|
92
|
+
end: string;
|
|
93
|
+
}[], now: Date) => string;
|
|
94
|
+
/**
|
|
95
|
+
* The institute's plan, if it was saved this academic year.
|
|
96
|
+
*
|
|
97
|
+
* @param {InstituteData} institute the institute.
|
|
98
|
+
* @param {Date} now the clock.
|
|
99
|
+
* @return {EngagementPlan|undefined} the plan in force.
|
|
100
|
+
*/
|
|
101
|
+
export declare const savedEngagementPlan: (institute: InstituteData, now: Date) => EngagementPlan | undefined;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.savedEngagementPlan = exports.defaultPlanTerm = exports.planColumnOf = exports.planColumns = exports.planYearOf = exports.currentPlanTerm = exports.planTermOn = exports.planTermStart = exports.planTermId = exports.PLAN_NEVER = void 0;
|
|
4
|
+
const outreachRules_1 = require("./outreachRules");
|
|
5
|
+
const schedule_1 = require("./surveys/schedule");
|
|
6
|
+
/** A card's term when the feature is not needed this year. */
|
|
7
|
+
exports.PLAN_NEVER = "never";
|
|
8
|
+
const TERMS = ["autumn", "spring", "summer"];
|
|
9
|
+
const TERM_LABELS = { autumn: "Autumn term", spring: "Spring term", summer: "Summer term" };
|
|
10
|
+
/**
|
|
11
|
+
* @param {number} startYear the year the academic year starts in.
|
|
12
|
+
* @param {PlanTerm} term the term.
|
|
13
|
+
* @return {string} its id, e.g. "2026-27:spring".
|
|
14
|
+
*/
|
|
15
|
+
const planTermId = (startYear, term) => `${(0, schedule_1.academicYearLabel)(startYear)}:${term}`;
|
|
16
|
+
exports.planTermId = planTermId;
|
|
17
|
+
const parseTermId = (id) => {
|
|
18
|
+
const [label, term] = id.split(":");
|
|
19
|
+
const startYear = Number(label?.slice(0, 4));
|
|
20
|
+
return startYear && TERMS.includes(term) ? { startYear, term: term } : undefined;
|
|
21
|
+
};
|
|
22
|
+
const holidayEnd = (year, label) => (0, outreachRules_1.schoolHolidays)(year).find((h) => h.label === label).end;
|
|
23
|
+
/**
|
|
24
|
+
* The first school day of a term: the day after the holiday before it.
|
|
25
|
+
*
|
|
26
|
+
* @param {string} id a term id.
|
|
27
|
+
* @return {string|undefined} YYYY-MM-DD, or undefined for "never" or a bad id.
|
|
28
|
+
*/
|
|
29
|
+
const planTermStart = (id) => {
|
|
30
|
+
const parsed = parseTermId(id);
|
|
31
|
+
if (!parsed)
|
|
32
|
+
return undefined;
|
|
33
|
+
const { startYear, term } = parsed;
|
|
34
|
+
if (term === "autumn")
|
|
35
|
+
return (0, outreachRules_1.addYmdDays)(holidayEnd(startYear, "Summer holidays"), 1);
|
|
36
|
+
if (term === "spring")
|
|
37
|
+
return (0, outreachRules_1.addYmdDays)(holidayEnd(startYear, "Christmas holidays"), 1);
|
|
38
|
+
return (0, outreachRules_1.addYmdDays)(holidayEnd(startYear + 1, "Easter holidays"), 1);
|
|
39
|
+
};
|
|
40
|
+
exports.planTermStart = planTermStart;
|
|
41
|
+
const termsAround = (date) => {
|
|
42
|
+
const year = Number(date.slice(0, 4));
|
|
43
|
+
const out = [];
|
|
44
|
+
for (let y = year - 2; y <= year + 1; y++) {
|
|
45
|
+
TERMS.forEach((t) => {
|
|
46
|
+
const id = (0, exports.planTermId)(y, t);
|
|
47
|
+
out.push({ id, start: (0, exports.planTermStart)(id) });
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return out.sort((a, b) => a.start.localeCompare(b.start));
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* The term a date belongs to. In term time, the term it is in; in the summer,
|
|
54
|
+
* Christmas or Easter holidays, the term that comes next.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} date YYYY-MM-DD.
|
|
57
|
+
* @return {string} the term id.
|
|
58
|
+
*/
|
|
59
|
+
const planTermOn = (date) => {
|
|
60
|
+
const terms = termsAround(date);
|
|
61
|
+
const year = Number(date.slice(0, 4));
|
|
62
|
+
const longHolidays = [year - 1, year].flatMap(outreachRules_1.schoolHolidays)
|
|
63
|
+
.filter((h) => /Summer|Christmas|Easter/.test(h.label));
|
|
64
|
+
if ((0, outreachRules_1.blackoutOn)(date, longHolidays))
|
|
65
|
+
return terms.find((t) => t.start > date).id;
|
|
66
|
+
return [...terms].reverse().find((t) => t.start <= date)?.id;
|
|
67
|
+
};
|
|
68
|
+
exports.planTermOn = planTermOn;
|
|
69
|
+
/**
|
|
70
|
+
* @param {Date} now the clock.
|
|
71
|
+
* @return {string} the term it is now, by the rule in planTermOn.
|
|
72
|
+
*/
|
|
73
|
+
const currentPlanTerm = (now) => (0, exports.planTermOn)((0, outreachRules_1.londonYmd)(now));
|
|
74
|
+
exports.currentPlanTerm = currentPlanTerm;
|
|
75
|
+
/**
|
|
76
|
+
* The academic year a plan saved now belongs to: the current term's. In the
|
|
77
|
+
* summer holidays that is the year about to start.
|
|
78
|
+
*
|
|
79
|
+
* @param {Date} now the clock.
|
|
80
|
+
* @return {string} e.g. "2026-27".
|
|
81
|
+
*/
|
|
82
|
+
const planYearOf = (now) => (0, exports.currentPlanTerm)(now).split(":")[0];
|
|
83
|
+
exports.planYearOf = planYearOf;
|
|
84
|
+
/**
|
|
85
|
+
* The board's columns today: this term, the rest of this academic year, next
|
|
86
|
+
* year (its autumn term) and not needed.
|
|
87
|
+
*
|
|
88
|
+
* @param {Date} now the clock.
|
|
89
|
+
* @return {PlanColumn[]} in board order.
|
|
90
|
+
*/
|
|
91
|
+
const planColumns = (now) => {
|
|
92
|
+
const current = parseTermId((0, exports.currentPlanTerm)(now));
|
|
93
|
+
const columns = TERMS.slice(TERMS.indexOf(current.term)).map((t, i) => {
|
|
94
|
+
const id = (0, exports.planTermId)(current.startYear, t);
|
|
95
|
+
return { id, label: i === 0 ? "This term" : TERM_LABELS[t], start: (0, exports.planTermStart)(id) };
|
|
96
|
+
});
|
|
97
|
+
const nextYear = (0, exports.planTermId)(current.startYear + 1, "autumn");
|
|
98
|
+
columns.push({ id: nextYear, label: "Next year", start: (0, exports.planTermStart)(nextYear) });
|
|
99
|
+
columns.push({ id: exports.PLAN_NEVER, label: "Not needed" });
|
|
100
|
+
return columns;
|
|
101
|
+
};
|
|
102
|
+
exports.planColumns = planColumns;
|
|
103
|
+
/**
|
|
104
|
+
* Which column a term id sits in today. A term already started is "This
|
|
105
|
+
* term"; one past next autumn is "Next year"; an unknown id is "Not needed".
|
|
106
|
+
*
|
|
107
|
+
* @param {string} term a card's term.
|
|
108
|
+
* @param {Date} now the clock.
|
|
109
|
+
* @return {string} the column id.
|
|
110
|
+
*/
|
|
111
|
+
const planColumnOf = (term, now) => {
|
|
112
|
+
const columns = (0, exports.planColumns)(now);
|
|
113
|
+
const start = (0, exports.planTermStart)(term);
|
|
114
|
+
if (!start)
|
|
115
|
+
return exports.PLAN_NEVER;
|
|
116
|
+
const dated = columns.filter((c) => c.start);
|
|
117
|
+
if (start <= dated[0].start)
|
|
118
|
+
return dated[0].id;
|
|
119
|
+
const nextYear = dated[dated.length - 1];
|
|
120
|
+
if (start >= nextYear.start)
|
|
121
|
+
return nextYear.id;
|
|
122
|
+
return dated.find((c) => c.start === start)?.id ?? nextYear.id;
|
|
123
|
+
};
|
|
124
|
+
exports.planColumnOf = planColumnOf;
|
|
125
|
+
const mmdd = (date) => date.slice(5);
|
|
126
|
+
/**
|
|
127
|
+
* Where a feature starts on a fresh board: the term its next season starts
|
|
128
|
+
* in, or this term for one in season now or with no season. Nothing defaults
|
|
129
|
+
* past next autumn.
|
|
130
|
+
*
|
|
131
|
+
* @param {object[]} seasons the feature's "MM-DD" windows, as in featureMarketing.ts.
|
|
132
|
+
* @param {Date} now the clock.
|
|
133
|
+
* @return {string} a term id.
|
|
134
|
+
*/
|
|
135
|
+
const defaultPlanTerm = (seasons, now) => {
|
|
136
|
+
const today = (0, outreachRules_1.londonYmd)(now);
|
|
137
|
+
const md = mmdd(today);
|
|
138
|
+
const current = (0, exports.currentPlanTerm)(now);
|
|
139
|
+
const inSeason = seasons.some(({ start, end }) => start <= end ? (md >= start && md <= end) : (md >= start || md <= end));
|
|
140
|
+
if (!seasons.length || inSeason)
|
|
141
|
+
return current;
|
|
142
|
+
const year = Number(today.slice(0, 4));
|
|
143
|
+
const next = seasons.map((s) => `${s.start > md ? year : year + 1}-${s.start}`).sort()[0];
|
|
144
|
+
return (0, exports.planColumnOf)((0, exports.planTermOn)(next), now);
|
|
145
|
+
};
|
|
146
|
+
exports.defaultPlanTerm = defaultPlanTerm;
|
|
147
|
+
/**
|
|
148
|
+
* The institute's plan, if it was saved this academic year.
|
|
149
|
+
*
|
|
150
|
+
* @param {InstituteData} institute the institute.
|
|
151
|
+
* @param {Date} now the clock.
|
|
152
|
+
* @return {EngagementPlan|undefined} the plan in force.
|
|
153
|
+
*/
|
|
154
|
+
const savedEngagementPlan = (institute, now) => {
|
|
155
|
+
const plan = institute.engagementPlan;
|
|
156
|
+
return plan && plan.academicYear === (0, exports.planYearOf)(now) ? plan : undefined;
|
|
157
|
+
};
|
|
158
|
+
exports.savedEngagementPlan = savedEngagementPlan;
|
|
159
|
+
//# sourceMappingURL=engagementPlan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engagementPlan.js","sourceRoot":"","sources":["../src/engagementPlan.ts"],"names":[],"mappings":";;;AACA,mDAAkF;AAClF,iDAAqD;AAwBrD,8DAA8D;AACjD,QAAA,UAAU,GAAG,OAAO,CAAC;AAElC,MAAM,KAAK,GAAe,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAEzD,MAAM,WAAW,GAA6B,EAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,EAAC,CAAC;AAKpH;;;;GAIG;AACI,MAAM,UAAU,GAAG,CAAC,SAAiB,EAAE,IAAc,EAAU,EAAE,CAAC,GAAG,IAAA,4BAAiB,EAAC,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC;AAAtG,QAAA,UAAU,cAA4F;AAEnH,MAAM,WAAW,GAAG,CAAC,EAAU,EAAiD,EAAE;IAC9E,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7C,OAAO,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAgB,CAAC,CAAC,CAAC,CAAC,EAAC,SAAS,EAAE,IAAI,EAAE,IAAgB,EAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAC3G,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,KAAa,EAAU,EAAE,CACtD,IAAA,8BAAc,EAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAmB,CAAC,GAAG,CAAC;AAE/E;;;;;GAKG;AACI,MAAM,aAAa,GAAG,CAAC,EAAU,EAAoB,EAAE;IAC1D,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,MAAM,EAAC,SAAS,EAAE,IAAI,EAAC,GAAG,MAAM,CAAC;IACjC,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAA,0BAAU,EAAC,UAAU,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC;IACtF,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAA,0BAAU,EAAC,UAAU,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC;IACzF,OAAO,IAAA,0BAAU,EAAC,UAAU,CAAC,SAAS,GAAG,CAAC,EAAE,iBAAiB,CAAC,EAAE,CAAC,CAAC,CAAC;AACvE,CAAC,CAAC;AAPW,QAAA,aAAa,iBAOxB;AAEF,MAAM,WAAW,GAAG,CAAC,IAAY,EAAiC,EAAE;IAChE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,GAAG,GAAkC,EAAE,CAAC;IAC9C,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YAChB,MAAM,EAAE,GAAG,IAAA,kBAAU,EAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC5B,GAAG,CAAC,IAAI,CAAC,EAAC,EAAE,EAAE,KAAK,EAAE,IAAA,qBAAa,EAAC,EAAE,CAAW,EAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACP,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9D,CAAC,CAAC;AAEF;;;;;;GAMG;AACI,MAAM,UAAU,GAAG,CAAC,IAAY,EAAU,EAAE;IAC/C,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,YAAY,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,8BAAc,CAAC;SACxD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5D,IAAI,IAAA,0BAAU,EAAC,IAAI,EAAE,YAAY,CAAC;QAAE,OAAQ,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAkB,CAAC,EAAE,CAAC;IAClG,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,EAAE,EAAY,CAAC;AAC3E,CAAC,CAAC;AAPW,QAAA,UAAU,cAOrB;AAEF;;;GAGG;AACI,MAAM,eAAe,GAAG,CAAC,GAAS,EAAU,EAAE,CAAC,IAAA,kBAAU,EAAC,IAAA,yBAAS,EAAC,GAAG,CAAC,CAAC,CAAC;AAApE,QAAA,eAAe,mBAAqD;AAEjF;;;;;;GAMG;AACI,MAAM,UAAU,GAAG,CAAC,GAAS,EAAU,EAAE,CAAC,IAAA,uBAAe,EAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAAvE,QAAA,UAAU,cAA6D;AAEpF;;;;;;GAMG;AACI,MAAM,WAAW,GAAG,CAAC,GAAS,EAAgB,EAAE;IACnD,MAAM,OAAO,GAAG,WAAW,CAAC,IAAA,uBAAe,EAAC,GAAG,CAAC,CAAwC,CAAC;IACzF,MAAM,OAAO,GAAiB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAChF,MAAM,EAAE,GAAG,IAAA,kBAAU,EAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QAC5C,OAAO,EAAC,EAAE,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAA,qBAAa,EAAC,EAAE,CAAC,EAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,IAAA,kBAAU,EAAC,OAAO,CAAC,SAAS,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,CAAC,EAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,IAAA,qBAAa,EAAC,QAAQ,CAAC,EAAC,CAAC,CAAC;IACjF,OAAO,CAAC,IAAI,CAAC,EAAC,EAAE,EAAE,kBAAU,EAAE,KAAK,EAAE,YAAY,EAAC,CAAC,CAAC;IACpD,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC;AAVW,QAAA,WAAW,eAUtB;AAEF;;;;;;;GAOG;AACI,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,GAAS,EAAU,EAAE;IAC5D,MAAM,OAAO,GAAG,IAAA,mBAAW,EAAC,GAAG,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,IAAA,qBAAa,EAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK;QAAE,OAAO,kBAAU,CAAC;IAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC7C,IAAI,KAAK,IAAK,KAAK,CAAC,CAAC,CAAC,CAAC,KAAgB;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzC,IAAI,KAAK,IAAK,QAAQ,CAAC,KAAgB;QAAE,OAAO,QAAQ,CAAC,EAAE,CAAC;IAC5D,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,EAAE,EAAE,IAAI,QAAQ,CAAC,EAAE,CAAC;AACnE,CAAC,CAAC;AATW,QAAA,YAAY,gBASvB;AAEF,MAAM,IAAI,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAErD;;;;;;;;GAQG;AACI,MAAM,eAAe,GAAG,CAAC,OAAuC,EAAE,GAAS,EAAU,EAAE;IAC1F,MAAM,KAAK,GAAG,IAAA,yBAAS,EAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACvB,MAAM,OAAO,GAAG,IAAA,uBAAe,EAAC,GAAG,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,EAAC,KAAK,EAAE,GAAG,EAAC,EAAE,EAAE,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;IACxH,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1F,OAAO,IAAA,oBAAY,EAAC,IAAA,kBAAU,EAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/C,CAAC,CAAC;AATW,QAAA,eAAe,mBAS1B;AAEF;;;;;;GAMG;AACI,MAAM,mBAAmB,GAAG,CAAC,SAAwB,EAAE,GAAS,EAA4B,EAAE;IACjG,MAAM,IAAI,GAAG,SAAS,CAAC,cAAc,CAAC;IACtC,OAAO,IAAI,IAAI,IAAI,CAAC,YAAY,KAAK,IAAA,kBAAU,EAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5E,CAAC,CAAC;AAHW,QAAA,mBAAmB,uBAG9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
jest.mock("firebase/firestore", () => ({ where: jest.fn() }));
|
|
4
|
+
jest.mock("./firebase/firebaseQuery", () => ({ __esModule: true, default: class {
|
|
5
|
+
} }));
|
|
6
|
+
const productResolver_1 = require("./productResolver");
|
|
7
|
+
const engagementPlan_1 = require("./engagementPlan");
|
|
8
|
+
const featureMarketing_1 = require("./featureMarketing");
|
|
9
|
+
const onboardingPathways_1 = require("./onboardingPathways");
|
|
10
|
+
const NOVEMBER = new Date("2026-11-02T09:00:00Z");
|
|
11
|
+
/** A school that has bought everything and set up nothing. */
|
|
12
|
+
const school = (overrides = {}) => ({
|
|
13
|
+
name: "Calder Park Academy",
|
|
14
|
+
package: "institutes-one",
|
|
15
|
+
workExperience: true,
|
|
16
|
+
employerEvents: true,
|
|
17
|
+
destinationTracking: true,
|
|
18
|
+
alumniManagement: true,
|
|
19
|
+
skillsAssessmentsProduct: true,
|
|
20
|
+
trackExtracurriculars: true,
|
|
21
|
+
...overrides,
|
|
22
|
+
});
|
|
23
|
+
const ctx = (institute, counts = {}, now = NOVEMBER) => ({
|
|
24
|
+
institute,
|
|
25
|
+
products: (0, productResolver_1.resolveProducts)(institute, { parentCount: counts.parents || 0 }),
|
|
26
|
+
counts,
|
|
27
|
+
now,
|
|
28
|
+
});
|
|
29
|
+
const plan = (cards, academicYear = "2026-27") => ({ engagementPlan: { academicYear, cards, savedAt: "2026-11-02T09:00:00Z", savedBy: "u1" } });
|
|
30
|
+
describe("terms", () => {
|
|
31
|
+
it("starts each term the day after the long holiday before it", () => {
|
|
32
|
+
expect((0, engagementPlan_1.planTermStart)("2026-27:autumn")).toBe("2026-09-07");
|
|
33
|
+
expect((0, engagementPlan_1.planTermStart)("2026-27:spring")).toBe("2027-01-04");
|
|
34
|
+
expect((0, engagementPlan_1.planTermStart)("2026-27:summer")).toBe("2027-04-10");
|
|
35
|
+
expect((0, engagementPlan_1.planTermStart)(engagementPlan_1.PLAN_NEVER)).toBeUndefined();
|
|
36
|
+
});
|
|
37
|
+
it("puts a long holiday in the term after it, and a half-term in its own", () => {
|
|
38
|
+
expect((0, engagementPlan_1.planTermOn)("2026-10-28")).toBe("2026-27:autumn");
|
|
39
|
+
expect((0, engagementPlan_1.planTermOn)("2026-12-21")).toBe("2026-27:spring");
|
|
40
|
+
expect((0, engagementPlan_1.planTermOn)("2026-08-10")).toBe("2026-27:autumn");
|
|
41
|
+
expect((0, engagementPlan_1.planTermOn)("2027-02-17")).toBe("2026-27:spring");
|
|
42
|
+
});
|
|
43
|
+
it("rolls the plan year over in the summer holidays", () => {
|
|
44
|
+
expect((0, engagementPlan_1.planYearOf)(new Date("2027-07-01T09:00:00Z"))).toBe("2026-27");
|
|
45
|
+
expect((0, engagementPlan_1.planYearOf)(new Date("2027-08-10T09:00:00Z"))).toBe("2027-28");
|
|
46
|
+
});
|
|
47
|
+
it("shows this term, the rest of the year, next year and not needed", () => {
|
|
48
|
+
expect((0, engagementPlan_1.planColumns)(NOVEMBER).map((c) => [c.id, c.label])).toEqual([
|
|
49
|
+
["2026-27:autumn", "This term"],
|
|
50
|
+
["2026-27:spring", "Spring term"],
|
|
51
|
+
["2026-27:summer", "Summer term"],
|
|
52
|
+
["2027-28:autumn", "Next year"],
|
|
53
|
+
[engagementPlan_1.PLAN_NEVER, "Not needed"],
|
|
54
|
+
]);
|
|
55
|
+
expect((0, engagementPlan_1.planColumns)(new Date("2027-05-10T09:00:00Z")).map((c) => c.label))
|
|
56
|
+
.toEqual(["This term", "Next year", "Not needed"]);
|
|
57
|
+
});
|
|
58
|
+
it("files a started term under this term, and anything later than next autumn under next year", () => {
|
|
59
|
+
expect((0, engagementPlan_1.planColumnOf)("2026-27:autumn", new Date("2027-01-20T09:00:00Z"))).toBe("2026-27:spring");
|
|
60
|
+
expect((0, engagementPlan_1.planColumnOf)("2028-29:spring", NOVEMBER)).toBe("2027-28:autumn");
|
|
61
|
+
expect((0, engagementPlan_1.planColumnOf)("nonsense", NOVEMBER)).toBe(engagementPlan_1.PLAN_NEVER);
|
|
62
|
+
});
|
|
63
|
+
it("defaults a feature to the term its next season starts in", () => {
|
|
64
|
+
expect((0, engagementPlan_1.defaultPlanTerm)([], NOVEMBER)).toBe("2026-27:autumn");
|
|
65
|
+
expect((0, engagementPlan_1.defaultPlanTerm)([{ start: "11-01", end: "11-30" }], NOVEMBER)).toBe("2026-27:autumn");
|
|
66
|
+
expect((0, engagementPlan_1.defaultPlanTerm)([{ start: "01-05", end: "02-15" }], NOVEMBER)).toBe("2026-27:spring");
|
|
67
|
+
expect((0, engagementPlan_1.defaultPlanTerm)([{ start: "05-01", end: "07-15" }], NOVEMBER)).toBe("2026-27:summer");
|
|
68
|
+
expect((0, engagementPlan_1.defaultPlanTerm)([{ start: "09-01", end: "10-31" }], NOVEMBER)).toBe("2027-28:autumn");
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe("board", () => {
|
|
72
|
+
it("lays out the agreed defaults for a school joining in November", () => {
|
|
73
|
+
const terms = Object.fromEntries((0, featureMarketing_1.engagementPlanBoard)(ctx(school())).map((c) => [c.key, c.term]));
|
|
74
|
+
expect(terms).toEqual({
|
|
75
|
+
wexCohort: "2026-27:autumn",
|
|
76
|
+
guidance: "2026-27:autumn",
|
|
77
|
+
events: "2026-27:autumn",
|
|
78
|
+
employerPortal: "2026-27:autumn",
|
|
79
|
+
careersLibrary: "2026-27:autumn",
|
|
80
|
+
aspirations: "2026-27:spring",
|
|
81
|
+
skills: "2026-27:spring",
|
|
82
|
+
activities: "2026-27:spring",
|
|
83
|
+
leavers: "2026-27:spring",
|
|
84
|
+
alumni: "2026-27:summer",
|
|
85
|
+
parents: "2027-28:autumn",
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
it("leaves the impact report off, and gives trusts and hubs no board", () => {
|
|
89
|
+
expect((0, featureMarketing_1.engagementPlanBoard)(ctx(school())).map((c) => c.key)).not.toContain("impactReport");
|
|
90
|
+
expect((0, featureMarketing_1.engagementPlanBoard)(ctx(school({ package: "institutes-two" })))).toEqual([]);
|
|
91
|
+
expect((0, featureMarketing_1.engagementPlanBoard)(ctx(school({ package: "careersHub" })))).toEqual([]);
|
|
92
|
+
});
|
|
93
|
+
it("uses the school's terms and order, and defaults for anything it has not placed", () => {
|
|
94
|
+
const board = (0, featureMarketing_1.engagementPlanBoard)(ctx(school(plan({
|
|
95
|
+
careersLibrary: { term: "2026-27:autumn", order: 1 },
|
|
96
|
+
activities: { term: "2026-27:autumn", order: 0 },
|
|
97
|
+
leavers: { term: engagementPlan_1.PLAN_NEVER, order: 0 },
|
|
98
|
+
}))));
|
|
99
|
+
expect(board.slice(0, 2).map((c) => c.key)).toEqual(["activities", "careersLibrary"]);
|
|
100
|
+
expect(board.find((c) => c.key === "leavers")?.term).toBe(engagementPlan_1.PLAN_NEVER);
|
|
101
|
+
expect(board[board.length - 1].key).toBe("leavers");
|
|
102
|
+
expect(board.find((c) => c.key === "alumni")?.term).toBe("2026-27:summer");
|
|
103
|
+
});
|
|
104
|
+
it("ignores a plan from last year", () => {
|
|
105
|
+
const institute = school(plan({ activities: { term: "2025-26:autumn", order: 0 } }, "2025-26"));
|
|
106
|
+
expect((0, engagementPlan_1.savedEngagementPlan)(institute, NOVEMBER)).toBeUndefined();
|
|
107
|
+
expect((0, featureMarketing_1.engagementPlanBoard)(ctx(institute)).find((c) => c.key === "activities")?.term).toBe("2026-27:spring");
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
describe("engine", () => {
|
|
111
|
+
it("pitches by season when there is no plan", () => {
|
|
112
|
+
const keys = (0, featureMarketing_1.featureMarketingCandidates)(ctx(school())).map((f) => f.key);
|
|
113
|
+
expect(keys).toContain("wexCohort");
|
|
114
|
+
expect(keys).not.toContain("activities");
|
|
115
|
+
});
|
|
116
|
+
it("pitches what the plan puts in this term, in the school's order, whatever the season", () => {
|
|
117
|
+
const c = ctx(school(plan({
|
|
118
|
+
activities: { term: "2026-27:autumn", order: 0 },
|
|
119
|
+
wexCohort: { term: "2026-27:spring", order: 0 },
|
|
120
|
+
leavers: { term: "2026-27:autumn", order: 1 },
|
|
121
|
+
})));
|
|
122
|
+
const keys = (0, featureMarketing_1.featureMarketingCandidates)(c).map((f) => f.key);
|
|
123
|
+
expect(keys.slice(0, 2)).toEqual(["activities", "leavers"]);
|
|
124
|
+
expect(keys).not.toContain("wexCohort");
|
|
125
|
+
expect((0, featureMarketing_1.evaluateFeatureAdoption)(c).find((a) => a.key === "wexCohort")?.planOpen).toBe(false);
|
|
126
|
+
});
|
|
127
|
+
it("never pitches a feature marked not needed", () => {
|
|
128
|
+
const c = ctx(school(plan({ guidance: { term: engagementPlan_1.PLAN_NEVER, order: 0 } })));
|
|
129
|
+
expect((0, featureMarketing_1.featureMarketingCandidates)(c).map((f) => f.key)).not.toContain("guidance");
|
|
130
|
+
});
|
|
131
|
+
it("skips an onboarding step whose term has not started, and offers the next open one", () => {
|
|
132
|
+
// Students in, aspirations set up, so destinations has begun and its
|
|
133
|
+
// next step would be leaver tracking. No work experience, whose
|
|
134
|
+
// pathway would otherwise come first.
|
|
135
|
+
const base = school({
|
|
136
|
+
workExperience: false,
|
|
137
|
+
destinationsConfig: { setupCompletedAt: "2026-09-10", aspirations: { enabled: true } },
|
|
138
|
+
});
|
|
139
|
+
const counts = { students: 100, surveyScopesThisYear: ["aspirations"] };
|
|
140
|
+
expect((0, onboardingPathways_1.nextOnboardingStep)({ ...ctx(base, counts), counts })?.step.key).toBe("destinations.leavers");
|
|
141
|
+
const planned = { ...base, ...plan({ leavers: { term: "2026-27:summer", order: 0 }, alumni: { term: "2026-27:autumn", order: 0 } }) };
|
|
142
|
+
expect((0, onboardingPathways_1.nextOnboardingStep)({ ...ctx(planned, counts), counts })?.step.key).toBe("destinations.alumni");
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
describe("moving one card from an email link", () => {
|
|
146
|
+
it("keeps every other card where it sits and puts the moved one last in its new column", () => {
|
|
147
|
+
const cards = (0, featureMarketing_1.engagementPlanCardsAfterMove)(ctx(school()), "careersLibrary", "2026-27:spring");
|
|
148
|
+
expect(cards.careersLibrary.term).toBe("2026-27:spring");
|
|
149
|
+
const spring = Object.entries(cards).filter(([, c]) => c.term === "2026-27:spring");
|
|
150
|
+
expect(cards.careersLibrary.order).toBe(spring.length - 1);
|
|
151
|
+
expect(cards.wexCohort.term).toBe("2026-27:autumn");
|
|
152
|
+
expect(Object.keys(cards)).toHaveLength(11);
|
|
153
|
+
});
|
|
154
|
+
it("can mark a feature not needed", () => {
|
|
155
|
+
expect((0, featureMarketing_1.engagementPlanCardsAfterMove)(ctx(school()), "leavers", engagementPlan_1.PLAN_NEVER).leavers).toEqual({ term: engagementPlan_1.PLAN_NEVER, order: 0 });
|
|
156
|
+
});
|
|
157
|
+
it("ignores a feature the school does not have", () => {
|
|
158
|
+
const cards = (0, featureMarketing_1.engagementPlanCardsAfterMove)(ctx(school({ alumniManagement: false })), "alumni", engagementPlan_1.PLAN_NEVER);
|
|
159
|
+
expect(cards.alumni).toBeUndefined();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
describe("planFeatureOf", () => {
|
|
163
|
+
it("finds the board feature behind a pitch or a step", () => {
|
|
164
|
+
expect((0, onboardingPathways_1.planFeatureOf)("marketing", "alumni")).toBe("alumni");
|
|
165
|
+
expect((0, onboardingPathways_1.planFeatureOf)("marketing", "impactReport")).toBeUndefined();
|
|
166
|
+
expect((0, onboardingPathways_1.planFeatureOf)("onboarding", "wex.placements")).toBe("wexCohort");
|
|
167
|
+
expect((0, onboardingPathways_1.planFeatureOf)("onboarding", "skills.guidance")).toBe("guidance");
|
|
168
|
+
expect((0, onboardingPathways_1.planFeatureOf)("onboarding", "students")).toBeUndefined();
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
//# sourceMappingURL=engagementPlan.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engagementPlan.test.js","sourceRoot":"","sources":["../src/engagementPlan.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -164,9 +164,69 @@ export type FeatureAdoption = {
|
|
|
164
164
|
inSeason: boolean;
|
|
165
165
|
/** Offered and, where the feature asks, with data behind it. */
|
|
166
166
|
ready: boolean;
|
|
167
|
-
/**
|
|
167
|
+
/** The school's saved plan has reached this feature's term. Undefined
|
|
168
|
+
* with no plan saved this year, when the season decides instead. */
|
|
169
|
+
planOpen?: boolean;
|
|
170
|
+
/** Offered, ready, not adopted and due: in its planned term when the
|
|
171
|
+
* school has a plan, in season when it has not. A campaign could start today. */
|
|
168
172
|
candidate: boolean;
|
|
169
173
|
};
|
|
174
|
+
/** One feature on the plan board. */
|
|
175
|
+
export type EngagementPlanBoardCard = {
|
|
176
|
+
key: FeatureMarketingKey;
|
|
177
|
+
label: string;
|
|
178
|
+
description: string;
|
|
179
|
+
/** A term id, or PLAN_NEVER. */
|
|
180
|
+
term: string;
|
|
181
|
+
order: number;
|
|
182
|
+
};
|
|
183
|
+
/**
|
|
184
|
+
* Whether an account plans its year at all: schools running their own
|
|
185
|
+
* careers programme. Trusts, hubs and hub schools drive somebody else's.
|
|
186
|
+
*
|
|
187
|
+
* @param {FeatureMarketingContext} ctx the institute and its products.
|
|
188
|
+
* @return {boolean} whether it gets the board.
|
|
189
|
+
*/
|
|
190
|
+
export declare const hasEngagementPlan: (ctx: FeatureMarketingContext) => boolean;
|
|
191
|
+
/**
|
|
192
|
+
* The board: every feature the school has, in the term the school put it in,
|
|
193
|
+
* or its default for a feature it has not placed (no plan yet, or a feature
|
|
194
|
+
* switched on since). Default order is the registry priority, after anything
|
|
195
|
+
* the school placed itself.
|
|
196
|
+
*
|
|
197
|
+
* @param {FeatureMarketingContext} ctx the institute and its products.
|
|
198
|
+
* @return {EngagementPlanBoardCard[]} the cards, earliest term first, then by order.
|
|
199
|
+
*/
|
|
200
|
+
export declare const engagementPlanBoard: (ctx: FeatureMarketingContext) => EngagementPlanBoardCard[];
|
|
201
|
+
/**
|
|
202
|
+
* The plan to save when one card moves, from an email link rather than the
|
|
203
|
+
* board: every card where it sits now (defaults included, so the school's
|
|
204
|
+
* board stops following the seasons and starts following this plan), with the
|
|
205
|
+
* moved card last in its new column.
|
|
206
|
+
*
|
|
207
|
+
* @param {FeatureMarketingContext} ctx the institute and its products.
|
|
208
|
+
* @param {FeatureMarketingKey} key the feature to move.
|
|
209
|
+
* @param {string} term the column to move it to: a term id or PLAN_NEVER.
|
|
210
|
+
* @return {object} the `cards` of the plan to save.
|
|
211
|
+
*/
|
|
212
|
+
export declare const engagementPlanCardsAfterMove: (ctx: FeatureMarketingContext, key: FeatureMarketingKey, term: string) => {
|
|
213
|
+
[key: string]: {
|
|
214
|
+
term: string;
|
|
215
|
+
order: number;
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* Where the school's saved plan puts one feature: whether its term has
|
|
220
|
+
* started, and its rank against the others.
|
|
221
|
+
*
|
|
222
|
+
* @param {FeatureMarketingContext} ctx the institute.
|
|
223
|
+
* @param {FeatureMarketingKey} key the feature.
|
|
224
|
+
* @return {object|undefined} open and rank, or undefined with no plan saved this year.
|
|
225
|
+
*/
|
|
226
|
+
export declare const featurePlanStatus: (ctx: FeatureMarketingContext, key: FeatureMarketingKey) => {
|
|
227
|
+
open: boolean;
|
|
228
|
+
rank: number;
|
|
229
|
+
} | undefined;
|
|
170
230
|
/**
|
|
171
231
|
* Every feature in the registry, judged for one institute.
|
|
172
232
|
*
|
|
@@ -174,12 +234,16 @@ export type FeatureAdoption = {
|
|
|
174
234
|
* from `candidate`, the admin panel shows adoption per feature, and a test can
|
|
175
235
|
* assert on any one line without re-running the detectors.
|
|
176
236
|
*
|
|
237
|
+
* A saved plan overrides the seasons: a school that put leaver tracking in
|
|
238
|
+
* the autumn hears about it in the autumn.
|
|
239
|
+
*
|
|
177
240
|
* @param {FeatureMarketingContext} ctx the institute, its products and counts.
|
|
178
241
|
* @return {FeatureAdoption[]} one line per feature, in registry order.
|
|
179
242
|
*/
|
|
180
243
|
export declare const evaluateFeatureAdoption: (ctx: FeatureMarketingContext) => FeatureAdoption[];
|
|
181
244
|
/**
|
|
182
|
-
* The features a campaign could start for today, best first
|
|
245
|
+
* The features a campaign could start for today, best first: in the school's
|
|
246
|
+
* plan order when it has one, by registry priority when it has not.
|
|
183
247
|
*
|
|
184
248
|
* @param {FeatureMarketingContext} ctx the institute, its products and counts.
|
|
185
249
|
* @return {FeatureMarketingEntry[]} candidates in priority order.
|