PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / status-page / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/status-page/index.js

329 lines 26.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 var el = wp.element.createElement;
3 var Fragment = wp.element.Fragment;
4 var registerBlockType = wp.blocks.registerBlockType;
5 var InspectorControls = wp.blockEditor.InspectorControls;
6 var useBlockProps = wp.blockEditor.useBlockProps;
7 var PanelBody = wp.components.PanelBody;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var ToggleControl = wp.components.ToggleControl;
10 var RangeControl = wp.components.RangeControl;
11 var SelectControl = wp.components.SelectControl;
12 var TextControl = wp.components.TextControl;
13 var TextareaControl = wp.components.TextareaControl;
14 var Button = wp.components.Button;
15
16 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
17 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
18
19 var overallStatusOptions = [
20 { label: '�
21 All Systems Operational', value: 'operational' },
22 { label: '⚠️ Partial Outage', value: 'partial' },
23 { label: '🔴 Major Outage', value: 'major' },
24 { label: '🔧 Under Maintenance', value: 'maintenance' }
25 ];
26 var componentStatusOptions = [
27 { label: '�
28 Operational', value: 'operational' },
29 { label: '⚠️ Degraded', value: 'degraded' },
30 { label: '🔴 Outage', value: 'outage' },
31 { label: '🔧 Maintenance', value: 'maintenance' }
32 ];
33 var severityOptions = [
34 { label: '🔴 Major', value: 'major' },
35 { label: '🟡 Minor', value: 'minor' },
36 { label: 'ℹ️ Notice', value: 'notice' }
37 ];
38 var updateStatusOptions = [
39 { label: 'Investigating', value: 'investigating' },
40 { label: 'Identified', value: 'identified' },
41 { label: 'Monitoring', value: 'monitoring' },
42 { label: 'Resolved', value: 'resolved' }
43 ];
44
45 function upd(arr, idx, field, val) {
46 return arr.map(function (e, i) {
47 if (i !== idx) return e;
48 var u = {}; u[field] = val;
49 return Object.assign({}, e, u);
50 });
51 }
52
53 function statusInfo(s, a) {
54 var map = {
55 operational: { label: 'Operational', bg: a.operationalBg, color: a.operationalColor, dot: '#16a34a' },
56 degraded: { label: 'Degraded', bg: a.degradedBg, color: a.degradedColor, dot: '#d97706' },
57 outage: { label: 'Outage', bg: a.outageBg, color: a.outageColor, dot: '#dc2626' },
58 maintenance: { label: 'Maintenance', bg: a.maintenanceBg, color: a.maintenanceColor, dot: '#6366f1' }
59 };
60 return map[s] || map.operational;
61 }
62
63 function overallBanner(s) {
64 if (s === 'operational') return { text: '�
65 All Systems Operational', bg: '#14532d', color: '#dcfce7' };
66 if (s === 'partial') return { text: '⚠️ Partial Service Disruption', bg: '#78350f', color: '#fef9c3' };
67 if (s === 'major') return { text: '🔴 Major Outage in Progress', bg: '#991b1b', color: '#fee2e2' };
68 return { text: '🔧 Scheduled Maintenance', bg: '#3730a3', color: '#e0e7ff' };
69 }
70
71 function updateDotColor(status, a) {
72 if (status === 'investigating') return a.updateDotInvestigating;
73 if (status === 'identified') return a.updateDotIdentified;
74 if (status === 'monitoring') return a.updateDotMonitoring;
75 return a.updateDotResolved;
76 }
77
78 function incidentBorderColor(severity, a) {
79 if (severity === 'major') return a.incidentBorderMajor;
80 if (severity === 'minor') return a.incidentBorderMinor;
81 return a.incidentBorderNotice;
82 }
83
84 registerBlockType('blockenberg/status-page', {
85 edit: function (props) {
86 var a = props.attributes;
87 var set = props.setAttributes;
88 var tv = getTypoCssVars();
89 var lh = (a.lineHeight / 100).toFixed(2);
90 var blockProps = useBlockProps({ className: 'bkbg-sp-editor-wrap', style: (function () {
91 var s = {
92 '--bksp-tt-sz': a.titleFontSize + 'px',
93 '--bksp-bd-sz': a.fontSize + 'px',
94 '--bksp-bd-lh': lh,
95 '--bksp-bd-wt': a.fontWeight
96 };
97 Object.assign(s, tv(a.titleTypo, '--bksp-tt-'));
98 Object.assign(s, tv(a.bodyTypo, '--bksp-bd-'));
99 Object.assign(s, tv(a.sectionHeadTypo, '--bksp-sh-'));
100 Object.assign(s, tv(a.componentNameTypo, '--bksp-cn-'));
101 Object.assign(s, tv(a.incidentTitleTypo, '--bksp-it-'));
102 return s;
103 }()) });
104 var ob = overallBanner(a.overallStatus);
105
106 var preview = el('div', { className: 'bkbg-sp-wrap', style: { border: '1px solid ' + a.borderColor, borderRadius: a.borderRadius + 'px', overflow: 'hidden', background: a.bgColor } },
107 // Header
108 el('div', { className: 'bkbg-sp-header', style: { background: a.headerBg, padding: '24px 28px' } },
109 el('h2', { className: 'bkbg-sp-title', style: { margin: '0 0 6px', color: a.headerColor } }, a.pageTitle),
110 a.showLastUpdated && el('div', { style: { fontSize: 11, color: a.metaColor } }, 'Last updated: ' + a.lastUpdated)
111 ),
112 // Overall status banner
113 el('div', { style: { background: ob.bg, color: ob.color, padding: '12px 28px', fontWeight: 700, fontSize: 14 } }, ob.text),
114 // Components
115 el('div', { style: { padding: '20px 28px' } },
116 el('h3', { style: { margin: '0 0 14px', fontSize: 13, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '.07em', color: a.sectionHeadColor } }, a.componentsLabel),
117 el('div', { style: { border: '1px solid ' + a.borderColor, borderRadius: 8, overflow: 'hidden' } },
118 a.components.map(function (comp, i) {
119 var si = statusInfo(comp.status, a);
120 return el('div', { key: i, style: { display: 'grid', gridTemplateColumns: '1fr auto', alignItems: 'center', padding: '11px 16px', borderBottom: i < a.components.length - 1 ? '1px solid ' + a.borderColor : 'none', gap: 12 } },
121 el('div', null,
122 el('div', { style: { fontWeight: 600, fontSize: a.fontSize + 'px', color: a.componentNameColor } }, comp.name),
123 a.showDescription && comp.description && el('div', { style: { fontSize: 11, color: a.componentDescColor, marginTop: 2 } }, comp.description)
124 ),
125 el('div', { style: { display: 'flex', alignItems: 'center', gap: 10, flexShrink: 0 } },
126 a.showUptime && el('span', { style: { fontSize: 11, color: a.uptimeColor, fontVariantNumeric: 'tabular-nums' } }, comp.uptime + '%'),
127 el('span', { style: { background: si.bg, color: si.color, padding: '3px 10px', borderRadius: 100, fontSize: 11, fontWeight: 700, whiteSpace: 'nowrap', display: 'flex', alignItems: 'center', gap: 5 } },
128 el('span', { style: { width: 7, height: 7, borderRadius: '50%', background: si.dot, display: 'inline-block', flexShrink: 0 } }),
129 si.label
130 )
131 )
132 );
133 })
134 )
135 ),
136 // Incidents
137 a.showIncidents && a.incidents.length > 0 && el('div', { style: { padding: '0 28px 24px' } },
138 el('h3', { style: { margin: '0 0 14px', fontSize: 13, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '.07em', color: a.sectionHeadColor } }, a.incidentsLabel),
139 el('div', { style: { display: 'grid', gap: 12 } },
140 a.incidents.map(function (inc, i) {
141 var borderC = incidentBorderColor(inc.severity, a);
142 return el('div', { key: i, style: { border: '1px solid ' + a.borderColor, borderLeft: '4px solid ' + borderC, borderRadius: 8, padding: '14px 16px', background: '#fafafa' } },
143 el('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10, flexWrap: 'wrap', gap: 6 } },
144 el('strong', { style: { fontSize: a.fontSize + 'px', color: a.componentNameColor } }, inc.title),
145 el('div', { style: { display: 'flex', gap: 8, alignItems: 'center' } },
146 el('span', { style: { fontSize: 11, color: a.componentDescColor } }, inc.date),
147 el('span', { style: { fontSize: 10, fontWeight: 700, padding: '2px 7px', borderRadius: 100, background: borderC + '22', color: borderC } }, inc.severity.toUpperCase())
148 )
149 ),
150 el('div', { style: { display: 'grid', gap: 8 } },
151 (inc.updates || []).map(function (u, j) {
152 var dotColor = updateDotColor(u.status, a);
153 return el('div', { key: j, style: { display: 'grid', gridTemplateColumns: '12px 60px 1fr', gap: 8, alignItems: 'flex-start' } },
154 el('div', { style: { width: 10, height: 10, borderRadius: '50%', background: dotColor, marginTop: 3, flexShrink: 0 } }),
155 el('span', { style: { fontSize: 11, color: a.componentDescColor, fontVariantNumeric: 'tabular-nums', flexShrink: 0 } }, u.time),
156 el('span', { style: { fontSize: (a.fontSize - 1) + 'px', color: a.componentNameColor, lineHeight: lh } }, u.message)
157 );
158 })
159 )
160 );
161 })
162 )
163 )
164 );
165
166 return el(Fragment, null,
167 el('div', blockProps, preview),
168 el(InspectorControls, null,
169 // Page Info
170 el(PanelBody, { title: 'Page Info', initialOpen: true },
171 el(TextControl, { label: 'Page Title', value: a.pageTitle, __nextHasNoMarginBottom: true, onChange: function (v) { set({ pageTitle: v }); } }),
172 el('div', { style: { marginTop: 8 } },
173 el(SelectControl, { label: 'Overall Status', value: a.overallStatus, options: overallStatusOptions, __nextHasNoMarginBottom: true, onChange: function (v) { set({ overallStatus: v }); } })
174 ),
175 el('div', { style: { marginTop: 8 } },
176 el(ToggleControl, { label: 'Show "Last Updated"', checked: a.showLastUpdated, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showLastUpdated: v }); } })
177 ),
178 a.showLastUpdated && el('div', { style: { marginTop: 8 } },
179 el(TextControl, { label: 'Last Updated Text', value: a.lastUpdated, __nextHasNoMarginBottom: true, onChange: function (v) { set({ lastUpdated: v }); } })
180 ),
181 el('div', { style: { marginTop: 8 } },
182 el(TextControl, { label: 'Components Heading', value: a.componentsLabel, __nextHasNoMarginBottom: true, onChange: function (v) { set({ componentsLabel: v }); } })
183 )
184 ),
185 // Components
186 el(PanelBody, { title: 'Components', initialOpen: false },
187 el('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 4, marginBottom: 10 } },
188 el(ToggleControl, { label: 'Show Uptime %', checked: a.showUptime, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showUptime: v }); } }),
189 el(ToggleControl, { label: 'Show Descriptions', checked: a.showDescription, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showDescription: v }); } })
190 ),
191 a.components.map(function (comp, i) {
192 return el('div', { key: i, style: { marginBottom: 10, padding: '10px 12px', border: '1px solid #e5e7eb', borderRadius: 8, background: '#f8fafc' } },
193 el('div', { style: { display: 'flex', justifyContent: 'space-between', marginBottom: 6, alignItems: 'center' } },
194 el('strong', { style: { fontSize: 11 } }, 'Component ' + (i + 1)),
195 el(Button, { isDestructive: true, variant: 'link', style: { fontSize: 11 }, onClick: function () { set({ components: a.components.filter(function (_, j) { return j !== i; }) }); } }, '')
196 ),
197 el(TextControl, { label: 'Name', value: comp.name, __nextHasNoMarginBottom: true, onChange: function (v) { set({ components: upd(a.components, i, 'name', v) }); } }),
198 el('div', { style: { marginTop: 8 } },
199 el(TextControl, { label: 'Description', value: comp.description, __nextHasNoMarginBottom: true, onChange: function (v) { set({ components: upd(a.components, i, 'description', v) }); } })
200 ),
201 el('div', { style: { marginTop: 8, display: 'grid', gridTemplateColumns: '1fr 80px', gap: 8, alignItems: 'flex-end' } },
202 el(SelectControl, { label: 'Status', value: comp.status, options: componentStatusOptions, __nextHasNoMarginBottom: true, onChange: function (v) { set({ components: upd(a.components, i, 'status', v) }); } }),
203 el(TextControl, { label: 'Uptime %', value: String(comp.uptime), type: 'number', __nextHasNoMarginBottom: true, onChange: function (v) { set({ components: upd(a.components, i, 'uptime', parseFloat(v) || 0) }); } })
204 )
205 );
206 }),
207 el(Button, { variant: 'primary', style: { width: '100%', justifyContent: 'center', marginTop: 4 }, onClick: function () {
208 set({ components: a.components.concat([{ name: 'New Service', status: 'operational', uptime: 99.9, description: '' }]) });
209 } }, '+ Add Component')
210 ),
211 // Incidents
212 el(PanelBody, { title: 'Incidents', initialOpen: false },
213 el(ToggleControl, { label: 'Show Incidents Section', checked: a.showIncidents, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showIncidents: v }); } }),
214 el('div', { style: { marginTop: 8 } },
215 el(TextControl, { label: 'Incidents Heading', value: a.incidentsLabel, __nextHasNoMarginBottom: true, onChange: function (v) { set({ incidentsLabel: v }); } })
216 ),
217 el('div', { style: { marginTop: 10 } },
218 a.incidents.map(function (inc, i) {
219 return el('div', { key: i, style: { marginBottom: 12, padding: '10px 12px', border: '1px solid #e5e7eb', borderRadius: 8, background: '#f8fafc' } },
220 el('div', { style: { display: 'flex', justifyContent: 'space-between', marginBottom: 8, alignItems: 'center' } },
221 el('strong', { style: { fontSize: 11 } }, 'Incident ' + (i + 1)),
222 el(Button, { isDestructive: true, variant: 'link', style: { fontSize: 11 }, onClick: function () { set({ incidents: a.incidents.filter(function (_, j) { return j !== i; }) }); } }, '')
223 ),
224 el(TextControl, { label: 'Title', value: inc.title, __nextHasNoMarginBottom: true, onChange: function (v) { set({ incidents: upd(a.incidents, i, 'title', v) }); } }),
225 el('div', { style: { marginTop: 8, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 } },
226 el(SelectControl, { label: 'Severity', value: inc.severity, options: severityOptions, __nextHasNoMarginBottom: true, onChange: function (v) { set({ incidents: upd(a.incidents, i, 'severity', v) }); } }),
227 el(TextControl, { label: 'Date', value: inc.date, __nextHasNoMarginBottom: true, onChange: function (v) { set({ incidents: upd(a.incidents, i, 'date', v) }); } })
228 ),
229 el('div', { style: { marginTop: 8 } },
230 el('label', { style: { fontSize: 11, fontWeight: 600, color: '#374151', display: 'block', marginBottom: 6 } }, 'Updates'),
231 (inc.updates || []).map(function (u, j) {
232 return el('div', { key: j, style: { background: '#fff', border: '1px solid #e5e7eb', borderRadius: 6, padding: '6px 8px', marginBottom: 6 } },
233 el('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6, marginBottom: 4 } },
234 el(TextControl, { label: 'Time (UTC)', value: u.time, __nextHasNoMarginBottom: true, onChange: function (v) {
235 var newUpd = (inc.updates || []).map(function (x, k) { return k === j ? Object.assign({}, x, { time: v }) : x; });
236 set({ incidents: upd(a.incidents, i, 'updates', newUpd) });
237 } }),
238 el(SelectControl, { label: 'Status', value: u.status, options: updateStatusOptions, __nextHasNoMarginBottom: true, onChange: function (v) {
239 var newUpd = (inc.updates || []).map(function (x, k) { return k === j ? Object.assign({}, x, { status: v }) : x; });
240 set({ incidents: upd(a.incidents, i, 'updates', newUpd) });
241 } })
242 ),
243 el(TextareaControl, { label: 'Message', value: u.message, rows: 2, __nextHasNoMarginBottom: true, onChange: function (v) {
244 var newUpd = (inc.updates || []).map(function (x, k) { return k === j ? Object.assign({}, x, { message: v }) : x; });
245 set({ incidents: upd(a.incidents, i, 'updates', newUpd) });
246 } })
247 );
248 }),
249 el(Button, { variant: 'secondary', style: { width: '100%', justifyContent: 'center', marginTop: 4 }, onClick: function () {
250 var newUpd = (inc.updates || []).concat([{ time: '00:00 UTC', status: 'investigating', message: 'Update message.' }]);
251 set({ incidents: upd(a.incidents, i, 'updates', newUpd) });
252 } }, '+ Add Update')
253 )
254 );
255 }),
256 el(Button, { variant: 'primary', style: { width: '100%', justifyContent: 'center', marginTop: 4 }, onClick: function () {
257 set({ incidents: a.incidents.concat([{ title: 'New Incident', severity: 'minor', date: '', updates: [] }]) });
258 } }, '+ Add Incident')
259 )
260 ),
261 // Typography
262 el(PanelBody, { title: 'Typography', initialOpen: false },
263 getTypoControl()({ label: __('Title', 'blockenberg'), value: a.titleTypo, onChange: function (v) { set({ titleTypo: v }); } }),
264 getTypoControl()({ label: __('Body', 'blockenberg'), value: a.bodyTypo, onChange: function (v) { set({ bodyTypo: v }); } }),
265 getTypoControl()({ label: __('Section Heading', 'blockenberg'), value: a.sectionHeadTypo, onChange: function (v) { set({ sectionHeadTypo: v }); } }),
266 getTypoControl()({ label: __('Component Name', 'blockenberg'), value: a.componentNameTypo, onChange: function (v) { set({ componentNameTypo: v }); } }),
267 getTypoControl()({ label: __('Incident Title', 'blockenberg'), value: a.incidentTitleTypo, onChange: function (v) { set({ incidentTitleTypo: v }); } })
268 ),
269 el(PanelBody, { title: 'Spacing', initialOpen: false },
270 el(RangeControl, { label: 'Border Radius (px)', value: a.borderRadius, min: 0, max: 24, __nextHasNoMarginBottom: true, onChange: function (v) { set({ borderRadius: v }); } })
271 ),
272 // Colors
273 el(PanelColorSettings, {
274 title: 'Header & Layout',
275 initialOpen: false,
276 colorSettings: [
277 { label: 'Block BG', value: a.bgColor, onChange: function (v) { set({ bgColor: v || '#ffffff' }); } },
278 { label: 'Border', value: a.borderColor, onChange: function (v) { set({ borderColor: v || '#e5e7eb' }); } },
279 { label: 'Header BG', value: a.headerBg, onChange: function (v) { set({ headerBg: v || '#0f172a' }); } },
280 { label: 'Header Text', value: a.headerColor, onChange: function (v) { set({ headerColor: v || '#ffffff' }); } },
281 { label: 'Meta Text', value: a.metaColor, onChange: function (v) { set({ metaColor: v || '#94a3b8' }); } },
282 { label: 'Section Head', value: a.sectionHeadColor, onChange: function (v) { set({ sectionHeadColor: v || '#111827' }); } },
283 { label: 'Component Name', value: a.componentNameColor,onChange: function (v) { set({ componentNameColor: v || '#1f2937' }); } },
284 { label: 'Component Desc', value: a.componentDescColor,onChange: function (v) { set({ componentDescColor: v || '#6b7280' }); } }
285 ]
286 }),
287 el(PanelColorSettings, {
288 title: 'Status Badge Colors',
289 initialOpen: false,
290 colorSettings: [
291 { label: 'Operational BG', value: a.operationalBg, onChange: function (v) { set({ operationalBg: v || '#dcfce7' }); } },
292 { label: 'Operational Text', value: a.operationalColor, onChange: function (v) { set({ operationalColor: v || '#14532d' }); } },
293 { label: 'Degraded BG', value: a.degradedBg, onChange: function (v) { set({ degradedBg: v || '#fef9c3' }); } },
294 { label: 'Degraded Text', value: a.degradedColor, onChange: function (v) { set({ degradedColor: v || '#713f12' }); } },
295 { label: 'Outage BG', value: a.outageBg, onChange: function (v) { set({ outageBg: v || '#fee2e2' }); } },
296 { label: 'Outage Text', value: a.outageColor, onChange: function (v) { set({ outageColor: v || '#991b1b' }); } },
297 { label: 'Maintenance BG', value: a.maintenanceBg, onChange: function (v) { set({ maintenanceBg: v || '#e0e7ff' }); } },
298 { label: 'Maintenance Text', value: a.maintenanceColor,onChange: function (v) { set({ maintenanceColor: v || '#3730a3' }); } }
299 ]
300 }),
301 el(PanelColorSettings, {
302 title: 'Incident & Update Colors',
303 initialOpen: false,
304 colorSettings: [
305 { label: 'Major Border', value: a.incidentBorderMajor, onChange: function (v) { set({ incidentBorderMajor: v || '#ef4444' }); } },
306 { label: 'Minor Border', value: a.incidentBorderMinor, onChange: function (v) { set({ incidentBorderMinor: v || '#f59e0b' }); } },
307 { label: 'Notice Border', value: a.incidentBorderNotice, onChange: function (v) { set({ incidentBorderNotice: v || '#3b82f6' }); } },
308 { label: 'Dot: Investigating', value: a.updateDotInvestigating, onChange: function (v) { set({ updateDotInvestigating: v || '#f59e0b' }); } },
309 { label: 'Dot: Identified', value: a.updateDotIdentified, onChange: function (v) { set({ updateDotIdentified: v || '#ef4444' }); } },
310 { label: 'Dot: Monitoring', value: a.updateDotMonitoring, onChange: function (v) { set({ updateDotMonitoring: v || '#3b82f6' }); } },
311 { label: 'Dot: Resolved', value: a.updateDotResolved, onChange: function (v) { set({ updateDotResolved: v || '#22c55e' }); } }
312 ]
313 })
314 )
315 );
316 },
317
318 save: function (props) {
319 var useBlockProps = wp.blockEditor.useBlockProps;
320 return wp.element.createElement('div', useBlockProps.save(),
321 wp.element.createElement('div', {
322 className: 'bkbg-status-page-app',
323 'data-opts': JSON.stringify(props.attributes)
324 })
325 );
326 }
327 });
328 }() );
329