Your IP : 216.73.216.138


Current Path : /home/ereika83/www/wp-content/plugins/edit-flow/modules/calendar/lib/react/
Upload File :
Current File : /home/ereika83/www/wp-content/plugins/edit-flow/modules/calendar/lib/react/calendar.react.js

/* global EF_CALENDAR, document */

/**
 * External dependencies
 */
import React from 'react';
import ReactDOM from 'react-dom';
import { _n, __, sprintf } from '@wordpress/i18n';

/**
 * Internal dependencies
 */
import { CalendarHeader } from './calendar-header';
import './style.react.scss';

// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
function flatDeep( arr, d = 1 ) {
	return d > 0 ? arr.reduce( ( acc, val ) => acc.concat( Array.isArray( val ) ? flatDeep( val, d - 1 ) : val ), [] )
		: arr.slice();
}

/**
 * Recursively organizes the items into Parent -> Child -> Child nested array
 * @param {*} items A list of items represent
 * @param {*} parent This is used recursively, to identify the child items parent
 * @param {*} level This is to identify the current level of nesting
 * @returns {array} Array of organized items
 */
function organizeItems( items, parent = 0, level = 0 ) {
	return items
		.filter( item => item.parent === parent )
		.map( item => {
			return [ { ...item, level } ]
				.concat(
					organizeItems( items, item.value, level + 1 )
				);
		} );
}

const EF_USER_MAP = ( { id: value, display_name: name } ) => ( { value, name } );
const EF_CATEGORY_MAP = ( { term_id: value, name, parent } ) => ( { value, name, parent } );

/**
 * The number of weeks is a drop listing the maximum number of weeks a user can select (usually 12). This creates an array and fills
 * it with null so we can map over the length of the array and fill it with the labels we need
 */
const NUM_WEEKS_OPTIONS = ( new Array( EF_CALENDAR.NUM_WEEKS.MAX ) )
	.fill( null )
	.map( ( value, index ) => ( { value: index + 1, label: sprintf( _n( '%d week', '%d weeks', index + 1, 'text-domain' ), index + 1 ) } ) );

const INITIAL_CATEGORY = EF_CALENDAR.CATEGORIES.filter( category => category.term_id === EF_CALENDAR.FILTERS.cat ).map( EF_CATEGORY_MAP )[ 0 ];
const INITIAL_USER = EF_CALENDAR.USERS.filter( user => user.id === EF_CALENDAR.FILTERS.author ).map( EF_USER_MAP )[ 0 ];

/**
 * Filters are hardcoded here for the moment, eventually should introduce some filtering to support custom filters
 * Maybe support applyFilters for folks who want to wrap an HOC around <CalendarFilters />
 */
const filters = [
	{
		name: 'post_status',
		filterType: 'select',
		label: __( 'Select a status', 'edit-flow' ),
		options: [ { value: '', label: __( 'Select a status', 'edit-flow' ) } ]
			.concat( EF_CALENDAR.POST_STATI.map( ( { name: value, label } ) => ( { value, label } ) ) ),
		initialValue: EF_CALENDAR.FILTERS.post_status,
	},
	{
		name: 'author',
		filterType: 'combobox',
		inputLabel: __( 'Find a user', 'edit-flow' ),
		buttonOpenLabel: __( 'Open user menu', 'edit-flow' ),
		buttonCloseLabel: __( 'Close user menu', 'edit-flow' ),
		buttonClearLabel: __( 'Clear user selection', 'edit-flow' ),
		placeholder: __( 'Select a user', 'edit-flow' ),
		options: EF_CALENDAR.USERS.map( EF_USER_MAP ),
		initialValue: INITIAL_USER ? INITIAL_USER : null,
		selectFirstItemOnBlur: true,
	},
	{
		name: 'cat',
		filterType: 'combobox',
		inputLabel: __( 'Find a category', 'edit-flow' ),
		buttonOpenLabel: __( 'Open category menu', 'edit-flow' ),
		buttonCloseLabel: __( 'Close category menu', 'edit-flow' ),
		buttonClearLabel: __( 'Clear category selection', 'edit-flow' ),
		placeholder: __( 'Select a category', 'edit-flow' ),
		options: flatDeep(
			organizeItems( EF_CALENDAR.CATEGORIES.map( EF_CATEGORY_MAP ), 0 ),
			Infinity
		),
		initialValue: INITIAL_CATEGORY ? INITIAL_CATEGORY : null,
		selectFirstItemOnBlur: true,
	},
];

if ( EF_CALENDAR.POST_TYPES && EF_CALENDAR.POST_TYPES.length > 1 ) {
	filters.push( {
		name: 'cpt',
		filterType: 'select',
		label: __( 'Select a type', 'edit-flow' ),
		options: [ { value: '', label: __( 'Select a type', 'edit-flow' ) } ]
			.concat( EF_CALENDAR.POST_TYPES.map( ( { name: value, label } ) => ( { value, label } ) ) ),
		initialValue: EF_CALENDAR.FILTERS.cpt,
	} );
}

filters.push( {
	name: 'num_weeks',
	filterType: 'select',
	label: __( 'Number of weeks', 'edit-flow' ),
	options: NUM_WEEKS_OPTIONS,
	initialValue: EF_CALENDAR.FILTERS.num_weeks,
} );

ReactDOM.render(
	<CalendarHeader
		numberOfWeeks={EF_CALENDAR.FILTERS.num_weeks}
		beginningOfWeek={EF_CALENDAR.BEGINNING_OF_WEEK}
		pageUrl={EF_CALENDAR.PAGE_URL}
		filters={filters}
		filterValues={EF_CALENDAR.FILTERS}
	/>,
	document.getElementById( 'ef-calendar-navigation-mount' )
);