UNPKG

@wordpress/block-library

Version:
415 lines (375 loc) 15.3 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = LatestPostsEdit; var _element = require("@wordpress/element"); var _lodash = require("lodash"); var _classnames = _interopRequireDefault(require("classnames")); var _components = require("@wordpress/components"); var _i18n = require("@wordpress/i18n"); var _date = require("@wordpress/date"); var _blockEditor = require("@wordpress/block-editor"); var _data = require("@wordpress/data"); var _icons = require("@wordpress/icons"); var _coreData = require("@wordpress/core-data"); var _notices = require("@wordpress/notices"); var _compose = require("@wordpress/compose"); var _constants = require("./constants"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ /** * Module Constants */ const CATEGORIES_LIST_QUERY = { per_page: -1, context: 'view' }; const USERS_LIST_QUERY = { per_page: -1, has_published_posts: ['post'], context: 'view' }; function getFeaturedImageDetails(post, size) { var _image$media_details$, _image$media_details, _image$media_details$2, _image$media_details$3; const image = (0, _lodash.get)(post, ['_embedded', 'wp:featuredmedia', '0']); return { url: (_image$media_details$ = image === null || image === void 0 ? void 0 : (_image$media_details = image.media_details) === null || _image$media_details === void 0 ? void 0 : (_image$media_details$2 = _image$media_details.sizes) === null || _image$media_details$2 === void 0 ? void 0 : (_image$media_details$3 = _image$media_details$2[size]) === null || _image$media_details$3 === void 0 ? void 0 : _image$media_details$3.source_url) !== null && _image$media_details$ !== void 0 ? _image$media_details$ : image === null || image === void 0 ? void 0 : image.source_url, alt: image === null || image === void 0 ? void 0 : image.alt_text }; } function LatestPostsEdit(_ref) { var _categoriesList$reduc; let { attributes, setAttributes } = _ref; const instanceId = (0, _compose.useInstanceId)(LatestPostsEdit); const { postsToShow, order, orderBy, categories, selectedAuthor, displayFeaturedImage, displayPostContentRadio, displayPostContent, displayPostDate, displayAuthor, postLayout, columns, excerptLength, featuredImageAlign, featuredImageSizeSlug, featuredImageSizeWidth, featuredImageSizeHeight, addLinkToFeaturedImage } = attributes; const { imageSizes, latestPosts, defaultImageWidth, defaultImageHeight, categoriesList, authorList } = (0, _data.useSelect)(select => { const { getEntityRecords, getUsers } = select(_coreData.store); const settings = select(_blockEditor.store).getSettings(); const catIds = categories && categories.length > 0 ? categories.map(cat => cat.id) : []; const latestPostsQuery = (0, _lodash.pickBy)({ categories: catIds, author: selectedAuthor, order, orderby: orderBy, per_page: postsToShow, _embed: 'wp:featuredmedia' }, value => typeof value !== 'undefined'); return { defaultImageWidth: (0, _lodash.get)(settings.imageDimensions, [featuredImageSizeSlug, 'width'], 0), defaultImageHeight: (0, _lodash.get)(settings.imageDimensions, [featuredImageSizeSlug, 'height'], 0), imageSizes: settings.imageSizes, latestPosts: getEntityRecords('postType', 'post', latestPostsQuery), categoriesList: getEntityRecords('taxonomy', 'category', CATEGORIES_LIST_QUERY), authorList: getUsers(USERS_LIST_QUERY) }; }, [featuredImageSizeSlug, postsToShow, order, orderBy, categories, selectedAuthor]); // If a user clicks to a link prevent redirection and show a warning. const { createWarningNotice, removeNotice } = (0, _data.useDispatch)(_notices.store); let noticeId; const showRedirectionPreventedNotice = event => { event.preventDefault(); // Remove previous warning if any, to show one at a time per block. removeNotice(noticeId); noticeId = `block-library/core/latest-posts/redirection-prevented/${instanceId}`; createWarningNotice((0, _i18n.__)('Links are disabled in the editor.'), { id: noticeId, type: 'snackbar' }); }; const imageSizeOptions = imageSizes.filter(_ref2 => { let { slug } = _ref2; return slug !== 'full'; }).map(_ref3 => { let { name, slug } = _ref3; return { value: slug, label: name }; }); const categorySuggestions = (_categoriesList$reduc = categoriesList === null || categoriesList === void 0 ? void 0 : categoriesList.reduce((accumulator, category) => ({ ...accumulator, [category.name]: category }), {})) !== null && _categoriesList$reduc !== void 0 ? _categoriesList$reduc : {}; const selectCategories = tokens => { const hasNoSuggestion = tokens.some(token => typeof token === 'string' && !categorySuggestions[token]); if (hasNoSuggestion) { return; } // Categories that are already will be objects, while new additions will be strings (the name). // allCategories nomalizes the array so that they are all objects. const allCategories = tokens.map(token => { return typeof token === 'string' ? categorySuggestions[token] : token; }); // We do nothing if the category is not selected // from suggestions. if ((0, _lodash.includes)(allCategories, null)) { return false; } setAttributes({ categories: allCategories }); }; const hasPosts = !!(latestPosts !== null && latestPosts !== void 0 && latestPosts.length); const inspectorControls = (0, _element.createElement)(_blockEditor.InspectorControls, null, (0, _element.createElement)(_components.PanelBody, { title: (0, _i18n.__)('Post content settings') }, (0, _element.createElement)(_components.ToggleControl, { label: (0, _i18n.__)('Post content'), checked: displayPostContent, onChange: value => setAttributes({ displayPostContent: value }) }), displayPostContent && (0, _element.createElement)(_components.RadioControl, { label: (0, _i18n.__)('Show:'), selected: displayPostContentRadio, options: [{ label: (0, _i18n.__)('Excerpt'), value: 'excerpt' }, { label: (0, _i18n.__)('Full post'), value: 'full_post' }], onChange: value => setAttributes({ displayPostContentRadio: value }) }), displayPostContent && displayPostContentRadio === 'excerpt' && (0, _element.createElement)(_components.RangeControl, { label: (0, _i18n.__)('Max number of words in excerpt'), value: excerptLength, onChange: value => setAttributes({ excerptLength: value }), min: _constants.MIN_EXCERPT_LENGTH, max: _constants.MAX_EXCERPT_LENGTH })), (0, _element.createElement)(_components.PanelBody, { title: (0, _i18n.__)('Post meta settings') }, (0, _element.createElement)(_components.ToggleControl, { label: (0, _i18n.__)('Display author name'), checked: displayAuthor, onChange: value => setAttributes({ displayAuthor: value }) }), (0, _element.createElement)(_components.ToggleControl, { label: (0, _i18n.__)('Display post date'), checked: displayPostDate, onChange: value => setAttributes({ displayPostDate: value }) })), (0, _element.createElement)(_components.PanelBody, { title: (0, _i18n.__)('Featured image settings') }, (0, _element.createElement)(_components.ToggleControl, { label: (0, _i18n.__)('Display featured image'), checked: displayFeaturedImage, onChange: value => setAttributes({ displayFeaturedImage: value }) }), displayFeaturedImage && (0, _element.createElement)(_element.Fragment, null, (0, _element.createElement)(_blockEditor.__experimentalImageSizeControl, { onChange: value => { const newAttrs = {}; if (value.hasOwnProperty('width')) { newAttrs.featuredImageSizeWidth = value.width; } if (value.hasOwnProperty('height')) { newAttrs.featuredImageSizeHeight = value.height; } setAttributes(newAttrs); }, slug: featuredImageSizeSlug, width: featuredImageSizeWidth, height: featuredImageSizeHeight, imageWidth: defaultImageWidth, imageHeight: defaultImageHeight, imageSizeOptions: imageSizeOptions, onChangeImage: value => setAttributes({ featuredImageSizeSlug: value, featuredImageSizeWidth: undefined, featuredImageSizeHeight: undefined }) }), (0, _element.createElement)(_components.BaseControl, { className: "editor-latest-posts-image-alignment-control" }, (0, _element.createElement)(_components.BaseControl.VisualLabel, null, (0, _i18n.__)('Image alignment')), (0, _element.createElement)(_blockEditor.BlockAlignmentToolbar, { value: featuredImageAlign, onChange: value => setAttributes({ featuredImageAlign: value }), controls: ['left', 'center', 'right'], isCollapsed: false })), (0, _element.createElement)(_components.ToggleControl, { label: (0, _i18n.__)('Add link to featured image'), checked: addLinkToFeaturedImage, onChange: value => setAttributes({ addLinkToFeaturedImage: value }) }))), (0, _element.createElement)(_components.PanelBody, { title: (0, _i18n.__)('Sorting and filtering') }, (0, _element.createElement)(_components.QueryControls, { order, orderBy, numberOfItems: postsToShow, onOrderChange: value => setAttributes({ order: value }), onOrderByChange: value => setAttributes({ orderBy: value }), onNumberOfItemsChange: value => setAttributes({ postsToShow: value }), categorySuggestions: categorySuggestions, onCategoryChange: selectCategories, selectedCategories: categories, onAuthorChange: value => setAttributes({ selectedAuthor: '' !== value ? Number(value) : undefined }), authorList: authorList !== null && authorList !== void 0 ? authorList : [], selectedAuthorId: selectedAuthor }), postLayout === 'grid' && (0, _element.createElement)(_components.RangeControl, { label: (0, _i18n.__)('Columns'), value: columns, onChange: value => setAttributes({ columns: value }), min: 2, max: !hasPosts ? _constants.MAX_POSTS_COLUMNS : Math.min(_constants.MAX_POSTS_COLUMNS, latestPosts.length), required: true }))); const blockProps = (0, _blockEditor.useBlockProps)({ className: (0, _classnames.default)({ 'wp-block-latest-posts__list': true, 'is-grid': postLayout === 'grid', 'has-dates': displayPostDate, 'has-author': displayAuthor, [`columns-${columns}`]: postLayout === 'grid' }) }); if (!hasPosts) { return (0, _element.createElement)("div", blockProps, inspectorControls, (0, _element.createElement)(_components.Placeholder, { icon: _icons.pin, label: (0, _i18n.__)('Latest Posts') }, !Array.isArray(latestPosts) ? (0, _element.createElement)(_components.Spinner, null) : (0, _i18n.__)('No posts found.'))); } // Removing posts from display should be instant. const displayPosts = latestPosts.length > postsToShow ? latestPosts.slice(0, postsToShow) : latestPosts; const layoutControls = [{ icon: _icons.list, title: (0, _i18n.__)('List view'), onClick: () => setAttributes({ postLayout: 'list' }), isActive: postLayout === 'list' }, { icon: _icons.grid, title: (0, _i18n.__)('Grid view'), onClick: () => setAttributes({ postLayout: 'grid' }), isActive: postLayout === 'grid' }]; const dateFormat = (0, _date.getSettings)().formats.date; return (0, _element.createElement)("div", null, inspectorControls, (0, _element.createElement)(_blockEditor.BlockControls, null, (0, _element.createElement)(_components.ToolbarGroup, { controls: layoutControls })), (0, _element.createElement)("ul", blockProps, displayPosts.map((post, i) => { const titleTrimmed = post.title.rendered.trim(); let excerpt = post.excerpt.rendered; const currentAuthor = authorList === null || authorList === void 0 ? void 0 : authorList.find(author => author.id === post.author); const excerptElement = document.createElement('div'); excerptElement.innerHTML = excerpt; excerpt = excerptElement.textContent || excerptElement.innerText || ''; const { url: imageSourceUrl, alt: featuredImageAlt } = getFeaturedImageDetails(post, featuredImageSizeSlug); const imageClasses = (0, _classnames.default)({ 'wp-block-latest-posts__featured-image': true, [`align${featuredImageAlign}`]: !!featuredImageAlign }); const renderFeaturedImage = displayFeaturedImage && imageSourceUrl; const featuredImage = renderFeaturedImage && (0, _element.createElement)("img", { src: imageSourceUrl, alt: featuredImageAlt, style: { maxWidth: featuredImageSizeWidth, maxHeight: featuredImageSizeHeight } }); const needsReadMore = excerptLength < excerpt.trim().split(' ').length && post.excerpt.raw === ''; const postExcerpt = needsReadMore ? (0, _element.createElement)(_element.Fragment, null, excerpt.trim().split(' ', excerptLength).join(' '), (0, _i18n.__)(' … '), (0, _element.createElement)("a", { href: post.link, rel: "noopener noreferrer", onClick: showRedirectionPreventedNotice }, (0, _i18n.__)('Read more'))) : excerpt; return (0, _element.createElement)("li", { key: i }, renderFeaturedImage && (0, _element.createElement)("div", { className: imageClasses }, addLinkToFeaturedImage ? (0, _element.createElement)("a", { className: "wp-block-latest-posts__post-title", href: post.link, rel: "noreferrer noopener", onClick: showRedirectionPreventedNotice }, featuredImage) : featuredImage), (0, _element.createElement)("a", { href: post.link, rel: "noreferrer noopener", dangerouslySetInnerHTML: !!titleTrimmed ? { __html: titleTrimmed } : undefined, onClick: showRedirectionPreventedNotice }, !titleTrimmed ? (0, _i18n.__)('(no title)') : null), displayAuthor && currentAuthor && (0, _element.createElement)("div", { className: "wp-block-latest-posts__post-author" }, (0, _i18n.sprintf)( /* translators: byline. %s: current author. */ (0, _i18n.__)('by %s'), currentAuthor.name)), displayPostDate && post.date_gmt && (0, _element.createElement)("time", { dateTime: (0, _date.format)('c', post.date_gmt), className: "wp-block-latest-posts__post-date" }, (0, _date.dateI18n)(dateFormat, post.date_gmt)), displayPostContent && displayPostContentRadio === 'excerpt' && (0, _element.createElement)("div", { className: "wp-block-latest-posts__post-excerpt" }, postExcerpt), displayPostContent && displayPostContentRadio === 'full_post' && (0, _element.createElement)("div", { className: "wp-block-latest-posts__post-full-content", dangerouslySetInnerHTML: { __html: post.content.raw.trim() } })); }))); } //# sourceMappingURL=edit.js.map