instantjob-recruiter-client
Version:
a set of tools for creating an instantjob recruiter react client
92 lines (82 loc) • 3.72 kB
JSX
import moment from 'common/moment'
import {
array_from_hash, for_all, find_optimum_in_sorted_array, flatten_array, split_array,
} from 'common/utilities'
import {mission_period} from 'common/missions'
import store from 'common/store'
import {show_popover} from 'actions/display'
import AgencyEditUserCalendar from 'components/input_calendar/agency_edit_user_calendar'
export function event_intersects(event, date, duration, unit) {
return moment(event.start).isBefore(moment(date).add(duration, unit)) && moment(event.end).isAfter(date)
}
export function event_intersects_or_consecutive(event1, event2, unit) {
return !(moment(event1.end).add(1, unit).isSameOrBefore(event2.start, unit) || moment(event2.end).add(1, unit).isSameOrBefore(event1.start, unit))
}
const make_period_from_event = (e) => ({is_period: true, start: moment(e.start), end: moment(e.end), events: [e], full_days: e.full_days})
export function intersecting_periods_interval(periods, start, end) {
let lower = find_optimum_in_sorted_array(periods, (period) => period.end.isAfter(start)) + 1
let upper = periods.length - 1 - find_optimum_in_sorted_array(periods.reverse(), (period) => period.start.isBefore(end))
periods.reverse()
return {lower, upper}
}
export const make_periods = (events) => {
let events_array = array_from_hash(events)
if (events_array.length == 0) {
return []
} else {
return events_array.slice(1).reduce((periods, e) => {
let extended_start = moment(e.start).subtract(1, "minute")
let extended_end = moment(e.end).add(1, "minute")
let {lower, upper} = intersecting_periods_interval(periods, extended_start, extended_end)
let merging_periods = periods.slice(lower, upper)
return [
...periods.slice(0, lower),
{
is_period: true,
start: merging_periods.length == 0 || merging_periods[0].start.isAfter(e.start) ? moment(e.start) : merging_periods[0].start,
end: merging_periods.length == 0 || merging_periods.slice(-1)[0].end.isBefore(e.end) ? moment(e.end) : merging_periods.slice(-1)[0].end,
full_days: e.full_days && for_all(merging_periods, (period) => period.full_days),
events: [...flatten_array(merging_periods.map((period) => period.events)), e],
},
...periods.slice(upper)
]
}, [make_period_from_event(events_array[0])])
}
}
export const make_slots = (periods) => flatten_array(
periods.map(({start, end, ...period}) => {
let current = moment(start).add(1, 'day').startOf('day'), previous = start
const periods = []
while (current.isBefore(end)) {
periods.push({start: previous, end: current, ...period})
previous = current
current = moment(current).add(1, 'day')
}
periods.push({start: previous, end, ...period})
return periods
})
)
function event_is_included_in_periods(event, periods) {
let {lower, upper} = intersecting_periods_interval(periods, event.start, event.end)
return lower == upper - 1 && periods[lower] && periods[lower].start.isSameOrBefore(event.start) && periods[lower].end.isSameOrAfter(event.end)
}
export function events_difference(old_events, new_events) {
let new_periods = make_periods(new_events)
let {remove, keep} = split_array(old_events, (event) => {
if (event_is_included_in_periods(event, new_periods)) {
return "keep"
} else {
return "remove"
}
})
let old_periods = make_periods(keep)
return {remove, add: new_events.filter((event) => {
return !event_is_included_in_periods(event, old_periods)
})}
}
export function action_agency_edit_user_events({id: user_id}) {
store.dispatch(show_popover(
AgencyEditUserCalendar,
{user_id}
))
}