- Rebuilt the entire project - now we can pass blockName in URL.

- Added "ViewMode"
This commit is contained in:
2024-01-14 00:36:14 +02:00
parent b76f83d4fa
commit f48b2a3274
26 changed files with 618 additions and 699 deletions
+3 -2
View File
@@ -7,12 +7,13 @@
<title>Block Development Tool</title>
</head>
<body>
<body class="{{#if viewMode }}view-mode{{/if}}">
{{> (include_partial "layouts/partials/toolbar") }}
<script>
window.devTool = {
blockName: '{{ blockName }}',
previewFrameUrl: '{{ previewFrameUrl }}',
{{#if publicUrl}}
publicUrl: true,
@@ -21,7 +22,7 @@
</script>
<div class="preview">
<iframe id="preview_frame" src="{{ previewFrameUrl }}?iframe=true" class="breakpoint"></iframe>
<iframe id="preview_frame" src="{{ previewFrameUrl }}?iframe=true&block={{blockName}}" class="breakpoint"></iframe>
</div>
<script src="/scripts/dist/index.min.js"></script>
+1 -1
View File
@@ -10,5 +10,5 @@
<link rel="stylesheet" href="{{ this }}">
{{/each}}
{{/if}}<link rel="stylesheet" href="/styles/page--view.css">{{# if config.blockName}}
<link rel="stylesheet" href="/styles/{{ config.blockName }}.min.css">{{/if}}
<link rel="stylesheet" id="block-stylesheet" href="{{staticFilesPath}}/styles/{{ config.blockName }}.min.css?v=1">{{/if}}
</head>
+1 -1
View File
@@ -10,5 +10,5 @@
{{/each}}
{{/if}}
{{#if config.blockName }}
<script src="/scripts/{{ config.blockName }}.min.js"></script>
<script id="block-script" src="{{staticFilesPath}}/scripts/{{ config.blockName }}.min.js?v=1"></script>
{{/if}}
+1 -1
View File
@@ -15,6 +15,6 @@
{{#if styleGuideUrl}}
<a href="{{ styleGuideUrl }}" target="_blank" class="palette" title="Open Style Guide"></a>
{{/if}}
<a href="{{ previewFrameUrl }}" target="_blank" class="open_in_new_tab" title="Open in New Window"></a>
<a href="{{ previewFrameUrl }}?block={{blockName}}" target="_blank" class="open_in_new_tab" title="Open in New Window"></a>
</div>
</header>
+1 -1
View File
@@ -1 +1 @@
let e;window.initBlock=function(e="",n="",r){t=function(){document.querySelectorAll(n).forEach((e=>r(e)))},t()};let t,n={};function r(r={}){r.template&&(e=r.template),r.data&&(n=r.data),e&&function(e,n,r){const a=Handlebars.compile(e);let o;Handlebars.registerHelper("esc_attr",(function(e){return e})),Handlebars.registerHelper("esc_url",(function(e){return e})),Handlebars.registerHelper("esc_html",(function(e){return e})),Handlebars.registerHelper("base_url",(function(){return"/"}));try{o=a(n)}catch(e){o=`<div style="max-width: 1280px; margin: 1rem auto;">\n <h1 style="all: unset; font-size: 1.5rem; font-weight: bold; display: block;">Syntax Error:</h1>\n <pre style="all: unset; padding: 10px 15px; background-color: #ffe6e6; border: 1px solid red; border-radius: 0.25rem; overflow: auto; display: block; white-space: pre;">${e.toString()}</pre>\n </div>`}r.innerHTML=o,t&&t()}(e,n||{},document.getElementById("hbs-container"))}!function(){function e(){const e=new URLSearchParams(window.location.search),t={};for(const[n,r]of e)t[n]=r;return t}!function(){const t=new URLSearchParams({name:e().data||"default"});fetch(`/data?${t}`).then((e=>e.json())).then((e=>{n=e.data,r({data:n})}))}(),window.addEventListener("message",(function(e){const t=e.data,a="dataUpdate:";if("string"==typeof t&&t.startsWith(a))try{n=JSON.parse(t.substring(a.length)),r({data:n})}catch(e){console.log("Error parsing incoming data.",e)}}))}(),function(){const e=window.io.connect();e.on("error",(function(e){console.log(e)})),e.on("templateUpdate",(function(e){r({template:e.template})}))}();
let e;window.initBlock=function(e="",n="",o){t=function(){document.querySelectorAll(n).forEach((e=>o(e)))},t()};let t,n={};!function(){const o=r().block;function r(){const e=new URLSearchParams(window.location.search),t={};for(const[n,o]of e)t[n]=o;return t}function a(e){const t=document.getElementById(e),n=t.parentNode;let o,r;return"SCRIPT"===t.tagName?(o=document.createElement("script"),o.type="text/javascript",r="src"):"LINK"===t.tagName&&(o=document.createElement("link"),o.rel="stylesheet",r="href"),o.id=e,o[r]=t[r].replace(/(\?v=)[^&]+/,`$1${Date.now()}`),t.remove(),n.append(o),o}function c(r={}){r.template&&(e=r.template),r.data&&(n=r.data),e&&function(e,n,r){const a=Handlebars.compile(e);let c;Handlebars.registerHelper("esc_attr",(function(e){return e})),Handlebars.registerHelper("esc_url",(function(e){return e})),Handlebars.registerHelper("esc_html",(function(e){return e})),Handlebars.registerHelper("base_url",(function(){const e=["block"];return o&&e.push(o.substr(1)),["",...e,""].join("/")}));try{c=a(n)}catch(e){c=`<div style="max-width: 1280px; margin: 1rem auto;">\n <h1 style="all: unset; font-size: 1.5rem; font-weight: bold; display: block;">Syntax Error:</h1>\n <pre style="all: unset; padding: 10px 15px; background-color: #ffe6e6; border: 1px solid red; border-radius: 0.25rem; overflow: auto; display: block; white-space: pre;">${e.toString()}</pre>\n </div>`}r.innerHTML=c,t&&t()}(e,n||{},document.getElementById("hbs-container"))}!function(){const e=new URLSearchParams({block:o,name:r().data||"default"});fetch(`/data?${e}`).then((e=>e.json())).then((e=>{n=e.data,c({data:n})}))}(),window.addEventListener("message",(function(e){const t=e.data,o="dataUpdate:";if("string"==typeof t&&t.startsWith(o))try{n=JSON.parse(t.substring(o.length)),c({data:n})}catch(e){console.log("Error parsing incoming data.",e)}})),function(){const e=window.io.connect("",{query:`block=${o}`});e.on("error",(function(e){console.log(e)})),e.on("templateUpdate",(function(e){c({template:e.template})})),e.on("scriptUpdate",(function(e){a("block-script").onload=()=>{c({template:e.template})}})),e.on("styleUpdate",(function(e){a("block-stylesheet")}))}()}();
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+90 -43
View File
@@ -17,6 +17,8 @@ function initBlock(blockName = '', selector = '', cb) {
// Data Updates Listeners.
(function () {
const block = getQueryParams().block;
loadDataOptions();
listenToDataOptionsUpdates();
@@ -50,7 +52,10 @@ function initBlock(blockName = '', selector = '', cb) {
}
function loadDataOptions() {
const queryParameters = new URLSearchParams({name: getQueryParams().data || 'default'});
const queryParameters = new URLSearchParams({
block,
name: getQueryParams().data || 'default'
});
fetch(`/data?${queryParameters}`)
.then((response) => response.json())
.then((response) => {
@@ -58,14 +63,12 @@ function initBlock(blockName = '', selector = '', cb) {
updateBlock({data});
})
}
})();
// Listen to Template updates.
(function () {
// Listen to Template updates.
initSocket();
function initSocket() {
const socket = window.io.connect();
const socket = window.io.connect('', {query: `block=${block}`});
socket.on('error', function (err) {
console.log(err);
@@ -78,60 +81,104 @@ function initBlock(blockName = '', selector = '', cb) {
socket.on('templateUpdate', function (args) {
updateBlock({template: args.template});
});
}
})();
function updateBlock(args = {}) {
if (args.template) {
template = args.template; // Update state.
socket.on('scriptUpdate', function (args) {
const tag = updateTag('block-script');
tag.onload = () => {
updateBlock({template: args.template});
}
});
socket.on('styleUpdate', function (args) {
updateTag('block-stylesheet');
});
}
if (args.data) {
data = args.data; // Update state.
function updateTag(id) {
const tag = document.getElementById(id);
const wrapper = tag.parentNode;
let clone;
let attr;
if (tag.tagName === 'SCRIPT') {
clone = document.createElement('script');
clone.type = 'text/javascript';
attr = 'src';
} else if (tag.tagName === 'LINK') {
clone = document.createElement('link');
clone.rel = 'stylesheet';
attr = 'href';
}
clone.id = id;
// Add version to the stylesheet URL, make sure we override the cache and already existing version there.
clone[attr] = tag[attr].replace(/(\?v=)[^&]+/, `$1${Date.now()}`);
tag.remove();
wrapper.append(clone);
return clone;
}
if (!template) {
return;
function updateBlock(args = {}) {
if (args.template) {
template = args.template; // Update state.
}
if (args.data) {
data = args.data; // Update state.
}
if (!template) {
return;
}
renderBlock(template, data || {}, document.getElementById("hbs-container"));
}
renderBlock(template, data || {}, document.getElementById("hbs-container"));
}
function renderBlock(templateHbs, jsonData, target) {
const template = Handlebars.compile(templateHbs);
function renderBlock(templateHbs, jsonData, target) {
const template = Handlebars.compile(templateHbs);
/**
* Handlebars Helpers
*/
Handlebars.registerHelper('esc_attr', function (attr) {
return attr;
});
/**
* Handlebars Helpers
*/
Handlebars.registerHelper('esc_attr', function (attr) {
return attr;
});
Handlebars.registerHelper('esc_url', function (attr) {
return attr;
});
Handlebars.registerHelper('esc_url', function (attr) {
return attr;
});
Handlebars.registerHelper('esc_html', function (attr) {
return attr;
});
Handlebars.registerHelper('esc_html', function (attr) {
return attr;
});
Handlebars.registerHelper('base_url', function () {
const list = ['block'];
Handlebars.registerHelper('base_url', function () {
return '/';
});
if (block) {
list.push(block.substr(1));
}
let html;
return ['', ...list, ''].join('/');
});
try {
html = template(jsonData);
} catch (e) {
html = `<div style="max-width: 1280px; margin: 1rem auto;">
let html;
try {
html = template(jsonData);
} catch (e) {
html = `<div style="max-width: 1280px; margin: 1rem auto;">
<h1 style="all: unset; font-size: 1.5rem; font-weight: bold; display: block;">Syntax Error:</h1>
<pre style="all: unset; padding: 10px 15px; background-color: #ffe6e6; border: 1px solid red; border-radius: 0.25rem; overflow: auto; display: block; white-space: pre;">${e.toString()}</pre>
</div>`;
}
}
target.innerHTML = html;
if (reload) {
reload();
target.innerHTML = html;
if (reload) {
reload();
}
}
}
})();
+27 -26
View File
@@ -46,31 +46,10 @@ function SyncScreen() {
</>
async function ignoreVersionSync() {
setLoading(true);
let data = {};
try {
const response = await fetch('/sync', {
method: 'POST',
body: JSON.stringify({ignore: true}),
headers: {
'Content-Type': 'application/json'
}
});
data = await response.json();
} catch (err) {
setError('Error: ' + err.message);
setLoading(false);
return;
}
if (data.status !== 200) {
setError(data.message);
setLoading(false);
return;
}
setTimeout(() => window.location.reload(), 1000);
// Add "ignore" query parameter to current URl and redirect.
const url = new URL(window.location.href);
url.searchParams.set('ignoreVersionSync', 'true');
window.location = url.href;
}
async function runSyncLogic() {
@@ -78,7 +57,14 @@ function SyncScreen() {
let data = {};
try {
const response = await fetch('/sync', {method: 'POST'});
const response = await fetch('/sync', {
method: 'POST',
body: JSON.stringify({block: getQueryParams().block}),
headers: {
'Content-Type': 'application/json'
}
});
data = await response.json();
} catch (err) {
setError('Error: ' + err.message);
@@ -95,6 +81,21 @@ function SyncScreen() {
setTimeout(() => window.location.reload(), 1000);
}
// TODO: This function is used in multiple places (repeated code).
// Move to a common place.
function getQueryParams() {
const urlParams = new URLSearchParams(window.location.search);
const params = {};
for (const [key, value] of urlParams) {
params[key] = value;
}
return params;
}
}
init();
@@ -169,7 +169,7 @@ function DataOptions(props = {}) {
}
async function fetchDataOptions(name = 'default') {
const queryParameters = new URLSearchParams({name});
const queryParameters = new URLSearchParams({name, block: window.devTool.blockName});
const response = await fetch(`/data?${queryParameters}`);
return await response.json();
}
+1
View File
@@ -43,6 +43,7 @@ function Publish(props = {}) {
export function setupPublish(rootAttributes) {
// INIT
const wrapper = document.createElement('div');
wrapper.setAttribute('id', 'publish-btn');
document.querySelector('.page_toolbar__right').append(wrapper)
const root = ReactDOM.createRoot(wrapper);
+3
View File
@@ -8,6 +8,9 @@ body {
font-size: 1rem;
background-color: #F7FAFC;
}
body.view-mode #publish-btn {
display: none;
}
.btn {
--btn-color: #333;
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["page--main.scss","_buttons.scss","_overlay.scss","_page--preview.scss"],"names":[],"mappings":"AAAA;EACE;EACA;;;AAGF;EACE;EACA;EAEA;;;ACTF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;;AC5BJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AFIF;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EAEA;EACA;EACA;EAEA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAKF;EADF;IAEI;;;AAKN;EAEE;EACA;EACA;EACA;;AAGF;EACE;;;AGlFJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EAGA;EACA;EAEA;EACA;EACA;EACA;;AAEA;EACE;EAEA;EACA;;;AHiEJ;EACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EAEE;;;AAGF;EAEE;EACA","file":"page--main.css"}
{"version":3,"sourceRoot":"","sources":["page--main.scss","_buttons.scss","_overlay.scss","_page--preview.scss"],"names":[],"mappings":"AAAA;EACE;EACA;;;AAGF;EACE;EACA;EAEA;;AAGE;EACE;;;ACbN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;;AC5BJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AFUF;EACE;EACA;EACA;EACA;EAEA;EACA;EACA;EAEA;EACA;EACA;EAEA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EAHF;IAII;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAKF;EADF;IAEI;;;AAKN;EAEE;EACA;EACA;EACA;;AAGF;EACE;;;AGxFJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EAGA;EACA;EAEA;EACA;EACA;EACA;;AAEA;EACE;EAEA;EACA;;;AHuEJ;EACE;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EAEE;;;AAGF;EAEE;EACA","file":"page--main.css"}
+6
View File
@@ -8,6 +8,12 @@ body {
font-size: 1rem;
//overflow: none;
background-color: #F7FAFC;
&.view-mode {
#publish-btn {
display: none;
}
}
}
@import "buttons";