1
|
|
|
import isEqual from "lodash/isEqual"; |
2
|
|
|
import { createSelector } from "reselect"; |
3
|
|
|
import createCachedSelector from "re-reselect"; |
4
|
|
|
import { RootState } from "../store"; |
5
|
|
|
import { |
6
|
|
|
Job, |
7
|
|
|
Criteria, |
8
|
|
|
JobPosterKeyTask, |
9
|
|
|
Comment, |
10
|
|
|
JobPosterQuestion, |
11
|
|
|
} from "../../models/types"; |
12
|
|
|
import { hasKey, getId } from "../../helpers/queries"; |
13
|
|
|
import { EntityState, UiState } from "./jobReducer"; |
14
|
|
|
|
15
|
|
|
const entities = (state: RootState): EntityState => state.jobs.entities; |
16
|
|
|
const ui = (state: RootState): UiState => state.jobs.ui; |
17
|
|
|
|
18
|
|
|
const getJobState = (state: RootState): { [id: number]: Job } => |
19
|
|
|
entities(state).jobs.byId; |
20
|
|
|
|
21
|
|
|
const getJobEditState = (state: RootState): { [id: number]: Job } => |
22
|
|
|
entities(state).jobEdits; |
23
|
|
|
|
24
|
|
|
const getJobUpdatingState = (state: RootState): { [id: number]: boolean } => |
25
|
|
|
ui(state).jobUpdating; |
26
|
|
|
|
27
|
|
|
export const getCriteriaState = ( |
28
|
|
|
state: RootState, |
29
|
|
|
): { [id: number]: Criteria } => entities(state).criteria.byId; |
30
|
|
|
|
31
|
|
|
const getJobPosterQuestionsState = ( |
32
|
|
|
state: RootState, |
33
|
|
|
): { [id: number]: JobPosterQuestion } => |
34
|
|
|
entities(state).jobPosterQuestions.byId; |
35
|
|
|
|
36
|
|
|
const getTaskState = ( |
37
|
|
|
state: RootState, |
38
|
|
|
): { [jobId: number]: JobPosterKeyTask[] } => entities(state).tasks.byJobId; |
39
|
|
|
|
40
|
|
|
const getCriteriaForJobUpdatingState = ( |
41
|
|
|
state: RootState, |
42
|
|
|
): { [id: number]: boolean } => ui(state).criteriaUpdatingByJob; |
43
|
|
|
|
44
|
|
|
const getTasksForJobUpdatingState = ( |
45
|
|
|
state: RootState, |
46
|
|
|
): { [id: number]: boolean } => ui(state).tasksUpdatingByJob; |
47
|
|
|
|
48
|
|
|
export const getAllJobs = createSelector(getJobState, (jobState): Job[] => |
49
|
|
|
Object.values(jobState), |
50
|
|
|
); |
51
|
|
|
|
52
|
|
|
export const getAllJobsInDept = createCachedSelector( |
53
|
|
|
getAllJobs, |
54
|
|
|
(state: RootState, ownProps: { departmentId: number }): number => |
55
|
|
|
ownProps.departmentId, |
56
|
|
|
(jobs, departmentId): Job[] => |
57
|
|
|
jobs.filter((job) => job.department_id === departmentId), |
58
|
|
|
)((state, ownProps): number => ownProps.departmentId); |
59
|
|
|
|
60
|
|
|
export const getJob = createCachedSelector( |
61
|
|
|
getJobState, |
62
|
|
|
(state: RootState, ownProps: { jobId: number }): number => ownProps.jobId, |
63
|
|
|
(jobState, jobId): Job | null => |
64
|
|
|
hasKey(jobState, jobId) ? jobState[jobId] : null, |
65
|
|
|
)((state, ownProps): number => ownProps.jobId); |
66
|
|
|
|
67
|
|
|
export const getSelectedJob = (state: RootState): Job | null => { |
68
|
|
|
const selectedId = ui(state).selectedJobId; |
69
|
|
|
return selectedId ? getJob(state, { jobId: selectedId }) : null; |
70
|
|
|
}; |
71
|
|
|
|
72
|
|
|
export const getEditJob = createCachedSelector( |
73
|
|
|
getJobEditState, |
74
|
|
|
(state: RootState, ownProps: { jobId: number }): number => ownProps.jobId, |
75
|
|
|
(jobState, jobId): Job | null => |
76
|
|
|
hasKey(jobState, jobId) ? jobState[jobId] : null, |
77
|
|
|
)((state, ownProps): number => ownProps.jobId); |
78
|
|
|
|
79
|
|
|
export const getJobIndexIsUpdating = (state: RootState): boolean => { |
80
|
|
|
return ui(state).jobIndexUpdating; |
81
|
|
|
}; |
82
|
|
|
|
83
|
|
|
export const getJobIsUpdating = (state: RootState, id: number): boolean => { |
84
|
|
|
const updating = getJobUpdatingState(state); |
85
|
|
|
return ( |
86
|
|
|
getJobIndexIsUpdating(state) || |
87
|
|
|
(hasKey(updating, id) ? updating[id] : false) |
88
|
|
|
); |
89
|
|
|
}; |
90
|
|
|
|
91
|
|
|
export const getJobIsEdited = createCachedSelector( |
92
|
|
|
getJob, |
93
|
|
|
getEditJob, |
94
|
|
|
(canon, edited): boolean => edited !== null && !isEqual(canon, edited), |
95
|
|
|
)((state, ownProps): number => ownProps.jobId); |
96
|
|
|
|
97
|
|
|
export const getCriteria = createSelector( |
98
|
|
|
getCriteriaState, |
99
|
|
|
(criteriaState): Criteria[] => Object.values(criteriaState), |
100
|
|
|
); |
101
|
|
|
|
102
|
|
|
export const getCriteriaById = ( |
103
|
|
|
state: RootState, |
104
|
|
|
{ criterionId }: { criterionId: number }, |
105
|
|
|
): Criteria | null => |
106
|
|
|
hasKey(entities(state).criteria.byId, criterionId) |
107
|
|
|
? entities(state).criteria.byId[criterionId] |
108
|
|
|
: null; |
109
|
|
|
|
110
|
|
|
export const getCreatingJob = (state: RootState): boolean => |
111
|
|
|
ui(state).creatingJob; |
112
|
|
|
|
113
|
|
|
export const getCriteriaByJob = createCachedSelector( |
114
|
|
|
getCriteria, |
115
|
|
|
(state: RootState, ownProps: { jobId: number }): number => ownProps.jobId, |
116
|
|
|
(criteria, jobId: number): Criteria[] => |
117
|
|
|
criteria.filter((criterion): boolean => criterion.job_poster_id === jobId), |
118
|
|
|
)((state, ownProps): number => ownProps.jobId); |
119
|
|
|
|
120
|
|
|
export const getCriteriaOfTypeByJob = createCachedSelector( |
121
|
|
|
getCriteriaByJob, |
122
|
|
|
(state: RootState, props: { criteriaTypeId: number }): number => |
123
|
|
|
props.criteriaTypeId, |
124
|
|
|
(criteria, criteriaTypeId): Criteria[] => |
125
|
|
|
criteria.filter( |
126
|
|
|
(criterion: Criteria): boolean => |
127
|
|
|
criterion.criteria_type_id === criteriaTypeId, |
128
|
|
|
), |
129
|
|
|
)((state, props): string => `${props.jobId}:${props.criteriaTypeId}`); |
130
|
|
|
|
131
|
|
|
export const getCriteriaIdsOfTypeByJob = createCachedSelector( |
132
|
|
|
getCriteriaOfTypeByJob, |
133
|
|
|
(criteria): number[] => criteria.map(getId), |
134
|
|
|
)((state, props): string => `${props.jobId}:${props.criteriaTypeId}`); |
135
|
|
|
|
136
|
|
|
export const getCriteriaIdsByJob = createCachedSelector( |
137
|
|
|
getCriteriaByJob, |
138
|
|
|
(criteria): number[] => criteria.map(getId), |
139
|
|
|
)((state, ownProps): number => ownProps.jobId); |
140
|
|
|
|
141
|
|
|
export const getCriteriaForJobIsUpdating = ( |
142
|
|
|
state: RootState, |
143
|
|
|
id: number, |
144
|
|
|
): boolean => { |
145
|
|
|
const updating = getCriteriaForJobUpdatingState(state); |
146
|
|
|
return hasKey(updating, id) ? updating[id] : false; |
147
|
|
|
}; |
148
|
|
|
|
149
|
|
|
export const getTasksForJobIsUpdating = ( |
150
|
|
|
state: RootState, |
151
|
|
|
id: number, |
152
|
|
|
): boolean => { |
153
|
|
|
const updating = getTasksForJobUpdatingState(state); |
154
|
|
|
return hasKey(updating, id) ? updating[id] : false; |
155
|
|
|
}; |
156
|
|
|
|
157
|
|
|
export const getTasksByJob = createCachedSelector( |
158
|
|
|
getTaskState, |
159
|
|
|
(state: RootState, ownProps: { jobId: number }): number => ownProps.jobId, |
160
|
|
|
(tasksByJob, jobId): JobPosterKeyTask[] => |
161
|
|
|
hasKey(tasksByJob, jobId) ? tasksByJob[jobId] : [], |
162
|
|
|
)((state, ownProps): number => ownProps.jobId); |
163
|
|
|
|
164
|
|
|
export const getCommentsState = (state: RootState): { [id: number]: Comment } => |
165
|
|
|
state.jobs.entities.comments.byJobId; |
166
|
|
|
|
167
|
|
|
export const getComments = createSelector( |
168
|
|
|
getCommentsState, |
169
|
|
|
(commentsState): Comment[] => Object.values(commentsState), |
170
|
|
|
); |
171
|
|
|
|
172
|
|
|
export const sortComments = (comments: Comment[]): Comment[] => { |
173
|
|
|
const comparator = (a: Comment, b: Comment): number => { |
174
|
|
|
return b.created_at.getTime() - a.created_at.getTime(); |
175
|
|
|
}; |
176
|
|
|
return comments.sort(comparator); |
177
|
|
|
}; |
178
|
|
|
|
179
|
|
|
export const getSortedComments = createSelector(getComments, sortComments); |
180
|
|
|
|
181
|
|
|
export const getSortedFilteredComments = createCachedSelector( |
182
|
|
|
getSortedComments, |
183
|
|
|
( |
184
|
|
|
state: RootState, |
185
|
|
|
ownProps: { |
186
|
|
|
filterComments?: (comment: Comment) => boolean; |
187
|
|
|
generalLocation: string; |
188
|
|
|
}, |
189
|
|
|
) => ownProps.filterComments, |
190
|
|
|
(comments, filterComments): Comment[] => { |
191
|
|
|
return filterComments !== undefined |
192
|
|
|
? comments.filter(filterComments) |
193
|
|
|
: comments; |
194
|
|
|
}, |
195
|
|
|
)((state, ownProps) => ownProps.generalLocation); |
196
|
|
|
|
197
|
|
|
export const fetchingComments = (state: RootState): boolean => |
198
|
|
|
ui(state).fetchingComments; |
199
|
|
|
|
200
|
|
|
export const getJobPosterQuestions = createSelector( |
201
|
|
|
getJobPosterQuestionsState, |
202
|
|
|
(jobPosterQuestionsState): JobPosterQuestion[] => |
203
|
|
|
Object.values(jobPosterQuestionsState), |
204
|
|
|
); |
205
|
|
|
|
206
|
|
|
export const getJobPosterQuestionsByJob = createCachedSelector( |
207
|
|
|
getJobPosterQuestions, |
208
|
|
|
(state: RootState, ownProps: { jobId: number }): number => ownProps.jobId, |
209
|
|
|
(jobPosterQuestions, jobId: number): JobPosterQuestion[] => |
210
|
|
|
jobPosterQuestions.filter( |
211
|
|
|
(jobPosterQuestion): boolean => jobPosterQuestion.job_poster_id === jobId, |
212
|
|
|
), |
213
|
|
|
)((state, ownProps): number => ownProps.jobId); |
214
|
|
|
|