placementt-core 1.400.1000 → 1.400.1003

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.
@@ -0,0 +1,116 @@
1
+ /**
2
+ * globalSearch — one query box, several Algolia indexes.
3
+ *
4
+ * The navbar search sends whatever the user typed here. Every index that the
5
+ * signed-in institute can see is queried in a single round trip, and the answer
6
+ * comes back keyed by index so the UI can render a section per index.
7
+ *
8
+ * Adding an index is meant to be a single entry in GLOBAL_SEARCH_INDEXES: name
9
+ * the Algolia index, say when an institute can see it, restrict it to that
10
+ * institute's records, and describe how one hit becomes a row.
11
+ */
12
+ import { InstituteData, UserData } from "../../typeDefinitions";
13
+ /** How many results a section shows before the user drills into one index. */
14
+ export declare const GLOBAL_SEARCH_OVERVIEW_HITS = 5;
15
+ /** How many results one index shows per page once the user has drilled in. */
16
+ export declare const GLOBAL_SEARCH_INDEX_HITS = 10;
17
+ export type GlobalSearchIndexId = "placements" | "employers" | "students";
18
+ /** One row, flattened out of whatever the underlying index stores. */
19
+ export type GlobalSearchHit = {
20
+ /** The Algolia objectID, which is the Firestore document id. */
21
+ id: string;
22
+ /** The bold line. */
23
+ title: string;
24
+ /** The line underneath, if there is anything worth saying. */
25
+ subtitle?: string;
26
+ /** A short right-hand label — a status, a year group, a sector. */
27
+ meta?: string;
28
+ /** Where clicking the row goes. */
29
+ path: string;
30
+ /** The untouched hit, for callers that need more than the fields above. */
31
+ raw: {
32
+ [key: string]: any;
33
+ };
34
+ };
35
+ /** The results for a single index. */
36
+ export type GlobalSearchIndexResults = {
37
+ id: GlobalSearchIndexId;
38
+ /** Plural, for the section heading. */
39
+ label: string;
40
+ /** Singular, for "1 employer". */
41
+ labelSingular: string;
42
+ /** Everything Algolia matched, not the number of hits returned. */
43
+ nbHits: number;
44
+ /** Zero-based, matching Algolia. */
45
+ page: number;
46
+ nbPages: number;
47
+ hits: GlobalSearchHit[];
48
+ };
49
+ /** Keyed by index id, so the UI can render sections in whatever order it likes. */
50
+ export type GlobalSearchResults = {
51
+ [id in GlobalSearchIndexId]?: GlobalSearchIndexResults;
52
+ };
53
+ export type GlobalSearchIndexDefinition = {
54
+ id: GlobalSearchIndexId;
55
+ label: string;
56
+ labelSingular: string;
57
+ /** The Algolia index name — the unsorted, relevance-ordered replica. */
58
+ indexName: string;
59
+ /** Whether this institute has the product that owns these records. */
60
+ available: (institute?: InstituteData, user?: UserData) => boolean;
61
+ /** Restricts the index to records this user is allowed to see. */
62
+ filters: (user: UserData, institute?: InstituteData) => string;
63
+ /** Turns one raw hit into a row. */
64
+ toHit: (hit: any) => GlobalSearchHit;
65
+ };
66
+ /**
67
+ * The indexes the navbar search covers.
68
+ *
69
+ * Alumni, destinations surveys, leaver surveys and skills surveys belong here
70
+ * too once their Algolia indexes exist — each is one more entry, nothing else.
71
+ */
72
+ export declare const GLOBAL_SEARCH_INDEXES: GlobalSearchIndexDefinition[];
73
+ /**
74
+ * The indexes this institute can search, in the order they should be shown.
75
+ *
76
+ * @param {InstituteData} [institute] the signed-in institute.
77
+ * @param {UserData} [user] the signed-in user.
78
+ * @return {GlobalSearchIndexDefinition[]} the searchable indexes.
79
+ */
80
+ export declare const availableGlobalSearchIndexes: (institute?: InstituteData, user?: UserData) => GlobalSearchIndexDefinition[];
81
+ export type GlobalSearchParams = {
82
+ user: UserData;
83
+ institute?: InstituteData;
84
+ /** Whatever the user typed. Blank returns nothing rather than everything. */
85
+ query: string;
86
+ /** Restrict to specific indexes — how the drill-down asks for one index. */
87
+ indexIds?: GlobalSearchIndexId[];
88
+ hitsPerPage?: number;
89
+ /** Zero-based, matching Algolia. */
90
+ page?: number;
91
+ };
92
+ /**
93
+ * Search every index this institute can see, in one round trip.
94
+ *
95
+ * Indexes with no matches are still returned, with `nbHits: 0` and no hits, so
96
+ * a drill-down can say "no results" rather than render nothing. The overview UI
97
+ * is expected to skip empty sections itself.
98
+ *
99
+ * @param {GlobalSearchParams} params the search.
100
+ * @return {Promise<GlobalSearchResults>} results keyed by index id.
101
+ */
102
+ export declare const globalSearch: ({ user, institute, query, indexIds, hitsPerPage, page, }: GlobalSearchParams) => Promise<GlobalSearchResults>;
103
+ /**
104
+ * The total across every section — what the header count is drawn from.
105
+ *
106
+ * @param {GlobalSearchResults} results a search response.
107
+ * @return {number} the number of matches Algolia reported in total.
108
+ */
109
+ export declare const totalGlobalSearchHits: (results: GlobalSearchResults) => number;
110
+ /**
111
+ * Only the sections worth rendering, in registry order.
112
+ *
113
+ * @param {GlobalSearchResults} results a search response.
114
+ * @return {GlobalSearchIndexResults[]} sections that matched something.
115
+ */
116
+ export declare const nonEmptyGlobalSearchSections: (results: GlobalSearchResults) => GlobalSearchIndexResults[];
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ /**
3
+ * globalSearch — one query box, several Algolia indexes.
4
+ *
5
+ * The navbar search sends whatever the user typed here. Every index that the
6
+ * signed-in institute can see is queried in a single round trip, and the answer
7
+ * comes back keyed by index so the UI can render a section per index.
8
+ *
9
+ * Adding an index is meant to be a single entry in GLOBAL_SEARCH_INDEXES: name
10
+ * the Algolia index, say when an institute can see it, restrict it to that
11
+ * institute's records, and describe how one hit becomes a row.
12
+ */
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.nonEmptyGlobalSearchSections = exports.totalGlobalSearchHits = exports.globalSearch = exports.availableGlobalSearchIndexes = exports.GLOBAL_SEARCH_INDEXES = exports.GLOBAL_SEARCH_INDEX_HITS = exports.GLOBAL_SEARCH_OVERVIEW_HITS = void 0;
18
+ const algoliasearch_1 = __importDefault(require("algoliasearch"));
19
+ const util_1 = require("../../firebase/util");
20
+ const ALGOLIA_APP_ID = "XMPXCMUUOJ";
21
+ /** How many results a section shows before the user drills into one index. */
22
+ exports.GLOBAL_SEARCH_OVERVIEW_HITS = 5;
23
+ /** How many results one index shows per page once the user has drilled in. */
24
+ exports.GLOBAL_SEARCH_INDEX_HITS = 10;
25
+ const fullName = (forename, surname) => [forename, surname].filter(Boolean).join(" ").trim();
26
+ const joinParts = (...parts) => parts.filter(Boolean).join(" · ") || undefined;
27
+ /** Packages that run their own students, placements and cohorts. */
28
+ const isSchoolPackage = (institute) => institute?.package === "institutes-one" || institute?.package === "institutes-two";
29
+ /**
30
+ * The indexes the navbar search covers.
31
+ *
32
+ * Alumni, destinations surveys, leaver surveys and skills surveys belong here
33
+ * too once their Algolia indexes exist — each is one more entry, nothing else.
34
+ */
35
+ exports.GLOBAL_SEARCH_INDEXES = [
36
+ {
37
+ id: "placements",
38
+ label: "Placements",
39
+ labelSingular: "placement",
40
+ indexName: "placements",
41
+ available: (institute) => Boolean(isSchoolPackage(institute) && institute?.workExperience),
42
+ filters: (user) => `oId:${(0, util_1.quoteAlgoliaFilterIfNeeded)(user.oId)} AND draft:false`,
43
+ toHit: (hit) => ({
44
+ id: hit.objectID,
45
+ title: hit.title || hit.name || "Untitled placement",
46
+ subtitle: joinParts(hit.title && hit.name, fullName(hit.contactForename, hit.contactSurname) || undefined, hit.locality),
47
+ meta: hit.statusType,
48
+ path: `/institutes/cohorts/placements/${hit.objectID}`,
49
+ raw: hit,
50
+ }),
51
+ },
52
+ {
53
+ id: "employers",
54
+ label: "Employers",
55
+ labelSingular: "employer",
56
+ indexName: "providerContacts",
57
+ available: (institute) => Boolean(institute && institute.network !== false),
58
+ // The oId is a Firestore id, so it goes into the attribute path unquoted —
59
+ // the same shape algoliaProviderContactSearch already uses.
60
+ filters: (user) => `savedBy.${user.oId}.exists:true`,
61
+ toHit: (hit) => ({
62
+ id: hit.objectID,
63
+ title: hit.name || fullName(hit.contactForename, hit.contactSurname) || "Unnamed employer",
64
+ subtitle: joinParts(fullName(hit.contactForename, hit.contactSurname) || undefined, hit.providerEmail),
65
+ meta: hit.sector,
66
+ path: `/institutes/viewProviderContact/${hit.objectID}`,
67
+ raw: hit,
68
+ }),
69
+ },
70
+ {
71
+ id: "students",
72
+ label: "Students",
73
+ labelSingular: "student",
74
+ indexName: "users",
75
+ available: (institute) => isSchoolPackage(institute),
76
+ filters: (user) => `oId:${(0, util_1.quoteAlgoliaFilterIfNeeded)(user.oId)} AND userType:Students`,
77
+ toHit: (hit) => ({
78
+ id: hit.objectID,
79
+ title: fullName(hit.details?.forename, hit.details?.surname) || hit.email || "Unnamed student",
80
+ subtitle: hit.email,
81
+ meta: hit.details?.year || hit.details?.form,
82
+ path: `/institutes/users/${hit.objectID}`,
83
+ raw: hit,
84
+ }),
85
+ },
86
+ ];
87
+ /**
88
+ * The indexes this institute can search, in the order they should be shown.
89
+ *
90
+ * @param {InstituteData} [institute] the signed-in institute.
91
+ * @param {UserData} [user] the signed-in user.
92
+ * @return {GlobalSearchIndexDefinition[]} the searchable indexes.
93
+ */
94
+ const availableGlobalSearchIndexes = (institute, user) => exports.GLOBAL_SEARCH_INDEXES.filter((index) => index.available(institute, user));
95
+ exports.availableGlobalSearchIndexes = availableGlobalSearchIndexes;
96
+ /**
97
+ * Search every index this institute can see, in one round trip.
98
+ *
99
+ * Indexes with no matches are still returned, with `nbHits: 0` and no hits, so
100
+ * a drill-down can say "no results" rather than render nothing. The overview UI
101
+ * is expected to skip empty sections itself.
102
+ *
103
+ * @param {GlobalSearchParams} params the search.
104
+ * @return {Promise<GlobalSearchResults>} results keyed by index id.
105
+ */
106
+ const globalSearch = async ({ user, institute, query, indexIds, hitsPerPage = exports.GLOBAL_SEARCH_OVERVIEW_HITS, page = 0, }) => {
107
+ const trimmed = query?.trim();
108
+ if (!trimmed || !user?.algoliaKey)
109
+ return {};
110
+ const indexes = (0, exports.availableGlobalSearchIndexes)(institute, user)
111
+ .filter((index) => !indexIds || indexIds.includes(index.id));
112
+ if (!indexes.length)
113
+ return {};
114
+ const client = (0, algoliasearch_1.default)(ALGOLIA_APP_ID, user.algoliaKey);
115
+ const { results } = await client.multipleQueries(indexes.map((index) => ({
116
+ indexName: index.indexName,
117
+ query: trimmed,
118
+ params: {
119
+ filters: index.filters(user, institute),
120
+ hitsPerPage,
121
+ page,
122
+ },
123
+ })));
124
+ return Object.fromEntries(indexes.map((index, i) => {
125
+ const result = results[i];
126
+ return [index.id, {
127
+ id: index.id,
128
+ label: index.label,
129
+ labelSingular: index.labelSingular,
130
+ nbHits: result?.nbHits ?? 0,
131
+ page: result?.page ?? page,
132
+ nbPages: result?.nbPages ?? 0,
133
+ hits: (result?.hits ?? []).map(index.toHit),
134
+ }];
135
+ }));
136
+ };
137
+ exports.globalSearch = globalSearch;
138
+ /**
139
+ * The total across every section — what the header count is drawn from.
140
+ *
141
+ * @param {GlobalSearchResults} results a search response.
142
+ * @return {number} the number of matches Algolia reported in total.
143
+ */
144
+ const totalGlobalSearchHits = (results) => Object.values(results).reduce((total, index) => total + (index?.nbHits ?? 0), 0);
145
+ exports.totalGlobalSearchHits = totalGlobalSearchHits;
146
+ /**
147
+ * Only the sections worth rendering, in registry order.
148
+ *
149
+ * @param {GlobalSearchResults} results a search response.
150
+ * @return {GlobalSearchIndexResults[]} sections that matched something.
151
+ */
152
+ const nonEmptyGlobalSearchSections = (results) => exports.GLOBAL_SEARCH_INDEXES
153
+ .map((index) => results[index.id])
154
+ .filter((section) => Boolean(section && section.nbHits > 0));
155
+ exports.nonEmptyGlobalSearchSections = nonEmptyGlobalSearchSections;
156
+ //# sourceMappingURL=globalSearch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"globalSearch.js","sourceRoot":"","sources":["../../../src/features/search/globalSearch.ts"],"names":[],"mappings":"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"}
package/lib/hooks.d.ts CHANGED
@@ -602,13 +602,11 @@ export declare function useGetIndividualPlacementForPlacementPage({ user, placem
602
602
  onboardingStatus: "Add onboarding documents" | "Onboarding sent" | "Onboarding docs completed" | "Onboarding docs approved" | "Complete onboarding";
603
603
  setSkipStagePopup: import("react").Dispatch<import("react").SetStateAction<boolean>>;
604
604
  onboardingPopup: boolean;
605
- setViewExternalLinkPopup: import("react").Dispatch<import("react").SetStateAction<boolean>>;
606
605
  setOnboardingPopup: import("react").Dispatch<import("react").SetStateAction<boolean>>;
607
606
  setRejectELIPopup: import("react").Dispatch<import("react").SetStateAction<boolean>>;
608
607
  eliData: string | undefined;
609
608
  riskAssessmentURL: string;
610
609
  dbsCheckURL: string;
611
- setExternalLinkCopied: import("react").Dispatch<import("react").SetStateAction<boolean>>;
612
610
  skipStagePopup: boolean;
613
611
  snackbar: {
614
612
  open: boolean;
@@ -637,8 +635,6 @@ export declare function useGetIndividualPlacementForPlacementPage({ user, placem
637
635
  eliPopupOpen: boolean;
638
636
  rejectExternalDocPopup: false | "riskAssessment" | "dbsCheck";
639
637
  externalDocPopupOpen: false | "riskAssessment" | "dbsCheck";
640
- viewExternalLinkPopup: boolean;
641
- externalLinkCopied: boolean;
642
638
  uploadInsurance: boolean;
643
639
  uploadRA: boolean;
644
640
  uploadDBS: boolean;
package/lib/hooks.js CHANGED
@@ -2982,8 +2982,6 @@ function useGetIndividualPlacementForPlacementPage({ user, placementId, organisa
2982
2982
  const [dbsCheckURL, setDbsCheckURL] = (0, react_1.useState)("");
2983
2983
  const [uploadProviderDocPopup, setUploadProviderDocPopup] = (0, react_1.useState)();
2984
2984
  const [skipStagePopup, setSkipStagePopup] = (0, react_1.useState)(false);
2985
- const [viewExternalLinkPopup, setViewExternalLinkPopup] = (0, react_1.useState)(false);
2986
- const [externalLinkCopied, setExternalLinkCopied] = (0, react_1.useState)(false);
2987
2985
  const [uploadInsurance, setUploadInsurance] = (0, react_1.useState)(false);
2988
2986
  const [uploadRA, setUploadRA] = (0, react_1.useState)(false);
2989
2987
  const [uploadDBS, setUploadDBS] = (0, react_1.useState)(false);
@@ -3246,7 +3244,7 @@ function useGetIndividualPlacementForPlacementPage({ user, placementId, organisa
3246
3244
  throw new Error("Must be a student to withdraw.");
3247
3245
  await (0, firebase_1.executeCallable)("placement-withdraw", { placementId: placementId });
3248
3246
  };
3249
- return { placement, wStage, student, workflow, editable, withdrawFromPlacementPopup, addOnboardingDocsPopup, setFeedbackComplete, setAddOnboardingDocsPopup, dismissOnboardingPopup, setDismissOnboardingPopup, setWithdrawFromPlacementPopup, withdrawFromPlacement, onFlagClick, setUploadInsurance, setUploadProviderDocPopup, setUploadRA, setUploadDBS, onboardingStatus, setSkipStagePopup, onboardingPopup, setViewExternalLinkPopup, setOnboardingPopup, setRejectELIPopup, eliData, riskAssessmentURL, dbsCheckURL, setExternalLinkCopied, skipStagePopup, snackbar, setSnackbar, cohort, disableEmail, rejectELIPopup, eliPopupOpen, rejectExternalDocPopup, externalDocPopupOpen, viewExternalLinkPopup, externalLinkCopied, uploadInsurance, uploadRA, uploadDBS, editStage, sendEmail, canEdit, approveELI, setEliPopupOpen, uploadProviderDocPopup, rejectELI, setRejectExternalDocPopup, setExternalDocPopupOpen, approveProviderDoc, rejectProviderDoc, manuallyConfigureProvider, institute, shareStudentRequestPopup, setShareStudentRequestPopup };
3247
+ return { placement, wStage, student, workflow, editable, withdrawFromPlacementPopup, addOnboardingDocsPopup, setFeedbackComplete, setAddOnboardingDocsPopup, dismissOnboardingPopup, setDismissOnboardingPopup, setWithdrawFromPlacementPopup, withdrawFromPlacement, onFlagClick, setUploadInsurance, setUploadProviderDocPopup, setUploadRA, setUploadDBS, onboardingStatus, setSkipStagePopup, onboardingPopup, setOnboardingPopup, setRejectELIPopup, eliData, riskAssessmentURL, dbsCheckURL, skipStagePopup, snackbar, setSnackbar, cohort, disableEmail, rejectELIPopup, eliPopupOpen, rejectExternalDocPopup, externalDocPopupOpen, uploadInsurance, uploadRA, uploadDBS, editStage, sendEmail, canEdit, approveELI, setEliPopupOpen, uploadProviderDocPopup, rejectELI, setRejectExternalDocPopup, setExternalDocPopupOpen, approveProviderDoc, rejectProviderDoc, manuallyConfigureProvider, institute, shareStudentRequestPopup, setShareStudentRequestPopup };
3250
3248
  }
3251
3249
  function useOnboardingPopup({ onboarding, providerId, placementId, user, onClose }) {
3252
3250
  const [fileUploadPopup, setFileUploadPopup] = (0, react_1.useState)(false);