Initial
This commit is contained in:
18
blocks/bar-graph/.editorconfig
Normal file
18
blocks/bar-graph/.editorconfig
Normal file
@ -0,0 +1,18 @@
|
||||
# This file is for unifying the coding style for different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
# WordPress Coding Standards
|
||||
# https://make.wordpress.org/core/handbook/coding-standards/
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = tab
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
30
blocks/bar-graph/.gitignore
vendored
Normal file
30
blocks/bar-graph/.gitignore
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Output of `npm pack`
|
||||
*.tgz
|
||||
|
||||
# Output of `wp-scripts plugin-zip`
|
||||
*.zip
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
74
blocks/bar-graph/lcp-bar-graph.php
Normal file
74
blocks/bar-graph/lcp-bar-graph.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* Bar Graph Block Registration
|
||||
*
|
||||
* @package LCP-Data-Blocks
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the block using the metadata loaded from the `block.json` file.
|
||||
*/
|
||||
function lcp_bar_graph_block_init() {
|
||||
// Register the block using the metadata loaded from the `block.json` file.
|
||||
register_block_type(
|
||||
__DIR__ . '/build',
|
||||
array(
|
||||
'render_callback' => 'lcp_render_bar_graph_block'
|
||||
)
|
||||
);
|
||||
}
|
||||
add_action('init', 'lcp_bar_graph_block_init');
|
||||
|
||||
/**
|
||||
* Register D3.js as a dependency
|
||||
*/
|
||||
function lcp_register_d3() {
|
||||
wp_register_script(
|
||||
'd3',
|
||||
'https://d3js.org/d3.v7.min.js',
|
||||
array(),
|
||||
'7.0.0',
|
||||
true
|
||||
);
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'lcp_register_d3');
|
||||
add_action('enqueue_block_editor_assets', 'lcp_register_d3');
|
||||
|
||||
/**
|
||||
* Renders the block on the server.
|
||||
*
|
||||
* @param array $attributes Block attributes.
|
||||
* @param string $content Block default content.
|
||||
* @return string Returns the block content.
|
||||
*/
|
||||
function lcp_render_bar_graph_block($attributes, $content) {
|
||||
if (!is_array($attributes)) {
|
||||
$attributes = array();
|
||||
}
|
||||
|
||||
// Get attributes with defaults
|
||||
$chart_height = $attributes['chartHeight'] ?? '400px';
|
||||
$background_color = $attributes['backgroundColor'] ?? '#ffffff';
|
||||
$bar_color = $attributes['barColor'] ?? '#0073aa';
|
||||
$bar_opacity = $attributes['barOpacity'] ?? 1;
|
||||
$show_grid_y = $attributes['showGridY'] ?? true;
|
||||
$grid_color = $attributes['gridColor'] ?? '#e0e0e0';
|
||||
|
||||
// Enqueue D3.js
|
||||
wp_enqueue_script('d3');
|
||||
|
||||
// Return the block's container
|
||||
return sprintf(
|
||||
'<div class="wp-block-lcp-bar-graph"><div class="lcp-bar-graph" style="height: %s; background-color: %s;" data-bar-color="%s" data-bar-opacity="%f" data-show-grid="%s" data-grid-color="%s"></div></div>',
|
||||
esc_attr($chart_height),
|
||||
esc_attr($background_color),
|
||||
esc_attr($bar_color),
|
||||
esc_attr($bar_opacity),
|
||||
esc_attr($show_grid_y ? 'true' : 'false'),
|
||||
esc_attr($grid_color)
|
||||
);
|
||||
}
|
||||
20608
blocks/bar-graph/package-lock.json
generated
Normal file
20608
blocks/bar-graph/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
blocks/bar-graph/package.json
Normal file
23
blocks/bar-graph/package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "lcp-bar-graph",
|
||||
"version": "0.1.0",
|
||||
"description": "Bar Graph block for LCP Data Blocks plugin",
|
||||
"author": "CoosGuide",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"main": "build/index.js",
|
||||
"scripts": {
|
||||
"build": "wp-scripts build",
|
||||
"format": "wp-scripts format",
|
||||
"lint:css": "wp-scripts lint-style",
|
||||
"lint:js": "wp-scripts lint-js",
|
||||
"packages-update": "wp-scripts packages-update",
|
||||
"plugin-zip": "wp-scripts plugin-zip",
|
||||
"start": "wp-scripts start"
|
||||
},
|
||||
"dependencies": {
|
||||
"d3": "^7.8.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@wordpress/scripts": "^30.8.1"
|
||||
}
|
||||
}
|
||||
55
blocks/bar-graph/readme.txt
Normal file
55
blocks/bar-graph/readme.txt
Normal file
@ -0,0 +1,55 @@
|
||||
=== Todo List ===
|
||||
Contributors: The WordPress Contributors
|
||||
Tags: block
|
||||
Tested up to: 6.7
|
||||
Stable tag: 0.1.0
|
||||
License: GPL-2.0-or-later
|
||||
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
Example block scaffolded with Create Block tool.
|
||||
|
||||
== Description ==
|
||||
|
||||
This is the long description. No limit, and you can use Markdown (as well as in the following sections).
|
||||
|
||||
For backwards compatibility, if this section is missing, the full length of the short description will be used, and
|
||||
Markdown parsed.
|
||||
|
||||
== Installation ==
|
||||
|
||||
This section describes how to install the plugin and get it working.
|
||||
|
||||
e.g.
|
||||
|
||||
1. Upload the plugin files to the `/wp-content/plugins/todo-list` directory, or install the plugin through the WordPress plugins screen directly.
|
||||
1. Activate the plugin through the 'Plugins' screen in WordPress
|
||||
|
||||
|
||||
== Frequently Asked Questions ==
|
||||
|
||||
= A question that someone might have =
|
||||
|
||||
An answer to that question.
|
||||
|
||||
= What about foo bar? =
|
||||
|
||||
Answer to foo bar dilemma.
|
||||
|
||||
== Screenshots ==
|
||||
|
||||
1. This screen shot description corresponds to screenshot-1.(png|jpg|jpeg|gif). Note that the screenshot is taken from
|
||||
the /assets directory or the directory that contains the stable readme.txt (tags or trunk). Screenshots in the /assets
|
||||
directory take precedence. For example, `/assets/screenshot-1.png` would win over `/tags/4.3/screenshot-1.png`
|
||||
(or jpg, jpeg, gif).
|
||||
2. This is the second screen shot
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 0.1.0 =
|
||||
* Release
|
||||
|
||||
== Arbitrary section ==
|
||||
|
||||
You may provide arbitrary sections, in the same format as the ones above. This may be of use for extremely complicated
|
||||
plugins where more information needs to be conveyed that doesn't fit into the categories of "description" or
|
||||
"installation." Arbitrary sections will be shown below the built-in sections outlined above.
|
||||
104
blocks/bar-graph/src/block.json
Normal file
104
blocks/bar-graph/src/block.json
Normal file
@ -0,0 +1,104 @@
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 2,
|
||||
"name": "lcp/bar-graph",
|
||||
"version": "0.1.0",
|
||||
"title": "LCP Bar Graph",
|
||||
"category": "widgets",
|
||||
"icon": "chart-bar",
|
||||
"description": "Display data in a bar graph format.",
|
||||
"supports": {
|
||||
"html": false
|
||||
},
|
||||
"textdomain": "lcp",
|
||||
"editorScript": "file:./index.js",
|
||||
"editorStyle": "file:./index.css",
|
||||
"style": "file:./style-index.css",
|
||||
"viewScript": "file:./view.js",
|
||||
"attributes": {
|
||||
"showBarValues": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"chartHeight": {
|
||||
"type": "string",
|
||||
"default": "400px"
|
||||
},
|
||||
"chartWidth": {
|
||||
"type": "string",
|
||||
"default": "100%"
|
||||
},
|
||||
"chartTitle": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"displayChartTitle": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"allowDownload": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"downloadMaxWidth": {
|
||||
"type": "string",
|
||||
"default": "2000px"
|
||||
},
|
||||
"showSorting": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"showFiltering": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"chartData": {
|
||||
"type": "object",
|
||||
"default": {}
|
||||
},
|
||||
"dataSource": {
|
||||
"type": "string",
|
||||
"default": "manual_json"
|
||||
},
|
||||
"barColor": {
|
||||
"type": "string",
|
||||
"default": "#0073aa"
|
||||
},
|
||||
"barOpacity": {
|
||||
"type": "number",
|
||||
"default": 1
|
||||
},
|
||||
"backgroundColor": {
|
||||
"type": "string",
|
||||
"default": "#ffffff"
|
||||
},
|
||||
"showGridX": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"showGridY": {
|
||||
"type": "boolean",
|
||||
"default": true
|
||||
},
|
||||
"gridColor": {
|
||||
"type": "string",
|
||||
"default": "#e0e0e0"
|
||||
},
|
||||
"gridWidth": {
|
||||
"type": "number",
|
||||
"default": 1
|
||||
},
|
||||
"xAxisLabel": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"yAxisLabel": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"gridOpacity": {
|
||||
"type": "number",
|
||||
"default": 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
184
blocks/bar-graph/src/components/BarGraph.js
Normal file
184
blocks/bar-graph/src/components/BarGraph.js
Normal file
@ -0,0 +1,184 @@
|
||||
import { useEffect, useRef } from '@wordpress/element';
|
||||
import * as d3 from 'd3';
|
||||
|
||||
const BarGraph = ({
|
||||
data,
|
||||
width = '100%',
|
||||
height = '400px',
|
||||
backgroundColor,
|
||||
title,
|
||||
showGridX,
|
||||
showGridY,
|
||||
gridColor,
|
||||
gridWidth,
|
||||
showBarValues,
|
||||
xAxisLabel,
|
||||
yAxisLabel
|
||||
}) => {
|
||||
const svgRef = useRef();
|
||||
const containerRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
if (!data || !svgRef.current || !containerRef.current) return;
|
||||
|
||||
// Clear previous content
|
||||
d3.select(svgRef.current).selectAll("*").remove();
|
||||
|
||||
// Convert data to simple array
|
||||
const chartData = [];
|
||||
for (const [dataset, items] of Object.entries(data)) {
|
||||
for (const item of items) {
|
||||
chartData.push({
|
||||
dataset,
|
||||
label: item.label,
|
||||
value: parseInt(item.value, 10),
|
||||
color: item.color || '#FF6384'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Get container dimensions
|
||||
const containerWidth = containerRef.current.clientWidth;
|
||||
const containerHeight = containerRef.current.clientHeight;
|
||||
|
||||
// Basic dimensions with extra margin for axis labels
|
||||
const margin = {
|
||||
top: title ? 40 : 20,
|
||||
right: 20,
|
||||
bottom: xAxisLabel ? 50 : 30,
|
||||
left: yAxisLabel ? 60 : 40
|
||||
};
|
||||
const innerWidth = containerWidth - margin.left - margin.right;
|
||||
const innerHeight = containerHeight - margin.top - margin.bottom;
|
||||
|
||||
// Create SVG
|
||||
const svg = d3.select(svgRef.current)
|
||||
.attr('width', containerWidth)
|
||||
.attr('height', containerHeight);
|
||||
|
||||
// Add title if present
|
||||
if (title) {
|
||||
svg.append('text')
|
||||
.attr('x', containerWidth / 2)
|
||||
.attr('y', 20)
|
||||
.attr('text-anchor', 'middle')
|
||||
.style('font-size', '16px')
|
||||
.text(title);
|
||||
}
|
||||
|
||||
// Create main group
|
||||
const g = svg.append('g')
|
||||
.attr('transform', `translate(${margin.left},${margin.top})`);
|
||||
|
||||
// Create scales
|
||||
const xScale = d3.scaleBand()
|
||||
.domain(chartData.map(d => d.label))
|
||||
.range([0, innerWidth])
|
||||
.padding(0.1);
|
||||
|
||||
const yScale = d3.scaleLinear()
|
||||
.domain([0, d3.max(chartData, d => d.value)])
|
||||
.range([innerHeight, 0]);
|
||||
|
||||
// Add X grid
|
||||
if (showGridX) {
|
||||
g.append('g')
|
||||
.attr('class', 'grid x-grid')
|
||||
.attr('transform', `translate(0,${innerHeight})`)
|
||||
.call(d3.axisBottom(xScale)
|
||||
.tickSize(-innerHeight)
|
||||
.tickFormat(''))
|
||||
.call(g => g.selectAll('.tick line')
|
||||
.attr('stroke', gridColor)
|
||||
.attr('stroke-width', gridWidth)
|
||||
.attr('opacity', 0.5));
|
||||
}
|
||||
|
||||
// Add Y grid
|
||||
if (showGridY) {
|
||||
g.append('g')
|
||||
.attr('class', 'grid y-grid')
|
||||
.call(d3.axisLeft(yScale)
|
||||
.tickSize(-innerWidth)
|
||||
.tickFormat(''))
|
||||
.call(g => g.selectAll('.tick line')
|
||||
.attr('stroke', gridColor)
|
||||
.attr('stroke-width', gridWidth)
|
||||
.attr('opacity', 0.5));
|
||||
}
|
||||
|
||||
// Add bars
|
||||
const bars = g.selectAll('rect')
|
||||
.data(chartData)
|
||||
.enter()
|
||||
.append('rect')
|
||||
.attr('x', d => xScale(d.label))
|
||||
.attr('y', d => yScale(d.value))
|
||||
.attr('width', xScale.bandwidth())
|
||||
.attr('height', d => innerHeight - yScale(d.value))
|
||||
.attr('fill', d => d.color);
|
||||
|
||||
// Add bar values
|
||||
if (showBarValues) {
|
||||
g.selectAll('.bar-value')
|
||||
.data(chartData)
|
||||
.enter()
|
||||
.append('text')
|
||||
.attr('class', 'bar-value')
|
||||
.attr('x', d => xScale(d.label) + xScale.bandwidth() / 2)
|
||||
.attr('y', d => yScale(d.value) - 5)
|
||||
.attr('text-anchor', 'middle')
|
||||
.text(d => d.value);
|
||||
}
|
||||
|
||||
// Add X axis
|
||||
g.append('g')
|
||||
.attr('transform', `translate(0,${innerHeight})`)
|
||||
.call(d3.axisBottom(xScale));
|
||||
|
||||
// Add Y axis
|
||||
g.append('g')
|
||||
.call(d3.axisLeft(yScale));
|
||||
|
||||
// Add X axis label
|
||||
if (xAxisLabel) {
|
||||
g.append('text')
|
||||
.attr('class', 'x-axis-label')
|
||||
.attr('x', innerWidth / 2)
|
||||
.attr('y', innerHeight + 40)
|
||||
.attr('text-anchor', 'middle')
|
||||
.style('font-size', '12px')
|
||||
.text(xAxisLabel);
|
||||
}
|
||||
|
||||
// Add Y axis label
|
||||
if (yAxisLabel) {
|
||||
g.append('text')
|
||||
.attr('class', 'y-axis-label')
|
||||
.attr('transform', 'rotate(-90)')
|
||||
.attr('x', -innerHeight / 2)
|
||||
.attr('y', -45)
|
||||
.attr('text-anchor', 'middle')
|
||||
.style('font-size', '12px')
|
||||
.text(yAxisLabel);
|
||||
}
|
||||
|
||||
}, [data, width, height, title, showGridX, showGridY, gridColor, gridWidth, showBarValues, xAxisLabel, yAxisLabel]);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="bar-graph"
|
||||
style={{
|
||||
width,
|
||||
height,
|
||||
backgroundColor,
|
||||
position: 'relative'
|
||||
}}
|
||||
>
|
||||
<svg ref={svgRef}></svg>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BarGraph;
|
||||
341
blocks/bar-graph/src/edit.js
Normal file
341
blocks/bar-graph/src/edit.js
Normal file
@ -0,0 +1,341 @@
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useBlockProps, InspectorControls } from '@wordpress/block-editor';
|
||||
import {
|
||||
PanelBody,
|
||||
Panel,
|
||||
ColorPicker,
|
||||
RangeControl,
|
||||
ToggleControl,
|
||||
TabPanel,
|
||||
TextControl,
|
||||
Button
|
||||
} from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './editor.scss';
|
||||
import LCPDataSelector from '../../../components/LCPDataSelector';
|
||||
import BarGraph from './components/BarGraph';
|
||||
import LCPDimensionControl from '../../../components/LCPDimensionControl';
|
||||
|
||||
export default function Edit({ attributes, setAttributes }) {
|
||||
const {
|
||||
chartHeight,
|
||||
chartWidth,
|
||||
barColor,
|
||||
barOpacity,
|
||||
backgroundColor,
|
||||
showGridY,
|
||||
gridColor,
|
||||
chartData,
|
||||
dataSource,
|
||||
displayChartTitle,
|
||||
chartTitle,
|
||||
allowDownload,
|
||||
downloadMaxWidth,
|
||||
showSorting,
|
||||
showFiltering,
|
||||
showBarValues,
|
||||
showGridX,
|
||||
gridWidth,
|
||||
xAxisLabel,
|
||||
yAxisLabel
|
||||
} = attributes;
|
||||
|
||||
const blockProps = useBlockProps();
|
||||
|
||||
const handleDataChange = (newData) => {
|
||||
console.log('New data:', newData); // Debug log
|
||||
setAttributes({ chartData: newData });
|
||||
};
|
||||
|
||||
const handleDataSourceChange = (newSource) => {
|
||||
setAttributes({
|
||||
dataSource: newSource,
|
||||
chartData: {} // Reset data when source changes
|
||||
});
|
||||
};
|
||||
|
||||
const handleDownload = () => {
|
||||
// Get the SVG element
|
||||
const svg = document.querySelector('.bar-graph svg');
|
||||
if (!svg) return;
|
||||
|
||||
// Create a canvas
|
||||
const canvas = document.createElement('canvas');
|
||||
const svgData = new XMLSerializer().serializeToString(svg);
|
||||
const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
|
||||
const DOMURL = window.URL || window.webkitURL || window;
|
||||
const url = DOMURL.createObjectURL(svgBlob);
|
||||
const img = new Image();
|
||||
|
||||
img.onload = () => {
|
||||
// Set canvas dimensions
|
||||
canvas.width = svg.width.baseVal.value;
|
||||
canvas.height = svg.height.baseVal.value;
|
||||
|
||||
// Draw background
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.fillStyle = backgroundColor;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Draw the image
|
||||
ctx.drawImage(img, 0, 0);
|
||||
|
||||
// Convert to blob and download
|
||||
canvas.toBlob((blob) => {
|
||||
const downloadUrl = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = downloadUrl;
|
||||
a.download = 'bar-graph.png';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(downloadUrl);
|
||||
DOMURL.revokeObjectURL(url);
|
||||
}, 'image/png');
|
||||
};
|
||||
|
||||
img.src = url;
|
||||
};
|
||||
|
||||
// Debug log to check chartData
|
||||
console.log('Chart data:', chartData);
|
||||
|
||||
return (
|
||||
<div {...blockProps}>
|
||||
<InspectorControls>
|
||||
<TabPanel
|
||||
className="lcp-tab-panel"
|
||||
activeClass="active-tab"
|
||||
tabs={[
|
||||
{
|
||||
name: 'data',
|
||||
title: __('Data Settings', 'lcp'),
|
||||
className: 'tab-data',
|
||||
},
|
||||
{
|
||||
name: 'appearance',
|
||||
title: __('Appearance', 'lcp'),
|
||||
className: 'tab-appearance',
|
||||
},
|
||||
{
|
||||
name: 'tools',
|
||||
title: __('Tools Settings', 'lcp'),
|
||||
className: 'tab-tools',
|
||||
},
|
||||
]}
|
||||
>
|
||||
{(tab) => {
|
||||
if (tab.name === 'data') {
|
||||
return (
|
||||
<Panel>
|
||||
<PanelBody title="Data Settings">
|
||||
<LCPDataSelector
|
||||
value={chartData}
|
||||
onChange={handleDataChange}
|
||||
dataSource={dataSource}
|
||||
onDataSourceChange={handleDataSourceChange}
|
||||
/>
|
||||
</PanelBody>
|
||||
<PanelBody title="Chart Settings">
|
||||
<ToggleControl
|
||||
label={__('Display Chart Title', 'lcp')}
|
||||
checked={displayChartTitle}
|
||||
onChange={(value) => setAttributes({ displayChartTitle: value })}
|
||||
/>
|
||||
{displayChartTitle && (
|
||||
<TextControl
|
||||
label={__('Chart Title', 'lcp')}
|
||||
value={chartTitle}
|
||||
onChange={(value) => setAttributes({ chartTitle: value })}
|
||||
/>
|
||||
)}
|
||||
<LCPDimensionControl
|
||||
label={__('Chart Width', 'lcp')}
|
||||
value={chartWidth}
|
||||
onChange={(value) => setAttributes({ chartWidth: value })}
|
||||
/>
|
||||
<LCPDimensionControl
|
||||
label={__('Chart Height', 'lcp')}
|
||||
value={chartHeight}
|
||||
onChange={(value) => setAttributes({ chartHeight: value })}
|
||||
/>
|
||||
</PanelBody>
|
||||
<PanelBody title="Appearance">
|
||||
<div className="components-base-control">
|
||||
<label className="components-base-control__label">
|
||||
{__('Bar Color', 'lcp')}
|
||||
</label>
|
||||
<ColorPicker
|
||||
color={barColor}
|
||||
onChangeComplete={(color) => setAttributes({ barColor: color.hex })}
|
||||
/>
|
||||
</div>
|
||||
<RangeControl
|
||||
label={__('Bar Opacity', 'lcp')}
|
||||
value={barOpacity}
|
||||
onChange={(value) => setAttributes({ barOpacity: value })}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.1}
|
||||
/>
|
||||
<div className="components-base-control">
|
||||
<label className="components-base-control__label">
|
||||
{__('Background Color', 'lcp')}
|
||||
</label>
|
||||
<ColorPicker
|
||||
color={backgroundColor}
|
||||
onChangeComplete={(color) => setAttributes({ backgroundColor: color.hex })}
|
||||
/>
|
||||
</div>
|
||||
<ToggleControl
|
||||
label={__('Show Bar Values', 'lcp')}
|
||||
checked={showBarValues}
|
||||
onChange={(value) => setAttributes({ showBarValues: value })}
|
||||
/>
|
||||
</PanelBody>
|
||||
<PanelBody title="Grid Settings">
|
||||
<TextControl
|
||||
label={__('X-Axis Label', 'lcp')}
|
||||
value={xAxisLabel}
|
||||
onChange={(value) => setAttributes({ xAxisLabel: value })}
|
||||
/>
|
||||
<TextControl
|
||||
label={__('Y-Axis Label', 'lcp')}
|
||||
value={yAxisLabel}
|
||||
onChange={(value) => setAttributes({ yAxisLabel: value })}
|
||||
/>
|
||||
<ToggleControl
|
||||
label={__('Show X-Axis Grid', 'lcp')}
|
||||
checked={showGridX}
|
||||
onChange={(value) => setAttributes({ showGridX: value })}
|
||||
/>
|
||||
<ToggleControl
|
||||
label={__('Show Y-Axis Grid', 'lcp')}
|
||||
checked={showGridY}
|
||||
onChange={(value) => setAttributes({ showGridY: value })}
|
||||
/>
|
||||
{(showGridX || showGridY) && (
|
||||
<>
|
||||
<div className="components-base-control">
|
||||
<label className="components-base-control__label">
|
||||
{__('Grid Color', 'lcp')}
|
||||
</label>
|
||||
<ColorPicker
|
||||
color={gridColor}
|
||||
onChangeComplete={(color) => setAttributes({ gridColor: color.hex })}
|
||||
/>
|
||||
</div>
|
||||
<RangeControl
|
||||
label={__('Grid Width', 'lcp')}
|
||||
value={gridWidth}
|
||||
onChange={(value) => setAttributes({ gridWidth: value })}
|
||||
min={1}
|
||||
max={5}
|
||||
step={1}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</PanelBody>
|
||||
</Panel>
|
||||
);
|
||||
}
|
||||
if (tab.name === 'appearance') {
|
||||
return (
|
||||
<PanelBody>
|
||||
|
||||
</PanelBody>
|
||||
);
|
||||
}
|
||||
if (tab.name === 'tools') {
|
||||
return (
|
||||
<PanelBody>
|
||||
<ToggleControl
|
||||
label={__('Allow Download', 'lcp')}
|
||||
checked={allowDownload}
|
||||
onChange={(value) => setAttributes({ allowDownload: value })}
|
||||
/>
|
||||
{allowDownload && (
|
||||
<TextControl
|
||||
type="number"
|
||||
label={__('Max Download Width (px)', 'lcp')}
|
||||
value={parseInt(downloadMaxWidth)}
|
||||
onChange={(value) => setAttributes({ downloadMaxWidth: `${value}px` })}
|
||||
min={100}
|
||||
max={5000}
|
||||
/>
|
||||
)}
|
||||
<ToggleControl
|
||||
label={__('Show Sorting Options', 'lcp')}
|
||||
checked={showSorting}
|
||||
onChange={(value) => setAttributes({ showSorting: value })}
|
||||
/>
|
||||
<ToggleControl
|
||||
label={__('Show Filtering Options', 'lcp')}
|
||||
checked={showFiltering}
|
||||
onChange={(value) => setAttributes({ showFiltering: value })}
|
||||
/>
|
||||
</PanelBody>
|
||||
);
|
||||
}
|
||||
}}
|
||||
</TabPanel>
|
||||
</InspectorControls>
|
||||
|
||||
{allowDownload && (
|
||||
<div className="lcp-bar-graph-toolbar">
|
||||
<Button
|
||||
isPrimary
|
||||
onClick={handleDownload}
|
||||
icon="download"
|
||||
>
|
||||
{__('Download Graph', 'lcp')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{chartData && Object.keys(chartData).length > 0 ? (
|
||||
<BarGraph
|
||||
data={chartData}
|
||||
height={chartHeight}
|
||||
width={chartWidth}
|
||||
backgroundColor={backgroundColor}
|
||||
defaultBarColor={barColor}
|
||||
barOpacity={barOpacity}
|
||||
showGridX={showGridX}
|
||||
showGridY={showGridY}
|
||||
gridColor={gridColor}
|
||||
gridWidth={gridWidth}
|
||||
title={displayChartTitle ? chartTitle : ''}
|
||||
showSorting={showSorting}
|
||||
showFiltering={showFiltering}
|
||||
showBarValues={showBarValues}
|
||||
xAxisLabel={xAxisLabel}
|
||||
yAxisLabel={yAxisLabel}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className="lcp-bar-graph-placeholder"
|
||||
style={{
|
||||
height: chartHeight,
|
||||
width: chartWidth,
|
||||
backgroundColor: backgroundColor,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
border: '2px dashed #ccc',
|
||||
borderRadius: '4px',
|
||||
color: '#666',
|
||||
}}
|
||||
>
|
||||
{__('Please add data using the Data Settings panel', 'lcp')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
68
blocks/bar-graph/src/editor.scss
Normal file
68
blocks/bar-graph/src/editor.scss
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* The following styles get applied inside the editor only.
|
||||
*
|
||||
* Replace them with your own styles or remove the file completely.
|
||||
*/
|
||||
|
||||
.wp-block-create-block-todo-list {
|
||||
border: 1px dotted #f00;
|
||||
}
|
||||
|
||||
.wp-block-lcp-bar-graph {
|
||||
margin: 1em 0;
|
||||
|
||||
.lcp-bar-graph-container {
|
||||
width: 100%;
|
||||
overflow: visible;
|
||||
|
||||
svg {
|
||||
overflow: visible;
|
||||
|
||||
.bar {
|
||||
transition: opacity 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.grid line {
|
||||
stroke-opacity: 0.1;
|
||||
}
|
||||
|
||||
.domain,
|
||||
.tick line {
|
||||
stroke: #666;
|
||||
}
|
||||
|
||||
.tick text {
|
||||
fill: #666;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.lcp-bar-graph-placeholder {
|
||||
padding: 2em;
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
// Data Selector Styles
|
||||
.lcp-data-selector {
|
||||
.components-base-control {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
.lcp-data-selector-error {
|
||||
margin-top: 0.5em;
|
||||
padding: 0.5em;
|
||||
border-left: 4px solid #cc1818;
|
||||
background-color: #f8d7da;
|
||||
}
|
||||
}
|
||||
39
blocks/bar-graph/src/index.js
Normal file
39
blocks/bar-graph/src/index.js
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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';
|
||||
|
||||
/**
|
||||
* Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
|
||||
* All files containing `style` keyword are bundled together. The code used
|
||||
* gets applied both to the front of your site and to the editor.
|
||||
*
|
||||
* @see https://www.npmjs.com/package/@wordpress/scripts#using-css
|
||||
*/
|
||||
import './style.scss';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import Edit from './edit';
|
||||
import save from './save';
|
||||
import metadata from './block.json';
|
||||
|
||||
/**
|
||||
* Every block starts by registering a new block type definition.
|
||||
*
|
||||
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
|
||||
*/
|
||||
registerBlockType( metadata.name, {
|
||||
/**
|
||||
* @see ./edit.js
|
||||
*/
|
||||
edit: Edit,
|
||||
|
||||
/**
|
||||
* @see ./save.js
|
||||
*/
|
||||
save,
|
||||
} );
|
||||
35
blocks/bar-graph/src/save.js
Normal file
35
blocks/bar-graph/src/save.js
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* React hook that is used to mark the block wrapper element.
|
||||
* It provides all the necessary props like the class name.
|
||||
*
|
||||
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
|
||||
*/
|
||||
import { useBlockProps } from '@wordpress/block-editor';
|
||||
|
||||
/**
|
||||
* The save function defines the way in which the different attributes should
|
||||
* be combined into the final markup, which is then serialized by the block
|
||||
* editor into `post_content`.
|
||||
*
|
||||
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#save
|
||||
*
|
||||
* @return {Element} Element to render.
|
||||
*/
|
||||
export default function save({ attributes }) {
|
||||
const {
|
||||
chartHeight,
|
||||
backgroundColor,
|
||||
} = attributes;
|
||||
|
||||
return (
|
||||
<div { ...useBlockProps.save() }>
|
||||
<div
|
||||
className="lcp-bar-graph"
|
||||
style={{
|
||||
height: chartHeight,
|
||||
backgroundColor: backgroundColor,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
12
blocks/bar-graph/src/style.scss
Normal file
12
blocks/bar-graph/src/style.scss
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* The following styles get applied both on the front of your site
|
||||
* and in the editor.
|
||||
*
|
||||
* Replace them with your own styles or remove the file completely.
|
||||
*/
|
||||
|
||||
.wp-block-create-block-todo-list {
|
||||
background-color: #21759b;
|
||||
color: #fff;
|
||||
padding: 2px;
|
||||
}
|
||||
25
blocks/bar-graph/src/view.js
Normal file
25
blocks/bar-graph/src/view.js
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Use this file for JavaScript code that you want to run in the front-end
|
||||
* on posts/pages that contain this block.
|
||||
*
|
||||
* When this file is defined as the value of the `viewScript` property
|
||||
* in `block.json` it will be enqueued on the front end of the site.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```js
|
||||
* {
|
||||
* "viewScript": "file:./view.js"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If you're not making any changes to this file because your project doesn't need any
|
||||
* JavaScript running in the front-end, then you should delete this file and remove
|
||||
* the `viewScript` property from `block.json`.
|
||||
*
|
||||
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/#view-script
|
||||
*/
|
||||
|
||||
/* eslint-disable no-console */
|
||||
console.log( 'Hello World! (from create-block-todo-list block)' );
|
||||
/* eslint-enable no-console */
|
||||
Reference in New Issue
Block a user