diff --git a/script.js b/assets/js/lcp.js similarity index 93% rename from script.js rename to assets/js/lcp.js index 20872e4..efc49a6 100644 --- a/script.js +++ b/assets/js/lcp.js @@ -30,7 +30,7 @@ document.addEventListener('DOMContentLoaded', function () { // Function to handle the scroll event function handleScroll() { document.documentElement.style.setProperty('--lcp--full-header--height', fullHeaderHeight + "px"); - + if (!headerIsSticky){ const scrolled = window.scrollY || document.documentElement.scrollTop; // Check if the page has scrolled past the height of the header @@ -48,11 +48,11 @@ document.addEventListener('DOMContentLoaded', function () { // sideContent.style.top = `${fullHeaderHeight}px`; } else if (headerIsSticky) { // If the header is sticky but not 'sticky-on-scroll', keep the side content height adjusted - sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)`; + // sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)`; } else { // Set side content height to 100vh when not sticky - sideContent.style.height = 'calc(100vh - 32px)'; + // sideContent.style.height = 'calc(100vh - 32px)'; // sideContent.style.top = '32px'; } @@ -62,17 +62,17 @@ document.addEventListener('DOMContentLoaded', function () { // sideContent.style.top = ''; // Reset the 'top' style // Reset height to 100vh when not fixed - sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)` ; + // sideContent.style.height = `calc(100vh - ${fullHeaderHeight}px)` ; // If header has the 'lcp-sticky-on-scroll' class, remove 'lcp-fixed' from the header if (headerIsStickyOnScroll) { header.classList.remove('lcp-fixed'); } } + } } - // Also trigger the scroll handler once on load in case the page is already scrolled handleScroll(); diff --git a/assets/json/icons/icon-definitions.json b/assets/json/icons/icon-definitions.json index 560561e..b3b4392 100644 --- a/assets/json/icons/icon-definitions.json +++ b/assets/json/icons/icon-definitions.json @@ -4,7 +4,8 @@ "setName": "Font Awesome - Regular", "setFamily": "Font Awesome", "version": "6.7.1", - "fileName": "/font-awesome/v6.7.1/font-awesome-v6.7.1-regular-svgs.json" + "fileName": "/font-awesome/v6.7.1/font-awesome-v6.7.1-regular-svgs.json", + "default": true }, { diff --git a/functions.php b/functions.php index 39ce1a6..11017f2 100644 --- a/functions.php +++ b/functions.php @@ -3,7 +3,8 @@ - +include get_template_directory() . '/includes/classes/wp-hooks.php'; +include get_template_directory() . '/includes/classes/lcp-newsletters.php'; //include get_template_directory(). '/includes/blocks/lcp-gallery/lcp-gallery.php'; include get_template_directory() . '/includes/classes/blocks.php'; @@ -18,11 +19,24 @@ function lcp_block_theme_setup() { add_theme_support( 'block-templates' ); } add_action( 'after_setup_theme', 'lcp_block_theme_setup' ); +/* Add Styles */ +function lcp_header_height_style() { + // Fetch the lcp_header_height value from wp_options. + $header_height = get_option('lcp_header_height', 0); // Default to 0 if not found + + // Ensure we have a valid value + if ($header_height) { + // Output the inline style tag with the CSS variable for header height + echo ""; + } +} +add_action('wp_enqueue_scripts', 'lcp_header_height_style',1); + function lcp_enqueue() { // Enqueue the theme's main stylesheet (style.css) wp_enqueue_style('lcp-style', get_stylesheet_uri()); - wp_enqueue_script('lcp-script', get_template_directory_uri() . '/script.js'); + wp_enqueue_script('lcp-script', get_template_directory_uri() . '/assets/js/lcp.js'); wp_enqueue_script('lcp-ui-script', get_template_directory_uri() . '/assets/js/lcp-ui.js'); } @@ -161,10 +175,6 @@ function drop_lcp_icons_table() { } -// Hook the function to the theme deactivation process - -// Register the function to run when the theme is switched (deactivated) -add_action('switch_theme', 'drop_lcp_icons_table'); @@ -241,88 +251,138 @@ add_action('admin_enqueue_scripts', 'mytheme_enqueue_dashboard_styles'); // Handle the AJAX request for installing icon sets -function mytheme_install_icon_set() { - if (!isset($_POST['icon_set_id'])) { - wp_send_json_error(array('message' => 'Invalid icon set ID.')); - } - - $icon_set_id = intval($_POST['icon_set_id']); +function lcp_install_icon_set($defaults = false) { $json_path = get_template_directory() . '/assets/json/icons/icon-definitions.json'; - // Create the database table if it doesn't exist - mytheme_create_icons_table(); + if ($defaults) { + // Import only the default icons + if (file_exists($json_path)) { + $json_data = file_get_contents($json_path); + $icon_sets = json_decode($json_data, true); - // Read the icon definitions JSON file - if (file_exists($json_path)) { - $json_data = file_get_contents($json_path); - $icon_sets = json_decode($json_data, true); + // Loop through all icon sets and filter for default icons + foreach ($icon_sets as $icon_set) { + if (isset($icon_set['default']) && $icon_set['default'] === true) { + $file_name = $icon_set['fileName']; // Assuming the JSON structure has 'fileName' key + $icon_file_path = get_template_directory() . '/assets/json/icons/' . $file_name; - // Search for the selected icon set by ID - $selected_icon_set = null; - foreach ($icon_sets as $icon_set) { - if ($icon_set['id'] === $icon_set_id) { - $selected_icon_set = $icon_set; - break; + if (file_exists($icon_file_path)) { + $icon_data = file_get_contents($icon_file_path); + $icon_json = json_decode($icon_data, true); + + // Check if svgs exist and process them + if (isset($icon_json[0]['svgs']) && is_array($icon_json[0]['svgs'])) { + foreach ($icon_json[0]['svgs'] as $svg) { + global $wpdb; + $table_name = $wpdb->prefix . 'lcp_icons'; + + // Insert the SVG data into the database + $wpdb->insert( + $table_name, + array( + 'icon_name' => $svg['name'], + 'icon_set_id' => $icon_set['id'], + 'icon_family' => $icon_set['setFamily'], + 'icon_version' => $icon_set['version'], + 'paths' => ($svg['paths']), + 'viewbox' => sanitize_text_field($svg['viewBox']), + 'icon_id' => sanitize_text_field($svg['id']), + ) + ); + } + } else { + wp_send_json_error(array('message' => 'SVGs data not found in the JSON file.')); + } + } else { + wp_send_json_error(array('message' => 'SVG file for default set not found.')); + } + } } + + } else { + wp_send_json_error(array('message' => 'Icon definitions file not found.')); + } + } elseif (isset($_POST['icon_set_id'])) { + // Default behavior - check for icon_set_id in $_POST + if (!isset($_POST['icon_set_id'])) { + wp_send_json_error(array('message' => 'Invalid icon set ID.')); } - // If the icon set is found - if ($selected_icon_set) { - // Dynamically build the icon file path using the fileName from icon-definitions.json - $file_name = $selected_icon_set['fileName']; // Assuming the JSON structure has 'fileName' key - $icon_file_path = get_template_directory() . '/assets/json/icons/' . $file_name; + $icon_set_id = intval($_POST['icon_set_id']); - // Now read the corresponding SVG file for the icon set - if (file_exists($icon_file_path)) { - $icon_data = file_get_contents($icon_file_path); - $icon_json = json_decode($icon_data, true); + // Create the database table if it doesn't exist + mytheme_create_icons_table(); - // Debugging: Check the structure of the decoded JSON - if (is_array($icon_json)) { - error_log(print_r($icon_json, true)); // Logs to PHP error log for inspection + // Read the icon definitions JSON file + if (file_exists($json_path)) { + $json_data = file_get_contents($json_path); + $icon_sets = json_decode($json_data, true); + + // Search for the selected icon set by ID + $selected_icon_set = null; + foreach ($icon_sets as $icon_set) { + if ($icon_set['id'] === $icon_set_id) { + $selected_icon_set = $icon_set; + break; } + } - // Loop through svgs if it exists and is an array - if (isset($icon_json[0]['svgs']) && is_array($icon_json[0]['svgs'])) { - // Insert rows with actual data from the SVG file - foreach ($icon_json[0]['svgs'] as $svg) { - global $wpdb; - $table_name = $wpdb->prefix . 'lcp_icons'; + // If the icon set is found + if ($selected_icon_set) { + $file_name = $selected_icon_set['fileName']; // Assuming the JSON structure has 'fileName' key + $icon_file_path = get_template_directory() . '/assets/json/icons/' . $file_name; - // Insert each SVG data into the database - $wpdb->insert( - $table_name, - array( - 'icon_name' => $svg['name'], // Using the name from the SVG JSON - 'icon_set_id' => $selected_icon_set['id'], - 'icon_family' => $selected_icon_set['setFamily'], // Get family dynamically from the selected icon set - 'icon_version' => $selected_icon_set['version'], // Get version dynamically from the selected icon set - 'paths' => ($svg['paths']), // SVG paths from the JSON - 'viewbox' => sanitize_text_field($svg['viewBox']), // Viewbox for the SVG - 'icon_id' => sanitize_text_field($svg['id']) // Using the actual icon ID from the JSON - ) - ); + // Now read the corresponding SVG file for the icon set + if (file_exists($icon_file_path)) { + $icon_data = file_get_contents($icon_file_path); + $icon_json = json_decode($icon_data, true); + + // Check the structure of the decoded JSON + if (is_array($icon_json)) { + error_log(print_r($icon_json, true)); // Logs to PHP error log for inspection } - wp_send_json_success(array('message' => 'Icon set installed and rows added with actual data.')); + // Loop through svgs if it exists and is an array + if (isset($icon_json[0]['svgs']) && is_array($icon_json[0]['svgs'])) { + foreach ($icon_json[0]['svgs'] as $svg) { + global $wpdb; + $table_name = $wpdb->prefix . 'lcp_icons'; + + // Insert each SVG data into the database + $wpdb->insert( + $table_name, + array( + 'icon_name' => $svg['name'], + 'icon_set_id' => $selected_icon_set['id'], + 'icon_family' => $selected_icon_set['setFamily'], + 'icon_version' => $selected_icon_set['version'], + 'paths' => ($svg['paths']), + 'viewbox' => sanitize_text_field($svg['viewBox']), + 'icon_id' => sanitize_text_field($svg['id']), + ) + ); + } + + wp_send_json_success(array('message' => 'Icon set installed and rows added with actual data.')); + } else { + wp_send_json_error(array('message' => 'SVGs data not found in the JSON file.')); + } } else { - wp_send_json_error(array('message' => 'SVGs data not found in the JSON file.')); + wp_send_json_error(array('message' => 'SVG file not found.')); } } else { - wp_send_json_error(array('message' => 'SVG file not found.')); + wp_send_json_error(array('message' => 'Icon set not found.')); } } else { - wp_send_json_error(array('message' => 'Icon set not found.')); + wp_send_json_error(array('message' => 'Icon definitions not found.')); } - } else { - wp_send_json_error(array('message' => 'Icon definitions not found.')); } } -add_action('wp_ajax_install_icon_set', 'mytheme_install_icon_set'); + +add_action('wp_ajax_install_icon_set', 'lcp_install_icon_set'); -// Function to create the icons table in the database if it doesn't exist // Function to create the icons table in the database if it doesn't exist function mytheme_create_icons_table() { global $wpdb; @@ -403,15 +463,3 @@ function mytheme_uninstall_icon_set() { add_action('wp_ajax_uninstall_icon_set', 'mytheme_uninstall_icon_set'); -/* Add Styles */ -function lcp_header_height_style() { - // Fetch the lcp_header_height value from wp_options. - $header_height = get_option('lcp_header_height', 0); // Default to 0 if not found - - // Ensure we have a valid value - if ($header_height) { - // Output the inline style tag with the CSS variable for header height - echo ""; - } -} -add_action('wp_head', 'lcp_header_height_style'); diff --git a/includes/blocks/lcp-sidecontent/build/index.asset.php b/includes/blocks/lcp-sidecontent/build/index.asset.php index f4f79ae..934b827 100644 --- a/includes/blocks/lcp-sidecontent/build/index.asset.php +++ b/includes/blocks/lcp-sidecontent/build/index.asset.php @@ -1 +1 @@ - array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => 'c0cad1dbf39c1f85add9'); + array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-i18n'), 'version' => '9fbf94ac3507c2365b0a'); diff --git a/includes/blocks/lcp-sidecontent/build/index.js b/includes/blocks/lcp-sidecontent/build/index.js index ba1c70d..8d7b519 100644 --- a/includes/blocks/lcp-sidecontent/build/index.js +++ b/includes/blocks/lcp-sidecontent/build/index.js @@ -1 +1 @@ -(()=>{"use strict";var e,n={650:()=>{const e=window.wp.blocks,n=(window.wp.i18n,window.wp.blockEditor),r=window.ReactJSXRuntime,o=JSON.parse('{"UU":"lcp/sidecontent"}');(0,e.registerBlockType)(o.UU,{edit:function(){return(0,n.useBlockProps)(),(0,r.jsx)("div",{...n.useBlockProps,children:(0,r.jsx)("div",{id:"lcp-sidecontent",children:(0,r.jsx)(n.InnerBlocks,{renderAppender:()=>(0,r.jsx)(n.InnerBlocks.ButtonBlockAppender,{})})})})},save:function(){const e=n.useBlockProps.save();return(0,r.jsxs)("div",{...e,id:"lcp-sidecontent",children:[(0,r.jsx)("div",{id:"lcp-sidecontent-inner",children:(0,r.jsx)(n.InnerBlocks.Content,{})}),(0,r.jsx)("div",{id:"lcp-scroll-track",children:(0,r.jsx)("div",{id:"lcp-scroll-bar"})})]})}})}},r={};function o(e){var i=r[e];if(void 0!==i)return i.exports;var s=r[e]={exports:{}};return n[e](s,s.exports,o),s.exports}o.m=n,e=[],o.O=(n,r,i,s)=>{if(!r){var t=1/0;for(p=0;p=s)&&Object.keys(o.O).every((e=>o.O[e](r[l])))?r.splice(l--,1):(c=!1,s0&&e[p-1][2]>s;p--)e[p]=e[p-1];e[p]=[r,i,s]},o.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={57:0,350:0};o.O.j=n=>0===e[n];var n=(n,r)=>{var i,s,t=r[0],c=r[1],l=r[2],d=0;if(t.some((n=>0!==e[n]))){for(i in c)o.o(c,i)&&(o.m[i]=c[i]);if(l)var p=l(o)}for(n&&n(r);do(650)));i=o.O(i)})(); \ No newline at end of file +(()=>{"use strict";var e,n={650:()=>{const e=window.wp.blocks,n=(window.wp.i18n,window.wp.blockEditor),r=window.ReactJSXRuntime,o=JSON.parse('{"UU":"lcp/sidecontent"}');(0,e.registerBlockType)(o.UU,{edit:function(){return(0,n.useBlockProps)(),(0,r.jsx)("div",{...n.useBlockProps,children:(0,r.jsx)("div",{id:"lcp-sidecontent",children:(0,r.jsx)(n.InnerBlocks,{renderAppender:()=>(0,r.jsx)(n.InnerBlocks.ButtonBlockAppender,{})})})})},save:function(){const e=n.useBlockProps.save();return(0,r.jsx)("div",{...e,id:"lcp-sidecontent",children:(0,r.jsx)(n.InnerBlocks.Content,{})})}})}},r={};function o(e){var t=r[e];if(void 0!==t)return t.exports;var s=r[e]={exports:{}};return n[e](s,s.exports,o),s.exports}o.m=n,e=[],o.O=(n,r,t,s)=>{if(!r){var i=1/0;for(d=0;d=s)&&Object.keys(o.O).every((e=>o.O[e](r[l])))?r.splice(l--,1):(c=!1,s0&&e[d-1][2]>s;d--)e[d]=e[d-1];e[d]=[r,t,s]},o.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={57:0,350:0};o.O.j=n=>0===e[n];var n=(n,r)=>{var t,s,i=r[0],c=r[1],l=r[2],p=0;if(i.some((n=>0!==e[n]))){for(t in c)o.o(c,t)&&(o.m[t]=c[t]);if(l)var d=l(o)}for(n&&n(r);po(650)));t=o.O(t)})(); \ No newline at end of file diff --git a/includes/blocks/lcp-sidecontent/src/save.js b/includes/blocks/lcp-sidecontent/src/save.js index d377f59..a3a1078 100644 --- a/includes/blocks/lcp-sidecontent/src/save.js +++ b/includes/blocks/lcp-sidecontent/src/save.js @@ -21,15 +21,11 @@ export default function Save() { return (
-
+ -
-
-
- -
-
+ +
diff --git a/includes/blocks/lcp-viewport/build/block.json b/includes/blocks/lcp-viewport/build/block.json index aeda567..88e597b 100644 --- a/includes/blocks/lcp-viewport/build/block.json +++ b/includes/blocks/lcp-viewport/build/block.json @@ -23,6 +23,10 @@ "hasStickyHeader": { "type": "boolean", "default": false + }, + "headerContainerStickyType": { + "type": "string", + "default": "" } }, "textdomain": "lcp-viewport", diff --git a/includes/blocks/lcp-viewport/build/index.asset.php b/includes/blocks/lcp-viewport/build/index.asset.php index 531a1e9..2f92f05 100644 --- a/includes/blocks/lcp-viewport/build/index.asset.php +++ b/includes/blocks/lcp-viewport/build/index.asset.php @@ -1 +1 @@ - array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => 'a54c989d69efb5b39b31'); + array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'b8ff5a7ac1d726017948'); diff --git a/includes/blocks/lcp-viewport/build/index.js b/includes/blocks/lcp-viewport/build/index.js index 8fab74f..78bde25 100644 --- a/includes/blocks/lcp-viewport/build/index.js +++ b/includes/blocks/lcp-viewport/build/index.js @@ -1 +1 @@ -(()=>{"use strict";var e,t={199:()=>{const e=window.wp.blocks,t=window.wp.i18n,o=window.wp.blockEditor,c=window.wp.components,n=window.wp.element,r=window.wp.data,i=window.ReactJSXRuntime,s=JSON.parse('{"UU":"lcp/viewport"}');(0,e.registerBlockType)(s.UU,{edit:function({attributes:s,setAttributes:l,clientId:a}){const{hasSidecontent:d,hasStickyHeader:p}=s,[u,w]=(0,n.useState)(!1),[k,h]=(0,n.useState)(!1),[v,f]=(0,n.useState)(!1),[b,B]=(0,n.useState)(null),x=(0,o.useBlockProps)({className:d?"has-sidecontent":""}),j=[d?["lcp/sidecontent"]:null,["lcp/header-container"],["lcp/main-area"],["lcp/footer-container"]].filter(Boolean);(0,n.useEffect)((()=>{if(d){const t=(0,e.createBlock)("lcp/sidecontent",{});wp.data.dispatch("core/block-editor").insertBlocks(t,1,a)}}),[d,a]),(0,n.useEffect)((()=>{const e=(0,r.subscribe)((()=>{const e=wp.data.select("core/block-editor").getBlocks();if(k||v)return;const t=e.find((e=>e.clientId!==a&&!wp.data.select("core/block-editor").getBlockParents(e.clientId).includes(a)));t&&(B(t),w(!0),f(!0))}));return()=>{e()}}),[a,k,v]);const m=()=>{if(b){const e=wp.data.select("core/block-editor").getBlocks(a).find((e=>"lcp/main-area"===e.name));e&&(console.log(e),wp.data.dispatch("core/block-editor").insertBlocks(b,e.clientId,0))}w(!1)};return(0,n.useEffect)((()=>{v&&h(!1)}),[v]),(0,r.useSelect)((e=>e("core/block-editor").getBlocks(x.clientId)),[x.clientId]),(0,i.jsxs)("div",{...x,children:[(0,i.jsx)(o.InspectorControls,{children:(0,i.jsx)(c.ToggleControl,{label:(0,t.__)("Include Side Content","lcp-viewport"),checked:d,onChange:e=>l({hasSidecontent:e})})}),(0,i.jsx)("div",{id:"lcp-viewport-outer",children:(0,i.jsx)("div",{id:"lcp-viewport-inner",children:(0,i.jsx)(o.InnerBlocks,{renderAppender:()=>(0,i.jsx)(o.InnerBlocks.ButtonBlockAppender,{}),template:j})})}),u&&!k&&(0,i.jsxs)(c.Modal,{title:(0,t.__)("Block Outside Viewport","lcp-viewport"),onRequestClose:m,className:"block-outside-popup",children:[(0,i.jsx)("p",{children:(0,t.__)("You added a block outside of the lcp/viewport container. Please make sure the block is inside the appropriate area.","lcp-viewport")}),(0,i.jsx)(c.Button,{isPrimary:!0,onClick:m,children:(0,t.__)("Close","lcp-viewport")}),(0,i.jsx)(c.Button,{isSecondary:!0,onClick:()=>{h(!0),w(!1)},children:(0,t.__)("Ignore","lcp-viewport")})]})]})},save:function({attributes:e}){const{hasSidecontent:t,hasStickyHeader:c}=e;o.useBlockProps.save();let n="";return t&&(n+="lcp-has-sidecontent "),c&&(n+="lcp-has-sticky-header"),(0,i.jsx)("div",{className:n,id:"lcp-viewport-outer",children:(0,i.jsx)("div",{id:"lcp-viewport-inner",className:n,children:(0,i.jsx)(o.InnerBlocks.Content,{})})})}})}},o={};function c(e){var n=o[e];if(void 0!==n)return n.exports;var r=o[e]={exports:{}};return t[e](r,r.exports,c),r.exports}c.m=t,e=[],c.O=(t,o,n,r)=>{if(!o){var i=1/0;for(d=0;d=r)&&Object.keys(c.O).every((e=>c.O[e](o[l])))?o.splice(l--,1):(s=!1,r0&&e[d-1][2]>r;d--)e[d]=e[d-1];e[d]=[o,n,r]},c.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={57:0,350:0};c.O.j=t=>0===e[t];var t=(t,o)=>{var n,r,i=o[0],s=o[1],l=o[2],a=0;if(i.some((t=>0!==e[t]))){for(n in s)c.o(s,n)&&(c.m[n]=s[n]);if(l)var d=l(c)}for(t&&t(o);ac(199)));n=c.O(n)})(); \ No newline at end of file +(()=>{"use strict";var e,t={798:()=>{const e=window.wp.blocks,t=window.wp.i18n,o=window.wp.blockEditor,n=(window.wp.hooks,window.wp.components),c=window.wp.element,r=window.wp.data,i=window.ReactJSXRuntime,s=JSON.parse('{"UU":"lcp/viewport"}');(0,e.registerBlockType)(s.UU,{edit:function({attributes:s,setAttributes:l,clientId:a}){const{hasSidecontent:d,headerContainerStickyType:p}=s,[u,w]=(0,c.useState)(!1),[h,k]=(0,c.useState)(!1),[v,f]=(0,c.useState)(!1),[b,B]=(0,c.useState)(null),m=(0,o.useBlockProps)({className:d?"has-sidecontent":""}),x=[d?["lcp/sidecontent"]:null,["lcp/header-container"],["lcp/main-area"],["lcp/footer-container"]].filter(Boolean);(0,c.useEffect)((()=>{if(d){const t=(0,e.createBlock)("lcp/sidecontent",{});wp.data.dispatch("core/block-editor").insertBlocks(t,1,a)}}),[d,a]),(0,c.useEffect)((()=>{const e=(0,r.subscribe)((()=>{const e=wp.data.select("core/block-editor").getBlocks();if(h||v)return;const t=e.find((e=>e.clientId!==a&&!wp.data.select("core/block-editor").getBlockParents(e.clientId).includes(a)));t&&(B(t),w(!0),f(!0))}));return()=>{e()}}),[a,h,v]);const y=()=>{if(b){const e=wp.data.select("core/block-editor").getBlocks(a).find((e=>"lcp/main-area"===e.name));e&&(console.log(e),wp.data.dispatch("core/block-editor").insertBlocks(b,e.clientId,0))}w(!1)};(0,c.useEffect)((()=>{v&&k(!1)}),[v]);const j=(0,r.useSelect)((e=>e("core/block-editor").getBlocks(a)),[a]);return(0,c.useEffect)((()=>{const e=j.find((e=>"lcp/header-container"===e.name));j.find((e=>"lcp/header-sidecontent"===e.name)),e&&e.attributes&&void 0!==e.attributes.sticky&&l({headerContainerStickyType:e.attributes.sticky})}),[j,a,l]),(0,i.jsxs)("div",{...m,children:[(0,i.jsx)(o.InspectorControls,{children:(0,i.jsx)(n.ToggleControl,{label:(0,t.__)("Include Side Content","lcp-viewport"),checked:d,onChange:e=>l({hasSidecontent:e})})}),(0,i.jsx)("div",{id:"lcp-viewport-outer",children:(0,i.jsx)("div",{id:"lcp-viewport-inner",children:(0,i.jsx)(o.InnerBlocks,{renderAppender:()=>(0,i.jsx)(o.InnerBlocks.ButtonBlockAppender,{}),template:x})})}),u&&!h&&(0,i.jsxs)(n.Modal,{title:(0,t.__)("Block Outside Viewport","lcp-viewport"),onRequestClose:y,className:"block-outside-popup",children:[(0,i.jsx)("p",{children:(0,t.__)("You added a block outside of the lcp/viewport container. Please make sure the block is inside the appropriate area.","lcp-viewport")}),(0,i.jsx)(n.Button,{isPrimary:!0,onClick:y,children:(0,t.__)("Close","lcp-viewport")}),(0,i.jsx)(n.Button,{isSecondary:!0,onClick:()=>{k(!0),w(!1)},children:(0,t.__)("Ignore","lcp-viewport")})]})]})},save:function({attributes:e}){const{hasSidecontent:t,headerContainerStickyType:n}=e;o.useBlockProps.save();let c="";return t&&(c+="lcp-has-sidecontent "),"always"===n?c+="lcp-has-sticky-header ":"onScroll"===n&&(c+="lcp-has-sticky-on-scroll-header "),(0,i.jsx)("div",{className:c,id:"lcp-viewport-outer",children:(0,i.jsx)("div",{id:"lcp-viewport-inner",className:c,children:(0,i.jsx)(o.InnerBlocks.Content,{})})})}})}},o={};function n(e){var c=o[e];if(void 0!==c)return c.exports;var r=o[e]={exports:{}};return t[e](r,r.exports,n),r.exports}n.m=t,e=[],n.O=(t,o,c,r)=>{if(!o){var i=1/0;for(d=0;d=r)&&Object.keys(n.O).every((e=>n.O[e](o[l])))?o.splice(l--,1):(s=!1,r0&&e[d-1][2]>r;d--)e[d]=e[d-1];e[d]=[o,c,r]},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={57:0,350:0};n.O.j=t=>0===e[t];var t=(t,o)=>{var c,r,i=o[0],s=o[1],l=o[2],a=0;if(i.some((t=>0!==e[t]))){for(c in s)n.o(s,c)&&(n.m[c]=s[c]);if(l)var d=l(n)}for(t&&t(o);an(798)));c=n.O(c)})(); \ No newline at end of file diff --git a/includes/blocks/lcp-viewport/lcp-viewport.php b/includes/blocks/lcp-viewport/lcp-viewport.php index 111424a..61e15df 100644 --- a/includes/blocks/lcp-viewport/lcp-viewport.php +++ b/includes/blocks/lcp-viewport/lcp-viewport.php @@ -28,3 +28,4 @@ function create_block_lcp_viewport_block_init() { register_block_type( __DIR__ . '/build' ); } add_action( 'init', 'create_block_lcp_viewport_block_init' ); + diff --git a/includes/blocks/lcp-viewport/src/block.json b/includes/blocks/lcp-viewport/src/block.json index bac1b06..80c19c2 100644 --- a/includes/blocks/lcp-viewport/src/block.json +++ b/includes/blocks/lcp-viewport/src/block.json @@ -23,6 +23,10 @@ "hasStickyHeader":{ "type":"boolean", "default":false + }, + "headerContainerStickyType":{ + "type": "string", + "default": "" } }, "textdomain": "lcp-viewport", diff --git a/includes/blocks/lcp-viewport/src/edit.js b/includes/blocks/lcp-viewport/src/edit.js index 6f6048a..c8a5db2 100644 --- a/includes/blocks/lcp-viewport/src/edit.js +++ b/includes/blocks/lcp-viewport/src/edit.js @@ -1,5 +1,6 @@ import { __ } from '@wordpress/i18n'; -import { useBlockProps, InnerBlocks, InspectorControls } from '@wordpress/block-editor'; +import { useBlockProps, InnerBlocks, InspectorControls, BlockEditor } from '@wordpress/block-editor'; +import {addFilter} from '@wordpress/hooks'; import { ToggleControl } from '@wordpress/components'; import { useEffect, useState } from '@wordpress/element'; import { createBlock } from '@wordpress/blocks'; // Used for creating new blocks @@ -8,7 +9,7 @@ import { Modal, Button } from '@wordpress/components'; // Import Modal for popup import './editor.scss'; export default function Edit({ attributes, setAttributes, clientId }) { - const { hasSidecontent, hasStickyHeader } = attributes; + const { hasSidecontent, headerContainerStickyType } = attributes; // Popup visibility state const [isPopupVisible, setIsPopupVisible] = useState(false); @@ -113,8 +114,25 @@ export default function Edit({ attributes, setAttributes, clientId }) { // Use useSelect to subscribe to the state of inner blocks const innerBlocks = useSelect((select) => { - return select('core/block-editor').getBlocks(blockProps.clientId); - }, [blockProps.clientId]); + return select('core/block-editor').getBlocks(clientId); + }, [clientId]); + + // useEffect to log "Header present" when the lcp/header-container block is found + useEffect(() => { + const headerBlock = innerBlocks.find((block) => block.name === 'lcp/header-container'); + const sidecontentBlock = innerBlocks.find((block) => block.name === 'lcp/header-sidecontent'); + // Check if the block is found and the 'sticky' attribute has changed + if (headerBlock && headerBlock.attributes && headerBlock.attributes.sticky !== undefined) { + // Update the state with the new sticky value + setAttributes({ headerContainerStickyType: headerBlock.attributes.sticky }); + } + // Check if there is already a sidecontent block and remove it if so + if (sidecontentBlock) { + + } + }, [innerBlocks, clientId, setAttributes]); // Trigger the effect whenever the blocks change + + return (
diff --git a/includes/blocks/lcp-viewport/src/save.js b/includes/blocks/lcp-viewport/src/save.js index 04f04ca..4f20224 100644 --- a/includes/blocks/lcp-viewport/src/save.js +++ b/includes/blocks/lcp-viewport/src/save.js @@ -10,16 +10,22 @@ import { useBlockProps, InnerBlocks } from '@wordpress/block-editor'; * @return {Element} Element to render. */ export default function Save({ attributes }) { - const { hasSidecontent, hasStickyHeader } = attributes; // Retrieve the hasSidecontent and hasStickyHeader attributes + const { hasSidecontent, headerContainerStickyType } = attributes; // Retrieve the attributes const blockProps = useBlockProps.save(); - // Conditionally add the 'has-sidecontent' and 'lcp-has-sticky-header' classes + // Conditionally add classes based on attributes let classNames = ''; + + // Add 'has-sidecontent' class if attribute is true if (hasSidecontent) { classNames += 'lcp-has-sidecontent '; } - if (hasStickyHeader) { - classNames += 'lcp-has-sticky-header'; + + // Conditionally add sticky header classes based on the headerContainerStickyStyle value + if (headerContainerStickyType === 'always') { + classNames += 'lcp-has-sticky-header '; + } else if (headerContainerStickyType === 'onScroll') { + classNames += 'lcp-has-sticky-on-scroll-header '; } return ( diff --git a/includes/classes/backend.php b/includes/classes/backend.php index 69a4b0e..31409ff 100644 --- a/includes/classes/backend.php +++ b/includes/classes/backend.php @@ -234,7 +234,7 @@ add_action( 'wp_footer', function() { - +// Register the settings page with tabs function render_lcp_theme_settings_page() { ?>
@@ -244,26 +244,35 @@ function render_lcp_theme_settings_page() {
    - + +
-
+ +

Custom SVG Icons

- +
+ +
+ +
+

Custom Code Settings

@@ -299,8 +308,9 @@ function render_lcp_theme_settings_page() { -// Hooks +/* HIGHLIGHT-TO-SHARE */ + // Render the highlight-to-share popup function highlight_to_share_popup() { echo "
@@ -311,6 +321,8 @@ function highlight_to_share_popup() { "; } +/* HOOKS */ + //Move to custom hooks class or file in future function lcp_wp_head_hooks(){ // Define lcp_theme_settings array from wp_options $options = get_option('lcp_theme_settings', array()); diff --git a/includes/classes/lcp-newsletters.php b/includes/classes/lcp-newsletters.php new file mode 100644 index 0000000..fb3bba4 --- /dev/null +++ b/includes/classes/lcp-newsletters.php @@ -0,0 +1,152 @@ +prefix . 'lcp_newsletter_subscribers'; + $table_name_campaign_lists = $wpdb->prefix . 'lcp_newsletter_lists'; + $table_name_communications = $wpdb->prefix . 'lcp_communications'; + + $charset_collate = $wpdb->get_charset_collate(); + + // SQL to create the subscribers table + $sql_contacts = " + CREATE TABLE $table_name_contacts ( + id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY, + email VARCHAR(255) NOT NULL, + user_id BIGINT(20) UNSIGNED UNIQUE, + first_name VARCHAR(255), + last_name VARCHAR(255), + subscription_date DATETIME DEFAULT CURRENT_TIMESTAMP, + UNIQUE KEY email_unique (email) + ) $charset_collate; + "; + + // SQL to create the subscriptions table (if needed, for storing subscription data) + $sql_subscriptions = " + CREATE TABLE $table_name_campaign_lists ( + id BIGINT(20) UNSIGNED AUTO_INCREMENT PRIMARY KEY, + subscriber_id BIGINT(20) UNSIGNED NOT NULL, + newsletter_name VARCHAR(255) NOT NULL, + subscription_date DATETIME DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (subscriber_id) REFERENCES $table_name_subscribers(id) ON DELETE CASCADE + ) $charset_collate; + "; + + $sql_communications = " + CREATE TABLE $table_name ( + id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + contact_id BIGINT(20) UNSIGNED NOT NULL, + status ENUM('scheduled', 'sent', 'failed') NOT NULL DEFAULT 'scheduled', + send_datetime DATETIME DEFAULT NULL, + attempts INT(10) UNSIGNED NOT NULL DEFAULT 0, + error_message TEXT DEFAULT NULL, + PRIMARY KEY (id), + KEY newsletter_id (newsletter_id) + + ) $charset_collate; + "; + + // Run the SQL queries to create the tables + require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); + dbDelta($sql_contacts); + dbDelta($sql_communications); + ; +} +add_action('after_switch_theme', 'lcp_create_newsletter_tables'); // or use 'register_activation_hook()' for a plugin + + +// Register Custom Post Type for 'lcp_newsletters' +function lcp_register_newsletters_cpt() { + $args = array( + 'label' => 'Newsletters', + 'description' => 'Custom post type for newsletters', + 'public' => true, + 'show_ui' => true, + 'show_in_menu' => true, + 'show_in_rest' => true, // Enable for REST API + 'supports' => array('title', 'editor', 'custom-fields'), // Supports custom fields + 'has_archive' => true, + 'rewrite' => array('slug' => 'newsletters'), + 'show_in_graphql' => true, + 'hierarchical' => false, // Set false as newsletters are usually single-level posts + ); + + register_post_type('lcp_newsletters', $args); +} +add_action('init', 'lcp_register_newsletters_cpt'); + +// Register Custom Taxonomy for 'newsletter_campaigns' +function lcp_register_newsletter_campaigns_taxonomy() { + $args = array( + 'hierarchical' => true, + 'label' => 'Newsletter Campaigns', + 'show_ui' => true, + 'show_in_rest' => true, + 'show_admin_column' => true, + 'rewrite' => array('slug' => 'newsletter-campaigns'), + ); + + register_taxonomy('newsletter_campaigns', array('lcp_newsletters'), $args); +} +add_action('init', 'lcp_register_newsletter_campaigns_taxonomy'); + +// Add the 'send_datetime' meta field for the 'lcp_newsletters' CPT +function lcp_add_send_datetime_meta_box() { + add_meta_box( + 'send_datetime_meta_box', // Meta box ID + 'Send Date and Time', // Title + 'lcp_render_send_datetime_meta_box', // Callback function to render content + 'lcp_newsletters', // Post type to attach the meta box to + 'side', // Context (side bar) + 'high' // Priority + ); +} +add_action('add_meta_boxes', 'lcp_add_send_datetime_meta_box'); + +// Render the 'send_datetime' field +function lcp_render_send_datetime_meta_box($post) { + wp_nonce_field(basename(__FILE__), 'send_datetime_nonce'); // Add nonce for security + $send_datetime = get_post_meta($post->ID, '_send_datetime', true); // Get current value from post meta + echo ''; +} + +// Save the 'send_datetime' field +function lcp_save_send_datetime_meta_box($post_id) { + if (!isset($_POST['send_datetime_nonce']) || !wp_verify_nonce($_POST['send_datetime_nonce'], basename(__FILE__))) { + return $post_id; // Nonce check failed, do not save + } + + $send_datetime = isset($_POST['send_datetime']) ? sanitize_text_field($_POST['send_datetime']) : ''; + + if (!empty($send_datetime)) { + update_post_meta($post_id, '_send_datetime', $send_datetime); // Save send_datetime as post meta + } else { + delete_post_meta($post_id, '_send_datetime'); // Delete meta if empty + } +} +add_action('save_post', 'lcp_save_send_datetime_meta_box'); + +function lcp_restrict_blocks_for_newsletters($allowed_blocks, $post) { + // Check if the post type is 'lcp_newsletters' + if ($post->post_type === 'lcp_newsletters') { + // Define the allowed blocks for 'lcp_newsletters' + $allowed_blocks = array( + 'core/paragraph', + 'core/heading', + 'core/list', + 'core/image', + 'core/quote', + 'core/button', + // Add any other blocks you want to allow + ); + } + + return $allowed_blocks; +} + +add_filter('allowed_block_types', 'lcp_restrict_blocks_for_newsletters', 10, 2); + + diff --git a/includes/classes/wp-hooks.php b/includes/classes/wp-hooks.php new file mode 100644 index 0000000..7795ac8 --- /dev/null +++ b/includes/classes/wp-hooks.php @@ -0,0 +1,15 @@ + + diff --git a/style.css b/style.css index 38f53f5..2461977 100644 --- a/style.css +++ b/style.css @@ -34,30 +34,43 @@ Version: 1.0 min-height:calc(100vh - 32px) } + + + /* Main Content */ .lcp-has-sidecontent #lcp-main-container > * > *{ padding:20px } + +#lcp-main-container { + margin-top: var(--lcp--header--height) +} /* Side content */ #lcp-sidecontent { + overflow:auto; position: absolute; left: 0; top: 0; width: 340px; height: 100%; - overflow: hidden; background: #fff; border-right: 2px solid #eee; z-index: 2; outline: 0; } -#lcp-sidecontent-inner { - height: 100%; - overflow: auto; /* Enable scrolling for inner content */ - padding:0 10px +#lcp-viewport-outer.lcp-has-sticky-header #lcp-sidecontent { + top: var(--lcp--header--height); + position:fixed!important; + height: calc(100vh - var(--lcp--header--height)) } +.admin-bar #lcp-viewport-outer.lcp-has-sticky-header #lcp-sidecontent { + top: calc(var(--lcp--header--height) + 32px); + height: calc(100vh - var(--lcp--header--height) - 32px) +} + + #lcp-sidecontent-inner > * { margin-top: 10px;} @@ -69,6 +82,17 @@ Version: 1.0 @media only screen and (max-width: 1199px) { #lcp-sidecontent:not(.lcp-open) {display:none} + #lcp-sidecontent.lcp-open { + display: block; + position: fixed; + overflow:auto; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 999; + } } /* Main content an Footer */ @@ -89,7 +113,10 @@ Version: 1.0 width: 100% } #lcp-sidecontent {top:var(--lcp---header--height)} -.admin-bar #lcp-sidecontent { +#lcp-sidecontent { + top: calc(var(--lcp--header--height) ); +} +.admin-bar #lcp-sidecontent.lcp-fixed { top: calc(var(--lcp--header--height) + 32px); } @@ -103,7 +130,7 @@ Version: 1.0 #lcp-header-container.lcp-sticky-on-scroll.lcp-fixed { position: fixed; - top:0; + top:32px; left: 0; right: 0; z-index: 3; @@ -142,40 +169,6 @@ Version: 1.0 - - - - - - - - - - - - - - - - - - -#lcp-scroll-track { - position: absolute; - top: 0; - right: 0; - width: 5px; - height: 100%; - background-color: #e0e0e0; -} - -#lcp-scroll-bar { - width: 100%; - background-color: #333; - cursor: pointer; - border-radius: 5px; -} - /* Highlight-to-share popup */ .popup { position: absolute; diff --git a/theme.json b/theme.json index 2f2acd5..a025fba 100644 --- a/theme.json +++ b/theme.json @@ -1,6 +1,9 @@ { "$schema": "https://schemas.wp.org/trunk/theme.json", "version": 3, + "patterns": [ + + ], "settings": { "appearanceTools": true, "color": { diff --git a/zip-theme.js b/zip-theme.js index b37fd9f..edfb5b1 100644 --- a/zip-theme.js +++ b/zip-theme.js @@ -13,7 +13,8 @@ const excludedDirs = [ 'package.json', 'package-lock.json', 'theme.zip', - '.git' + '.git', + 'react' ]; // Helper function to check if a file or directory should be excluded