UNPKG

instantjob-recruiter-client

Version:

a set of tools for creating an instantjob recruiter react client

383 lines (364 loc) 13.5 kB
import {tolerant_selector} from 'selectors/base' import { make_memoized, array_from_set, set_from_array, hash_with_key, filter_hash, property_getter, create_hash, empty_array, map_hash, array_from_hash, flatten_array, split_hash, } from 'common/utilities' import { missions_fields_options, users_fields_options, action_create_value, action_add_user_value, action_update_field, action_remove_field, action_select_entity_value, action_remove_entity_value, action_update_entity_comment, action_view_entity_template, action_upload_entity_file, action_fetch_entity_computed_value, action_remove_value, action_update_value, action_create_value_field, action_show_associated_values, } from 'common/fields' import {get_user_assigned_mission_ids} from './user_missions' import store from 'common/store' const get_raw_fields = (state) => state.fields.fields const get_raw_values = (state) => state.fields.values const get_raw_missions = (state) => state.missions.missions const get_raw_deals = (state) => state.missions.deals const get_raw_users = (state) => state.users.users const get_raw_shifts = (state) => state.shifts.shifts export const get_proposal_ids = tolerant_selector( [get_raw_missions], (missions) => flatten_array( array_from_hash(missions).map(({assigned_proposals}) => (assigned_proposals || []).map(property_getter('id'))) ) ) export const get_values = tolerant_selector( [get_raw_values], (values) => map_hash(values, (value) => { const {field_id, id} = value return { ...value, update(new_value) { action_update_value({id, ...new_value}) }, remove() { action_remove_value(id) }, create_value_field() { return action_create_value_field(field_id) }, show_associated_values() { action_show_associated_values(id) }, } }) ) export const get_values_by_field = tolerant_selector( [get_values, get_raw_fields], (values, fields) => split_hash(values, property_getter('field_id'), Object.keys(fields)) ) export const get_fields = tolerant_selector( [get_raw_fields, get_values_by_field], (fields, values_by_field) => array_from_hash(fields).map((field) => { const values = values_by_field[field.id] return { ...field, value_ids: Object.keys(values), values: array_from_hash(values), tolerant: true, get_value_props(value_id) { return values[value_id] }, get_item_values({id}) { return [field.value_id_for[id]].filter(Boolean) }, update(new_field) { return action_update_field({id: field.id, ...new_field}) }, remove() { return action_remove_field(field.id) }, view_template(id) { return action_view_entity_template(id, field) }, create_value(value_name) { return action_create_value(field.id, value_name) }, select_value(entity_id, value_id, for_missions) { return action_select_entity_value(entity_id, value_id, for_missions) }, update_comment(entity_id, comment) { return action_update_entity_comment(entity_id, field.id, comment) }, fetch_value(entity_id) { return action_fetch_entity_computed_value(entity_id, field.id) }, } }) ) function make_get_entity_ids(entity_type) { switch (entity_type) { case 'User': return (state) => Object.keys(state.users.users) case 'Mission': return (state) => Object.keys(state.missions.missions) case 'MissionProposal': return get_proposal_ids case 'Shift': return (state) => Object.keys(state.shifts.shifts) case 'Value': return (state) => Object.keys(state.fields.values) case 'Workplace': return (state) => Object.keys(state.missions.workplaces) case 'Deal': return (state) => Object.keys(state.missions.deals) default: return (state) => [] } } const make_get_entity_values_by_entity = make_memoized((entity_type) => { if (entity_type == 'Mission') { return get_mission_values_by_mission } return tolerant_selector( [get_raw_values, make_get_entity_ids(entity_type), get_raw_fields], (values, entity_ids, fields) => create_hash( entity_ids, (entity_id) => Object.keys(values).filter((value_id) => { const {field_id, entity_ids} = values[value_id] || {} const {for_entity, category, value_id_for} = fields[field_id] || {} if (for_entity == entity_type) { switch (category) { case 'non_exclusive': return entity_ids[entity_id] case 'exclusive': return value_id == value_id_for[entity_id] default: return false } } return false }) ) ) }) export const get_mission_values_by_mission = tolerant_selector( [get_raw_values, get_raw_missions, get_raw_deals, get_raw_fields], (values, missions, deals, fields) => { return create_hash( Object.keys(missions), (mission_id) => { const {deal_id} = missions[mission_id] const {custom_field_ids, template_mission_id} = deals[deal_id] || {custom_field_ids: {}} const get_mission_id = make_memoized((field_id) => custom_field_ids[field_id] ? mission_id : template_mission_id) return Object.keys(values).filter((value_id) => { const {mission_ids, field_id} = values[value_id] || {mission_ids: {}} const {for_entity, recycled, category, value_id_for} = fields[field_id] || {} if (for_entity == 'Mission' || recycled) { if (category == 'exclusive' && for_entity == 'Mission') { return value_id == value_id_for[get_mission_id(field_id)] } else { return mission_ids[get_mission_id(field_id)] } } return false }) } ) } ) const make_fields_with_selected_values = (item_type, item_id, fields, values, selected_values) => { let field_ids = fields.map(property_getter('id')) let selected_values_by_field = create_hash(field_ids, () => []) selected_values.forEach((id) => { const value = values[id] if (selected_values_by_field[value.field_id]) { selected_values_by_field[value.field_id].push(value) } }) const for_missions = item_type == 'Mission' return hash_with_key(fields.map((field) => { const { value_id_for, id, recycled, files, select_value, update_comment, view_template, fetch_value, comments, } = field let {category} = field if (recycled && for_missions) { category = 'non_exclusive' } const selected_value_id = (value_id_for || {})[item_id] function is_empty() { switch (category) { case "non_exclusive": return empty_array(selected_values_by_field[id]) case "comment": return !comments[item_id] case "file": return !files[item_id] case "exclusive": return !selected_value_id } } return { ...field, category, selected_values: selected_values_by_field[field.id], selected_value: values[selected_value_id], empty: is_empty(), comment: (comments || {})[item_id], file: (files || {})[item_id], selected: selected_value_id, allow_creating_values: !for_missions || !field.recycled, on_select_value(value_id) { return select_value(item_id, value_id, for_missions) }, on_deselect_value(value_id) { return action_remove_entity_value(item_id, value_id, for_missions) }, on_clear() { return action_remove_entity_value(item_id, selected_value_id) }, on_submit_comment(comment) { return update_comment(item_id, comment) }, view_template() { return view_template(item_id) }, upload_file(file) { return action_upload_entity_file(item_id, id, file) }, fetch_value() { return fetch_value(item_id) }, user_id: item_type == 'User' && item_id, } })) } const make_get_fields_by_entity = (entity_type) => { function make_fields_filter(entity_id, values) { if (entity_type == 'Mission') { return ({for_entity, recycled}) => recycled || for_entity == 'Mission' } if (entity_type == 'Value') { const value = values[entity_id] || {} return ({for_entity, field_id}) => for_entity == 'Value' && value.field_id == field_id } return ({for_entity}) => for_entity == entity_type } return tolerant_selector( [ get_fields, get_values, make_get_entity_ids(entity_type), make_get_entity_values_by_entity(entity_type), ], (fields, values, entity_ids, entity_values_by_entity) => create_hash( entity_ids, (entity_id) => make_fields_with_selected_values( entity_type, entity_id, fields.filter(make_fields_filter(entity_id, values)), values, entity_values_by_entity[entity_id] ) ) ) } export const get_fields_by_proposal = make_get_fields_by_entity('MissionProposal') export const get_fields_by_shift = make_get_fields_by_entity('Shift') export const get_fields_by_user = make_get_fields_by_entity('User') export const get_fields_by_mission = make_get_fields_by_entity('Mission') export const get_fields_by_value = make_get_fields_by_entity('Value') export const get_fields_by_workplace = make_get_fields_by_entity('Workplace') export const get_fields_by_deal = make_get_fields_by_entity('Deal') export const get_mission_fields = make_memoized((mission_id) => tolerant_selector( [get_fields_by_mission], (fields_by_mission) => fields_by_mission[mission_id] )) export const get_user_fields = make_memoized((user_id) => tolerant_selector( [get_fields_by_user], (fields_by_user) => fields_by_user[user_id] )) export const get_users_fields_with_locked_values = make_memoized((mission_id, status) => tolerant_selector( [get_mission_values_by_mission, get_users_filter_fields], (mission_values_by_mission, fields) => { if (status == 'available') { const locked_value_ids = set_from_array(mission_values_by_mission[mission_id] || []) return fields.map(({values, ...field}) => ({ ...field, values: field.recycled ? values.map((value) => ({ ...value, locked: locked_value_ids[value.id], })) : values, })) } else { return fields } } )) const make_get_specific_fields = (entity_type, for_missions = false) => tolerant_selector( [get_fields], (fields) => fields.filter( ({for_entity, recycled}) => for_entity == entity_type || (for_missions && recycled) ).map((field) => { if (field.recycled && for_missions) { return { ...field, category: 'non_exclusive', } } return field }) ) export const get_users_fields = make_get_specific_fields('User') export const get_missions_fields = make_get_specific_fields('Mission', true) export const get_proposals_fields = make_get_specific_fields('MissionProposal') export const get_shifts_fields = make_get_specific_fields('Shift') export const get_workplaces_fields = make_get_specific_fields('Workplace') export const get_exports_fields = make_get_specific_fields('Agency') export const get_deals_fields = make_get_specific_fields('Deal') export const get_missions_filter_fields = tolerant_selector( [get_missions_fields], (fields) => fields.map((field) => ({ ...field, get_item_values({template_mission, custom_field_ids, missions}) { if (custom_field_ids[field.id]) { return flatten_array(missions.map(field.get_item_values)) } return field.get_item_values(template_mission) }, })) ) export const get_users_filter_fields = tolerant_selector( [ get_users_fields, get_missions_fields, get_user_assigned_mission_ids, get_fields_by_mission, get_raw_missions, get_raw_deals, ], (users_fields, missions_fields, user_assigned_mission_ids, fields_by_mission, missions, deals) => { return [ ...users_fields, ...missions_fields.map((field) => { const {category, recycled} = field if (category == 'exclusive' && !recycled) { return { ...field, get_item_values({id}) { const mission_ids = user_assigned_mission_ids[id] || [] return flatten_array(mission_ids.map((mission_id) => { const mission = missions[mission_id] || {} const {custom_field_ids, template_mission_id} = deals[mission.deal_id] || {} if ((custom_field_ids || {})[field.id]) { return field.get_item_values(mission) } else { return field.get_item_values(missions[template_mission_id] || {}) } })) }, } } return null }).filter(Boolean), ] } ) export const get_missions_recyclable_fields = tolerant_selector( [get_raw_fields], (fields) => filter_hash( fields, ({for_entity, recycled, category}) => for_entity == 'User' && !recycled && (category == 'non_exclusive' || category == 'exclusive') ) ) export const get_mission_fields_by_deal = tolerant_selector( [get_fields_by_mission, get_raw_deals], (fields_by_mission, deals) => map_hash(deals, ({template_mission_id}) => array_from_hash(fields_by_mission[template_mission_id])) )