|
1
|
|
|
import { createSelector } from "reselect"; |
|
2
|
|
|
import createCachedSelector from "re-reselect"; |
|
3
|
|
|
import { RootState } from "../store"; |
|
4
|
|
|
import { EntityState, UiState, ExperienceSection } from "./experienceReducer"; |
|
5
|
|
|
import { |
|
6
|
|
|
ExperienceWork, |
|
7
|
|
|
ExperienceEducation, |
|
8
|
|
|
ExperienceCommunity, |
|
9
|
|
|
ExperienceAward, |
|
10
|
|
|
ExperiencePersonal, |
|
11
|
|
|
ExperienceSkill, |
|
12
|
|
|
Experience, |
|
13
|
|
|
} from "../../models/types"; |
|
14
|
|
|
import { notEmpty, hasKey } from "../../helpers/queries"; |
|
15
|
|
|
|
|
16
|
|
|
const entities = (state: RootState): EntityState => state.experience.entities; |
|
17
|
|
|
const ui = (state: RootState): UiState => state.experience.ui; |
|
18
|
|
|
|
|
19
|
|
|
interface ExperienceSet { |
|
20
|
|
|
work: ExperienceWork[]; |
|
21
|
|
|
education: ExperienceEducation[]; |
|
22
|
|
|
community: ExperienceCommunity[]; |
|
23
|
|
|
award: ExperienceAward[]; |
|
24
|
|
|
personal: ExperiencePersonal[]; |
|
25
|
|
|
} |
|
26
|
|
|
|
|
27
|
|
|
const getWorkState = (state: RootState): ExperienceSection<ExperienceWork> => |
|
28
|
|
|
entities(state).work; |
|
29
|
|
|
const getEducationState = ( |
|
30
|
|
|
state: RootState, |
|
31
|
|
|
): ExperienceSection<ExperienceEducation> => entities(state).education; |
|
32
|
|
|
const getCommunityState = ( |
|
33
|
|
|
state: RootState, |
|
34
|
|
|
): ExperienceSection<ExperienceCommunity> => entities(state).community; |
|
35
|
|
|
const getAwardState = (state: RootState): ExperienceSection<ExperienceAward> => |
|
36
|
|
|
entities(state).award; |
|
37
|
|
|
const getPersonalState = ( |
|
38
|
|
|
state: RootState, |
|
39
|
|
|
): ExperienceSection<ExperiencePersonal> => entities(state).personal; |
|
40
|
|
|
|
|
41
|
|
|
const stateByType = { |
|
42
|
|
|
work: getWorkState, |
|
43
|
|
|
education: getEducationState, |
|
44
|
|
|
community: getCommunityState, |
|
45
|
|
|
award: getAwardState, |
|
46
|
|
|
personal: getPersonalState, |
|
47
|
|
|
}; |
|
48
|
|
|
|
|
49
|
|
|
function getStateOfType<T extends keyof typeof stateByType>( |
|
50
|
|
|
type: T, |
|
51
|
|
|
): typeof stateByType[T] { |
|
52
|
|
|
return stateByType[type]; |
|
53
|
|
|
} |
|
54
|
|
|
|
|
55
|
|
|
const extractId = (state: RootState, ownProps: { id: number }): number => |
|
56
|
|
|
ownProps.id; |
|
57
|
|
|
const extractApplicantId = ( |
|
58
|
|
|
state: RootState, |
|
59
|
|
|
ownProps: { applicantId: number }, |
|
60
|
|
|
): number => ownProps.applicantId; |
|
61
|
|
|
const extractApplicationId = ( |
|
62
|
|
|
state: RootState, |
|
63
|
|
|
ownProps: { applicationId: number }, |
|
64
|
|
|
): number => ownProps.applicationId; |
|
65
|
|
|
|
|
66
|
|
|
function experienceByApplicant<T>( |
|
67
|
|
|
experienceState: ExperienceSection<T>, |
|
68
|
|
|
applicantId: number, |
|
69
|
|
|
): T[] { |
|
70
|
|
|
const idsForApplicant = experienceState.idsByApplicant[applicantId]; |
|
71
|
|
|
return idsForApplicant |
|
72
|
|
|
? idsForApplicant.map((id) => experienceState.byId[id]).filter(notEmpty) |
|
73
|
|
|
: []; |
|
74
|
|
|
} |
|
75
|
|
|
|
|
76
|
|
|
function experienceByApplication<T>( |
|
77
|
|
|
experienceState: ExperienceSection<T>, |
|
78
|
|
|
applicationId: number, |
|
79
|
|
|
): T[] { |
|
80
|
|
|
const idsForApplication = experienceState.idsByApplication[applicationId]; |
|
81
|
|
|
return idsForApplication |
|
82
|
|
|
? idsForApplication.map((id) => experienceState.byId[id]).filter(notEmpty) |
|
83
|
|
|
: []; |
|
84
|
|
|
} |
|
85
|
|
|
|
|
86
|
|
|
function experienceById<T>( |
|
87
|
|
|
experienceState: ExperienceSection<T>, |
|
88
|
|
|
id: number, |
|
89
|
|
|
): T | null { |
|
90
|
|
|
return hasKey(experienceState.byId, id) ? experienceState.byId[id] : null; |
|
91
|
|
|
} |
|
92
|
|
|
|
|
93
|
|
|
function getExperienceTypeByApplicant<T>( |
|
94
|
|
|
getState: (state: RootState) => ExperienceSection<T>, |
|
95
|
|
|
) { |
|
96
|
|
|
return createCachedSelector( |
|
97
|
|
|
getState, |
|
98
|
|
|
extractApplicantId, |
|
99
|
|
|
experienceByApplicant, |
|
100
|
|
|
)(extractApplicantId); |
|
101
|
|
|
} |
|
102
|
|
|
function getExperienceTypeByApplication<T>( |
|
103
|
|
|
getState: (state: RootState) => ExperienceSection<T>, |
|
104
|
|
|
) { |
|
105
|
|
|
return createCachedSelector( |
|
106
|
|
|
getState, |
|
107
|
|
|
extractApplicationId, |
|
108
|
|
|
experienceByApplication, |
|
109
|
|
|
)(extractApplicationId); |
|
110
|
|
|
} |
|
111
|
|
|
|
|
112
|
|
|
export const getWorkByApplicant = getExperienceTypeByApplicant(getWorkState); |
|
113
|
|
|
export const getEducationByApplicant = getExperienceTypeByApplicant( |
|
114
|
|
|
getEducationState, |
|
115
|
|
|
); |
|
116
|
|
|
export const getCommunityByApplicant = getExperienceTypeByApplicant( |
|
117
|
|
|
getCommunityState, |
|
118
|
|
|
); |
|
119
|
|
|
export const getAwardByApplicant = getExperienceTypeByApplicant(getAwardState); |
|
120
|
|
|
export const getPersonalByApplicant = getExperienceTypeByApplicant( |
|
121
|
|
|
getPersonalState, |
|
122
|
|
|
); |
|
123
|
|
|
|
|
124
|
|
|
export const getExperienceByApplicant = createSelector( |
|
125
|
|
|
getWorkByApplicant, |
|
126
|
|
|
getEducationByApplicant, |
|
127
|
|
|
getCommunityByApplicant, |
|
128
|
|
|
getAwardByApplicant, |
|
129
|
|
|
getPersonalByApplicant, |
|
130
|
|
|
(work, education, community, award, personal) => ({ |
|
131
|
|
|
work, |
|
132
|
|
|
education, |
|
133
|
|
|
community, |
|
134
|
|
|
award, |
|
135
|
|
|
personal, |
|
136
|
|
|
}), |
|
137
|
|
|
); |
|
138
|
|
|
|
|
139
|
|
|
export const getWorkByApplication = getExperienceTypeByApplication( |
|
140
|
|
|
getWorkState, |
|
141
|
|
|
); |
|
142
|
|
|
export const getEducationByApplication = getExperienceTypeByApplication( |
|
143
|
|
|
getEducationState, |
|
144
|
|
|
); |
|
145
|
|
|
export const getCommunityByApplication = getExperienceTypeByApplication( |
|
146
|
|
|
getCommunityState, |
|
147
|
|
|
); |
|
148
|
|
|
export const getAwardByApplication = getExperienceTypeByApplication( |
|
149
|
|
|
getAwardState, |
|
150
|
|
|
); |
|
151
|
|
|
export const getPersonalByApplication = getExperienceTypeByApplication( |
|
152
|
|
|
getPersonalState, |
|
153
|
|
|
); |
|
154
|
|
|
|
|
155
|
|
|
export const getExperienceByApplication = createSelector( |
|
156
|
|
|
getWorkByApplication, |
|
157
|
|
|
getEducationByApplication, |
|
158
|
|
|
getCommunityByApplication, |
|
159
|
|
|
getAwardByApplication, |
|
160
|
|
|
getPersonalByApplication, |
|
161
|
|
|
(work, education, community, award, personal) => ({ |
|
162
|
|
|
work, |
|
163
|
|
|
education, |
|
164
|
|
|
community, |
|
165
|
|
|
award, |
|
166
|
|
|
personal, |
|
167
|
|
|
}), |
|
168
|
|
|
); |
|
169
|
|
|
|
|
170
|
|
|
function getExperienceTypeById<T>( |
|
171
|
|
|
getState: (state: RootState) => ExperienceSection<T>, |
|
172
|
|
|
) { |
|
173
|
|
|
return createCachedSelector(getState, extractId, experienceById)(extractId); |
|
174
|
|
|
} |
|
175
|
|
|
|
|
176
|
|
|
export const getWorkById = getExperienceTypeById(getWorkState); |
|
177
|
|
|
export const getEducationById = getExperienceTypeById(getEducationState); |
|
178
|
|
|
export const getCommunityById = getExperienceTypeById(getCommunityState); |
|
179
|
|
|
export const getAwardById = getExperienceTypeById(getAwardState); |
|
180
|
|
|
export const getPersonalById = getExperienceTypeById(getPersonalState); |
|
181
|
|
|
|
|
182
|
|
|
export const getUpdatingByApplicant = ( |
|
183
|
|
|
state: RootState, |
|
184
|
|
|
{ applicantId }: { applicantId: number }, |
|
185
|
|
|
): boolean => { |
|
186
|
|
|
return ui(state).updatingByApplicant[applicantId] ?? false; |
|
187
|
|
|
}; |
|
188
|
|
|
|
|
189
|
|
|
export const getUpdatingByApplication = ( |
|
190
|
|
|
state: RootState, |
|
191
|
|
|
{ applicationId }: { applicationId: number }, |
|
192
|
|
|
): boolean => { |
|
193
|
|
|
return ui(state).updatingByApplication[applicationId] ?? false; |
|
194
|
|
|
}; |
|
195
|
|
|
|
|
196
|
|
|
export const getUpdatingByTypeAndId = ( |
|
197
|
|
|
state: RootState, |
|
198
|
|
|
{ id, type }: { id: number; type: keyof UiState["updatingByTypeAndId"] }, |
|
199
|
|
|
): boolean => { |
|
200
|
|
|
return ui(state).updatingByTypeAndId[type][id] ?? false; |
|
201
|
|
|
}; |
|
202
|
|
|
|
|
203
|
|
|
export const getExperienceSkillById = ( |
|
204
|
|
|
state: RootState, |
|
205
|
|
|
id: number, |
|
206
|
|
|
): ExperienceSkill | null => { |
|
207
|
|
|
const expSkills = entities(state).experienceSkills.byId; |
|
208
|
|
|
return hasKey(expSkills, id) ? expSkills[id] : null; |
|
209
|
|
|
}; |
|
210
|
|
|
|
|
211
|
|
|
const getExperienceSkillByIdState = (state: RootState) => |
|
212
|
|
|
entities(state).experienceSkills.byId; |
|
213
|
|
|
|
|
214
|
|
|
const getExperienceSkillByWorkState = (state: RootState) => |
|
215
|
|
|
entities(state).experienceSkills.idsByWork; |
|
216
|
|
|
const getExperienceSkillByEducationState = (state: RootState) => |
|
217
|
|
|
entities(state).experienceSkills.idsByEducation; |
|
218
|
|
|
const getExperienceSkillByCommunityState = (state: RootState) => |
|
219
|
|
|
entities(state).experienceSkills.idsByCommunity; |
|
220
|
|
|
const getExperienceSkillByAwardState = (state: RootState) => |
|
221
|
|
|
entities(state).experienceSkills.idsByAward; |
|
222
|
|
|
const getExperienceSkillByPersonalState = (state: RootState) => |
|
223
|
|
|
entities(state).experienceSkills.idsByPersonal; |
|
224
|
|
|
|
|
225
|
|
|
export const getExperienceSkillsByWork = createCachedSelector( |
|
226
|
|
|
getExperienceSkillByIdState, |
|
227
|
|
|
getExperienceSkillByWorkState, |
|
228
|
|
|
(state: RootState, { workId }: { workId: number }) => workId, |
|
229
|
|
|
(expSkillById, idsByWork, workId): ExperienceSkill[] => { |
|
230
|
|
|
const expSkillIds = idsByWork[workId] ?? []; |
|
231
|
|
|
return expSkillIds.map((id) => expSkillById[id]).filter(notEmpty); |
|
232
|
|
|
}, |
|
233
|
|
|
)((state, { workId }) => workId); |
|
234
|
|
|
|
|
235
|
|
|
export const getExperienceSkillsByEducation = createCachedSelector( |
|
236
|
|
|
getExperienceSkillByIdState, |
|
237
|
|
|
getExperienceSkillByEducationState, |
|
238
|
|
|
(state: RootState, { educationId }: { educationId: number }) => educationId, |
|
239
|
|
|
(expSkillById, idsByWork, educationId): ExperienceSkill[] => { |
|
240
|
|
|
const expSkillIds = idsByWork[educationId] ?? []; |
|
241
|
|
|
return expSkillIds.map((id) => expSkillById[id]).filter(notEmpty); |
|
242
|
|
|
}, |
|
243
|
|
|
)((state, { educationId }) => educationId); |
|
244
|
|
|
|
|
245
|
|
|
export const getExperienceSkillsByCommunity = createCachedSelector( |
|
246
|
|
|
getExperienceSkillByIdState, |
|
247
|
|
|
getExperienceSkillByCommunityState, |
|
248
|
|
|
(state: RootState, { communityId }: { communityId: number }) => communityId, |
|
249
|
|
|
(expSkillById, idsByWork, communityId): ExperienceSkill[] => { |
|
250
|
|
|
const expSkillIds = idsByWork[communityId] ?? []; |
|
251
|
|
|
return expSkillIds.map((id) => expSkillById[id]).filter(notEmpty); |
|
252
|
|
|
}, |
|
253
|
|
|
)((state, { communityId }) => communityId); |
|
254
|
|
|
|
|
255
|
|
|
export const getExperienceSkillsByAward = createCachedSelector( |
|
256
|
|
|
getExperienceSkillByIdState, |
|
257
|
|
|
getExperienceSkillByAwardState, |
|
258
|
|
|
(state: RootState, { awardId }: { awardId: number }) => awardId, |
|
259
|
|
|
(expSkillById, idsByWork, awardId): ExperienceSkill[] => { |
|
260
|
|
|
const expSkillIds = idsByWork[awardId] ?? []; |
|
261
|
|
|
return expSkillIds.map((id) => expSkillById[id]).filter(notEmpty); |
|
262
|
|
|
}, |
|
263
|
|
|
)((state, { awardId }) => awardId); |
|
264
|
|
|
|
|
265
|
|
|
export const getExperienceSkillsByPersonal = createCachedSelector( |
|
266
|
|
|
getExperienceSkillByIdState, |
|
267
|
|
|
getExperienceSkillByPersonalState, |
|
268
|
|
|
(state: RootState, { personalId }: { personalId: number }) => personalId, |
|
269
|
|
|
(expSkillById, idsByWork, personalId): ExperienceSkill[] => { |
|
270
|
|
|
const expSkillIds = idsByWork[personalId] ?? []; |
|
271
|
|
|
return expSkillIds.map((id) => expSkillById[id]).filter(notEmpty); |
|
272
|
|
|
}, |
|
273
|
|
|
)((state, { personalId }) => personalId); |
|
274
|
|
|
|
|
275
|
|
|
export const getExperienceSkillIdsByWork = ( |
|
276
|
|
|
state: RootState, |
|
277
|
|
|
id: number, |
|
278
|
|
|
): number[] => entities(state).experienceSkills.idsByWork[id] ?? []; |
|
279
|
|
|
export const getExperienceSkillIdsByEducation = ( |
|
280
|
|
|
state: RootState, |
|
281
|
|
|
id: number, |
|
282
|
|
|
): number[] => entities(state).experienceSkills.idsByEducation[id] ?? []; |
|
283
|
|
|
export const getExperienceSkillIdsByCommunity = ( |
|
284
|
|
|
state: RootState, |
|
285
|
|
|
id: number, |
|
286
|
|
|
): number[] => entities(state).experienceSkills.idsByCommunity[id] ?? []; |
|
287
|
|
|
export const getExperienceSkillIdsByAward = ( |
|
288
|
|
|
state: RootState, |
|
289
|
|
|
id: number, |
|
290
|
|
|
): number[] => entities(state).experienceSkills.idsByAward[id] ?? []; |
|
291
|
|
|
export const getExperienceSkillIdsByPersonal = ( |
|
292
|
|
|
state: RootState, |
|
293
|
|
|
id: number, |
|
294
|
|
|
): number[] => entities(state).experienceSkills.idsByPersonal[id] ?? []; |
|
295
|
|
|
|
|
296
|
|
|
export const getExperienceSkillUpdating = ( |
|
297
|
|
|
state: RootState, |
|
298
|
|
|
id: number, |
|
299
|
|
|
): boolean => { |
|
300
|
|
|
return ui(state).updatingExperienceSkill[id] ?? false; |
|
301
|
|
|
}; |
|
302
|
|
|
|
|
303
|
|
|
function getExperienceSkillsByGroup<T>( |
|
304
|
|
|
getExperience: ( |
|
305
|
|
|
state: RootState, |
|
306
|
|
|
props: T, |
|
307
|
|
|
) => { |
|
308
|
|
|
award: ExperienceAward[]; |
|
309
|
|
|
community: ExperienceCommunity[]; |
|
310
|
|
|
education: ExperienceEducation[]; |
|
311
|
|
|
personal: ExperiencePersonal[]; |
|
312
|
|
|
work: ExperienceWork[]; |
|
313
|
|
|
}, |
|
314
|
|
|
) { |
|
315
|
|
|
return createCachedSelector( |
|
316
|
|
|
getExperience, |
|
317
|
|
|
getExperienceSkillByIdState, |
|
318
|
|
|
getExperienceSkillByAwardState, |
|
319
|
|
|
getExperienceSkillByCommunityState, |
|
320
|
|
|
getExperienceSkillByEducationState, |
|
321
|
|
|
getExperienceSkillByPersonalState, |
|
322
|
|
|
getExperienceSkillByWorkState, |
|
323
|
|
|
( |
|
324
|
|
|
experiences, |
|
325
|
|
|
expSkills, |
|
326
|
|
|
idsByAward, |
|
327
|
|
|
idsByCommunity, |
|
328
|
|
|
idsByEducation, |
|
329
|
|
|
idsByPersonal, |
|
330
|
|
|
idsByWork, |
|
331
|
|
|
): ExperienceSkill[] => { |
|
332
|
|
|
const experienceToSkillsFactory = (expIdToSkillId: { |
|
333
|
|
|
[expId: number]: number[]; |
|
334
|
|
|
}) => ( |
|
335
|
|
|
experienceSkills: ExperienceSkill[], |
|
336
|
|
|
experience: Experience, |
|
337
|
|
|
): ExperienceSkill[] => { |
|
338
|
|
|
const expSkillIds = hasKey(expIdToSkillId, experience.id) |
|
339
|
|
|
? expIdToSkillId[experience.id] |
|
340
|
|
|
: []; |
|
341
|
|
|
const newExpSkills = expSkillIds |
|
342
|
|
|
.map((id) => expSkills[id]) |
|
343
|
|
|
.filter(notEmpty); |
|
344
|
|
|
return [...newExpSkills, ...experienceSkills]; |
|
345
|
|
|
}; |
|
346
|
|
|
|
|
347
|
|
|
const awardSkills = experiences.award.reduce( |
|
348
|
|
|
experienceToSkillsFactory(idsByAward), |
|
349
|
|
|
[], |
|
350
|
|
|
); |
|
351
|
|
|
const communitySkills = experiences.community.reduce( |
|
352
|
|
|
experienceToSkillsFactory(idsByCommunity), |
|
353
|
|
|
[], |
|
354
|
|
|
); |
|
355
|
|
|
const educationSkills = experiences.education.reduce( |
|
356
|
|
|
experienceToSkillsFactory(idsByEducation), |
|
357
|
|
|
[], |
|
358
|
|
|
); |
|
359
|
|
|
const personalSkills = experiences.personal.reduce( |
|
360
|
|
|
experienceToSkillsFactory(idsByPersonal), |
|
361
|
|
|
[], |
|
362
|
|
|
); |
|
363
|
|
|
const workSkills = experiences.work.reduce( |
|
364
|
|
|
experienceToSkillsFactory(idsByWork), |
|
365
|
|
|
[], |
|
366
|
|
|
); |
|
367
|
|
|
return [ |
|
368
|
|
|
...awardSkills, |
|
369
|
|
|
...communitySkills, |
|
370
|
|
|
...educationSkills, |
|
371
|
|
|
...personalSkills, |
|
372
|
|
|
...workSkills, |
|
373
|
|
|
]; |
|
374
|
|
|
}, |
|
375
|
|
|
); |
|
376
|
|
|
} |
|
377
|
|
|
|
|
378
|
|
|
export const getExperienceSkillsByApplication = getExperienceSkillsByGroup( |
|
379
|
|
|
getExperienceByApplication, |
|
380
|
|
|
)((state, { applicationId }) => applicationId); |
|
381
|
|
|
|
|
382
|
|
|
export const getExperienceSkillsByApplicant = getExperienceSkillsByGroup( |
|
383
|
|
|
getExperienceByApplicant, |
|
384
|
|
|
)((state, { applicantId }) => applicantId); |
|
385
|
|
|
|