diff --git a/includes/blocks/build/sections/block.json b/includes/blocks/build/sections/block.json new file mode 100644 index 0000000..8feca55 --- /dev/null +++ b/includes/blocks/build/sections/block.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "knowledgebase/sections", + "version": "2.3.0", + "title": "Knowledge Base Sections", + "category": "design", + "icon": "book", + "keywords": [ + "knowledgbase", + "sections", + "kb" + ], + "description": "Display the list of sections when browsing a knowledge base page", + "supports": { + "html": false + }, + "attributes": { + "className": { + "type": "string", + "default": "" + }, + "title": { + "type": "string", + "default": "" + }, + "termID": { + "type": "string", + "default": "" + }, + "depth": { + "type": "string", + "default": "" + }, + "beforeLiItem": { + "type": "string", + "default": "" + }, + "afterLiItem": { + "type": "string", + "default": "" + } + }, + "example": {}, + "textdomain": "knowledgebase", + "editorScript": "file:./index.js", + "editorStyle": "file:./index.css" +} \ No newline at end of file diff --git a/includes/blocks/build/sections/index-rtl.css b/includes/blocks/build/sections/index-rtl.css new file mode 100644 index 0000000..55ede6e --- /dev/null +++ b/includes/blocks/build/sections/index-rtl.css @@ -0,0 +1 @@ +.wzkb-articles-list{margin:0!important;padding:0!important}.wzkb-articles-list li{list-style-type:none!important;margin:5px 0}.wzkb-articles-list li:before{content:"";display:inline-block;font-family:dashicons;font-size:20px;font-style:normal;font-weight:400;height:20px;line-height:1;text-align:center;text-decoration:inherit;transition:color .1s ease-in 0;vertical-align:top;width:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;margin-left:10px;word-wrap:break-word;color:#666}@media only screen and (max-width:480px){.col{margin:1% 0}.span_1_of_2,.span_1_of_3,.span_1_of_4,.span_1_of_5,.span_2_of_2,.span_2_of_3,.span_2_of_4,.span_2_of_5,.span_3_of_3,.span_3_of_4,.span_3_of_5,.span_4_of_4,.span_4_of_5,.span_5_of_5{width:100%}} diff --git a/includes/blocks/build/sections/index.asset.php b/includes/blocks/build/sections/index.asset.php new file mode 100644 index 0000000..9fbe136 --- /dev/null +++ b/includes/blocks/build/sections/index.asset.php @@ -0,0 +1 @@ + array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-i18n', 'wp-server-side-render'), 'version' => '8dcdb4c49c5937146313'); diff --git a/includes/blocks/build/sections/index.css b/includes/blocks/build/sections/index.css new file mode 100644 index 0000000..130e0c1 --- /dev/null +++ b/includes/blocks/build/sections/index.css @@ -0,0 +1 @@ +.wzkb-articles-list{margin:0!important;padding:0!important}.wzkb-articles-list li{list-style-type:none!important;margin:5px 0}.wzkb-articles-list li:before{content:"";display:inline-block;font-family:dashicons;font-size:20px;font-style:normal;font-weight:400;height:20px;line-height:1;text-align:center;text-decoration:inherit;transition:color .1s ease-in 0;vertical-align:top;width:20px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;margin-right:10px;word-wrap:break-word;color:#666}@media only screen and (max-width:480px){.col{margin:1% 0}.span_1_of_2,.span_1_of_3,.span_1_of_4,.span_1_of_5,.span_2_of_2,.span_2_of_3,.span_2_of_4,.span_2_of_5,.span_3_of_3,.span_3_of_4,.span_3_of_5,.span_4_of_4,.span_4_of_5,.span_5_of_5{width:100%}} diff --git a/includes/blocks/build/sections/index.js b/includes/blocks/build/sections/index.js new file mode 100644 index 0000000..28aa497 --- /dev/null +++ b/includes/blocks/build/sections/index.js @@ -0,0 +1 @@ +(()=>{"use strict";var e={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},d:(t,n)=>{for(var l in n)e.o(n,l)&&!e.o(t,l)&&Object.defineProperty(t,l,{enumerable:!0,get:n[l]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.wp.blocks,n=window.React,l=window.wp.i18n,o=window.wp.serverSideRender;var a=e.n(o);const r=window.wp.blockEditor,s=window.wp.data,i=window.wp.coreData,d=window.wp.components;(0,t.registerBlockType)("knowledgebase/sections",{edit:function({attributes:e,setAttributes:t}){const{termID:o,depth:c,beforeLiItem:w,afterLiItem:m}=e,b=(0,r.useBlockProps)(),{terms:g,hasResolved:p,error:u}=(0,s.useSelect)((e=>{const t=["taxonomy","wzkb_category",{per_page:-1}];try{return{terms:e(i.store).getEntityRecords(...t),hasResolved:e(i.store).hasFinishedResolution("getEntityRecords",t),error:null}}catch(e){return{terms:[],hasResolved:!0,error:e}}}),[]),_=g?.map((e=>({label:`${e.name} (#${e.id})`,value:e.id.toString()})))||[];return(0,n.createElement)(n.Fragment,null,(0,n.createElement)(r.InspectorControls,null,u&&(0,n.createElement)(d.Notice,{status:"error",isDismissible:!1},(0,l.__)("Error loading categories. Please try again.","knowledgebase")),(0,n.createElement)(d.PanelBody,{title:(0,l.__)("Knowledge Base Sections Settings","knowledgebase"),initialOpen:!0},(0,n.createElement)(d.PanelRow,null,p?(0,n.createElement)(d.ComboboxControl,{label:(0,l.__)("Select Knowledge Base Section","knowledgebase"),value:o,onChange:e=>t({termID:e}),options:_,help:(0,l.__)("Search and select a knowledge base section","knowledgebase")}):(0,n.createElement)(d.Spinner,null)),(0,n.createElement)(d.PanelRow,null,(0,n.createElement)(d.TextControl,{label:(0,l.__)("Depth","knowledgebase"),value:c,type:"number",min:"0",onChange:e=>t({depth:e}),help:(0,l.__)("Enter the depth of sections to display (0 for all)","knowledgebase")})),(0,n.createElement)(d.PanelRow,null,(0,n.createElement)(d.TextControl,{label:(0,l.__)("Before list item","knowledgebase"),value:w,onChange:e=>t({beforeLiItem:e}),help:(0,l.__)("HTML/text to add before each list item","knowledgebase")})),(0,n.createElement)(d.PanelRow,null,(0,n.createElement)(d.TextControl,{label:(0,l.__)("After list item","knowledgebase"),value:m,onChange:e=>t({afterLiItem:e}),help:(0,l.__)("HTML/text to add after each list item","knowledgebase")})))),(0,n.createElement)("div",{...b},(0,n.createElement)(d.Disabled,null,(0,n.createElement)(a(),{block:"knowledgebase/sections",attributes:e}))))}})})(); \ No newline at end of file diff --git a/includes/blocks/class-blocks.php b/includes/blocks/class-blocks.php index 2028eed..17414fe 100644 --- a/includes/blocks/class-blocks.php +++ b/includes/blocks/class-blocks.php @@ -45,6 +45,7 @@ public function register_blocks() { 'alerts' => 'render_alerts_block', 'articles' => 'render_articles_block', 'breadcrumb' => 'render_breadcrumb_block', + 'sections' => 'render_sections_block', ); foreach ( $blocks as $block_name => $render_callback ) { @@ -199,4 +200,53 @@ public static function render_breadcrumb_block( $attributes ) { return $output; } + + /** + * Renders the `knowledgebase/sections` block on server. + * + * @since 2.3.0 + * + * @param array $attributes The block attributes. + * + * @return string Returns the sections list. + */ + public function render_sections_block( $attributes ) { + $mappings = array( + 'term_id' => 'termID', + 'before_li_item' => 'beforeLiItem', + 'after_li_item' => 'afterLiItem', + ); + + $attributes = $this->map_attributes( $attributes, $mappings ); + + $arguments = array( + 'is_block' => 1, + 'depth' => ( ! empty( $attributes['depth'] ) ) ? (int) $attributes['depth'] : 0, + 'before_li_item' => ( ! empty( $attributes['before_li_item'] ) ) ? $attributes['before_li_item'] : '', + 'after_li_item' => ( ! empty( $attributes['after_li_item'] ) ) ? $attributes['after_li_item'] : '', + ); + + $term_id = ! empty( $attributes['term_id'] ) ? (int) $attributes['term_id'] : 0; + + /** + * Filters arguments passed to wzkb_categories_list for the block. + * + * @since 2.3.0 + * + * @param array $arguments Knowledge Base block options array. + * @param array $attributes Block attributes array. + */ + $arguments = apply_filters( 'wzkb_sections_block_options', $arguments, $attributes ); + + $wrapper_attributes = get_block_wrapper_attributes(); + + $output = sprintf( + '
%2$s%3$s
', + $wrapper_attributes, + ! empty( $attributes['title'] ) ? '

' . esc_html( $attributes['title'] ) . '

' : '', + wzkb_categories_list( $term_id, 0, $arguments ) + ); + + return $output; + } } diff --git a/includes/blocks/src/sections/block.json b/includes/blocks/src/sections/block.json new file mode 100644 index 0000000..92bd1b4 --- /dev/null +++ b/includes/blocks/src/sections/block.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "name": "knowledgebase/sections", + "version": "2.3.0", + "title": "Knowledge Base Sections", + "category": "design", + "icon": "book", + "keywords": ["knowledgbase", "sections", "kb"], + "description": "Display the list of sections when browsing a knowledge base page", + "supports": { + "html": false + }, + "attributes": { + "className": { + "type": "string", + "default": "" + }, + "title": { + "type": "string", + "default": "" + }, + "termID": { + "type": "string", + "default": "" + }, + "depth": { + "type": "string", + "default": "" + }, + "beforeLiItem": { + "type": "string", + "default": "" + }, + "afterLiItem": { + "type": "string", + "default": "" + } + }, + "example": {}, + "textdomain": "knowledgebase", + "editorScript": "file:./index.js", + "editorStyle": "file:./index.css" +} diff --git a/includes/blocks/src/sections/edit.js b/includes/blocks/src/sections/edit.js new file mode 100644 index 0000000..770282f --- /dev/null +++ b/includes/blocks/src/sections/edit.js @@ -0,0 +1,146 @@ +import { __ } from '@wordpress/i18n'; +import ServerSideRender from '@wordpress/server-side-render'; +import { useBlockProps, InspectorControls } from '@wordpress/block-editor'; +import { useSelect } from '@wordpress/data'; +import { store as coreStore } from '@wordpress/core-data'; + +import { + Disabled, + ComboboxControl, + PanelBody, + PanelRow, + Spinner, + TextControl, + Notice, +} from '@wordpress/components'; + +import './editor.scss'; + +export default function Edit({ attributes, setAttributes }) { + const { termID, depth, beforeLiItem, afterLiItem } = attributes; + + const blockProps = useBlockProps(); + + const { terms, hasResolved, error } = useSelect((select) => { + const query = { per_page: -1 }; + const selectorArgs = ['taxonomy', 'wzkb_category', query]; + + try { + return { + terms: select(coreStore).getEntityRecords(...selectorArgs), + hasResolved: select(coreStore).hasFinishedResolution( + 'getEntityRecords', + selectorArgs + ), + error: null, + }; + } catch (fetchError) { + return { + terms: [], + hasResolved: true, + error: fetchError, + }; + } + }, []); + + const termOptions = + terms?.map((term) => ({ + label: `${term.name} (#${term.id})`, + value: term.id.toString(), + })) || []; + + return ( + <> + + {error && ( + + {__( + 'Error loading categories. Please try again.', + 'knowledgebase' + )} + + )} + + + + {!hasResolved ? ( + + ) : ( + + setAttributes({ termID: value }) + } + options={termOptions} + help={__( + 'Search and select a knowledge base section', + 'knowledgebase' + )} + /> + )} + + + + setAttributes({ depth: value }) + } + help={__( + 'Enter the depth of sections to display (0 for all)', + 'knowledgebase' + )} + /> + + + + setAttributes({ beforeLiItem: value }) + } + help={__( + 'HTML/text to add before each list item', + 'knowledgebase' + )} + /> + + + + setAttributes({ afterLiItem: value }) + } + help={__( + 'HTML/text to add after each list item', + 'knowledgebase' + )} + /> + + + + +
+ + + +
+ + ); +} diff --git a/includes/blocks/src/sections/editor.scss b/includes/blocks/src/sections/editor.scss new file mode 100644 index 0000000..a1d51b7 --- /dev/null +++ b/includes/blocks/src/sections/editor.scss @@ -0,0 +1,61 @@ +/** + * The following styles get applied inside the editor only. + * + * Replace them with your own styles or remove the file completely. + */ + +.wzkb-articles-list { + margin: 0 !important; + padding: 0 !important; +} + +.wzkb-articles-list li { + margin: 5px 0; + list-style-type: none !important; +} + +.wzkb-articles-list li:before { + content: "\f123"; + display: inline-block; + width: 20px; + height: 20px; + font-size: 20px; + line-height: 1; + font-family: dashicons; + text-decoration: inherit; + font-weight: 400; + font-style: normal; + vertical-align: top; + text-align: center; + -webkit-transition: color .1s ease-in 0; + transition: color .1s ease-in 0; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + margin-right: 10px; + word-wrap: break-word; + color: #666; +} + +/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ +@media only screen and (max-width: 480px) { + .col { + margin: 1% 0; + } + + .span_2_of_2, + .span_1_of_2, + .span_1_of_3, + .span_2_of_3, + .span_3_of_3, + .span_1_of_4, + .span_2_of_4, + .span_3_of_4, + .span_4_of_4, + .span_1_of_5, + .span_2_of_5, + .span_3_of_5, + .span_4_of_5, + .span_5_of_5 { + width: 100%; + } +} \ No newline at end of file diff --git a/includes/blocks/src/sections/index.js b/includes/blocks/src/sections/index.js new file mode 100644 index 0000000..5a50112 --- /dev/null +++ b/includes/blocks/src/sections/index.js @@ -0,0 +1,23 @@ +/** + * Registers a new block provided a unique name and an object defining its behavior. + * + * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/ + */ +import { registerBlockType } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import Edit from './edit'; + +/** + * Every block starts by registering a new block type definition. + * + * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/ + */ +registerBlockType('knowledgebase/sections', { + /** + * @see ./edit.js + */ + edit: Edit, +}); diff --git a/package.json b/package.json index b1b164b..34d07bf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@webberzone/knowledgebase", - "version": "2.2.1", + "version": "2.3.0", "description": "Fastest way to create a highly-flexible multi-product knowledge base.", "author": "WebberZone", "license": "GPL-2.0-or-later", @@ -11,6 +11,7 @@ "build:kb": "wp-scripts build --webpack-src-dir=includes/blocks/src/kb/ --output-path=includes/blocks/build/kb/", "build:articles": "wp-scripts build --webpack-src-dir=includes/blocks/src/articles/ --output-path=includes/blocks/build/articles/", "build:breadcrumb": "wp-scripts build --webpack-src-dir=includes/blocks/src/breadcrumb/ --output-path=includes/blocks/build/breadcrumb/", + "build:sections": "wp-scripts build --webpack-src-dir=includes/blocks/src/sections/ --output-path=includes/blocks/build/sections/", "format": "wp-scripts format ./includes/blocks/src/", "lint:css": "wp-scripts lint-style ./includes/blocks/src/", "lint:js": "wp-scripts lint-js ./includes/blocks/src/", @@ -20,6 +21,7 @@ "start:kb": "wp-scripts start --webpack-src-dir=includes/blocks/src/kb/ --output-path=includes/blocks/build/kb/", "start:articles": "wp-scripts start --webpack-src-dir=includes/blocks/src/articles/ --output-path=includes/blocks/build/articles/", "start:breadcrumb": "wp-scripts start --webpack-src-dir=includes/blocks/src/breadcrumb/ --output-path=includes/blocks/build/breadcrumb/", + "start:sections": "wp-scripts start --webpack-src-dir=includes/blocks/src/sections/ --output-path=includes/blocks/build/sections/", "zip": "wp-scripts plugin-zip" }, "files": [ diff --git a/readme.txt b/readme.txt index fc6f212..cec14b0 100644 --- a/readme.txt +++ b/readme.txt @@ -125,6 +125,7 @@ The plugin has been completely rewritten to use classes and autoloading. * Features: * New block: Knowledge Base Articles. * New block: Knowledge Base Breadcrumbs. + * New block: Knowledge Base Sections. * Modifications: * Enhanced breadcrumb navigation with semantic HTML5 markup and improved accessibility