corvée(dépendances) ajoute Carbon Fields
This commit is contained in:
parent
135cc65eed
commit
62368587e5
459 changed files with 72750 additions and 26 deletions
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import produce from 'immer';
|
||||
import { applyFilters } from '@wordpress/hooks';
|
||||
import { assign } from 'lodash';
|
||||
import {
|
||||
pipe,
|
||||
merge,
|
||||
scan
|
||||
} from 'callbag-basics';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import './post-parent';
|
||||
import './post-format';
|
||||
import './post-template';
|
||||
import './post-term';
|
||||
import './term-parent';
|
||||
import './user-role';
|
||||
|
||||
/**
|
||||
* The function that controls the stream of side effects.
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {string} props.context
|
||||
* @return {Object}
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
export default function aperture( component, { context } ) {
|
||||
const postParent$ = applyFilters( `carbon-fields.conditional-display-post-parent.${ context }` );
|
||||
const postFormat$ = applyFilters( `carbon-fields.conditional-display-post-format.${ context }` );
|
||||
const postTemplate$ = applyFilters( `carbon-fields.conditional-display-post-template.${ context }` );
|
||||
const postTerm$ = applyFilters( `carbon-fields.conditional-display-post-term.${ context }` );
|
||||
const termParent$ = applyFilters( `carbon-fields.conditional-display-term-parent.${ context }` );
|
||||
const userRole$ = applyFilters( `carbon-fields.conditional-display-user-role.${ context }` );
|
||||
|
||||
return pipe(
|
||||
merge(
|
||||
postParent$,
|
||||
postFormat$,
|
||||
postTemplate$,
|
||||
postTerm$,
|
||||
termParent$,
|
||||
userRole$
|
||||
),
|
||||
scan( ( previous, current ) => produce( previous, ( draft ) => {
|
||||
assign( draft, current );
|
||||
} ) )
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import of from 'callbag-of';
|
||||
import startWith from 'callbag-start-with';
|
||||
import fromDelegatedEvent from 'callbag-from-delegated-event';
|
||||
import distinctUntilChanged from 'callbag-distinct-until-changed';
|
||||
import { addFilter } from '@wordpress/hooks';
|
||||
import { select } from '@wordpress/data';
|
||||
import {
|
||||
pipe,
|
||||
map,
|
||||
filter
|
||||
} from 'callbag-basics';
|
||||
|
||||
/**
|
||||
* Carbon Fields dependencies.
|
||||
*/
|
||||
import { fromSelector } from '@carbon-fields/core';
|
||||
|
||||
/**
|
||||
* The default state.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
const INITIAL_STATE = {
|
||||
post_format: 'standard'
|
||||
};
|
||||
|
||||
/**
|
||||
* Extracts `post_format` from the input.
|
||||
*
|
||||
* @param {Object} input
|
||||
* @return {Object}
|
||||
*/
|
||||
function getPostFormatFromRadioInput( input ) {
|
||||
let value = input.value;
|
||||
|
||||
// Normalize the value of "Standard" input.
|
||||
if ( value === '0' ) {
|
||||
value = 'standard';
|
||||
}
|
||||
|
||||
return {
|
||||
post_format: value
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the side effects for Classic Editor.
|
||||
*/
|
||||
addFilter( 'carbon-fields.conditional-display-post-format.classic', 'carbon-fields/metaboxes', () => {
|
||||
const node = document.querySelector( 'div#post-formats-select' );
|
||||
|
||||
if ( ! node ) {
|
||||
return of( INITIAL_STATE );
|
||||
}
|
||||
|
||||
return pipe(
|
||||
fromDelegatedEvent( node, 'input.post-format', 'change' ),
|
||||
map( ( { target } ) => getPostFormatFromRadioInput( target ) ),
|
||||
startWith( getPostFormatFromRadioInput( node.querySelector( 'input.post-format:checked' ) ) )
|
||||
);
|
||||
} );
|
||||
|
||||
/**
|
||||
* Defines the side effects for Gutenberg.
|
||||
*/
|
||||
addFilter( 'carbon-fields.conditional-display-post-format.gutenberg', 'carbon-fields/metaboxes', ( ) => {
|
||||
return pipe(
|
||||
fromSelector( select( 'core/editor' ).getEditedPostAttribute, 'format' ),
|
||||
distinctUntilChanged(),
|
||||
filter( Boolean ),
|
||||
map( ( postFormat ) => ( {
|
||||
post_format: postFormat
|
||||
} ) ),
|
||||
startWith( INITIAL_STATE )
|
||||
);
|
||||
} );
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import of from 'callbag-of';
|
||||
import startWith from 'callbag-start-with';
|
||||
import distinctUntilChanged from 'callbag-distinct-until-changed';
|
||||
import { addFilter } from '@wordpress/hooks';
|
||||
import { select } from '@wordpress/data';
|
||||
import {
|
||||
get,
|
||||
find,
|
||||
isEqual
|
||||
} from 'lodash';
|
||||
import {
|
||||
pipe,
|
||||
map,
|
||||
combine,
|
||||
fromEvent
|
||||
} from 'callbag-basics';
|
||||
|
||||
/**
|
||||
* Carbon Fields dependencies.
|
||||
*/
|
||||
import { fromSelector } from '@carbon-fields/core';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import getParentIdFromOption from '../utils/get-parent-id-from-option';
|
||||
import getLevelFromOption from '../utils/get-level-from-option';
|
||||
import getAncestorsFromOption from '../utils/get-ancestors-from-option';
|
||||
|
||||
/**
|
||||
* The default state.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
const INITIAL_STATE = {
|
||||
post_ancestors: [],
|
||||
post_parent_id: 0,
|
||||
post_level: 1
|
||||
};
|
||||
|
||||
/**
|
||||
* Extracts the `post_ancestors`, `post_parent_id` & `post_level` from the select.
|
||||
*
|
||||
* @param {Object} node
|
||||
* @return {Object}
|
||||
*/
|
||||
function getParentIdAncestorsAndLevelFromSelect( node ) {
|
||||
const option = node.options[ node.selectedIndex ];
|
||||
const ancestors = getAncestorsFromOption( option );
|
||||
const parentId = getParentIdFromOption( option );
|
||||
const level = getLevelFromOption( option ) + 1;
|
||||
|
||||
return {
|
||||
post_ancestors: ancestors,
|
||||
post_parent_id: parentId,
|
||||
post_level: level
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts `post_ancestors` from the list.
|
||||
*
|
||||
* @param {number} parentId
|
||||
* @param {Object[]} posts
|
||||
* @param {Array} ancestors
|
||||
* @return {number[]}
|
||||
*/
|
||||
function getAncestorsFromPostsList( parentId, posts, ancestors = [] ) {
|
||||
const parent = find( posts, [ 'id', parentId ] );
|
||||
|
||||
if ( ! parent ) {
|
||||
return ancestors;
|
||||
}
|
||||
|
||||
ancestors.unshift( parent.id );
|
||||
|
||||
if ( parent.parent ) {
|
||||
return getAncestorsFromPostsList( parent.parent, posts, ancestors );
|
||||
}
|
||||
|
||||
return ancestors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the side effects for Classic Editor.
|
||||
*/
|
||||
addFilter( 'carbon-fields.conditional-display-post-parent.classic', 'carbon-fields/metaboxes', ( ) => {
|
||||
const node = document.querySelector( 'select#parent_id' );
|
||||
|
||||
if ( ! node ) {
|
||||
return of( INITIAL_STATE );
|
||||
}
|
||||
|
||||
return pipe(
|
||||
fromEvent.default( node, 'change' ),
|
||||
map( ( { target } ) => getParentIdAncestorsAndLevelFromSelect( target ) ),
|
||||
startWith( getParentIdAncestorsAndLevelFromSelect( node ) )
|
||||
);
|
||||
} );
|
||||
|
||||
/**
|
||||
* Defines the side effects for Gutenberg.
|
||||
*/
|
||||
addFilter( 'carbon-fields.conditional-display-post-parent.gutenberg', 'carbon-fields/metaboxes', ( ) => {
|
||||
const { getPostType, getEntityRecords } = select( 'core' );
|
||||
|
||||
return pipe(
|
||||
combine(
|
||||
fromSelector( select( 'core/editor' ).getCurrentPostId ),
|
||||
fromSelector( select( 'core/editor' ).getEditedPostAttribute, 'type' ),
|
||||
fromSelector( select( 'core/editor' ).getEditedPostAttribute, 'parent' )
|
||||
),
|
||||
distinctUntilChanged( isEqual ),
|
||||
map( ( [ postId, postTypeSlug, parentId ] ) => {
|
||||
parentId = parseInt( parentId, 10 );
|
||||
|
||||
if ( isNaN( parentId ) ) {
|
||||
return INITIAL_STATE;
|
||||
}
|
||||
|
||||
const postType = getPostType( postTypeSlug );
|
||||
const isHierarchical = get( postType, [ 'hierarchical' ], false );
|
||||
|
||||
if ( ! isHierarchical ) {
|
||||
return INITIAL_STATE;
|
||||
}
|
||||
|
||||
// Borrowed from https://github.com/WordPress/gutenberg/blob/master/packages/editor/src/components/page-attributes/parent.js
|
||||
const items = getEntityRecords( 'postType', postTypeSlug, {
|
||||
per_page: -1,
|
||||
exclude: postId,
|
||||
parent_exclude: postId,
|
||||
orderby: 'menu_order',
|
||||
order: 'asc'
|
||||
} ) || [];
|
||||
|
||||
const ancestors = getAncestorsFromPostsList( parentId, items );
|
||||
const level = ancestors.length + 1;
|
||||
|
||||
return {
|
||||
post_ancestors: ancestors,
|
||||
post_parent_id: parentId,
|
||||
post_level: level
|
||||
};
|
||||
} )
|
||||
);
|
||||
} );
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import of from 'callbag-of';
|
||||
import startWith from 'callbag-start-with';
|
||||
import distinctUntilChanged from 'callbag-distinct-until-changed';
|
||||
import { addFilter } from '@wordpress/hooks';
|
||||
import { select } from '@wordpress/data';
|
||||
import { isString } from 'lodash';
|
||||
import {
|
||||
pipe,
|
||||
map,
|
||||
filter,
|
||||
fromEvent
|
||||
} from 'callbag-basics';
|
||||
|
||||
/**
|
||||
* Carbon Fields dependencies.
|
||||
*/
|
||||
import { fromSelector } from '@carbon-fields/core';
|
||||
|
||||
/**
|
||||
* The default state.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
const INITIAL_STATE = {
|
||||
post_template: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* Extracts `post_template` from the select.
|
||||
*
|
||||
* @param {Object} node
|
||||
* @return {Object}
|
||||
*/
|
||||
function getPostTemplateFromSelect( node ) {
|
||||
let { value } = node;
|
||||
|
||||
// In Gutenberg for the "Default" template is used an empty string.
|
||||
if ( value === 'default' ) {
|
||||
value = '';
|
||||
}
|
||||
|
||||
return {
|
||||
post_template: value
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the side effects for Classic Editor.
|
||||
*/
|
||||
addFilter( 'carbon-fields.conditional-display-post-template.classic', 'carbon-fields/metaboxes', () => {
|
||||
const node = document.querySelector( 'select#page_template' );
|
||||
|
||||
if ( ! node ) {
|
||||
return of( INITIAL_STATE );
|
||||
}
|
||||
|
||||
return pipe(
|
||||
fromEvent.default( node, 'change' ),
|
||||
map( ( { target } ) => getPostTemplateFromSelect( target ) ),
|
||||
startWith( getPostTemplateFromSelect( node ) )
|
||||
);
|
||||
} );
|
||||
|
||||
/**
|
||||
* Defines the side effects for Gutenberg.
|
||||
*/
|
||||
addFilter( 'carbon-fields.conditional-display-post-template.gutenberg', 'carbon-fields/metaboxes', () => {
|
||||
return pipe(
|
||||
fromSelector( select( 'core/editor' ).getEditedPostAttribute, 'template' ),
|
||||
distinctUntilChanged(),
|
||||
filter( isString ),
|
||||
map( ( postTemplate ) => ( {
|
||||
post_template: postTemplate
|
||||
} ) ),
|
||||
startWith( INITIAL_STATE )
|
||||
);
|
||||
} );
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import produce from 'immer';
|
||||
import startWith from 'callbag-start-with';
|
||||
import fromDelegatedEvent from 'callbag-from-delegated-event';
|
||||
import {
|
||||
merge,
|
||||
pipe,
|
||||
scan,
|
||||
map,
|
||||
filter,
|
||||
fromEvent
|
||||
} from 'callbag-basics';
|
||||
import { addFilter } from '@wordpress/hooks';
|
||||
import { select } from '@wordpress/data';
|
||||
import { pull, fromPairs } from 'lodash';
|
||||
|
||||
/**
|
||||
* Carbon Fields dependencies.
|
||||
*/
|
||||
import { fromSelector } from '@carbon-fields/core';
|
||||
|
||||
const TAGS_DELIMITER = ',';
|
||||
|
||||
/**
|
||||
* Applies a monkey patch to the specified method of `window.tagBox` API
|
||||
* so we can detect changes of the non-hierarchical taxonomies.
|
||||
*
|
||||
* @param {Object} tagBox
|
||||
* @param {string} method
|
||||
* @return {void}
|
||||
*/
|
||||
function patchWordPressTagBoxAPI( tagBox, method ) {
|
||||
tagBox[ `original_${ method }` ] = tagBox[ method ];
|
||||
|
||||
tagBox[ method ] = function( ...args ) {
|
||||
const event = new Event( 'change' );
|
||||
const textarea = window.jQuery( args[ 0 ] )
|
||||
.closest( '.postbox' )
|
||||
.find( 'textarea.the-tags' )
|
||||
.get( 0 );
|
||||
|
||||
const result = tagBox[ `original_${ method }` ]( ...args );
|
||||
|
||||
textarea.dispatchEvent( event );
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
if ( window.tagBox ) {
|
||||
patchWordPressTagBoxAPI( window.tagBox, 'parseTags' );
|
||||
patchWordPressTagBoxAPI( window.tagBox, 'flushTags' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the terms of a hierarchical taxonomy.
|
||||
*
|
||||
* @param {string} taxonomy
|
||||
* @return {Object}
|
||||
*/
|
||||
function getTermsFromChecklist( taxonomy ) {
|
||||
const inputs = document.querySelectorAll( `#${ taxonomy }checklist input[type="checkbox"]:checked` );
|
||||
|
||||
return [ ...inputs ].reduce( ( memo, input ) => {
|
||||
const value = parseInt( input.value, 10 );
|
||||
|
||||
memo[ taxonomy ].push( value );
|
||||
|
||||
return memo;
|
||||
}, {
|
||||
[ taxonomy ]: []
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the terms of a non-hierarchical taxonomy.
|
||||
*
|
||||
* @param {string} taxonomy
|
||||
* @return {Object}
|
||||
*/
|
||||
function getTermsFromText( taxonomy ) {
|
||||
const node = document.querySelector( `#tagsdiv-${ taxonomy } textarea.the-tags` );
|
||||
const terms = node.value
|
||||
? node.value.split( TAGS_DELIMITER )
|
||||
: [];
|
||||
|
||||
return {
|
||||
[ taxonomy ]: terms
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps track of the hierarchical taxonomies like `categories`.
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
function trackHierarchicalTaxonomies() {
|
||||
const nodes = document.querySelectorAll( 'div[id^="taxonomy-"]' );
|
||||
|
||||
return [ ...nodes ].map( ( node ) => {
|
||||
const taxonomy = node.id.replace( 'taxonomy-', '' );
|
||||
|
||||
return pipe(
|
||||
fromDelegatedEvent( node.querySelector( `#${ taxonomy }checklist` ), 'input[type="checkbox"]', 'change' ),
|
||||
scan( ( stack, { target } ) => {
|
||||
return produce( stack, ( draft ) => {
|
||||
const value = parseInt( target.value, 10 );
|
||||
|
||||
if ( target.checked ) {
|
||||
draft[ taxonomy ].push( value );
|
||||
} else {
|
||||
pull( draft[ taxonomy ], value );
|
||||
}
|
||||
} );
|
||||
}, {
|
||||
[ taxonomy ]: []
|
||||
} ),
|
||||
startWith( getTermsFromChecklist( taxonomy ) )
|
||||
);
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps track of the non-hierarchical taxonomies like `tags`.
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
function trackNonHierarchicalTaxonomies() {
|
||||
const nodes = document.querySelectorAll( 'div[id^="tagsdiv-"]' );
|
||||
|
||||
return [ ...nodes ].map( ( node ) => {
|
||||
const taxonomy = node.id.replace( 'tagsdiv-', '' );
|
||||
|
||||
return pipe(
|
||||
fromEvent.default( node.querySelector( 'textarea.the-tags' ), 'change' ),
|
||||
map( ( { target } ) => ( {
|
||||
[ taxonomy ]: target.value
|
||||
? target.value.split( TAGS_DELIMITER )
|
||||
: []
|
||||
} ) ),
|
||||
startWith( getTermsFromText( taxonomy ) )
|
||||
);
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the side effects for Classic Editor.
|
||||
*/
|
||||
addFilter( 'carbon-fields.conditional-display-post-term.classic', 'carbon-fields/metaboxes', () => {
|
||||
return pipe(
|
||||
merge(
|
||||
...trackHierarchicalTaxonomies(),
|
||||
...trackNonHierarchicalTaxonomies()
|
||||
),
|
||||
scan( ( previous, current ) => {
|
||||
return {
|
||||
post_term: {
|
||||
...previous.post_term,
|
||||
...current
|
||||
}
|
||||
};
|
||||
}, {
|
||||
post_term: {}
|
||||
} )
|
||||
);
|
||||
} );
|
||||
|
||||
/**
|
||||
* Defines the side effects for Gutenberg.
|
||||
*/
|
||||
addFilter( 'carbon-fields.conditional-display-post-term.gutenberg', 'carbon-fields/metaboxes', () => {
|
||||
const { getTaxonomies } = select( 'core' );
|
||||
const { getEditedPostAttribute } = select( 'core/editor' );
|
||||
|
||||
// Borrowed from https://github.com/WordPress/gutenberg/blob/master/packages/editor/src/components/post-taxonomies/index.js
|
||||
return pipe(
|
||||
fromSelector( getTaxonomies, { per_page: -1 } ),
|
||||
filter( Boolean ),
|
||||
map( ( taxonomies ) => {
|
||||
const pairs = taxonomies.map( ( taxonomy ) => ( [
|
||||
taxonomy.slug,
|
||||
getEditedPostAttribute( taxonomy.rest_base ) || []
|
||||
] ) );
|
||||
|
||||
return {
|
||||
post_term: fromPairs( pairs )
|
||||
};
|
||||
} )
|
||||
);
|
||||
} );
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import of from 'callbag-of';
|
||||
import startWith from 'callbag-start-with';
|
||||
import { addFilter } from '@wordpress/hooks';
|
||||
import {
|
||||
pipe,
|
||||
map,
|
||||
fromEvent
|
||||
} from 'callbag-basics';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import getParentIdFromOption from '../utils/get-parent-id-from-option';
|
||||
import getLevelFromOption from '../utils/get-level-from-option';
|
||||
import getAncestorsFromOption from '../utils/get-ancestors-from-option';
|
||||
|
||||
/**
|
||||
* The default state.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
const INITIAL_STATE = {
|
||||
term_ancestors: [],
|
||||
term_parent: 0,
|
||||
term_level: 1
|
||||
};
|
||||
|
||||
/**
|
||||
* Extracts the `term_ancestors`, `term_parent` & `term_level` from the select.
|
||||
*
|
||||
* @param {Object} node
|
||||
* @return {Object}
|
||||
*/
|
||||
function getParentIdAncestorsAndLevelFromSelect( node ) {
|
||||
const option = node.options[ node.selectedIndex ];
|
||||
const ancestors = getAncestorsFromOption( option );
|
||||
const parentId = getParentIdFromOption( option );
|
||||
const level = getLevelFromOption( option ) + 1;
|
||||
|
||||
return {
|
||||
term_ancestors: ancestors,
|
||||
term_parent: parentId,
|
||||
term_level: level
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the side effects for Classic Editor.
|
||||
*/
|
||||
addFilter( 'carbon-fields.conditional-display-term-parent.classic', 'carbon-fields/metaboxes', ( ) => {
|
||||
const node = document.querySelector( 'select#parent' );
|
||||
|
||||
if ( ! node ) {
|
||||
return of( INITIAL_STATE );
|
||||
}
|
||||
|
||||
return pipe(
|
||||
fromEvent.default( node, 'change' ),
|
||||
map( ( { target } ) => getParentIdAncestorsAndLevelFromSelect( target ) ),
|
||||
startWith( getParentIdAncestorsAndLevelFromSelect( node ) )
|
||||
);
|
||||
} );
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import of from 'callbag-of';
|
||||
import startWith from 'callbag-start-with';
|
||||
import { addFilter } from '@wordpress/hooks';
|
||||
import {
|
||||
pipe,
|
||||
map,
|
||||
fromEvent
|
||||
} from 'callbag-basics';
|
||||
|
||||
/**
|
||||
* The default state.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
const INITIAL_STATE = {
|
||||
user_role: ''
|
||||
};
|
||||
|
||||
/**
|
||||
* Extracts `user_role` from a select.
|
||||
*
|
||||
* @param {Object} node
|
||||
* @return {Object}
|
||||
*/
|
||||
function getRoleFromSelect( node ) {
|
||||
return {
|
||||
user_role: node.value
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the side effects for Classic Editor.
|
||||
*/
|
||||
addFilter( 'carbon-fields.conditional-display-user-role.classic', 'carbon-fields/metaboxes', ( ) => {
|
||||
const node = document.querySelector( 'select#role' );
|
||||
|
||||
if ( ! node ) {
|
||||
const fieldset = document.querySelector( 'fieldset[data-profile-role]' );
|
||||
|
||||
// The selectbox doesn't exist on the "Profile" page.
|
||||
// So we need to read the role from the container in DOM.
|
||||
if ( fieldset ) {
|
||||
return of( {
|
||||
user_role: fieldset.dataset.profileRole
|
||||
} );
|
||||
}
|
||||
|
||||
return of( INITIAL_STATE );
|
||||
}
|
||||
|
||||
return pipe(
|
||||
fromEvent.default( node, 'change' ),
|
||||
map( ( { target } ) => getRoleFromSelect( target ) ),
|
||||
startWith( getRoleFromSelect( node ) )
|
||||
);
|
||||
} );
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { intersection } from 'lodash';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import base from './base';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
operators: [ 'IN', 'NOT IN' ],
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
evaluate( a, operator, b ) {
|
||||
switch ( operator ) {
|
||||
case 'IN':
|
||||
return intersection( a, b ).length > 0;
|
||||
case 'NOT IN':
|
||||
return intersection( a, b ).length === 0;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { includes } from 'lodash';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import base from './base';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
operators: [ '=', '!=' ],
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
evaluate( a, operator, b ) {
|
||||
switch ( operator ) {
|
||||
case '=':
|
||||
return includes( a, b );
|
||||
case '!=':
|
||||
return ! includes( a, b );
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
export default {
|
||||
/**
|
||||
* The supported operators.
|
||||
*
|
||||
* @type {string[]}
|
||||
*/
|
||||
operators: [],
|
||||
|
||||
/**
|
||||
* Checks if the operator is supported.
|
||||
*
|
||||
* @param {string} operator
|
||||
* @return {boolean}
|
||||
*/
|
||||
isOperatorSupported( operator ) {
|
||||
return this.operators.indexOf( operator ) > -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Performs the comparison.
|
||||
*
|
||||
* @param {mixed} a
|
||||
* @param {string} operator
|
||||
* @param {mixed} b
|
||||
* @return {boolean}
|
||||
*/
|
||||
evaluate() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import base from './base';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
operators: [ 'IN', 'NOT IN' ],
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
evaluate( a, operator, b ) {
|
||||
switch ( operator ) {
|
||||
case 'IN':
|
||||
return b.indexOf( a ) > -1;
|
||||
case 'NOT IN':
|
||||
return b.indexOf( a ) === -1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* eslint eqeqeq: "off" */
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import base from './base';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
operators: [ '=', '!=' ],
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
evaluate( a, operator, b ) {
|
||||
switch ( operator ) {
|
||||
case '=':
|
||||
return a == b;
|
||||
case '!=':
|
||||
return a != b;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import base from './base';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
operators: [ '>', '>=', '<', '<=' ],
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
evaluate( a, operator, b ) {
|
||||
switch ( operator ) {
|
||||
case '>':
|
||||
return a > b;
|
||||
case '>=':
|
||||
return a >= b;
|
||||
case '<':
|
||||
return a < b;
|
||||
case '<=':
|
||||
return a <= b;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { find } from 'lodash';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import equality from '../comparers/equality';
|
||||
import contain from '../comparers/contain';
|
||||
import scalar from '../comparers/scalar';
|
||||
|
||||
export default {
|
||||
/**
|
||||
* The supported comparers.
|
||||
*
|
||||
* @type {Function[]}
|
||||
*/
|
||||
comparers: [
|
||||
equality,
|
||||
contain,
|
||||
scalar
|
||||
],
|
||||
|
||||
/**
|
||||
* Checks if the condition is fulfiled.
|
||||
*
|
||||
* @param {Object} definition
|
||||
* @param {Object} values
|
||||
* @return {boolean}
|
||||
*/
|
||||
isFulfiled( definition, values ) {
|
||||
const { compare, value } = definition;
|
||||
|
||||
return this.firstComparerIsCorrect( this.getEnvironmentValue( definition, values ), compare, value );
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if any comparer is correct for `a` and `b`.
|
||||
*
|
||||
* @param {mixed} a
|
||||
* @param {string} operator
|
||||
* @param {mixed} b
|
||||
* @return {boolean}
|
||||
*/
|
||||
firstComparerIsCorrect( a, operator, b ) {
|
||||
const comparer = find( this.comparers, ( item ) => item.isOperatorSupported( operator ) );
|
||||
|
||||
if ( ! comparer ) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error( sprintf( __( 'Unsupported container condition comparison operator used - "%1$s".', 'carbon-fields-ui' ), operator ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return comparer.evaluate( a, operator, b );
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the value from the environment.
|
||||
*
|
||||
* @param {Object} definition
|
||||
* @param {Object} values
|
||||
* @return {Object}
|
||||
*/
|
||||
getEnvironmentValue( definition, values ) {
|
||||
return values[ definition.type ];
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import base from './base';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
getEnvironmentValue() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { get } from 'lodash';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import anyEquality from '../comparers/any-equality';
|
||||
import anyContain from '../comparers/any-contain';
|
||||
import base from './base';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
comparers: [
|
||||
anyEquality,
|
||||
anyContain
|
||||
],
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
getEnvironmentValue( definition, values ) {
|
||||
return get( values, 'post_ancestors', [] );
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { isArray } from 'lodash';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import base from './base';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
isFulfiled( definition, values ) {
|
||||
definition = { ...definition };
|
||||
|
||||
// In Gutenberg for the "Default" template is used an empty string.
|
||||
if ( definition.value === 'default' ) {
|
||||
definition.value = '';
|
||||
} else if ( isArray( definition.value ) ) {
|
||||
const defaultIndex = definition.value.indexOf( 'default' );
|
||||
|
||||
if ( defaultIndex !== -1 ) {
|
||||
definition.value[ defaultIndex ] = '';
|
||||
}
|
||||
}
|
||||
|
||||
return base.isFulfiled( definition, values );
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { get, isArray } from 'lodash';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import anyEquality from '../comparers/any-equality';
|
||||
import base from './base';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
comparers: [
|
||||
anyEquality
|
||||
],
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
isFulfiled( definition, values ) {
|
||||
let { compare, value } = definition;
|
||||
|
||||
if ( isArray( value ) ) {
|
||||
let method;
|
||||
|
||||
switch ( compare ) {
|
||||
case 'IN':
|
||||
compare = '=';
|
||||
method = 'some';
|
||||
break;
|
||||
|
||||
case 'NOT IN':
|
||||
compare = '!=';
|
||||
method = 'every';
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
const results = value.map( ( descriptor ) => {
|
||||
return this.isFulfiled( {
|
||||
...definition,
|
||||
compare,
|
||||
value: descriptor
|
||||
}, values );
|
||||
} );
|
||||
|
||||
return results[ method ]( Boolean );
|
||||
}
|
||||
|
||||
// TODO: Improve value resolution in context of Gutenberg
|
||||
value = value.taxonomy_object.hierarchical
|
||||
? value.term_object.term_id
|
||||
: value.term_object.name;
|
||||
|
||||
return this.firstComparerIsCorrect( this.getEnvironmentValue( definition, values ), compare, value );
|
||||
},
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
getEnvironmentValue( definition, values ) {
|
||||
return get( values, `post_term.${ definition.value.taxonomy }`, [] );
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import {
|
||||
get,
|
||||
isArray,
|
||||
isPlainObject
|
||||
} from 'lodash';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import anyEquality from '../comparers/any-equality';
|
||||
import anyContain from '../comparers/any-contain';
|
||||
import base from './base';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
comparers: [
|
||||
anyEquality,
|
||||
anyContain
|
||||
],
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
isFulfiled( definition, values ) {
|
||||
const { compare } = definition;
|
||||
let { value } = definition;
|
||||
|
||||
if ( isArray( value ) ) {
|
||||
value = value.map( ( item ) => item.term_object.term_id );
|
||||
} else if ( isPlainObject( value ) ) {
|
||||
value = value.term_object.term_id;
|
||||
}
|
||||
|
||||
return this.firstComparerIsCorrect( this.getEnvironmentValue( definition, values ), compare, value );
|
||||
},
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
getEnvironmentValue( definition, values ) {
|
||||
return get( values, 'term_ancestors', [] );
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { isArray, isPlainObject } from 'lodash';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import base from './base';
|
||||
|
||||
export default {
|
||||
...base,
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
isFulfiled( definition, values ) {
|
||||
const { compare } = definition;
|
||||
let { value } = definition;
|
||||
|
||||
if ( isArray( value ) ) {
|
||||
value = value.map( ( item ) => item.term_object.term_id );
|
||||
} else if ( isPlainObject( value ) ) {
|
||||
value = value.term_object.term_id;
|
||||
}
|
||||
|
||||
return this.firstComparerIsCorrect( this.getEnvironmentValue( definition, values ), compare, value );
|
||||
}
|
||||
};
|
||||
136
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/conditional-display/handler/index.js
vendored
Normal file
136
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/conditional-display/handler/index.js
vendored
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { get, map } from 'lodash';
|
||||
import { createRoot } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import { renderContainer } from '../../../containers';
|
||||
import base from '../conditions/base';
|
||||
import boolean from '../conditions/boolean';
|
||||
import postTerm from '../conditions/post-term';
|
||||
import postTemplate from '../conditions/post-template';
|
||||
import postAncestorId from '../conditions/post-ancestor-id';
|
||||
import termParentId from '../conditions/term-parent-id';
|
||||
import termAncestorId from '../conditions/term-ancestor-id';
|
||||
import { getContainerRoot } from '../../../containers/root-registry';
|
||||
|
||||
/**
|
||||
* Keeps track of supported conditions.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
const conditions = {
|
||||
boolean,
|
||||
post_term: postTerm,
|
||||
post_ancestor_id: postAncestorId,
|
||||
post_parent_id: base,
|
||||
post_level: base,
|
||||
post_format: base,
|
||||
post_template: postTemplate,
|
||||
term_level: base,
|
||||
term_parent: termParentId,
|
||||
term_ancestor: termAncestorId,
|
||||
user_role: base
|
||||
};
|
||||
|
||||
/**
|
||||
* Walks through the definitions and evaluates the conditions.
|
||||
*
|
||||
* @param {Object[]} definitions
|
||||
* @param {Object} values
|
||||
* @param {string} relation
|
||||
* @return {boolean}
|
||||
*/
|
||||
function evaluate( definitions, values, relation ) {
|
||||
const results = definitions.map( ( definition ) => {
|
||||
if ( ! definition.relation ) {
|
||||
const condition = get( conditions, definition.type );
|
||||
|
||||
if ( condition ) {
|
||||
return condition.isFulfiled( definition, values );
|
||||
} else { // eslint-disable-line no-else-return
|
||||
// eslint-disable-next-line no-console
|
||||
console.error( sprintf( __( 'Unsupported container condition - "%1$s".', 'carbon-fields-ui' ), definition.type ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
} else { // eslint-disable-line no-else-return
|
||||
return evaluate( definition.conditions, values, definition.relation );
|
||||
}
|
||||
} );
|
||||
|
||||
switch ( relation ) {
|
||||
case 'AND':
|
||||
return results.every( Boolean );
|
||||
|
||||
case 'OR':
|
||||
return results.some( Boolean );
|
||||
|
||||
default:
|
||||
// eslint-disable-next-line no-console
|
||||
console.error( sprintf( __( 'Unsupported container condition relation used - "%1$s".', 'carbon-fields-ui' ), relation ) );
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The function that causes the side effects.
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {Object} props.containers
|
||||
* @param {string} props.context
|
||||
* @return {Function}
|
||||
*/
|
||||
export default function handler( { containers, context } ) {
|
||||
return function( effect ) {
|
||||
const results = map( containers, ( container, id ) => {
|
||||
return [
|
||||
id,
|
||||
evaluate( container.conditions.conditions, effect, container.conditions.relation )
|
||||
];
|
||||
} );
|
||||
|
||||
results.forEach( ( [ id, result ] ) => {
|
||||
const postboxNode = document.getElementById( id );
|
||||
const containerNode = document.querySelector( `.container-${ id }` );
|
||||
const isMounted = !! containerNode?.dataset?.mounted;
|
||||
|
||||
if ( postboxNode ) {
|
||||
postboxNode.hidden = ! result;
|
||||
}
|
||||
|
||||
if ( containerNode ) {
|
||||
if ( createRoot ) {
|
||||
const containerRoot = getContainerRoot( id );
|
||||
|
||||
if ( result && ! containerRoot ) {
|
||||
renderContainer( containers[ id ], context );
|
||||
}
|
||||
|
||||
if ( ! result && containerRoot ) {
|
||||
containerRoot.unmount();
|
||||
}
|
||||
} else {
|
||||
if ( result && ! isMounted ) {
|
||||
renderContainer( containers[ id ], context );
|
||||
}
|
||||
|
||||
if ( ! result && isMounted ) {
|
||||
delete containerNode?.dataset?.mounted;
|
||||
|
||||
// Rely on React's internals instead of `unmountComponentAtNode`
|
||||
// due to https://github.com/facebook/react/issues/13690.
|
||||
// TODO: Conditionally render the fields in the container, this way
|
||||
// we can move away from mount/unmount cycles.
|
||||
containerNode?._reactRootContainer?.unmount();
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
};
|
||||
}
|
||||
36
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/conditional-display/index.js
vendored
Normal file
36
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/conditional-display/index.js
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { withSelect } from '@wordpress/data';
|
||||
import { withEffects } from 'refract-callbag';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import aperture from './aperture';
|
||||
import handler from './handler';
|
||||
|
||||
/**
|
||||
* Performs the evaluation of conditions.
|
||||
*
|
||||
* @return {null}
|
||||
*/
|
||||
function ConditionalDisplay() {
|
||||
return null;
|
||||
}
|
||||
|
||||
const applyWithSelect = withSelect( ( select ) => {
|
||||
const containers = select( 'carbon-fields/metaboxes' ).getContainers();
|
||||
|
||||
return {
|
||||
containers
|
||||
};
|
||||
} );
|
||||
|
||||
const applyWithEffects = withEffects( aperture, { handler } );
|
||||
|
||||
export default compose(
|
||||
applyWithSelect,
|
||||
applyWithEffects
|
||||
)( ConditionalDisplay );
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import getLevelFromOption from './get-level-from-option';
|
||||
|
||||
/**
|
||||
* Extracts the ancestors of the post/term from an option.
|
||||
*
|
||||
* @param {Object} option
|
||||
* @return {number[]}
|
||||
*/
|
||||
export default function getAncestorsFromOption( option ) {
|
||||
const ancestors = [];
|
||||
|
||||
let previousOption = option;
|
||||
let level = getLevelFromOption( option );
|
||||
|
||||
while ( level > 0 && previousOption ) {
|
||||
if ( getLevelFromOption( previousOption ) !== level ) {
|
||||
previousOption = previousOption.previousSibling;
|
||||
|
||||
// Skip this iteration because the option isn't an ancestor.
|
||||
continue;
|
||||
}
|
||||
|
||||
const id = parseInt( previousOption.value, 10 );
|
||||
|
||||
if ( id > 0 ) {
|
||||
ancestors.unshift( id );
|
||||
}
|
||||
|
||||
previousOption = previousOption.previousSibling;
|
||||
|
||||
level--;
|
||||
}
|
||||
|
||||
return ancestors;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* Extracts the level from an option.
|
||||
*
|
||||
* @param {Object} option
|
||||
* @return {number}
|
||||
*/
|
||||
export default function getLevelFromOption( option ) {
|
||||
let level = 0;
|
||||
|
||||
if ( option.className ) {
|
||||
const matches = option.className.match( /^level-(\d+)/ );
|
||||
|
||||
if ( matches ) {
|
||||
level = parseInt( matches[ 1 ], 10 ) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return level;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Extracts the id of the post/term parent from an option.
|
||||
*
|
||||
* @param {Object} option
|
||||
* @return {number}
|
||||
*/
|
||||
export default function getParentIdFromOption( option ) {
|
||||
const value = parseInt( option.value, 10 );
|
||||
|
||||
return ( ! isNaN( value ) && value >= 0 ) ? value : 0;
|
||||
}
|
||||
61
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/index.js
vendored
Normal file
61
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/index.js
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { Fragment, render, createRoot } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import SaveLock from './save-lock';
|
||||
import ConditionalDisplay from './conditional-display';
|
||||
import WidgetHandler from './widget-handler';
|
||||
import RevisionsFlag from './revisions-flag';
|
||||
import isGutenberg from '../utils/is-gutenberg';
|
||||
import { PAGE_NOW_WIDGETS, PAGE_NOW_CUSTOMIZE } from '../lib/constants';
|
||||
|
||||
/**
|
||||
* Initializes the monitors.
|
||||
*
|
||||
* @param {string} context
|
||||
* @return {void}
|
||||
*/
|
||||
export default function initializeMonitors( context ) {
|
||||
const { pagenow } = window.cf.config;
|
||||
|
||||
const MonitorElement = document.createElement( 'div' );
|
||||
const MonitorComponent = <Fragment>
|
||||
{ ! isGutenberg() && (
|
||||
<SaveLock />
|
||||
) }
|
||||
|
||||
{ ( pagenow === PAGE_NOW_WIDGETS || pagenow === PAGE_NOW_CUSTOMIZE ) && (
|
||||
<WidgetHandler />
|
||||
) }
|
||||
|
||||
<ConditionalDisplay context={ context } />
|
||||
</Fragment>;
|
||||
|
||||
if ( createRoot ) {
|
||||
createRoot( MonitorElement ).render( MonitorComponent );
|
||||
} else {
|
||||
render(
|
||||
MonitorComponent,
|
||||
MonitorElement,
|
||||
);
|
||||
}
|
||||
|
||||
const postStuffNode = document.querySelector( '#poststuff' );
|
||||
|
||||
if ( postStuffNode ) {
|
||||
const postStuffElement = document.createElement( 'div' );
|
||||
const postStuffComponenet = <RevisionsFlag />;
|
||||
|
||||
const postStuffChildElement = postStuffNode.appendChild( postStuffElement );
|
||||
|
||||
if ( createRoot ) {
|
||||
createRoot( postStuffChildElement ).render( postStuffComponenet );
|
||||
} else {
|
||||
render( postStuffComponenet, postStuffChildElement );
|
||||
}
|
||||
}
|
||||
}
|
||||
26
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/revisions-flag/index.js
vendored
Normal file
26
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/revisions-flag/index.js
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { withSelect } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Renders the input used to notify the backend about the changes.
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {boolean} props.isDirty
|
||||
* @return {mixed}
|
||||
*/
|
||||
function RevisionsFlag( props ) {
|
||||
return (
|
||||
<input
|
||||
type="hidden"
|
||||
name={ window.cf.config.revisionsInputKey }
|
||||
disabled={ ! props.isDirty }
|
||||
value="1"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default withSelect( ( select ) => ( {
|
||||
isDirty: select( 'carbon-fields/metaboxes' ).isDirty()
|
||||
} ) )( RevisionsFlag );
|
||||
51
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/save-lock/index.js
vendored
Normal file
51
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/save-lock/index.js
vendored
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { withEffects } from 'refract-callbag';
|
||||
import { select } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Carbon Fields dependencies.
|
||||
*/
|
||||
import { fromSelector } from '@carbon-fields/core';
|
||||
|
||||
/**
|
||||
* Toggles the ability to save the page.
|
||||
*
|
||||
* @return {null}
|
||||
*/
|
||||
function SaveLock() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function that controls the stream of side effects.
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
function aperture() {
|
||||
return fromSelector( select( 'carbon-fields/metaboxes' ).isSavingLocked );
|
||||
}
|
||||
|
||||
/**
|
||||
* The function that causes the side effects.
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
function handler() {
|
||||
return function( isLocked ) {
|
||||
const nodes = document.querySelectorAll( `
|
||||
#publishing-action input#publish,
|
||||
#publishing-action input#save,
|
||||
#addtag input#submit,
|
||||
#edittag input[type="submit"],
|
||||
#your-profile input#submit
|
||||
` );
|
||||
|
||||
nodes.forEach( ( node ) => {
|
||||
node.disabled = isLocked;
|
||||
} );
|
||||
};
|
||||
}
|
||||
|
||||
export default withEffects( aperture, { handler } )( SaveLock );
|
||||
47
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/unsaved-changes/index.js
vendored
Normal file
47
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/unsaved-changes/index.js
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { select } from '@wordpress/data';
|
||||
import { withEffects } from 'refract-callbag';
|
||||
|
||||
/**
|
||||
* Carbon Fields dependencies.
|
||||
*/
|
||||
import { fromSelector } from '@carbon-fields/core';
|
||||
|
||||
/**
|
||||
* Toggles the alert if the page has not been saved before reload.
|
||||
*
|
||||
* @return {null}
|
||||
*/
|
||||
function UnsavedChanges() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function that controls the stream of side effects.
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
function aperture() {
|
||||
return fromSelector( select( 'carbon-fields/metaboxes' ).isDirty );
|
||||
}
|
||||
|
||||
/**
|
||||
* The function that causes the side effects.
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
function handler() {
|
||||
return function( isDirty ) {
|
||||
if ( ! isDirty ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Support for custom message has been removed
|
||||
// Ref : https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload#Browser_compatibility
|
||||
window.onbeforeunload = ( e ) => e;
|
||||
};
|
||||
}
|
||||
|
||||
export default withEffects( aperture, { handler } )( UnsavedChanges );
|
||||
183
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/widget-handler/index.js
vendored
Normal file
183
web/vendor/htmlburger/carbon-fields/packages/metaboxes/monitors/widget-handler/index.js
vendored
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/**
|
||||
* External dependencies.
|
||||
*/
|
||||
import { dispatch, select } from '@wordpress/data';
|
||||
import { unmountComponentAtNode } from '@wordpress/element';
|
||||
import { startsWith, flow } from 'lodash';
|
||||
import { withEffects } from 'refract-callbag';
|
||||
import {
|
||||
map,
|
||||
merge,
|
||||
pipe,
|
||||
filter
|
||||
} from 'callbag-basics';
|
||||
|
||||
/**
|
||||
* Internal dependencies.
|
||||
*/
|
||||
import urldecode from '../../utils/urldecode';
|
||||
import flattenField from '../../utils/flatten-field';
|
||||
import fromEventPattern from '../../utils/from-event-pattern';
|
||||
import { renderContainer } from '../../containers';
|
||||
import {
|
||||
CARBON_FIELDS_CONTAINER_ID_PREFIX,
|
||||
CARBON_FIELDS_CONTAINER_WIDGET_ID_PREFIX,
|
||||
PAGE_NOW_CUSTOMIZE
|
||||
} from '../../lib/constants';
|
||||
|
||||
/**
|
||||
* Performs the re-initialization of widgets.
|
||||
*
|
||||
* @return {null}
|
||||
*/
|
||||
function WidgetHandler() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the widget is created by Carbon Fields.
|
||||
*
|
||||
* @param {string} identifier
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isCarbonFieldsWidget( identifier ) {
|
||||
return identifier.indexOf( CARBON_FIELDS_CONTAINER_WIDGET_ID_PREFIX ) > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The function that controls the stream of side effects.
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
function aperture() {
|
||||
return merge(
|
||||
pipe(
|
||||
fromEventPattern(
|
||||
( handler ) => window.jQuery( document ).on( 'widget-added widget-updated', handler ),
|
||||
( handler ) => window.jQuery( document ).off( 'widget-added widget-updated', handler ),
|
||||
( event, $widget ) => ( {
|
||||
event,
|
||||
$widget
|
||||
} )
|
||||
),
|
||||
filter( ( { $widget } ) => {
|
||||
return isCarbonFieldsWidget( $widget[ 0 ].id );
|
||||
} ),
|
||||
map( ( payload ) => ( {
|
||||
type: 'WIDGET_CREATED_OR_UPDATED',
|
||||
payload
|
||||
} ) )
|
||||
),
|
||||
|
||||
pipe(
|
||||
fromEventPattern(
|
||||
( handler ) => window.jQuery( document ).on( 'ajaxSend', handler ),
|
||||
( handler ) => window.jQuery( document ).off( 'ajaxSend', handler ),
|
||||
( event, xhr, options, data ) => ( {
|
||||
event,
|
||||
xhr,
|
||||
options,
|
||||
data
|
||||
} )
|
||||
),
|
||||
filter( ( { options } ) => {
|
||||
return startsWith( options.data, CARBON_FIELDS_CONTAINER_ID_PREFIX );
|
||||
} ),
|
||||
map( ( payload ) => ( {
|
||||
type: 'WIDGET_BEIGN_UPDATED_OR_DELETED',
|
||||
payload
|
||||
} ) )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The function that causes the side effects.
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
function handler() {
|
||||
return function( effect ) {
|
||||
const { getContainerById } = select( 'carbon-fields/metaboxes' );
|
||||
const {
|
||||
addContainer,
|
||||
removeContainer,
|
||||
addFields,
|
||||
removeFields
|
||||
} = dispatch( 'carbon-fields/metaboxes' );
|
||||
|
||||
switch ( effect.type ) {
|
||||
case 'WIDGET_CREATED_OR_UPDATED': {
|
||||
const { event, $widget } = effect.payload;
|
||||
|
||||
const container = flow(
|
||||
urldecode,
|
||||
JSON.parse
|
||||
)(
|
||||
$widget
|
||||
.find( '[data-json]' )
|
||||
.data( 'json' )
|
||||
);
|
||||
|
||||
const fields = [];
|
||||
|
||||
container.fields = container.fields.map( ( field ) => flattenField( field, container, fields ) );
|
||||
|
||||
addFields( fields );
|
||||
addContainer( container );
|
||||
|
||||
renderContainer( container, 'classic' );
|
||||
|
||||
// WARNING: This piece of code manipulates the core behavior of WordPress Widgets.
|
||||
// Some day this code will stop to work and we'll need to find another workaround.
|
||||
//
|
||||
// * Disable the submit { handler } since it breaks our validation logic.
|
||||
// * Disable live preview mode because we can't detect when the widget is updated/synced.
|
||||
// * Show the "Apply" button because it's hidden by the live mode.
|
||||
if ( window.cf.config.pagenow === PAGE_NOW_CUSTOMIZE && event.type === 'widget-added' ) {
|
||||
const widgetId = $widget
|
||||
.find( '[name="widget-id"]' )
|
||||
.val();
|
||||
|
||||
$widget
|
||||
.find( '[name="savewidget"]' )
|
||||
.show()
|
||||
.end()
|
||||
.find( '.widget-content:first' )
|
||||
.off( 'keydown', 'input' )
|
||||
.off( 'change input propertychange', ':input' );
|
||||
|
||||
const instance = wp.customize.Widgets.getWidgetFormControlForWidget( widgetId );
|
||||
|
||||
// Change the flag for 'live mode' so we can receive proper `widget-updated` events.
|
||||
instance.liveUpdateMode = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'WIDGET_BEIGN_UPDATED_OR_DELETED': {
|
||||
const [ , widgetId ] = effect.payload.options.data.match( /widget-id=(.+?)&/ );
|
||||
|
||||
const containerId = `${ CARBON_FIELDS_CONTAINER_ID_PREFIX }${ widgetId }`;
|
||||
|
||||
// Get the container from the store.
|
||||
const container = getContainerById( containerId );
|
||||
|
||||
// Remove the current instance from DOM.
|
||||
unmountComponentAtNode( document.querySelector( `.container-${ containerId }` ) );
|
||||
|
||||
// Get the fields that belongs to the container.
|
||||
const fieldsIds = _.map( container.fields, 'id' );
|
||||
|
||||
// Remove everything from the store.
|
||||
removeContainer( containerId );
|
||||
removeFields( fieldsIds );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default withEffects( aperture, { handler } )( WidgetHandler );
|
||||
Loading…
Add table
Add a link
Reference in a new issue